Merge lp:~mardy/online-accounts-api/dbus-api into lp:online-accounts-api
- dbus-api
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 8 |
Proposed branch: | lp:~mardy/online-accounts-api/dbus-api |
Merge into: | lp:online-accounts-api |
Prerequisite: | lp:~mardy/online-accounts-api/style |
Diff against target: |
304 lines (+140/-88) 3 files modified
src/daemon/manager.cpp (+16/-26) src/daemon/manager.h (+8/-7) src/daemon/manager.xml (+116/-55) |
To merge this branch: | bzr merge lp:~mardy/online-accounts-api/dbus-api |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Henstridge | Pending | ||
Review via email: mp+249285@code.launchpad.net |
This proposal supersedes a proposal from 2015-02-09.
Commit message
Description of the change
Update D-Bus API, fix warnings
James Henstridge (jamesh) wrote : Posted in a previous version of this proposal | # |
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal | # |
> Many of these changes seem to be things that we disagreed about in the meeting
> previously. I have also been working on updating the interface as we
> discussed at that meeting, so can we hold off on this?
I'm proposing this exactly in order to discuss about the disagreements. :-)
Keep in mind that what we currently have in trunk has not been agreed upon either. Anyway, I won't merge this until we've got a consensus, or until we come to the conclusion that a consensus cannot be reached.
On the other hand, defining this interface is our top priority, because all the client side will be blocked until we settle this.
Alberto Mardegan (mardy) wrote : Posted in a previous version of this proposal | # |
I just pushed a new commit, taking your comments into account. I also replied to them, but in order to see my replies you'll have to select the "r4 into r3" diff into the "Preview Diff" selection box below.
James Henstridge (jamesh) wrote : Posted in a previous version of this proposal | # |
Replies to r4 comments.
James Henstridge (jamesh) wrote : Posted in a previous version of this proposal | # |
Now for r5:
As a general question, what style guide are you trying to convert this code to conform to exactly? I'd really appreciate it if you didn't mix these kinds of code clean ups in with functional changes: all it does is obscure what you're changing.
Alberto Mardegan (mardy) wrote : | # |
> Can you explain why security decisions shouldn't be made based on service ID? The entire security model of this simplified API is built around the idea that we _can_ use them as a basis for security decisions: confined apps can only make use of services that belong to their package, and unconfined apps can access everything (because they aren't being controlled by AppArmor).
No, it doesn't work like that. The decision is taken on the combination of account + service: as I wrote before, if your app uses the google account and ships a service file for it, it won't automatically be granted access to the account.
> In this model, there may be usable accounts that haven't been used with this service ID yet, but that's what Authenticate() is there for.
You mean RequestAccess, or whatever we'll call it?
> As for the rest, if you have specific filters in mind for this method, please make them real method arguments. We haven't set the D-Bus API in stone yet, so if there are important features that are missing we should just add them.
No, I really think this should be an a{sv}, because sometimes you use some filters (account Id), sometimes others (app ID).
> The details of OAuth client IDs or scopes are the realm of the service configuration file though, right? Can you point out cases where this feature is needed?
When the app developer wants to store them in the binary. This allows the same app to authenticate different times with different keys; for example, an app which is both an email and a calendar app, might want to use two separate client IDs (this covers the case that Thomas was talking about, I assume). Also, the scope list can be dynamic.
> In contrast, I don't know what "RequestAccess" sounds like it is used to gain access to something that already exists on the system.
The app doesn't know whether the account exists or not. What the API does is requesting OA to obtain a *new* (for the app) account. Maybe RequestAccount is a better name?
- 6. By Alberto Mardegan
-
merge from style
- 7. By Alberto Mardegan
-
Update
- 8. By Alberto Mardegan
-
style
- 9. By Alberto Mardegan
-
merge style
- 10. By Alberto Mardegan
-
from trunk
- 11. By Alberto Mardegan
-
Update docstring
Preview Diff
1 | === modified file 'src/daemon/manager.cpp' |
2 | --- src/daemon/manager.cpp 2015-02-11 09:08:57 +0000 |
3 | +++ src/daemon/manager.cpp 2015-02-18 12:26:47 +0000 |
4 | @@ -82,34 +82,21 @@ |
5 | return hasAccess; |
6 | } |
7 | |
8 | -QList<AccountInfo> Manager::GetAccounts(const QStringList &serviceIds) |
9 | -{ |
10 | - Q_FOREACH(const QString &serviceId, serviceIds) { |
11 | - if (!checkAccess(serviceId)) { |
12 | - return QList<AccountInfo>(); |
13 | - } |
14 | - } |
15 | - |
16 | - return QList<AccountInfo>({AccountInfo(0, QVariantMap())}); |
17 | -} |
18 | - |
19 | -AccountInfo Manager::GetAccountInfo(const QString &serviceId, uint accountId) |
20 | -{ |
21 | - Q_UNUSED(accountId); |
22 | - |
23 | - if (!checkAccess(serviceId)) { |
24 | - return AccountInfo(); |
25 | - } |
26 | - |
27 | - return AccountInfo(accountId, QVariantMap()); |
28 | -} |
29 | - |
30 | -QVariantMap Manager::Authenticate(const QString &serviceId, uint accountId, |
31 | - bool interactive, bool invalidate) |
32 | +QList<AccountInfo> Manager::GetAccounts(const QVariantMap &filters) |
33 | +{ |
34 | + Q_UNUSED(filters); |
35 | + |
36 | + return QList<AccountInfo>(); |
37 | +} |
38 | + |
39 | +QVariantMap Manager::Authenticate(uint accountId, const QString &serviceId, |
40 | + bool interactive, bool invalidate, |
41 | + const QVariantMap ¶meters) |
42 | { |
43 | Q_UNUSED(accountId); |
44 | Q_UNUSED(interactive); |
45 | Q_UNUSED(invalidate); |
46 | + Q_UNUSED(parameters); |
47 | |
48 | if (!checkAccess(serviceId)) { |
49 | return QVariantMap(); |
50 | @@ -118,13 +105,16 @@ |
51 | return QVariantMap(); |
52 | } |
53 | |
54 | -AccountInfo Manager::Register(const QString &serviceId, QVariantMap &credentials) |
55 | +AccountInfo Manager::RequestAccess(const QString &serviceId, |
56 | + const QVariantMap ¶meters, |
57 | + QVariantMap &credentials) |
58 | { |
59 | - Q_UNUSED(credentials); |
60 | + Q_UNUSED(parameters); |
61 | |
62 | if (!checkAccess(serviceId)) { |
63 | return AccountInfo(); |
64 | } |
65 | |
66 | + credentials = QVariantMap(); |
67 | return AccountInfo(); |
68 | } |
69 | |
70 | === modified file 'src/daemon/manager.h' |
71 | --- src/daemon/manager.h 2015-02-11 12:59:23 +0000 |
72 | +++ src/daemon/manager.h 2015-02-18 12:26:47 +0000 |
73 | @@ -31,15 +31,16 @@ |
74 | ~Manager(); |
75 | |
76 | public Q_SLOTS: |
77 | - QList<AccountInfo> GetAccounts(const QStringList &serviceIds); |
78 | - AccountInfo GetAccountInfo(const QString &serviceId, uint accountId); |
79 | - QVariantMap Authenticate(const QString &serviceId, uint accountId, |
80 | - bool interactive, bool invalidate); |
81 | - AccountInfo Register(const QString &serviceId, QVariantMap &credentials); |
82 | + QList<AccountInfo> GetAccounts(const QVariantMap &filters); |
83 | + QVariantMap Authenticate(uint accountId, const QString &serviceId, |
84 | + bool interactive, bool invalidate, |
85 | + const QVariantMap ¶meters); |
86 | + AccountInfo RequestAccess(const QString &serviceId, |
87 | + const QVariantMap ¶meters, |
88 | + QVariantMap &credentials); |
89 | |
90 | Q_SIGNALS: |
91 | - void AccountChanged(const QString &serviceId, uint accountId, bool enabled); |
92 | - void CredentialsChanged(const QString &serviceId, uint accountId); |
93 | + void AccountChanged(const QString &serviceId, AccountInfo accountInfo); |
94 | |
95 | private: |
96 | bool canAccess(const QString &serviceId); |
97 | |
98 | === modified file 'src/daemon/manager.xml' |
99 | --- src/daemon/manager.xml 2015-02-10 07:33:36 +0000 |
100 | +++ src/daemon/manager.xml 2015-02-18 12:26:47 +0000 |
101 | @@ -5,87 +5,148 @@ |
102 | <interface name="com.ubuntu.OnlineAccounts.Manager"> |
103 | |
104 | <!-- |
105 | - GetAccounts: returns a list containing account information for |
106 | - accounts that provide one of a list of service IDs. |
107 | + Global concepts: |
108 | + |
109 | + Clients are identified by their "applicationId", which is the |
110 | + "<package>_<app>" of the client. |
111 | + |
112 | + The "serviceId" is an application-specific name for an account provider. |
113 | + That is, the "serviceId" contains the information about the application |
114 | + which will use it, and the account provider (e.g. "google", "facebook"). |
115 | + "serviceId"s are backed by files shipped with the application, which can |
116 | + contain application/account-provider specific information, such as the |
117 | + ClientId and ClientSecret to be used when authentication with OAuth 2.0. |
118 | + An application can ship more than one "serviceId", if they refer to |
119 | + different account providers; that is, one application can have a |
120 | + serviceId for Google and one for Facebook, but the same application |
121 | + cannot have one for GMail and another for Picasa. |
122 | + --> |
123 | + |
124 | + <!-- |
125 | + GetAccounts: returns a list of account IDs that satisfy the given |
126 | + filters. |
127 | + |
128 | + Allowed keys for the "filters" parameter (any combination is allowed, |
129 | + though not all combinations might make sense): |
130 | + |
131 | + - "applicationId" ("s"): the "<package>_<app>" of the client. An |
132 | + unconfined application can specify this in order to restrict the set |
133 | + of results to only those accounts that the application has been |
134 | + authorized to use. For confined apps, OA will deduce the |
135 | + applicationId from the apparmor label of the caller. |
136 | + |
137 | + - "serviceId" ("s"): if the application wants to list only those |
138 | + accounts coming from a specific provider (e.g., "Facebook"). |
139 | + |
140 | + - "accountId" ("u"): the ID of an account. |
141 | + |
142 | + In any case, an application will receive only those accounts which the |
143 | + user has authorized the application to use. See |
144 | + http://wiki.ubuntu.com/OnlineAccounts |
145 | + for an overview of the UI experience. |
146 | + |
147 | + Disabled accounts will not be returned. |
148 | --> |
149 | <method name="GetAccounts"> |
150 | - <arg name="service_ids" type="as" direction="in" /> |
151 | + <arg name="filters" type="a{sv}" direction="in" /> |
152 | + <!-- |
153 | + The return value is a list of account IDs paired with a dictionary of account data. |
154 | + This will always include: |
155 | + - "serviceId" (s) |
156 | + - "displayName" (s) |
157 | + Other settings stored on the account will also be included, such as the |
158 | + server address and port of an owncloud or IMAP account, but we haven't |
159 | + defined exactly how. Possibly, all account-specific keys will be |
160 | + prefixed by "settings/", in order not to clash with the keys defined at |
161 | + the framework level. |
162 | + --> |
163 | <arg name="accounts" type="a(ua{sv})" direction="out" /> |
164 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/> |
165 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" |
166 | value="QList<AccountInfo>"/> |
167 | </method> |
168 | |
169 | <!-- |
170 | - GetAccountInfo: return information about a given account ID |
171 | - --> |
172 | - <method name="GetAccountInfo"> |
173 | - <arg name="service_id" type="s" direction="in" /> |
174 | - <arg name="account_id" type="u" direction="in" /> |
175 | - <arg name="details" type="(ua{sv})" direction="out" /> |
176 | - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="AccountInfo"/> |
177 | - </method> |
178 | - |
179 | - <!-- |
180 | - Authenticate: request authentication credentials for the given |
181 | - account ID in the context of a particualr service. |
182 | - |
183 | - If "interactive" is false, an error will be returned if |
184 | - user interaction would be required to retrieve the |
185 | - credentials. |
186 | - |
187 | - If "invalidate" is true, any stored credentials will be |
188 | - ignored and new credentials will be requested from the account |
189 | - provider. |
190 | + Authenticate: request authentication credentials for the given |
191 | + account ID in the context of a particular service. |
192 | + |
193 | + If "interactive" is false, an error will be returned if |
194 | + user interaction would be required to retrieve the |
195 | + credentials. |
196 | + |
197 | + If "invalidate" is true, any stored credentials will be |
198 | + ignored and new credentials will be requested from the account |
199 | + provider. |
200 | --> |
201 | <method name="Authenticate"> |
202 | - <arg name="service_id" type="s" direction="in" /> |
203 | - <arg name="account_id" type="u" direction="in" /> |
204 | + <arg name="accountId" type="u" direction="in" /> |
205 | + <arg name="serviceId" type="s" direction="in" /> |
206 | <arg name="interactive" type="b" direction="in" /> |
207 | <arg name="invalidate" type="b" direction="in" /> |
208 | - <!-- <arg name="reply_socket" type="h" direction="in" /> --> |
209 | + <!-- |
210 | + This dictionary can be used to specify OAuth client keys or permission |
211 | + scopes. While it's possible to statically define them a the "serviceId" |
212 | + level, some apps might want to change this information at runtime. |
213 | + Possible use cases: |
214 | + 1) OAuth keys are retrieved from a server (so that they can be updated |
215 | + when the old ones are revoked). |
216 | + 2) An app might want to use different keys when talking to GMail and |
217 | + Picasa. |
218 | + 3) The scope list can also be dynamic, and depending on how the user is |
219 | + using the app. |
220 | + 4) SASL: the parameters would contain the latest challenge got from the |
221 | + server. |
222 | + --> |
223 | + <arg name="parameters" type="a{sv}" direction="in" /> |
224 | <arg name="credentials" type="a{sv}" direction="out" /> |
225 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QVariantMap"/> |
226 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> |
227 | </method> |
228 | |
229 | <!-- |
230 | - Register: register a new account for use with the given |
231 | - service. |
232 | + RequestAccess: register a new account for use with the given |
233 | + service. |
234 | + This method also performs the authentication, since that's what apps |
235 | + would do as soon as they get the account. |
236 | --> |
237 | - <method name="Register"> |
238 | - <arg name="service_id" type="s" direction="in" /> |
239 | - <!-- <arg name="reply_socket" type="h" direction="in" /> --> |
240 | + <method name="RequestAccess"> |
241 | + <arg name="serviceId" type="s" direction="in" /> |
242 | + <arg name="parameters" type="a{sv}" direction="in" /> |
243 | <arg name="account" type="(ua{sv})" direction="out" /> |
244 | + <arg name="credentials" type="a{sv}" direction="out" /> |
245 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/> |
246 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="AccountInfo"/> |
247 | - <arg name="credentials" type="a{sv}" direction="out" /> |
248 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/> |
249 | </method> |
250 | |
251 | <!-- |
252 | - AccountChanged: emitted when account details are changed. |
253 | - |
254 | - This signal will be emitted when new accounts are enabled, and |
255 | - when existing accounts are disabled. Clients can detect these |
256 | - cases by checking the "enabled" flag and comparing the account |
257 | - ID with the list of accounts they currently know about. |
258 | - |
259 | - The actual changed account details can be retrieved with |
260 | - GetAccountInfo(). |
261 | + AccountChanged: emitted when account details are changed. |
262 | + |
263 | + The apparmor policy will NOT ALLOW confined applications to receive |
264 | + this signal on the account manager object path (which might be |
265 | + /com/ubuntu/OnlineAccounts/Manager). Only unconfined applications will |
266 | + be able to listen to this signal from that object path. |
267 | + |
268 | + Confined apps will have to catch this signal from a different object path: |
269 | + /com/ubuntu/OnlineAccounts/Manager/@{APP_PKGNAME_DBUS}, which will |
270 | + deliver the signal only for those accounts which the app has been |
271 | + authorized to use. |
272 | --> |
273 | <signal name="AccountChanged"> |
274 | - <arg name="service_id" type="s" /> |
275 | - <arg name="account_id" type="u" /> |
276 | - <arg name="enabled" type="b" /> |
277 | - </signal> |
278 | - |
279 | - <!-- |
280 | - CredentialsChanged: emitted when the credentials for the given |
281 | - service ID on the given account change. |
282 | - |
283 | - The new credentials can be retrieved with Authenticate(). |
284 | - --> |
285 | - <signal name="CredentialsChanged"> |
286 | - <arg name="service_id" type="s" /> |
287 | - <arg name="account_id" type="u" /> |
288 | + <!-- |
289 | + The serviceId will also be included in the "account" dictionary. The |
290 | + reason for having it also here is to allow clients to filter D-Bus |
291 | + messages by arg0. This can be important for unconfined clients, which |
292 | + would otherwise be woken up by any account change, even those not |
293 | + relevant to them. |
294 | + --> |
295 | + <arg name="serviceId" type="s" /> |
296 | + <!-- |
297 | + The dictionary contains a changeType key, type "u", whose value is |
298 | + enum { enabled, disabled, changed } |
299 | + --> |
300 | + <arg name="account" type="(ua{sv})" /> |
301 | + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="AccountInfo"/> |
302 | </signal> |
303 | |
304 | </interface> |
Hi Alberto,
Many of these changes seem to be things that we disagreed about in the meeting previously. I have also been working on updating the interface as we discussed at that meeting, so can we hold off on this?
I've left some inline comments in the diff.