services/sync/modules/userapi.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:945f56289779
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 this.EXPORTED_SYMBOLS = [
8 "UserAPI10Client",
9 ];
10
11 const {utils: Cu} = Components;
12
13 Cu.import("resource://gre/modules/Log.jsm");
14 Cu.import("resource://services-common/rest.js");
15 Cu.import("resource://services-common/utils.js");
16 Cu.import("resource://services-sync/identity.js");
17 Cu.import("resource://services-sync/util.js");
18
19 /**
20 * A generic client for the user API 1.0 service.
21 *
22 * http://docs.services.mozilla.com/reg/apis.html
23 *
24 * Instances are constructed with the base URI of the service.
25 */
26 this.UserAPI10Client = function UserAPI10Client(baseURI) {
27 this._log = Log.repository.getLogger("Sync.UserAPI");
28 this._log.level = Log.Level[Svc.Prefs.get("log.logger.userapi")];
29
30 this.baseURI = baseURI;
31 }
32 UserAPI10Client.prototype = {
33 USER_CREATE_ERROR_CODES: {
34 2: "Incorrect or missing captcha.",
35 4: "User exists.",
36 6: "JSON parse failure.",
37 7: "Missing password field.",
38 9: "Requested password not strong enough.",
39 12: "No email address on file.",
40 },
41
42 /**
43 * Determine whether a specified username exists.
44 *
45 * Callback receives the following arguments:
46 *
47 * (Error) Describes error that occurred or null if request was
48 * successful.
49 * (boolean) True if user exists. False if not. null if there was an error.
50 */
51 usernameExists: function usernameExists(username, cb) {
52 if (typeof(cb) != "function") {
53 throw new Error("cb must be a function.");
54 }
55
56 let url = this.baseURI + username;
57 let request = new RESTRequest(url);
58 request.get(this._onUsername.bind(this, cb, request));
59 },
60
61 /**
62 * Obtain the Weave (Sync) node for a specified user.
63 *
64 * The callback receives the following arguments:
65 *
66 * (Error) Describes error that occurred or null if request was successful.
67 * (string) Username request is for.
68 * (string) URL of user's node. If null and there is no error, no node could
69 * be assigned at the time of the request.
70 */
71 getWeaveNode: function getWeaveNode(username, password, cb) {
72 if (typeof(cb) != "function") {
73 throw new Error("cb must be a function.");
74 }
75
76 let request = this._getRequest(username, "/node/weave", password);
77 request.get(this._onWeaveNode.bind(this, cb, request));
78 },
79
80 /**
81 * Change a password for the specified user.
82 *
83 * @param username
84 * (string) The username whose password to change.
85 * @param oldPassword
86 * (string) The old, current password.
87 * @param newPassword
88 * (string) The new password to switch to.
89 */
90 changePassword: function changePassword(username, oldPassword, newPassword, cb) {
91 let request = this._getRequest(username, "/password", oldPassword);
92 request.onComplete = this._onChangePassword.bind(this, cb, request);
93 request.post(CommonUtils.encodeUTF8(newPassword));
94 },
95
96 createAccount: function createAccount(email, password, captchaChallenge,
97 captchaResponse, cb) {
98 let username = IdentityManager.prototype.usernameFromAccount(email);
99 let body = JSON.stringify({
100 "email": email,
101 "password": Utils.encodeUTF8(password),
102 "captcha-challenge": captchaChallenge,
103 "captcha-response": captchaResponse
104 });
105
106 let url = this.baseURI + username;
107 let request = new RESTRequest(url);
108
109 if (this.adminSecret) {
110 request.setHeader("X-Weave-Secret", this.adminSecret);
111 }
112
113 request.onComplete = this._onCreateAccount.bind(this, cb, request);
114 request.put(body);
115 },
116
117 _getRequest: function _getRequest(username, path, password=null) {
118 let url = this.baseURI + username + path;
119 let request = new RESTRequest(url);
120
121 if (password) {
122 let up = username + ":" + password;
123 request.setHeader("authorization", "Basic " + btoa(up));
124 }
125
126 return request;
127 },
128
129 _onUsername: function _onUsername(cb, request, error) {
130 if (error) {
131 cb(error, null);
132 return;
133 }
134
135 let body = request.response.body;
136 if (body == "0") {
137 cb(null, false);
138 return;
139 } else if (body == "1") {
140 cb(null, true);
141 return;
142 } else {
143 cb(new Error("Unknown response from server: " + body), null);
144 return;
145 }
146 },
147
148 _onWeaveNode: function _onWeaveNode(cb, request, error) {
149 if (error) {
150 cb.network = true;
151 cb(error, null);
152 return;
153 }
154
155 let response = request.response;
156
157 if (response.status == 200) {
158 let body = response.body;
159 if (body == "null") {
160 cb(null, null);
161 return;
162 }
163
164 cb(null, body);
165 return;
166 }
167
168 let error = new Error("Sync node retrieval failed.");
169 switch (response.status) {
170 case 400:
171 error.denied = true;
172 break;
173 case 404:
174 error.notFound = true;
175 break;
176 default:
177 error.message = "Unexpected response code: " + response.status;
178 }
179
180 cb(error, null);
181 return;
182 },
183
184 _onChangePassword: function _onChangePassword(cb, request, error) {
185 this._log.info("Password change response received: " +
186 request.response.status);
187 if (error) {
188 cb(error);
189 return;
190 }
191
192 let response = request.response;
193 if (response.status != 200) {
194 cb(new Error("Password changed failed: " + response.body));
195 return;
196 }
197
198 cb(null);
199 },
200
201 _onCreateAccount: function _onCreateAccount(cb, request, error) {
202 let response = request.response;
203
204 this._log.info("Create account response: " + response.status + " " +
205 response.body);
206
207 if (error) {
208 cb(new Error("HTTP transport error."), null);
209 return;
210 }
211
212 if (response.status == 200) {
213 cb(null, response.body);
214 return;
215 }
216
217 let error = new Error("Could not create user.");
218 error.body = response.body;
219
220 cb(error, null);
221 return;
222 },
223 };
224 Object.freeze(UserAPI10Client.prototype);

mercurial