Changeset View
Changeset View
Standalone View
Standalone View
libs/bolt/manager.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright (c) 2018 Daniel Vrátil <dvratil@kde.org> | ||||
3 | * | ||||
4 | * This program is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU General Public License as | ||||
6 | * published by the Free Software Foundation; either version 2 of | ||||
7 | * the License or (at your option) version 3 or any later version | ||||
8 | * accepted by the membership of KDE e.V. (or its successor approved | ||||
9 | * by the membership of KDE e.V.), which shall act as a proxy | ||||
10 | * defined in Section 14 of version 3 of the license. | ||||
11 | * | ||||
12 | * This program is distributed in the hope that it will be useful, | ||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | * GNU General Public License for more details. | ||||
16 | * | ||||
17 | * You should have received a copy of the GNU General Public License | ||||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | */ | ||||
20 | | ||||
21 | #include "manager.h" | ||||
22 | #include "device.h" | ||||
23 | #include "managerinterface.h" | ||||
24 | #include "dbushelper.h" | ||||
25 | #include "libkbolt_debug.h" | ||||
26 | | ||||
27 | using namespace Bolt; | ||||
28 | | ||||
29 | using ManagerInterface = org::freedesktop::bolt1::Manager; | ||||
30 | | ||||
31 | Manager::Manager(QObject *parent) | ||||
32 | : QObject(parent) | ||||
33 | , mInterface(std::make_unique<ManagerInterface>( | ||||
34 | DBusHelper::serviceName(), QStringLiteral("/org/freedesktop/bolt"), | ||||
35 | DBusHelper::connection())) | ||||
36 | { | ||||
37 | if (!mInterface->isValid()) { | ||||
38 | qCWarning(log_libkbolt, "Failed to connect to Bolt manager DBus interface: %s", | ||||
39 | qUtf8Printable(mInterface->lastError().message())); | ||||
40 | return; | ||||
41 | } | ||||
42 | | ||||
43 | connect(mInterface.get(), &ManagerInterface::DeviceAdded, | ||||
44 | this, [this](const QDBusObjectPath &path) { | ||||
45 | if (auto device = Device::create(path, this)) { | ||||
46 | mDevices.push_back(device); | ||||
47 | qCDebug(log_libkbolt, "New device %s (%s) added", | ||||
48 | qUtf8Printable(device->uid()), qUtf8Printable(device->name())); | ||||
49 | Q_EMIT deviceAdded(device); | ||||
50 | } | ||||
51 | }); | ||||
52 | connect(mInterface.get(), &ManagerInterface::DeviceRemoved, | ||||
53 | this, [this](const QDBusObjectPath &path) { | ||||
54 | if (auto device = this->device(path)) { | ||||
55 | mDevices.removeOne(device); | ||||
56 | qCDebug(log_libkbolt, "Device %s (%s) removed", | ||||
57 | qUtf8Printable(device->uid()), qUtf8Printable(device->name())); | ||||
58 | Q_EMIT deviceRemoved(device); | ||||
59 | } | ||||
60 | }); | ||||
61 | | ||||
62 | const auto devicePaths = mInterface->ListDevices().argumentAt<0>(); | ||||
63 | for (const auto &devicePath : devicePaths) { | ||||
64 | qCDebug(log_libkbolt, "Discovered device %s", qUtf8Printable(devicePath.path())); | ||||
65 | if (auto device = Device::create(devicePath, this)) { | ||||
66 | mDevices.push_back(device); | ||||
67 | } | ||||
68 | } | ||||
69 | } | ||||
70 | | ||||
71 | Manager::~Manager() = default; | ||||
72 | | ||||
73 | bool Manager::isAvailable() const | ||||
74 | { | ||||
75 | return mInterface.get() && mInterface->isValid(); | ||||
76 | } | ||||
77 | | ||||
78 | uint Manager::version() const | ||||
79 | { | ||||
80 | return mInterface->version(); | ||||
81 | } | ||||
82 | | ||||
83 | bool Manager::isProbing() const | ||||
84 | { | ||||
85 | return mInterface->probing(); | ||||
86 | } | ||||
87 | | ||||
88 | Policy Manager::defaultPolicy() const | ||||
89 | { | ||||
90 | const auto policy = mInterface->defaultPolicy(); | ||||
91 | if (!mInterface->isValid() || policy.isEmpty()) { | ||||
92 | return Policy::Unknown; | ||||
93 | } | ||||
94 | return policyFromString(policy); | ||||
95 | } | ||||
96 | | ||||
97 | Security Manager::securityLevel() const | ||||
98 | { | ||||
99 | const auto level = mInterface->securityLevel(); | ||||
100 | if (!mInterface->isValid() || level.isEmpty()) { | ||||
101 | return Security::Unknown; | ||||
102 | } | ||||
103 | return securityFromString(level); | ||||
104 | } | ||||
105 | | ||||
106 | AuthMode Manager::authMode() const | ||||
107 | { | ||||
108 | const auto mode = mInterface->authMode(); | ||||
109 | if (!mInterface->isValid() || mode.isEmpty()) { | ||||
110 | return AuthMode::Disabled; | ||||
111 | } | ||||
112 | return authModeFromString(mode); | ||||
113 | } | ||||
114 | | ||||
115 | void Manager::setAuthMode(AuthMode mode) | ||||
116 | { | ||||
117 | mInterface->setAuthMode(authModeToString(mode)); | ||||
118 | } | ||||
119 | | ||||
120 | QSharedPointer<Device> Manager::device(std::function<bool(const QSharedPointer<Device> &)> &&match) const | ||||
121 | { | ||||
122 | auto device = std::find_if(mDevices.cbegin(), mDevices.cend(), std::move(match)); | ||||
123 | return device == mDevices.cend() ? QSharedPointer<Device>() : *device; | ||||
124 | } | ||||
125 | | ||||
126 | QSharedPointer<Device> Manager::device(const QString &uid) const | ||||
127 | { | ||||
128 | return device([uid](const auto &device) { return device->uid() == uid; }); | ||||
129 | } | ||||
130 | | ||||
131 | QSharedPointer<Device> Manager::device(const QDBusObjectPath &path) const | ||||
132 | { | ||||
133 | return device([path](const auto &device) { return device->dbusPath() == path; }); | ||||
134 | } | ||||
135 | | ||||
136 | QList<QSharedPointer<Device>> Manager::devices() const | ||||
137 | { | ||||
138 | return mDevices; | ||||
139 | } | ||||
140 | | ||||
141 | void Manager::enrollDevice(const QString &uid, Policy policy, AuthFlags authFlags, | ||||
142 | std::function<void()> successCallback, | ||||
143 | std::function<void(const QString &)> errorCallback) | ||||
144 | { | ||||
145 | qCDebug(log_libkbolt, "Enrolling device %s with policy %s and flags %s", | ||||
146 | qUtf8Printable(uid), qUtf8Printable(policyToString(policy)), | ||||
147 | qUtf8Printable(authFlagsToString(authFlags))); | ||||
148 | | ||||
149 | auto device = this->device(uid); | ||||
150 | if (device) { | ||||
151 | device->setStatusOverride(Status::Authorizing); | ||||
152 | } else { | ||||
153 | qCDebug(log_libkbolt, "Found no matching device object for uid %s", | ||||
154 | qUtf8Printable(uid)); | ||||
155 | } | ||||
156 | | ||||
157 | DBusHelper::call<QString, QString, QString>(mInterface.get(), | ||||
158 | QStringLiteral("EnrollDevice"), uid, | ||||
159 | policyToString(policy), authFlagsToString(authFlags), | ||||
160 | [uid, device, policy, authFlags, cb = std::move(successCallback)]() { | ||||
161 | qCDebug(log_libkbolt, "Device %s was successfully enrolled", qUtf8Printable(uid)); | ||||
162 | if (device) { | ||||
163 | device->clearStatusOverride(); | ||||
164 | Q_EMIT device->storedChanged(true); | ||||
165 | Q_EMIT device->policyChanged(policy); | ||||
166 | Q_EMIT device->authFlagsChanged(authFlags); | ||||
167 | } | ||||
168 | if (cb) { | ||||
169 | cb(); | ||||
170 | } | ||||
171 | }, | ||||
172 | [this, uid, device, cb = std::move(errorCallback)](const QString &error) { | ||||
173 | qCWarning(log_libkbolt, "Failed to enroll device %s: %s", | ||||
174 | qUtf8Printable(uid), qUtf8Printable(error)); | ||||
175 | if (device) { | ||||
176 | device->setStatusOverride(Status::AuthError); | ||||
177 | } | ||||
178 | if (cb) { | ||||
179 | cb(error); | ||||
180 | } | ||||
181 | }, | ||||
182 | this); | ||||
183 | } | ||||
184 | | ||||
185 | void Manager::forgetDevice(const QString &uid, | ||||
186 | std::function<void()> successCallback, | ||||
187 | std::function<void(const QString &)> errorCallback) | ||||
188 | { | ||||
189 | qCDebug(log_libkbolt, "Forgetting device %s", qUtf8Printable(uid)); | ||||
190 | | ||||
191 | DBusHelper::call<QString>(mInterface.get(), | ||||
192 | QStringLiteral("ForgetDevice"), uid, | ||||
193 | [this, uid, cb = std::move(successCallback)]() { | ||||
194 | qCDebug(log_libkbolt, "Device %s was successfully forgotten", qUtf8Printable(uid)); | ||||
195 | if (auto device = this->device(uid)) { | ||||
196 | device->clearStatusOverride(); | ||||
197 | Q_EMIT device->storedChanged(false); | ||||
198 | Q_EMIT device->authFlagsChanged(Auth::None); | ||||
199 | Q_EMIT device->policyChanged(Policy::Auto); | ||||
200 | } | ||||
201 | if (cb) { | ||||
202 | cb(); | ||||
203 | } | ||||
204 | }, | ||||
205 | [this, uid, cb = std::move(errorCallback)](const QString &error) { | ||||
206 | qCWarning(log_libkbolt, "Failed to forget device %s: %s", | ||||
207 | qUtf8Printable(uid), qUtf8Printable(error)); | ||||
208 | if (auto device = this->device(uid)) { | ||||
209 | device->setStatusOverride(Status::AuthError); | ||||
210 | } | ||||
211 | if (cb) { | ||||
212 | cb(error); | ||||
213 | } | ||||
214 | }, | ||||
215 | this); | ||||
216 | } |