feat: add multi-BU tenancy with per-user team scoping (Option B)
- Add bu_teams column to users table (migration + fresh schema) - Create shared KNOWN_TEAMS constant and validateTeams helper - Expose user teams in auth middleware, login, and /me responses - Add bu_teams CRUD to user management routes with audit logging - Make Ivanti FINDINGS_FILTERS configurable via IVANTI_BU_FILTER env var - Add query-time team filtering to GET /findings and /findings/counts - Update AuthContext with teams helpers and admin scope toggle - Create AdminScopeToggle component (My Teams / All BUs) - Scope ReportingPage findings fetch by user teams - Scope CompliancePage team selector by user teams - Scope ExportsPage findings exports by user teams - Add BU teams multi-select to UserManagement create/edit forms - Display team badges in user list table
This commit is contained in:
@@ -2,6 +2,9 @@ import React, { createContext, useContext, useState, useEffect, useCallback } fr
|
||||
|
||||
const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api';
|
||||
|
||||
// Known BU teams — must match backend helpers/teams.js
|
||||
const KNOWN_TEAMS = ['STEAM', 'ACCESS-ENG', 'ACCESS-OPS', 'INTELDEV'];
|
||||
|
||||
const AuthContext = createContext(null);
|
||||
|
||||
export function AuthProvider({ children }) {
|
||||
@@ -9,6 +12,11 @@ export function AuthProvider({ children }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
// Admin scope toggle — persisted in localStorage
|
||||
const [adminScope, setAdminScope] = useState(
|
||||
() => localStorage.getItem('admin_bu_scope') || 'my-teams'
|
||||
);
|
||||
|
||||
// Check if user is authenticated on mount
|
||||
const checkAuth = useCallback(async () => {
|
||||
try {
|
||||
@@ -93,6 +101,46 @@ export function AuthProvider({ children }) {
|
||||
// Check if user is admin
|
||||
const isAdmin = () => isInGroup('Admin');
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Multi-BU tenancy helpers
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// Whether the user has any BU teams assigned
|
||||
const hasTeams = () => (user?.teams?.length ?? 0) > 0;
|
||||
|
||||
// Whether the user is a member of a specific team (or is Admin in "All BUs" mode)
|
||||
const isTeamMember = (team) => {
|
||||
if (!user) return false;
|
||||
if (isInGroup('Admin') && adminScope === 'all') return true;
|
||||
return (user.teams || []).includes(team);
|
||||
};
|
||||
|
||||
// Toggle admin scope between 'my-teams' and 'all'
|
||||
const toggleAdminScope = () => {
|
||||
setAdminScope(prev => {
|
||||
const next = prev === 'my-teams' ? 'all' : 'my-teams';
|
||||
localStorage.setItem('admin_bu_scope', next);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
// Returns the comma-joined teams string for API query params.
|
||||
// Empty string means "no filter" (show all).
|
||||
const getActiveTeamsParam = () => {
|
||||
if (!user) return '';
|
||||
if (isInGroup('Admin') && adminScope === 'all') return '';
|
||||
const teams = user.teams || [];
|
||||
return teams.join(',');
|
||||
};
|
||||
|
||||
// Returns the list of teams available for UI selectors (compliance team picker, etc.)
|
||||
// Admin in "All BUs" mode sees all known teams; otherwise scoped to user's teams.
|
||||
const getAvailableTeams = () => {
|
||||
if (!user) return [];
|
||||
if (isInGroup('Admin') && adminScope === 'all') return KNOWN_TEAMS;
|
||||
return user.teams || [];
|
||||
};
|
||||
|
||||
const value = {
|
||||
user,
|
||||
loading,
|
||||
@@ -105,7 +153,15 @@ export function AuthProvider({ children }) {
|
||||
canDelete,
|
||||
canExport,
|
||||
isAdmin,
|
||||
isAuthenticated: !!user
|
||||
isAuthenticated: !!user,
|
||||
// Multi-BU tenancy
|
||||
hasTeams,
|
||||
isTeamMember,
|
||||
adminScope,
|
||||
toggleAdminScope,
|
||||
getActiveTeamsParam,
|
||||
getAvailableTeams,
|
||||
KNOWN_TEAMS,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user