refactor(auth): added module and submodule access to the user
This commit is contained in:
@@ -1,9 +1,3 @@
|
|||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { getUsers } from "@/utils/querys/admin/users";
|
import { getUsers } from "@/utils/querys/admin/users";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import UserCard from "./components/UserCard";
|
import UserCard from "./components/UserCard";
|
||||||
@@ -22,22 +16,13 @@ export default function UserPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="m-2 w-dvw">
|
<div className="m-2 w-dvw">
|
||||||
<Accordion type="single" collapsible>
|
|
||||||
{data.map((u: any) => {
|
{data.map((u: any) => {
|
||||||
return (
|
return (
|
||||||
<AccordionItem key={u.user_id} value={u.user_id}>
|
|
||||||
<AccordionTrigger>
|
|
||||||
<span>{u.username}</span>
|
|
||||||
</AccordionTrigger>
|
|
||||||
<AccordionContent>
|
|
||||||
<div>
|
<div>
|
||||||
<UserCard user={u} />
|
<UserCard user={u} />
|
||||||
</div>
|
</div>
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Accordion>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ export default function ModuleAccess(data: any) {
|
|||||||
<div className="flex flex-row flex-wrap">
|
<div className="flex flex-row flex-wrap">
|
||||||
{modules?.map((m: any) => {
|
{modules?.map((m: any) => {
|
||||||
return (
|
return (
|
||||||
|
<div key={m.module_id}>
|
||||||
<ModuleForm
|
<ModuleForm
|
||||||
key={m.module_id}
|
module={m}
|
||||||
i={m}
|
user={data.user}
|
||||||
username={data.user.username}
|
refetch={data.refetch}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
import {
|
||||||
@@ -10,21 +9,26 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { getUserRoles } from "@/utils/querys/admin/userRoles";
|
|
||||||
import { useForm } from "@tanstack/react-form";
|
import { useForm } from "@tanstack/react-form";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export default function ModuleForm(props: any) {
|
export default function ModuleForm(props: any) {
|
||||||
const { refetch } = useQuery(getUserRoles());
|
|
||||||
const token = localStorage.getItem("auth_token");
|
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({
|
const form = useForm({
|
||||||
defaultValues: { role: props.i.role },
|
defaultValues: {
|
||||||
|
role: role,
|
||||||
|
},
|
||||||
onSubmit: async ({ value }) => {
|
onSubmit: async ({ value }) => {
|
||||||
const data = {
|
const data: any = {
|
||||||
username: props.username,
|
username: props.user.username,
|
||||||
module: props.i.name,
|
module: props.module.name,
|
||||||
role: value.role,
|
role: value.role,
|
||||||
};
|
};
|
||||||
console.log(data);
|
console.log(data);
|
||||||
@@ -37,7 +41,7 @@ export default function ModuleForm(props: any) {
|
|||||||
|
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
toast.success(res.data.message);
|
toast.success(res.data.message);
|
||||||
refetch();
|
props.refetch();
|
||||||
form.reset();
|
form.reset();
|
||||||
} else {
|
} else {
|
||||||
res.data.message;
|
res.data.message;
|
||||||
@@ -49,16 +53,13 @@ export default function ModuleForm(props: any) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="m-2 p-1">
|
<div className="">
|
||||||
<LstCard>
|
|
||||||
<p className="text-center">Module: {props.i.name}</p>
|
|
||||||
|
|
||||||
<p className="p-1">Current role: </p>
|
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
|
className="flex flex-row"
|
||||||
>
|
>
|
||||||
<form.Field
|
<form.Field
|
||||||
name="role"
|
name="role"
|
||||||
@@ -67,7 +68,7 @@ export default function ModuleForm(props: any) {
|
|||||||
return (
|
return (
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
<Label htmlFor={field.name}>
|
<Label htmlFor={field.name}>
|
||||||
Select role
|
Module: {props.module.name}
|
||||||
</Label>
|
</Label>
|
||||||
<Select
|
<Select
|
||||||
value={field.state.value}
|
value={field.state.value}
|
||||||
@@ -113,7 +114,6 @@ export default function ModuleForm(props: any) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</LstCard>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,12 @@ import axios from "axios";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
import { CardHeader } from "@/components/ui/card";
|
import { CardHeader } from "@/components/ui/card";
|
||||||
|
import ModuleAccess from "./ModuleAccess";
|
||||||
|
|
||||||
export default function UserCard(data: any) {
|
export default function UserCard(data: any) {
|
||||||
const token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
const { refetch } = useQuery(getUsers());
|
const { refetch } = useQuery(getUsers());
|
||||||
|
|
||||||
//console.log(modules);
|
|
||||||
//console.log(data.user);
|
|
||||||
//console.log(userRoles);
|
//console.log(userRoles);
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
...userFormOptions(data.user),
|
...userFormOptions(data.user),
|
||||||
@@ -268,13 +267,17 @@ export default function UserCard(data: any) {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</form>
|
<div className="mt-4 ml-4">
|
||||||
</LstCard>
|
|
||||||
<div className="mt-4">
|
|
||||||
<Button onClick={form.handleSubmit}>Save</Button>
|
<Button onClick={form.handleSubmit}>Save</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<ModuleAccess user={data.user} refetch={refetch} />
|
||||||
|
</LstCard>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col"></div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ export const useGetUserRoles = create<SettingState>()((set) => ({
|
|||||||
try {
|
try {
|
||||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||||
const token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
|
if (token) {
|
||||||
const response = await axios.get("/api/auth/getuseraccess", {
|
const response = await axios.get("/api/auth/getuseraccess", {
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
const data: FetchModulesResponse = response.data; //await response.json();
|
const data: FetchModulesResponse = response.data; //await response.json();
|
||||||
|
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
set({ userRoles: data.data });
|
set({ userRoles: data.data });
|
||||||
|
} else {
|
||||||
|
//console.log(data);
|
||||||
|
set({ userRoles: [] });
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch settings:", error);
|
console.error("Failed to fetch settings:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function getUsers() {
|
|||||||
queryFn: () => fetchUsers(token),
|
queryFn: () => fetchUsers(token),
|
||||||
enabled: !!token, // Prevents query if token is null
|
enabled: !!token, // Prevents query if token is null
|
||||||
staleTime: 1000,
|
staleTime: 1000,
|
||||||
//refetchInterval: 2 * 2000,
|
refetchInterval: 2 * 2000,
|
||||||
refetchOnWindowFocus: true,
|
refetchOnWindowFocus: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,42 @@ import {User} from "@/types/users";
|
|||||||
|
|
||||||
// user will need access to the module.
|
// user will need access to the module.
|
||||||
// users role will determine there visual access
|
// 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
|
// get the modules for the id
|
||||||
const filteredModule = modules?.filter((f) => f.name === moduleName);
|
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,
|
// 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 (role.includes("viewer")) return true;
|
||||||
if (!user) return false;
|
if (!user) return false;
|
||||||
|
|
||||||
// get only the module in the user profile
|
// get only the module in the user profile
|
||||||
|
//console.log(user);
|
||||||
const userRole = user?.roles.filter((role) => role.module_id === module_id);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import { userRoles } from "../../../../../database/schema/userRoles.js";
|
||||||
import { users } from "../../../../../database/schema/users.js";
|
import { users } from "../../../../../database/schema/users.js";
|
||||||
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
|
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
@@ -9,8 +10,25 @@ export const getAllUsers = async () => {
|
|||||||
* returns all users that are in lst
|
* returns all users that are in lst
|
||||||
*/
|
*/
|
||||||
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
||||||
|
|
||||||
|
// get all users
|
||||||
const { data, error } = await tryCatch(db.select().from(users));
|
const { data, error } = await tryCatch(db.select().from(users));
|
||||||
|
|
||||||
|
// 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) {
|
if (error) {
|
||||||
returnRes(
|
returnRes(
|
||||||
false,
|
false,
|
||||||
@@ -19,6 +37,6 @@ export const getAllUsers = async () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
returnRes(true, "All users.", data);
|
//returnRes(true, "All users.", data);
|
||||||
return { success: true, message: "All users", data };
|
return { success: true, message: "All users", data: userData };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,11 +54,17 @@ export const setUserAccess = async (
|
|||||||
|
|
||||||
// set the user
|
// set the user
|
||||||
try {
|
try {
|
||||||
const userRole = await db.insert(userRoles).values({
|
const userRole = await db
|
||||||
|
.insert(userRoles)
|
||||||
|
.values({
|
||||||
user_id: user[0].user_id,
|
user_id: user[0].user_id,
|
||||||
role_id: role[0].role_id,
|
role_id: role[0].role_id,
|
||||||
module_id: module[0].module_id,
|
module_id: module[0].module_id,
|
||||||
role: roleName,
|
role: roleName,
|
||||||
|
})
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: userRoles.user_id,
|
||||||
|
set: { role_id: role[0].role_id, role: roleName },
|
||||||
});
|
});
|
||||||
//.returning({user: users.username, email: users.email});
|
//.returning({user: users.username, email: users.email});
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ app.openapi(
|
|||||||
{
|
{
|
||||||
success: access.success,
|
success: access.success,
|
||||||
message: access.message,
|
message: access.message,
|
||||||
data: access.data,
|
data: [], //access?.data,
|
||||||
},
|
},
|
||||||
200
|
200
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user