bugfix: fixes HTTP POST on credentials, including person+subject (#184)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/184 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package net.hostsharing.hsadminng.credentials;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import net.hostsharing.hsadminng.config.MessageTranslator;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.ContextResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CredentialContextResourceToEntityMapper {
|
||||
|
||||
private final EntityManager em;
|
||||
private final MessageTranslator messageTranslator;
|
||||
|
||||
@Autowired
|
||||
public CredentialContextResourceToEntityMapper(EntityManager em, MessageTranslator messageTranslator) {
|
||||
this.em = em;
|
||||
this.messageTranslator = messageTranslator;
|
||||
}
|
||||
|
||||
public Set<HsCredentialsContextRealEntity> mapCredentialsToContextEntities(
|
||||
List<ContextResource> resources
|
||||
) {
|
||||
final var entities = new HashSet<HsCredentialsContextRealEntity>();
|
||||
syncCredentialsContextEntities(resources, entities);
|
||||
return entities;
|
||||
}
|
||||
|
||||
public void syncCredentialsContextEntities(
|
||||
List<ContextResource> resources,
|
||||
Set<HsCredentialsContextRealEntity> entities
|
||||
) {
|
||||
final var resourceUuids = resources.stream()
|
||||
.map(ContextResource::getUuid)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var entityUuids = entities.stream()
|
||||
.map(HsCredentialsContextRealEntity::getUuid)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
entities.removeIf(e -> !resourceUuids.contains(e.getUuid()));
|
||||
|
||||
for (final var resource : resources) {
|
||||
if (!entityUuids.contains(resource.getUuid())) {
|
||||
final var existingContextEntity = em.find(HsCredentialsContextRealEntity.class, resource.getUuid());
|
||||
if (existingContextEntity == null) {
|
||||
throw new EntityNotFoundException(
|
||||
messageTranslator.translate("{0} \"{1}\" not found or not accessible",
|
||||
"credentials uuid", resource.getUuid()));
|
||||
}
|
||||
if (!existingContextEntity.getType().equals(resource.getType()) &&
|
||||
!existingContextEntity.getQualifier().equals(resource.getQualifier())) {
|
||||
throw new EntityNotFoundException(
|
||||
messageTranslator.translate("existing {0} does not match given resource {1}",
|
||||
existingContextEntity, resource));
|
||||
}
|
||||
entities.add(existingContextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.hostsharing.hsadminng.credentials.generated.api.v1.model.ContextResou
|
||||
import net.hostsharing.hsadminng.mapper.StrictMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@@ -26,6 +27,7 @@ public class HsCredentialsContextsController implements ContextsApi {
|
||||
private HsCredentialsContextRbacRepository contextRepo;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
@Timed("app.credentials.contexts.getListOfLoginContexts")
|
||||
public ResponseEntity<List<ContextResource>> getListOfContexts(final String assumedRoles) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.hostsharing.hsadminng.credentials;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -15,21 +14,27 @@ import net.hostsharing.hsadminng.credentials.generated.api.v1.api.CredentialsApi
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.CredentialsInsertResource;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.CredentialsPatchResource;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.CredentialsResource;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.HsOfficePersonResource;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacRepository;
|
||||
import net.hostsharing.hsadminng.mapper.StrictMapper;
|
||||
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectEntity;
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static java.util.Optional.of;
|
||||
|
||||
@RestController
|
||||
@SecurityRequirement(name = "casTicket")
|
||||
public class HsCredentialsController implements CredentialsApi {
|
||||
|
||||
private static DateTimeFormatter FULL_TIMESTAMP_FORMAT = DateTimeFormatter.BASIC_ISO_DATE;
|
||||
|
||||
@Autowired
|
||||
private Context context;
|
||||
|
||||
@@ -39,16 +44,23 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
@Autowired
|
||||
private StrictMapper mapper;
|
||||
|
||||
@Autowired
|
||||
private RbacSubjectRepository subjectRepo;
|
||||
|
||||
@Autowired
|
||||
private CredentialContextResourceToEntityMapper contextMapper;
|
||||
|
||||
@Autowired
|
||||
private MessageTranslator messageTranslator;
|
||||
|
||||
@Autowired
|
||||
private HsOfficePersonRbacRepository personRepo;
|
||||
private HsOfficePersonRbacRepository rbacPersonRepo;
|
||||
|
||||
@Autowired
|
||||
private HsCredentialsRepository credentialsRepo;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
@Timed("app.credentials.credentials.getSingleCredentialsByUuid")
|
||||
public ResponseEntity<CredentialsResource> getSingleCredentialsByUuid(
|
||||
final String assumedRoles,
|
||||
@@ -56,11 +68,16 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
context.assumeRoles(assumedRoles);
|
||||
|
||||
final var credentials = credentialsRepo.findByUuid(credentialsUuid);
|
||||
final var result = mapper.map(credentials, CredentialsResource.class);
|
||||
if (credentials.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
final var result = mapper.map(
|
||||
credentials.get(), CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
@Timed("app.credentials.credentials.getListOfCredentialsByPersonUuid")
|
||||
public ResponseEntity<List<CredentialsResource>> getListOfCredentialsByPersonUuid(
|
||||
final String assumedRoles,
|
||||
@@ -68,18 +85,20 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
|
||||
final var person = personRepo.findByUuid(personUuid).orElseThrow(
|
||||
final var person = rbacPersonRepo.findByUuid(personUuid).orElseThrow(
|
||||
() -> new EntityNotFoundException(
|
||||
messageTranslator.translate("{0} \"{1}\" not found or not accessible", "personUuid", personUuid)
|
||||
)
|
||||
|
||||
);
|
||||
final var credentials = credentialsRepo.findByPerson(person);
|
||||
final var result = mapper.mapList(credentials, CredentialsResource.class);
|
||||
final var result = mapper.mapList(
|
||||
credentials, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Timed("app.credentials.credentials.postNewCredentials")
|
||||
public ResponseEntity<CredentialsResource> postNewCredentials(
|
||||
final String assumedRoles,
|
||||
@@ -87,13 +106,28 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
|
||||
final var newCredentialsEntity = mapper.map(body, HsCredentialsEntity.class);
|
||||
final var savedCredentialsEntity = credentialsRepo.save(newCredentialsEntity);
|
||||
final var newCredentialsResource = mapper.map(savedCredentialsEntity, CredentialsResource.class);
|
||||
return ResponseEntity.ok(newCredentialsResource);
|
||||
// first create and save the subject to get its UUID
|
||||
final var newlySavedSubject = createSubject(body.getNickname());
|
||||
|
||||
// afterward, create and save the credentials entity with the subject's UUID
|
||||
final var newCredentialsEntity = mapper.map(
|
||||
body, HsCredentialsEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
||||
newCredentialsEntity.setSubject(newlySavedSubject);
|
||||
em.persist(newCredentialsEntity); // newCredentialsEntity.uuid == newlySavedSubject.uuid => do not use repository!
|
||||
|
||||
// return the new credentials as a resource
|
||||
final var uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/hs/credentials/credentials/{id}")
|
||||
.buildAndExpand(newCredentialsEntity.getUuid())
|
||||
.toUri();
|
||||
final var newCredentialsResource = mapper.map(
|
||||
newCredentialsEntity, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.created(uri).body(newCredentialsResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Timed("app.credentials.credentials.deleteCredentialsByUuid")
|
||||
public ResponseEntity<Void> deleteCredentialsByUuid(final String assumedRoles, final UUID credentialsUuid) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
@@ -103,6 +137,7 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Timed("app.credentials.credentials.patchCredentials")
|
||||
public ResponseEntity<CredentialsResource> patchCredentials(
|
||||
final String assumedRoles,
|
||||
@@ -113,10 +148,11 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
|
||||
final var current = credentialsRepo.findByUuid(credentialsUuid).orElseThrow();
|
||||
|
||||
new HsCredentialsEntityPatcher(em, messageTranslator, current).apply(body);
|
||||
new HsCredentialsEntityPatcher(contextMapper, current).apply(body);
|
||||
|
||||
final var saved = credentialsRepo.save(current);
|
||||
final var mapped = mapper.map(saved, CredentialsResource.class);
|
||||
final var mapped = mapper.map(
|
||||
saved, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(mapped);
|
||||
}
|
||||
|
||||
@@ -137,7 +173,38 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
return ResponseEntity.ok(mapped);
|
||||
}
|
||||
|
||||
private RbacSubjectEntity createSubject(final String nickname) {
|
||||
final var newRbacSubject = subjectRepo.create(new RbacSubjectEntity(null, nickname));
|
||||
if(context.fetchCurrentSubject() == null) {
|
||||
context.define("activate newly created self-servie subject", null, nickname, null);
|
||||
}
|
||||
return subjectRepo.findByUuid(newRbacSubject.getUuid()); // attached to EM
|
||||
}
|
||||
|
||||
final BiConsumer<HsCredentialsEntity, CredentialsResource> ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||
resource.setLastUsed(entity.getLastUsed().atOffset(ZoneOffset.UTC));
|
||||
ofNullable(entity.getLastUsed()).ifPresent(
|
||||
dt -> resource.setLastUsed(dt.atOffset(ZoneOffset.UTC)));
|
||||
of(entity.getSubject()).ifPresent(
|
||||
subject -> resource.setNickname(subject.getName())
|
||||
);
|
||||
of(entity.getPerson()).ifPresent(
|
||||
person -> resource.setPerson(
|
||||
mapper.map(person, HsOfficePersonResource.class)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
final BiConsumer<CredentialsInsertResource, HsCredentialsEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||
|
||||
// TODO.impl: we need to make sure that the current subject is OWNER (or ADMIN?) of the person
|
||||
final var person = rbacPersonRepo.findByUuid(resource.getPersonUuid()).orElseThrow(
|
||||
() -> new EntityNotFoundException(
|
||||
messageTranslator.translate("{0} \"{1}\" not found or not accessible", "personUuid", resource.getPersonUuid())
|
||||
)
|
||||
);
|
||||
|
||||
entity.setLoginContexts(contextMapper.mapCredentialsToContextEntities(resource.getContexts()));
|
||||
|
||||
entity.setPerson(person);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.credentials;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacEntity;
|
||||
import net.hostsharing.hsadminng.persistence.BaseEntity; // Assuming BaseEntity exists
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectEntity;
|
||||
import net.hostsharing.hsadminng.repr.Stringify;
|
||||
@@ -45,7 +45,7 @@ public class HsCredentialsEntity implements BaseEntity<HsCredentialsEntity>, Str
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "person_uuid", nullable = false, updatable = false, referencedColumnName = "uuid")
|
||||
private HsOfficePersonRealEntity person;
|
||||
private HsOfficePersonRbacEntity person;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
@@ -92,6 +92,11 @@ public class HsCredentialsEntity implements BaseEntity<HsCredentialsEntity>, Str
|
||||
return loginContexts;
|
||||
}
|
||||
|
||||
public void setSubject(final RbacSubjectEntity subject) {
|
||||
this.uuid = subject.getUuid();
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toShortString() {
|
||||
return active + ":" + emailAddress + ":" + globalUid;
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
package net.hostsharing.hsadminng.credentials;
|
||||
|
||||
import net.hostsharing.hsadminng.config.MessageTranslator;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.ContextResource;
|
||||
import net.hostsharing.hsadminng.credentials.generated.api.v1.model.CredentialsPatchResource;
|
||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HsCredentialsEntityPatcher implements EntityPatcher<CredentialsPatchResource> {
|
||||
|
||||
private final EntityManager em;
|
||||
private MessageTranslator messageTranslator;
|
||||
private CredentialContextResourceToEntityMapper contextMapper;
|
||||
private final HsCredentialsEntity entity;
|
||||
|
||||
public HsCredentialsEntityPatcher(final EntityManager em, MessageTranslator messageTranslator, final HsCredentialsEntity entity) {
|
||||
this.em = em;
|
||||
this.messageTranslator = messageTranslator;
|
||||
public HsCredentialsEntityPatcher(final CredentialContextResourceToEntityMapper contextMapper, final HsCredentialsEntity entity) {
|
||||
this.contextMapper = contextMapper;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@@ -38,40 +29,7 @@ public class HsCredentialsEntityPatcher implements EntityPatcher<CredentialsPatc
|
||||
OptionalFromJson.of(resource.getPhonePassword())
|
||||
.ifPresent(entity::setPhonePassword);
|
||||
if (resource.getContexts() != null) {
|
||||
syncLoginContextEntities(resource.getContexts(), entity.getLoginContexts());
|
||||
}
|
||||
}
|
||||
|
||||
public void syncLoginContextEntities(
|
||||
List<ContextResource> resources,
|
||||
Set<HsCredentialsContextRealEntity> entities
|
||||
) {
|
||||
final var resourceUuids = resources.stream()
|
||||
.map(ContextResource::getUuid)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var entityUuids = entities.stream()
|
||||
.map(HsCredentialsContextRealEntity::getUuid)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
entities.removeIf(e -> !resourceUuids.contains(e.getUuid()));
|
||||
|
||||
for (final var resource : resources) {
|
||||
if (!entityUuids.contains(resource.getUuid())) {
|
||||
final var existingContextEntity = em.find(HsCredentialsContextRealEntity.class, resource.getUuid());
|
||||
if ( existingContextEntity == null ) {
|
||||
throw new EntityNotFoundException(
|
||||
messageTranslator.translate("{0} \"{1}\" not found or not accessible",
|
||||
"credentials uuid", resource.getUuid()));
|
||||
}
|
||||
if (!existingContextEntity.getType().equals(resource.getType()) &&
|
||||
!existingContextEntity.getQualifier().equals(resource.getQualifier())) {
|
||||
throw new EntityNotFoundException(
|
||||
messageTranslator.translate("existing {0} does not match given resource {1}",
|
||||
existingContextEntity, resource));
|
||||
}
|
||||
entities.add(existingContextEntity);
|
||||
}
|
||||
contextMapper.syncCredentialsContextEntities(resource.getContexts(), entity.getLoginContexts());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.UUID;
|
||||
@Table(schema = "rbac", name = "subject_rv")
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@ToString
|
||||
@Immutable
|
||||
@NoArgsConstructor
|
||||
|
||||
@@ -45,7 +45,7 @@ public interface RbacSubjectRepository extends Repository<RbacSubjectEntity, UUI
|
||||
rbacSubjectEntity.setUuid(UUID.randomUUID());
|
||||
}
|
||||
insert(rbacSubjectEntity);
|
||||
return rbacSubjectEntity;
|
||||
return rbacSubjectEntity; // Not yet attached to EM!
|
||||
}
|
||||
|
||||
@Timed("app.rbac.subjects.repo.deleteByUuid")
|
||||
|
||||
@@ -2,7 +2,7 @@ get:
|
||||
summary: Returns a list of all accessible contexts.
|
||||
description: Returns the list of all contexts which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- -contexts
|
||||
- contexts
|
||||
operationId: getListOfContexts
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
|
||||
@@ -9,6 +9,11 @@ components:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
person:
|
||||
$ref: '../hs-office/hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
nickname:
|
||||
type: string
|
||||
pattern: '^[a-z][a-z0-9]{1,8}-[a-z0-9]{1,10}$' # TODO.spec: pattern for login nickname
|
||||
totpSecret:
|
||||
type: string
|
||||
telephonePassword:
|
||||
@@ -64,9 +69,12 @@ components:
|
||||
CredentialsInsert:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
person.uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nickname:
|
||||
type: string
|
||||
pattern: '^[a-z][a-z0-9]{1,8}-[a-z0-9]{1,10}$' # TODO.spec: pattern for login nickname
|
||||
totpSecret:
|
||||
type: string
|
||||
telephonePassword:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
post:
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
description: 'Is called when credentials got used for a login.'
|
||||
operationId: credentialsUsed
|
||||
parameters:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
get:
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
description: 'Fetch a single credentials its uuid, if visible for the current subject.'
|
||||
operationId: getSingleCredentialsByUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: CredentialsUuid
|
||||
- name: credentialsUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@@ -27,12 +27,12 @@ get:
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
description: 'Updates a single credentials identified by its uuid, if permitted for the current subject.'
|
||||
operationId: patchCredentials
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: CredentialsUuid
|
||||
- name: credentialsUuid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@@ -57,7 +57,7 @@ patch:
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
description: 'Delete a single credentials identified by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteCredentialsByUuid
|
||||
parameters:
|
||||
|
||||
@@ -2,7 +2,7 @@ get:
|
||||
summary: Returns a list of all credentials.
|
||||
description: Returns the list of all credentials which are visible to the current subject or any of it's assumed roles.
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
operationId: getListOfCredentialsByPersonUuid
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
@@ -30,7 +30,7 @@ get:
|
||||
post:
|
||||
summary: Adds a new credentials.
|
||||
tags:
|
||||
- -credentials
|
||||
- credentials
|
||||
operationId: postNewCredentials
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
|
||||
Reference in New Issue
Block a user