diff options
Diffstat (limited to 'src/app/api/auth')
| -rw-r--r-- | src/app/api/auth/login/route.ts | 48 | ||||
| -rw-r--r-- | src/app/api/auth/logout/route.ts | 12 | ||||
| -rw-r--r-- | src/app/api/auth/sso/route.ts | 18 | ||||
| -rw-r--r-- | src/app/api/auth/verify/route.ts | 15 |
4 files changed, 93 insertions, 0 deletions
diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..17ca2f7 --- /dev/null +++ b/src/app/api/auth/login/route.ts @@ -0,0 +1,48 @@ +import { z } from 'zod'; +import { saveAuth } from '@/lib/auth'; +import { ROLES } from '@/lib/constants'; +import { secret } from '@/lib/crypto'; +import { createSecureToken } from '@/lib/jwt'; +import { checkPassword } from '@/lib/password'; +import redis from '@/lib/redis'; +import { parseRequest } from '@/lib/request'; +import { json, unauthorized } from '@/lib/response'; +import { getAllUserTeams, getUserByUsername } from '@/queries/prisma'; + +export async function POST(request: Request) { + const schema = z.object({ + username: z.string(), + password: z.string(), + }); + + const { body, error } = await parseRequest(request, schema, { skipAuth: true }); + + if (error) { + return error(); + } + + const { username, password } = body; + + const user = await getUserByUsername(username, { includePassword: true }); + + if (!user || !checkPassword(password, user.password)) { + return unauthorized({ code: 'incorrect-username-password' }); + } + + const { id, role, createdAt } = user; + + let token: string; + + if (redis.enabled) { + token = await saveAuth({ userId: id, role }); + } else { + token = createSecureToken({ userId: user.id, role }, secret()); + } + + const teams = await getAllUserTeams(id); + + return json({ + token, + user: { id, username, role, createdAt, isAdmin: role === ROLES.admin, teams }, + }); +} diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts new file mode 100644 index 0000000..7bf0a81 --- /dev/null +++ b/src/app/api/auth/logout/route.ts @@ -0,0 +1,12 @@ +import redis from '@/lib/redis'; +import { ok } from '@/lib/response'; + +export async function POST(request: Request) { + if (redis.enabled) { + const token = request.headers.get('authorization')?.split(' ')?.[1]; + + await redis.client.del(token); + } + + return ok(); +} diff --git a/src/app/api/auth/sso/route.ts b/src/app/api/auth/sso/route.ts new file mode 100644 index 0000000..bba3dde --- /dev/null +++ b/src/app/api/auth/sso/route.ts @@ -0,0 +1,18 @@ +import { saveAuth } from '@/lib/auth'; +import redis from '@/lib/redis'; +import { parseRequest } from '@/lib/request'; +import { json } from '@/lib/response'; + +export async function POST(request: Request) { + const { auth, error } = await parseRequest(request); + + if (error) { + return error(); + } + + if (redis.enabled) { + const token = await saveAuth({ userId: auth.user.id }, 86400); + + return json({ user: auth.user, token }); + } +} diff --git a/src/app/api/auth/verify/route.ts b/src/app/api/auth/verify/route.ts new file mode 100644 index 0000000..b308b7b --- /dev/null +++ b/src/app/api/auth/verify/route.ts @@ -0,0 +1,15 @@ +import { parseRequest } from '@/lib/request'; +import { json } from '@/lib/response'; +import { getAllUserTeams } from '@/queries/prisma'; + +export async function POST(request: Request) { + const { auth, error } = await parseRequest(request); + + if (error) { + return error(); + } + + const teams = await getAllUserTeams(auth.user.id); + + return json({ ...auth.user, teams }); +} |