Introduce pic_sort_order to persist custom user ordering Replace data table with a custom draggable grid layout Add API endpoint to handle bulk order updates
92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
import type { H3Event } from 'h3'
|
|
|
|
import {
|
|
hasValidFullName,
|
|
isUserRole,
|
|
isValidPhoneNumber,
|
|
isValidUsername,
|
|
normalizeFullName,
|
|
normalizePhoneNumber,
|
|
normalizeUsername,
|
|
type UserRole
|
|
} from '~~/shared/auth'
|
|
|
|
import { assertBadRequest, getRequiredRouteParam, httpError } from './http'
|
|
import { getUserById } from './user-repository'
|
|
|
|
export function requireUserIdParam(event: H3Event) {
|
|
return getRequiredRouteParam(event, 'id', 'User id')
|
|
}
|
|
|
|
export async function requireExistingUser(userId: string, statusMessage = 'User not found') {
|
|
const user = await getUserById(userId)
|
|
|
|
if (!user) {
|
|
httpError(404, statusMessage)
|
|
}
|
|
|
|
return user
|
|
}
|
|
|
|
export function parseCreateUserInput(body: {
|
|
username?: string
|
|
fullName?: string
|
|
phoneNumber?: string
|
|
role?: UserRole
|
|
}) {
|
|
const username = normalizeUsername(body.username || '')
|
|
const fullName = normalizeFullName(body.fullName || '')
|
|
const phoneNumber = normalizePhoneNumber(body.phoneNumber || '')
|
|
const role = body.role === 'super_admin' ? 'super_admin' : 'staff'
|
|
|
|
assertBadRequest(
|
|
isValidUsername(username),
|
|
'Username must be 3 to 32 characters using lowercase letters, numbers, dot, dash, or underscore'
|
|
)
|
|
assertBadRequest(hasValidFullName(fullName), 'Full name must be at least 2 characters')
|
|
assertBadRequest(isValidPhoneNumber(phoneNumber), 'Phone number must include a country code, e.g. +60123456789')
|
|
|
|
return {
|
|
username,
|
|
fullName,
|
|
phoneNumber,
|
|
role
|
|
}
|
|
}
|
|
|
|
export function parseUserProfileInput(body: {
|
|
fullName?: string
|
|
phoneNumber?: string
|
|
role?: UserRole
|
|
}) {
|
|
const fullName = normalizeFullName(body.fullName || '')
|
|
const phoneNumber = normalizePhoneNumber(body.phoneNumber || '')
|
|
const role = body.role
|
|
|
|
assertBadRequest(hasValidFullName(fullName), 'Display name must be at least 2 characters')
|
|
assertBadRequest(isValidPhoneNumber(phoneNumber), 'Phone number must include a country code, e.g. +60123456789')
|
|
assertBadRequest(isUserRole(role), 'Role is invalid')
|
|
|
|
return {
|
|
fullName,
|
|
phoneNumber,
|
|
role
|
|
}
|
|
}
|
|
|
|
export function parseUserOrderInput(body: {
|
|
userIds?: unknown
|
|
}) {
|
|
assertBadRequest(Array.isArray(body.userIds), 'User ids must be an array')
|
|
assertBadRequest(body.userIds.every((value) => typeof value === 'string' && value.trim()), 'Every user id is required')
|
|
|
|
const userIds = body.userIds.map((value) => value.trim())
|
|
const uniqueUserIds = new Set(userIds)
|
|
|
|
assertBadRequest(uniqueUserIds.size === userIds.length, 'User ids must be unique')
|
|
|
|
return {
|
|
userIds
|
|
}
|
|
}
|