mirror of
https://github.com/Retropex/apolloapi-v2.git
synced 2025-05-29 21:42:30 +02:00
settings api / login api
This commit is contained in:
parent
d8dbe343bd
commit
817cf6fcf9
@ -1,4 +1,4 @@
|
|||||||
FROM arm32v7/node:8
|
FROM arm32v7/node:9
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN npm --version
|
RUN npm --version
|
||||||
RUN npm install yarn
|
RUN npm install yarn
|
||||||
|
@ -5,6 +5,34 @@ exports.up = async function (knex) {
|
|||||||
table.timestamps(false, true)
|
table.timestamps(false, true)
|
||||||
table.text('password')
|
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) {
|
exports.down = async function (knex) {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ module.exports.typeDefs = `
|
|||||||
}
|
}
|
||||||
|
|
||||||
type McuStats {
|
type McuStats {
|
||||||
|
timestamp: String!
|
||||||
hostname: String,
|
hostname: String,
|
||||||
operatingSystem: String
|
operatingSystem: String
|
||||||
uptime: String
|
uptime: String
|
||||||
|
28
src/graphql/graphqlModules/Settings/Settings.js
Normal file
28
src/graphql/graphqlModules/Settings/Settings.js
Normal 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 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/graphql/graphqlModules/Settings/SettingsRead.js
Normal file
13
src/graphql/graphqlModules/Settings/SettingsRead.js
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
src/graphql/graphqlModules/Settings/SettingsUpdate.js
Normal file
34
src/graphql/graphqlModules/Settings/SettingsUpdate.js
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/store/api/auth/authLogin.js
Normal file
18
src/store/api/auth/authLogin.js
Normal 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 }
|
||||||
|
})
|
||||||
|
}
|
@ -6,7 +6,7 @@ module.exports = ({ define }) => {
|
|||||||
throw new errors.AuthorizationError('Setup already done')
|
throw new errors.AuthorizationError('Setup already done')
|
||||||
}
|
}
|
||||||
await knex('setup').insert({
|
await knex('setup').insert({
|
||||||
password: utils.hashPassword(password)
|
password: await utils.auth.hashPassword(password)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,7 @@ const { exec } = require('child_process')
|
|||||||
module.exports = ({ define }) => {
|
module.exports = ({ define }) => {
|
||||||
define('reboot', async (payload, { knex, errors, utils }) => {
|
define('reboot', async (payload, { knex, errors, utils }) => {
|
||||||
exec('shutdown -r now')
|
exec('shutdown -r now')
|
||||||
|
}, {
|
||||||
|
auth: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,7 @@ const { exec } = require('child_process')
|
|||||||
module.exports = ({ define }) => {
|
module.exports = ({ define }) => {
|
||||||
define('shutdown', async (payload, { knex, errors, utils }) => {
|
define('shutdown', async (payload, { knex, errors, utils }) => {
|
||||||
exec('shutdown now')
|
exec('shutdown now')
|
||||||
|
}, {
|
||||||
|
auth: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,10 @@ const { exec } = require('child_process')
|
|||||||
module.exports = ({ define }) => {
|
module.exports = ({ define }) => {
|
||||||
define('stats', async (payload, { knex, errors, utils }) => {
|
define('stats', async (payload, { knex, errors, utils }) => {
|
||||||
const stats = await getOsStats()
|
const stats = await getOsStats()
|
||||||
|
stats.timestamp = new Date().toISOString()
|
||||||
return { stats }
|
return { stats }
|
||||||
|
}, {
|
||||||
|
auth: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/store/api/settings/collection/settingsRead.js
Normal file
16
src/store/api/settings/collection/settingsRead.js
Normal 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
|
||||||
|
})
|
||||||
|
}
|
23
src/store/api/settings/collection/settingsUpdate.js
Normal file
23
src/store/api/settings/collection/settingsUpdate.js
Normal 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)
|
||||||
|
})
|
||||||
|
}
|
11
src/store/api/settings/settingsRead.js
Normal file
11
src/store/api/settings/settingsRead.js
Normal 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
|
||||||
|
})
|
||||||
|
}
|
11
src/store/api/settings/settingsUpdate.js
Normal file
11
src/store/api/settings/settingsUpdate.js
Normal 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
3
src/test.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
const store = require('./store')
|
||||||
|
|
||||||
|
store.dispatch('api/auth/login', { password: 'abcdef' })
|
14
src/utils.js
14
src/utils.js
@ -1,4 +1,6 @@
|
|||||||
const bcrypt = require('bcryptjs')
|
const bcrypt = require('bcryptjs')
|
||||||
|
const jwt = require('jsonwebtoken')
|
||||||
|
const config = require('config')
|
||||||
|
|
||||||
module.exports.auth = {
|
module.exports.auth = {
|
||||||
hashPassword (password) {
|
hashPassword (password) {
|
||||||
@ -10,5 +12,15 @@ module.exports.auth = {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return bcrypt.compare(password, hash)
|
return bcrypt.compare(password, hash)
|
||||||
}
|
},
|
||||||
|
|
||||||
|
generateAccessToken () {
|
||||||
|
const accessToken = jwt.sign({}, config.get('server.secret'), {
|
||||||
|
subject: 'apollouser',
|
||||||
|
audience: 'auth'
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
accessToken
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user