More stuff
This commit is contained in:
parent
edffe130a5
commit
7371cc8851
@ -18,6 +18,7 @@
|
||||
"@t3-oss/env-nextjs": "^0.10.1",
|
||||
"drizzle-orm": "^0.33.0",
|
||||
"geist": "^1.3.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"next": "^14.2.4",
|
||||
"postgres": "^3.4.4",
|
||||
"react": "^18.3.1",
|
||||
@ -26,6 +27,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/jsonwebtoken": "^9.0.7",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
|
103
pnpm-lock.yaml
generated
103
pnpm-lock.yaml
generated
@ -17,6 +17,9 @@ importers:
|
||||
geist:
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.1(next@14.2.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
jsonwebtoken:
|
||||
specifier: ^9.0.2
|
||||
version: 9.0.2
|
||||
next:
|
||||
specifier: ^14.2.4
|
||||
version: 14.2.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@ -36,6 +39,9 @@ importers:
|
||||
'@types/eslint':
|
||||
specifier: ^8.56.10
|
||||
version: 8.56.12
|
||||
'@types/jsonwebtoken':
|
||||
specifier: ^9.0.7
|
||||
version: 9.0.7
|
||||
'@types/node':
|
||||
specifier: ^20.14.10
|
||||
version: 20.16.5
|
||||
@ -539,6 +545,9 @@ packages:
|
||||
'@types/json5@0.0.29':
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
|
||||
'@types/jsonwebtoken@9.0.7':
|
||||
resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==}
|
||||
|
||||
'@types/node@20.16.5':
|
||||
resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==}
|
||||
|
||||
@ -785,6 +794,9 @@ packages:
|
||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||
|
||||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
@ -1005,6 +1017,9 @@ packages:
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
@ -1503,10 +1518,20 @@ packages:
|
||||
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
|
||||
hasBin: true
|
||||
|
||||
jsonwebtoken@9.0.2:
|
||||
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
jwa@1.4.1:
|
||||
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
|
||||
|
||||
jws@3.2.2:
|
||||
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
@ -1536,9 +1561,30 @@ packages:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
lodash.includes@4.3.0:
|
||||
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||
|
||||
lodash.isboolean@3.0.3:
|
||||
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||
|
||||
lodash.isinteger@4.0.4:
|
||||
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||
|
||||
lodash.isnumber@3.0.3:
|
||||
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||
|
||||
lodash.isplainobject@4.0.6:
|
||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||
|
||||
lodash.isstring@4.0.1:
|
||||
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
lodash.once@4.1.1:
|
||||
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
@ -1893,6 +1939,9 @@ packages:
|
||||
resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
||||
safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
safe-regex-test@1.0.3:
|
||||
resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2450,6 +2499,10 @@ snapshots:
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
|
||||
'@types/jsonwebtoken@9.0.7':
|
||||
dependencies:
|
||||
'@types/node': 20.16.5
|
||||
|
||||
'@types/node@20.16.5':
|
||||
dependencies:
|
||||
undici-types: 6.19.8
|
||||
@ -2768,6 +2821,8 @@ snapshots:
|
||||
dependencies:
|
||||
fill-range: 7.1.1
|
||||
|
||||
buffer-equal-constant-time@1.0.1: {}
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
busboy@1.6.0:
|
||||
@ -2923,6 +2978,10 @@ snapshots:
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emoji-regex@9.2.2: {}
|
||||
@ -3130,7 +3189,7 @@ snapshots:
|
||||
debug: 4.3.7
|
||||
enhanced-resolve: 5.17.1
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0)
|
||||
eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.8.0
|
||||
is-bun-module: 1.2.1
|
||||
@ -3143,7 +3202,7 @@ snapshots:
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0):
|
||||
eslint-module-utils@2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@ -3647,6 +3706,19 @@ snapshots:
|
||||
dependencies:
|
||||
minimist: 1.2.8
|
||||
|
||||
jsonwebtoken@9.0.2:
|
||||
dependencies:
|
||||
jws: 3.2.2
|
||||
lodash.includes: 4.3.0
|
||||
lodash.isboolean: 3.0.3
|
||||
lodash.isinteger: 4.0.4
|
||||
lodash.isnumber: 3.0.3
|
||||
lodash.isplainobject: 4.0.6
|
||||
lodash.isstring: 4.0.1
|
||||
lodash.once: 4.1.1
|
||||
ms: 2.1.3
|
||||
semver: 7.6.3
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
dependencies:
|
||||
array-includes: 3.1.8
|
||||
@ -3654,6 +3726,17 @@ snapshots:
|
||||
object.assign: 4.1.5
|
||||
object.values: 1.2.0
|
||||
|
||||
jwa@1.4.1:
|
||||
dependencies:
|
||||
buffer-equal-constant-time: 1.0.1
|
||||
ecdsa-sig-formatter: 1.0.11
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
jws@3.2.2:
|
||||
dependencies:
|
||||
jwa: 1.4.1
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
@ -3679,8 +3762,22 @@ snapshots:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
|
||||
lodash.includes@4.3.0: {}
|
||||
|
||||
lodash.isboolean@3.0.3: {}
|
||||
|
||||
lodash.isinteger@4.0.4: {}
|
||||
|
||||
lodash.isnumber@3.0.3: {}
|
||||
|
||||
lodash.isplainobject@4.0.6: {}
|
||||
|
||||
lodash.isstring@4.0.1: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash.once@4.1.1: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
@ -3979,6 +4076,8 @@ snapshots:
|
||||
has-symbols: 1.0.3
|
||||
isarray: 2.0.5
|
||||
|
||||
safe-buffer@5.2.1: {}
|
||||
|
||||
safe-regex-test@1.0.3:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
|
22
src/app/api/countdown/createOrUpdateCountdown/route.ts
Normal file
22
src/app/api/countdown/createOrUpdateCountdown/route.ts
Normal file
@ -0,0 +1,22 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { createOrUpdateCountdown } from "~/server/functions";
|
||||
import { middleware } from "~/middleware";
|
||||
|
||||
export const POST = async (request: NextRequest) => {
|
||||
const middlewareResponse = middleware(request);
|
||||
if (middlewareResponse) return middlewareResponse;
|
||||
try {
|
||||
const { relationshipId, title, date } = await request.json() as {
|
||||
relationshipId: string;
|
||||
title: string;
|
||||
date: string;
|
||||
};
|
||||
await createOrUpdateCountdown(Number.parseInt(relationshipId), title, new Date(date));
|
||||
return NextResponse.json({ message: "Countdown created or updated successfully" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return NextResponse.json({ message: "Error" }, { status: 500 });
|
||||
}
|
||||
};
|
23
src/app/api/countdown/getCountdownByRelationship/route.ts
Normal file
23
src/app/api/countdown/getCountdownByRelationship/route.ts
Normal file
@ -0,0 +1,23 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { getCountdownByRelationship } from "~/server/functions";
|
||||
|
||||
export const GET = async (request: Request) => {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const apiKey = url.searchParams.get("apiKey");
|
||||
if (apiKey !== process.env.API_KEY) {
|
||||
console.log("Invalid API Key");
|
||||
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
|
||||
} else {
|
||||
const relationshipId = url.searchParams.get("relationshipId");
|
||||
if (!relationshipId)
|
||||
return NextResponse.json({ message: "Invalid relationshipId" }, { status: 400 });
|
||||
const countdown = await getCountdownByRelationship(parseInt(relationshipId));
|
||||
return NextResponse.json(countdown);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return NextResponse.json({ message: "Error" }, { status: 500 });
|
||||
}
|
||||
};
|
@ -0,0 +1,26 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { fetchMessages } from "~/server/functions";
|
||||
|
||||
export const GET = async (request: Request) => {
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const apiKey = url.searchParams.get("apiKey");
|
||||
if (apiKey !== process.env.API_KEY) {
|
||||
console.log("Invalid API Key");
|
||||
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
|
||||
} else {
|
||||
const userId = url.searchParams.get("userId");
|
||||
if (!userId)
|
||||
return NextResponse.json({ message: "Invalid userId" }, { status: 400 });
|
||||
const partnerId = url.searchParams.get("partnerId");
|
||||
if (!partnerId)
|
||||
return NextResponse.json({ message: "Invalid partnerId" }, { status: 400 });
|
||||
const messages = await fetchMessages(parseInt(userId), parseInt(partnerId));
|
||||
return NextResponse.json(messages);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return NextResponse.json({ message: "Error" }, { status: 500 });
|
||||
}
|
||||
};
|
@ -2,7 +2,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createRelationshipRequest } from "~/server/functions";
|
||||
|
||||
interface CreateRequestRequest {
|
||||
type CreateRequestRequest = {
|
||||
apiKey: string;
|
||||
userId: number;
|
||||
targetUserId: number;
|
||||
|
@ -21,8 +21,6 @@ export const POST = async (request: Request) => {
|
||||
|
||||
console.log("Changing password for user:", userId);
|
||||
await changePassword(userId, oldPassword, newPassword);
|
||||
|
||||
console.log("Password changed successfully");
|
||||
return NextResponse.json({ message: "Password changed successfully" });
|
||||
} catch (error) {
|
||||
console.error("Error in changePassword:", error);
|
||||
|
@ -10,7 +10,10 @@ export const GET = async (request: Request) => {
|
||||
console.log("Invalid API Key");
|
||||
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
|
||||
} else {
|
||||
const userId = url.searchParams.get("userId") ?? "2";
|
||||
const userId = url.searchParams.get("userId");
|
||||
if (!userId) {
|
||||
return NextResponse.json({ message: "Invalid userId" }, { status: 400 });
|
||||
}
|
||||
const user = await getUserById(parseInt(userId));
|
||||
return NextResponse.json(user);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { userLogin } from "~/server/functions";
|
||||
import { login } from "~/server/functions";
|
||||
|
||||
interface LoginRequest {
|
||||
apiKey: string;
|
||||
@ -23,7 +23,7 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
console.log("Logging in user:", username);
|
||||
const result = await userLogin(username, password);
|
||||
const result = await login(username, password);
|
||||
|
||||
if (result) {
|
||||
console.log("User logged in successfully");
|
||||
|
32
src/app/api/users/logout/route.ts
Normal file
32
src/app/api/users/logout/route.ts
Normal file
@ -0,0 +1,32 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { logout } from "~/server/functions";
|
||||
import { middleware } from "~/middleware";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export const POST = async (request: NextRequest) => {
|
||||
const middlewareResponse = middleware(request);
|
||||
if (middlewareResponse) return middlewareResponse;
|
||||
|
||||
try {
|
||||
const { token } = await request.json() as { token: string };
|
||||
if (!token)
|
||||
return NextResponse.json({ message: "Token is required" },{ status: 400 });
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: number };
|
||||
if (!decoded.userId)
|
||||
throw new Error("Invalid token");
|
||||
await logout(decoded.userId);
|
||||
return NextResponse.json({ message: "Logged out successfully" });
|
||||
} catch (jwtError) {
|
||||
return NextResponse.json({ message: "Invalid token", error: jwtError }, { status: 400 });
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error)
|
||||
return NextResponse.json({ message: error.message }, { status: 400 });
|
||||
else
|
||||
return NextResponse.json({ message: "Unknown error occurred" }, { status: 500 });
|
||||
}
|
||||
}
|
22
src/app/api/users/refreshToken/route.ts
Normal file
22
src/app/api/users/refreshToken/route.ts
Normal file
@ -0,0 +1,22 @@
|
||||
"use server";
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { refreshToken } from "~/server/functions";
|
||||
import { middleware } from "~/middleware";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const middlewareResponse = middleware(request);
|
||||
if (middlewareResponse) return middlewareResponse;
|
||||
try {
|
||||
const { refreshToken: token } = await request.json() as { refreshToken: string };
|
||||
if (!token)
|
||||
return NextResponse.json({ message: "Refresh token is required" },{ status: 400 });
|
||||
const tokens = await refreshToken(token);
|
||||
return NextResponse.json(tokens);
|
||||
} catch (error) {
|
||||
if (error instanceof Error)
|
||||
return NextResponse.json({ message: error.message }, { status: 400 });
|
||||
else
|
||||
return NextResponse.json({ message: "Unknown error occurred" }, { status: 500 });
|
||||
}
|
||||
}
|
13
src/middleware.ts
Normal file
13
src/middleware.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
const apiKey = request.headers.get('x-api-key');
|
||||
|
||||
if (!apiKey || apiKey !== process.env.API_KEY)
|
||||
return NextResponse.json({ message: 'Invalid API key' }, { status: 401 });
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: '/api/:path*',
|
||||
};
|
@ -24,7 +24,8 @@ export const users = createTable(
|
||||
passwordHash: varchar("password_hash", {length: 255}).notNull(),
|
||||
name: varchar("name", { length: 100 }),
|
||||
pfpURL: varchar("pfp_url", { length: 255 }),
|
||||
pushToken: varchar("pushToken", { length: 256 }),
|
||||
pushToken: varchar("pushToken", { length: 255 }),
|
||||
refreshToken: varchar("refreshToken", { length: 255 }),
|
||||
lastLogin: timestamp("last_login", { withTimezone: true }),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
|
@ -3,6 +3,7 @@ import { db } from '~/server/db';
|
||||
import * as schema from '~/server/db/schema';
|
||||
import { eq, and, or } from 'drizzle-orm';
|
||||
import { pgEnum } from 'drizzle-orm/pg-core';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
// --- Helper Functions --- //
|
||||
|
||||
@ -198,19 +199,24 @@ export const updateUserPushToken = async (userId: number, pushToken: string) =>
|
||||
}
|
||||
};
|
||||
|
||||
export const userLogin = async (username: string, passwordHash: string) => {
|
||||
export const login = async (username: string, passwordHash: string) => {
|
||||
try {
|
||||
const user = await getUserByUsername(username);
|
||||
if (user?.passwordHash !== passwordHash) {
|
||||
throw new Error("Invalid password");
|
||||
}
|
||||
|
||||
const accessToken = jwt.sign({ userId: user.id }, process.env.JWT_SECRET!,
|
||||
{expiresIn: '15m' });
|
||||
const refreshToken = jwt.sign({ userId: user.id }, process.env.JWT_REFRESH_SECRET!,
|
||||
{expiresIn: '7d' });
|
||||
|
||||
// Update last login timestamp
|
||||
await db.update(schema.users)
|
||||
.set({ lastLogin: new Date() })
|
||||
.where(eq(schema.users.id, user.id));
|
||||
|
||||
return user;
|
||||
return { user, accessToken, refreshToken };
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Failed to Log in: ${error.message}`);
|
||||
@ -220,6 +226,47 @@ export const userLogin = async (username: string, passwordHash: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const refreshToken = async (refreshToken: string) => {
|
||||
try {
|
||||
const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET!) as { userId: number };
|
||||
if (!decoded.userId)
|
||||
throw new Error("Invalid refresh token");
|
||||
const user = await getUserById(decoded.userId);
|
||||
if (!user || user.refreshToken !== refreshToken)
|
||||
throw new Error("Invalid refresh token");
|
||||
const newAccessToken = jwt.sign({ userId: user.id }, process.env.JWT_SECRET!,
|
||||
{expiresIn: '15m' });
|
||||
const newRefreshToken = jwt.sign({ userId: user.id }, process.env.JWT_REFRESH_SECRET!,
|
||||
{expiresIn: '7d' });
|
||||
await db.update(schema.users)
|
||||
.set({ refreshToken: newRefreshToken })
|
||||
.where(eq(schema.users.id, user.id));
|
||||
|
||||
return { accessToken: newAccessToken, refreshToken: newRefreshToken };
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Failed to refresh token: ${error.message}`);
|
||||
} else {
|
||||
throw new Error("Unknown error occurred while refreshing token");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const logout = async (userId: number) => {
|
||||
try {
|
||||
await db.update(schema.users)
|
||||
.set({ lastLogin: null })
|
||||
.where(eq(schema.users.id, userId));
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Failed to logout: ${error.message}`);
|
||||
} else {
|
||||
throw new Error("Unknown error occurred while logging out");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// --- Relationship Management Functions --- //
|
||||
|
||||
export const createRelationshipRequest = async (requestorId: number, requestedId: number) => {
|
||||
|
Loading…
Reference in New Issue
Block a user