Public Access
feat: enhance setup process with SMTP configuration and token generation
fix: require authentication for certain routes and improve exam data handling chore: update .gitignore to include additional database files
This commit is contained in:
1 parent
ca9c646b65
commit
83bb412b35
8 files changed
+115
-28
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { Router } from 'express'
|
||||
import rateLimit from 'express-rate-limit'
|
||||
import { validateBody } from '../middleware/validate.js'
|
||||
import { requireAuth } from '../middleware/auth.js'
|
||||
import { asyncHandler } from '../utils/asyncHandler.js'
|
||||
import * as authService from '../services/authService.js'
|
||||
import * as userRepo from '../repositories/userRepo.js'
|
||||
@@ -51,6 +52,7 @@ router.post(
|
||||
// GET /api/auth/me
|
||||
router.get(
|
||||
'/me',
|
||||
requireAuth,
|
||||
asyncHandler(async (req: Request, res) => {
|
||||
const user = authService.getMe(req.user!.userId)
|
||||
res.json(user)
|
||||
@@ -60,6 +62,7 @@ router.get(
|
||||
// PUT /api/auth/me
|
||||
router.put(
|
||||
'/me',
|
||||
requireAuth,
|
||||
validateBody(updateProfileSchema),
|
||||
asyncHandler(async (req: Request, res) => {
|
||||
const user = await authService.updateProfile(req.user!.userId, req.body)
|
||||
@@ -70,6 +73,7 @@ router.put(
|
||||
// POST /api/auth/change-password
|
||||
router.post(
|
||||
'/change-password',
|
||||
requireAuth,
|
||||
validateBody(changePasswordSchema),
|
||||
asyncHandler(async (req: Request, res) => {
|
||||
await authService.changePassword(req.user!.userId, req.body)
|
||||
@@ -112,6 +116,7 @@ router.post(
|
||||
// DELETE /api/auth/me
|
||||
router.delete(
|
||||
'/me',
|
||||
requireAuth,
|
||||
asyncHandler(async (req: Request, res) => {
|
||||
authService.deleteUserAccount(req.user!.userId)
|
||||
res.json({ success: true })
|
||||
|
||||
@@ -31,7 +31,8 @@ router.get(
|
||||
if (!exam) {
|
||||
throw new AppError(404, 'Exam not found')
|
||||
}
|
||||
res.json(exam)
|
||||
const parsedExam = JSON.parse(exam.exam_json)
|
||||
res.json({ ...parsedExam, id: exam.id })
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
+46
-10
@@ -6,7 +6,7 @@ import { AppError } from '../middleware/error.js'
|
||||
import * as userRepo from '../repositories/userRepo.js'
|
||||
import * as settingsRepo from '../repositories/settingsRepo.js'
|
||||
import { setupSchema } from '../validators/setupSchemas.js'
|
||||
import { sendTestEmail } from '../utils/email.js'
|
||||
import { signToken } from '../utils/tokens.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
@@ -41,11 +41,24 @@ router.post(
|
||||
throw new AppError(400, 'Users already exist')
|
||||
}
|
||||
|
||||
const { email, password, displayName, siteTitle, language } = req.body
|
||||
const {
|
||||
email,
|
||||
password,
|
||||
displayName,
|
||||
siteTitle,
|
||||
language,
|
||||
smtpHost,
|
||||
smtpPort,
|
||||
smtpUser,
|
||||
smtpPass,
|
||||
smtpFrom,
|
||||
smtpSecure,
|
||||
appUrl,
|
||||
} = req.body
|
||||
|
||||
const passwordHash = await bcrypt.hash(password, SALT_ROUNDS)
|
||||
|
||||
userRepo.createUser({
|
||||
const { id } = userRepo.createUser({
|
||||
email,
|
||||
passwordHash,
|
||||
displayName,
|
||||
@@ -53,16 +66,39 @@ router.post(
|
||||
emailVerified: 1,
|
||||
})
|
||||
|
||||
settingsRepo.setSettingsBatch([
|
||||
['site_title', siteTitle.trim()],
|
||||
['site_language', language],
|
||||
const settings: Array<[string, string]> = [
|
||||
['site_title', siteTitle?.trim() || 'BrainWave'],
|
||||
['site_language', language || 'en'],
|
||||
['maintenance_mode', 'false'],
|
||||
])
|
||||
]
|
||||
|
||||
// Send a test email to the new admin
|
||||
sendTestEmail(email).catch(() => {})
|
||||
if (smtpHost !== undefined) settings.push(['smtp_host', smtpHost])
|
||||
if (smtpPort !== undefined) settings.push(['smtp_port', smtpPort])
|
||||
if (smtpUser !== undefined) settings.push(['smtp_user', smtpUser])
|
||||
if (smtpPass !== undefined) settings.push(['smtp_pass', smtpPass])
|
||||
if (smtpFrom !== undefined) settings.push(['smtp_from', smtpFrom])
|
||||
if (smtpSecure !== undefined) settings.push(['smtp_secure', smtpSecure])
|
||||
if (appUrl !== undefined) settings.push(['app_url', appUrl])
|
||||
|
||||
res.status(201).json({ success: true })
|
||||
settingsRepo.setSettingsBatch(settings)
|
||||
|
||||
const token = signToken({
|
||||
userId: id,
|
||||
email,
|
||||
displayName,
|
||||
role: 'admin',
|
||||
})
|
||||
|
||||
res.status(201).json({
|
||||
message: 'Setup completed successfully',
|
||||
token,
|
||||
user: {
|
||||
id,
|
||||
email,
|
||||
displayName,
|
||||
role: 'admin',
|
||||
},
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
@@ -4,11 +4,19 @@ export const setupSchema = z.object({
|
||||
email: z.string().email().max(255),
|
||||
password: z.string().min(8, 'Password must be at least 8 characters'),
|
||||
displayName: z.string().min(1, 'Display name is required').max(100),
|
||||
siteTitle: z.string().min(1, 'Site title is required').max(255),
|
||||
language: z.enum(['en', 'nl']),
|
||||
siteTitle: z.string().min(1, 'Site title is required').max(255).optional(),
|
||||
language: z.enum(['en', 'nl']).optional(),
|
||||
smtpHost: z.string().max(255).optional(),
|
||||
smtpPort: z.string().max(10).optional(),
|
||||
smtpUser: z.string().max(255).optional(),
|
||||
smtpPass: z.string().max(255).optional(),
|
||||
smtpFrom: z.string().max(255).optional(),
|
||||
smtpSecure: z.enum(['auto', 'true', 'false']).optional(),
|
||||
appUrl: z.string().max(255).optional(),
|
||||
})
|
||||
|
||||
export const setupStatusSchema = z.object({
|
||||
email: z.string().email().max(255).optional(),
|
||||
|
||||
password: z.string().min(8).optional(),
|
||||
})
|
||||
Reference in new issue
Block a user