From b630bae50d43602212c230b58248ba5f93743f0b Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Tue, 8 Apr 2025 06:46:56 -0500 Subject: [PATCH] test(auth): more and more auth setup --- frontend/src/routes/_admin/modules.tsx | 15 ++-- frontend/src/routes/_admin/subModules.tsx | 14 ++++ frontend/src/utils/querys/admin/modules.tsx | 25 ++++++ .../src/utils/querys/admin/subModules.tsx | 25 ++++++ frontend/src/utils/querys/admin/userRoles.tsx | 26 ++++++ server/services/auth/authService.ts | 24 +++--- .../controllers/userAdmin/getAllUserRoles.ts | 24 ++++++ .../controllers/userRoles/getUserAccess.ts | 41 ++++++--- .../controllers/userRoles/setUserRoles.ts | 84 +++++++++++++++---- .../auth/routes/userAdmin/getAllUserRoles.ts | 34 ++++++++ 10 files changed, 265 insertions(+), 47 deletions(-) create mode 100644 frontend/src/routes/_admin/subModules.tsx create mode 100644 frontend/src/utils/querys/admin/modules.tsx create mode 100644 frontend/src/utils/querys/admin/subModules.tsx create mode 100644 frontend/src/utils/querys/admin/userRoles.tsx create mode 100644 server/services/auth/controllers/userAdmin/getAllUserRoles.ts create mode 100644 server/services/auth/routes/userAdmin/getAllUserRoles.ts diff --git a/frontend/src/routes/_admin/modules.tsx b/frontend/src/routes/_admin/modules.tsx index 254ebe3..34e719b 100644 --- a/frontend/src/routes/_admin/modules.tsx +++ b/frontend/src/routes/_admin/modules.tsx @@ -1,9 +1,14 @@ -import { createFileRoute } from '@tanstack/react-router' +import ModulesPage from "@/components/admin/modules/ModulePage"; +import { createFileRoute } from "@tanstack/react-router"; -export const Route = createFileRoute('/_admin/modules')({ - component: RouteComponent, -}) +export const Route = createFileRoute("/_admin/modules")({ + component: RouteComponent, +}); function RouteComponent() { - return
Hello "/_admin/modules"!
+ return ( +
+ +
+ ); } diff --git a/frontend/src/routes/_admin/subModules.tsx b/frontend/src/routes/_admin/subModules.tsx new file mode 100644 index 0000000..c9a0c72 --- /dev/null +++ b/frontend/src/routes/_admin/subModules.tsx @@ -0,0 +1,14 @@ +import SubModulePage from "@/components/admin/supModules/SubModulePage"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/_admin/subModules")({ + component: RouteComponent, +}); + +function RouteComponent() { + return ( +
+ +
+ ); +} diff --git a/frontend/src/utils/querys/admin/modules.tsx b/frontend/src/utils/querys/admin/modules.tsx new file mode 100644 index 0000000..260f08b --- /dev/null +++ b/frontend/src/utils/querys/admin/modules.tsx @@ -0,0 +1,25 @@ +import { queryOptions } from "@tanstack/react-query"; +import axios from "axios"; + +export function getModules(token: string) { + return queryOptions({ + queryKey: ["modules"], + queryFn: () => fetchSettings(token), + enabled: !!token, + //staleTime: 1000, + refetchOnWindowFocus: true, + }); +} + +const fetchSettings = async (token: string) => { + const { data } = await axios.get("/api/server/modules", { + headers: { Authorization: `Bearer ${token}` }, + }); + // if we are not localhost ignore the devDir setting. + const url: string = window.location.host.split(":")[0]; + let settingsData = data.data; + if (url != "localhost") { + settingsData.filter((n: any) => n.name === "devDir"); + } + return settingsData; +}; diff --git a/frontend/src/utils/querys/admin/subModules.tsx b/frontend/src/utils/querys/admin/subModules.tsx new file mode 100644 index 0000000..d50322b --- /dev/null +++ b/frontend/src/utils/querys/admin/subModules.tsx @@ -0,0 +1,25 @@ +import { queryOptions } from "@tanstack/react-query"; +import axios from "axios"; + +export function getSubModules(token: string) { + return queryOptions({ + queryKey: ["submodules"], + queryFn: () => fetchSettings(token), + enabled: !!token, + //staleTime: 1000, + refetchOnWindowFocus: true, + }); +} + +const fetchSettings = async (token: string) => { + const { data } = await axios.get("/api/server/submodules", { + headers: { Authorization: `Bearer ${token}` }, + }); + // if we are not localhost ignore the devDir setting. + const url: string = window.location.host.split(":")[0]; + let settingsData = data.data; + if (url != "localhost") { + settingsData.filter((n: any) => n.name === "devDir"); + } + return settingsData; +}; diff --git a/frontend/src/utils/querys/admin/userRoles.tsx b/frontend/src/utils/querys/admin/userRoles.tsx new file mode 100644 index 0000000..daa765b --- /dev/null +++ b/frontend/src/utils/querys/admin/userRoles.tsx @@ -0,0 +1,26 @@ +import { queryOptions } from "@tanstack/react-query"; +import axios from "axios"; + +export function getUserRoles() { + const token = localStorage.getItem("auth_token"); + return queryOptions({ + queryKey: ["getUsers"], + queryFn: () => fetchUsers(token), + enabled: !!token, // Prevents query if token is null + staleTime: 1000, + //refetchInterval: 2 * 2000, + refetchOnWindowFocus: true, + }); +} + +const fetchUsers = async (token: string | null) => { + const { data } = await axios.get(`/api/auth/allusersroles`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + // if we are not localhost ignore the devDir setting. + //const url: string = window.location.host.split(":")[0]; + return data.data ?? []; +}; diff --git a/server/services/auth/authService.ts b/server/services/auth/authService.ts index 5ff4dd7..ce49995 100644 --- a/server/services/auth/authService.ts +++ b/server/services/auth/authService.ts @@ -9,29 +9,31 @@ import { areRolesIn } from "./utils/roleCheck.js"; import createUser from "./routes/userAdmin/createUser.js"; import allUsers from "./routes/userAdmin/getUsers.js"; import updateUser from "./routes/userAdmin/updateUser.js"; +import allUserRoles from "./routes/userAdmin/getAllUserRoles.js"; const app = new OpenAPIHono(); // run the role check setTimeout(() => { - areRolesIn(); + areRolesIn(); }, 5000); const routes = [ - login, - register, - session, - profile, - getAccess, - setAccess, - createUser, - allUsers, - updateUser, + login, + register, + session, + profile, + getAccess, + setAccess, + createUser, + allUsers, + allUserRoles, + updateUser, ] as const; // app.route("/server", modules); const appRoutes = routes.forEach((route) => { - app.route("/auth", route); + app.route("/auth", route); }); export default app; diff --git a/server/services/auth/controllers/userAdmin/getAllUserRoles.ts b/server/services/auth/controllers/userAdmin/getAllUserRoles.ts new file mode 100644 index 0000000..621d463 --- /dev/null +++ b/server/services/auth/controllers/userAdmin/getAllUserRoles.ts @@ -0,0 +1,24 @@ +import { db } from "../../../../../database/dbclient.js"; +import { userRoles } from "../../../../../database/schema/userRoles.js"; +import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { createLog } from "../../../logger/logger.js"; + +export const getAllUsersRoles = async () => { + /** + * returns all users that are in lst + */ + createLog("info", "apiAuthedRoute", "auth", "Get all users"); + const { data, error } = await tryCatch(db.select().from(userRoles)); + + if (error) { + returnRes( + false, + "There was an error getting users", + new Error("No user exists.") + ); + } + + returnRes(true, "All users.", data); + return { success: true, message: "All users", data }; +}; diff --git a/server/services/auth/controllers/userRoles/getUserAccess.ts b/server/services/auth/controllers/userRoles/getUserAccess.ts index 82927ae..60c2cab 100644 --- a/server/services/auth/controllers/userRoles/getUserAccess.ts +++ b/server/services/auth/controllers/userRoles/getUserAccess.ts @@ -3,24 +3,39 @@ pass over a users uuid and return all modules they have permission too. in the login route we attach it to user under roles. */ -import {eq} from "drizzle-orm"; -import {db} from "../../../../../database/dbclient.js"; -import {userRoles} from "../../../../../database/schema/userRoles.js"; +import { eq } from "drizzle-orm"; +import { db } from "../../../../../database/dbclient.js"; +import { userRoles } from "../../../../../database/schema/userRoles.js"; export const roleCheck = async (user_id: string | undefined) => { if (!user_id) { throw Error("Missing user_id"); } + let returnRoles: any = []; // get the user roles by the user_id - const roles = await db - .select({ - user_id: userRoles.user_id, - role_id: userRoles.role_id, - module_id: userRoles.module_id, - role: userRoles.role, - }) - .from(userRoles) - .where(eq(userRoles.user_id, user_id)); + returnRoles = await db + .select({ + user_id: userRoles.user_id, + role_id: userRoles.role_id, + module_id: userRoles.module_id, + role: userRoles.role, + }) + .from(userRoles) + .where(eq(userRoles.user_id, user_id)); - return roles; + if (returnRoles[0]?.role.includes("systemAdmin")) { + const roles = await db + .select({ + user_id: userRoles.user_id, + role_id: userRoles.role_id, + module_id: userRoles.module_id, + role: userRoles.role, + }) + .from(userRoles) + .where(eq(userRoles.user_id, user_id)); + + return roles; + } + + return returnRoles; }; diff --git a/server/services/auth/controllers/userRoles/setUserRoles.ts b/server/services/auth/controllers/userRoles/setUserRoles.ts index 3c78dfa..3f7414f 100644 --- a/server/services/auth/controllers/userRoles/setUserRoles.ts +++ b/server/services/auth/controllers/userRoles/setUserRoles.ts @@ -3,21 +3,38 @@ pass over a users uuid and return all modules they have permission too. in the login route we attach it to user under roles. */ -import {eq} from "drizzle-orm"; -import {db} from "../../../../../database/dbclient.js"; -import {userRoles} from "../../../../../database/schema/userRoles.js"; -import {users} from "../../../../../database/schema/users.js"; -import {modules} from "../../../../../database/schema/modules.js"; -import {roles} from "../../../../../database/schema/roles.js"; -import {setSysAdmin} from "./setSysAdmin.js"; +import { and, eq } from "drizzle-orm"; +import { db } from "../../../../../database/dbclient.js"; +import { userRoles } from "../../../../../database/schema/userRoles.js"; +import { users } from "../../../../../database/schema/users.js"; +import { modules } from "../../../../../database/schema/modules.js"; +import { roles } from "../../../../../database/schema/roles.js"; +import { setSysAdmin } from "./setSysAdmin.js"; -export const setUserAccess = async (username: string, moduleName: string, roleName: string, override?: string) => { +export const setUserAccess = async ( + username: string, + moduleName: string, + roleName: string, + override?: string +) => { // get the user roles by the user_id - const user = await db.select().from(users).where(eq(users.username, username)); - const module = await db.select().from(modules).where(eq(modules.name, moduleName)); + const user = await db + .select() + .from(users) + .where(eq(users.username, username)); + const module = await db + .select() + .from(modules) + .where(eq(modules.name, moduleName)); - if (process.env.SECRETOVERRIDECODE != override && roleName === "systemAdmin") { - return {success: false, message: "The override code provided is invalid."}; + if ( + process.env.SECRETOVERRIDECODE != override && + roleName === "systemAdmin" + ) { + return { + success: false, + message: "The override code provided is invalid.", + }; } const role = await db.select().from(roles).where(eq(roles.name, roleName)); @@ -37,9 +54,12 @@ export const setUserAccess = async (username: string, moduleName: string, roleNa // set the user try { - const userRole = await db - .insert(userRoles) - .values({user_id: user[0].user_id, role_id: role[0].role_id, module_id: module[0].module_id, role: roleName}); + const userRole = await db.insert(userRoles).values({ + user_id: user[0].user_id, + role_id: role[0].role_id, + module_id: module[0].module_id, + role: roleName, + }); //.returning({user: users.username, email: users.email}); // return c.json({message: "User Registered", user}, 200); @@ -48,10 +68,38 @@ export const setUserAccess = async (username: string, moduleName: string, roleNa message: `${username} has been granted access to ${moduleName} with the role ${roleName}`, }; } catch (error) { + await changeRole( + roleName, + user[0].user_id, + module[0].module_id, + role[0].role_id + ); return { - success: false, - message: `There was an error granting ${username} access to ${moduleName} with the role ${roleName}`, - data: error, + success: true, + message: `${username} access on ${moduleName} has been changed to ${roleName}`, }; } }; + +const changeRole = async ( + role: any, + userID: any, + moduleID: any, + roleID: any +) => { + await db + .delete(userRoles) + .where( + and( + eq(userRoles.user_id, userID), + eq(userRoles.module_id, moduleID) + ) + ); + + const userRole = await db.insert(userRoles).values({ + user_id: userID, + role_id: roleID, + module_id: moduleID, + role: role, + }); +}; diff --git a/server/services/auth/routes/userAdmin/getAllUserRoles.ts b/server/services/auth/routes/userAdmin/getAllUserRoles.ts new file mode 100644 index 0000000..3b3710f --- /dev/null +++ b/server/services/auth/routes/userAdmin/getAllUserRoles.ts @@ -0,0 +1,34 @@ +import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi"; + +import { responses } from "../../../../globalUtils/routeDefs/responses.js"; +import { authMiddleware } from "../../middleware/authMiddleware.js"; +import hasCorrectRole from "../../middleware/roleCheck.js"; +import { getAllUsersRoles } from "../../controllers/userAdmin/getAllUserRoles.js"; + +const app = new OpenAPIHono(); + +app.openapi( + createRoute({ + tags: ["Auth:admin"], + summary: "Gets Users Roles", + method: "get", + path: "/allusersroles", + middleware: [ + authMiddleware, + hasCorrectRole(["admin", "systemAdmin"], "admin"), + ], + responses: responses(), + }), + async (c) => { + // apit hit + //apiHit(c, {endpoint: "api/auth/register"}); + const allUsers: any = await getAllUsersRoles(); + return c.json({ + success: allUsers?.success, + message: allUsers?.message, + data: allUsers?.data, + }); + } +); + +export default app;