fe66575ffe
Login: add an in-memory per-IP throttle (8 failed attempts -> 15-min lockout, 429 + Retry-After), raise the change-password minimum to 8 with a 72-char cap, and apply the same minimum on the StartOS Set Login Password action. Records: add a record_floor column for manually-pinned bests plus recomputeRecord(); the live record is now the direction-aware best of the best logged value and the floor, recomputed on entry edit/delete so it can drop again (never below the floor). Settings exposes the floor as an override and shows the live best as a placeholder. Bump package 0.1.6:0 -> 0.1.7:0 and the service-worker cache to v7.
46 lines
1.1 KiB
TypeScript
46 lines
1.1 KiB
TypeScript
import { store } from '../fileModels/store'
|
|
import { i18n } from '../i18n'
|
|
import { sdk } from '../sdk'
|
|
|
|
const { InputSpec, Value } = sdk
|
|
|
|
const inputSpec = InputSpec.of({
|
|
password: Value.text({
|
|
name: i18n('Password'),
|
|
description: i18n(
|
|
'The password Gunner types on the login screen (at least 8 characters)',
|
|
),
|
|
required: true,
|
|
default: null,
|
|
masked: true,
|
|
minLength: 8,
|
|
maxLength: 72,
|
|
}),
|
|
})
|
|
|
|
export const setPassword = sdk.Action.withInput(
|
|
'set-password',
|
|
|
|
async ({ effects }) => ({
|
|
name: i18n('Set Login Password'),
|
|
description: i18n('Set the password Gunner uses to log in to Premier Gunner'),
|
|
warning: null,
|
|
allowedStatuses: 'any',
|
|
group: null,
|
|
visibility: 'enabled',
|
|
}),
|
|
|
|
inputSpec,
|
|
|
|
async ({ effects }) => {
|
|
const password = await store.read((s) => s.password).const(effects)
|
|
return { password: password ?? undefined }
|
|
},
|
|
|
|
async ({ effects, input }) => {
|
|
await store.merge(effects, { password: input.password })
|
|
},
|
|
)
|
|
|
|
export const actions = sdk.Actions.of().addAction(setPassword)
|