refactor(auth): added module and submodule access to the user

This commit is contained in:
2025-04-09 17:47:02 -05:00
parent ded074a1ce
commit efc630f5f8
10 changed files with 181 additions and 142 deletions

View File

@@ -1,9 +1,3 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { getUsers } from "@/utils/querys/admin/users";
import { useQuery } from "@tanstack/react-query";
import UserCard from "./components/UserCard";
@@ -22,22 +16,13 @@ export default function UserPage() {
return (
<div className="m-2 w-dvw">
<Accordion type="single" collapsible>
{data.map((u: any) => {
return (
<AccordionItem key={u.user_id} value={u.user_id}>
<AccordionTrigger>
<span>{u.username}</span>
</AccordionTrigger>
<AccordionContent>
<div>
<UserCard user={u} />
</div>
</AccordionContent>
</AccordionItem>
);
})}
</Accordion>
{data.map((u: any) => {
return (
<div>
<UserCard user={u} />
</div>
);
})}
</div>
);
}

View File

@@ -19,11 +19,13 @@ export default function ModuleAccess(data: any) {
<div className="flex flex-row flex-wrap">
{modules?.map((m: any) => {
return (
<ModuleForm
key={m.module_id}
i={m}
username={data.user.username}
/>
<div key={m.module_id}>
<ModuleForm
module={m}
user={data.user}
refetch={data.refetch}
/>
</div>
);
})}
</div>

View File

@@ -1,4 +1,3 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import {
@@ -10,21 +9,26 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { getUserRoles } from "@/utils/querys/admin/userRoles";
import { useForm } from "@tanstack/react-form";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { toast } from "sonner";
export default function ModuleForm(props: any) {
const { refetch } = useQuery(getUserRoles());
const token = localStorage.getItem("auth_token");
const role =
props.user?.moduleRoles?.filter(
(m: any) => m.module_id === props.module.module_id
)[0]?.role ?? " ";
const form = useForm({
defaultValues: { role: props.i.role },
defaultValues: {
role: role,
},
onSubmit: async ({ value }) => {
const data = {
username: props.username,
module: props.i.name,
const data: any = {
username: props.user.username,
module: props.module.name,
role: value.role,
};
console.log(data);
@@ -37,7 +41,7 @@ export default function ModuleForm(props: any) {
if (res.data.success) {
toast.success(res.data.message);
refetch();
props.refetch();
form.reset();
} else {
res.data.message;
@@ -49,71 +53,67 @@ export default function ModuleForm(props: any) {
});
return (
<div className="m-2 p-1">
<LstCard>
<p className="text-center">Module: {props.i.name}</p>
<p className="p-1">Current role: </p>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
<div className="">
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
className="flex flex-row"
>
<form.Field
name="role"
//listeners={{onChange: ({value})=>{}}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<Label htmlFor={field.name}>
Module: {props.module.name}
</Label>
<Select
value={field.state.value}
onValueChange={field.handleChange}
>
<SelectTrigger className="w-[180px]">
<SelectValue
id={field.name}
placeholder="Select Role"
/>
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Roles</SelectLabel>
<SelectItem value="viewer">
Viewer
</SelectItem>
<SelectItem value="technician">
Technician
</SelectItem>
<SelectItem value="supervisor">
Supervisor
</SelectItem>
<SelectItem value="manager">
Manager
</SelectItem>
<SelectItem value="tester">
Tester
</SelectItem>
<SelectItem value="admin">
Admin
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
);
}}
>
<form.Field
name="role"
//listeners={{onChange: ({value})=>{}}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<Label htmlFor={field.name}>
Select role
</Label>
<Select
value={field.state.value}
onValueChange={field.handleChange}
>
<SelectTrigger className="w-[180px]">
<SelectValue
id={field.name}
placeholder="Select Role"
/>
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Roles</SelectLabel>
<SelectItem value="viewer">
Viewer
</SelectItem>
<SelectItem value="technician">
Technician
</SelectItem>
<SelectItem value="supervisor">
Supervisor
</SelectItem>
<SelectItem value="manager">
Manager
</SelectItem>
<SelectItem value="tester">
Tester
</SelectItem>
<SelectItem value="admin">
Admin
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
);
}}
/>
<div className="mt-4">
<Button type="submit" onClick={form.handleSubmit}>
Save
</Button>
</div>
</form>
</LstCard>
/>
<div className="mt-4">
<Button type="submit" onClick={form.handleSubmit}>
Save
</Button>
</div>
</form>
</div>
);
}

View File

@@ -22,13 +22,12 @@ import axios from "axios";
import { toast } from "sonner";
import { CardHeader } from "@/components/ui/card";
import ModuleAccess from "./ModuleAccess";
export default function UserCard(data: any) {
const token = localStorage.getItem("auth_token");
const { refetch } = useQuery(getUsers());
//console.log(modules);
//console.log(data.user);
//console.log(userRoles);
const form = useForm({
...userFormOptions(data.user),
@@ -268,13 +267,17 @@ export default function UserCard(data: any) {
);
}}
/>
<div className="mt-4 ml-4">
<Button onClick={form.handleSubmit}>Save</Button>
</div>
</form>
</LstCard>
<div className="mt-4">
<Button onClick={form.handleSubmit}>Save</Button>
</div>
</div>
<div className="flex flex-col"></div>
<div>
<LstCard>
<ModuleAccess user={data.user} refetch={refetch} />
</LstCard>
</div>
</div>
);
}

