Skip to content

Commit

Permalink
Create seperate database table for AccessTokens to hide jwt token and…
Browse files Browse the repository at this point in the history
… tokenId from user
  • Loading branch information
vbanthia committed Nov 25, 2015
1 parent 62413b3 commit 9cb2313
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 71 deletions.
23 changes: 13 additions & 10 deletions lib/db/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,20 +309,23 @@ dbapi.loadDevice = function(serial) {
}

dbapi.saveUserAccessToken = function(email, token) {
return db.run(r.table('users').get(email).update({
accessTokens: r.row('accessTokens').default([]).append({
title: token.title
, tokenId: token.tokenId
, jwt: token.jwt
})
return db.run(r.table('accessTokens').insert({
email: email
, id: token.id
, title: token.title
, jwt: token.jwt
}))
}

dbapi.removeUserAccessToken = function(email, title) {
return db.run(r.table('users').get(email).update({
accessTokens: r.row('accessTokens').default([]).filter(function(token) {
return token('title').ne(title)
})
return db.run(r.table('accessTokens').getAll(email, {
index: 'email'
}).filter({"title": title}).delete())
}

dbapi.loadAccessTokens = function(email) {
return db.run(r.table('accessTokens').getAll(email, {
index: 'email'
}))
}

Expand Down
11 changes: 6 additions & 5 deletions lib/db/tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ module.exports = {
indexFunction: function(user) {
return user('adbKeys')('fingerprint')
}
, accessTokens: {
indexFunction: function(user) {
return user('accessTokens')('tokenId')
}
}
, options: {
multi: true
}
}
}
}
, accessTokens: {
primaryKey: 'id'
, indexes: {
email: null
}
}
, vncauth: {
primaryKey: 'password'
, indexes: {
Expand Down
23 changes: 23 additions & 0 deletions lib/units/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,29 @@ module.exports = function(options) {
})
})

app.get('/app/api/v1/accessTokens', function(req, res) {
dbapi.loadAccessTokens(req.user.email)
.then(function(cursor) {
return Promise.promisify(cursor.toArray, cursor)()
.then(function(list) {
var titles = []
list.forEach(function(token) {
titles.push(token.title)
})
res.json({
success: true
, titles: titles
})
})
})
.catch(function(err) {
log.error('Failed to load tokens: ', err.stack)
res.json(500, {
success: false
})
})
})

server.listen(options.port)
log.info('Listening on port %d', options.port)
}
3 changes: 1 addition & 2 deletions lib/units/websocket/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,13 @@ module.exports = function(options) {

return dbapi.saveUserAccessToken(user.email, {
title: title
, tokenId: tokenId
, id: tokenId
, jwt: jwt
})
.then(function() {
socket.emit('user.keys.accessToken.generated', {
title: title
, tokenId: tokenId
, jwt: jwt
})
})
})
Expand Down
35 changes: 35 additions & 0 deletions res/app/components/stf/tokens/access-token-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = function AccessTokenServiceFactory(
$rootScope
, $http
, socket
) {
var AccessTokenService = {}

AccessTokenService.getAccessTokens = function() {
return $http.get('/app/api/v1/accessTokens')
}

AccessTokenService.generateAccessToken = function(title) {
socket.emit('user.keys.accessToken.generate', {
title: title
})
}

AccessTokenService.removeAccessToken = function(title) {
socket.emit('user.keys.accessToken.remove', {
title: title
})
}

socket.on('user.keys.accessToken.generated', function(token) {
$rootScope.$broadcast('user.keys.accessTokens.generated', token)
$rootScope.$apply()
})

socket.on('user.keys.accessToken.removed', function() {
$rootScope.$broadcast('user.keys.accessTokens.updated')
$rootScope.$apply()
})

return AccessTokenService
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ module.exports = function generateAccessTokenDirective() {
replace: true,
scope: {
showGenerate: '=',
showClipboard: '=',
},
template: require('./generate-access-token.jade'),
controller: function($scope, UserService) {
controller: function($scope, AccessTokenService) {
$scope.generateForm = {
title: ''
}

$scope.generateToken = function () {
UserService.generateAccessToken($scope.generateForm.title)
AccessTokenService.generateAccessToken($scope.generateForm.title)
$scope.closeGenerateToken()
}

Expand Down
1 change: 1 addition & 0 deletions res/app/components/stf/tokens/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports = angular.module('stf.tokens', [
require('./generate-access-token').name,
])
.factory('AccessTokenService', require('./access-token-service'))
36 changes: 0 additions & 36 deletions res/app/components/stf/user/user-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,6 @@ module.exports = function UserServiceFactory(

var user = UserService.currentUser = AppState.user

UserService.getAccessTokens = function() {
return (user.accessTokens || (user.accessTokens = []))
}

UserService.generateAccessToken = function(title) {
socket.emit('user.keys.accessToken.generate', {
title: title
})
}

UserService.removeAccessToken = function(title) {
socket.emit('user.keys.accessToken.remove', {
title: title
})
}

UserService.getAdbKeys = function() {
return (user.adbKeys || (user.adbKeys = []))
}
Expand All @@ -40,26 +24,6 @@ module.exports = function UserServiceFactory(
socket.emit('user.keys.adb.remove', key)
}

// socket.on('user.keys.accessToken.generated', function(token) {
// UserService.getAccessTokens().push(token)
// $rootScope.$broadcast('user.keys.accessTokens.updated', user.accessTokens)
// $rootScope.$apply()
// })

socket.on('user.keys.accessToken.generated', function(token) {
$rootScope.$broadcast('user.keys.accessTokens.generated', token)
$rootScope.$apply()
})

socket.on('user.keys.accessToken.removed', function(title) {
user.accessTokens = UserService.getAccessTokens().filter(function(token) {
return token.title !== title
})
$rootScope.$broadcast('user.keys.accessTokens.updated', user.accessTokens)
$rootScope.$apply()
})


socket.on('user.keys.adb.added', function(key) {
UserService.getAdbKeys().push(key)
$rootScope.$broadcast('user.keys.adb.updated', user.adbKeys)
Expand Down
18 changes: 9 additions & 9 deletions res/app/settings/keys/access-tokens/access-tokens-controller.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
module.exports = function AccessTokensCtrl($scope, $http, UserService) {
module.exports = function AccessTokensCtrl($scope, AccessTokenService) {

$scope.accessTokens = []
$scope.accessTokenTitles = []
$scope.newToken = null

function updateTokens() {
$scope.accessTokens = UserService.getAccessTokens()
AccessTokenService.getAccessTokens()
.success(function(response) {
$scope.accessTokenTitles = response.titles || []
})
}

$scope.removeToken = function (title) {
UserService.removeAccessToken(title)
AccessTokenService.removeAccessToken(title)
}

$scope.tokenGenerated = function() {
$scope.accessToken = ''
$scope.closeGenerated = function() {
$scope.showGenerated = false
UserService.getAccessTokens().push($scope.newToken)
$scope.newToken = null
updateTokens()
}

$scope.$on('user.keys.accessTokens.generated', function(event, token) {
$scope.showGenerated = true
$scope.accessTokenId = token.tokenId
$scope.newToken = token
$scope.showGenerated = true
})

$scope.$on('user.keys.accessTokens.updated', updateTokens)
Expand Down
12 changes: 6 additions & 6 deletions res/app/settings/keys/access-tokens/access-tokens.jade
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
.widget-content.padded

nothing-to-show(icon='fa-key', message='{{"No access tokens" | translate}}',
ng-if='!accessTokens.length && !showGenerate && !showGenerated')
ng-if='!accessTokenTitles.length && !showGenerate && !showGenerated')

generate-access-token(show-clipboard='true', show-generate='showGenerate')

Expand All @@ -24,17 +24,17 @@
span  
span(translate) Make sure to copy your access token now. You won't be able to see it again!
br
button.btn.pull-right.btn-primary.btn-sm(ng-click='tokenGenerated()')
button.btn.pull-right.btn-primary.btn-sm(ng-click='closeGenerated()')
i.fa.fa-check.fa-fw
textarea(readonly, rows='1', text-focus-select, ng-model='accessTokenId').form-control.token-id-textarea
textarea(readonly, rows='1', text-focus-select, ng-model='newToken.tokenId').form-control.token-id-textarea

ul.list-group.key-list
li.list-group-item(ng-repeat='token in accessTokens').animate-repeat
li.list-group-item(ng-repeat='title in accessTokenTitles').animate-repeat
a
i.fa.fa-key.fa-2x.fa-fw.key-list-icon
.key-list-details.selectable
.key-list-title(ng-bind='token.title')
.key-list-title(ng-bind='title')

button.btn.btn-xs.btn-danger-outline.pull-right.key-list-remove(ng-click='removeToken(token.title)')
button.btn.btn-xs.btn-danger-outline.pull-right.key-list-remove(ng-click='removeToken(title)')
i.fa.fa-trash-o
span(translate) Remove
1 change: 1 addition & 0 deletions res/app/settings/keys/access-tokens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ require('./access-tokens.css')

module.exports = angular.module('stf.settings.keys.access-tokens', [
require('stf/common-ui').name,
require('stf/tokens').name,
require('stf/tokens/generate-access-token').name
])
.run(["$templateCache", function ($templateCache) {
Expand Down

0 comments on commit 9cb2313

Please sign in to comment.