Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update Citizen Consents structure #7

Merged
merged 20 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading