Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
17
gaia/apps/system/fxa/test/marionette/lib/config.json
Executable file
17
gaia/apps/system/fxa/test/marionette/lib/config.json
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"MARIONETTE_TIMEOUT": 20000,
|
||||
"USER_NEW": 0,
|
||||
"USER_EXISTING": 1,
|
||||
"USER_EXISTING_EMAIL": "kilroy_exists",
|
||||
"USER_EXISTING_PW": "123456789",
|
||||
"USERNAME_LEN": "24",
|
||||
"USER_NEW_PW": "123456789",
|
||||
"PASSWORD_HASH": "059b7beebaf4824e5395fb9eba6e8424b6ee27b43675130608502790e4af2178",
|
||||
"MAIL_HOST": "restmail.net",
|
||||
"SERVER_HOST": "localhost",
|
||||
"SERVER_PORT": 8081,
|
||||
"SERVER_PATH": "v1",
|
||||
"AUTH_SERVER_URL": "https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format",
|
||||
"DEBUG": false
|
||||
}
|
||||
|
||||
235
gaia/apps/system/fxa/test/marionette/lib/fxa.js
Executable file
235
gaia/apps/system/fxa/test/marionette/lib/fxa.js
Executable file
|
|
@ -0,0 +1,235 @@
|
|||
'use strict';
|
||||
|
||||
var FxAUser = require('./fxa_user'),
|
||||
config = require('./config.json');
|
||||
|
||||
/**
|
||||
* Abstraction around FxA app.
|
||||
* 'Entrance point' app URL is passed in since FxA acts more like a
|
||||
* component than a standalone app
|
||||
* (launched by Settings, Marketplace, FTU, FMD, dev_apps, etc.)
|
||||
*
|
||||
* @param client
|
||||
* @constructor
|
||||
*/
|
||||
function FxA(client) {
|
||||
this.config = config;
|
||||
this.fxaUser = new FxAUser();
|
||||
this.client = client.scope({ searchTimeout: config.MARIONETTE_TIMEOUT});
|
||||
}
|
||||
|
||||
FxA.SETTINGS_ORIGIN = 'app://settings.gaiamobile.org';
|
||||
FxA.UITEST_ORIGIN = 'app://uitest.gaiamobile.org';
|
||||
FxA.TEST_FXA_CLIENT_ORIGIN = 'app://test-fxa-client.gaiamobile.org';
|
||||
FxA.FTU_ORIGIN = 'app://ftu.gaiamobile.org';
|
||||
FxA.SERVER_PATH = 'http://' +
|
||||
config.SERVER_HOST + ':' +
|
||||
config.SERVER_PORT + '/' +
|
||||
config.SERVER_PATH;
|
||||
FxA.SERVER_ARGS = [
|
||||
config.SERVER_HOST,
|
||||
config.SERVER_PORT,
|
||||
config.SERVER_PATH
|
||||
];
|
||||
|
||||
FxA.COPPA_YEAR = new Date().getFullYear() - 13;
|
||||
|
||||
FxA.Selectors = {
|
||||
body: 'body',
|
||||
bodyReady: 'body .view-body',
|
||||
// dev_apps/uitest
|
||||
apiFxaFrame: '#test-iframe',
|
||||
fxaFrame: '#fxa-iframe',
|
||||
tabAPI: '#API',
|
||||
fxaButton: '#mozId-fxa',
|
||||
requestButton: '#request',
|
||||
// dev_apps/test-fxa-client
|
||||
tabOpenFlow: '#openFlow',
|
||||
// apps/settings
|
||||
menuItemFxa: '#menuItem-fxa',
|
||||
menuItemFmd: '#menuItem-findmydevice',
|
||||
fxaLogin: '#fxa-login',
|
||||
fmdLogin: '#findmydevice-login',
|
||||
fxaCancelAccountConfirmation: '#fxa-cancel-confirmation',
|
||||
// apps/ftu
|
||||
forward: '#forward',
|
||||
createAccountOrLogin: '#fxa-create-account',
|
||||
// apps/findmydevice
|
||||
emailInput: '#fxa-email-input',
|
||||
fxaForgotPassword: 'fxa-forgot-password',
|
||||
pwInput: '#fxa-pw-input',
|
||||
//COPPA (age-restriction menu no longer appears,
|
||||
// but password input tag is still different)
|
||||
pwInputPostCOPPA: '#fxa-pw-set-input',
|
||||
pwSetInput: '#fxa-pw-set-input',
|
||||
pwRefresh: '#fxa-pw-input-refresh',
|
||||
COPPAElementId: '#fxa-coppa',
|
||||
COPPASelectId: '#fxa-age-select',
|
||||
COPPAOptionVal: FxA.COPPA_YEAR + ' or earlier',
|
||||
COPPAOptionValToFail: FxA.COPPA_YEAR.toString(),
|
||||
moduleNext: '#fxa-module-next',
|
||||
moduleDone: '#fxa-module-done',
|
||||
errorOK: '#fxa-error-ok'
|
||||
};
|
||||
|
||||
FxA.prototype = {
|
||||
/**
|
||||
* Launches FxA app and focuses on frame.
|
||||
*/
|
||||
launch: function (origin) {
|
||||
// do unless FTU
|
||||
if (origin.search('ftu') === -1) {
|
||||
this.client.apps.launch(origin);
|
||||
}
|
||||
this.client.apps.switchToApp(origin);
|
||||
},
|
||||
|
||||
enterInput: function (inputId, inputString) {
|
||||
this.client.helper
|
||||
.waitForElement(inputId)
|
||||
.sendKeys(inputString);
|
||||
},
|
||||
|
||||
enterCOPPANew: function () {
|
||||
var sel = FxA.Selectors.COPPASelectId;
|
||||
var inputString = FxA.Selectors.COPPAOptionVal;
|
||||
this.client.helper.tapSelectOption(sel, inputString);
|
||||
},
|
||||
|
||||
enterEmailNew: function () {
|
||||
var sel = FxA.Selectors.emailInput;
|
||||
var inputString = this.fxaUser.email(config.USER_NEW);
|
||||
this.client.helper.fillInputField(sel, inputString);
|
||||
},
|
||||
enterPasswordNew: function () {
|
||||
var sel = FxA.Selectors.pwInputPostCOPPA;
|
||||
var inputString = this.fxaUser.password(config.USER_NEW);
|
||||
this.client.helper.fillInputField(sel, inputString);
|
||||
},
|
||||
enterEmailExisting: function () {
|
||||
var sel = FxA.Selectors.emailInput;
|
||||
var inputString = this.fxaUser.email(config.USER_EXISTING);
|
||||
this.client.helper.fillInputField(sel, inputString);
|
||||
},
|
||||
enterPasswordExisting: function () {
|
||||
var sel = FxA.Selectors.pwInput;
|
||||
var inputString = this.fxaUser.password(config.USER_EXISTING);
|
||||
this.client.helper.fillInputField(sel, inputString);
|
||||
},
|
||||
onClick: function(searchSelector) {
|
||||
var element = this.client.findElement(searchSelector);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickNext: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.moduleNext);
|
||||
var client = this.client;
|
||||
|
||||
client.waitFor(function () {
|
||||
return client.findElement(FxA.Selectors.moduleNext)
|
||||
.scriptWith(function (el) {
|
||||
return el.getAttribute('disabled') !== 'disabled';
|
||||
});
|
||||
});
|
||||
|
||||
client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickDone: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.moduleDone);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickTabOpenFlow: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.tabOpenFlow);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickFxaLogin: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.fxaLogin);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickMenuItemFxa: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.menuItemFxa);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickRequestButton: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.requestButton);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickTabAPI: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.tabAPI);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
clickFxaButton: function() {
|
||||
var element = this.client.findElement(FxA.Selectors.fxaButton);
|
||||
this.client.helper
|
||||
.waitForElement(element)
|
||||
.tap();
|
||||
},
|
||||
switchFrame: function(frameId) {
|
||||
this.client.switchToFrame();
|
||||
var frame = this.client.findElement(frameId);
|
||||
this.client.switchToFrame(frame);
|
||||
},
|
||||
switchFrameDirect: function(frameId) {
|
||||
var frame = this.client.findElement(frameId);
|
||||
this.client.switchToFrame(frame);
|
||||
},
|
||||
clickThruPanel: function(panelId, buttonId) {
|
||||
if (panelId === '#wifi') {
|
||||
// The wifi panel will bring up a screen to show it is scanning for
|
||||
// networks. Not waiting for this to clear will blow test timing
|
||||
// and cause things to fail.
|
||||
this.client.helper.waitForElementToDisappear('#loading-overlay');
|
||||
}
|
||||
// waitForElement is used to make sure animations and page changes have
|
||||
// finished, and that the panel is displayed.
|
||||
this.client.helper.waitForElement(panelId);
|
||||
|
||||
if (buttonId) {
|
||||
var button = this.client.helper.waitForElement(buttonId);
|
||||
button.click();
|
||||
}
|
||||
},
|
||||
runSettingsMenu: function() {
|
||||
this.clickMenuItemFxa();
|
||||
this.clickFxaLogin();
|
||||
this.switchFrame(FxA.Selectors.fxaFrame);
|
||||
},
|
||||
runUITestMenu: function() {
|
||||
this.clickTabAPI();
|
||||
this.clickFxaButton();
|
||||
this.switchFrameDirect(FxA.Selectors.apiFxaFrame);
|
||||
this.clickRequestButton();
|
||||
this.switchFrame(FxA.Selectors.fxaFrame);
|
||||
},
|
||||
runFTUMenu: function() {
|
||||
this.clickThruPanel('#languages', '#forward');
|
||||
this.clickThruPanel('#wifi', '#forward');
|
||||
this.clickThruPanel('#date_and_time', '#forward');
|
||||
this.clickThruPanel('#geolocation', '#forward');
|
||||
this.clickThruPanel('#import_contacts', '#forward');
|
||||
this.clickThruPanel('#firefox_accounts',
|
||||
FxA.Selectors.createAccountOrLogin);
|
||||
this.switchFrame(FxA.Selectors.fxaFrame);
|
||||
},
|
||||
runFxAClientTestMenu: function() {
|
||||
this.clickTabOpenFlow();
|
||||
this.switchFrame(FxA.Selectors.fxaFrame);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = FxA;
|
||||
54
gaia/apps/system/fxa/test/marionette/lib/fxa_user.js
Executable file
54
gaia/apps/system/fxa/test/marionette/lib/fxa_user.js
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
'use strict';
|
||||
|
||||
var config = require('./config.json');
|
||||
|
||||
/**
|
||||
* FxA user handler for email, password & string generations
|
||||
* @constructor
|
||||
*/
|
||||
function FxAUser() {
|
||||
}
|
||||
|
||||
FxAUser.prototype = {
|
||||
_randString: function(len, charSet){
|
||||
charSet = charSet || 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var rand = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
var randomPoz = Math.floor(Math.random() * charSet.length);
|
||||
rand += charSet.substring(randomPoz, randomPoz + 1);
|
||||
}
|
||||
return rand;
|
||||
},
|
||||
|
||||
get _uniqueUserName() {
|
||||
return this._randString(config.USERNAME_LEN);
|
||||
},
|
||||
|
||||
/**
|
||||
* @TODO bug 1052267
|
||||
* add ability to generate variety of "invalid" email strings
|
||||
*/
|
||||
email: function(userType) {
|
||||
switch(userType) {
|
||||
case config.USER_NEW:
|
||||
return this._uniqueUserName + '@' + config.MAIL_HOST;
|
||||
default:
|
||||
return config.USER_EXISTING_EMAIL + '@' + config.MAIL_HOST;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @TODO bug 1052267
|
||||
* add ability to generate variety of "invalid" password strings
|
||||
*/
|
||||
password: function(userType) {
|
||||
switch(userType) {
|
||||
case config.USER_NEW:
|
||||
return config.USER_NEW_PW;
|
||||
default:
|
||||
return config.USER_EXISTING_PW;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = FxAUser;
|
||||
39
gaia/apps/system/fxa/test/marionette/lib/server.js
Executable file
39
gaia/apps/system/fxa/test/marionette/lib/server.js
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
function Server(child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
Server.prototype = {
|
||||
/**
|
||||
* Sends signal to stop child process and stop server.
|
||||
*
|
||||
* TODO: Bug 1056186:
|
||||
* [FxA] Create unit tests for Firefox Accounts mock server process
|
||||
*/
|
||||
stop: function() {
|
||||
this.child.kill('SIGTERM');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Spawn the child process where the FxA mock server lives.
|
||||
*
|
||||
* @param args - [ host, port, path ]
|
||||
* @param callback
|
||||
*/
|
||||
function create(args, callback) {
|
||||
var child = require('child_process')
|
||||
.fork(__dirname + '/server_mock_fxa.js', args)
|
||||
.on('message', function(data) {
|
||||
if (Array.isArray(data) && data[0] === 'start') {
|
||||
callback(null, new Server(child));
|
||||
}
|
||||
})
|
||||
.on('error', function (err) {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
|
||||
Server.create = create;
|
||||
module.exports = Server;
|
||||
434
gaia/apps/system/fxa/test/marionette/lib/server_mock_fxa.js
Executable file
434
gaia/apps/system/fxa/test/marionette/lib/server_mock_fxa.js
Executable file
|
|
@ -0,0 +1,434 @@
|
|||
'use strict';
|
||||
|
||||
var restify = require('restify'),
|
||||
ecstatic = require('ecstatic'),
|
||||
config = require('./config.json');
|
||||
|
||||
var server = restify.createServer({
|
||||
name: 'Mock Firefox Accounts Server'
|
||||
});
|
||||
|
||||
server.hostname = process.argv[2];
|
||||
server.port = process.argv[3];
|
||||
server.version = process.argv[4];
|
||||
|
||||
process.on('uncaughtException', gracefulShutdown);
|
||||
server.on('uncaughtException', gracefulShutdown);
|
||||
|
||||
function shutdown(cb) {
|
||||
try {
|
||||
server.close(cb);
|
||||
} catch (e) {
|
||||
console.error(e.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function gracefulShutdown(err) {
|
||||
if (err) {
|
||||
console.error(err.stack);
|
||||
}
|
||||
shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* authPW = 123456789
|
||||
* client accepts any hex Token the server kindly grants it
|
||||
* Note: other user types could be added: i.e. verified user
|
||||
*/
|
||||
var account = {
|
||||
'new': {
|
||||
'authPW': config.PASSWORD_HASH,
|
||||
'uid': randomString(32),
|
||||
'sessionToken': randomString(64),
|
||||
'keyFetchToken': randomString(64),
|
||||
'passwordChangeToken': randomString(64),
|
||||
'verified': false,
|
||||
'authAt': Date.now()
|
||||
},
|
||||
|
||||
'exists': {
|
||||
'email': config.USER_EXISTING_EMAIL + '@' + config.MAIL_HOST,
|
||||
'authPW': config.PASSWORD_HASH,
|
||||
'uid': randomString(32),
|
||||
'sessionToken': randomString(64),
|
||||
'keyFetchToken': randomString(64),
|
||||
'passwordChangeToken': randomString(64),
|
||||
'verified': false,
|
||||
'authAt': Date.now()
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mock Firefox Accounts Server
|
||||
*
|
||||
* Purpose:
|
||||
* Mimic behavior of FxA server v1
|
||||
* (SHA: 29dc9abbacb3fe1b6de763f3c7bd85e63215297c)
|
||||
* with mostly 'canned' responses
|
||||
* Some APIs (i.e. for authentication) provide limited logical checking
|
||||
* for testing B2G
|
||||
*
|
||||
* Reference
|
||||
* https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md
|
||||
*/
|
||||
var Server = {
|
||||
|
||||
//set to true for verbose logging
|
||||
debug: config.DEBUG || false,
|
||||
|
||||
// allows for terminating process directly when calling server standalone
|
||||
// when calling as child process, use child.kill() from parent
|
||||
stop: function() {
|
||||
gracefulShutdown();
|
||||
console.log('SERVER STOPPED');
|
||||
},
|
||||
|
||||
start: function() {
|
||||
server.use(restify.acceptParser(server.acceptable));
|
||||
server.use(restify.queryParser());
|
||||
server.use(restify.bodyParser());
|
||||
server.use(ecstatic({ root: __dirname + '/' }));
|
||||
server.get('/', ecstatic({ root: __dirname }));
|
||||
server.listen(server.port, function() {
|
||||
var debug = Server.debug || false;
|
||||
if (debug) {
|
||||
console.log(' %s running on port: %s', server.name, server.port);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
(function(err, port) {
|
||||
Server.start();
|
||||
process.send(['start']);
|
||||
})();
|
||||
|
||||
// handle process messages
|
||||
process.on('message', function(data) {
|
||||
switch (data) {
|
||||
case 'stop':
|
||||
console.log('STOPPING MOCK SERVER');
|
||||
Server.stop();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
server.post('/v1/account/create', postAccountCreate);
|
||||
server.get('/v1/account/status', getAccountStatus);
|
||||
server.get('/v1/account/devices', getAccountDevices);
|
||||
server.get('/v1/account/keys', getAccountKeys);
|
||||
server.post('/v1/account/reset', respondEmpty);
|
||||
server.post('/v1/account/destroy', respondEmpty);
|
||||
server.post('/v1/account/login', postAccountLogin);
|
||||
server.get('/v1/session/status', respondEmpty);
|
||||
server.post('/v1/session/destroy', respondEmpty);
|
||||
server.get('/v1/recovery_email/status', getRecoveryEmailStatus);
|
||||
server.post('/v1/recovery_email/resend_code', respondEmpty);
|
||||
server.post('/v1/recovery_email/verify_code', respondEmpty);
|
||||
server.post('/v1/certificate/sign', postCertificateSign);
|
||||
server.post('/v1/password/change/start', postPasswordChangeStart);
|
||||
server.post('/v1/password/change/finish', respondEmpty);
|
||||
server.post('/v1/password/forgot/send_code', postPasswordForgotSendCode);
|
||||
server.post('/v1/password/forgot/resend_code', postPasswordForgotResendCode);
|
||||
server.post('/v1/password/forgot/verify_code', postPasswordForgotVerifyCode);
|
||||
server.get('/v1/forgot/status', getPasswordForgotStatus);
|
||||
server.post('/v1/get_random_bytes', postGetRandomBytes);
|
||||
|
||||
//catch any undefined requests
|
||||
server.get(/^\/([a-zA-Z0-9_\.~-]+)\/(.*)/, anyUndefined);
|
||||
server.post(/^\/([a-zA-Z0-9_\.~-]+)\/(.*)/, anyUndefined);
|
||||
|
||||
/************************************
|
||||
* API: Account
|
||||
************************************/
|
||||
|
||||
function postAccountCreate(req,res,next) {
|
||||
var accountSelected = getAccountType(req.body.email);
|
||||
var jsonResponse = getRespAccountCreate(accountSelected);
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function getAccountStatus(req,res,next) {
|
||||
var jsonResponse = { 'exists': false };
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function getAccountDevices(req,res,next) {
|
||||
var jsonResponse = {
|
||||
'devices': [
|
||||
{
|
||||
'id': '4c352927-cd4f-4a4a-a03d-7d1893d950b8',
|
||||
'type': 'computer',
|
||||
'name': 'Foxys Macbook'
|
||||
}
|
||||
]
|
||||
};
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function getAccountKeys(req,res,next) {
|
||||
var jsonResponse = {
|
||||
'bundle': randomString(256)
|
||||
};
|
||||
printLog('GET /account/keys', jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Authentication
|
||||
************************************/
|
||||
|
||||
function postAccountLogin(req,res,next) {
|
||||
var jsonResponse;
|
||||
var accountSelected = getAccountType(req.body.email);
|
||||
|
||||
if (req.body.email === account.exists.email) {
|
||||
if (req.body.authPW === account.exists.authPW) {
|
||||
jsonResponse = getRespAccountLogin(accountSelected);
|
||||
res.send(200, jsonResponse);
|
||||
} else {
|
||||
//status code 400, errno 103: incorrect password
|
||||
jsonResponse = getError(103,accountSelected);
|
||||
res.send(jsonResponse);
|
||||
}
|
||||
} else {
|
||||
//status code 400, errno 102: attempt to access a non-existent account
|
||||
jsonResponse = getError(102, accountSelected);
|
||||
res.send(jsonResponse);
|
||||
}
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Recovery Email
|
||||
************************************/
|
||||
|
||||
function getRecoveryEmailStatus(req,res,next) {
|
||||
var accountSelected = getAccountType(req.body.email);
|
||||
var jsonResponse = getRespRecoveryEmail(accountSelected);
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Certificate Signing
|
||||
************************************/
|
||||
|
||||
function postCertificateSign(req,res,next) {
|
||||
var jsonResponse = {
|
||||
'cert': randomString(520,
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ.abcdefghijklmnopqrstuvwxyz0123456789')
|
||||
};
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Password
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* should verify request of format:
|
||||
* {
|
||||
* "email": "me@example.com",
|
||||
* "oldAuthPW":
|
||||
* "d486e79c9f3214b0010fe31bfb50fa6c12e1d093f7770c81c6b1c19c7ee375a6"
|
||||
* }
|
||||
*/
|
||||
function postPasswordChangeStart(req,res,next) {
|
||||
|
||||
var accountSelected = getAccountType(req.body.email);
|
||||
var jsonResponse;
|
||||
if (req.body.email === account.exists.email) {
|
||||
jsonResponse = getRespPasswordChangeStart(accountSelected);
|
||||
res.send(200, jsonResponse);
|
||||
} else {
|
||||
//status code 400, errno 102: attempt to access non-existent account
|
||||
jsonResponse = getError(102, accountSelected);
|
||||
res.send(jsonResponse);
|
||||
}
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function postPasswordForgotSendCode(req,res,next) {
|
||||
var jsonResponse = getRespPasswordForgotSendCode();
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function postPasswordForgotResendCode(req,res,next) {
|
||||
var jsonResponse = getRespPasswordForgotSendCode();
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function postPasswordForgotVerifyCode(req,res,next) {
|
||||
var jsonResponse = {
|
||||
'accountResetToken': randomString(128)
|
||||
};
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
function getPasswordForgotStatus(req,res,next) {
|
||||
var jsonResponse = { 'tries': 3, 'ttl': 420 };
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Miscellaneous
|
||||
************************************/
|
||||
|
||||
function postGetRandomBytes(req,res,next) {
|
||||
var randomData = getRandomBytes();
|
||||
var jsonResponse = { 'data': randomData };
|
||||
printLog(req.method + ' ' + req.url, jsonResponse);
|
||||
res.send(200,jsonResponse);
|
||||
}
|
||||
|
||||
/************************************
|
||||
* API: Undefined
|
||||
* any other requests land here
|
||||
************************************/
|
||||
|
||||
function anyUndefined(req,res,next) {
|
||||
printLog(req.method + ' ' + req.url + ' (UNDEFINED)',
|
||||
'value of req is: ' + req);
|
||||
}
|
||||
|
||||
function randomString(len, charSet) {
|
||||
charSet = charSet || 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var rand = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
var randomPoz = Math.floor(Math.random() * charSet.length);
|
||||
rand += charSet.substring(randomPoz,randomPoz+1);
|
||||
}
|
||||
return rand;
|
||||
}
|
||||
|
||||
/**
|
||||
* mock API will random 64 char length hex strings
|
||||
* @returns {string}
|
||||
*/
|
||||
function getRandomBytes() {
|
||||
return randomString(64);
|
||||
}
|
||||
|
||||
function getAccountType(returnType) {
|
||||
switch(returnType) {
|
||||
case account.exists.email:
|
||||
return account.exists;
|
||||
default:
|
||||
return account.new;
|
||||
}
|
||||
}
|
||||
|
||||
function respondEmpty(req,res,next) {
|
||||
printLog(req.method + ' ' + req.url, {});
|
||||
res.send(200, {});
|
||||
}
|
||||
|
||||
function getRespAccountLogin(accountSelected) {
|
||||
return {
|
||||
'uid': accountSelected.uid,
|
||||
'sessionToken': accountSelected.sessionToken,
|
||||
'verified': accountSelected.verified,
|
||||
'authAt': Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
function getRespRecoveryEmail(accountSelected) {
|
||||
return {
|
||||
'email': accountSelected.email,
|
||||
'verified': accountSelected.verified
|
||||
};
|
||||
}
|
||||
|
||||
function getRespAccountCreate(accountSelected) {
|
||||
return {
|
||||
'uid': accountSelected.uid,
|
||||
'sessionToken': accountSelected.sessionToken,
|
||||
'keyFetchToken': accountSelected.keyFetchToken,
|
||||
'authAt': Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
function getRespPasswordChangeStart(accountSelected) {
|
||||
return {
|
||||
'keyFetchToken': accountSelected.keyFetchToken,
|
||||
'passwordChangeToken': accountSelected.passwordChangeToken,
|
||||
'verified': accountSelected.verified
|
||||
};
|
||||
}
|
||||
|
||||
function getRespPasswordForgotSendCode() {
|
||||
return {
|
||||
'passwordForgotToken': randomString(128),
|
||||
'ttl': 900,
|
||||
'codeLength': 8,
|
||||
'tries': 3
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Use:
|
||||
* var errNum = req.socket._httpMessage.statusCode;
|
||||
* @param errNum
|
||||
* @param accountSelected
|
||||
* @returns {*}
|
||||
*/
|
||||
function getError(errNum,accountSelected) {
|
||||
var info = config.AUTH_SERVER_URL;
|
||||
switch(errNum) {
|
||||
case 102:
|
||||
return {
|
||||
'code': 400,
|
||||
'errno': errNum,
|
||||
'error': 'Bad Request',
|
||||
'message': 'Attempt to access an account that does not exist',
|
||||
'info': info,
|
||||
'email': accountSelected.email,
|
||||
'log': []
|
||||
};
|
||||
|
||||
case 103:
|
||||
return {
|
||||
'code': 400,
|
||||
'errno': errNum,
|
||||
'error': 'Bad Request',
|
||||
'message': 'Incorrect password',
|
||||
'info': info,
|
||||
'email': accountSelected.email,
|
||||
'log': []
|
||||
};
|
||||
|
||||
case 999:
|
||||
return {
|
||||
'code': errNum,
|
||||
'errno': 999,
|
||||
'error': 'Not Found',
|
||||
'message': 'Unspecified error',
|
||||
'info': info,
|
||||
'log': []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log req/res to stdout
|
||||
*/
|
||||
function printLog(title,msg) {
|
||||
if (config.DEBUG) {
|
||||
console.log('\n========================');
|
||||
console.log(title);
|
||||
console.log('========================');
|
||||
console.log(msg);
|
||||
console.log('\n\n');
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue