-
Notifications
You must be signed in to change notification settings - Fork 423
Add more apis #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more apis #102
Changes from all commits
02f08d7
abf6a7c
a9e37cd
c2df2d0
8bacd68
2f78497
6244da1
85769eb
fc03563
5988dad
970a526
df8109e
068dfa1
e93d4e6
83d9679
1996538
103b1da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| // This file contains shared configuration for server actions | ||
| export const runtime = "nodejs"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import { handlers } from "@/auth"; | ||
|
|
||
| export const runtime = "nodejs"; | ||
| export const { GET, POST } = handlers; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,167 @@ | ||||||||||||||||||||||||||||
| import { db } from "@bubba/db"; | ||||||||||||||||||||||||||||
| import { NextResponse, type NextRequest } from "next/server"; | ||||||||||||||||||||||||||||
| import { getOrganizationFromApiKey } from "@/lib/api-key"; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Configure this route to use Node.js runtime instead of Edge | ||||||||||||||||||||||||||||
| export const runtime = "nodejs"; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||
| * GET /api/v1/employees/:id | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Get a single employee by ID for the organization associated with the API key | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Headers: | ||||||||||||||||||||||||||||
| * - Authorization: Bearer {api_key} or X-API-Key: {api_key} | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Path Parameters: | ||||||||||||||||||||||||||||
| * - id: string - The ID of the employee to fetch | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Returns: | ||||||||||||||||||||||||||||
| * - 200: { success: true, data: Employee } | ||||||||||||||||||||||||||||
| * - 401: { success: false, error: "Invalid or missing API key" } | ||||||||||||||||||||||||||||
| * - 404: { success: false, error: "Employee not found" } | ||||||||||||||||||||||||||||
| * - 500: { success: false, error: "Failed to fetch employee" } | ||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||
| export async function GET( | ||||||||||||||||||||||||||||
| request: NextRequest, | ||||||||||||||||||||||||||||
| { params }: { params: Promise<{ id: string }> } | ||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||
| // Get the organization ID from the API key | ||||||||||||||||||||||||||||
| const { organizationId, errorResponse } = | ||||||||||||||||||||||||||||
| await getOrganizationFromApiKey(request); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // If there's an error response, return it | ||||||||||||||||||||||||||||
| if (errorResponse) { | ||||||||||||||||||||||||||||
| return errorResponse; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||
| const employeeId = (await params).id; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove unnecessary await for params. Since params should not be a Promise (as noted in the previous comment), you don't need to await it. - const employeeId = (await params).id;
+ const employeeId = params.id;📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
| // Fetch the employee | ||||||||||||||||||||||||||||
| const employee = await db.employee.findFirst({ | ||||||||||||||||||||||||||||
| where: { | ||||||||||||||||||||||||||||
| id: employeeId, | ||||||||||||||||||||||||||||
| organizationId: organizationId!, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| select: { | ||||||||||||||||||||||||||||
| id: true, | ||||||||||||||||||||||||||||
| name: true, | ||||||||||||||||||||||||||||
| email: true, | ||||||||||||||||||||||||||||
| department: true, | ||||||||||||||||||||||||||||
| isActive: true, | ||||||||||||||||||||||||||||
| externalEmployeeId: true, | ||||||||||||||||||||||||||||
| createdAt: true, | ||||||||||||||||||||||||||||
| updatedAt: true, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // If employee not found, return 404 | ||||||||||||||||||||||||||||
| if (!employee) { | ||||||||||||||||||||||||||||
| return NextResponse.json( | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| success: false, | ||||||||||||||||||||||||||||
| error: "Employee not found", | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { status: 404 } | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Format dates for JSON response | ||||||||||||||||||||||||||||
| const formattedEmployee = { | ||||||||||||||||||||||||||||
| ...employee, | ||||||||||||||||||||||||||||
| createdAt: employee.createdAt.toISOString(), | ||||||||||||||||||||||||||||
| updatedAt: employee.updatedAt.toISOString(), | ||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| return NextResponse.json({ | ||||||||||||||||||||||||||||
| success: true, | ||||||||||||||||||||||||||||
| data: formattedEmployee, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||
| console.error("Error fetching employee:", error); | ||||||||||||||||||||||||||||
| return NextResponse.json( | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| success: false, | ||||||||||||||||||||||||||||
| error: "Failed to fetch employee", | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { status: 500 } | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||
| * DELETE /api/v1/employees/:id | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Delete an employee by ID for the organization associated with the API key | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Headers: | ||||||||||||||||||||||||||||
| * - Authorization: Bearer {api_key} or X-API-Key: {api_key} | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Path Parameters: | ||||||||||||||||||||||||||||
| * - id: string - The ID of the employee to delete | ||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||
| * Returns: | ||||||||||||||||||||||||||||
| * - 200: { success: true, data: { message: string } } | ||||||||||||||||||||||||||||
| * - 401: { success: false, error: string } | ||||||||||||||||||||||||||||
| * - 404: { success: false, error: string } | ||||||||||||||||||||||||||||
| * - 500: { success: false, error: string } | ||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||
| export async function DELETE( | ||||||||||||||||||||||||||||
| request: NextRequest, | ||||||||||||||||||||||||||||
| { params }: { params: Promise<{ id: string }> } | ||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||
|
Comment on lines
+110
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix the params type in DELETE method. Similar to the GET method, the params parameter is incorrectly typed as a Promise. export async function DELETE(
request: NextRequest,
- { params }: { params: Promise<{ id: string }> }
+ { params }: { params: { id: string } }
)📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
| // Get the organization ID from the API key | ||||||||||||||||||||||||||||
| const { organizationId, errorResponse } = | ||||||||||||||||||||||||||||
| await getOrganizationFromApiKey(request); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // If there's an error response, return it | ||||||||||||||||||||||||||||
| if (errorResponse) { | ||||||||||||||||||||||||||||
| return errorResponse; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||
| const employeeId = (await params).id; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
Comment on lines
+123
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove unnecessary await for params in DELETE method. Since params should not be a Promise, you don't need to await it here either. - const employeeId = (await params).id;
+ const employeeId = params.id;📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
| // Check if the employee exists and belongs to the organization | ||||||||||||||||||||||||||||
| const existingEmployee = await db.employee.findFirst({ | ||||||||||||||||||||||||||||
| where: { | ||||||||||||||||||||||||||||
| id: employeeId, | ||||||||||||||||||||||||||||
| organizationId: organizationId!, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if (!existingEmployee) { | ||||||||||||||||||||||||||||
| return NextResponse.json( | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| success: false, | ||||||||||||||||||||||||||||
| error: "Employee not found", | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { status: 404 } | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Delete the employee | ||||||||||||||||||||||||||||
| await db.employee.delete({ | ||||||||||||||||||||||||||||
| where: { | ||||||||||||||||||||||||||||
| id: employeeId, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
|
Comment on lines
+144
to
+149
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security issue: Missing organization ID in deletion criteria. The deletion query only filters by employee ID, not by organization ID. This could potentially allow deletion of employees from other organizations if the ID is known. - // Delete the employee
- await db.employee.delete({
- where: {
- id: employeeId,
- },
- });
+ // Delete the employee, ensuring it belongs to the correct organization
+ await db.employee.delete({
+ where: {
+ id: employeeId,
+ organizationId: organizationId!,
+ },
+ });Note: If you implement the optimization from the previous comment, this issue would be resolved automatically. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| return NextResponse.json({ | ||||||||||||||||||||||||||||
| success: true, | ||||||||||||||||||||||||||||
| data: { | ||||||||||||||||||||||||||||
| message: "Employee deleted successfully", | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||
| console.error("Error deleting employee:", error); | ||||||||||||||||||||||||||||
| return NextResponse.json( | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| success: false, | ||||||||||||||||||||||||||||
| error: "Failed to delete employee", | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { status: 500 } | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix the params type - it shouldn't be a Promise.
The type for
paramsis defined asPromise<{ id: string }>, which is unusual. Typically, route parameters in Next.js are not promises.📝 Committable suggestion