First Commit
This commit is contained in:
commit
bac95bdb2e
154 files changed
+26610
No files matched your search
@@ -0,0 +1,116 @@
|
||||
import type { FastifyReply, FastifyRequest } from 'fastify'
|
||||
import {
|
||||
getUserApps,
|
||||
getUserById,
|
||||
getUserPermissions,
|
||||
type UserRow,
|
||||
} from '@authportal/db'
|
||||
import type { AppId, MeResponse } from '@authportal/shared'
|
||||
import { APP_IDS } from '@authportal/shared'
|
||||
|
||||
export type AuthUser = {
|
||||
id: string
|
||||
email: string
|
||||
name: string
|
||||
isAdmin: boolean
|
||||
apps: AppId[]
|
||||
permissions: string[]
|
||||
}
|
||||
|
||||
declare module '@fastify/jwt' {
|
||||
interface FastifyJWT {
|
||||
payload: {
|
||||
sub: string
|
||||
email: string
|
||||
name: string
|
||||
apps: string[]
|
||||
permissions: string[]
|
||||
is_admin?: boolean
|
||||
iss: string
|
||||
}
|
||||
user: {
|
||||
sub: string
|
||||
email: string
|
||||
name: string
|
||||
apps: string[]
|
||||
permissions: string[]
|
||||
is_admin?: boolean
|
||||
iss: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyRequest {
|
||||
authUser?: AuthUser
|
||||
}
|
||||
}
|
||||
|
||||
function asAppIds(apps: string[]): AppId[] {
|
||||
return apps.filter((a): a is AppId =>
|
||||
(APP_IDS as readonly string[]).includes(a),
|
||||
)
|
||||
}
|
||||
|
||||
export function toMe(user: UserRow, apps: string[], permissions: string[]): MeResponse {
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
is_admin: user.isAdmin,
|
||||
apps: asAppIds(apps),
|
||||
permissions,
|
||||
}
|
||||
}
|
||||
|
||||
export function loadAuthUser(
|
||||
request: FastifyRequest,
|
||||
user: UserRow,
|
||||
): AuthUser {
|
||||
const apps = getUserApps(request.server.db, user.id)
|
||||
const permissions = getUserPermissions(request.server.db, user.id)
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
isAdmin: user.isAdmin,
|
||||
apps: asAppIds(apps),
|
||||
permissions,
|
||||
}
|
||||
}
|
||||
|
||||
export async function requireAuth(
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await request.jwtVerify()
|
||||
} catch {
|
||||
return reply.status(401).send({
|
||||
error: { code: 'UNAUTHORIZED', message: 'Требуется авторизация' },
|
||||
})
|
||||
}
|
||||
|
||||
const sub = request.user.sub
|
||||
const row = getUserById(request.server.db, sub)
|
||||
if (!row || row.disabled) {
|
||||
return reply.status(401).send({
|
||||
error: { code: 'UNAUTHORIZED', message: 'Пользователь недоступен' },
|
||||
})
|
||||
}
|
||||
|
||||
request.authUser = loadAuthUser(request, row)
|
||||
}
|
||||
|
||||
export async function requireAdmin(
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply,
|
||||
): Promise<void> {
|
||||
await requireAuth(request, reply)
|
||||
if (reply.sent) return
|
||||
if (!request.authUser?.isAdmin) {
|
||||
return reply.status(403).send({
|
||||
error: { code: 'FORBIDDEN', message: 'Только для администраторов' },
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user