mirror of
https://github.com/zhigang1992/firebase-tools.git
synced 2026-01-12 17:22:36 +08:00
basic auth structure with helper functions and skeleton modules
This commit is contained in:
26
bin/firebase
26
bin/firebase
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var optimist = require('optimist'),
|
||||
argv = optimist.usage('Usage: firebase (auth|app)').argv,
|
||||
app = require('../lib/app')
|
||||
auth = require('../lib/auth');
|
||||
argv = optimist.usage('Usage: firebase').argv,
|
||||
Auth = require('../lib/auth'),
|
||||
auth = new Auth(argv),
|
||||
App = require('../lib/app');
|
||||
|
||||
if (argv._.length === 0) {
|
||||
|
||||
@@ -11,15 +12,24 @@ if (argv._.length === 0) {
|
||||
optimist.showHelp();
|
||||
|
||||
} else {
|
||||
// Router
|
||||
// Top-level router
|
||||
switch (argv._[0]) {
|
||||
case 'app':
|
||||
app(argv);
|
||||
case 'refreshtoken':
|
||||
auth.login(
|
||||
function(email, token) {
|
||||
console.log('New token saved for ' + email + ': ' + token);
|
||||
},
|
||||
function() {
|
||||
console.log("Sorry, we couldn't refresh the token");
|
||||
},
|
||||
this
|
||||
);
|
||||
break;
|
||||
case 'auth':
|
||||
auth(argv);
|
||||
case 'app':
|
||||
new App(auth, argv);
|
||||
break;
|
||||
default:
|
||||
// No route found
|
||||
optimist.showHelp();
|
||||
}
|
||||
}
|
||||
|
||||
48
lib/api.js
Normal file
48
lib/api.js
Normal file
@@ -0,0 +1,48 @@
|
||||
var https = require('https'),
|
||||
querystring = require('querystring')
|
||||
|
||||
/**
|
||||
* Static API methods.
|
||||
*/
|
||||
var Api = {
|
||||
request: function(method, resource, data, callback, scope) {
|
||||
if (typeof(scope) === 'undefined') {
|
||||
var scope = this;
|
||||
}
|
||||
|
||||
// TODO: Add support for other request types
|
||||
if (method !== 'GET') {
|
||||
method = 'GET';
|
||||
}
|
||||
|
||||
if (method === 'GET') {
|
||||
var separator = resource.match(/\?/) ? '&' : '?';
|
||||
resource += separator + querystring.stringify(data);
|
||||
}
|
||||
|
||||
var options = {
|
||||
host: 'admin.firebase.com',
|
||||
path: resource,
|
||||
port: 443,
|
||||
method: method
|
||||
};
|
||||
|
||||
var req = https.request(options, function(res) {
|
||||
var responseString = '';
|
||||
res.setEncoding('utf8');
|
||||
|
||||
res.on('data', function (chunk) {
|
||||
responseString += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
var response = JSON.parse(responseString);
|
||||
callback.call(scope, res.statusCode, response);
|
||||
});
|
||||
})
|
||||
|
||||
req.end();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Api;
|
||||
22
lib/app.js
22
lib/app.js
@@ -1,5 +1,21 @@
|
||||
module.exports = app;
|
||||
var optimist = require('optimist');
|
||||
|
||||
function app(argv) {
|
||||
console.log('app', argv);
|
||||
function App(auth, argv) {
|
||||
// TODO: Ensure valid route
|
||||
var validRoute = true;
|
||||
if (validRoute) {
|
||||
auth.requireLogin(function() {
|
||||
// TODO: App-specific router
|
||||
console.log('app', argv);
|
||||
},
|
||||
function() {
|
||||
console.log("Sorry, we couldn't log you in");
|
||||
},
|
||||
this
|
||||
);
|
||||
} else {
|
||||
optimist.showHelp();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = App;
|
||||
|
||||
192
lib/auth.js
192
lib/auth.js
@@ -1,5 +1,191 @@
|
||||
module.exports = auth;
|
||||
var prompt = require('prompt'),
|
||||
fs = require('fs'),
|
||||
configFile = process.env['HOME'] + '/.firebaserc',
|
||||
Api = require('./api');
|
||||
|
||||
function auth(argv) {
|
||||
console.log('auth', argv);
|
||||
/**
|
||||
* Auth-related methods.
|
||||
* Stores the current user's credentials and syncs them to disc.
|
||||
*/
|
||||
function Auth(argv) {
|
||||
try {
|
||||
var data = fs.readFileSync(configFile),
|
||||
config;
|
||||
config = JSON.parse(data);
|
||||
if (typeof(config.authToken) === 'string') {
|
||||
this.authToken = config.authToken;
|
||||
} else {
|
||||
this.authToken = '';
|
||||
}
|
||||
if (typeof(config.email) === 'string') {
|
||||
this.email = config.email;
|
||||
} else {
|
||||
this.email = '';
|
||||
}
|
||||
} catch (err) {
|
||||
this.authToken = '';
|
||||
this.email = '';
|
||||
}
|
||||
this.argv = argv;
|
||||
}
|
||||
|
||||
Auth.prototype.validate = function(successCallback, errorCallback, scope) {
|
||||
if (typeof(scope) === 'undefined') {
|
||||
var scope = this;
|
||||
}
|
||||
Api.request('GET',
|
||||
'/token/validate',
|
||||
{
|
||||
token: this.authToken
|
||||
},
|
||||
function(statusCode, response) {
|
||||
if (response.success) {
|
||||
if (typeof(successCallback) === 'function') {
|
||||
successCallback.call(scope);
|
||||
}
|
||||
} else {
|
||||
if (typeof(errorCallback) === 'function') {
|
||||
errorCallback.call(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Auth.prototype.loginRequest = function(successCallback, errorCallback, scope) {
|
||||
if (typeof(scope) === 'undefined') {
|
||||
var scope = this;
|
||||
}
|
||||
var that = this,
|
||||
schema = {
|
||||
properties: {
|
||||
email: {
|
||||
description: 'Email',
|
||||
pattern: /@/,
|
||||
message: 'Must be a valid email address',
|
||||
required: true
|
||||
},
|
||||
password: {
|
||||
description: 'Password',
|
||||
hidden: true,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.email.length > 0) {
|
||||
schema.properties.email.default = this.email;
|
||||
}
|
||||
|
||||
prompt.override = this.argv;
|
||||
prompt.message = '';
|
||||
prompt.delimiter = '';
|
||||
|
||||
prompt.get(schema, function(err, result) {
|
||||
if (err) {
|
||||
if (typeof(errorCallback) === 'function') {
|
||||
errorCallback.call(scope);
|
||||
}
|
||||
return;
|
||||
}
|
||||
that.email = result.email;
|
||||
that.authenticate(
|
||||
result.email,
|
||||
result.password,
|
||||
successCallback,
|
||||
errorCallback,
|
||||
scope
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
var maxRetries = 3;
|
||||
|
||||
Auth.prototype.requireLogin = function(successCallback, errorCallback, scope) {
|
||||
if (typeof(scope) === 'undefined') {
|
||||
var scope = this;
|
||||
}
|
||||
var that = this;
|
||||
|
||||
this.validate(
|
||||
successCallback,
|
||||
that.attemptLogin(maxRetries, successCallback, errorCallback, scope),
|
||||
scope
|
||||
);
|
||||
};
|
||||
|
||||
Auth.prototype.attemptLogin = function(tries, successCallback, errorCallback, scope) {
|
||||
var that = this;
|
||||
return function() {
|
||||
if (tries > 0) {
|
||||
if (tries == maxRetries) {
|
||||
console.log('You need to be logged in to perform this action');
|
||||
} else {
|
||||
console.log('Email or password incorrect, please try again');
|
||||
}
|
||||
that.loginRequest(
|
||||
successCallback,
|
||||
that.attemptLogin(tries - 1, successCallback, errorCallback, scope),
|
||||
scope
|
||||
);
|
||||
} else {
|
||||
if (typeof(errorCallback) === 'function') {
|
||||
errorCallback.call(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Auth.prototype.login = function(successCallback, errorCallback, scope) {
|
||||
this.attemptLogin(maxRetries, successCallback, errorCallback, scope)();
|
||||
};
|
||||
|
||||
Auth.prototype.authenticate = function(email, password, successCallback, errorCallback, scope) {
|
||||
var data = {
|
||||
email: email,
|
||||
password: password,
|
||||
rememberMe: true
|
||||
};
|
||||
Api.request(
|
||||
'GET',
|
||||
'/account/login',
|
||||
data,
|
||||
this.handleLogin(successCallback, errorCallback, scope),
|
||||
this
|
||||
);
|
||||
};
|
||||
|
||||
Auth.prototype.handleLogin = function(successCallback, errorCallback, scope) {
|
||||
return function(statusCode, response) {
|
||||
var token = response.adminToken;
|
||||
if (!token) {
|
||||
if (typeof(errorCallback) === 'function') {
|
||||
errorCallback.call(scope);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.storeToken(token, successCallback, errorCallback, scope);
|
||||
}
|
||||
};
|
||||
|
||||
Auth.prototype.storeToken = function(token, successCallback, errorCallback, scope) {
|
||||
this.authToken = token;
|
||||
var data = {
|
||||
email: this.email,
|
||||
authToken: this.authToken
|
||||
};
|
||||
var dataString = JSON.stringify(data, null, 2) + "\n";
|
||||
fs.writeFile(configFile, dataString, function (err) {
|
||||
if (err) {
|
||||
if (typeof(errorCallback) === 'function') {
|
||||
errorCallback.call(scope);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (typeof(successCallback) === 'function') {
|
||||
successCallback.call(scope, data.email, data.authToken);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Auth;
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"repository": "https://github.com/firebase/firebase-cli.git",
|
||||
"homepage": "https://github.com/firebase/firebase-cli",
|
||||
"dependencies": {
|
||||
"optimist": "0.6.x"
|
||||
"optimist": "0.6.x",
|
||||
"prompt": "0.2.x"
|
||||
},
|
||||
"bin": {
|
||||
"firebase": "./bin/firebase"
|
||||
|
||||
Reference in New Issue
Block a user