Skip to content

Commit

Permalink
HFS console commands
Browse files Browse the repository at this point in the history
  • Loading branch information
rejetto committed Jun 26, 2022
1 parent ef589f2 commit e70cb92
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 25 deletions.
15 changes: 5 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,12 @@ You won't find all previous features here (yet), but still we got:
2. click on `Assets`
3. **download** the right version for your computer
4. launch `hfs` file
5. the browser should automatically open on `localhost` address, so you can configure the rest
5. the browser should automatically open on `localhost` address, so you can configure the rest in the Admin panel.
- if a browser cannot be opened on the computer where you are installing HFS,
you should enter this command in HFS console: `create-admin <PASSWORD>`

If you access HFS via localhost, by default it won't require your to login.

### Cloud server?

If you are installing HFS on "another" machine, then step 5 may not be possible.
In this case you should run hfs with `--create-admin <PASSWORD>`.
This will both
- create an account with username `admin` with the provided password and Admin privilege (granting access to Admin panel).
- disable the unprotected access (no login) to Admin panel
If you access *Admin panel* via localhost, by default HFS **won't** require your to login.
If you don't like this behavior, disable it in the Admin panel or enter this console command `config localhost_admin false`.

### Other systems

Expand Down
8 changes: 4 additions & 4 deletions server/src/api.accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { changePasswordHelper, changeSrpHelper } from './api.helpers'
import { ApiError, ApiHandlers } from './apiMiddleware'
import {
Account,
accountCanLogin,
accountCanLoginAdmin,
accountHasPassword,
addAccount,
delAccount,
getAccount,
getAccounts, getCurrentUsername,
getFromAccount,
getAccounts,
getCurrentUsername,
setAccount
} from './perm'
import _ from 'lodash'
Expand All @@ -21,7 +21,7 @@ function prepareAccount(ac: Account | undefined) {
..._.omit(ac, ['password','hashed_password','srp']),
username: ac.username, // omit won't copy it because it's a hidden prop
hasPassword: accountHasPassword(ac),
adminActualAccess: accountCanLogin(ac) && getFromAccount(ac, a => a.admin),
adminActualAccess: accountCanLoginAdmin(ac),
}
}

Expand Down
55 changes: 55 additions & 0 deletions server/src/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { addAccount, getAccount, updateAccount } from './perm'
import { getConfigDefinition, setConfig } from './config'

console.log(`HINT: type "help" for help`)
require('readline').createInterface({ input: process.stdin }).on('line', (line: string) => {
const [command, ...params] = line.split(/ +/)
const fun = (commands as any)[command]
if (!fun)
return console.error("cannot understand entered command")
if (fun.length > params.length) {
const [args] = /\((.+)\)\s*\{/.exec(fun)!
return console.error("insufficient parameters, expected: " + args)
}
fun(...params).then(() =>console.log("command executed"),
(err: any) => {
if (typeof err === 'string')
console.error("command failed:", err)
else
throw err
})
})

const commands = {
async help() {
console.log("supported commands:", ...Object.keys(commands).map(x => '\n - ' + x))
},
async 'create-admin'(password: string, username='admin') {
if (getAccount(username))
throw `user ${username} already exists`
const acc = addAccount(username, { admin: true })
await updateAccount(acc!, acc => {
acc.password = password
})
},
async 'change-password'(user: string, password: string) {
const acc = getAccount(user)
if (!acc)
throw "user doesn't exist"
await updateAccount(acc!, acc => {
acc.password = password
})
},
async config(key: string, value: string) {
const conf = getConfigDefinition(key)
if (!conf)
throw "specified key doesn't exist"
let v: any = value
try { v = JSON.parse(v) }
catch {}
setConfig({ [key]: v })
},
async quit() {
process.exit(0)
}
}
4 changes: 4 additions & 0 deletions server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export function defineConfig<T>(k: string, defaultValue?: T) {
}
}

export function getConfigDefinition(k: string) {
return configProps[k]
}

const stack: any[] = []
function subscribeConfig<T>(k:string, cb: (v:T, was?:T)=>void) {
if (started) // initial event already passed, we'll make the first call
Expand Down
1 change: 1 addition & 0 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { pluginsMiddleware } from './plugins'
import { throttler } from './throttler'
import { headRequests, gzipper, sessions, serveGuiAndSharedFiles, someSecurity, prepareState } from './middlewares'
import './listen'
import './commands'
import { adminApis } from './adminApis'
import { defineConfig } from './config'
import { ok } from 'assert'
Expand Down
3 changes: 3 additions & 0 deletions server/src/listen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import open from 'open'
import { debounceAsync, onlyTruthy, wait } from './misc'
import { ADMIN_URI, DEV } from './const'
import findProcess from 'find-process'
import { anyAccountCanLoginAdmin } from './perm'

interface ServerExtra { name: string, error?: string, busy?: Promise<string> }
let httpSrv: http.Server & ServerExtra
Expand All @@ -33,6 +34,8 @@ portCfg.sub(async port => {
console.debug(String(e))
console.warn("cannot launch browser on this machine >PLEASE< open your browser and reach one of these (you may need a different address)",
...Object.values(getUrls()).flat().map(x => '\n - ' + x + ADMIN_URI))
if (! anyAccountCanLoginAdmin())
console.log(`HINT: you can enter command: create-admin YOUR_PASSWORD`)
})
})

Expand Down
19 changes: 8 additions & 11 deletions server/src/perm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import Koa from 'koa'
import { defineConfig, saveConfigAsap } from './config'
import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
import events from './events'
import { argv } from './const'
import { localhostAdmin } from './adminApis'

export interface Account {
username: string, // we'll have username in it, so we don't need to pass it separately
Expand Down Expand Up @@ -100,15 +98,6 @@ accountsConfig.sub(async v => {
}))
})

events.once('config ready', async () => {
const pwd = argv['create-admin']
if (!pwd) return
const acc = getAccount('admin') || addAccount('admin', { admin: true })
await updateAccount(acc!, acc => acc.password = pwd)
localhostAdmin.set(false)
console.log("account 'admin' created while unprotected admin access on localhost is now disabled")
})

function normalizeUsername(username: string) {
return username.toLocaleLowerCase()
}
Expand Down Expand Up @@ -195,3 +184,11 @@ export function accountHasPassword(account: Account) {
export function accountCanLogin(account: Account) {
return accountHasPassword(account)
}

export function accountCanLoginAdmin(account: Account) {
return accountCanLogin(account) && getFromAccount(account, a => a.admin)
}

export function anyAccountCanLoginAdmin() {
return Object.values(accounts).find(accountCanLoginAdmin)
}

0 comments on commit e70cb92

Please sign in to comment.