e3f80af47d
Build & Push / Pipeline Tests (push) Failing after 1m26s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 50s
Test / API Unit Tests (push) Failing after 1m6s
Test / Homepage Unit Tests (push) Successful in 48s
Test / Carplace Unit Tests (push) Successful in 44s
Test / Admin Unit Tests (push) Successful in 40s
Test / Dashboard Unit Tests (push) Successful in 41s
Test / API Integration Tests (push) Successful in 1m6s
118 lines
4.0 KiB
TypeScript
118 lines
4.0 KiB
TypeScript
import { Router } from 'express'
|
|
import { requireCompanyAuth } from '../../middleware/requireCompanyAuth'
|
|
import { parseBody } from '../../http/validate'
|
|
import { ok } from '../../http/respond'
|
|
import { setSessionCookie, clearSessionCookie } from '../../security/sessionCookies'
|
|
import { getEmployeeMenu } from '../menu/menu.service'
|
|
import {
|
|
employeeForgotPasswordSchema,
|
|
employee2faVerifySchema,
|
|
employeeLanguageSchema,
|
|
employeeLoginSchema,
|
|
employeeResetPasswordSchema,
|
|
} from './auth.employee.schemas'
|
|
import * as service from './auth.employee.service'
|
|
|
|
const router = Router()
|
|
|
|
router.get('/me', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
ok(res, await service.getMe(req.employee.id))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.get('/menu', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
ok(res, await getEmployeeMenu(req.employee.id))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/login', async (req, res, next) => {
|
|
try {
|
|
const body = parseBody(employeeLoginSchema, req)
|
|
const result = await service.login(body)
|
|
if ('twoFactorRequired' in result) {
|
|
return res.status(401).json({ error: 'two_factor_required', message: '2FA code required', method: result.method, statusCode: 401 })
|
|
}
|
|
if ('token' in result) {
|
|
clearSessionCookie(res, 'admin')
|
|
setSessionCookie(res, 'employee', String(result.token), 8 * 60 * 60 * 1000)
|
|
}
|
|
ok(res, result)
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/logout', (_req, res) => {
|
|
clearSessionCookie(res, 'employee')
|
|
ok(res, { success: true })
|
|
})
|
|
|
|
router.post('/2fa/setup', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
ok(res, await service.setupTotp(req.employee.id))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/2fa/verify', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
const { code } = parseBody(employee2faVerifySchema, req)
|
|
const result = await service.verifyTotp(req.employee.id, code)
|
|
if (!result) return res.status(400).json({ error: 'invalid_code', message: 'Invalid 2FA code', statusCode: 400 })
|
|
if ('token' in result) setSessionCookie(res, 'employee', String(result.token), 8 * 60 * 60 * 1000)
|
|
ok(res, result)
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/2fa/email/setup', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
ok(res, await service.setupEmail2fa(req.employee.id))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/2fa/email/verify', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
const { code } = parseBody(employee2faVerifySchema, req)
|
|
const result = await service.verifyEmail2fa(req.employee.id, code)
|
|
if (!result) return res.status(400).json({ error: 'invalid_code', message: 'Invalid email verification code', statusCode: 400 })
|
|
if ('token' in result) setSessionCookie(res, 'employee', String(result.token), 8 * 60 * 60 * 1000)
|
|
ok(res, result)
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/forgot-password', async (req, res, next) => {
|
|
try {
|
|
const { email } = parseBody(employeeForgotPasswordSchema, req)
|
|
ok(res, await service.forgotPassword(email))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.patch('/me/language', requireCompanyAuth, async (req, res, next) => {
|
|
try {
|
|
const { language } = parseBody(employeeLanguageSchema, req)
|
|
ok(res, await service.updateLanguage(req.employee.id, language))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/reset-password', async (req, res, next) => {
|
|
try {
|
|
const { token, password } = parseBody(employeeResetPasswordSchema, req)
|
|
ok(res, await service.resetPassword(token, password))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/verify-email', async (req, res, next) => {
|
|
try {
|
|
const { token } = parseBody(employeeResetPasswordSchema.pick({ token: true }), req)
|
|
ok(res, await service.verifyEmail(token))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/resend-verification', async (req, res, next) => {
|
|
try {
|
|
const { email } = parseBody(employeeForgotPasswordSchema, req)
|
|
ok(res, await service.resendVerification(email))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
export default router
|