Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 : #pragma once
18 :
19 : #include "account_manager.h"
20 :
21 : #include <queue>
22 : #include <set>
23 : #include <chrono>
24 :
25 : namespace jami {
26 :
27 : class ServerAccountManager : public AccountManager
28 : {
29 : public:
30 : ServerAccountManager(const std::string& accountId,
31 : const std::filesystem::path& path,
32 : const std::string& managerHostname,
33 : const std::string& nameServer);
34 :
35 : struct ServerAccountCredentials : AccountCredentials
36 : {
37 : std::string username;
38 : std::shared_ptr<dht::crypto::Certificate> ca;
39 : dht::crypto::Identity identity;
40 : };
41 :
42 : void initAuthentication(std::string deviceName,
43 : std::unique_ptr<AccountCredentials> credentials,
44 : AuthSuccessCallback onSuccess,
45 : AuthFailureCallback onFailure,
46 : const OnChangeCallback& onChange) override;
47 :
48 0 : bool changePassword(const std::string& /*password_old*/, const std::string& /*password_new*/) override
49 : {
50 0 : return false;
51 : }
52 :
53 : void syncDevices() override;
54 :
55 : using SyncBlueprintCallback = std::function<void(const std::map<std::string, std::string>& config)>;
56 :
57 : void syncBlueprintConfig(SyncBlueprintCallback onSuccess);
58 :
59 : bool revokeDevice(const std::string& device,
60 : std::string_view scheme,
61 : const std::string& password,
62 : RevokeDeviceCallback cb) override;
63 :
64 : bool searchUser(const std::string& query, SearchCallback cb) override;
65 : void registerName(const std::string& name,
66 : std::string_view scheme,
67 : const std::string& password,
68 : RegistrationCallback cb) override;
69 :
70 0 : void onDeviceRevoked(std::function<void()> cb) { onDeviceRevoked_ = std::move(cb); }
71 :
72 : private:
73 : struct AuthContext
74 : {
75 : std::string accountId;
76 : PrivateKey key;
77 : CertRequest request;
78 : std::string deviceName;
79 : std::unique_ptr<ServerAccountCredentials> credentials;
80 : AuthSuccessCallback onSuccess;
81 : AuthFailureCallback onFailure;
82 : };
83 :
84 : const std::string managerHostname_;
85 : std::shared_ptr<dht::Logger> logger_;
86 :
87 : std::mutex requestLock_;
88 : std::set<std::shared_ptr<dht::http::Request>> requests_;
89 : std::unique_ptr<ServerAccountCredentials> creds_;
90 :
91 : void sendRequest(const std::shared_ptr<dht::http::Request>& request);
92 : void clearRequest(const std::weak_ptr<dht::http::Request>& request);
93 :
94 : enum class TokenScope : unsigned { None = 0, Device, User, Admin };
95 : std::mutex tokenLock_;
96 : std::string token_ {};
97 : TokenScope tokenScope_ {};
98 : std::chrono::steady_clock::time_point tokenExpire_ {std::chrono::steady_clock::time_point::min()};
99 :
100 : using RequestQueue = std::queue<std::shared_ptr<dht::http::Request>>;
101 : RequestQueue pendingDeviceRequests_;
102 : RequestQueue pendingAccountRequests_;
103 0 : RequestQueue& getRequestQueue(TokenScope scope)
104 : {
105 0 : return scope == TokenScope::Device ? pendingDeviceRequests_ : pendingAccountRequests_;
106 : }
107 0 : bool hasAuthorization(TokenScope scope) const
108 : {
109 0 : return not token_.empty() and tokenScope_ >= scope and tokenExpire_ >= std::chrono::steady_clock::now();
110 : }
111 : void setAuthHeaderFields(dht::http::Request& request) const;
112 :
113 : void sendDeviceRequest(const std::shared_ptr<dht::http::Request>& req);
114 : void sendAccountRequest(const std::shared_ptr<dht::http::Request>& req, const std::string& password);
115 :
116 : void authenticateDevice();
117 : void authenticateAccount(const std::string& username, const std::string& password);
118 : void authFailed(TokenScope scope, int code);
119 : void authError(TokenScope scope);
120 : void onAuthEnded(const Json::Value& json, const dht::http::Response& response, TokenScope scope);
121 : std::function<void()> onDeviceRevoked_;
122 :
123 : void setToken(std::string token, TokenScope scope, std::chrono::steady_clock::time_point expiration);
124 : };
125 :
126 : } // namespace jami
|