Skip to content

Commit

Permalink
feat: update Citizen Consents structure (#7)
Browse files Browse the repository at this point in the history
Co-authored-by: DanieleRanaldo <Daniele.Ranaldo@nttdata.com>
Co-authored-by: Vitolo-Andrea <andrea.vitolo@emeal.nttdata.com>
  • Loading branch information
3 people authored Nov 14, 2024
1 parent 3aed12c commit 63157c2
Show file tree
Hide file tree
Showing 38 changed files with 2,519 additions and 194 deletions.
19 changes: 19 additions & 0 deletions .spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
extends:
- "spectral:oas"
- "spectral:asyncapi"
- "https://unpkg.com/@stoplight/spectral-owasp-ruleset/dist/ruleset.mjs"
overrides:
- files:
- "src/main/resources/META-INF/openapi.yaml#/paths/~1token/post/security"
rules:
owasp:api2:2023-write-restricted: "off"
- files:
- "src/main/resources/META-INF/openapi.yaml#/paths/~1.well-known~1jwks.json/get/security"
- "src/main/resources/META-INF/openapi.yaml#/paths/~1.well-known~1openid-configuration/get/security"
rules:
owasp:api2:2023-read-restricted: "off"
- files:
- "src/main/resources/META-INF/openapi.yaml"
rules:
owasp:api3:2023-no-additionalProperties: "off"
owasp:api3:2023-constrained-additionalProperties: "off"
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public ExceptionMap() {
message
)
);

exceptions.put(CitizenConstants.ExceptionName.TPP_NOT_FOUND, message ->
new ClientExceptionWithBody(
HttpStatus.NOT_FOUND,
CitizenConstants.ExceptionCode.TPP_NOT_FOUND,
message
)
);
}

public RuntimeException throwException(String exceptionKey, String message) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package it.gov.pagopa.onboarding.citizen.connector.tpp;

import it.gov.pagopa.onboarding.citizen.dto.TppDTO;
import reactor.core.publisher.Mono;

