feat: IsEligible authproc filter and claim source
parent
bfb143365b
commit
2e0aaa772b
|
@ -75,10 +75,6 @@ contact_p=V p\u0159\u00EDpad\u011B nejasnost\u00ED n\u00E1s kontaktujte na
|
||||||
403_informationPage=Pro v\u00EDce informac\u00ED o slu\u017Eb\u011B nav\u0161tivte
|
403_informationPage=Pro v\u00EDce informac\u00ED o slu\u017Eb\u011B nav\u0161tivte
|
||||||
403_contactSupport=Pokud si mysl\u00EDte \u017Ee m\u00E1te m\u00EDt p\u0159\u00EDstup, kontaktujte administr\u00E1tora:
|
403_contactSupport=Pokud si mysl\u00EDte \u017Ee m\u00E1te m\u00EDt p\u0159\u00EDstup, kontaktujte administr\u00E1tora:
|
||||||
403_subject=Probl\u00E9m s p\u0159ihl\u00E1\u0161en\u00EDm do slu\u017Eby
|
403_subject=Probl\u00E9m s p\u0159ihl\u00E1\u0161en\u00EDm do slu\u017Eby
|
||||||
403_isCesnetEligible_notSet_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
|
||||||
403_isCesnetEligible_notSet_msg=P\u0159\u00EDstup ke slu\u017Eb\u011B zam\u00EDtnut, proto\u017Ee V\u00E1\u0161 \u00FA\u010Det nen\u00ED z \u010Desk\u00E9 akademick\u00E9 instituce. P\u0159ihlaste se, pros\u00EDm, pomoc\u00ED sv\u00E9ho \u00FA\u010Dtu u akademick\u00E9 instituce.<br/><a class="mt-2 cw btn btn-primary btn-lg btn-block" href="%%TARGET%%">Znovu p\u0159ihl\u00E1sit</a>
|
|
||||||
403_isCesnetEligible_expired_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
|
||||||
403_isCesnetEligible_expired_msg=P\u0159\u00EDstup ke slu\u017Eb\u011B zam\u00EDtnut, proto\u017Ee plynula doba 12 m\u011Bs\u00EDc\u016F od Va\u0161eho posledn\u00EDho p\u0159ihl\u00E1\u0161en\u00ED \u00FA\u010Dtem z \u010Desk\u00E9 akademick\u00E9 instituce. P\u0159ihlaste se, pros\u00EDm, pomoc\u00ED sv\u00E9ho \u00FA\u010Dtu u akademick\u00E9 instituce.<br/><a class="mt-2 cw btn btn-lg btn-primary btn-block" href="%%TARGET%%">Znovu p\u0159ihl\u00E1sit</a>
|
|
||||||
403_ensure_vo_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
403_ensure_vo_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
||||||
403_ensure_vo_msg=Nem\u00E1te dostate\u010Dn\u00E1 pr\u00E1va pro p\u0159\u00EDstup ke slu\u017Eb\u011B
|
403_ensure_vo_msg=Nem\u00E1te dostate\u010Dn\u00E1 pr\u00E1va pro p\u0159\u00EDstup ke slu\u017Eb\u011B
|
||||||
403_authorization_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
403_authorization_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
||||||
|
@ -92,6 +88,11 @@ contact_p=V p\u0159\u00EDpad\u011B nejasnost\u00ED n\u00E1s kontaktujte na
|
||||||
403_not_logged_in_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
403_not_logged_in_hdr=P\u0159\u00EDstup zam\u00EDtnut
|
||||||
403_not_logged_in_msg=Zd\u00E1 se, \u017Ee p\u0159ihl\u00E1\u0161en\u00ED selhalo. Zkuste, pros\u00EDm, zav\u0159\u00EDt V\u00E1\u0161 prohl\u00ED\u017Ee\u010D a p\u0159ihl\u00E1sit se znovu.
|
403_not_logged_in_msg=Zd\u00E1 se, \u017Ee p\u0159ihl\u00E1\u0161en\u00ED selhalo. Zkuste, pros\u00EDm, zav\u0159\u00EDt V\u00E1\u0161 prohl\u00ED\u017Ee\u010D a p\u0159ihl\u00E1sit se znovu.
|
||||||
|
|
||||||
|
403_is_eligible_default_header_text=P\u0159\u00EDstup zam\u00EDtnut
|
||||||
|
403_is_eligible_default_text=P\u0159\u00EDstup ke slu\u017Eb\u011B byl zam\u00EDtnut, proto\u017Ee V\u00E1\u0161 \u00FA\u010Det nespl\u0148uje pomd\u00EDnky p\u0159\u00EDstupu. P\u0159ihlaste se, pros\u00EDme, pomoc\u00ED jin\u00E9ho \u00FA\u010Dtu.
|
||||||
|
403_is_eligible_default_button_text=Pokra\u010Dovat
|
||||||
|
403_is_eligible_default_contact_text=Pokud si mysl\u00EDte, \u017Ee pou\u017E\u00EDv\u00E1te spr\u00E1vn\u00FD \u00FA\u010Det a p\u0159\u00EDstup je V\u00E1m odm\u00EDtnut nepr\u00E1vem, pros\u00EDme kontakujte n\u00E1s na
|
||||||
|
|
||||||
#GO TO REGISTRATION
|
#GO TO REGISTRATION
|
||||||
go_to_registration_title=Je vy\u017Eadov\u00E1na Va\u0161e aktivita
|
go_to_registration_title=Je vy\u017Eadov\u00E1na Va\u0161e aktivita
|
||||||
go_to_registration_header1=Pro p\u0159\u00EDstup ke slu\u017Eb\u011B
|
go_to_registration_header1=Pro p\u0159\u00EDstup ke slu\u017Eb\u011B
|
||||||
|
|
|
@ -74,10 +74,6 @@ contact_p=In case of any questions, do not hesitate to contact us at
|
||||||
403_informationPage=For more information about this service please visit this
|
403_informationPage=For more information about this service please visit this
|
||||||
403_contactSupport=If you think you should have an access contact service operator at
|
403_contactSupport=If you think you should have an access contact service operator at
|
||||||
403_subject=Problem with login to service:
|
403_subject=Problem with login to service:
|
||||||
403_isCesnetEligible_notSet_hdr=Access denied
|
|
||||||
403_isCesnetEligible_notSet_msg=Your account is not from Czech academic institution. Please log in with your account from academic institution.<a class="mt-2 cw btn btn-primary btn-lg btn-block" href="%%TARGET%%">Log in again</a>
|
|
||||||
403_isCesnetEligible_expired_hdr=Access denied
|
|
||||||
403_isCesnetEligible_expired_msg=Your last login, from Czech academic institution, has been registered 12 months ago. Please sign in with your account from academic institution.<a class="mt-2 cw btn btn-primary btn-lg btn-block" href="%%TARGET%%">Log in again</a>
|
|
||||||
403_ensure_vo_hdr=Access denied
|
403_ensure_vo_hdr=Access denied
|
||||||
403_ensure_vo_msg=You don't meet the prerequisites to access the service.
|
403_ensure_vo_msg=You don't meet the prerequisites to access the service.
|
||||||
403_authorization_hdr=Access denied
|
403_authorization_hdr=Access denied
|
||||||
|
@ -91,6 +87,11 @@ contact_p=In case of any questions, do not hesitate to contact us at
|
||||||
403_not_logged_in_hdr=Access denied
|
403_not_logged_in_hdr=Access denied
|
||||||
403_not_logged_in_msg=It appears the login process has failed. Please close your browser and try to log in again.
|
403_not_logged_in_msg=It appears the login process has failed. Please close your browser and try to log in again.
|
||||||
|
|
||||||
|
403_is_eligible_default_header_text=Access denied
|
||||||
|
403_is_eligible_default_text=Your account does not meet the criteria for accessing the service. Please log in with other account.
|
||||||
|
403_is_eligible_default_button_text=Continue with other account.
|
||||||
|
403_is_eligible_default_contact_text=If you think you have used an account which meets the criteria, and you are still prevented from logging in to the service, please contact us at
|
||||||
|
|
||||||
#GO TO REGISTRATION
|
#GO TO REGISTRATION
|
||||||
go_to_registration_title=Your activity is necessary
|
go_to_registration_title=Your activity is necessary
|
||||||
go_to_registration_header1=Your activity is necessary to access the
|
go_to_registration_header1=Your activity is necessary to access the
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||||
|
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||||
|
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
|
||||||
|
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
|
||||||
|
<%@ taglib prefix="ls" tagdir="/WEB-INF/tags/lsaai" %>
|
||||||
|
|
||||||
|
<ls:header />
|
||||||
|
|
||||||
|
<div class="error_message" style="word-wrap: break-word;">
|
||||||
|
<h1><spring:message code="${outHeader}"/></h1>
|
||||||
|
<p><spring:message code="${outMessage}"/></p>
|
||||||
|
<c:if test="${hasTarget}">
|
||||||
|
<form method="POST" action="" class="mb-4">
|
||||||
|
<button class="btn btn-primary btn-block"><spring:message code="${outButton}"/></button>
|
||||||
|
</form>
|
||||||
|
</c:if>
|
||||||
|
<p><spring:message code="${outContactP}"/>${" "}<a href="mailto:${contactMail}">${contactMail}</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ls:footer/>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" trimDirectiveWhitespaces="true" %>
|
||||||
|
<%@ page import="java.util.ArrayList" %>
|
||||||
|
<%@ page import="java.util.List" %>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||||
|
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
|
||||||
|
<%@ taglib prefix="t" tagdir="/WEB-INF/tags/common"%>
|
||||||
|
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
|
||||||
|
|
||||||
|
<%
|
||||||
|
|
||||||
|
List<String> cssLinks = new ArrayList<>();
|
||||||
|
|
||||||
|
pageContext.setAttribute("cssLinks", cssLinks);
|
||||||
|
|
||||||
|
%>
|
||||||
|
|
||||||
|
<t:header title="${title}" reqURL="${reqURL}" baseURL="${baseURL}" cssLinks="${cssLinks}" theme="${theme}"/>
|
||||||
|
|
||||||
|
</div> <%-- header --%>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
<div class="error_message" style="word-wrap: break-word;">
|
||||||
|
<h1><spring:message code="${outHeader}"/></h1>
|
||||||
|
<p><spring:message code="${outMessage}"/></p>
|
||||||
|
<c:if test="${hasTarget}">
|
||||||
|
<form method="POST" action="" class="mb-4">
|
||||||
|
<button class="btn btn-primary btn-block"><spring:message code="${outButton}"/></button>
|
||||||
|
</form>
|
||||||
|
</c:if>
|
||||||
|
<p><spring:message code="${outContactP}"/>${" "}<a href="mailto:${contactMail}">${contactMail}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- ENDWRAP -->
|
||||||
|
|
||||||
|
<t:footer baseURL="${baseURL}" theme="${theme}"/>
|
|
@ -65,7 +65,7 @@
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_MAPPING}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_MAPPING}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_AUTHORIZATION}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_AUTHORIZATION}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_ENSURE_VO_MAPPING}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_ENSURE_VO_MAPPING}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_IS_CESNET_ELIGIBLE_MAPPING}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_IS_ELIGIBLE_MAPPING}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_PROD_VOS_GROUPS}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_PROD_VOS_GROUPS}**" />
|
||||||
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_TEST_VOS_GROUPS}**" />
|
<mvc:exclude-mapping path="#{T(cz.muni.ics.oidc.web.controllers.PerunUnapprovedController).UNAPPROVED_NOT_IN_TEST_VOS_GROUPS}**" />
|
||||||
|
|
|
@ -65,6 +65,23 @@ public class ClaimUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int fillIntegerPropertyOrDefaultVal(String suffix, ClaimSourceInitContext ctx, int defaultVal) {
|
||||||
|
return fillIntegerPropertyOrDefaultVal(ctx.getProperty(suffix, NO_VALUE), defaultVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int fillIntegerPropertyOrDefaultVal(String prop, int defaultVal) {
|
||||||
|
if (StringUtils.hasText(prop)) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(prop);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("Caught {}", e.getClass().getSimpleName(), e);
|
||||||
|
return defaultVal;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static ArrayNode listToArrayNode(List<String> list) {
|
public static ArrayNode listToArrayNode(List<String> list) {
|
||||||
ArrayNode res = JsonNodeFactory.instance.arrayNode();
|
ArrayNode res = JsonNodeFactory.instance.arrayNode();
|
||||||
if (list != null && !list.isEmpty()) {
|
if (list != null && !list.isEmpty()) {
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package cz.muni.ics.oidc.server.claims.sources;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
|
import cz.muni.ics.oauth2.model.SamlAuthenticationDetails;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSource;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext;
|
||||||
|
import cz.muni.ics.oidc.server.claims.ClaimUtils;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This source checks if the timestamp is within defined months subtracted from the current timestamp.
|
||||||
|
* If so, returns TRUE, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Configuration (replace [claimName] with the name of the claim):
|
||||||
|
* <ul>
|
||||||
|
* <li><b>custom.claim.[claimName].source.attribute</b> - attribute containing the eligibility last seen timestamp passed via SAML authentication</li>
|
||||||
|
* <li><b>custom.claim.[claimName].source.validityPeriodMonths</b> - amount of months that we subtract from the current timestamp and compare it with the eligibility timestamp. If not provided, default 12 months is used</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Pavol Pluta <pavol.pluta1@gmail.com>
|
||||||
|
* @author Dominik Frantisek Bucik <bucik@ics.muni.cz>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class IsEligibleClaimSource extends ClaimSource {
|
||||||
|
|
||||||
|
private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
private static final int DEFAULT_VALIDITY_PERIOD = 12; // 12 months
|
||||||
|
|
||||||
|
private static final String SOURCE_ATTR_NAME = "attribute";
|
||||||
|
private static final String VALIDITY_PERIOD_MONTHS = "validityPeriodMonths";
|
||||||
|
|
||||||
|
private final String sourceAttr;
|
||||||
|
private final int validityPeriodMonths;
|
||||||
|
|
||||||
|
public IsEligibleClaimSource(ClaimSourceInitContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
|
||||||
|
this.sourceAttr = ClaimUtils.fillStringMandatoryProperty(SOURCE_ATTR_NAME, ctx, getClaimName());
|
||||||
|
this.validityPeriodMonths = ClaimUtils.fillIntegerPropertyOrDefaultVal(VALIDITY_PERIOD_MONTHS, ctx, DEFAULT_VALIDITY_PERIOD);
|
||||||
|
log.debug("{} - SAML attribute: '{}', validity period in months: '{}'", getClaimName(), sourceAttr, validityPeriodMonths);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAttrIdentifiers() {
|
||||||
|
return Collections.singleton(sourceAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode produceValue(ClaimSourceProduceContext pctx) {
|
||||||
|
SamlAuthenticationDetails details = pctx.getSamlAuthenticationDetails();
|
||||||
|
if (details == null || details.getAttributes() == null || details.getAttributes().isEmpty()) {
|
||||||
|
log.warn("{} - no attribute set to get the source attribute from, returning FALSE", getClaimName());
|
||||||
|
return JsonNodeFactory.instance.booleanNode(false);
|
||||||
|
}
|
||||||
|
String[] attrValue = details.getAttributes().getOrDefault(sourceAttr, new String[] {});
|
||||||
|
if (attrValue == null || attrValue.length == 0) {
|
||||||
|
log.warn("{} - no attribute to construct value from, returning FALSE", getClaimName());
|
||||||
|
return JsonNodeFactory.instance.booleanNode(false);
|
||||||
|
} else {
|
||||||
|
if (attrValue.length > 1) {
|
||||||
|
log.warn("{} - configured source attribute '{}' has more than one value, will use just the first one", getClaimName(), sourceAttr);
|
||||||
|
}
|
||||||
|
String timestamp = attrValue[0];
|
||||||
|
return JsonNodeFactory.instance.booleanNode(isEligible(timestamp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEligible(String eligibleLastSeenValue) {
|
||||||
|
if (!StringUtils.hasText(eligibleLastSeenValue)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LocalDate eligibleLastSeenTimestamp;
|
||||||
|
try {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
|
||||||
|
eligibleLastSeenTimestamp = LocalDate.parse(eligibleLastSeenValue, formatter);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
log.warn("{} - could not parse value '{}' as timestamp in format '{}'. Returning NOT ELIGIBLE.",
|
||||||
|
getClaimName(), eligibleLastSeenValue, TIMESTAMP_FORMAT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate now = LocalDateTime.now().toLocalDate();
|
||||||
|
boolean isValid = !eligibleLastSeenTimestamp.isBefore(now.minusMonths(validityPeriodMonths));
|
||||||
|
log.debug("{} - timestamp '{}' is time {} the defined period of '{} months'",
|
||||||
|
getClaimName(), eligibleLastSeenTimestamp, isValid ? "within" : "out of", DEFAULT_VALIDITY_PERIOD);
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -357,15 +357,23 @@ public class FiltersUtils {
|
||||||
public static String fillStringMandatoryProperty(String propertyName,
|
public static String fillStringMandatoryProperty(String propertyName,
|
||||||
String filterName,
|
String filterName,
|
||||||
AuthProcFilterInitContext params) {
|
AuthProcFilterInitContext params) {
|
||||||
String filled = params.getProperty(propertyName);
|
String filled = fillStringProperty(propertyName, params, null);
|
||||||
|
|
||||||
if (!StringUtils.hasText(filled)) {
|
if (filled == null) {
|
||||||
throw new IllegalArgumentException("No value configured for '" + propertyName + "' in filter " + filterName);
|
throw new IllegalArgumentException("No value configured for '" + propertyName + "' in filter " + filterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return filled;
|
return filled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String fillStringProperty(String propertyName, AuthProcFilterInitContext params, String defaultValue) {
|
||||||
|
String filled = params.getProperty(propertyName);
|
||||||
|
if (!StringUtils.hasText(filled)) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return filled;
|
||||||
|
}
|
||||||
|
|
||||||
private static void redirectToRegistrationForm(String base, HttpServletResponse response,
|
private static void redirectToRegistrationForm(String base, HttpServletResponse response,
|
||||||
String clientIdentifier, Facility facility, PerunUser user) {
|
String clientIdentifier, Facility facility, PerunUser user) {
|
||||||
Map<String, String> params = new HashMap<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
package cz.muni.ics.oidc.server.filters.impl;
|
||||||
|
|
||||||
|
import cz.muni.ics.oidc.BeanUtil;
|
||||||
|
import cz.muni.ics.oidc.exceptions.ConfigurationException;
|
||||||
|
import cz.muni.ics.oidc.server.configurations.PerunOidcConfig;
|
||||||
|
import cz.muni.ics.oidc.server.filters.AuthProcFilter;
|
||||||
|
import cz.muni.ics.oidc.server.filters.AuthProcFilterCommonVars;
|
||||||
|
import cz.muni.ics.oidc.server.filters.AuthProcFilterConstants;
|
||||||
|
import cz.muni.ics.oidc.server.filters.AuthProcFilterInitContext;
|
||||||
|
import cz.muni.ics.oidc.server.filters.FiltersUtils;
|
||||||
|
import cz.muni.ics.oidc.web.controllers.ControllerUtils;
|
||||||
|
import cz.muni.ics.oidc.web.controllers.PerunUnapprovedController;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
|
import org.springframework.security.saml.SAMLCredential;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This filter verifies that user attribute isCesnetEligible is not older than given time frame.
|
||||||
|
* In case the value is older, denies access to the service and forces user to use verified identity.
|
||||||
|
* Otherwise, user can to access the service.
|
||||||
|
*
|
||||||
|
* Configuration (replace [name] part with the name defined for the filter):
|
||||||
|
* <ul>
|
||||||
|
* <li><b>filter.[name].samlAttribute</b> - mapping to isCesnetEligible attribute</li>
|
||||||
|
* <li><b>filter.[name].triggerScope</b> - scope that has to be requested to apply this filter</li>
|
||||||
|
* <li><b>filter.[name].validityPeriodMonths</b> - specify in months, how long the value can be old, if no value
|
||||||
|
* or invalid value has been provided, defaults to 12 months</li>
|
||||||
|
* </ul>
|
||||||
|
* @author Dominik Frantisek Bucik <bucik@ics.muni.cz>
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class IsEligibleFilter extends AuthProcFilter {
|
||||||
|
|
||||||
|
public static final String APPLIED = "APPLIED_" + IsEligibleFilter.class.getSimpleName();
|
||||||
|
|
||||||
|
public final static String DEFAULT_HEADER_TRANSLATION_KEY = "403_is_eligible_default_header_text";
|
||||||
|
public final static String DEFAULT_TEXT_TRANSLATION_KEY = "403_is_eligible_default_text";
|
||||||
|
public final static String DEFAULT_BUTTON_TRANSLATION_KEY = "403_is_eligible_default_button_text";
|
||||||
|
public final static String DEFAULT_CONTACT_TRANSLATION_KEY = "403_is_eligible_default_contact_text";
|
||||||
|
|
||||||
|
public static final String HEADER_TRANSLATION = "header_translation";
|
||||||
|
public static final String TEXT_TRANSLATION = "text_translation";
|
||||||
|
public static final String BUTTON_TRANSLATION = "button_translation";
|
||||||
|
public static final String CONTACT_TRANSLATION = "contact_translation";
|
||||||
|
|
||||||
|
/* CONFIGURATION PROPERTIES */
|
||||||
|
private static final String SAML_ATTRIBUTE = "samlAttribute";
|
||||||
|
private static final String TRIGGER_SCOPE = "triggerScope";
|
||||||
|
private static final String VALIDITY_PERIOD = "validityPeriodMonths";
|
||||||
|
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
private static final String OLD_VALUE_HEADER_TRANSLATION_KEY = "old_value_header_translation_key";
|
||||||
|
private static final String OLD_VALUE_TEXT_TRANSLATION_KEY = "old_value_text_translation_key";
|
||||||
|
private static final String OLD_VALUE_BUTTON_TRANSLATION_KEY = "old_value_button_translation_key";
|
||||||
|
private static final String OLD_VALUE_CONTACT_TRANSLATION_KEY = "old_value_contact_translation_key";
|
||||||
|
|
||||||
|
private static final String NO_VALUE_HEADER_TRANSLATION_KEY = "no_value_header_translation_key";
|
||||||
|
private static final String NO_VALUE_TEXT_TRANSLATION_KEY = "no_value_text_translation_key";
|
||||||
|
private static final String NO_VALUE_BUTTON_TRANSLATION_KEY = "no_value_button_translation_key";
|
||||||
|
private static final String NO_VALUE_CONTACT_TRANSLATION_KEY = "no_value_contact_translation_key";
|
||||||
|
|
||||||
|
/* END OF CONFIGURATION PROPERTIES */
|
||||||
|
|
||||||
|
private final String eligibleLastSeenSAMLAttributeName;
|
||||||
|
private final String triggerScope;
|
||||||
|
private final int validityPeriod;
|
||||||
|
|
||||||
|
private final String oldValueHeaderTranslationKey;
|
||||||
|
private final String oldValueTextTranslationKey;
|
||||||
|
private final String oldValueButtonTranslationKey;
|
||||||
|
private final String oldValueContactTranslationKey;
|
||||||
|
|
||||||
|
private final String noValueHeaderTranslationKey;
|
||||||
|
private final String noValueTextTranslationKey;
|
||||||
|
private final String noValueButtonTranslationKey;
|
||||||
|
private final String noValueContactTranslationKey;
|
||||||
|
|
||||||
|
private final PerunOidcConfig config;
|
||||||
|
private final String filterName;
|
||||||
|
|
||||||
|
public IsEligibleFilter(AuthProcFilterInitContext ctx) throws ConfigurationException {
|
||||||
|
super(ctx);
|
||||||
|
this.filterName = ctx.getFilterName();
|
||||||
|
|
||||||
|
BeanUtil beanUtil = ctx.getBeanUtil();
|
||||||
|
this.config = beanUtil.getBean(PerunOidcConfig.class);
|
||||||
|
this.eligibleLastSeenSAMLAttributeName = FiltersUtils.fillStringMandatoryProperty(SAML_ATTRIBUTE, filterName, ctx);
|
||||||
|
this.triggerScope = FiltersUtils.fillStringMandatoryProperty(TRIGGER_SCOPE, filterName, ctx);
|
||||||
|
int validityPeriodParam = 12;
|
||||||
|
if (ctx.hasProperty(VALIDITY_PERIOD)) {
|
||||||
|
try {
|
||||||
|
validityPeriodParam = Integer.parseInt(ctx.getProperty(VALIDITY_PERIOD));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
//no problem, we have default value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldValueHeaderTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
OLD_VALUE_HEADER_TRANSLATION_KEY, ctx, DEFAULT_HEADER_TRANSLATION_KEY);
|
||||||
|
this.oldValueTextTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
OLD_VALUE_TEXT_TRANSLATION_KEY, ctx, DEFAULT_TEXT_TRANSLATION_KEY);
|
||||||
|
this.oldValueButtonTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
OLD_VALUE_BUTTON_TRANSLATION_KEY, ctx, DEFAULT_BUTTON_TRANSLATION_KEY);
|
||||||
|
this.oldValueContactTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
OLD_VALUE_CONTACT_TRANSLATION_KEY, ctx, DEFAULT_CONTACT_TRANSLATION_KEY);
|
||||||
|
|
||||||
|
this.noValueHeaderTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
NO_VALUE_HEADER_TRANSLATION_KEY, ctx, DEFAULT_HEADER_TRANSLATION_KEY);
|
||||||
|
this.noValueTextTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
NO_VALUE_TEXT_TRANSLATION_KEY, ctx, DEFAULT_TEXT_TRANSLATION_KEY);
|
||||||
|
this.noValueButtonTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
NO_VALUE_BUTTON_TRANSLATION_KEY, ctx, DEFAULT_BUTTON_TRANSLATION_KEY);
|
||||||
|
this.noValueContactTranslationKey = FiltersUtils.fillStringProperty(
|
||||||
|
NO_VALUE_CONTACT_TRANSLATION_KEY, ctx, DEFAULT_CONTACT_TRANSLATION_KEY);
|
||||||
|
|
||||||
|
this.validityPeriod = validityPeriodParam;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getSessionAppliedParamName() {
|
||||||
|
return APPLIED + filterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean process(HttpServletRequest req, HttpServletResponse res, AuthProcFilterCommonVars params) {
|
||||||
|
if (!FiltersUtils.isScopePresent(req.getParameter(AuthProcFilterConstants.PARAM_SCOPE), triggerScope)) {
|
||||||
|
log.debug("{} - skip execution: scope '{}' is not present in request", filterName, triggerScope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAMLCredential samlCredential = FiltersUtils.getSamlCredential(req);
|
||||||
|
if (samlCredential == null) {
|
||||||
|
log.debug("{} - skip execution: no SAML credential to fetch attribute from is available", filterName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String eligibleLastSeenTimestamp = samlCredential.getAttributeAsString(eligibleLastSeenSAMLAttributeName);
|
||||||
|
|
||||||
|
String headerKey = noValueHeaderTranslationKey;
|
||||||
|
String textKey = noValueTextTranslationKey;
|
||||||
|
String buttonKey = noValueButtonTranslationKey;
|
||||||
|
String contactKey = noValueContactTranslationKey;
|
||||||
|
|
||||||
|
if (StringUtils.hasText(eligibleLastSeenTimestamp)) {
|
||||||
|
LocalDateTime timeStamp;
|
||||||
|
try {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
|
||||||
|
timeStamp = LocalDateTime.parse(eligibleLastSeenTimestamp, formatter);
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
log.warn("{} - could not parse timestamp from attribute '{}' with value '{}'",
|
||||||
|
filterName, eligibleLastSeenSAMLAttributeName, eligibleLastSeenTimestamp);
|
||||||
|
log.debug("{} - skip execution - have no timestamp to compare to", filterName);
|
||||||
|
log.trace("{} - details:", filterName, e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if (now.minusMonths(validityPeriod).isBefore(timeStamp)) {
|
||||||
|
log.debug("{} - attribute '{}' value is valid", filterName, eligibleLastSeenSAMLAttributeName);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
headerKey = oldValueHeaderTranslationKey;
|
||||||
|
textKey = oldValueTextTranslationKey;
|
||||||
|
buttonKey = oldValueButtonTranslationKey;
|
||||||
|
contactKey = oldValueContactTranslationKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpSession sess = req.getSession(true);
|
||||||
|
sess.setAttribute(HEADER_TRANSLATION, headerKey);
|
||||||
|
sess.setAttribute(TEXT_TRANSLATION, textKey);
|
||||||
|
sess.setAttribute(BUTTON_TRANSLATION, buttonKey);
|
||||||
|
sess.setAttribute(CONTACT_TRANSLATION, contactKey);
|
||||||
|
|
||||||
|
log.debug("{} - attribute '{}' value is invalid, stop user at this point", filterName, eligibleLastSeenTimestamp);
|
||||||
|
this.redirect(req, res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void redirect(HttpServletRequest req, HttpServletResponse res) {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
|
||||||
|
String targetURL = FiltersUtils.buildRequestURL(req,
|
||||||
|
Collections.singletonMap(AuthProcFilterConstants.PARAM_PROMPT, "login"));
|
||||||
|
params.put(AuthProcFilterConstants.PARAM_TARGET, targetURL);
|
||||||
|
|
||||||
|
String redirectUrl = ControllerUtils.createRedirectUrl(config.getConfigBean().getIssuer(),
|
||||||
|
PerunUnapprovedController.UNAPPROVED_IS_ELIGIBLE_MAPPING, params);
|
||||||
|
log.debug("{} - redirecting user to unapproved: URL '{}'", filterName, redirectUrl);
|
||||||
|
res.reset();
|
||||||
|
res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
|
||||||
|
res.setHeader(HttpHeaders.LOCATION, redirectUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,8 +3,15 @@ package cz.muni.ics.oidc.web.controllers;
|
||||||
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_CLIENT_ID;
|
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_CLIENT_ID;
|
||||||
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_HEADER;
|
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_HEADER;
|
||||||
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_MESSAGE;
|
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_MESSAGE;
|
||||||
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_REASON;
|
|
||||||
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_TARGET;
|
import static cz.muni.ics.oidc.server.filters.AuthProcFilterConstants.PARAM_TARGET;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.BUTTON_TRANSLATION;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.CONTACT_TRANSLATION;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_BUTTON_TRANSLATION_KEY;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_CONTACT_TRANSLATION_KEY;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_HEADER_TRANSLATION_KEY;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.DEFAULT_TEXT_TRANSLATION_KEY;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.HEADER_TRANSLATION;
|
||||||
|
import static cz.muni.ics.oidc.server.filters.impl.IsEligibleFilter.TEXT_TRANSLATION;
|
||||||
|
|
||||||
import cz.muni.ics.oauth2.model.ClientDetailsEntity;
|
import cz.muni.ics.oauth2.model.ClientDetailsEntity;
|
||||||
import cz.muni.ics.oauth2.service.ClientDetailsEntityService;
|
import cz.muni.ics.oauth2.service.ClientDetailsEntityService;
|
||||||
|
@ -13,13 +20,19 @@ import cz.muni.ics.oidc.web.WebHtmlClasses;
|
||||||
import cz.muni.ics.openid.connect.view.HttpCodeView;
|
import cz.muni.ics.openid.connect.view.HttpCodeView;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||||
|
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ctonroller for the unapproved page.
|
* Ctonroller for the unapproved page.
|
||||||
|
@ -32,7 +45,7 @@ public class PerunUnapprovedController {
|
||||||
|
|
||||||
public static final String UNAPPROVED_MAPPING = "/unapproved";
|
public static final String UNAPPROVED_MAPPING = "/unapproved";
|
||||||
public static final String UNAPPROVED_SPECIFIC_MAPPING = "/unapproved_spec";
|
public static final String UNAPPROVED_SPECIFIC_MAPPING = "/unapproved_spec";
|
||||||
public static final String UNAPPROVED_IS_CESNET_ELIGIBLE_MAPPING = "/unapprovedIce";
|
public static final String UNAPPROVED_IS_ELIGIBLE_MAPPING = "/unapprovedNotEligible";
|
||||||
public static final String UNAPPROVED_ENSURE_VO_MAPPING = "/unapprovedEnsureVo";
|
public static final String UNAPPROVED_ENSURE_VO_MAPPING = "/unapprovedEnsureVo";
|
||||||
public static final String UNAPPROVED_AUTHORIZATION = "/unapprovedAuthorization";
|
public static final String UNAPPROVED_AUTHORIZATION = "/unapprovedAuthorization";
|
||||||
public static final String UNAPPROVED_NOT_IN_TEST_VOS_GROUPS = "/unapprovedNotInTestVosGroups";
|
public static final String UNAPPROVED_NOT_IN_TEST_VOS_GROUPS = "/unapprovedNotInTestVosGroups";
|
||||||
|
@ -40,11 +53,9 @@ public class PerunUnapprovedController {
|
||||||
public static final String UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS = "/unapprovedNotInMandatoryVosGroups";
|
public static final String UNAPPROVED_NOT_IN_MANDATORY_VOS_GROUPS = "/unapprovedNotInMandatoryVosGroups";
|
||||||
public static final String UNAPPROVED_NOT_LOGGED_IN = "/unapprovedNotLoggedIn";
|
public static final String UNAPPROVED_NOT_LOGGED_IN = "/unapprovedNotLoggedIn";
|
||||||
|
|
||||||
public static final String REASON_NOT_SET = "notSet";
|
|
||||||
public static final String REASON_EXPIRED = "expired";
|
|
||||||
|
|
||||||
private static final String OUT_HEADER = "outHeader";
|
private static final String OUT_HEADER = "outHeader";
|
||||||
private static final String OUT_MESSAGE = "outMessage";
|
private static final String OUT_MESSAGE = "outMessage";
|
||||||
|
private static final String OUT_BUTTON = "outButton";
|
||||||
private static final String OUT_CONTACT_P = "outContactP";
|
private static final String OUT_CONTACT_P = "outContactP";
|
||||||
|
|
||||||
private static final String ENSURE_VO_HDR = "403_ensure_vo_hdr";
|
private static final String ENSURE_VO_HDR = "403_ensure_vo_hdr";
|
||||||
|
@ -53,11 +64,6 @@ public class PerunUnapprovedController {
|
||||||
private static final String AUTHORIZATION_HDR = "403_authorization_hdr";
|
private static final String AUTHORIZATION_HDR = "403_authorization_hdr";
|
||||||
private static final String AUTHORIZATION_MSG = "403_authorization_msg";
|
private static final String AUTHORIZATION_MSG = "403_authorization_msg";
|
||||||
|
|
||||||
private static final String ICE_NOT_SET_HDR = "403_isCesnetEligible_notSet_hdr";
|
|
||||||
private static final String ICE_NOT_SET_MSG = "403_isCesnetEligible_notSet_msg";
|
|
||||||
private static final String ICE_EXPIRED_HDR = "403_isCesnetEligible_expired_hdr";
|
|
||||||
private static final String ICE_EXPIRED_MSG = "403_isCesnetEligible_expired_msg";
|
|
||||||
|
|
||||||
private static final String NOT_IN_TEST_VOS_GROUPS_HDR = "403_not_in_test_vos_groups_hdr";
|
private static final String NOT_IN_TEST_VOS_GROUPS_HDR = "403_not_in_test_vos_groups_hdr";
|
||||||
private static final String NOT_IN_TEST_VOS_GROUPS_MSG = "403_not_in_test_vos_groups_msg";
|
private static final String NOT_IN_TEST_VOS_GROUPS_MSG = "403_not_in_test_vos_groups_msg";
|
||||||
|
|
||||||
|
@ -72,6 +78,10 @@ public class PerunUnapprovedController {
|
||||||
|
|
||||||
private static final String CONTACT_LANG_PROP_KEY = "contact_p";
|
private static final String CONTACT_LANG_PROP_KEY = "contact_p";
|
||||||
private static final String CONTACT_MAIL = "contactMail";
|
private static final String CONTACT_MAIL = "contactMail";
|
||||||
|
private static final String HAS_TARGET = "hasTarget";
|
||||||
|
private static final String REASON = "reason";
|
||||||
|
|
||||||
|
public static final String TARGET = "target";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClientDetailsEntityService clientService;
|
private ClientDetailsEntityService clientService;
|
||||||
|
@ -82,6 +92,9 @@ public class PerunUnapprovedController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private WebHtmlClasses htmlClasses;
|
private WebHtmlClasses htmlClasses;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityContextLogoutHandler logoutHandler;
|
||||||
|
|
||||||
@GetMapping(value = UNAPPROVED_MAPPING)
|
@GetMapping(value = UNAPPROVED_MAPPING)
|
||||||
public String showUnapproved(HttpServletRequest req,
|
public String showUnapproved(HttpServletRequest req,
|
||||||
Map<String, Object> model,
|
Map<String, Object> model,
|
||||||
|
@ -134,36 +147,45 @@ public class PerunUnapprovedController {
|
||||||
return "unapproved_spec";
|
return "unapproved_spec";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = UNAPPROVED_IS_CESNET_ELIGIBLE_MAPPING)
|
@GetMapping(value = UNAPPROVED_IS_ELIGIBLE_MAPPING)
|
||||||
public String showUnapprovedIsCesnetEligible(HttpServletRequest req, Map<String, Object> model,
|
public String showUnapprovedIsEligible(HttpServletRequest req,
|
||||||
@RequestParam(value = PARAM_TARGET) String target,
|
Map<String, Object> model,
|
||||||
@RequestParam(value = PARAM_REASON) String reason) {
|
@RequestParam(value = PARAM_TARGET, required = false) String target)
|
||||||
|
{
|
||||||
ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig);
|
ControllerUtils.setPageOptions(model, req, htmlClasses, perunOidcConfig);
|
||||||
|
|
||||||
String header;
|
HttpSession sess = req.getSession();
|
||||||
String message;
|
String header = loadSessionTranslationKey(sess, HEADER_TRANSLATION, DEFAULT_HEADER_TRANSLATION_KEY);
|
||||||
|
String message = loadSessionTranslationKey(sess, TEXT_TRANSLATION, DEFAULT_TEXT_TRANSLATION_KEY);
|
||||||
if (REASON_EXPIRED.equals(reason)) {
|
String button = loadSessionTranslationKey(sess, BUTTON_TRANSLATION, DEFAULT_BUTTON_TRANSLATION_KEY);
|
||||||
header = ICE_EXPIRED_HDR;
|
String contactP = loadSessionTranslationKey(sess, CONTACT_TRANSLATION, DEFAULT_CONTACT_TRANSLATION_KEY);
|
||||||
message = ICE_EXPIRED_MSG;
|
|
||||||
} else if (REASON_NOT_SET.equals(reason)){
|
|
||||||
header = ICE_NOT_SET_HDR;
|
|
||||||
message = ICE_NOT_SET_MSG;
|
|
||||||
} else {
|
|
||||||
model.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
|
|
||||||
return HttpCodeView.VIEWNAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
model.put(OUT_HEADER, header);
|
model.put(OUT_HEADER, header);
|
||||||
model.put(OUT_MESSAGE, message);
|
model.put(OUT_MESSAGE, message);
|
||||||
model.put(OUT_CONTACT_P, CONTACT_LANG_PROP_KEY);
|
model.put(OUT_BUTTON, button);
|
||||||
|
model.put(OUT_CONTACT_P, contactP);
|
||||||
model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact());
|
model.put(CONTACT_MAIL, perunOidcConfig.getEmailContact());
|
||||||
|
model.put(HAS_TARGET, StringUtils.hasText(target));
|
||||||
|
req.getSession(true).setAttribute(TARGET, target);
|
||||||
|
|
||||||
if (perunOidcConfig.getTheme().equalsIgnoreCase("lsaai")) {
|
if (perunOidcConfig.getTheme().equalsIgnoreCase("lsaai")) {
|
||||||
return "lsaai/unapproved_spec";
|
return "lsaai/unapproved_is_eligible";
|
||||||
|
}
|
||||||
|
return "unapproved_is_eligible";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = UNAPPROVED_IS_ELIGIBLE_MAPPING)
|
||||||
|
public String showUnapprovedIsEligibleHandle(HttpServletRequest req,
|
||||||
|
HttpServletResponse res,
|
||||||
|
Map<String, Object> model,
|
||||||
|
@SessionAttribute(PARAM_TARGET) String target)
|
||||||
|
{
|
||||||
|
if (!StringUtils.hasText(target)) {
|
||||||
|
return showUnapprovedIsEligible(req, model, null);
|
||||||
|
} else {
|
||||||
|
logoutHandler.logout(req, res, null);
|
||||||
|
return "redirect:" + target;
|
||||||
}
|
}
|
||||||
return "unapproved_spec";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = UNAPPROVED_ENSURE_VO_MAPPING)
|
@GetMapping(value = UNAPPROVED_ENSURE_VO_MAPPING)
|
||||||
|
@ -253,4 +275,12 @@ public class PerunUnapprovedController {
|
||||||
return "unapproved_spec";
|
return "unapproved_spec";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String loadSessionTranslationKey(HttpSession sess, String key, String fallbackValue) {
|
||||||
|
if (sess != null && StringUtils.hasText((String) sess.getAttribute(key))) {
|
||||||
|
return (String) sess.getAttribute(key);
|
||||||
|
}
|
||||||
|
return fallbackValue;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue