Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions app/models/_user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
var schemas = require("./schemas.js");
var _ = require("lodash");
var fs = require('fs');
var userHomeDirectory = require('user-home');
var createIfNotExist = require("create-if-not-exist");

var User = function (data) {
this.data = data;
}

var usersPath = userHomeDirectory + '/users.json';

User.prototype.data = {}

User.prototype.changeName = function (name) {
this.data.name = name;
}

User.prototype.get = function (name) {
return this.data[name];
}

User.prototype.set = function (name, value) {
this.data[name] = value;
}

User.prototype.sanitize = function (data) {
data = data || {};
schema = schemas.user;
return _.pick(_.defaults(data, schema), _.keys(schema));
}

User.prototype.save = function (callback) {
var self = this;
this.data = this.data;
var result = saveUser({github: this.data.github}, this.data);
callback(null, result);
}

User.findById = function (id, callback) {
var data = getUsers({github: id});
if (err) return callback(err);
callback(null, new User(data));
}

User.findOne = function(findBy, callback) {
var users = getUsers(findBy);
if(!users || users.length === 0) {
callback();
} else {
callback(undefined, users);
}

}

User.getAllUsers = function() {
return getUsers();
}

function getUsers(findBy) {
createIfNotExist(usersPath, '{ "users":[] }');
var users = JSON.parse(fs.readFileSync(usersPath, 'utf8')).users;
if (!findBy) {
return users;
}
return _.find(users, findBy);
}

function saveUser(findBy, newUserData) {
if (!findBy || !newUserData) {
return;
}

var users = getUsers();

var match = _.find(users, findBy);
if (match) {
var index = _.indexOf(users, match);
users.splice(index, 1, newUserData);
} else {
users.push(newUserData);
}

var usersFile = {
"users": users
};

fs.writeFile(usersPath,
JSON.stringify(usersFile, null, 2),
'utf8',
function(err) {
if (err) {
res.json(err);
console.error('users couldn\'t be saved: ' + err);
} else {
console.info('users saved: ' + usersPath);
}
}
);
}

module.exports = User;
9 changes: 9 additions & 0 deletions app/models/schemas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var schemas = {
user: {
id: null,
name: null,
password: null
}
}

module.exports = schemas;
40 changes: 39 additions & 1 deletion app/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,48 @@ module.exports = function(app, express) {
require('../models/userHomeDirectoryService.js'),
downloadService = require('../models/downloadService.js'),
quotesService = require('../models/quotesService.js'),
settingsService = require('../models/settingsService.js');
settingsService = require('../models/settingsService.js'),
jwt = require('jsonwebtoken');

var config = {
TOKEN_SECRET: 'kibibitIsAwesome'
};

var apiRouter = express.Router();

// route middleware to verify a token
apiRouter.use(function(req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.params.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.TOKEN_SECRET, function(err, decoded) {
if (err) {
console.info('failed to authenticate', err);
return res.status(403).send({
success: false,
message: 'Failed to authenticate token.'
});
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
console.info('user authenticated successfully');
next();
}
});
} else {
// if there is no token
// return an HTTP response of 403 (access forbidden) and an error message
console.info('No token provided');
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
// next() used to be here
});

