Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/AppLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function Layout({ children = null }) {
(state) => state.user.currentAccessibleModules,
);
const pluggedNavigation = useSelector(
(state) => state.user.pluggedNavigation,
(state) => state.user.currentPluggedNavigation,
);
const unreadCount = useSelector((state) => state.notification.unreadCount);
const profilePhoto = useSelector((state) => state.user.profilePhoto);
Expand Down
2 changes: 1 addition & 1 deletion src/helper/validateauth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function ValidateAuth() {
last_selected_role,
roll_no,
must_complete_profile = false,
plugged_navigation = [],
plugged_navigation = {},
} = data;

dispatch(setUserName(name));
Expand Down
7 changes: 5 additions & 2 deletions src/redux/userslice.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const userSlice = createSlice({
authChecked: false, // /api/auth/me has resolved (gates route rendering)
programmeType: null, // UG | PG | PHD — decides which academic pages exist
profilePhoto: "", // student's own photo, shown on the sidebar avatar
pluggedNavigation: [], // menus contributed by modules another service serves
pluggedNavigation: {}, // Format---> {role: [section]}, from other services
currentPluggedNavigation: [], // the acting role's share of the above
},
reducers: {
setProgrammeType: (state, action) => {
Expand Down Expand Up @@ -43,14 +44,16 @@ const userSlice = createSlice({
state.role = action.payload;
},
setPluggedNavigation: (state, action) => {
state.pluggedNavigation = action.payload ?? [];
state.pluggedNavigation = action.payload ?? {};
},
setAccessibleModules: (state, action) => {
state.accessibleModules = action.payload;
},
setCurrentAccessibleModules: (state) => {
state.currentAccessibleModules =
state.accessibleModules[state.role] || {};
state.currentPluggedNavigation =
state.pluggedNavigation[state.role] || [];
},
clearUserName: (state) => {
state.username = "User";
Expand Down
36 changes: 36 additions & 0 deletions src/redux/userslice.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, it } from "vitest";

import reducer, {
setAccessibleModules,
setCurrentAccessibleModules,
setPluggedNavigation,
setRole,
} from "./userslice";

const placement = [
{ section: "Placement", items: [{ code: "placement_cell", links: [] }] },
];
const leave = [{ section: "Leave", items: [{ code: "leave", links: [] }] }];

const stateFor = (role) =>
[
setAccessibleModules({
student: { placement_cell: true },
acadadmin: { leave: true },
}),
setPluggedNavigation({ student: placement, acadadmin: leave }),
setRole(role),
setCurrentAccessibleModules(),
].reduce(reducer, undefined);

describe("the acting role's own sidebar", () => {
it("gives a role only the menus granted to it", () => {
expect(stateFor("student").currentPluggedNavigation).toEqual(placement);
expect(stateFor("acadadmin").currentPluggedNavigation).toEqual(leave);
});

it("draws nothing for a role that was granted nothing", () => {
expect(stateFor("faculty").currentPluggedNavigation).toEqual([]);
expect(stateFor("faculty").currentAccessibleModules).toEqual({});
});
});
5 changes: 4 additions & 1 deletion src/ui/routing/PluggedModule.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ export function PluggedModule({ title }) {
className={classes.frame}
src={src}
title={title}
// Same institute, same session; it needs its cookie and nothing beyond.
// Not a boundary: same-origin plus scripts lets the frame drop its own
// sandbox, and it needs both. The frame is trusted because it is ours and
// the origin is ours; what keeps that true is that nothing else — an
// upload above all — is ever served from this origin as a page.
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-downloads"
/>
);
Expand Down
Loading