Skip to content

Commit 0744f3c

Browse files
committed
fix accesskeys
1 parent a5ee1f5 commit 0744f3c

File tree

13 files changed

+176
-46
lines changed

13 files changed

+176
-46
lines changed

app.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var helmet = require('helmet');
99
var routes = require('./routes/index');
1010
var auth = require('./routes/auth');
1111
var accessKeys = require('./routes/accessKeys');
12+
var sessions = require('./routes/sessions');
1213
var account = require('./routes/account');
1314
var apps = require('./routes/apps');
1415
var app = express();
@@ -35,6 +36,7 @@ app.use(express.static(path.join(__dirname, 'public')));
3536
app.use('/', routes);
3637
app.use('/auth', auth);
3738
app.use('/accessKeys', accessKeys);
39+
app.use('/sessions', sessions);
3840
app.use('/account', account);
3941
app.use('/apps', apps);
4042

core/middleware.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var _ = require('lodash');
33
var Promise = require('bluebird');
44
var security = require('../core/utils/security');
55
var models = require('../models');
6+
var moment = require('moment');
67

78
var middleware = module.exports
89

@@ -15,7 +16,7 @@ var checkAuthToken = function (authToken) {
1516
throw new Error('401 Unauthorized');
1617
}
1718
return models.UserTokens.findOne({
18-
where: {tokens: authToken, uid: users.id}
19+
where: {tokens: authToken, uid: users.id, expires_at: { gt: moment().utc().format('YYYY-MM-DD hh:mm:ss') }}
1920
})
2021
.then(function(tokenInfo){
2122
if (_.isEmpty(tokenInfo)){
@@ -78,6 +79,6 @@ middleware.checkToken = function(req, res, next) {
7879
res.status(401).send(e.message);
7980
});
8081
} else {
81-
res.status(401).send(e.message);
82+
res.status(401).send('401 Unauthorized');
8283
}
8384
};

core/services/account-manager.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var models = require('../../models');
44
var _ = require('lodash');
55
var validator = require('validator');
66
var security = require('../utils/security');
7+
var moment = require('moment');
78

