Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions src/app/api/approveEmployees/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ import { db } from "../../../server/db/index";
import { users } from "../../../server/db/schema";
import { eq } from "drizzle-orm";
import { auth } from "@clerk/nextjs/server";
import * as console from "console";

type PostBody = {
employeeId: string;
}
import { validateRequestBody, EmployeeIdSchema } from "~/lib/validation";


export async function POST(request: Request) {
try {
// Validate request body first
const validation = await validateRequestBody(request, EmployeeIdSchema);
if (!validation.success) {
return validation.response;
}

const { userId } = await auth();

if (!userId) {
return NextResponse.json({
success: false,
message: "Unauthorized"
}, { status: 401 });
}
}

const [userInfo] = await db
.select()
Expand All @@ -38,20 +40,24 @@ export async function POST(request: Request) {
}, { status: 401 });
}

const { employeeId } = (await request.json()) as PostBody;
// Use validated data
const { employeeId } = validation.data;

await db
.update(users)
.set({
status: "verified"
})
.where(eq(users.id, Number(employeeId)));
.where(eq(users.id, employeeId));

return NextResponse.json({ status: 200 });
return NextResponse.json({
success: true,
message: "Employee approved successfully"
});
} catch (error: unknown) {
console.error("Error fetching documents:", error);
console.error("Error approving employee:", error);
return NextResponse.json(
{ error: "Unable to fetch documents" },
{ success: false, error: "Failed to approve employee" },
{ status: 500 }
);
}
Expand Down
74 changes: 40 additions & 34 deletions src/app/api/removeEmployees/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,55 @@ import { NextResponse } from "next/server";
import { db } from "../../../server/db/index";
import { users } from "../../../server/db/schema";
import { eq } from "drizzle-orm";
import * as console from "console";
import { auth } from "@clerk/nextjs/server";

type PostBody = {
employeeId: string;
}
import { validateRequestBody, EmployeeIdSchema } from "~/lib/validation";

