Skip to content

Commit

Permalink
Update API for OIDC scopes (#3)
Browse files Browse the repository at this point in the history
* update api

* CHanging data model. Increasing version of openapi code generator.

* Additional repo classes.

* Adapt API controller and change data model.

* Add query param for oidcScope

* Adapt API tests

* Adapt repo and mapper

* Fix tests with empty default OIDC scope

* Fixed typo

* Fixed test

* Fixed tests

* Updated codegen version

* Add Tests for ServiceMapper

* workaround

* Workaroud for faulty openapi codegen

* bug fixing and api update

* pr remarks

---------

Co-authored-by: Tim Smyth <tim.smyth@fiware.org>
Co-authored-by: Beknazar Esenbek <beknazar.esenbek@fiware.org>
  • Loading branch information
3 people authored Nov 16, 2023
1 parent de84244 commit f54385a
Show file tree
Hide file tree
Showing 13 changed files with 945 additions and 572 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/**
32 changes: 24 additions & 8 deletions api/credentials-config-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'

/service/{id}:
get:
tags:
Expand Down Expand Up @@ -130,6 +129,7 @@ paths:
- service
parameters:
- $ref: '#/components/parameters/Id'
- $ref: '#/components/parameters/OidcScope'
operationId: getScopeForService
summary: Get the scope for the service
description: Returns the scope(e.g. credential types to be requested) for the requested service
Expand All @@ -146,7 +146,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'

components:
parameters:
Id:
Expand All @@ -156,6 +155,13 @@ components:
schema:
type: string
example: packet-delivery-service
OidcScope:
name: oidcScope
in: query
required: false
schema:
type: string
example: did_read
PageSize:
name: pageSize
in: query
Expand Down Expand Up @@ -208,6 +214,11 @@ components:
example: https://til-pdc.gaia-x.fiware.dev
required:
- type
ServiceScopesEntry:
type: array
minItems: 1
items:
$ref: '#/components/schemas/Credential'
Service:
type: object
description: Configuration of a service and its credentials
Expand All @@ -216,13 +227,18 @@ components:
type: string
description: Id of the service to be configured. If no id is provided, the service will generate one.
example: packet-delivery-service
credentials:
type: array
description: All credential configurations for the service
items:
$ref: '#/components/schemas/Credential'
defaultOidcScope:
type: string
description: Default OIDC scope to be used if none is specified
example: default
oidcScopes:
type: object
description: A specific OIDC scope for that service, specifying the necessary VC types (credentials)
additionalProperties:
$ref: '#/components/schemas/ServiceScopesEntry'
required:
- credentials
- oidcScopes
- defaultOidcScope
Services:
type: object
description: The paginated list of services
Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

<!-- code gen -->
<version.org.openapitools.generator-maven-plugin>6.6.0</version.org.openapitools.generator-maven-plugin>
<version.io.kokuwa.micronaut.codegen>3.3.1</version.io.kokuwa.micronaut.codegen>
<version.io.kokuwa.micronaut.codegen>3.4.6</version.io.kokuwa.micronaut.codegen>

<!-- test -->
<version.org.mockito.mocktio-all>1.10.19</version.org.mockito.mocktio-all>
Expand Down Expand Up @@ -246,6 +246,7 @@
<strictSpec>true</strictSpec>
<modelPackage>org.fiware.iam.ccs.model</modelPackage>
<generateAliasAsModel>true</generateAliasAsModel>
<generateModels>true</generateModels>
<generateApiTests>true</generateApiTests>
<generatorName>micronaut</generatorName>
<modelNameSuffix>VO</modelNameSuffix>
Expand Down
203 changes: 115 additions & 88 deletions src/main/java/org/fiware/iam/ServiceMapper.java
Original file line number Diff line number Diff line change
@@ -1,103 +1,130 @@
package org.fiware.iam;

import org.fiware.iam.ccs.model.CredentialVO;
import org.fiware.iam.ccs.model.ServiceVO;
import org.fiware.iam.ccs.model.*;
import org.fiware.iam.repository.Credential;
import org.fiware.iam.repository.EndpointEntry;
import org.fiware.iam.repository.EndpointType;
import org.fiware.iam.repository.Service;
import org.mapstruct.Mapper;

import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
* Responsible for mapping entities from the Service api domain to the internal model.
*/
@Mapper(componentModel = "jsr330")
public interface ServiceMapper {

Service map(ServiceVO serviceVO);

ServiceVO map(Service service);

default Credential map(CredentialVO credentialVO) {
if (credentialVO == null) {
return null;
}
Credential credential = new Credential()
.setCredentialType(credentialVO.getType());
List<EndpointEntry> trustedList = new ArrayList<>();
trustedList.addAll(issuersToEntries(credentialVO.getTrustedIssuersLists()));
trustedList.addAll(participantsToEntries(credentialVO.getTrustedParticipantsLists()));
credential.setTrustedLists(trustedList);
return credential;
}

default CredentialVO map(Credential credential) {
if (credential == null) {
return null;
}
return new CredentialVO()
.type(credential.getCredentialType())
.trustedIssuersLists(entriesToIssuers(credential.getTrustedLists()))
.trustedParticipantsLists(entriesToParticipants(credential.getTrustedLists()));
}

/**
* Map a list of string-entries, encoding TrustedParticipants endpoints to a list of {@link EndpointEntry} with
* type {{@link EndpointType.TRUSTED_PARTICIPANTS}
*/
default List<EndpointEntry> participantsToEntries(List<String> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.map(endpoint -> new EndpointEntry()
.setEndpoint(endpoint)
.setType(EndpointType.TRUSTED_PARTICIPANTS))
.toList();
}

/**
* Map a list of string-entries, encoding TrustedIssuers endpoints to a list of {@link EndpointEntry} with
* type {{@link EndpointType.TRUSTED_ISSUERS}
*/
default List<EndpointEntry> issuersToEntries(List<String> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.map(endpoint -> new EndpointEntry()
.setEndpoint(endpoint)
.setType(EndpointType.TRUSTED_ISSUERS))
.toList();
}

/**
* Return issuer endpoints from the {@link EndpointEntry} list to a list of strings
*/
default List<String> entriesToIssuers(List<EndpointEntry> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.filter(entry -> entry.getType().equals(EndpointType.TRUSTED_ISSUERS))
.map(EndpointEntry::getEndpoint)
.toList();
}

/**
* Return participant endpoints from the {@link EndpointEntry} list to a list of strings
*/
default List<String> entriesToParticipants(List<EndpointEntry> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.filter(entry -> entry.getType().equals(EndpointType.TRUSTED_PARTICIPANTS))
.map(EndpointEntry::getEndpoint)
.toList();
}

}
Service map(ServiceVO serviceVO);


default Map<String,Collection<Credential>> map(Map<String,ServiceScopesEntryVO> value){
return Optional.ofNullable(value)
.orElseGet(Map::of)
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream().map(this::map).toList()));
}

