services/sync/modules/userapi.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial