fix: atomic setup transaction, prune devDependencies from runtime image
This commit is contained in:
@@ -13,6 +13,7 @@ RUN npm ci
|
|||||||
COPY tsconfig.json vitest.config.ts ./
|
COPY tsconfig.json vitest.config.ts ./
|
||||||
COPY server ./server
|
COPY server ./server
|
||||||
RUN npm run build:server && npm test
|
RUN npm run build:server && npm test
|
||||||
|
RUN npm prune --omit=dev
|
||||||
|
|
||||||
# ---- runtime stage ----
|
# ---- runtime stage ----
|
||||||
FROM node:22-slim
|
FROM node:22-slim
|
||||||
|
|||||||
@@ -80,18 +80,25 @@ export async function registerAuthRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
const { username, password } = (request.body ?? {}) as { username?: string; password?: string }
|
const { username, password } = (request.body ?? {}) as { username?: string; password?: string }
|
||||||
const invalid = validateCredentials(username, password)
|
const invalid = validateCredentials(username, password)
|
||||||
if (invalid) return reply.code(400).send({ error: 'invalid_input', detail: invalid })
|
if (invalid) return reply.code(400).send({ error: 'invalid_input', detail: invalid })
|
||||||
let user
|
const passwordHash = await hashPassword(password as string)
|
||||||
try {
|
|
||||||
user = createUser(request.server.db, username as string, await hashPassword(password as string), true)
|
const insertSetup = request.server.db.transaction((): 'taken' | { user: UserRow } => {
|
||||||
} catch (err: any) {
|
const current = (
|
||||||
if (String(err.message).includes('UNIQUE constraint failed')) {
|
request.server.db.prepare('SELECT COUNT(*) AS n FROM users').get() as { n: number }
|
||||||
return reply.code(403).send({ error: 'setup_already_done' })
|
).n
|
||||||
}
|
if (current > 0) return 'taken'
|
||||||
throw err
|
const user = createUser(request.server.db, username as string, passwordHash, true)
|
||||||
}
|
|
||||||
request.server.db.prepare('INSERT INTO settings (user_id) VALUES (?)').run(user.id)
|
request.server.db.prepare('INSERT INTO settings (user_id) VALUES (?)').run(user.id)
|
||||||
const token = createSession(request.server.db, user.id)
|
return { user }
|
||||||
return reply.setCookie(COOKIE_NAME, token, cookieOpts()).code(200).send({ user: toPublicUser(user) })
|
})
|
||||||
|
const result = insertSetup.immediate()
|
||||||
|
if (result === 'taken') return reply.code(403).send({ error: 'setup_already_done' })
|
||||||
|
|
||||||
|
const token = createSession(request.server.db, result.user.id)
|
||||||
|
return reply
|
||||||
|
.setCookie(COOKIE_NAME, token, cookieOpts())
|
||||||
|
.code(200)
|
||||||
|
.send({ user: toPublicUser(result.user) })
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post('/api/login', async (request, reply) => {
|
app.post('/api/login', async (request, reply) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user