default Map<String,ServiceScopesEntryVO> mapCredentials(Map<String,Collection<Credential>> value){
Map<String,ServiceScopesEntryVO> answer = new HashMap<>();
Optional.ofNullable(value)
.orElseGet(Map::of)
.entrySet().forEach(entry -> {
ServiceScopesEntryVO credentialVOS = new ServiceScopesEntryVO();
entry.getValue().stream().map(this::map).forEach(credentialVOS::add);
answer.put(entry.getKey(), credentialVOS);
});
return answer;
}

ServiceVO map(Service service);

default Credential map(CredentialVO credentialVO) {
if (credentialVO == null) {
return null;
}
Credential credential = new Credential()
.setCredentialType(credentialVO.getType());
List<EndpointEntry> trustedList = new ArrayList<>();
Optional.ofNullable(issuersToEntries(credentialVO.getTrustedIssuersLists())).ifPresent(trustedList::addAll);
Optional.ofNullable(participantsToEntries(credentialVO.getTrustedParticipantsLists())).ifPresent(trustedList::addAll);
credential.setTrustedLists(trustedList);
return credential;
}

default Collection<CredentialVO> map(Collection<Credential> credentials) {
if (credentials == null) {
return null;
}
return credentials.stream().map(this::map).toList();
}

default CredentialVO map(Credential credential) {
if (credential == null) {
return null;
}
return new CredentialVO()
.type(credential.getCredentialType())
.trustedIssuersLists(entriesToIssuers(credential.getTrustedLists()))
.trustedParticipantsLists(entriesToParticipants(credential.getTrustedLists()));
}