89
var proto = module.exports = function (){
910
function AccountManager() {
@@ -50,24 +51,38 @@ proto.findUserByEmail = function (email) {
5051

5152
proto.getAllAccessKeyByUid = function (uid) {
5253
return models.UserTokens.findAll({where: {uid: uid}})
53-
.then(function (token) {
54-
return _.map(token, function(v){
54+
.then(function (tokens) {
55+
return _.map(tokens, function(v){
5556
return {
56-
name: v.tokens,
57-
createdTime: v.created_at,
57+
id: v.id + "",
58+
name: '(hidden)',
59+
createdTime: parseInt(moment(v.created_at).format('x')),
5860
createdBy: v.created_by,
61+
expires: parseInt(moment(v.expires_at).format('x')),
62+
friendlyName: v.name,
63+
isSession: v.is_session == 0 ? false : true,
5964
description: v.description,
6065
};
6166
});
6267
});
6368
};
6469

65-
proto.createAccessKey = function (uid, newAccessKey, createdBy, description) {
70+
proto.isExsitAccessKeyName = function (uid, friendlyName) {
71+
return models.UserTokens.findOne({
72+
where: {uid: uid, name: friendlyName}
73+
});
74+
};
75+
76+
proto.createAccessKey = function (uid, newAccessKey, isSession, ttl, friendlyName, createdBy, description) {
6677
return models.UserTokens.create({
6778
uid: uid,
79+
name: friendlyName,
6880
tokens: newAccessKey,
6981
description: description,
70-
created_by: createdBy
82+
is_session: isSession ? true : false,
83+
created_by: createdBy,
84+
expires_at: moment().utc().add(ttl/1000, 'seconds').format('YYYY-MM-DD hh:mm:ss'),
85+
created_at: moment().utc().format('YYYY-MM-DD hh:mm:ss'),
7186
});
7287
};
7388

models/user_tokens.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ module.exports = function(sequelize, DataTypes) {
99
primaryKey: true
1010
},
1111
uid: DataTypes.BIGINT(20),
12+
name: DataTypes.STRING,
1213
tokens: DataTypes.STRING,
1314
description: DataTypes.STRING,
14-
created_by:DataTypes.STRING,
15-
created_at:DataTypes.TIME,
15+
is_session: DataTypes.INTEGER(3),
16+
created_by: DataTypes.STRING,
17+
created_at: DataTypes.TIME,
1618
expires_at : DataTypes.TIME
1719
}, {
1820
updatedAt: false,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"jade": "~1.11.0",
2929
"jsonwebtoken": "^7.1.7",
3030
"lodash": "^4.5.1",
31+
"moment": "^2.14.1",
3132
"morgan": "~1.6.1",
3233
"mysql": "^2.10.2",
3334
"ncp": "^2.0.0",

public/stylesheets/index.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.site-notice {
2+
padding: 5px 0;
3+
text-align: center;
4+
background-color: #fff;
5+
}

public/stylesheets/tokens.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.site-notice {
2+
padding: 5px 0;
3+
text-align: center;
4+
background-color: #fff;
5+
}

routes/accessKeys.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,35 @@ router.post('/', middleware.checkToken, function(req, res, next) {
2020
var uid = req.users.id;
2121
var identical = req.users.identical;
2222
var createdBy = _.trim(req.body.createdBy);
23+
var friendlyName = _.trim(req.body.friendlyName);
24+
var isSession = req.body.isSession;
25+
var ttl = parseInt(req.body.ttl);
2326
var description = _.trim(req.body.description);
2427
var newAccessKey = security.randToken(28).concat(identical);
25-
accountManager.createAccessKey(uid, newAccessKey, createdBy, description)
28+
accountManager.isExsitAccessKeyName(uid, friendlyName).then(function (data) {
29+
if (!_.isEmpty(data)) {
30+
throw Error(`The access key ${friendlyName} already exists.`);
31+
}
32+
return accountManager.createAccessKey(uid, newAccessKey, isSession, ttl, friendlyName, createdBy, description);
33+
})
2634
.then(function(newToken){
2735
var info = {
2836
name : newToken.tokens,
2937
createdTime : newToken.created_at,
3038
createdBy : newToken.created_by,
3139
description : newToken.description,
40+
friendlyName: newToken.name,
3241
};
3342
res.send({accessKey:info});
3443
}).catch(function (e) {
3544
res.status(406).send(e.message);
3645
});
3746
});
3847

39-
router.delete('/:accessKey', middleware.checkToken, function(req, res, next){
40-
var accessKey = _.trim(decodeURI(req.params.accessKey));
48+
router.delete('/:name', middleware.checkToken, function(req, res, next){
49+
var name = _.trim(decodeURI(req.params.name));
4150
var uid = req.users.id;
42-
models.UserTokens.destroy({where: {tokens:accessKey, uid: uid}})
51+
models.UserTokens.destroy({where: {name:name, uid: uid}})
4352
.then(function(rowNum){
4453
res.send("");
4554
}).catch(function (e) {

routes/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ router.get('/', function(req, res, next) {
99
res.render('index', { title: 'CodePushServer' });
1010
});
1111

12+
router.get('/tokens', function(req, res, next) {
13+
res.render('tokens', { title: '获取token' });
14+
});
15+
1216
router.get('/updateCheck', function(req, res, next){
1317
var deploymentKey = _.get(req, "query.deploymentKey");
1418
var appVersion = _.get(req, "query.appVersion");

routes/sessions.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var express = require('express');
2+
var router = express.Router();
3+
var _ = require('lodash');
4+
var security = require('../core/utils/security');
5+
var models = require('../models');
6+
var middleware = require('../core/middleware');
7+
var accountManager = require('../core/services/account-manager')();
8+
9+
router.delete('/:machineName', middleware.checkToken, function(req, res, next){
10+
var machineName = _.trim(decodeURI(req.params.machineName));
11+
var uid = req.users.id;
12+
models.UserTokens.destroy({where: {created_by:machineName, uid: uid}})
13+
.then(function(rowNum){
14+
res.send("");
15+
}).catch(function (e) {
16+
res.status(406).send(e.message);
17+
});
18+
});
19+
20+
module.exports = router;

views/auth/login.jade

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,39 @@ block css
55
block content
66
.container
77
form#form.form-signin(method="post")
8-
h2.form-signin-heading Please sign in
9-
label.sr-only(for="inputEmail") Email address
10-
input#inputEmail.form-control(type="text" name="account" placeholder="Email address" required autofocus)
11-
label.sr-only(for="inputPassword") Password
12-
input#inputPassword.form-control(type="password" name="password" placeholder="Password" required)
8+
h2.form-signin-heading 请登录
9+
label.sr-only(for="inputEmail") 邮箱地址/用户名
10+
input#inputEmail.form-control(type="text" name="account" placeholder="邮箱地址/用户名" required autofocus)
11+
label.sr-only(for="inputPassword") 密码
12+
input#inputPassword.form-control(type="password" name="password" placeholder="密码" required)
1313
.checkbox
1414
label
1515
input(type="checkbox" value="remember-me")
16-
span Remember me
17-
a#submitBtn.btn.btn-lg.btn-primary.btn-block Sign in
16+
span 记住我
17+
a#submitBtn.btn.btn-lg.btn-primary.btn-block 登录
1818

19-
#myModal.modal.fade.bs-example-modal-sm(tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel")
20-
.modal-dialog.modal-md
21-
.modal-content
22-
.modal-header
23-
button.close(data-dismiss="modal" aria-label="Close")
24-
span(aria-hidden="true") ×
25-
h4#mySmallModalLabel.modal-title login token
26-
.modal-body ...
27-
.modal-footer
28-
button.btn.btn-default(type="button" data-dismiss="modal") Close
29-
button.btn.btn-primary(type="button" data-dismiss="modal") OK
3019
block js
3120
script().
3221
var submit = false;
3322
$('#submitBtn').on('click', function () {
3423
if (submit) {
3524
return ;
3625
}
37-
var myModal = $('#myModal');
38-
myModal.on('hidden.bs.modal', function (e) {
39-
window.close();
40-
});
4126
submit = true;
4227
$.ajax({
4328
type: 'post',
4429
data: $('#form').serializeArray(),
4530
url: $('#form').attr('action'),
4631
dataType: 'json',
4732
success: function (data) {
48-
if (data.status == "OK") {
49-
myModal.find(".modal-body").text(data.results.tokens)
50-
myModal.modal('show');
51-
submit = false;
52-
} else {
53-
alert(data.errorMessage);
54-
submit = false;
55-
}
33+
if (data.status == "OK") {
34+
sessionStorage.setItem('auth', data.results.tokens)
35+
submit = false;
36+
location.href = '/tokens/' + location.search;
37+
} else {
38+
alert(data.errorMessage);
39+
submit = false;
40+
}
5641
}
5742
});
5843
});

views/index.jade

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
extends layout
2+
block css
3+
link(rel='stylesheet', href='/stylesheets/index.css')
24

35
block content
4-
h1= title
5-
p Welcome to #{title}
6+
.site-notice react naitve 热更新服务器
7+
h1(style="text-align: center;")= title
8+
p(style="text-align: center;") Welcome to #{title}
9+
.site-notice
10+
a.btn.btn-primary(href="/auth/login" type="button") 登录

views/tokens.jade

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
extends layout
2+
block css
3+
link(rel='stylesheet', href='/stylesheets/tokens.css')
4+
5+
block content
6+
h1(style="text-align: center;")= title
7+
.site-notice
8+
a#submitBtn.btn.btn-lg.btn-primary 获取token
9+
.form-group
10+
#tipsSuccess(style="display:none")
11+
h2(style="text-align: center;") Authentication succeeded.
12+
h2(style="text-align: center;") Please copy and paste this access key to the command window:
13+
.form-group
14+
.col-sm-offset-3.col-sm-6
15+
input#key.form-control(style="display:none" readonly)
16+
br
17+
.form-group
18+
#tipsClose(style="display:none")
19+
h2(style="text-align: center;") After doing so, please close this browser.
20+
21+
block js
22+
script().
23+
var submit = false;
24+
function parseQuery(query) {
25+
query = query.substring(1);
26+
var vars = query.split('&');
27+
var rs = {};
28+
for (var i = 0; i < vars.length; i++) {
29+
var pair = vars[i].split('=');
30+
rs[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
31+
}
32+
return rs;
33+
}
34+
$('#submitBtn').on('click', function () {
35+
if (submit) {
36+
return ;
37+
}
38+
submit = true;
39+
var query = parseQuery(location.search);
40+
var createdBy = query.hostname;
41+
var time = (new Date()).getTime();
42+
if (createdBy == null || createdBy == undefined || createdBy=="") {
43+
createdBy = 'Login-' + time;
44+
}
45+
var postParams = {
46+
createdBy: createdBy,
47+
friendlyName: "Login-" + time,
48+
ttl: 60*60*24*30*1000,
49+
description: "Login-" + time,
50+
isSession: true
51+
};
52+
var access_token = sessionStorage.getItem('auth');
53+
$.ajax({
54+
type: 'post',
55+
data: postParams,
56+
url: '/accessKeys?access_token='+access_token,
57+
dataType: 'json',
58+
success: function (data) {
59+
submit = false;
60+
$('#tipsSuccess').show();
61+
$('#key').val(data.accessKey.name);
62+
$('#key').show();
63+
$('#tipsClose').show();
64+
},
65+
error: function(XMLHttpRequest, textStatus, errorThrown) {
66+
submit = false;
67+
if (errorThrown == 'Unauthorized') {
68+
alert('请重新登录!');
69+
location.href = '/auth/login'
70+
}else {
71+
alert(errorThrown);
72+
}
73+
}
74+
});
75+
});
76+

0 commit comments

Comments
 (0)