-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from GenieWizards/feature/8-crud-group-table
Feature/8 crud group table
- Loading branch information
Showing
6 changed files
with
247 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import type { AppRouteHandler } from "@/common/lib/types"; | ||
import type { TSelectGroupSchema } from "@/db/schemas/group.model"; | ||
|
||
import * as HTTPStatusCodes from "@/common/utils/http-status-codes.util"; | ||
|
||
import type { TCreateGroupRoute, TDeleteGroupRoute } from "./group.routes"; | ||
|
||
import { createGroupRepository, deleteGroupRepository } from "./group.repository"; | ||
|
||
export const createGroup: AppRouteHandler<TCreateGroupRoute> = async (c) => { | ||
const user = c.get("user"); | ||
const payload = c.req.valid("json"); | ||
const logger = c.get("logger"); | ||
|
||
if (!user) { | ||
logger.error("User is not authorized to create group"); | ||
return c.json( | ||
{ | ||
success: false, | ||
message: "You are not authorized, please login", | ||
}, | ||
HTTPStatusCodes.UNAUTHORIZED, | ||
); | ||
} | ||
|
||
const group: TSelectGroupSchema | null = await createGroupRepository(payload); | ||
|
||
if (!group) { | ||
logger.error("Failed to create group"); | ||
return c.json( | ||
{ | ||
success: false, | ||
message: "Failed to create group", | ||
}, | ||
HTTPStatusCodes.INTERNAL_SERVER_ERROR, | ||
); | ||
} | ||
|
||
logger.debug(`Group created successfully with name ${group.name}`); | ||
|
||
return c.json( | ||
{ | ||
success: true, | ||
message: "Group created successfully", | ||
data: group, | ||
}, | ||
HTTPStatusCodes.CREATED, | ||
); | ||
}; | ||
|
||
export const deleteGroup: AppRouteHandler<TDeleteGroupRoute> = async (c) => { | ||
const user = c.get("user"); | ||
const params = c.req.valid("param"); | ||
const logger = c.get("logger"); | ||
|
||
if (!user) { | ||
logger.error("User is not authorized to delete group"); | ||
return c.json( | ||
{ | ||
success: false, | ||
message: "You are not authorized, please login", | ||
}, | ||
HTTPStatusCodes.UNAUTHORIZED, | ||
); | ||
} | ||
|
||
const deletedGroupId: string | null = await deleteGroupRepository(params.id); | ||
|
||
if (!deletedGroupId) { | ||
logger.error(`Group with ${params.id} not found`); | ||
return c.json( | ||
{ | ||
success: false, | ||
message: `Group with ${params.id} not found`, | ||
}, | ||
HTTPStatusCodes.NOT_FOUND, | ||
); | ||
} | ||
|
||
logger.debug(`Group with ${deletedGroupId} deleted successfully`); | ||
|
||
return c.json( | ||
{ | ||
success: true, | ||
message: `Group with ${deletedGroupId} deleted successfully`, | ||
}, | ||
HTTPStatusCodes.OK, | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { createRouter } from "@/common/lib/create-app.lib"; | ||
|
||
import * as handlers from "./group.handler"; | ||
import * as routes from "./group.routes"; | ||
|
||
export const groupRouters = createRouter() | ||
.openapi(routes.createGroupRoute, handlers.createGroup) | ||
.openapi(routes.deleteGroupRoute, handlers.deleteGroup); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { eq } from "drizzle-orm"; | ||
|
||
import type { TInsertGroupSchema } from "@/db/schemas/group.model"; | ||
|
||
import { db } from "@/db/adapter"; | ||
import groupModel from "@/db/schemas/group.model"; | ||
|
||
export async function createGroupRepository( | ||
groupPayload: TInsertGroupSchema, | ||
) { | ||
const [group] = await db | ||
.insert(groupModel) | ||
.values(groupPayload) | ||
.returning(); | ||
|
||
return group; | ||
} | ||
|
||
export async function deleteGroupRepository( | ||
groupId: string, | ||
) { | ||
const [deletedGroups] = await db | ||
.delete(groupModel) | ||
.where(eq(groupModel.id, groupId)) | ||
.returning(); | ||
|
||
return deletedGroups?.id || null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { createRoute } from "@hono/zod-openapi"; | ||
import { z } from "zod"; | ||
|
||
import { AuthRoles } from "@/common/enums"; | ||
import jsonContentRequired from "@/common/helpers/json-content-required.helper"; | ||
import { jsonContent } from "@/common/helpers/json-content.helper"; | ||
import { authMiddleware, checkRoleGuard, requireAuth } from "@/common/middlewares/auth.middleware"; | ||
import * as HTTPStatusCodes from "@/common/utils/http-status-codes.util"; | ||
import { insertGroupSchema, selectGroupSchema } from "@/db/schemas/group.model"; | ||
|
||
const tags = ["Groups"]; | ||
|
||
export const createGroupRoute = createRoute({ | ||
tags, | ||
method: "post", | ||
path: "/group", | ||
middleware: [ | ||
authMiddleware(), | ||
requireAuth(), | ||
checkRoleGuard(AuthRoles.ADMIN, AuthRoles.USER), | ||
] as const, | ||
request: { | ||
body: jsonContentRequired( | ||
insertGroupSchema.omit({ | ||
id: true, | ||
status: true, | ||
createdAt: true, | ||
updatedAt: true, | ||
}), | ||
"Group creation", | ||
), | ||
}, | ||
responses: { | ||
[HTTPStatusCodes.CREATED]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(true), | ||
message: z.string(), | ||
data: selectGroupSchema, | ||
}), | ||
"Group created successfully", | ||
), | ||
[HTTPStatusCodes.BAD_REQUEST]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"Validation error(s)", | ||
), | ||
[HTTPStatusCodes.UNAUTHORIZED]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"You are not authorized, please login", | ||
), | ||
[HTTPStatusCodes.INTERNAL_SERVER_ERROR]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"Failed to create the group", | ||
), | ||
}, | ||
}); | ||
|
||
export const deleteGroupRoute = createRoute({ | ||
tags, | ||
method: "delete", | ||
path: "group/:id", | ||
middleware: [ | ||
authMiddleware(), | ||
requireAuth(), | ||
checkRoleGuard(AuthRoles.ADMIN, AuthRoles.USER), | ||
] as const, | ||
request: { | ||
params: z.object({ | ||
id: z.string(), | ||
}), | ||
}, | ||
responses: { | ||
[HTTPStatusCodes.OK]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(true), | ||
message: z.string(), | ||
}), | ||
"Group deleted successfully", | ||
), | ||
[HTTPStatusCodes.NOT_FOUND]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"Group with id does not exist", | ||
), | ||
[HTTPStatusCodes.UNAUTHORIZED]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"You are not authorized, please login", | ||
), | ||
[HTTPStatusCodes.FORBIDDEN]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"You are not allowed to perform this action", | ||
), | ||
[HTTPStatusCodes.INTERNAL_SERVER_ERROR]: jsonContent( | ||
z.object({ | ||
success: z.boolean().default(false), | ||
message: z.string(), | ||
}), | ||
"Something went wrong, please try again later", | ||
), | ||
}, | ||
}); | ||
|
||
export type TCreateGroupRoute = typeof createGroupRoute; | ||
export type TDeleteGroupRoute = typeof deleteGroupRoute; |