public interface TppConnector {
Mono<TppDTO> get(String tppId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package it.gov.pagopa.onboarding.citizen.connector.tpp;

import it.gov.pagopa.onboarding.citizen.dto.TppDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class TppConnectorImpl implements TppConnector {
private final WebClient webClient;

public TppConnectorImpl(WebClient.Builder webClientBuilder,
@Value("${rest-client.tpp.baseUrl}") String baseUrl) {
this.webClient = webClientBuilder.baseUrl(baseUrl).build();
}

@Override
public Mono<TppDTO> get(String tppId) {
return webClient.get()
.uri("/emd/tpp/" + tppId)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<>() {
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,36 @@ public static final class ExceptionCode {

public static final String CITIZEN_NOT_ONBOARDED = "CITIZEN_NOT_ONBOARDED";
public static final String GENERIC_ERROR = "GENERIC_ERROR";
public static final String TPP_NOT_FOUND = "TPP_NOT_FOUND";

private ExceptionCode() {}
}

public static final class ExceptionMessage {

public static final String CITIZEN_NOT_ONBOARDED = "CITIZEN_NOT_ONBOARDED";
public static final String GENERIC_ERROR = "GENERIC_ERROR";
public static final String TPP_NOT_FOUND = "TPP does not exist or is not active";

private ExceptionMessage() {}
}

public static final class ExceptionName {

public static final String CITIZEN_NOT_ONBOARDED = "CITIZEN_NOT_ONBOARDED";
public static final String GENERIC_ERROR = "GENERIC_ERROR";
public static final String TPP_NOT_FOUND = "TPP_NOT_FOUND";

private ExceptionName() {}
}

public static final class ValidationRegex {

public static final String FISCAL_CODE_STRUCTURE_REGEX = "(^([A-Za-z]{6}[0-9lmnpqrstuvLMNPQRSTUV]{2}[abcdehlmprstABCDEHLMPRST][0-9lmnpqrstuvLMNPQRSTUV]{2}[A-Za-z][0-9lmnpqrstuvLMNPQRSTUV]{3}[A-Za-z])$)|(^(\\d{11})$)";

private ValidationRegex() {}
}


private CitizenConstants() {}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
package it.gov.pagopa.onboarding.citizen.controller;

import it.gov.pagopa.onboarding.citizen.dto.CitizenConsentDTO;
import it.gov.pagopa.onboarding.citizen.dto.CitizenConsentStateUpdateDTO;
import jakarta.validation.Valid;

import jakarta.validation.constraints.Pattern;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.List;

import static it.gov.pagopa.onboarding.citizen.constants.CitizenConstants.ValidationRegex.FISCAL_CODE_STRUCTURE_REGEX;


@RequestMapping("/emd/citizen")
public interface CitizenController {

@PostMapping("")
Mono<ResponseEntity<CitizenConsentDTO>> saveCitizenConsent(@Valid @RequestBody CitizenConsentDTO citizenConsentDTO);

/**
* Update the state of a citizen's consent.
*
* @param citizenConsentDTO contains the hashedFiscalCode, channelId, and channelState to update
* @return the updated citizen consents
*/
@PutMapping("/stateUpdate")
Mono<ResponseEntity<CitizenConsentDTO>> stateUpdate(@Valid @RequestBody CitizenConsentDTO citizenConsentDTO);

/**
* Get the consent status for a specific citizen and channel.
*
Expand All @@ -33,7 +28,16 @@ public interface CitizenController {
* @return the citizen consent status
*/
@GetMapping("/{fiscalCode}/{tppId}")
Mono<ResponseEntity<CitizenConsentDTO>> getConsentStatus(@PathVariable String fiscalCode, @PathVariable String tppId);
Mono<ResponseEntity<CitizenConsentDTO>> getConsentStatus(@PathVariable @Pattern(regexp = FISCAL_CODE_STRUCTURE_REGEX, message = "Invalid fiscal code format") String fiscalCode, @PathVariable String tppId);

/**
* Update the state of a citizen's consent.
*
* @param citizenConsentStateUpdateDTO contains the hashedFiscalCode, channelId, and channelState to update
* @return the updated citizen consents
*/
@PutMapping("/stateUpdate")
Mono<ResponseEntity<CitizenConsentDTO>> stateUpdate(@Valid @RequestBody CitizenConsentStateUpdateDTO citizenConsentStateUpdateDTO);

/**
* List all channels with enabled consents for a specific citizen.
Expand All @@ -42,7 +46,7 @@ public interface CitizenController {
* @return a list of channels with enabled consents
*/
@GetMapping("/list/{fiscalCode}/enabled")
Mono<ResponseEntity<List<CitizenConsentDTO>>> getCitizenConsentsEnabled(@PathVariable String fiscalCode);
Mono<ResponseEntity<List<String>>> getTppEnabledList(@PathVariable @Pattern(regexp = FISCAL_CODE_STRUCTURE_REGEX, message = "Invalid fiscal code format") String fiscalCode);

/**
* List all channels and their consent status for a specific citizen.
Expand All @@ -51,6 +55,10 @@ public interface CitizenController {
* @return a list of all channels with their consent statuses
*/
@GetMapping("/list/{fiscalCode}")
Mono<ResponseEntity<List<CitizenConsentDTO>>> getCitizenConsents(@PathVariable String fiscalCode);
Mono<ResponseEntity<CitizenConsentDTO>> get(@PathVariable @Pattern(regexp = FISCAL_CODE_STRUCTURE_REGEX, message = "Invalid fiscal code format") String fiscalCode);

@GetMapping("/filter/{fiscalCode}")
Mono<ResponseEntity<String>> getAllFiscalCode(@PathVariable @Pattern(regexp = FISCAL_CODE_STRUCTURE_REGEX, message = "Invalid fiscal code format") String fiscalCode);


}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package it.gov.pagopa.onboarding.citizen.controller;

import it.gov.pagopa.onboarding.citizen.dto.CitizenConsentDTO;
import it.gov.pagopa.onboarding.citizen.dto.CitizenConsentStateUpdateDTO;
import it.gov.pagopa.onboarding.citizen.service.BloomFilterServiceImpl;
import it.gov.pagopa.onboarding.citizen.service.CitizenServiceImpl;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
Expand All @@ -12,9 +15,12 @@
@RestController
public class CitizenControllerImpl implements CitizenController {

private final BloomFilterServiceImpl bloomFilterService;

private final CitizenServiceImpl citizenService;

public CitizenControllerImpl(CitizenServiceImpl citizenService) {
public CitizenControllerImpl(BloomFilterServiceImpl bloomFilterService, CitizenServiceImpl citizenService) {
this.bloomFilterService = bloomFilterService;
this.citizenService = citizenService;
}

Expand All @@ -25,11 +31,11 @@ public Mono<ResponseEntity<CitizenConsentDTO>> saveCitizenConsent(@Valid Citizen
}

@Override
public Mono<ResponseEntity<CitizenConsentDTO>> stateUpdate(@Valid CitizenConsentDTO citizenConsentDTO) {
return citizenService.updateChannelState(
citizenConsentDTO.getHashedFiscalCode(), //at this stage the fiscalCode has not yet been hashed
citizenConsentDTO.getTppId(),
citizenConsentDTO.getTppState())
public Mono<ResponseEntity<CitizenConsentDTO>> stateUpdate(@Valid CitizenConsentStateUpdateDTO citizenConsentStateUpdateDTO) {
return citizenService.updateTppState(
citizenConsentStateUpdateDTO.getFiscalCode(),
citizenConsentStateUpdateDTO.getTppId(),
citizenConsentStateUpdateDTO.getTppState())
.map(ResponseEntity::ok);
}

Expand All @@ -40,14 +46,25 @@ public Mono<ResponseEntity<CitizenConsentDTO>> getConsentStatus(String fiscalCod
}

@Override
public Mono<ResponseEntity<List<CitizenConsentDTO>>> getCitizenConsentsEnabled(String fiscalCode) {
return citizenService.getListEnabledConsents(fiscalCode)
public Mono<ResponseEntity<List<String>>> getTppEnabledList(String fiscalCode) {
return citizenService.getTppEnabledList(fiscalCode)
.map(ResponseEntity::ok);
}

@Override
public Mono<ResponseEntity<List<CitizenConsentDTO>>> getCitizenConsents(String fiscalCode) {
return citizenService.getListAllConsents(fiscalCode)
public Mono<ResponseEntity<CitizenConsentDTO>> get(String fiscalCode) {
return citizenService.get(fiscalCode)
.map(ResponseEntity::ok);
}

@Override
public Mono<ResponseEntity<String>> getAllFiscalCode(String fiscalCode) {
return Mono.fromCallable(() ->
bloomFilterService.mightContain(fiscalCode) ?
ResponseEntity.ok("OK") :
ResponseEntity.status(HttpStatus.ACCEPTED).body("NO CHANNELS ENABLED")
);

}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
package it.gov.pagopa.onboarding.citizen.dto;

import com.fasterxml.jackson.annotation.JsonAlias;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.time.LocalDateTime;
import java.util.Map;

import static it.gov.pagopa.onboarding.citizen.constants.CitizenConstants.ValidationRegex.FISCAL_CODE_STRUCTURE_REGEX;

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class CitizenConsentDTO {
@JsonAlias("fiscalCode")
private String hashedFiscalCode;
private String tppId;
private Boolean tppState;
private LocalDateTime creationDate;
private LocalDateTime lastUpdateDate;
@NotBlank(message = "Fiscal Code must not be blank")
@Pattern(regexp = FISCAL_CODE_STRUCTURE_REGEX,
message = "Fiscal Code must be 11 digits or up to 16 alphanumeric characters")
private String fiscalCode;
private Map<String, ConsentDTO> consents;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public static class ConsentDTO {
private Boolean tppState;
private LocalDateTime tcDate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package it.gov.pagopa.onboarding.citizen.dto;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class CitizenConsentStateUpdateDTO {
private String fiscalCode;
private String tppId;
private Boolean tppState;
}
15 changes: 15 additions & 0 deletions src/main/java/it/gov/pagopa/onboarding/citizen/dto/Contact.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package it.gov.pagopa.onboarding.citizen.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Contact {

private String name;
private String number;
private String email;
}
26 changes: 26 additions & 0 deletions src/main/java/it/gov/pagopa/onboarding/citizen/dto/TppDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package it.gov.pagopa.onboarding.citizen.dto;


import it.gov.pagopa.onboarding.citizen.enums.AuthenticationType;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
@NoArgsConstructor
public class TppDTO {
@NotNull
private String tppId;
private String entityId;
private String businessName;
private String messageUrl;
private String authenticationUrl;
private AuthenticationType authenticationType;
private Contact contact;
private Boolean state;



}
Loading

0 comments on commit 63157c2

Please sign in to comment.