Merge lp:~mardy/online-accounts-api/dbus-api into lp:online-accounts-api

Proposed by Alberto Mardegan
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
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.

Description of the change

Update D-Bus API, fix warnings

To post a comment you must log in.
Revision history for this message
James Henstridge (jamesh) wrote : Posted in a previous version of this proposal

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.

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
James Henstridge (jamesh) wrote : Posted in a previous version of this proposal

Replies to r4 comments.

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 &parameters)
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 &parameters,
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 &parameters);
86+ AccountInfo RequestAccess(const QString &serviceId,
87+ const QVariantMap &parameters,
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&lt;AccountInfo&gt;"/>
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>

Subscribers

People subscribed via source and target branches