settings api / login api

This commit is contained in:
Aleksander Barszczewski 2018-10-26 13:11:30 +02:00
parent d8dbe343bd
commit 817cf6fcf9
18 changed files with 234 additions and 3 deletions

View File

@ -1,4 +1,4 @@
FROM arm32v7/node:8
FROM arm32v7/node:9
WORKDIR /app
RUN npm --version
RUN npm install yarn

View File

@ -5,6 +5,34 @@ exports.up = async function (knex) {
table.timestamps(false, true)
table.text('password')
})
// settings
await knex.schema.createTable('settings', table => {
table.increments('id')
table.timestamps(false, true)
table.enum('miner_mode', ['eco', 'turbo', 'custom']).notNullable()
table.float('voltage').notNullable()
table.integer('frequency').notNullable()
table.integer('fan').notNullable()
table.text('connected_wifi')
table.boolean('left_sidebar_visibility').notNullable()
table.boolean('left_sidebar_extended').notNullable()
table.boolean('right_sidebar_visibility').notNullable()
table.enum('temperature_unit', ['f', 'c']).notNullable()
})
// default settings
await knex('settings').insert({
miner_mode: 'eco',
voltage: 0.5,
frequency: 450,
fan: -1,
connected_wifi: null,
left_sidebar_visibility: true,
left_sidebar_extended: true,
right_sidebar_visibility: false,
temperature_unit: 'f'
})
}
exports.down = async function (knex) {

View File

@ -0,0 +1,26 @@
module.exports.typeDefs = `
type AuthActions {
login (input: AuthLoginInput!): AuthLoginOutput!
}
input AuthLoginInput {
password: String!
}
type AuthLoginOutput {
result: AuthLoginResult
error: Error
}
type AuthLoginResult {
accessToken: String!
}
`
module.exports.resolvers = {
AuthActions: {
login (root, args, { dispatch }) {
return dispatch('api/auth/login', args.input)
}
}
}

View File

@ -13,6 +13,7 @@ module.exports.typeDefs = `
}
type McuStats {
timestamp: String!
hostname: String,
operatingSystem: String
uptime: String

View File

@ -0,0 +1,28 @@
module.exports.typeDefs = `
type Query {
Settings: SettingsActions
}
enum MinerMode { eco, turbo, custom }
enum TemperatureUnit { f, c }
type Settings {
minerMode: MinerMode!
voltage: Float!,
frequency: Int!,
fan: Int!
connectedWifi: String
leftSidebarVisibility: Boolean!
leftSidebarExtended: Boolean!
rightSidebarVisibility: Boolean!
temperatureUnit: TemperatureUnit!
}
`
module.exports.resolvers = {
Query: {
Settings () {
return {}
}
}
}

View File

@ -0,0 +1,13 @@
module.exports.typeDefs = `
type SettingsActions {
read: SettingsUpdateOutput!
}
`
module.exports.resolvers = {
SettingsActions: {
read (root, args, { dispatch }) {
return dispatch('api/settings/read', args.input)
}
}
}

View File

@ -0,0 +1,34 @@
module.exports.typeDefs = `
type SettingsActions {
update (input: SettingsUpdateInput!): SettingsUpdateOutput!
}
input SettingsUpdateInput {
minerMode: MinerMode
voltage: Float,
frequency: Int,
fan: Int
connectedWifi: String
leftSidebarVisibility: Boolean
leftSidebarExtended: Boolean
rightSidebarVisibility: Boolean
temperatureUnit: TemperatureUnit
}
type SettingsUpdateOutput {
result: SettingsUpdateResult
error: Error
}
type SettingsUpdateResult {
settings: Settings!
}
`
module.exports.resolvers = {
SettingsActions: {
update (root, args, { dispatch }) {
return dispatch('api/settings/update', args.input)
}
}
}

View File

@ -0,0 +1,18 @@
module.exports = ({ define }) => {
define('login', async ({ password }, { knex, errors, utils }) => {
// TODO transaction
const [ setup ] = await knex('setup').select('*').limit(1)
if (!setup) {
throw new errors.AuthorizationError('Setup not finished')
}
const isPasswordValid = await utils.auth.comparePassword(password, setup.password)
if (!isPasswordValid) {
throw new errors.AuthenticationError('Invalid password').addReason({
path: 'password',
message: 'Invalid password'
})
}
const { accessToken } = utils.auth.generateAccessToken()
return { accessToken }
})
}

View File

@ -6,7 +6,7 @@ module.exports = ({ define }) => {
throw new errors.AuthorizationError('Setup already done')
}
await knex('setup').insert({
password: utils.hashPassword(password)
password: await utils.auth.hashPassword(password)
})
})
}

View File

@ -3,5 +3,7 @@ const { exec } = require('child_process')
module.exports = ({ define }) => {
define('reboot', async (payload, { knex, errors, utils }) => {
exec('shutdown -r now')
}, {
auth: true
})
}

View File

@ -3,5 +3,7 @@ const { exec } = require('child_process')
module.exports = ({ define }) => {
define('shutdown', async (payload, { knex, errors, utils }) => {
exec('shutdown now')
}, {
auth: true
})
}

View File

@ -4,7 +4,10 @@ const { exec } = require('child_process')
module.exports = ({ define }) => {
define('stats', async (payload, { knex, errors, utils }) => {
const stats = await getOsStats()
stats.timestamp = new Date().toISOString()
return { stats }
}, {
auth: true
})
}

View File

@ -0,0 +1,16 @@
module.exports = ({ define }) => {
define('read', async (payload, { knex, errors, utils }) => {
const [ settings ] = await knex('settings').select([
'miner_mode as minerMode',
'voltage',
'frequency',
'fan',
'connected_wifi as connectedWifi',
'left_sidebar_visibility as leftSidebarVisibility',
'left_sidebar_extended as leftSidebarExtended',
'right_sidebar_visibility as rightSidebarVisibility',
'temperature_unit as temperatureUnit',
]).limit(1)
return settings
})
}

View File

@ -0,0 +1,23 @@
const updateFields = {
minerMode: 'miner_mode',
voltage: 'voltage',
frequency: 'frequency',
fan: 'fan',
connectedWifi: 'connected_wifi',
leftSidebarVisibility: 'left_sidebar_visibility',
leftSidebarExtended: 'left_sidebar_extended',
rightSidebarVisibility: 'right_sidebar_visibility',
temperatureUnit: 'temperature_unit'
}
module.exports = ({ define }) => {
define('update', async (update = {}, { knex, errors, utils }) => {
const updateData = {}
Object.keys(update).forEach(key => {
if (updateFields[key]) {
updateData[updateFields[key]] = update[key]
}
})
await knex('settings').update(updateData)
})
}

View File

@ -0,0 +1,11 @@
module.exports = ({ define }) => {
define('read', async (payload, { dispatch, errors, utils }) => {
const settings = await dispatch('api/settings/collection/read')
console.log(settings)
return {
settings
}
}, {
auth: true
})
}

View File

@ -0,0 +1,11 @@
module.exports = ({ define }) => {
define('update', async (settings, { dispatch, errors, utils }) => {
await dispatch('api/settings/collection/update', settings)
const newSettings = await dispatch('api/settings/collection/read')
return {
settings: newSettings
}
}, {
auth: true
})
}

3
src/test.js Normal file
View File

@ -0,0 +1,3 @@
const store = require('./store')
store.dispatch('api/auth/login', { password: 'abcdef' })

View File

@ -1,4 +1,6 @@
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('config')
module.exports.auth = {
hashPassword (password) {
@ -10,5 +12,15 @@ module.exports.auth = {
return false
}
return bcrypt.compare(password, hash)
},
generateAccessToken () {
const accessToken = jwt.sign({}, config.get('server.secret'), {
subject: 'apollouser',
audience: 'auth'
})
return {
accessToken
}
},
}