apiRouter.get('/', function(req, res) {
res.json({
message: 'hooray! welcome to our api!'
Expand Down
102 changes: 102 additions & 0 deletions app/routes/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
module.exports = function(app, express) {

var qs = require('querystring');
var express = require('express');
var jwt = require('jwt-simple');
var request = require('request');
var fs = require('fs');
var User = require('../models/_user');
var moment = require('moment');

var authRouter = express.Router();

var config = {
TOKEN_SECRET: 'kibibitIsAwesome'
};

//var users = userHomeDirectory + '/.users.json';

authRouter.route('/github')
.post(function(req, res) {
var accessTokenUrl = 'https://github.com/login/oauth/access_token';
var userApiUrl = 'https://api.github.com/user';
var params = {
code: req.body.code,
client_id: req.body.clientId,
client_secret: 'f0c57fb762f6fe9e7472eb23a8de902265bd5f63',
redirect_uri: req.body.redirectUri
};

// Step 1. Exchange authorization code for access token.
request.get({ url: accessTokenUrl, qs: params }, function(err, response, accessToken) {
accessToken = qs.parse(accessToken);
var headers = { 'User-Agent': 'Satellizer' };

// Step 2. Retrieve profile information about the current user.
request.get({ url: userApiUrl, qs: accessToken, headers: headers, json: true }, function(err, response, profile) {

// Step 3a. Link user accounts.
if (req.header('Authorization')) {
User.findOne({ github: profile.id }, function(err, existingUser) {
if (existingUser) {
return res.status(409).send({ message: 'There is already a GitHub account that belongs to you' });
}
var token = req.header('Authorization').split(' ')[1];
var payload = jwt.decode(token, config.TOKEN_SECRET);
User.findById(payload.sub, function(err, user) {
if (!user) {
return res.status(400).send({ message: 'User not found' });
}
user.set('github', profile.id);
user.set('picture', user.picture || profile.avatar_url);
user.set('displayName', user.login || user.displayName || profile.name);
user.save(function() {
var token = createJWT(user);
res.send({ token: token });
});
});
});
} else {
// Step 3b. Create a new user account or return an existing one.
User.findOne({ github: profile.id }, function(err, existingUser) {
if (existingUser) {
var token = createJWT(existingUser);
return res.send({ token: token });
}
var user = new User({});
user.set('github', profile.id);
user.set('picture', profile.avatar_url);
user.set('displayName', profile.login || profile.name)
user.save(function() {
var token = createJWT(user);
res.send({ token: token });
});
});
}
});
});
});

authRouter.route('/getUser')
.get(function(req, res) {
res.json({
"user": User.getAllUsers()[0]
});
});

/*
|--------------------------------------------------------------------------
| Generate JSON Web Token
|--------------------------------------------------------------------------
*/
function createJWT(user) {
var payload = {
sub: user._id,
iat: moment().unix(),
exp: moment().add(14, 'days').unix()
};
return jwt.encode(payload, config.TOKEN_SECRET);
}

return authRouter;
};
4 changes: 3 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
"opentype.js": "^0.6.3",
"underscore": "^1.8.3",
"angular-material-icons": "^0.7.1",
"svg-morpheus": "^0.3.2"
"svg-morpheus": "^0.3.2",
"satellizer": "^0.15.4",
"angular-strap": "^2.3.9"
},
"resolutions": {
"angular": "1.5.8"
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@
"body-parser": "^1.14.2",
"colors": "~1.1.2",
"compression": "^1.6.2",
"create-if-not-exist": "0.0.2",
"express": "^4.13.4",
"helmet": "^2.1.1",
"jsonwebtoken": "^7.1.9",
"jwt-simple": "^0.5.0",
"lodash": "^4.15.0",
"mime-types": "^2.1.11",
"moment": "^2.14.1",
"octonode": "^0.7.6",
"querystring": "^0.2.0",
"request": "^2.74.0",
"scribe-js": "^2.0.4",
"serve-favicon": "~2.3.0",
"user-home": "^2.0.0"
Expand Down
22 changes: 21 additions & 1 deletion public/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,32 @@ angular.module('kibibitCodeEditor',
'jsonFormatter',
'ngclipboard',
'ng.deviceDetector',
'ngMdIcons'])
'ngMdIcons',
'satellizer'])

// application configuration to integrate token into requests
.config(function($httpProvider) {
// attach our auth interceptor to the http requests
$httpProvider.interceptors.push('AuthInterceptor');
})

.config(['$compileProvider', function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}])

.config(function($authProvider) {
$authProvider.github({
clientId: 'e4c42e628b792e23f268'
});

$authProvider.tokenName = 'token';
$authProvider.tokenPrefix = 'kibibit';
$authProvider.tokenHeader = 'Authorization';
$authProvider.tokenType = 'Bearer';
$authProvider.storageType = 'localStorage';
//$authProvider.redirectUri = window.location.origin;
})

.config(['ScrollBarsProvider', function(ScrollBarsProvider) {
// the following settings are defined for all scrollbars unless the
// scrollbar has local scope configuration
Expand Down
36 changes: 31 additions & 5 deletions public/app/app.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,44 @@ angular.module('app.routes', ['ngRoute'])

.config(function($routeProvider, $locationProvider) {

/**
* Helper auth functions
*/
var skipIfLoggedIn = function($q, $auth) {
var deferred = $q.defer();
if ($auth.isAuthenticated()) {
deferred.reject();
} else {
deferred.resolve();
}
return deferred.promise;
};

var loginRequired = function($q, $location, $auth) {
var deferred = $q.defer();
if ($auth.isAuthenticated()) {
deferred.resolve();
} else {
$location.path('/login');
}
return deferred.promise;
};

$routeProvider

// route for the home page
.when('/', {
templateUrl: 'app/views/home.html'
})
.when('/', {
templateUrl: 'app/views/home.html'
})

// login page
// login page
.when('/login', {
templateUrl: 'app/views/login.html',
controller: 'mainController',
controllerAs: 'login'
controllerAs: 'login',
resolve: {
skipIfLoggedIn: skipIfLoggedIn
}
})

// show all users
Expand Down
Loading