Skip to content

Commit 73be29a

Browse files
authored
Merge pull request #27 from grycap/vo-filter
Allow select only user's VOs
2 parents aff8c97 + 435d5fa commit 73be29a

File tree

6 files changed

+51
-10
lines changed

6 files changed

+51
-10
lines changed

src/contexts/AuthContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ type EGISessionInfo = {
2323
preferred_username: string; // Nombre de usuario preferido
2424
sub: string; // Identificador único del usuario
2525
voperson_verified_email: string[]; // Lista de correos electrónicos verificados
26+
27+
group_membership: string[];
2628
};
2729

2830
export type AuthData = {

src/lib/utils.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { AuthData } from "@/contexts/AuthContext";
2+
import { SystemConfig } from "@/models/systemConfig";
13
import { type ClassValue, clsx } from "clsx"
24
import { twMerge } from "tailwind-merge"
35

@@ -70,6 +72,42 @@ export function isVersionLower(version: string, target: string) {
7072
return false;
7173
}
7274

75+
export function getUserVOs(authData: AuthData): string[] {
76+
const vos: string[] = [];
77+
if (authData.egiSession?.eduperson_entitlement) {
78+
authData.egiSession.eduperson_entitlement.forEach((entitlement) => {
79+
// "urn:mace:egi.eu:group:vo.example.eu:role=member#aai.egi.eu"
80+
const match = entitlement.match(/^urn:mace:egi\.eu:group:(vo\..+?):role=member(?:#|$)/);
81+
if (match && match[1]) {
82+
vos.push(match[1]);
83+
}
84+
});
85+
}
86+
if (authData.egiSession?.group_membership) {
87+
authData.egiSession.group_membership.forEach((group) => {
88+
// "/employees/vo.example.eu"
89+
const match = group.match(/^\/.*\/(vo\..+)$/);
90+
if (match && match[1]) {
91+
vos.push(match[1]);
92+
}
93+
});
94+
}
95+
return vos;
96+
}
97+
98+
export function getAllowedVOs(systemConfig: {config: SystemConfig} | null, authData: AuthData): string[] {
99+
if (!systemConfig || !systemConfig.config || !systemConfig.config.oidc_groups || systemConfig.config.oidc_groups.length === 0) return [];
100+
// If user is oscar, return all allowed VOs from system config
101+
if (authData.user === "oscar") return systemConfig.config.oidc_groups;
102+
// Get user's VOs
103+
const userVOs = getUserVOs(authData);
104+
// If user has no VOs, return all allowed VOs from system config
105+
if (userVOs.length === 0) return systemConfig.config.oidc_groups;
106+
// Filter allowed VOs based on user's VOs
107+
const filteredVOs = systemConfig.config.oidc_groups.filter((vo) => userVOs.includes(vo));
108+
return filteredVOs;
109+
}
110+
73111
function sleep(ms: number) {
74112
return new Promise(resolve => setTimeout(resolve, ms));
75-
}
113+
}

src/pages/ui/flows/components/FlowsFormPopover/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ import { useMinio } from "@/contexts/Minio/MinioContext";
1515
import { Info, Plus, RefreshCcwIcon } from "lucide-react";
1616
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
1717
import RequestButton from "@/components/RequestButton";
18-
import { generateReadableName, genRandomString } from "@/lib/utils";
18+
import { generateReadableName, genRandomString, getAllowedVOs } from "@/lib/utils";
1919

2020

2121

2222
function FlowsFormPopover() {
2323
const { buckets } = useMinio();
2424
const [isOpen, setIsOpen] = useState(false);
25-
const {systemConfig, clusterInfo } = useAuth();
25+
const {systemConfig, clusterInfo, authData } = useAuth();
2626
const { refreshServices } = useServicesContext();
2727
const [newBucket, setNewBucket] = useState(false);
2828

29-
const oidcGroups = systemConfig?.config?.oidc_groups ?? [];
29+
const oidcGroups = getAllowedVOs(systemConfig, authData);
3030

3131
function nameService() {
3232
return `flows-${generateReadableName(6)}-${genRandomString(8).toLowerCase()}`;

src/pages/ui/hub/components/HubServiceConfPopover/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Label } from "@/components/ui/label";
77
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
88
import { useAuth } from "@/contexts/AuthContext";
99
import { alert } from "@/lib/alert";
10-
import { generateReadableName, genRandomString } from "@/lib/utils";
10+
import { generateReadableName, genRandomString, getAllowedVOs } from "@/lib/utils";
1111
import useServicesContext from "@/pages/ui/services/context/ServicesContext";
1212
import { Service } from "@/pages/ui/services/models/service";
1313
import OscarColors from "@/styles";
@@ -26,10 +26,10 @@ interface HubServiceConfPopoverProps {
2626
}
2727

2828
function HubServiceConfPopover({ roCrateServiceDef, service, isOpen = false, setIsOpen, className = "", variant = "default", title = "Deploy Service" }: HubServiceConfPopoverProps) {
29-
const {systemConfig } = useAuth();
29+
const {systemConfig, authData } = useAuth();
3030
const { refreshServices } = useServicesContext();
3131

32-
const oidcGroups = systemConfig?.config.oidc_groups ?? [];
32+
const oidcGroups = getAllowedVOs(systemConfig, authData);
3333
const asyncService = roCrateServiceDef.type.toLowerCase() === "asynchronous";
3434

3535
function nameService() {

src/pages/ui/juno/components/JunoFormPopover/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
88
import { useAuth } from "@/contexts/AuthContext";
99
import { useMinio } from "@/contexts/Minio/MinioContext";
1010
import { alert } from "@/lib/alert";
11-
import { generateReadableName, genRandomString } from "@/lib/utils";
11+
import { generateReadableName, genRandomString, getAllowedVOs } from "@/lib/utils";
1212
import yamlToServices from "@/pages/ui/services/components/FDL/utils/yamlToService";
1313
import useServicesContext from "@/pages/ui/services/context/ServicesContext";
1414
import { Service } from "@/pages/ui/services/models/service";
@@ -24,7 +24,7 @@ function JunoFormPopover() {
2424
const { refreshServices } = useServicesContext();
2525
const [newBucket, setNewBucket] = useState(false);
2626

27-
const oidcGroups = systemConfig?.config.oidc_groups ?? [];
27+
const oidcGroups = getAllowedVOs(systemConfig, authData);
2828

2929
function nameService() {
3030
return `juno-${generateReadableName(6)}-${genRandomString(8).toLowerCase()}`;

src/pages/ui/services/components/ServiceForm/components/GeneralTab/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ import EnviromentSecrets from "./components/EnviromentSecrets";
2525
import Annotations from "./components/Annotations";
2626

2727
import { AllowedUsersPopover } from "./components/AllowedUsersPopover";
28+
import { getAllowedVOs } from "@/lib/utils";
2829

2930
function ServiceGeneralTab() {
3031
const { formService, setFormService, formMode, formFunctions } =
3132
useServicesContext();
3233

3334
const { handleChange, onBlur, errors } = formFunctions;
3435
const { systemConfig, authData } = useAuth();
35-
const voGroups = systemConfig?.config.oidc_groups;
36+
const voGroups = getAllowedVOs(systemConfig, authData);
3637
function voGroupsIsEmpthy(){
3738
if( voGroups === undefined){ return true}
3839
else if (JSON.stringify(voGroups) === '[""]'){ return true}

0 commit comments

Comments
 (0)