/**
* Map a list of string-entries, encoding TrustedParticipants endpoints to a list of {@link EndpointEntry} with
* type {{@link EndpointType#TRUSTED_PARTICIPANTS}
*/
default List<EndpointEntry> participantsToEntries(List<String> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.map(endpoint -> new EndpointEntry()
.setEndpoint(endpoint)
.setType(EndpointType.TRUSTED_PARTICIPANTS))
.toList();
}

/**
* Map a list of string-entries, encoding TrustedIssuers endpoints to a list of {@link EndpointEntry} with
* type {{@link EndpointType#TRUSTED_ISSUERS}
*/
default List<EndpointEntry> issuersToEntries(List<String> endpoints) {
if (endpoints == null) {
return null;
}
return endpoints.stream()
.map(endpoint -> new EndpointEntry()
.setEndpoint(endpoint)
.setType(EndpointType.TRUSTED_ISSUERS))
.toList();
}

/**
* Return issuer endpoints from the {@link EndpointEntry} list to a list of strings
*/
default List<String> entriesToIssuers(List<EndpointEntry> endpoints) {
if (endpoints == null) {
return List.of();
}
return endpoints.stream()
.filter(entry -> entry.getType().equals(EndpointType.TRUSTED_ISSUERS))
.map(EndpointEntry::getEndpoint)
.toList();
}

/**
* Return participant endpoints from the {@link EndpointEntry} list to a list of strings
*/
default List<String> entriesToParticipants(List<EndpointEntry> endpoints) {
if (endpoints == null) {
return List.of();
}
return endpoints.stream()
.filter(entry -> entry.getType().equals(EndpointType.TRUSTED_PARTICIPANTS))
.map(EndpointEntry::getEndpoint)
.toList();
}

}
10 changes: 1 addition & 9 deletions src/main/java/org/fiware/iam/repository/Credential.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,16 @@
@Data
@Accessors(chain = true)
@Entity
@EqualsAndHashCode(exclude = "service")
@ToString(exclude = "service")
public class Credential {

@GeneratedValue
@Id
private Integer id;

private String credentialType;

@OneToMany(mappedBy = "credential", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<EndpointEntry> trustedLists;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "service_id")
private Service service;




}
}
8 changes: 0 additions & 8 deletions src/main/java/org/fiware/iam/repository/EndpointEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,11 @@
@Data
@Accessors(chain = true)
@Entity
@EqualsAndHashCode(exclude = "credential")
@ToString(exclude = "credential")
public class EndpointEntry {

@GeneratedValue
@Id
private Integer id;

private EndpointType type;

private String endpoint;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "credential_id")
private Credential credential;
}
18 changes: 10 additions & 8 deletions src/main/java/org/fiware/iam/repository/Service.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package org.fiware.iam.repository;

import io.micronaut.core.annotation.Introspected;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import io.micronaut.core.annotation.TypeHint;
import io.micronaut.data.annotation.TypeDef;
import io.micronaut.data.model.DataType;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.Collection;
import java.util.Map;

/**
* Data entity representing a service
Expand All @@ -25,6 +25,8 @@ public class Service {
@Id
private String id;

@OneToMany(mappedBy = "service", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Collection<Credential> credentials;
}
private String defaultOidcScope;

@TypeDef(type = DataType.JSON)
private Map<String,Collection<Credential>> oidcScopes;
}
Loading

0 comments on commit f54385a

Please sign in to comment.