export async function POST(request: Request) {
const { userId } = await auth();
if (!userId) {
return NextResponse.json({
success: false,
message: "Unauthorized"
}, { status: 401 });
}
try {
// Validate request body first
const validation = await validateRequestBody(request, EmployeeIdSchema);
if (!validation.success) {
return validation.response;
}

const [userInfo] = await db
.select()
.from(users)
.where(eq(users.userId, userId));
const { userId } = await auth();
if (!userId) {
return NextResponse.json({
success: false,
message: "Unauthorized"
}, { status: 401 });
}

if (!userInfo) {
return NextResponse.json({
success: false,
message: "Invalid user."
}, { status: 400 });
} else if (userInfo.role !== "employer" && userInfo.role !== "owner") {
return NextResponse.json({
success: false,
message: "Unauthorized"
}, { status: 401 });
}

try {
const { employeeId } = (await request.json()) as PostBody;
const [userInfo] = await db
.select()
.from(users)
.where(eq(users.userId, userId));

await db.delete(users).where(eq(users.id, Number(employeeId)));
if (!userInfo) {
return NextResponse.json({
success: false,
message: "Invalid user."
}, { status: 400 });
} else if (userInfo.role !== "employer" && userInfo.role !== "owner") {
return NextResponse.json({
success: false,
message: "Unauthorized"
}, { status: 401 });
}

return NextResponse.json( { status: 200 });
// Use validated data
const { employeeId } = validation.data;

await db.delete(users).where(eq(users.id, employeeId));

return NextResponse.json({
success: true,
message: "Employee removed successfully"
});
} catch (error: unknown) {
console.error("Error fetching documents:", error);
console.error("Error removing employee:", error);
return NextResponse.json(
{ error: "Unable to fetch documents" },
{ success: false, error: "Failed to remove employee" },
{ status: 500 }
);
}
Expand Down
43 changes: 28 additions & 15 deletions src/app/api/signup/employee/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import { NextResponse } from "next/server";
import { db } from "~/server/db/index";
import { users, company } from "~/server/db/schema";
import { and, eq } from "drizzle-orm";

type PostBody = {
userId: string;
name: string;
email: string;
employeePasskey: string;
companyName: string;
};
import { validateRequestBody, SignupEmployeeSchema } from "~/lib/validation";

export async function POST(request: Request) {
try {
const { userId, name, email, employeePasskey, companyName } = (await request.json()) as PostBody;
// Validate request body
const validation = await validateRequestBody(request, SignupEmployeeSchema);
if (!validation.success) {
return validation.response;
}

const { userId, name, email, employeePasskey, companyName } = validation.data;

// Find company by company name
const [existingCompany] = await db
Expand All @@ -28,24 +27,38 @@ export async function POST(request: Request) {

if (!existingCompany) {
return NextResponse.json(
{ error: "Invalid company name or passkey." },
{
success: false,
error: "Validation Error",
message: "Invalid company name or employee passkey. Please check your credentials."
},
{ status: 400 }
);
}

// Insert new user
await db.insert(users).values({
userId,
name: name,
email: email,
name,
email,
companyId: existingCompany.id.toString(),
status: "pending",
role: "employee",
});

return NextResponse.json({ success: true });
return NextResponse.json({
success: true,
message: "Employee account created successfully. Awaiting approval."
});
} catch (error: unknown) {
console.error(error);
return NextResponse.json({ error: error }, { status: 500 });
console.error("Error during employee signup:", error);
return NextResponse.json(
{
success: false,
error: "Registration failed",
message: "An error occurred during registration. Please try again."
},
{ status: 500 }
);
}
}
50 changes: 30 additions & 20 deletions src/app/api/signup/employer/route.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import { NextResponse } from "next/server";
import { db } from "~/server/db/index";
import { users, company } from "~/server/db/schema";
import {and, eq} from "drizzle-orm";
import * as console from "console";

type PostBody = {
userId: string;
name: string;
email: string;
employerPasskey: string;
companyName: string;
}
import { and, eq } from "drizzle-orm";
import { validateRequestBody, SignupEmployerSchema } from "~/lib/validation";


export async function POST(request: Request) {
try {
const {userId, name, email, employerPasskey, companyName} = (await request.json()) as PostBody;
// Validate request body
const validation = await validateRequestBody(request, SignupEmployerSchema);
if (!validation.success) {
return validation.response;
}

const { userId, name, email, employerPasskey, companyName } = validation.data;

let companyId: string;
const [existingCompany] = await db
.select()
.from(company)
Expand All @@ -30,13 +27,16 @@ export async function POST(request: Request) {

if (!existingCompany) {
return NextResponse.json(
{error: "Invalid company name or passkey."},
{status: 400}
{
success: false,
error: "Validation Error",
message: "Invalid company name or employer passkey. Please check your credentials."
},
{ status: 400 }
);
}

// eslint-disable-next-line prefer-const
companyId = existingCompany.id.toString();
const companyId = existingCompany.id.toString();

await db.insert(users).values({
userId,
Expand All @@ -47,9 +47,19 @@ export async function POST(request: Request) {
role: "employer",
});

}
catch (error: unknown) {
console.error(error);
return NextResponse.json({ error: error}, { status: 500 });
return NextResponse.json({
success: true,
message: "Employer account created successfully. Awaiting approval."
});
} catch (error: unknown) {
console.error("Error during employer signup:", error);
return NextResponse.json(
{
success: false,
error: "Registration failed",
message: "An error occurred during registration. Please try again."
},
{ status: 500 }
);
}
}
26 changes: 26 additions & 0 deletions src/lib/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,29 @@ export const EmployerAuthSchema = z.object({
userId: z.string().min(1, "User ID is required"),
companyPasskey: z.string().min(1, "Company passkey is required"),
});

export const EmployeeIdSchema = z.object({
employeeId: z.coerce
.number({
required_error: "Employee ID is required",
invalid_type_error: "Employee ID must be a number"
})
.int("Employee ID must be an integer")
.positive("Employee ID must be a positive number"),
});

export const SignupEmployeeSchema = z.object({
userId: z.string().min(1, "User ID is required").max(256, "User ID is too long").trim(),
name: z.string().min(1, "Name is required").max(256, "Name is too long").trim(),
email: z.string().email("Invalid email address").max(256, "Email is too long").trim(),
employeePasskey: z.string().min(1, "Employee passkey is required").max(256, "Employee passkey is too long"),
companyName: z.string().min(1, "Company name is required").max(256, "Company name is too long").trim(),
});

export const SignupEmployerSchema = z.object({
userId: z.string().min(1, "User ID is required").max(256, "User ID is too long").trim(),
name: z.string().min(1, "Name is required").max(256, "Name is too long").trim(),
email: z.string().email("Invalid email address").max(256, "Email is too long").trim(),
employerPasskey: z.string().min(1, "Employer passkey is required").max(256, "Employer passkey is too long"),
companyName: z.string().min(1, "Company name is required").max(256, "Company name is too long").trim(),
});