Skip to content

Commit

Permalink
Feature flag for service desk, part of #587
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Feb 3, 2025
1 parent 4750c7a commit 04a254d
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 19 deletions.
1 change: 1 addition & 0 deletions account-gui/src/routes/Stepup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
id={id}
showInstitutionOption={!isExternalNameValidation}
serviceName={serviceName}
serviceDeskActive={$conf.featureServiceDeskActive}
/>
{:else}
<h2>{I18n.t("Stepup.Header.COPY")}</h2>
Expand Down
1 change: 1 addition & 0 deletions account-gui/src/stores/conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const conf = writable({
idpBaseUrl: "",
featureWarningEducationalEmailDomain: false,
featureIdVerify: false,
featureServiceDeskActive: false,
emailSpamThresholdSeconds: 5,
mobileAppRedirect: ""
});
Expand Down
9 changes: 6 additions & 3 deletions account-gui/src/verify/VerifyChoice.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
export let addEuropean;
export let issuers = [];
export let showInstitutionOption = true;
export let serviceDeskActive;
export let serviceName;
let showOtherOptions = false;
Expand Down Expand Up @@ -220,9 +221,11 @@
onClick={() => proceed(addEuropean)}/>
</div>
</div>
<div class="choice-container other-options" on:click={() => showServiceDesk = !showServiceDesk}>
<p>{I18n.t("verify.modal.info.cantUse")}</p>
</div>
{#if serviceDeskActive}
<div class="choice-container other-options" on:click={() => showServiceDesk = !showServiceDesk}>
<p>{I18n.t("verify.modal.info.cantUse")}</p>
</div>
{/if}
{/if}
{/if}
{#if showBankOptions && !busyProcessing && !showServiceDesk}
Expand Down
1 change: 1 addition & 0 deletions myconext-gui/src/stores/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const config = writable({
featureDefaultRememberMe: false,
featureWarningEducationalEmailDomain: false,
featureIdVerify: false,
featureServiceDeskActive: false,
createEduIDInstitutionEnabled: false,
expirationNonValidatedDurationDays: 0
});
Expand Down
8 changes: 5 additions & 3 deletions myconext-gui/src/verify/VerifyChoice.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,11 @@
onClick={() => proceed(addEuropean)}/>
</div>
</div>
<div class="choice-container other-options" on:click={() => showServiceDesk = !showServiceDesk}>
<p>{I18n.t("verify.modal.info.cantUse")}</p>
</div>
{#if $config.featureServiceDeskActive}
<div class="choice-container other-options" on:click={() => showServiceDesk = !showServiceDesk}>
<p>{I18n.t("verify.modal.info.cantUse")}</p>
</div>
{/if}
{/if}
{/if}
{#if showBankOptions && !busyProcessing && !showServiceDesk && !showControlCode}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public LoginController(UserRepository userRepository,
@Value("${email_spam_threshold_seconds}") long emailSpamThresholdSeconds,
@Value("${linked_accounts.expiry-duration-days-non-validated}") long expirationNonValidatedDurationDays,
@Value("${mobile_app_redirect}") String mobileAppRedirect,
@Value("${feature.id_verify}") boolean idVerify
@Value("${feature.id_verify}") boolean idVerify,
@Value("${feature.service_desk_active}") boolean serviceDeskActive
) {
this.config.put("basePath", basePath);
this.config.put("loginUrl", basePath + "/login");
Expand All @@ -100,6 +101,7 @@ public LoginController(UserRepository userRepository,
this.config.put("expirationNonValidatedDurationDays", expirationNonValidatedDurationDays);
this.config.put("mobileAppRedirect", mobileAppRedirect);
this.config.put("featureIdVerify", idVerify);
this.config.put("featureServiceDeskActive", serviceDeskActive);
this.secureCookie = secureCookie;
this.userRepository = userRepository;
this.authenticationRequestRepository = authenticationRequestRepository;
Expand Down
26 changes: 16 additions & 10 deletions myconext-server/src/main/java/myconext/api/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public class UserController implements UserAuthentication {
private final List<VerifyIssuer> issuers;
//For now, hardcode the not known issuers from test
private final List<String> unknownIssuers = List.of("CURRNL2A");
private final boolean serviceDeskActive;

public UserController(UserRepository userRepository,
UserCredentialRepository userCredentialRepository,
Expand All @@ -128,6 +129,7 @@ public UserController(UserRepository userRepository,
@Value("${rp_id}") String rpId,
@Value("${feature.default_remember_me}") boolean featureDefaultRememberMe,
@Value("${feature.send_js_exceptions}") boolean sendJsExceptions,
@Value("${feature.service_desk_active}") boolean serviceDeskActive,
@Value("${verify.issuers_path}") Resource issuersResource,
ServicesConfiguration servicesConfiguration) throws IOException {
this.userRepository = userRepository;
Expand All @@ -153,6 +155,7 @@ public UserController(UserRepository userRepository,
this.emailGuessingPreventor = new EmailGuessingPrevention(emailGuessingSleepMillis);
this.featureDefaultRememberMe = featureDefaultRememberMe;
this.sendJsExceptions = sendJsExceptions;
this.serviceDeskActive = serviceDeskActive;

List<IdinIssuers> idinIssuers = objectMapper.readValue(issuersResource.getInputStream(), new TypeReference<>() {
});
Expand Down Expand Up @@ -1012,20 +1015,23 @@ public ResponseEntity<StatusResponse> deleteUser(Authentication authentication,

@Operation(summary = "Create verification control code password link",
description = """
Create a verification control code which users can use to prove their identity at the Service Desk. The
code is also send by email to the user. The required field are firstName, lastName and dayOfBirth.
There are no input validations, if the user's dayOfBirth can not be parsed, then this is solved in
the approval proces in the Serivce Desk
""")
Create a verification control code which users can use to prove their identity at the Service Desk. The
code is also send by email to the user. The required field are firstName, lastName and dayOfBirth.
There are no input validations, if the user's dayOfBirth can not be parsed, then this is solved in
the approval proces in the Serivce Desk
""")
@PostMapping("sp/control-code")
public ResponseEntity<ControlCode> createUserControlCode(Authentication authentication,
@RequestBody ControlCode controlCode) {
User user = userFromAuthentication(authentication);
if (!this.serviceDeskActive) {
throw new ForbiddenException("ServiceDesk is not active. Foul play by " + user.getEmail());
}
//First check if we need to clean up expired accounts
Instant nowInstant = new Date().toInstant();
List<LinkedAccount> linkedAccounts = user.getLinkedAccounts().stream()
.filter(linkedAccount -> linkedAccount.getExpiresAt().toInstant().isAfter(nowInstant))
.toList();
List<LinkedAccount> linkedAccounts = user.getLinkedAccounts().stream()
.filter(linkedAccount -> linkedAccount.getExpiresAt().toInstant().isAfter(nowInstant))
.toList();
user.setLinkedAccounts(linkedAccounts);
List<ExternalLinkedAccount> externalLinkedAccounts = user.getExternalLinkedAccounts().stream()
.filter(linkedAccount -> linkedAccount.getExpiresAt().toInstant().isAfter(nowInstant))
Expand Down Expand Up @@ -1058,8 +1064,8 @@ public ResponseEntity<ControlCode> createUserControlCode(Authentication authenti

@Operation(summary = "Delete existing verification control code",
description = """
Delete an existing verification control code for a user
""")
Delete an existing verification control code for a user
""")
@DeleteMapping("sp/control-code")
public ResponseEntity<UserResponse> deleteUserControlCode(Authentication authentication) {
User user = userFromAuthentication(authentication);
Expand Down
3 changes: 3 additions & 0 deletions myconext-server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ feature:
mail_inactivity_mails: True
# Do we mail users who have not installed the eduID app
nudge_app_mail: True
# Set to true if the servicedesk is fully operational (e.g. show the user the control-code option)
service_desk_active: true

secure_cookie: false
idp_entity_id: https://localhost.surf.id
private_key_path: classpath:/myconext.pem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -20,7 +20,8 @@

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
"service_desk_role_auto_provisioning=True"
"service_desk_role_auto_provisioning=True",
"feature.service_desk_active=False"
})
class ServiceDeskControllerTest extends AbstractIntegrationTest {

Expand Down Expand Up @@ -129,4 +130,17 @@ void convertUserControlCodeLinkedAccountsPresent() {
.then()
.statusCode(403);
}

@Test
void createUserControlCode() {
clearExternalAccounts("[email protected]");
ControlCode controlCode = new ControlCode("Lee", "Harpers", "01 Mar 1977");
given()
.body(controlCode)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.when()
.post("/myconext/api/sp/control-code")
.then()
.statusCode(HttpStatus.FORBIDDEN.value());
}
}

0 comments on commit 04a254d

Please sign in to comment.