Compare commits
10 commits
1878692fa1
...
2381ccd75c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2381ccd75c | ||
|
|
649151d613 | ||
|
|
55b0a0300c | ||
|
|
0e49fc53ab | ||
|
|
473a741f10 | ||
|
|
90f67dfa03 | ||
|
|
86e38900fc | ||
|
|
15d1f6967e | ||
|
|
73631d1972 | ||
|
|
08eb4d92ab |
21 changed files with 697 additions and 160 deletions
15
.env
Normal file
15
.env
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
SERVER_URL=http://localhost
|
||||||
|
SERVER_PORT=3000
|
||||||
|
|
||||||
|
DATABASE_URL=postgres://postgres:saimon%40567@localhost:5432/planpost_canvas
|
||||||
|
|
||||||
|
MINIO_ACCESS_KEY=rEiuiqB8JCSmWt7AswOM
|
||||||
|
MINIO_SECRET_KEY=en3ut7Zp71uAfGrhvMkH6Pk7ZM1qZb9mFxj7KzD5
|
||||||
|
MINIO_ENDPOINT=localhost
|
||||||
|
MINIO_PORT=9000
|
||||||
|
|
||||||
|
CLERK_SECRET_KEY=sk_test_X4OZbPdnr9ZxlccH8eaA7Ou0oQvQ9FpQ0mq0KuwLUz
|
||||||
|
|
||||||
|
JWT_ACCESS_TOKEN_SECRET=planpostai%^$_%43%65576canvas%%$$
|
||||||
|
|
||||||
|
JWT_REFRESH_TOKEN_SECRET=planpostai!@43223_canvas$%^$349332$$
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -25,7 +25,6 @@ yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env
|
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
|
|
|
||||||
2
drizzle/0002_serious_green_goblin.sql
Normal file
2
drizzle/0002_serious_green_goblin.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE "projects" ADD COLUMN "is_active" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "projects" ADD COLUMN "preview_url" text;
|
||||||
231
drizzle/meta/0002_snapshot.json
Normal file
231
drizzle/meta/0002_snapshot.json
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
{
|
||||||
|
"id": "97be3edd-38c0-499d-accc-13797e7318aa",
|
||||||
|
"prevId": "b6897b47-e0f0-48c5-8917-696944c8524b",
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"tables": {
|
||||||
|
"public.projects": {
|
||||||
|
"name": "projects",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"project_id": {
|
||||||
|
"name": "project_id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"object": {
|
||||||
|
"name": "object",
|
||||||
|
"type": "json",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"name": "description",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"is_active": {
|
||||||
|
"name": "is_active",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"preview_url": {
|
||||||
|
"name": "preview_url",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"projects_user_id_users_user_id_fk": {
|
||||||
|
"name": "projects_user_id_users_user_id_fk",
|
||||||
|
"tableFrom": "projects",
|
||||||
|
"tableTo": "users",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.uploads": {
|
||||||
|
"name": "uploads",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "gen_random_uuid()"
|
||||||
|
},
|
||||||
|
"filename": {
|
||||||
|
"name": "filename",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"name": "url",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"projectId": {
|
||||||
|
"name": "projectId",
|
||||||
|
"type": "uuid",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"uploads_projectId_projects_project_id_fk": {
|
||||||
|
"name": "uploads_projectId_projects_project_id_fk",
|
||||||
|
"tableFrom": "uploads",
|
||||||
|
"tableTo": "projects",
|
||||||
|
"columnsFrom": [
|
||||||
|
"projectId"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"project_id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.users": {
|
||||||
|
"name": "users",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"last_name": {
|
||||||
|
"name": "last_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"first_name": {
|
||||||
|
"name": "first_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"paid_status": {
|
||||||
|
"name": "paid_status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"expires_in": {
|
||||||
|
"name": "expires_in",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"refresh_token": {
|
||||||
|
"name": "refresh_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {},
|
||||||
|
"schemas": {},
|
||||||
|
"sequences": {},
|
||||||
|
"roles": {},
|
||||||
|
"policies": {},
|
||||||
|
"views": {},
|
||||||
|
"_meta": {
|
||||||
|
"columns": {},
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,13 @@
|
||||||
"when": 1737876981144,
|
"when": 1737876981144,
|
||||||
"tag": "0001_shallow_umar",
|
"tag": "0001_shallow_umar",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 2,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1738213216210,
|
||||||
|
"tag": "0002_serious_green_goblin",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
18
env.example.js
Normal file
18
env.example.js
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// all of these are required to run the project
|
||||||
|
|
||||||
|
|
||||||
|
// SERVER_URL
|
||||||
|
// SERVER_PORT
|
||||||
|
|
||||||
|
// DATABASE_URL
|
||||||
|
|
||||||
|
// MINIO_ACCESS_KEY
|
||||||
|
// MINIO_SECRET_KEY
|
||||||
|
// MINIO_ENDPOINT
|
||||||
|
// MINIO_PORT
|
||||||
|
|
||||||
|
// CLERK_SECRET_KEY
|
||||||
|
|
||||||
|
// JWT_ACCESS_TOKEN_SECRET
|
||||||
|
|
||||||
|
// JWT_REFRESH_TOKEN_SECRET
|
||||||
|
|
@ -47,7 +47,10 @@ export const getUserData = async (userId: string) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateUser = async (id: string, body) => {
|
export const updateUser = async (id: string, body: {
|
||||||
|
paid_status: string,
|
||||||
|
package_expire_date: string,
|
||||||
|
}) => {
|
||||||
try {
|
try {
|
||||||
const updateUserData = await db.update(users).set({ paid_status: body?.paid_status, expires_in: body?.package_expire_date }).where(eq(users.id, id)).returning({ updatedId: users.id });
|
const updateUserData = await db.update(users).set({ paid_status: body?.paid_status, expires_in: body?.package_expire_date }).where(eq(users.id, id)).returning({ updatedId: users.id });
|
||||||
|
|
||||||
|
|
@ -62,42 +65,52 @@ export const updateUser = async (id: string, body) => {
|
||||||
export const generateToken = async (context: any) => {
|
export const generateToken = async (context: any) => {
|
||||||
try {
|
try {
|
||||||
const userId = context?.params?.userId;
|
const userId = context?.params?.userId;
|
||||||
// generating accessToken and refreshToken
|
const access_cookie = context?.cookie?.access_token?.value;
|
||||||
const user = await checkUserInDB(userId);
|
const refresh_cookie = context?.cookie?.refresh_token?.value;
|
||||||
if (user?.found === true) {
|
|
||||||
|
|
||||||
// generate access token
|
if (access_cookie !== undefined || refresh_cookie !== undefined) {
|
||||||
const accessToken = jwt.sign({ userId }, ENV.JWT_ACCESS_TOKEN_SECRET, { expiresIn: '3h' });
|
const verify = await verifyAuth(context?.cookie);
|
||||||
|
return verify;
|
||||||
|
}
|
||||||
|
else if (access_cookie === undefined && refresh_cookie === undefined && userId !== undefined) {
|
||||||
|
const user = await checkUserInDB(userId);
|
||||||
|
if (user?.found === true) {
|
||||||
|
|
||||||
// generate refresh token
|
// generate access token
|
||||||
const refreshToken = jwt.sign({ userId }, ENV.JWT_REFRESH_TOKEN_SECRET, { expiresIn: '7d' });
|
const accessToken = jwt.sign({ userId }, ENV.JWT_ACCESS_TOKEN_SECRET, { expiresIn: '3h' });
|
||||||
|
|
||||||
// store refresh token in db
|
// generate refresh token
|
||||||
const storeRToken = await storeRefreshToken(userId, refreshToken);
|
const refreshToken = jwt.sign({ userId }, ENV.JWT_REFRESH_TOKEN_SECRET, { expiresIn: '7d' });
|
||||||
|
|
||||||
if (storeRToken.status === 200) {
|
// store refresh token in db
|
||||||
context.cookie.access_token.set({
|
const storeRToken = await storeRefreshToken(userId, refreshToken);
|
||||||
value: accessToken,
|
|
||||||
httpOnly: true,
|
|
||||||
secure: true, // Set to true in production
|
|
||||||
sameSite: 'none', // Adjust based on your needs
|
|
||||||
path: "/",
|
|
||||||
maxAge: 3 * 60 * 60, // 3 hours in seconds
|
|
||||||
});
|
|
||||||
|
|
||||||
context.cookie.refresh_token.set({
|
if (storeRToken.status === 200) {
|
||||||
value: refreshToken,
|
context.cookie.access_token.set({
|
||||||
httpOnly: true,
|
value: accessToken,
|
||||||
secure: true, // Set to true in production
|
httpOnly: true,
|
||||||
sameSite: 'none', // Adjust based on your needs
|
secure: true, // Set to true in production
|
||||||
path: "/",
|
sameSite: 'none', // Adjust based on your needs
|
||||||
maxAge: 7 * 24 * 60 * 60, // 7 days in seconds
|
path: "/",
|
||||||
});
|
maxAge: 3 * 60 * 60, // 3 hours in seconds
|
||||||
|
});
|
||||||
|
|
||||||
return { status: 200, message: "Token generated successfully", token: accessToken };
|
context.cookie.refresh_token.set({
|
||||||
|
value: refreshToken,
|
||||||
|
httpOnly: true,
|
||||||
|
secure: true, // Set to true in production
|
||||||
|
sameSite: 'none', // Adjust based on your needs
|
||||||
|
path: "/",
|
||||||
|
maxAge: 7 * 24 * 60 * 60, // 7 days in seconds
|
||||||
|
});
|
||||||
|
|
||||||
|
return { status: 201, message: "Token generated successfully", token: accessToken, userId: user?.id };
|
||||||
|
}
|
||||||
|
return { status: 500, message: "An error occurred while storing the refresh token" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { status: 404, message: "User not found" };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { status: 500, message: "An error occurred while storing the refresh token" };
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return { status: 404, message: "Unauthorized!!!" };
|
return { status: 404, message: "Unauthorized!!!" };
|
||||||
|
|
@ -108,19 +121,5 @@ export const generateToken = async (context: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const verifyToken = async (context: any) => {
|
|
||||||
try {
|
|
||||||
// if token is in cookie, verify it
|
|
||||||
// const token_cookie = context.cookie.access_token.value;
|
|
||||||
const verify = await verifyAuth(context.cookie);
|
|
||||||
|
|
||||||
return verify;
|
|
||||||
|
|
||||||
} catch (error: any) {
|
|
||||||
console.log("Error in verifyToken:", error.message || error.toString());
|
|
||||||
return { status: 500, message: `An error occurred while verifying the token` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Elysia from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import { generateToken, getUserData, updateUser, verifyToken } from "./auth.controller";
|
import { generateToken, getUserData, updateUser } from "./auth.controller";
|
||||||
|
|
||||||
export const authRoute = new Elysia({
|
export const authRoute = new Elysia({
|
||||||
prefix: "/auth",
|
prefix: "/auth",
|
||||||
|
|
@ -9,11 +9,21 @@ export const authRoute = new Elysia({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
authRoute.get("/user/:userId", async ({ params: { userId } }) => await getUserData(userId));
|
authRoute.get("/user/:userId", async ({ params: { userId } }) => await getUserData(userId), {
|
||||||
|
params: t.Object({
|
||||||
|
userId: t.String()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
authRoute.post("/user/update/:userId", async ({ params: { userId }, body }) => await updateUser(userId, body));
|
authRoute.post("/user/update/:userId", async ({ params: { userId }, body }) => await updateUser(userId, body), {
|
||||||
|
params: t.Object({
|
||||||
|
userId: t.String()
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
paid_status: t.String(),
|
||||||
|
package_expire_date: t.String(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
authRoute.get("/generate-token/:userId", async (context) => await generateToken(context));
|
authRoute.get("/generate-token/:userId", async (context) => await generateToken(context));
|
||||||
|
|
||||||
authRoute.get("/verify-token", async (context) => await verifyToken(context));
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,132 @@
|
||||||
export const getEachProjects = async (id: string) => {
|
import { eq } from "drizzle-orm";
|
||||||
|
import { db } from "../../db";
|
||||||
|
import { projects, uploads } from "../../db/schema";
|
||||||
|
import { createEmptyProject } from "../../helper/projects/createProject";
|
||||||
|
import { createBucket } from "../../helper/upload/createBucket";
|
||||||
|
import { removeBucket } from "../../helper/upload/removeBucket";
|
||||||
|
|
||||||
|
export const getEachProjects = async (id: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
console.log(id);
|
const project = await db.select({
|
||||||
return { id: id }
|
id: projects.id,
|
||||||
} catch (error) {
|
name: projects.name,
|
||||||
console.log(error.msg)
|
description: projects.description,
|
||||||
return { status: 500, message: "An error occurred while fetching projects" }
|
preview_url: projects.preview_url,
|
||||||
|
object: projects.object,
|
||||||
|
}).from(projects).where(eq(projects.id, id)).limit(1);
|
||||||
|
if (project.length === 0) {
|
||||||
|
return { status: 404, message: "Project not found", token };
|
||||||
|
}
|
||||||
|
return { status: 200, message: "Project fetched successfully", data: project[0], token };
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(error.message);
|
||||||
|
return { status: 500, message: "An error occurred while fetching projects", token };
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getAllProjects = async () => {
|
export const getAllProjects = async (userId: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
// this will return all the project associated with the user
|
// Fetch all projects for the given user
|
||||||
} catch (error) {
|
const allProjects = await db.select({
|
||||||
console.log(error.msg);
|
id: projects.id,
|
||||||
return { status: 500, message: "An error occurred while fetching projects" }
|
name: projects.name,
|
||||||
}
|
description: projects.description,
|
||||||
}
|
preview_url: projects.preview_url,
|
||||||
|
object: projects.object,
|
||||||
|
}).from(projects).where(eq(projects.userId, userId));
|
||||||
|
|
||||||
export const updateProject = async (id: string, data: any) => {
|
if (allProjects.length === 0) {
|
||||||
|
return { status: 404, message: "No projects found", token };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { status: 200, message: "Projects fetched successfully", data: allProjects, token };
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(error.message);
|
||||||
|
return { status: 500, message: "An error occurred while fetching projects", token };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createProject = async (userId: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
|
const { id } = await createEmptyProject(userId);
|
||||||
|
const bucket = await createBucket(id);
|
||||||
|
return { status: 200, message: "New project created successfully", data: { id, bucketName: bucket }, token };
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.log(error.msg);
|
console.log(error.message);
|
||||||
return { status: 500, message: "An error occurred while updating projects" }
|
return { status: 500, message: "An error occurred while creating projects", token }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const deleteProject = async (id: string) => {
|
export const updateProject = async (id: string, body: any, token: string) => {
|
||||||
try {
|
try {
|
||||||
|
// 1. Validate if project exists
|
||||||
|
const existingProject = await db.select().from(projects).where(eq(projects.id, id)).limit(1);
|
||||||
|
if (existingProject.length === 0) {
|
||||||
|
return { status: 404, message: "Project not found", token };
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
const { object, name, description, preview_url } = body;
|
||||||
console.log(error.msg);
|
// The preview_url will come from client-side as well, where before updating the project a project capture will be taken and uploaded to the bucket. than the url will be sent to the server.And rest of them are normal process
|
||||||
return { status: 500, message: "An error occurred while deleting projects" }
|
|
||||||
|
const updatedProject = await db.update(projects).set({
|
||||||
|
object,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
preview_url
|
||||||
|
}).where(eq(projects.id, id)).returning({
|
||||||
|
id: projects.id,
|
||||||
|
object: projects.object,
|
||||||
|
name: projects.name,
|
||||||
|
description: projects.description,
|
||||||
|
preview_url: projects.preview_url
|
||||||
|
});
|
||||||
|
|
||||||
|
if (updatedProject.length === 0) {
|
||||||
|
return { status: 500, message: "Failed to update the project", token };
|
||||||
|
}
|
||||||
|
return { status: 200, message: "Project updated successfully", data: updatedProject[0], token };
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log("Error updating project:", error.message || error.toString());
|
||||||
|
return { status: 500, message: "An error occurred while updating the project", token };
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const deleteProject = async (id: string, token: string) => {
|
||||||
|
try {
|
||||||
|
const deletedUploads = await db
|
||||||
|
.delete(uploads)
|
||||||
|
.where(eq(uploads.projectId, id))
|
||||||
|
.returning({ id: uploads.id });
|
||||||
|
|
||||||
|
if (deletedUploads.length >= 0) {
|
||||||
|
// Step 4: Delete the project
|
||||||
|
const deletedProject = await db
|
||||||
|
.delete(projects)
|
||||||
|
.where(eq(projects.id, id))
|
||||||
|
.returning({ id: projects.id });
|
||||||
|
|
||||||
|
if (deletedProject.length === 0) {
|
||||||
|
return { status: 404, message: "Project not found", token };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5: Delete the associated bucket
|
||||||
|
const bucketDeletionResult = await removeBucket(id);
|
||||||
|
|
||||||
|
if (bucketDeletionResult.status !== 200) {
|
||||||
|
return {
|
||||||
|
status: bucketDeletionResult.status,
|
||||||
|
message: `Error deleting bucket: ${bucketDeletionResult.message}`,
|
||||||
|
token
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { status: 200, message: "Project and associated bucket deleted successfully", token };
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log("Error in deleteProject:", error.message || error.toString());
|
||||||
|
return { status: 500, message: "An error occurred while deleting the project", token };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Elysia } from "elysia";
|
import { Elysia, t } from "elysia";
|
||||||
import { deleteProject, getAllProjects, getEachProjects, updateProject } from "./project.controller";
|
import { createProject, deleteProject, getAllProjects, getEachProjects, updateProject } from "./project.controller";
|
||||||
import { verifyAuth } from "../../middlewares/auth.middlewares";
|
import { verifyAuth } from "../../middlewares/auth.middlewares";
|
||||||
|
|
||||||
export const projectRoutes = new Elysia({
|
export const projectRoutes = new Elysia({
|
||||||
|
|
@ -8,17 +8,78 @@ export const projectRoutes = new Elysia({
|
||||||
detail: {
|
detail: {
|
||||||
description: "Routes for managing projects",
|
description: "Routes for managing projects",
|
||||||
}
|
}
|
||||||
}).derive(({ cookie }) => { verifyAuth(cookie) });
|
}).derive(async ({ cookie }) => {
|
||||||
|
const authData = await verifyAuth(cookie);
|
||||||
|
return { authData }; // Inject into context
|
||||||
|
});
|
||||||
|
|
||||||
projectRoutes.post("/add", (context) => {
|
projectRoutes.get("/each/:project_id", async ({ params: { project_id }, authData }) => {
|
||||||
console.log("this is from project route/add", context);
|
if (authData.status !== 200)
|
||||||
})
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData.token;
|
||||||
|
const response = await getEachProjects(project_id, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({
|
||||||
|
project_id: t.String()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
projectRoutes.get("/:id", ({ params }) => getEachProjects(params.id));
|
projectRoutes.get("/", async ({ authData }: any) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const userId = authData.userId;
|
||||||
|
const token = authData.token;
|
||||||
|
const response = await getAllProjects(userId, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
projectRoutes.get("/", () => getAllProjects());
|
projectRoutes.post("/create", async ({ authData }: any) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const userId = authData.userId;
|
||||||
|
const token = authData.token;
|
||||||
|
const response = await createProject(userId, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
projectRoutes.put("/update/:id", ({ request, params }) => updateProject(params.id, request.body));
|
projectRoutes.put("/update/:project_id", async ({ body, params: { project_id }, authData }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData.token;
|
||||||
|
const response = await updateProject(project_id, body, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({
|
||||||
|
project_id: t.String()
|
||||||
|
}),
|
||||||
|
body: t.Object({
|
||||||
|
object: t.Record(t.String(), t.Any()), // Allows any JSON object
|
||||||
|
name: t.String(),
|
||||||
|
description: t.String(),
|
||||||
|
preview_url: t.String(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
projectRoutes.delete("/delete/:id", ({ params }) => deleteProject(params.id));
|
projectRoutes.delete("/delete/:project_id", async ({ params: { project_id }, authData }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData.token;
|
||||||
|
const response = await deleteProject(project_id, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({
|
||||||
|
project_id: t.String()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,104 +1,106 @@
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "../../db";
|
import { db } from "../../db";
|
||||||
import { uploads } from "../../db/schema";
|
import { projects, uploads } from "../../db/schema";
|
||||||
import { createEmptyProject } from "../../helper/projects/createProject";
|
|
||||||
import { createBucket } from "../../helper/upload/createBucket";
|
|
||||||
import { uploadToMinio } from "../../helper/upload/uploadToMinio";
|
import { uploadToMinio } from "../../helper/upload/uploadToMinio";
|
||||||
import { removeFromMinio } from "../../helper/upload/removeFromMinio";
|
import { removeFromMinio } from "../../helper/upload/removeFromMinio";
|
||||||
|
|
||||||
export const uploadPhoto = async (req: Request) => {
|
export const uploadPhoto = async (file: File, project_id: string, userId: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
// Use the formData API to extract the data from the request
|
// Validate userId
|
||||||
const formData = await req.formData();
|
if (!userId || typeof userId !== "string") {
|
||||||
|
return { status: 400, message: "Invalid user ID", token };
|
||||||
const projectId = formData.get("id");
|
|
||||||
const userId = formData.get("userId");
|
|
||||||
const file = formData.get("file");
|
|
||||||
|
|
||||||
// Validate the file input
|
|
||||||
if (!file || !(file instanceof File)) {
|
|
||||||
throw new Error("Invalid or missing file in form data");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId) {
|
// Validate projectId
|
||||||
if (projectId) {
|
if (!project_id || typeof project_id !== "string") {
|
||||||
const urlLink = await uploadToMinio(file, projectId, file.name);
|
return { status: 400, message: "Invalid project ID", token };
|
||||||
|
}
|
||||||
|
|
||||||
const saveFile = await db
|
// Validate file input
|
||||||
.insert(uploads)
|
if (!file || !(file instanceof File) || !file.name) {
|
||||||
.values({ filename: file.name, url: urlLink?.url, projectId })
|
return { status: 400, message: "Invalid or missing file", token };
|
||||||
.returning();
|
}
|
||||||
|
const findProject = await db.select().from(projects).where(eq(projects.id, project_id));
|
||||||
|
|
||||||
return { status: 200, data: { msg: "File uploaded successfully", data: saveFile } };
|
if (findProject.length > 0) {
|
||||||
} else {
|
// Extract file extension (e.g., ".jpg", ".png")
|
||||||
|
const fileExtension = file.name.substring(file.name.lastIndexOf("."));
|
||||||
|
|
||||||
const newProjectId = await createEmptyProject(userId.toString());
|
// Generate a unique filename using the timestamp
|
||||||
const bucket = await createBucket(newProjectId?.id);
|
const timestamp = Date.now(); // Current timestamp in milliseconds
|
||||||
const urlLink = await uploadToMinio(file, bucket, file.name);
|
const uniqueFileName = `${file.name.split(".")[0]}-${timestamp}${fileExtension}`;
|
||||||
|
|
||||||
const saveFile = await db
|
// Upload file to MinIO with the unique filename
|
||||||
.insert(uploads)
|
const urlLink = await uploadToMinio(file, project_id, uniqueFileName);
|
||||||
.values({ filename: file.name, url: urlLink?.url, projectId: newProjectId?.id })
|
if (!urlLink || !urlLink.url) {
|
||||||
.returning();
|
return { status: 500, message: "File upload failed", token };
|
||||||
|
|
||||||
return { status: 200, data: { msg: "New project created and file uploaded successfully", data: saveFile } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
// Save file info in DB with modified filename
|
||||||
return { status: 404, message: "User not found" };
|
const saveFile = await db.insert(uploads).values({
|
||||||
|
filename: uniqueFileName,
|
||||||
|
url: urlLink.url,
|
||||||
|
projectId: project_id,
|
||||||
|
}).returning();
|
||||||
|
|
||||||
|
return { status: 200, message: "File uploaded successfully", data: saveFile, token };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
else {
|
||||||
|
return { status: 404, message: "No projects found with this project id", token }
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
console.error("Error processing file:", error);
|
console.error("Error processing file:", error);
|
||||||
return { status: 500, message: "An error occurred while uploading the photo" };
|
return { status: 500, message: "An error occurred while uploading the photo", token };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deletePhoto = async (id: string) => {
|
export const deletePhoto = async (url: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
if (!id) {
|
if (!url) {
|
||||||
throw new Error("Invalid or missing file ID");
|
return { status: 404, message: "File url is missing", token }
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteFile = await db
|
const deleteFile = await db
|
||||||
.delete(uploads)
|
.delete(uploads)
|
||||||
.where(eq(uploads.id, id))
|
.where(eq(uploads.url, url))
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
// Ensure there's a file to delete
|
// Ensure there's a file to delete
|
||||||
if (!deleteFile || deleteFile.length === 0) {
|
if (!deleteFile || deleteFile.length === 0) {
|
||||||
throw new Error("File not found or already deleted");
|
return { status: 404, message: "File not found", token };
|
||||||
}
|
}
|
||||||
|
|
||||||
const { projectId, filename } = deleteFile[0];
|
const { projectId, filename } = deleteFile[0];
|
||||||
|
|
||||||
// Ensure projectId and filename are valid
|
// Ensure projectId and filename are valid
|
||||||
if (!projectId || !filename) {
|
if (!projectId || !filename) {
|
||||||
throw new Error("Project ID or filename is missing");
|
return { status: 400, message: "Invalid project ID or filename", token };
|
||||||
}
|
}
|
||||||
|
|
||||||
const minioRemove = await removeFromMinio(projectId, filename);
|
const minioRemove = await removeFromMinio(projectId, filename);
|
||||||
|
|
||||||
return { status: 200, message: minioRemove.msg };
|
return { status: 200, message: minioRemove.msg, token };
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("Error processing file:", error);
|
console.error("Error processing file:", error);
|
||||||
return { status: 500, message: `An error occurred while deleting the photo: ${error.message}` };
|
return { status: 500, message: `An error occurred while deleting the photo: ${error.message}`, token };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAllPhoto = async (id: string) => {
|
export const getAllPhoto = async (id: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
// project id
|
// project id
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error("Invalid or missing project ID");
|
return { status: 404, message: "Project ID is missing", token }
|
||||||
}
|
}
|
||||||
const getAllPhoto = await db.select().from(uploads).where(eq(uploads.projectId, id));
|
const getAllPhoto = await db.select().from(uploads).where(eq(uploads.projectId, id));
|
||||||
if (getAllPhoto.length === 0) {
|
if (getAllPhoto.length === 0) {
|
||||||
return { status: 200, data: { msg: "No photos found for the given project ID", data: [] } }
|
return { status: 200, message: "No photos found for the given project ID", data: [], token }
|
||||||
}
|
}
|
||||||
return { status: 200, data: { msg: "Photos retrieved successfully", data: getAllPhoto } };
|
return { status: 200, message: "All photos retrieved successfully", data: getAllPhoto, token };
|
||||||
} catch (error) {
|
|
||||||
|
} catch (error: any) {
|
||||||
console.log(`Error getting photos: ${error.message}`);
|
console.log(`Error getting photos: ${error.message}`);
|
||||||
return { status: 500, message: "An error occurred while getting the photos" }
|
return { status: 500, message: "An error occurred while getting the photos", token }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Elysia } from "elysia";
|
import { Elysia, t } from "elysia";
|
||||||
import { deletePhoto, getAllPhoto, uploadPhoto } from "./upload.controller";
|
import { deletePhoto, getAllPhoto, uploadPhoto } from "./upload.controller";
|
||||||
|
import { verifyAuth } from "../../middlewares/auth.middlewares";
|
||||||
|
|
||||||
export const uploadRoutes = new Elysia({
|
export const uploadRoutes = new Elysia({
|
||||||
prefix: "/uploads",
|
prefix: "/uploads",
|
||||||
|
|
@ -7,10 +8,53 @@ export const uploadRoutes = new Elysia({
|
||||||
detail: {
|
detail: {
|
||||||
description: "Routes for uploading and managing photos",
|
description: "Routes for uploading and managing photos",
|
||||||
}
|
}
|
||||||
|
}).derive(async ({ cookie }) => {
|
||||||
|
const authData = await verifyAuth(cookie);
|
||||||
|
return { authData }; // Inject into context
|
||||||
});
|
});
|
||||||
|
|
||||||
uploadRoutes.post("/add", async ({ request }) => uploadPhoto(request));
|
uploadRoutes.post("/add", async ({ body, authData }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData?.token;
|
||||||
|
const user_id: String | any = authData?.userId;
|
||||||
|
const { id: project_id, file } = body;
|
||||||
|
const response = await uploadPhoto(file, project_id, user_id, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
body: t.Object({
|
||||||
|
file: t.File(),
|
||||||
|
id: t.String(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
uploadRoutes.delete("/delete/:id", async ({ params }) => deletePhoto(params.id));
|
uploadRoutes.delete("/delete", async ({ query, authData }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData?.token;
|
||||||
|
const { url } = query;
|
||||||
|
const response = await deletePhoto(url, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
query: t.Object({
|
||||||
|
url: t.String(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
uploadRoutes.get("/get/:id", async ({ params }) => getAllPhoto(params.id));
|
uploadRoutes.get("/getAll/:id", async ({ params: { id }, authData }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const token = authData?.token;
|
||||||
|
const response = await getAllPhoto(id, token);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
params: t.Object({
|
||||||
|
id: t.String()
|
||||||
|
})
|
||||||
|
});
|
||||||
11
src/app.ts
11
src/app.ts
|
|
@ -5,9 +5,17 @@ import { ENV } from "./config/env";
|
||||||
import cors from "@elysiajs/cors";
|
import cors from "@elysiajs/cors";
|
||||||
import { api } from "./api";
|
import { api } from "./api";
|
||||||
|
|
||||||
|
const allowedOrigins = [
|
||||||
|
"http://localhost:5175",
|
||||||
|
"http://localhost:5173",
|
||||||
|
"https://your-production-site.com",
|
||||||
|
];
|
||||||
|
|
||||||
const app = new Elysia()
|
const app = new Elysia()
|
||||||
.use(cors({
|
.use(cors({
|
||||||
origin: "http://localhost:5175",
|
origin: allowedOrigins,
|
||||||
|
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
||||||
|
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "Accept", "Origin", "Access-Control-Allow-Origin"],
|
||||||
credentials: true,
|
credentials: true,
|
||||||
}))
|
}))
|
||||||
.use(swagger({
|
.use(swagger({
|
||||||
|
|
@ -33,6 +41,7 @@ const app = new Elysia()
|
||||||
.onError(({ code, error }) => {
|
.onError(({ code, error }) => {
|
||||||
if (code === 'NOT_FOUND')
|
if (code === 'NOT_FOUND')
|
||||||
return 'Not Found :(';
|
return 'Not Found :(';
|
||||||
|
console.log("hello from app.ts under error");
|
||||||
console.error(error)
|
console.error(error)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { json, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
import { boolean, json, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
export const users = pgTable("users", {
|
export const users = pgTable("users", {
|
||||||
id: text("user_id").primaryKey().notNull(),
|
id: text("user_id").primaryKey().notNull(),
|
||||||
|
|
@ -17,6 +17,8 @@ export const projects = pgTable("projects", {
|
||||||
object: json(),
|
object: json(),
|
||||||
name: text("name"),
|
name: text("name"),
|
||||||
description: text("description"),
|
description: text("description"),
|
||||||
|
is_public: boolean("is_active").notNull().default(false),
|
||||||
|
preview_url: text("preview_url"),
|
||||||
created_at: timestamp("created_at").defaultNow(),
|
created_at: timestamp("created_at").defaultNow(),
|
||||||
updated_at: timestamp("updated_at").defaultNow(),
|
updated_at: timestamp("updated_at").defaultNow(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,12 @@ type User = {
|
||||||
export const checkUserInDB = async (id: string) => {
|
export const checkUserInDB = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
const user = await db.select().from(users).where(eq(users.id, id));
|
const user = await db.select().from(users).where(eq(users.id, id));
|
||||||
return { status: 200, found: user?.length > 0 };
|
if (user.length > 0) {
|
||||||
|
return { found: true, id: user[0]?.id };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { found: false };
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error in checkUserInDB:", error.message || error.toString());
|
console.error("Error in checkUserInDB:", error.message || error.toString());
|
||||||
return { status: 500, message: `An error occurred while checking the user in DB` };
|
return { status: 500, message: `An error occurred while checking the user in DB` };
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ export const createEmptyProject = async (userId: string): Promise<{ id: string }
|
||||||
object: {}, // Empty object as default
|
object: {}, // Empty object as default
|
||||||
name: "", // Empty name
|
name: "", // Empty name
|
||||||
description: "", // Empty description
|
description: "", // Empty description
|
||||||
|
preview_url: "", // Empty preview URL
|
||||||
|
is_public: false, // Add default value for is_public
|
||||||
})
|
})
|
||||||
.returning({ id: projects.id }); // Returning the ID of the created project
|
.returning({ id: projects.id }); // Returning the ID of the created project
|
||||||
// Return the newly created project's ID
|
// Return the newly created project's ID
|
||||||
|
|
@ -19,4 +21,4 @@ export const createEmptyProject = async (userId: string): Promise<{ id: string }
|
||||||
console.error("Error creating an empty project:", error);
|
console.error("Error creating an empty project:", error);
|
||||||
throw new Error("Failed to create an empty project");
|
throw new Error("Failed to create an empty project");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,8 @@ export const createBucket = async (bucketName: string) => {
|
||||||
} else {
|
} else {
|
||||||
return bucketName; // Return the bucket name if it already exists
|
return bucketName; // Return the bucket name if it already exists
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("Error creating or configuring bucket:", error);
|
console.error("Error creating or configuring bucket:", error);
|
||||||
|
|
||||||
// Optionally rethrow the error with additional context
|
// Optionally rethrow the error with additional context
|
||||||
throw new Error(`Error creating bucket "${bucketName}": ${error.message}`);
|
throw new Error(`Error creating bucket "${bucketName}": ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
src/helper/upload/removeBucket.ts
Normal file
30
src/helper/upload/removeBucket.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { minioClient } from "../../config/minioClient";
|
||||||
|
|
||||||
|
export const removeBucket = async (bucketName: string) => {
|
||||||
|
try {
|
||||||
|
// Check if the bucket exists before proceeding
|
||||||
|
const bucketExists = await minioClient.bucketExists(bucketName);
|
||||||
|
if (!bucketExists) {
|
||||||
|
return { status: 404, message: `Bucket ${bucketName} does not exist` };
|
||||||
|
}
|
||||||
|
|
||||||
|
// List objects in the bucket, which returns a stream
|
||||||
|
const objects = minioClient.listObjects(bucketName);
|
||||||
|
|
||||||
|
// Iterate over the stream of objects using 'for await...of'
|
||||||
|
for await (const obj of objects) {
|
||||||
|
await minioClient.removeObject(bucketName, obj.name);
|
||||||
|
console.log(`Removed object: ${obj.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now remove the bucket after clearing all objects
|
||||||
|
await minioClient.removeBucket(bucketName);
|
||||||
|
|
||||||
|
return { status: 200, message: `Bucket ${bucketName} and its data removed successfully` };
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(`Error removing bucket ${bucketName}: ${error.message}`);
|
||||||
|
return { status: 500, message: `Error removing bucket ${bucketName}: ${error.message}` };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ export const removeFromMinio = async (bucketName: string, objectName: string): P
|
||||||
// Remove the object from MinIO
|
// Remove the object from MinIO
|
||||||
await minioClient.removeObject(bucketName, objectName);
|
await minioClient.removeObject(bucketName, objectName);
|
||||||
return { msg: `Successfully removed ${objectName}` };
|
return { msg: `Successfully removed ${objectName}` };
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("Error removing object from MinIO:", error);
|
console.error("Error removing object from MinIO:", error);
|
||||||
throw new Error(`Failed to remove ${objectName} from bucket ${bucketName}: ${error.message}`);
|
throw new Error(`Failed to remove ${objectName} from bucket ${bucketName}: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,8 @@ export const uploadToMinio = async (file: File, bucketName: string, objectName:
|
||||||
|
|
||||||
return { url: publicUrl };
|
return { url: publicUrl };
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("Error uploading file to MinIO:", error);
|
console.error("Error uploading file to MinIO:", error);
|
||||||
|
|
||||||
throw new Error(`Error uploading file: ${error.message}`);
|
throw new Error(`Error uploading file: ${error.message}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -8,41 +8,49 @@ import { eq } from "drizzle-orm";
|
||||||
export const verifyAuth = async (cookie: any) => {
|
export const verifyAuth = async (cookie: any) => {
|
||||||
try {
|
try {
|
||||||
const access_cookie = cookie?.access_token?.value;
|
const access_cookie = cookie?.access_token?.value;
|
||||||
|
|
||||||
const refresh_cookie = cookie?.refresh_token?.value;
|
const refresh_cookie = cookie?.refresh_token?.value;
|
||||||
|
|
||||||
console.log("this is access cookie", access_cookie);
|
if (access_cookie !== undefined) {
|
||||||
console.log("this is refresh cookie", refresh_cookie);
|
|
||||||
|
|
||||||
if (access_cookie) {
|
|
||||||
// Verify JWT token
|
// Verify JWT token
|
||||||
const verify_cookie = jwt.verify(access_cookie, ENV.JWT_ACCESS_TOKEN_SECRET);
|
const verify_cookie = jwt.verify(access_cookie, ENV.JWT_ACCESS_TOKEN_SECRET);
|
||||||
// Query the user from the database
|
// Query the user from the database
|
||||||
const findUser = await db.select().from(users).where(eq(users.id, verify_cookie.userId));
|
const findUser = await db.select().from(users).where(eq(users.id, verify_cookie.userId));
|
||||||
if (findUser.length > 0) {
|
if (findUser.length > 0) {
|
||||||
return { status: 200, message: "Token verified successfully" };
|
return { status: 200, message: "Token verified successfully", token: access_cookie, userId: findUser[0].id };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw { status: 401, message: "Unauthorized" };
|
return { status: 401, message: "Unauthorized" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!access_cookie && refresh_cookie) {
|
else if (access_cookie === undefined && refresh_cookie) {
|
||||||
// Verify JWT token
|
// Verify JWT token
|
||||||
const verify_cookie = jwt.verify(refresh_cookie, ENV.JWT_REFRESH_TOKEN_SECRET);
|
const verify_cookie = jwt.verify(refresh_cookie, ENV.JWT_REFRESH_TOKEN_SECRET);
|
||||||
|
|
||||||
// Query the user from the database
|
// Query the user from the database
|
||||||
const findUser = await db.select().from(users).where(eq(users.id, verify_cookie.userId));
|
const findUser = await db.select().from(users).where(eq(users.id, verify_cookie.userId));
|
||||||
if (findUser.length === 0 || findUser[0].refresh_token !== refresh_cookie) {
|
if (findUser.length === 0 || findUser[0].refresh_token !== refresh_cookie) {
|
||||||
throw { status: 401, message: "Unauthorized" };
|
return { status: 401, message: "Unauthorized" };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return { status: 200, message: "Token verified successfully" };
|
// generate access token
|
||||||
|
const accessToken = jwt.sign({ userId: verify_cookie?.userId }, ENV.JWT_ACCESS_TOKEN_SECRET, { expiresIn: '3h' });
|
||||||
|
|
||||||
|
cookie.access_token.set({
|
||||||
|
value: accessToken,
|
||||||
|
httpOnly: true,
|
||||||
|
secure: true, // Set to true in production
|
||||||
|
sameSite: 'none', // Adjust based on your needs
|
||||||
|
path: "/",
|
||||||
|
maxAge: 3 * 60 * 60, // 3 hours in seconds
|
||||||
|
});
|
||||||
|
|
||||||
|
return { status: 200, message: "Token verified successfully", token: accessToken, userId: findUser[0].id };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
throw { status: 401, message: "No token provided" };
|
return { status: 401, message: "Unauthorized" };
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue