mirror of
https://github.com/openstf/stf
synced 2025-10-04 10:19:30 +02:00
Create seperate database table for AccessTokens to hide jwt token and tokenId from user
This commit is contained in:
parent
62413b3780
commit
9cb231391a
11 changed files with 97 additions and 71 deletions
|
@ -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
|
||||
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'
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
35
res/app/components/stf/tokens/access-token-service.js
Normal file
35
res/app/components/stf/tokens/access-token-service.js
Normal file
|
@ -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
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module.exports = angular.module('stf.tokens', [
|
||||
require('./generate-access-token').name,
|
||||
])
|
||||
.factory('AccessTokenService', require('./access-token-service'))
|
||||
|
|
|
@ -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 = []))
|
||||
}
|
||||
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue