~aleteoryx/muditaos

ref: 3812cfd7b8342c27442e23380554aa446e176a1d muditaos/module-services/service-desktop/endpoints/security/SecurityEndpointHelper.cpp -rw-r--r-- 4.9 KiB
3812cfd7 — rrandomsky [MOS-1010] Fix for Alarm disappearance during end of call window 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <endpoints/security/SecurityEndpointHelper.hpp>
#include <endpoints/message/Sender.hpp>
#include <endpoints/JsonKeyNames.hpp>
#include <service-appmgr/ServiceApplicationManagerName.hpp>
#include <service-appmgr/messages/PreventBlockingRequest.hpp>
#include <service-desktop/ServiceDesktop.hpp>
#include <apps-common/locks/data/PhoneLockMessages.hpp>

namespace sdesktop::endpoints
{
    using sender::putToSendQueue;

    auto SecurityEndpointHelper::preventBlockingDevice() -> bool
    {
        auto desktopService = dynamic_cast<ServiceDesktop *>(owner);
        auto msg            = std::make_shared<app::manager::PreventBlockingRequest>(desktopService->GetName());
        return desktopService->bus.sendUnicast(std::move(msg), "ApplicationManager");
    }

    auto SecurityEndpointHelper::processPut(Context &context) -> ProcessResult
    {
        auto code = processConfiguration(context);
        return {sent::no, ResponseContext{.status = code}};
    }

    auto SecurityEndpointHelper::processGet(Context &context) -> ProcessResult
    {
        if (context.getBody()[json::messages::category].string_value() == json::usb::phoneLockStatus) {
            return {sent::no, processStatus(context)};
        }
        if (context.getBody()[json::messages::category].string_value() == json::usb::phoneLockTime) {
            if (auto phoneLockTime = getPhoneLockTime(context); phoneLockTime > std::time(nullptr)) {
                auto timeLeftToNextAttempt = phoneLockTime - std::time(nullptr);
                context.setResponseBody(json11::Json::object(
                    {{json::usb::phoneLockTime, static_cast<int>(phoneLockTime)},
                     {json::usb::timeLeftToNextAttempt, static_cast<int>(timeLeftToNextAttempt)}}));
                context.setResponseStatus(http::Code::OK);
            }
            else {
                context.setResponseStatus(http::Code::UnprocessableEntity);
            }
            putToSendQueue(context.createSimpleResponse());
            return {sent::yes, std::nullopt};
        }
        return {sent::no, ResponseContext{.status = http::Code::BadRequest}};
    }

    auto SecurityEndpointHelper::processStatus(Context & /*context*/) -> ResponseContext
    {
        auto desktopService = dynamic_cast<ServiceDesktop *>(owner);
        auto security       = desktopService->getSecurity()->getEndpointSecurity();
        ResponseContext responseContext{};

        if (security.access == EndpointSecurity::Allow) {
            preventBlockingDevice();
            responseContext.status = http::Code::NoContent;
        }
        else {
            switch (security.reason) {
            case BlockReason::NoReason:
            case BlockReason::DeviceLocked:
                responseContext.status = http::Code::Forbidden;
                break;
            case BlockReason::OnboardingNotFinished:
            case BlockReason::BatteryCriticalLevel:
                responseContext.status = http::Code::Locked;
                responseContext.body =
                    json11::Json::object({{json::reason, std::to_string(static_cast<int>(security.reason))}});
                break;
            }
        }
        return responseContext;
    }

    auto SecurityEndpointHelper::getPhoneLockTime(Context & /*context*/) -> time_t
    {
        auto desktopService = static_cast<ServiceDesktop *>(owner);
        return desktopService->getSecurity()->getPhoneLockTime();
    }

    auto SecurityEndpointHelper::passCodeArrayToVecOfInts(const json11::Json::array &passCode)
        -> std::vector<unsigned int>
    {
        std::vector<unsigned int> passCodeAsInts(0, 0);

        for (const auto &value : passCode) {
            if (value.is_number()) {
                auto v = value.number_value();
                passCodeAsInts.push_back(v);
            }
            else {
                throw std::invalid_argument("value not a digit");
            }
        }

        return passCodeAsInts;
    }

    auto SecurityEndpointHelper::processConfiguration(Context &context) -> http::Code
    {
        auto body     = context.getBody();
        auto passCode = body[json::usb::phoneLockCode].array_items();
        http::Code status{http::Code::BadRequest};

        if (passCode.size() == PasscodeLength) {
            try {
                auto msg = std::make_shared<locks::ExternalUnLockPhone>(passCodeArrayToVecOfInts(passCode));
                status   = owner->bus.sendUnicast(std::move(msg), service::name::appmgr)
                               ? http::Code::NoContent
                               : http::Code::InternalServerError;
            }
            catch (const std::exception &e) {
                LOG_ERROR("Passcode decoding exception");
            }
        }

        return status;
    }

} // namespace sdesktop::endpoints