1- import React , { useEffect , useState } from "react" ;
1+ import React , { useEffect , useMemo , useState } from "react" ;
22import { useLocation , useNavigate } from "react-router-dom" ;
33import { useAppStore } from "../stores/AppStore" ;
44import I18n from "../locale/I18n" ;
@@ -13,7 +13,6 @@ import {
1313import UserIcon from "@surfnet/sds/icons/functional-icons/id-2.svg" ;
1414import UpIcon from "@surfnet/sds/icons/functional-icons/arrow-up-2.svg" ;
1515import DownIcon from "@surfnet/sds/icons/functional-icons/arrow-down-2.svg" ;
16- import WarningIcon from "@surfnet/sds/icons/functional-icons/alert-triangle.svg" ;
1716import {
1817 eduidIdentityProvider ,
1918 newInvitation ,
@@ -106,6 +105,37 @@ export const InvitationForm = () => {
106105 useAppStore . setState ( { breadcrumbPath : breadcrumbPath } ) ;
107106 } , [ user ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
108107
108+ const acrWarning = useMemo ( ( ) => {
109+ if ( isEmpty ( invitation . requestedAuthnContext ) || isEmpty ( eduIDIdP ) || isEmpty ( selectedRoles ) ) {
110+ return null ;
111+ }
112+ //Filter out the roles that are linked to applications that are not present in the mfaEntities of the eduIDIdp
113+ //or where the MFA level does not equal the requestedAuthnContext. If the requestedAuthnContext === TransparentAuthnContext,
114+ //then we skip the warning
115+ const mfaEntities = eduIDIdP . mfaEntities ;
116+ const acrValue = acrValues [ invitation . requestedAuthnContext ] ;
117+ const missingEntities = selectedRoles . reduce ( ( acc , role ) => {
118+ const missingMfaApps = role . applicationMaps
119+ . filter ( app => {
120+ const mfa = mfaEntities . find ( mfa => mfa . name === app . entityid ) ;
121+ return isEmpty ( mfa ) || ( mfa . level !== acrValue && mfa . level !== acrValues . TransparentAuthnContext ) ;
122+ } ) ;
123+ if ( ! isEmpty ( missingMfaApps ) ) {
124+ acc . applications = acc . applications . concat ( missingMfaApps . map ( app => app [ `name:${ I18n . locale } ` ] || app [ "name:en" ] ) ) ;
125+ acc . roles . push ( role . name )
126+ }
127+ return acc ;
128+ } , { applications : [ ] , roles : [ ] } )
129+ if ( isEmpty ( missingEntities . roles ) ) {
130+ return null ;
131+ }
132+ const roleNames = splitListSemantically ( missingEntities . roles , I18n . t ( "forms.and" ) ) ;
133+ const applicationNames = splitListSemantically ( missingEntities . applications , I18n . t ( "forms.and" ) ) ;
134+ return DOMPurify . sanitize ( I18n . t ( "invitations.requestedAuthnContextWarning" ,
135+ { roles : roleNames , applications : applicationNames } ) ) ;
136+
137+ } ,
138+ [ invitation . requestedAuthnContext , eduIDIdP , selectedRoles , acrValues ] )
109139
110140 const setInitialRole = markedRoles => {
111141 const urlSearchParams = new URLSearchParams ( window . location . search ) ;
@@ -255,37 +285,6 @@ export const InvitationForm = () => {
255285 }
256286 }
257287
258- const renderACRWarnings = ( ) => {
259- if ( isEmpty ( invitation . requestedAuthnContext ) || isEmpty ( eduIDIdP ) || isEmpty ( selectedRoles ) ) {
260- return null ;
261- }
262- //Filter out the roles that are linked to applications that are not present in the mfaEntities of the eduIDIdp
263- //or where the MFA level does not equal the requestedAuthnContext. If the requestedAuthnContext === TransparentAuthnContext,
264- //then we skip the warning
265- const mfaEntities = eduIDIdP . mfaEntities ;
266- const acrValue = acrValues [ invitation . requestedAuthnContext ] ;
267- const missingEntities = selectedRoles . reduce ( ( acc , role ) => {
268- const missingMfaApps = role . applicationMaps
269- . filter ( app => {
270- const mfa = mfaEntities . find ( mfa => mfa . name === app . entityid ) ;
271- return isEmpty ( mfa ) || ( mfa . level !== acrValue && mfa . level !== acrValues . TransparentAuthnContext ) ;
272- } ) ;
273- if ( ! isEmpty ( missingMfaApps ) ) {
274- acc . applications = acc . applications . concat ( missingMfaApps . map ( app => app [ `name:${ I18n . locale } ` ] || app [ "name:en" ] ) ) ;
275- acc . roles . push ( role . name )
276- }
277- return acc ;
278- } , { applications : [ ] , roles : [ ] } )
279- if ( isEmpty ( missingEntities . roles ) ) {
280- return null ;
281- }
282- const roleNames = splitListSemantically ( missingEntities . roles , I18n . t ( "forms.and" ) ) ;
283- const applicationNames = splitListSemantically ( missingEntities . applications , I18n . t ( "forms.and" ) ) ;
284- const html = DOMPurify . sanitize ( I18n . t ( "invitations.requestedAuthnContextWarning" ,
285- { roles : roleNames , applications : applicationNames } ) ) ;
286- return < p className = "warning" dangerouslySetInnerHTML = { { __html : html } } />
287- }
288-
289288 const authorityChanged = option => {
290289 setInvitation ( {
291290 ...invitation ,
@@ -478,7 +477,8 @@ export const InvitationForm = () => {
478477 clearable = { true }
479478 onChange = { requestedAuthnContextChanged }
480479 >
481- { renderACRWarnings ( ) }
480+ { acrWarning &&
481+ < p className = "warning" dangerouslySetInnerHTML = { { __html : acrWarning } } /> }
482482 </ SelectField > }
483483
484484 { ( invitation . intendedAuthority !== AUTHORITIES . GUEST && ! isInviter &&
0 commit comments