aboutsummaryrefslogtreecommitdiff
path: root/src/app/api/auth
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/api/auth')
-rw-r--r--src/app/api/auth/login/route.ts48
-rw-r--r--src/app/api/auth/logout/route.ts12
-rw-r--r--src/app/api/auth/sso/route.ts18
-rw-r--r--src/app/api/auth/verify/route.ts15
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 });
+}