This commit is contained in:
2025-06-19 14:03:04 +05:00
parent daca480edf
commit 971cd8ff8e
30 changed files with 148 additions and 139 deletions
-6
View File
@@ -11,12 +11,6 @@ const authController = new Elysia({ prefix: "/auth" })
password: t.String({ minLength: 1 }),
}),
})
// .post("/register", async ({}) => {}, {
// body: t.Object({
// username: t.String({ minLength: 1 }),
// password: t.String({ minLength: 1 }),
// }),
// })
.use(authMiddleware)
.get("/me", async ({ auth }) => await me(auth))
.get(
+4 -4
View File
@@ -7,8 +7,8 @@ export const commentsController = new Elysia({ prefix: "comments" })
.use(authMiddleware)
.get(
"/:sessionId",
async ({ params: { sessionId }, auth: { userId } }) =>
await getComments(sessionId, userId),
async ({ params: { sessionId }, auth: { managerId } }) =>
await getComments(sessionId, managerId),
{
params: t.Object({
sessionId: t.String(),
@@ -17,8 +17,8 @@ export const commentsController = new Elysia({ prefix: "comments" })
)
.post(
"/",
async ({ auth: { userId }, body: { text, sessionId } }) =>
await createComment({ userId, text, sessionId }),
async ({ auth: { managerId }, body: { text, sessionId } }) =>
await createComment({ managerId, text, sessionId }),
{
body: t.Object({
text: t.String(),
@@ -2,8 +2,8 @@ import Elysia from "elysia";
import authMiddleware from "../middlewares/auth";
import getManagers from "../services/users/getManagers";
const usersController = new Elysia({ prefix: "/users" })
const managersController = new Elysia({ prefix: "/users" })
.use(authMiddleware)
.get("/", ({ auth }) => getManagers(auth));
export default usersController;
export default managersController;
+4 -4
View File
@@ -22,8 +22,8 @@ const sessionsController = new Elysia({ prefix: "/sessions" })
t.Literal("ended"),
]),
clientSearch: t.String(),
appIds: t.Array(t.String()),
ownerIds: t.Array(t.String()),
appIds: t.ArrayString(),
managerIds: t.ArrayString(),
})
),
})
@@ -33,7 +33,7 @@ const sessionsController = new Elysia({ prefix: "/sessions" })
{
query: t.Partial(
t.Object({
ownerIds: t.ArrayString(),
managerIds: t.ArrayString(),
appIds: t.ArrayString(),
clientSearch: t.String(),
})
@@ -48,7 +48,7 @@ const sessionsController = new Elysia({ prefix: "/sessions" })
client: true,
app: true,
server: true,
owner: {
manager: {
columns: {
password: false,
fullname: true,
+36 -5
View File
@@ -1,17 +1,20 @@
import { pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
import {
pgTable,
primaryKey,
timestamp,
uuid,
varchar,
} from "drizzle-orm/pg-core";
import { companiesTable } from "./companies";
import { relations } from "drizzle-orm";
import { sessionsTable } from "./sessions";
import { usersTable } from "./users";
import { managersTable } from "./managers";
export const clientsTable = pgTable("clients", {
id: uuid("id").defaultRandom().primaryKey(),
name: varchar("name").notNull(),
phone: varchar("phone", { length: 11 }).unique().notNull(),
email: varchar("email"),
ownerId: uuid("owner_id")
.notNull()
.references(() => usersTable.id, { onDelete: "cascade" }),
companyId: uuid("company_id")
.notNull()
.references(() => companiesTable.id, { onDelete: "cascade" }),
@@ -30,4 +33,32 @@ export const clientsRelations = relations(clientsTable, ({ one, many }) => ({
references: [companiesTable.id],
}),
sessions: many(sessionsTable),
managers: many(clientsToManagers),
}));
export const clientsToManagers = pgTable(
"clients_to_managers",
{
clientId: uuid("client_id")
.notNull()
.references(() => clientsTable.id, { onDelete: "cascade" }),
managerId: uuid("manager_id")
.notNull()
.references(() => managersTable.id, { onDelete: "cascade" }),
},
(t) => [primaryKey({ columns: [t.clientId, t.managerId] })]
);
export const clientsToManagersRelations = relations(
clientsToManagers,
({ one }) => ({
client: one(clientsTable, {
fields: [clientsToManagers.clientId],
references: [clientsTable.id],
}),
manager: one(managersTable, {
fields: [clientsToManagers.managerId],
references: [managersTable.id],
}),
})
);
+6 -6
View File
@@ -1,5 +1,5 @@
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { usersTable } from "./users";
import { managersTable } from "./managers";
import { sessionsTable } from "./sessions";
import { relations } from "drizzle-orm";
@@ -8,18 +8,18 @@ export const commentsTable = pgTable("comments", {
text: text("text").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
ownerId: uuid("owner_id")
managerId: uuid("manager_id")
.notNull()
.references(() => usersTable.id, { onDelete: "cascade" }),
.references(() => managersTable.id, { onDelete: "cascade" }),
sessionId: uuid("session_id")
.notNull()
.references(() => sessionsTable.id, { onDelete: "cascade" }),
});
export const commentsRelations = relations(commentsTable, ({ one }) => ({
owner: one(usersTable, {
fields: [commentsTable.ownerId],
references: [usersTable.id],
manager: one(managersTable, {
fields: [commentsTable.managerId],
references: [managersTable.id],
}),
session: one(sessionsTable, {
fields: [commentsTable.sessionId],
+2 -2
View File
@@ -1,6 +1,6 @@
import { relations } from "drizzle-orm";
import { pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
import { usersTable } from "./users";
import { managersTable } from "./managers";
import { appsTable } from "./apps";
import { serversTable } from "./servers";
@@ -17,7 +17,7 @@ export const companiesTable = pgTable("companies", {
});
export const companiesRelations = relations(companiesTable, ({ many }) => ({
users: many(usersTable),
managers: many(managersTable),
servers: many(serversTable),
apps: many(appsTable),
}));
+1 -1
View File
@@ -1,4 +1,4 @@
export * from "./users";
export * from "./managers";
export * from "./tokens";
export * from "./companies";
export * from "./servers";
@@ -3,8 +3,9 @@ import { pgTable, text, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
import { tokensTable } from "./tokens";
import { companiesTable } from "./companies";
import { commentsTable } from "./comments";
import { clientsToManagers } from "./clients";
export const usersTable = pgTable("users", {
export const managersTable = pgTable("managers", {
id: uuid("id").defaultRandom().primaryKey(),
fullname: text("fullname"),
email: varchar("email").unique().notNull(),
@@ -21,11 +22,12 @@ export const usersTable = pgTable("users", {
.$onUpdate(() => new Date()),
});
export const usersRelations = relations(usersTable, ({ one, many }) => ({
export const managersRelations = relations(managersTable, ({ one, many }) => ({
company: one(companiesTable, {
fields: [usersTable.companyId],
fields: [managersTable.companyId],
references: [companiesTable.id],
}),
tokens: many(tokensTable),
comments: many(commentsTable),
clients: many(clientsToManagers),
}));
+6 -6
View File
@@ -7,7 +7,7 @@ import {
integer,
} from "drizzle-orm/pg-core";
import { companiesTable } from "./companies";
import { usersTable } from "./users";
import { managersTable } from "./managers";
import { relations } from "drizzle-orm";
import { serversTable } from "./servers";
import { clientsTable } from "./clients";
@@ -28,9 +28,9 @@ export const sessionsTable = pgTable(
appId: uuid("app_id")
.notNull()
.references(() => appsTable.id, { onDelete: "cascade" }),
ownerId: uuid("owner_id")
managerId: uuid("manager_id")
.notNull()
.references(() => usersTable.id, { onDelete: "cascade" }),
.references(() => managersTable.id, { onDelete: "cascade" }),
serverId: uuid("server_id")
.notNull()
.references(() => serversTable.id, { onDelete: "cascade" }),
@@ -56,9 +56,9 @@ export const sessionsTable = pgTable(
);
export const sessionsRelations = relations(sessionsTable, ({ one, many }) => ({
owner: one(usersTable, {
fields: [sessionsTable.ownerId],
references: [usersTable.id],
manager: one(managersTable, {
fields: [sessionsTable.managerId],
references: [managersTable.id],
}),
server: one(serversTable, {
fields: [sessionsTable.serverId],
+6 -6
View File
@@ -1,13 +1,13 @@
import { relations } from "drizzle-orm";
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { usersTable } from "./users";
import { managersTable } from "./managers";
export const tokensTable = pgTable("tokens", {
id: uuid("id").defaultRandom().primaryKey(),
token: text("token").notNull(),
userId: uuid("user_id")
managerId: uuid("manager_id")
.notNull()
.references(() => usersTable.id, { onDelete: "cascade" }),
.references(() => managersTable.id, { onDelete: "cascade" }),
createdAt: timestamp("created_at", { withTimezone: true })
.notNull()
.defaultNow(),
@@ -18,8 +18,8 @@ export const tokensTable = pgTable("tokens", {
});
export const tokensRelations = relations(tokensTable, ({ one }) => ({
user: one(usersTable, {
fields: [tokensTable.userId],
references: [usersTable.id],
manager: one(managersTable, {
fields: [tokensTable.managerId],
references: [managersTable.id],
}),
}));
+2 -2
View File
@@ -2,7 +2,7 @@ import { differenceInSeconds } from "date-fns";
import { Elysia } from "elysia";
import cors from "@elysiajs/cors";
import authController from "./controllers/authController";
import usersController from "./controllers/usersController";
import managersController from "./controllers/managersController";
import sessionsController from "./controllers/sessionsController";
import serversController from "./controllers/serversController";
import appsController from "./controllers/appsController";
@@ -23,7 +23,7 @@ app.use(
})
);
app.use(authController);
app.use(usersController);
app.use(managersController);
app.use(serversController);
app.use(sessionsController);
app.use(appsController);
+10 -10
View File
@@ -3,10 +3,10 @@ import Elysia, { status } from "elysia";
import { jwtVerify } from "jose";
import { createHmac } from "crypto";
import db from "../db";
import { usersTable } from "../db/schema";
import { managersTable } from "../db/schema";
export type AuthContext = {
userId: string;
managerId: string;
companyId: string;
};
@@ -25,21 +25,21 @@ const authMiddleware = new Elysia()
try {
const {
payload: { userId },
} = await jwtVerify<{ userId: string }>(accessToken, secret);
payload: { managerId },
} = await jwtVerify<{ managerId: string }>(accessToken, secret);
const user = await db.query.usersTable.findFirst({
where: eq(usersTable.id, userId),
const manager = await db.query.managersTable.findFirst({
where: eq(managersTable.id, managerId),
});
if (!user) {
if (!manager) {
return status(401);
}
return {
auth: {
userId: user.id,
companyId: user.companyId,
managerId: manager.id,
companyId: manager.companyId,
},
};
} catch (error) {
@@ -63,7 +63,7 @@ const authMiddleware = new Elysia()
return {
auth: {
userId: "hmac-user",
managerId: "hmac-manager",
companyId: "hmac-company",
},
};
+1 -1
View File
@@ -12,7 +12,7 @@ export default async function createApp(
companyId: string;
}
) {
if (auth.userId !== "hmac-user") {
if (auth.managerId !== "hmac-manager") {
return status(403, {
error: "Forbidden",
});
+6 -6
View File
@@ -1,6 +1,6 @@
import { eq } from "drizzle-orm";
import db from "../../db";
import { tokensTable, usersTable } from "../../db/schema";
import { tokensTable, managersTable } from "../../db/schema";
import { status } from "elysia";
import { generateToken } from "../../utils/generateToken";
@@ -12,18 +12,18 @@ export default async function login({
password: string;
}) {
try {
const user = await db.query.usersTable.findFirst({
where: eq(usersTable.email, email),
const manager = await db.query.managersTable.findFirst({
where: eq(managersTable.email, email),
});
if (!user || !Bun.password.verifySync(password, user.password))
if (!manager || !Bun.password.verifySync(password, manager.password))
return status(401, { error: "Wrong credentials" });
const token = await generateToken(user.id);
const token = await generateToken(manager.id);
await db.insert(tokensTable).values({
token,
userId: user.id,
managerId: manager.id,
});
return {
+4 -4
View File
@@ -1,13 +1,13 @@
import { eq } from "drizzle-orm";
import db from "../../db";
import { usersTable } from "../../db/schema";
import { managersTable } from "../../db/schema";
import { status } from "elysia";
import type { AuthContext } from "../../middlewares/auth";
export default async function me(auth: AuthContext) {
try {
const user = await db.query.usersTable.findFirst({
where: eq(usersTable.id, auth.userId),
const manager = await db.query.managersTable.findFirst({
where: eq(managersTable.id, auth.managerId),
columns: {
id: true,
email: true,
@@ -15,7 +15,7 @@ export default async function me(auth: AuthContext) {
},
});
return user;
return manager;
} catch (error) {
console.log((error as Error).message);
return status(500, "Internal Server Error");
-26
View File
@@ -1,26 +0,0 @@
// import { error } from "elysia";
// import { eq } from "drizzle-orm";
// import db from "../../db";
// import { usersTable } from "../../db/schema";
// export default async function register(payload: {
// username: string;
// password: string;
// companyId: string;
// }) {
// const { companyId, username } = payload;
// try {
// const candidate = await db.query.usersTable.findFirst({
// where: eq(usersTable.username, username),
// });
// if (candidate) return error(400, "user already exists");
// const password = Bun.hash(payload.password);
// const user = await db
// .insert(usersTable)
// .values({ companyId, username, password });
// } catch (error) {}
// }
+21 -15
View File
@@ -1,10 +1,10 @@
import db from "../../db";
import { clientsTable } from "../../db/schema";
import { clientsTable, clientsToManagers } from "../../db/schema";
import { status } from "elysia";
async function createClient(
auth: {
userId: string;
managerId: string;
companyId: string;
},
body: {
@@ -15,20 +15,26 @@ async function createClient(
) {
try {
// Create new client
const [newClient] = await db
.insert(clientsTable)
.values({
...body,
ownerId: auth.userId,
companyId: auth.companyId,
})
.onConflictDoUpdate({
target: [clientsTable.phone],
set: { ...body, ownerId: auth.userId, companyId: auth.companyId },
})
.returning();
return await db.transaction(async (tx) => {
const [newClient] = await tx
.insert(clientsTable)
.values({
...body,
companyId: auth.companyId,
})
.onConflictDoUpdate({
target: [clientsTable.phone],
set: { ...body, companyId: auth.companyId },
})
.returning();
return newClient;
await tx.insert(clientsToManagers).values({
clientId: newClient.id,
managerId: auth.managerId,
});
return newClient;
});
} catch (error) {
console.log((error as Error).message);
return status(500, "Internal Server Error");
+5 -4
View File
@@ -5,10 +5,11 @@ import { status } from "elysia";
async function getByPhone(phone: string) {
try {
const user = await db.query.clientsTable.findFirst({
where: eq(clientsTable.phone, phone),
});
return user || status(404, "Not Found");
return (
(await db.query.clientsTable.findFirst({
where: eq(clientsTable.phone, phone),
})) || status(404, "Not Found")
);
} catch (error) {
console.log((error as Error).message);
return status(500, "Internal Server Error");
+3 -2
View File
@@ -26,11 +26,12 @@ async function getClients({
),
limit,
with: {
managers: { with: { manager: { columns: { password: false } } } },
sessions: {
with: {
owner: { columns: { password: false } },
manager: { columns: { password: false } },
app: true,
comments: { with: { owner: { columns: { password: false } } } },
comments: { with: { manager: { columns: { password: false } } } },
},
},
},
+3 -3
View File
@@ -4,11 +4,11 @@ import { commentsTable } from "../../db/schema";
export async function createComment({
sessionId,
userId,
managerId,
text,
}: {
sessionId: string;
userId: string;
managerId: string;
text: string;
}) {
try {
@@ -16,7 +16,7 @@ export async function createComment({
.insert(commentsTable)
.values({
sessionId,
ownerId: userId,
managerId,
text,
})
.returning();
+3 -3
View File
@@ -3,15 +3,15 @@ import { and, desc, eq } from "drizzle-orm";
import db from "../../db";
import { commentsTable } from "../../db/schema";
export async function getComments(sessionId: string, userId: string) {
export async function getComments(sessionId: string, managerId: string) {
try {
const comments = await db.query.commentsTable.findMany({
where: and(
eq(commentsTable.sessionId, sessionId),
eq(commentsTable.ownerId, userId)
eq(commentsTable.managerId, managerId)
),
with: {
owner: {
manager: {
columns: {
fullname: true,
id: true,
+1 -1
View File
@@ -13,7 +13,7 @@ export default async function createServer(
companyId: string;
}
) {
if (auth.userId !== "hmac-user") return status(403, "Forbidden");
if (auth.managerId !== "hmac-manager") return status(403, "Forbidden");
try {
const server = await db
+1 -1
View File
@@ -45,7 +45,7 @@ export default async function getServers(
},
},
server: true,
owner: {
manager: {
columns: {
fullname: true,
},
+1 -1
View File
@@ -1,7 +1,7 @@
import { status } from "elysia";
import { eq } from "drizzle-orm";
import db from "../../db";
import { serversTable } from "../../db/schema/servers";
import { serversTable } from "../../db/schema";
async function updateServer({
params,
+2 -2
View File
@@ -5,7 +5,7 @@ import { status } from "elysia";
async function createSession(
auth: {
userId: string;
managerId: string;
companyId: string;
},
body: {
@@ -36,7 +36,7 @@ async function createSession(
.insert(sessionsTable)
.values({
...body,
ownerId: auth.userId,
managerId: auth.managerId,
companyId: auth.companyId,
})
.returning();
+3 -3
View File
@@ -4,12 +4,12 @@ import { and, count, eq, ilike, inArray } from "drizzle-orm";
import { clientsTable, sessionsTable } from "../../db/schema";
async function getCount({
ownerIds,
managerIds,
appIds,
clientSearch,
companyId,
}: {
ownerIds?: string[];
managerIds?: string[];
appIds?: string[];
clientSearch?: string;
companyId: string;
@@ -21,7 +21,7 @@ async function getCount({
.where(
and(
eq(sessionsTable.companyId, companyId),
ownerIds ? inArray(sessionsTable.ownerId, ownerIds) : undefined,
managerIds ? inArray(sessionsTable.managerId, managerIds) : undefined,
appIds ? inArray(sessionsTable.appId, appIds) : undefined,
clientSearch
? inArray(
+5 -5
View File
@@ -11,7 +11,7 @@ async function getSessions(
status?: "starting" | "started" | "restarting" | "ending" | "ended";
clientSearch?: string;
appIds?: string[];
ownerIds?: string[];
managerIds?: string[];
}
) {
try {
@@ -30,8 +30,8 @@ async function getSessions(
)
: undefined,
query.appIds ? inArray(sessionsTable.appId, query.appIds) : undefined,
query.ownerIds
? inArray(sessionsTable.ownerId, query.ownerIds)
query.managerIds
? inArray(sessionsTable.managerId, query.managerIds)
: undefined
),
with: {
@@ -40,14 +40,14 @@ async function getSessions(
server: true,
comments: {
with: {
owner: {
manager: {
columns: {
fullname: true,
},
},
},
},
owner: {
manager: {
columns: {
password: false,
fullname: true,
+3 -3
View File
@@ -1,13 +1,13 @@
import db from "../../db";
import type { AuthContext } from "../../middlewares/auth";
import { eq } from "drizzle-orm";
import { usersTable } from "../../db/schema";
import { managersTable } from "../../db/schema";
import { status } from "elysia";
async function getManagers(auth: AuthContext) {
try {
return await db.query.usersTable.findMany({
where: eq(usersTable.companyId, auth.companyId),
return await db.query.managersTable.findMany({
where: eq(managersTable.companyId, auth.companyId),
columns: {
id: true,
fullname: true,
+2 -2
View File
@@ -1,8 +1,8 @@
import { SignJWT } from "jose";
export async function generateToken(userId: string) {
export async function generateToken(managerId: string) {
return await new SignJWT({
userId,
managerId,
})
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(process.env.JWT_EXPIRATION)