Decouple storage, both secure and general.

This commit is contained in:
joshaber 2016-05-31 15:07:53 -04:00
parent ccaf0aa41f
commit 3928ddc72d
5 changed files with 42 additions and 30 deletions

View file

@ -1,5 +1,4 @@
import {shell} from 'electron' import {shell} from 'electron'
import * as keytar from 'keytar'
import guid from './lib/guid' import guid from './lib/guid'
import User from './user' import User from './user'
@ -49,16 +48,6 @@ export function askUserToAuth(endpoint: string) {
shell.openExternal(getOAuthURL(authState)) shell.openExternal(getOAuthURL(authState))
} }
export function getToken(login: string, endpoint: string): string { export function getKeyForUser(user: User): string {
const serviceName = getServiceNameForUser(new User(login, endpoint, ''))
return keytar.getPassword(serviceName, login)
}
export function setToken(user: User, token: string) {
const serviceName = getServiceNameForUser(user)
keytar.addPassword(serviceName, user.getLogin(), token)
}
function getServiceNameForUser(user: User): string {
return `GitHub ${user.getEndpoint()}` return `GitHub ${user.getEndpoint()}`
} }

View file

@ -8,6 +8,7 @@ import {requestToken, getDotComEndpoint} from './auth'
import {URLActionType, OAuthAction} from './lib/parse-url' import {URLActionType, OAuthAction} from './lib/parse-url'
import UsersStore from './users-store' import UsersStore from './users-store'
import User from './user' import User from './user'
import tokenStore from './token-store'
const Octokat = require('octokat') const Octokat = require('octokat')
@ -27,8 +28,8 @@ const style = {
paddingTop: process.platform === 'darwin' ? 20 : 0 paddingTop: process.platform === 'darwin' ? 20 : 0
} }
const usersStore = new UsersStore() const usersStore = new UsersStore(localStorage, tokenStore)
usersStore.loadFromDisk() usersStore.loadFromStore()
ReactDOM.render(<App style={style} usersStore={usersStore}/>, document.getElementById('content')) ReactDOM.render(<App style={style} usersStore={usersStore}/>, document.getElementById('content'))

9
src/stores.ts Normal file
View file

@ -0,0 +1,9 @@
export interface SecureStore {
setItem(key: string, login: string, value: string): void
getItem(key: string, login: string): string
}
export interface DataStore {
setItem(key: string, value: string): void
getItem(key: string): string
}

11
src/token-store.ts Normal file
View file

@ -0,0 +1,11 @@
import * as keytar from 'keytar'
export default {
setItem: function (key: string, login: string, value: string) {
keytar.addPassword(key, login, value)
},
getItem: function (key: string, login: string): string {
return keytar.getPassword(key, login)
}
}

View file

@ -1,18 +1,21 @@
import {Emitter, Disposable} from 'event-kit' import {Emitter, Disposable} from 'event-kit'
import {setToken, getToken} from './auth' import {DataStore, SecureStore} from './stores'
import {getKeyForUser} from './auth'
import User from './user' import User from './user'
export default class UsersStore { export default class UsersStore {
private dataStore: DataStore
private secureStore: SecureStore
private emitter: Emitter private emitter: Emitter
private users: User[] private users: User[]
private persisted: boolean public constructor(dataStore: DataStore, secureStore: SecureStore) {
this.dataStore = dataStore
public constructor() { this.secureStore = secureStore
this.emitter = new Emitter() this.emitter = new Emitter()
this.users = [] this.users = []
this.persisted = false
} }
public onUsersChanged(fn: (users: User[]) => void): Disposable { public onUsersChanged(fn: (users: User[]) => void): Disposable {
@ -28,33 +31,32 @@ export default class UsersStore {
} }
public addUser(user: User) { public addUser(user: User) {
setToken(user, user.getToken()) this.secureStore.setItem(getKeyForUser(user), user.getLogin(), user.getToken())
this.users.push(user) this.users.push(user)
this.usersDidChange() this.usersDidChange()
if (this.persisted) { this.save()
this.saveToDisk()
}
} }
public loadFromDisk() { public loadFromStore() {
this.persisted = true const raw = this.dataStore.getItem('users')
const raw = localStorage.getItem('users')
if (!raw || !raw.length) { if (!raw || !raw.length) {
return return
} }
const rawUsers: any[] = JSON.parse(raw) const rawUsers: any[] = JSON.parse(raw)
const usersWithTokens = rawUsers.map(user => new User(user.login, user.endpoint, getToken(user.login, user.endpoint))) const usersWithTokens = rawUsers.map(user => {
const userWithoutToken = new User(user.login, user.endpoint, '')
return userWithoutToken.userWithToken(this.secureStore.getItem(getKeyForUser(userWithoutToken), user.login))
})
this.users = usersWithTokens this.users = usersWithTokens
this.usersDidChange() this.usersDidChange()
} }
private saveToDisk() { private save() {
const usersWithoutTokens = this.users.map(user => user.userWithToken('')) const usersWithoutTokens = this.users.map(user => user.userWithToken(''))
localStorage.setItem('users', JSON.stringify(usersWithoutTokens)) this.dataStore.setItem('users', JSON.stringify(usersWithoutTokens))
} }
} }