View File

@@ -19,12 +19,18 @@ export const useGetUserRoles = create<SettingState>()((set) => ({
try {
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
const token = localStorage.getItem("auth_token");
const response = await axios.get("/api/auth/getuseraccess", {
headers: { Authorization: `Bearer ${token}` },
});
const data: FetchModulesResponse = response.data; //await response.json();
//console.log(data);
set({ userRoles: data.data });
if (token) {
const response = await axios.get("/api/auth/getuseraccess", {
headers: { Authorization: `Bearer ${token}` },
});
const data: FetchModulesResponse = response.data; //await response.json();
//console.log(data);
set({ userRoles: data.data });
} else {
//console.log(data);
set({ userRoles: [] });
}
} catch (error) {
console.error("Failed to fetch settings:", error);
}

View File

@@ -8,7 +8,7 @@ export function getUsers() {
queryFn: () => fetchUsers(token),
enabled: !!token, // Prevents query if token is null
staleTime: 1000,
//refetchInterval: 2 * 2000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}

View File

@@ -1,25 +1,44 @@
import {Modules} from "@/types/modules";
import {User} from "@/types/users";
import { Modules } from "@/types/modules";
import { User } from "@/types/users";
// user will need access to the module.
// users role will determine there visual access
export function hasAccess(user: User | null, moduleName: string | null, modules: Modules[]): boolean {
export function hasAccess(
user: User | null,
moduleName: string | null,
modules: Modules[]
): boolean {
// get the modules for the id
const filteredModule = modules?.filter((f) => f.name === moduleName);
//console.log(filteredModule[0].module_id);
//console.log(filteredModule[0]);
// userroles and filter out by the module id,
return user?.roles.find((role) => role.module_id === filteredModule[0].module_id) ? true : false;
const roleCheck: any = user?.roles.find(
(role) => role.module_id === filteredModule[0].module_id
);
if (filteredModule[0].roles.includes(roleCheck?.role)) {
return true;
}
//if(filteredModule[0].roles.includes(roleCheck.))
return false;
}
export function hasPageAccess(user: User | null, role: any, module_id: string): boolean {
export function hasPageAccess(
user: User | null,
role: any,
module_id: string
): boolean {
if (role.includes("viewer")) return true;
if (!user) return false;
// get only the module in the user profile
//console.log(user);
const userRole = user?.roles.filter((role) => role.module_id === module_id);
console.log(userRole[0]?.role);
// if (role.includes(userRole[0]?.role)) {
if (role.includes(userRole[0]?.role)) return true;
// return true};
if (userRole.length !== 0) return true;
return false;
}

View File

@@ -1,24 +1,42 @@
import { db } from "../../../../../database/dbclient.js";
import { userRoles } from "../../../../../database/schema/userRoles.js";
import { users } from "../../../../../database/schema/users.js";
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
export const getAllUsers = async () => {
/**
* returns all users that are in lst
*/
createLog("info", "apiAuthedRoute", "auth", "Get all users");
const { data, error } = await tryCatch(db.select().from(users));
/**
* returns all users that are in lst
*/
createLog("info", "apiAuthedRoute", "auth", "Get all users");
if (error) {
returnRes(
false,
"There was an error getting users",
new Error("No user exists.")
);
}
// get all users
const { data, error } = await tryCatch(db.select().from(users));
returnRes(true, "All users.", data);
return { success: true, message: "All users", data };
// add there modules they are in
const { data: m, error: em } = await tryCatch(db.select().from(userRoles));
const user: any = data;
const userData = user.map((i: any) => {
// module in
const module = m?.filter((x: any) => x.user_id === i.user_id);
if (module) {
return { ...i, moduleRoles: module };
} else {
return;
}
});
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: userData };
};

View File

@@ -54,12 +54,18 @@ export const setUserAccess = async (
// 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,
})
.onConflictDoUpdate({
target: userRoles.user_id,
set: { role_id: role[0].role_id, role: roleName },
});
//.returning({user: users.username, email: users.email});
// return c.json({message: "User Registered", user}, 200);

View File

@@ -59,7 +59,7 @@ app.openapi(
{
success: access.success,
message: access.message,
data: access.data,
data: [], //access?.data,
},
200
);