Merge pull request #4 from digitalsolutiongroup/feat/register
Develop API Register
This commit is contained in:
commit
6e8c3cbdf8
|
|
@ -17,10 +17,18 @@ const roleData: RoleData[] = [
|
|||
name: "Super Admin",
|
||||
permissions: permissionsData.map((permission) => permission.code),
|
||||
},
|
||||
{
|
||||
code: "user",
|
||||
description:
|
||||
"User with standard access rights for general usage of the application.",
|
||||
isActive: true,
|
||||
name: "User",
|
||||
permissions: permissionsData.map((permission) => permission.code),
|
||||
},
|
||||
];
|
||||
|
||||
// Manually specify the union of role codes
|
||||
export type RoleCode = "super-admin" | "*";
|
||||
export type RoleCode = "super-admin" | "user" | "*";
|
||||
|
||||
const exportedRoleData = roleData;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { configDotenv } from "dotenv";
|
|||
import { Hono } from "hono";
|
||||
import authRoutes from "./routes/auth/route";
|
||||
import usersRoute from "./routes/users/route";
|
||||
import respondentsRoute from "./routes/register/route";
|
||||
import { verifyAccessToken } from "./utils/authUtils";
|
||||
import permissionRoutes from "./routes/permissions/route";
|
||||
import { cors } from "hono/cors";
|
||||
|
|
@ -80,6 +81,7 @@ const routes = app
|
|||
.route("/roles", rolesRoute)
|
||||
.route("/dev", devRoutes)
|
||||
.route("/questions", questionsRoute)
|
||||
.route("/register", respondentsRoute)
|
||||
.onError((err, c) => {
|
||||
if (err instanceof DashboardError) {
|
||||
return c.json(
|
||||
|
|
|
|||
131
apps/backend/src/routes/register/route.ts
Normal file
131
apps/backend/src/routes/register/route.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import { Hono } from "hono";
|
||||
import { HTTPException } from "hono/http-exception";
|
||||
import db from "../../drizzle";
|
||||
import { respondents } from "../../drizzle/schema/respondents";
|
||||
import { users } from "../../drizzle/schema/users";
|
||||
import { rolesSchema } from "../../drizzle/schema/roles";
|
||||
import { rolesToUsers } from "../../drizzle/schema/rolesToUsers";
|
||||
import { hashPassword } from "../../utils/passwordUtils";
|
||||
import requestValidator from "../../utils/requestValidator";
|
||||
import authInfo from "../../middlewares/authInfo";
|
||||
import { or, eq } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import HonoEnv from "../../types/HonoEnv";
|
||||
import { notFound } from "../../errors/DashboardError";
|
||||
|
||||
const registerFormSchema = z.object({
|
||||
name: z.string().min(1).max(255),
|
||||
username: z.string().min(1).max(255),
|
||||
email: z.string().email(),
|
||||
password: z.string().min(6),
|
||||
companyName: z.string().min(1).max(255),
|
||||
position: z.string().min(1).max(255),
|
||||
workExperience: z.string().min(1).max(255),
|
||||
address: z.string().min(1),
|
||||
phoneNumber: z.string().min(1).max(13),
|
||||
isEnabled: z.string().default("false"),
|
||||
});
|
||||
|
||||
const respondentsRoute = new Hono<HonoEnv>()
|
||||
.use(authInfo)
|
||||
//post user
|
||||
.post("/", requestValidator("json", registerFormSchema), async (c) => {
|
||||
const formData = c.req.valid("json");
|
||||
|
||||
// Check if the provided email or username is already exists in database
|
||||
const conditions = [];
|
||||
if (formData.email) {
|
||||
conditions.push(eq(users.email, formData.email));
|
||||
}
|
||||
conditions.push(eq(users.username, formData.username));
|
||||
|
||||
const existingUser = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(
|
||||
or(
|
||||
eq(users.email, formData.email),
|
||||
eq(users.username, formData.username)
|
||||
)
|
||||
);
|
||||
|
||||
const existingRespondent = await db
|
||||
.select()
|
||||
.from(respondents)
|
||||
.where(eq(respondents.phoneNumber, formData.phoneNumber));
|
||||
|
||||
if (existingUser.length > 0) {
|
||||
throw new HTTPException(400, {
|
||||
message: "Email or username has been registered",
|
||||
});
|
||||
}
|
||||
|
||||
if (existingRespondent.length > 0) {
|
||||
throw new HTTPException(400, {
|
||||
message: "Phone number has been registered",
|
||||
});
|
||||
}
|
||||
|
||||
// Hash the password
|
||||
const hashedPassword = await hashPassword(formData.password);
|
||||
|
||||
// Start a transaction
|
||||
const result = await db.transaction(async (trx) => {
|
||||
// Create user
|
||||
const [newUser] = await trx
|
||||
.insert(users)
|
||||
.values({
|
||||
name: formData.name,
|
||||
username: formData.username,
|
||||
email: formData.email,
|
||||
password: hashedPassword,
|
||||
isEnabled: formData.isEnabled?.toLowerCase() === "true" || true,
|
||||
})
|
||||
.returning()
|
||||
.catch(() => {
|
||||
throw new HTTPException(500, { message: "Error creating user" });
|
||||
});
|
||||
|
||||
// Create respondent
|
||||
await trx
|
||||
.insert(respondents)
|
||||
.values({
|
||||
companyName: formData.companyName,
|
||||
position: formData.position,
|
||||
workExperience: formData.workExperience,
|
||||
address: formData.address,
|
||||
phoneNumber: formData.phoneNumber,
|
||||
userId: newUser.id,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new HTTPException(500, {
|
||||
message: "Error creating respondent",
|
||||
});
|
||||
});
|
||||
|
||||
// Automatically assign "user" role to the new user
|
||||
const [role] = await trx
|
||||
.select()
|
||||
.from(rolesSchema)
|
||||
.where(eq(rolesSchema.code, "user"))
|
||||
.limit(1);
|
||||
|
||||
if (!role) throw notFound();
|
||||
|
||||
await trx.insert(rolesToUsers).values({
|
||||
userId: newUser.id,
|
||||
roleId: role.id,
|
||||
});
|
||||
|
||||
return newUser;
|
||||
});
|
||||
|
||||
return c.json(
|
||||
{
|
||||
message: "User created successfully",
|
||||
},
|
||||
201
|
||||
);
|
||||
});
|
||||
|
||||
export default respondentsRoute;
|
||||
Loading…
Reference in New Issue
Block a user