Added fetch profile

This commit is contained in:
sianida26 2024-05-08 19:08:47 +07:00
parent 951115fcce
commit 7fc39aee58
3 changed files with 77 additions and 48 deletions

View File

@ -15,6 +15,12 @@ import {
import { rolesSchema } from "../../drizzle/schema/roles"; import { rolesSchema } from "../../drizzle/schema/roles";
import { rolesToUsers } from "../../drizzle/schema/rolesToUsers"; import { rolesToUsers } from "../../drizzle/schema/rolesToUsers";
import HonoEnv from "../../types/HonoEnv"; import HonoEnv from "../../types/HonoEnv";
import { permissionsToUsers } from "../../drizzle/schema/permissionsToUsers";
import { permissionsToRoles } from "../../drizzle/schema/permissionsToRoles";
import { permissionsSchema } from "../../drizzle/schema/permissions";
import { SpecificPermissionCode } from "../../data/permissions";
import authInfo from "../../middlewares/authInfo";
import { unauthorized } from "../../errors/DashboardError";
const authRoutes = new Hono<HonoEnv>() const authRoutes = new Hono<HonoEnv>()
.post( .post(
@ -30,7 +36,7 @@ const authRoutes = new Hono<HonoEnv>()
async (c) => { async (c) => {
const formData = c.req.valid("form"); const formData = c.req.valid("form");
const [user] = await db const user = await db
.select() .select()
.from(users) .from(users)
.where( .where(
@ -42,9 +48,32 @@ const authRoutes = new Hono<HonoEnv>()
eq(users.email, formData.username) eq(users.email, formData.username)
) )
) )
)
.leftJoin(
permissionsToUsers,
eq(permissionsToUsers.userId, users.id)
)
.leftJoin(rolesToUsers, eq(rolesToUsers.userId, users.id))
.leftJoin(rolesSchema, eq(rolesToUsers.roleId, rolesSchema.id))
.leftJoin(
permissionsToRoles,
eq(permissionsToRoles.roleId, rolesSchema.id)
)
.leftJoin(
permissionsSchema,
or(
eq(
permissionsSchema.id,
permissionsToUsers.permissionId
),
eq(
permissionsSchema.id,
permissionsToRoles.permissionId
)
)
); );
if (!user) { if (!user.length) {
throw new HTTPException(400, { throw new HTTPException(400, {
message: "Invalid username or password", message: "Invalid username or password",
}); });
@ -52,7 +81,7 @@ const authRoutes = new Hono<HonoEnv>()
const isSuccess = await checkPassword( const isSuccess = await checkPassword(
formData.password, formData.password,
user.password user[0].users.password
); );
if (!isSuccess) { if (!isSuccess) {
@ -62,11 +91,11 @@ const authRoutes = new Hono<HonoEnv>()
} }
const accessToken = await generateAccessToken({ const accessToken = await generateAccessToken({
uid: user.id, uid: user[0].users.id,
}); });
const refreshToken = await generateRefreshToken({ const refreshToken = await generateRefreshToken({
uid: user.id, uid: user[0].users.id,
}); });
const cookieSecret = process.env.COOKIE_SECRET; const cookieSecret = process.env.COOKIE_SECRET;
@ -89,13 +118,22 @@ const authRoutes = new Hono<HonoEnv>()
// } // }
// ); // );
const permissions = new Set<SpecificPermissionCode>();
user.forEach((user) => {
if (user.permissions?.code) {
permissions.add(
user.permissions.code as SpecificPermissionCode
);
}
});
return c.json({ return c.json({
accessToken, accessToken,
refreshToken, refreshToken,
user: { user: {
id: user.id, id: user[0].users.id,
name: user.name, name: user[0].users.name,
permissions: [] as string[], permissions: Array.from(permissions),
}, },
}); });
} }
@ -128,44 +166,14 @@ const authRoutes = new Hono<HonoEnv>()
}); });
} }
) )
.get("/my-profile", async (c) => { .get("/my-profile", authInfo, async (c) => {
const uid = c.var.uid; const currentUser = c.var.currentUser;
if (!uid) { if (!currentUser) {
throw new HTTPException(401, { message: "Unauthorized" }); throw unauthorized();
} }
const user = await db return c.json({ ...currentUser, id: c.var.uid! });
.select({
id: users.id,
username: users.username,
email: users.email,
roles: rolesSchema.code,
})
.from(rolesToUsers)
.innerJoin(users, eq(users.id, rolesToUsers.userId))
.innerJoin(rolesSchema, eq(rolesToUsers.roleId, rolesSchema.id))
.where(eq(users.id, uid))
.then((userData) => {
return userData.reduce(
(prev, curr) => ({
...prev,
roles: [...prev.roles, curr.roles],
}),
{
id: uid,
username: userData[0].username,
email: userData[0].email,
roles: [] as string[],
}
);
});
if (!user) {
throw new HTTPException(401, { message: "Unauthorized" });
}
return c.json(user);
}) })
.get("/logout", (c) => { .get("/logout", (c) => {
const uid = c.var.uid; const uid = c.var.uid;

View File

@ -10,7 +10,7 @@ interface AuthContextType {
accessToken: string | null; accessToken: string | null;
saveAuthData: ( saveAuthData: (
userData: NonNullable<AuthContextType["user"]>, userData: NonNullable<AuthContextType["user"]>,
accessToken: NonNullable<AuthContextType["accessToken"]> accessToken?: NonNullable<AuthContextType["accessToken"]>
) => void; ) => void;
clearAuthData: () => void; clearAuthData: () => void;
isAuthenticated: boolean; isAuthenticated: boolean;
@ -30,13 +30,15 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const saveAuthData = ( const saveAuthData = (
userData: NonNullable<AuthContextType["user"]>, userData: NonNullable<AuthContextType["user"]>,
accessToken: NonNullable<AuthContextType["accessToken"]> accessToken?: NonNullable<AuthContextType["accessToken"]>
) => { ) => {
setUserId(userData.id); setUserId(userData.id);
setUserName(userData.name); setUserName(userData.name);
setPermissions(userData.permissions); setPermissions(userData.permissions);
setAccessToken(accessToken); if (accessToken) {
localStorage.setItem("accessToken", accessToken); setAccessToken(accessToken);
localStorage.setItem("accessToken", accessToken);
}
}; };
const clearAuthData = () => { const clearAuthData = () => {

View File

@ -4,6 +4,9 @@ import { useDisclosure } from "@mantine/hooks";
import AppHeader from "../components/AppHeader"; import AppHeader from "../components/AppHeader";
import AppNavbar from "../components/AppNavbar"; import AppNavbar from "../components/AppNavbar";
import useAuth from "@/hooks/useAuth"; import useAuth from "@/hooks/useAuth";
import { useQuery } from "@tanstack/react-query";
import fetchRPC from "@/utils/fetchRPC";
import client from "@/honoClient";
export const Route = createFileRoute("/_dashboardLayout")({ export const Route = createFileRoute("/_dashboardLayout")({
component: DashboardLayout, component: DashboardLayout,
@ -18,7 +21,23 @@ export const Route = createFileRoute("/_dashboardLayout")({
}); });
function DashboardLayout() { function DashboardLayout() {
const { isAuthenticated } = useAuth(); const { isAuthenticated, saveAuthData } = useAuth();
useQuery({
queryKey: ["my-profile"],
queryFn: async () => {
const response = await fetchRPC(client.auth["my-profile"].$get());
saveAuthData({
id: response.id,
name: response.name,
permissions: response.permissions,
});
return response;
},
enabled: isAuthenticated,
});
const [openNavbar, { toggle }] = useDisclosure(false); const [openNavbar, { toggle }] = useDisclosure(false);