mirror of
https://github.com/openstf/stf
synced 2025-10-04 18:29:17 +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) {
|
dbapi.saveUserAccessToken = function(email, token) {
|
||||||
return db.run(r.table('users').get(email).update({
|
return db.run(r.table('accessTokens').insert({
|
||||||
accessTokens: r.row('accessTokens').default([]).append({
|
email: email
|
||||||
title: token.title
|
, id: token.id
|
||||||
, tokenId: token.tokenId
|
, title: token.title
|
||||||
, jwt: token.jwt
|
, jwt: token.jwt
|
||||||
})
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
dbapi.removeUserAccessToken = function(email, title) {
|
dbapi.removeUserAccessToken = function(email, title) {
|
||||||
return db.run(r.table('users').get(email).update({
|
return db.run(r.table('accessTokens').getAll(email, {
|
||||||
accessTokens: r.row('accessTokens').default([]).filter(function(token) {
|
index: 'email'
|
||||||
return token('title').ne(title)
|
}).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) {
|
indexFunction: function(user) {
|
||||||
return user('adbKeys')('fingerprint')
|
return user('adbKeys')('fingerprint')
|
||||||
}
|
}
|
||||||
, accessTokens: {
|
|
||||||
indexFunction: function(user) {
|
|
||||||
return user('accessTokens')('tokenId')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
, options: {
|
, options: {
|
||||||
multi: true
|
multi: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
, accessTokens: {
|
||||||
|
primaryKey: 'id'
|
||||||
|
, indexes: {
|
||||||
|
email: null
|
||||||
|
}
|
||||||
|
}
|
||||||
, vncauth: {
|
, vncauth: {
|
||||||
primaryKey: 'password'
|
primaryKey: 'password'
|
||||||
, indexes: {
|
, 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)
|
server.listen(options.port)
|
||||||
log.info('Listening on port %d', options.port)
|
log.info('Listening on port %d', options.port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,14 +352,13 @@ module.exports = function(options) {
|
||||||
|
|
||||||
return dbapi.saveUserAccessToken(user.email, {
|
return dbapi.saveUserAccessToken(user.email, {
|
||||||
title: title
|
title: title
|
||||||
, tokenId: tokenId
|
, id: tokenId
|
||||||
, jwt: jwt
|
, jwt: jwt
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
socket.emit('user.keys.accessToken.generated', {
|
socket.emit('user.keys.accessToken.generated', {
|
||||||
title: title
|
title: title
|
||||||
, tokenId: tokenId
|
, 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,
|
replace: true,
|
||||||
scope: {
|
scope: {
|
||||||
showGenerate: '=',
|
showGenerate: '=',
|
||||||
showClipboard: '=',
|
|
||||||
},
|
},
|
||||||
template: require('./generate-access-token.jade'),
|
template: require('./generate-access-token.jade'),
|
||||||
controller: function($scope, UserService) {
|
controller: function($scope, AccessTokenService) {
|
||||||
$scope.generateForm = {
|
$scope.generateForm = {
|
||||||
title: ''
|
title: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.generateToken = function () {
|
$scope.generateToken = function () {
|
||||||
UserService.generateAccessToken($scope.generateForm.title)
|
AccessTokenService.generateAccessToken($scope.generateForm.title)
|
||||||
$scope.closeGenerateToken()
|
$scope.closeGenerateToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
module.exports = angular.module('stf.tokens', [
|
module.exports = angular.module('stf.tokens', [
|
||||||
require('./generate-access-token').name,
|
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
|
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() {
|
UserService.getAdbKeys = function() {
|
||||||
return (user.adbKeys || (user.adbKeys = []))
|
return (user.adbKeys || (user.adbKeys = []))
|
||||||
}
|
}
|
||||||
|
@ -40,26 +24,6 @@ module.exports = function UserServiceFactory(
|
||||||
socket.emit('user.keys.adb.remove', key)
|
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) {
|
socket.on('user.keys.adb.added', function(key) {
|
||||||
UserService.getAdbKeys().push(key)
|
UserService.getAdbKeys().push(key)
|
||||||
$rootScope.$broadcast('user.keys.adb.updated', user.adbKeys)
|
$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
|
$scope.newToken = null
|
||||||
|
|
||||||
function updateTokens() {
|
function updateTokens() {
|
||||||
$scope.accessTokens = UserService.getAccessTokens()
|
AccessTokenService.getAccessTokens()
|
||||||
|
.success(function(response) {
|
||||||
|
$scope.accessTokenTitles = response.titles || []
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.removeToken = function (title) {
|
$scope.removeToken = function (title) {
|
||||||
UserService.removeAccessToken(title)
|
AccessTokenService.removeAccessToken(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.tokenGenerated = function() {
|
$scope.closeGenerated = function() {
|
||||||
$scope.accessToken = ''
|
|
||||||
$scope.showGenerated = false
|
$scope.showGenerated = false
|
||||||
UserService.getAccessTokens().push($scope.newToken)
|
|
||||||
$scope.newToken = null
|
$scope.newToken = null
|
||||||
updateTokens()
|
updateTokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.$on('user.keys.accessTokens.generated', function(event, token) {
|
$scope.$on('user.keys.accessTokens.generated', function(event, token) {
|
||||||
$scope.showGenerated = true
|
|
||||||
$scope.accessTokenId = token.tokenId
|
|
||||||
$scope.newToken = token
|
$scope.newToken = token
|
||||||
|
$scope.showGenerated = true
|
||||||
})
|
})
|
||||||
|
|
||||||
$scope.$on('user.keys.accessTokens.updated', updateTokens)
|
$scope.$on('user.keys.accessTokens.updated', updateTokens)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
.widget-content.padded
|
.widget-content.padded
|
||||||
|
|
||||||
nothing-to-show(icon='fa-key', message='{{"No access tokens" | translate}}',
|
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')
|
generate-access-token(show-clipboard='true', show-generate='showGenerate')
|
||||||
|
|
||||||
|
@ -24,17 +24,17 @@
|
||||||
span
|
span
|
||||||
span(translate) Make sure to copy your access token now. You won't be able to see it again!
|
span(translate) Make sure to copy your access token now. You won't be able to see it again!
|
||||||
br
|
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
|
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
|
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
|
a
|
||||||
i.fa.fa-key.fa-2x.fa-fw.key-list-icon
|
i.fa.fa-key.fa-2x.fa-fw.key-list-icon
|
||||||
.key-list-details.selectable
|
.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
|
i.fa.fa-trash-o
|
||||||
span(translate) Remove
|
span(translate) Remove
|
||||||
|
|
|
@ -2,6 +2,7 @@ require('./access-tokens.css')
|
||||||
|
|
||||||
module.exports = angular.module('stf.settings.keys.access-tokens', [
|
module.exports = angular.module('stf.settings.keys.access-tokens', [
|
||||||
require('stf/common-ui').name,
|
require('stf/common-ui').name,
|
||||||
|
require('stf/tokens').name,
|
||||||
require('stf/tokens/generate-access-token').name
|
require('stf/tokens/generate-access-token').name
|
||||||
])
|
])
|
||||||
.run(["$templateCache", function ($templateCache) {
|
.run(["$templateCache", function ($templateCache) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue