Added fetch profile
This commit is contained in:
parent
951115fcce
commit
7fc39aee58
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 = () => {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user