credentials validation (#194)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/194 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
+1
-1
@@ -60,7 +60,7 @@ public class CredentialContextResourceToEntityMapper {
|
||||
(resource.getQualifier() != null && !existingContextEntity.getQualifier().equals(resource.getQualifier()))) {
|
||||
throw new EntityNotFoundException(
|
||||
messageTranslator.translate(
|
||||
"credentials.existing-{0}-does-not-match-given-resource-{1}",
|
||||
"credentials.existing-credentials-context-{0}-does-not-match-given-resource-{1}",
|
||||
existingContextEntity, resource));
|
||||
}
|
||||
entities.add(existingContextEntity);
|
||||
|
||||
@@ -61,9 +61,13 @@ public abstract class HsCredentialsContext implements Stringifyable, BaseEntity<
|
||||
@Column(name = "public_access")
|
||||
private boolean publicAccess;
|
||||
|
||||
public boolean isHsadminContext() {
|
||||
return "HSADMIN".equals(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toShortString() {
|
||||
return toString();
|
||||
return type + (qualifier != null ? ":" + qualifier : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-1
@@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.accounts;
|
||||
import java.util.List;
|
||||
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.val;
|
||||
import net.hostsharing.hsadminng.config.NoSecurityRequirement;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.api.ContextsApi;
|
||||
@@ -37,7 +38,10 @@ public class HsCredentialsContextsController implements ContextsApi {
|
||||
if (SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
}
|
||||
final var loginContexts = contextRepo.findAll();
|
||||
val isGlobalAdmin = context.isGlobalAdmin();
|
||||
final var loginContexts = contextRepo.findAll().stream().filter(
|
||||
context -> context.isPublicAccess() || isGlobalAdmin
|
||||
).toList();
|
||||
final var result = mapper.mapList(loginContexts, ContextResource.class);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import lombok.val;
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.model.ContextResource;
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.model.CurrentLoginUserResource;
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.model.RbacSubjectResource;
|
||||
@@ -19,7 +21,7 @@ import net.hostsharing.hsadminng.accounts.generated.api.v1.model.CredentialsPatc
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.model.CredentialsResource;
|
||||
import net.hostsharing.hsadminng.accounts.generated.api.v1.model.HsOfficePersonResource;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePerson;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||
import net.hostsharing.hsadminng.mapper.StrictMapper;
|
||||
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||
@@ -62,7 +64,7 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
private MessageTranslator messageTranslator;
|
||||
|
||||
@Autowired
|
||||
private HsOfficePersonRbacRepository rbacPersonRepo;
|
||||
private HsOfficePersonRealRepository realPersonRepo;
|
||||
|
||||
@Autowired
|
||||
private HsCredentialsRepository credentialsRepo;
|
||||
@@ -77,11 +79,11 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
|
||||
context.define(); // without assumed roles, otherwise we cannot access the subject anymore
|
||||
|
||||
final var credentialsEntity = credentialsRepo.findByUuid(credentialsUuid);
|
||||
val credentialsEntity = credentialsRepo.findByUuid(credentialsUuid);
|
||||
if (credentialsEntity.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
final var result = mapper.map(
|
||||
val result = mapper.map(
|
||||
credentialsEntity.get(), CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
@@ -95,10 +97,10 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
|
||||
final var credentials = personUuid == null
|
||||
val credentials = personUuid == null
|
||||
? credentialsRepo.findByCurrentSubject()
|
||||
: findByPersonUuid(personUuid);
|
||||
final var result = mapper.mapList(
|
||||
val result = mapper.mapList(
|
||||
credentials, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
@@ -112,22 +114,25 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
context.define(); // without assumed roles, otherwise we cannot access the subject anymore
|
||||
|
||||
// first create and save the subject to get its UUID
|
||||
final var newlySavedSubject = createSubject(body.getNickname());
|
||||
val newlySavedSubject = createSubject(body.getNickname());
|
||||
|
||||
// afterward, create and save the credentials entity with the subject's UUID
|
||||
final var newCredentialsEntity = mapper.map(
|
||||
val newCredentialsEntity = mapper.map(
|
||||
body, HsCredentialsEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
||||
validate(newCredentialsEntity);
|
||||
newCredentialsEntity.setSubject(newlySavedSubject);
|
||||
validateOnCreate(newCredentialsEntity);
|
||||
|
||||
// switch to the new subject to get access to its own subject RBAC object
|
||||
context.define("activate newly created self-service subject", null, body.getNickname(), null);
|
||||
newCredentialsEntity.setSubject(em.merge(newlySavedSubject)); // attached to EM by the new subject
|
||||
em.persist(newCredentialsEntity); // newCredentialsEntity.uuid == newlySavedSubject.uuid => do not use repository!
|
||||
|
||||
// return the new credentials as a resource
|
||||
final var uri =
|
||||
val uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/hs/accounts/credentials/{id}")
|
||||
.buildAndExpand(newCredentialsEntity.getUuid())
|
||||
.toUri();
|
||||
final var newCredentialsResource = mapper.map(
|
||||
val newCredentialsResource = mapper.map(
|
||||
newCredentialsEntity, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.created(uri).body(newCredentialsResource);
|
||||
}
|
||||
@@ -137,8 +142,9 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
@Timed("app.credentials.credentials.deleteCredentialsByUuid")
|
||||
public ResponseEntity<Void> deleteCredentialsByUuid(final UUID credentialsUuid) {
|
||||
context.define(); // without assumed roles, otherwise we cannot access the subject anymore
|
||||
final var credentialsEntity = em.getReference(HsCredentialsEntity.class, credentialsUuid);
|
||||
val credentialsEntity = em.getReference(HsCredentialsEntity.class, credentialsUuid);
|
||||
credentialsEntity.getLoginContexts().clear();
|
||||
validateOnDelete(credentialsEntity);
|
||||
em.flush();
|
||||
em.remove(credentialsEntity);
|
||||
em.remove(credentialsEntity.getSubject());
|
||||
@@ -154,12 +160,13 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
) {
|
||||
context.define(); // without assumed roles, otherwise we cannot access the subject anymore
|
||||
|
||||
final var current = credentialsRepo.findByUuid(credentialsUuid).orElseThrow();
|
||||
val current = credentialsRepo.findByUuid(credentialsUuid).orElseThrow();
|
||||
|
||||
new HsCredentialsEntityPatcher(contextMapper, current).apply(body);
|
||||
validateOnUpdate(current);
|
||||
|
||||
final var saved = credentialsRepo.save(current);
|
||||
final var mapped = mapper.map(
|
||||
val saved = credentialsRepo.save(current);
|
||||
val mapped = mapper.map(
|
||||
saved, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(mapped);
|
||||
}
|
||||
@@ -173,56 +180,129 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
context.define();
|
||||
|
||||
// fetch the data
|
||||
final var currentSubjectUuid = context.fetchCurrentSubjectUuid();
|
||||
final var currentSubject = rbacSubjectRepo.findByUuid(currentSubjectUuid);
|
||||
val currentSubjectUuid = context.fetchCurrentSubjectUuid();
|
||||
val currentSubject = rbacSubjectRepo.findByUuid(currentSubjectUuid);
|
||||
val person = credentialsRepo.findByUuid(currentSubjectUuid).orElseThrow().getPerson();
|
||||
|
||||
final boolean isGlobalAdmin = context.isGlobalAdmin();
|
||||
final var person = credentialsRepo.findByUuid(currentSubjectUuid).orElseThrow().getPerson();
|
||||
|
||||
// finally, return the result
|
||||
final var result = currentLoginUserResponse(currentSubject, person, isGlobalAdmin);
|
||||
val result = currentLoginUserResponse(currentSubject, person, isGlobalAdmin);
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Timed("app.credentials.credentials.credentialsUsed")
|
||||
public ResponseEntity<CredentialsResource> credentialsUsed(
|
||||
final String assumedRoles,
|
||||
final UUID credentialsUuid) {
|
||||
context.assumeRoles(assumedRoles);
|
||||
public ResponseEntity<CredentialsResource> credentialsUsed(final UUID credentialsUuid) {
|
||||
context.define();
|
||||
|
||||
final var current = credentialsRepo.findByUuid(credentialsUuid).orElseThrow();
|
||||
val current = credentialsRepo.findByUuid(credentialsUuid).orElseThrow();
|
||||
|
||||
current.setOnboardingToken(null);
|
||||
current.setLastUsed(LocalDateTime.now());
|
||||
|
||||
final var saved = credentialsRepo.save(current);
|
||||
final var mapped = mapper.map(saved, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
val saved = credentialsRepo.save(current);
|
||||
val mapped = mapper.map(saved, CredentialsResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(mapped);
|
||||
}
|
||||
|
||||
private void validate(final HsCredentialsEntity newCredentialsEntity) {
|
||||
// the referenced person must be represented by currently logged in person
|
||||
final var personUuid = newCredentialsEntity.getPerson().getUuid();
|
||||
final var representedPersonUuids = rbacPersonRepo.findPersonsRepresentedByPersonWithUuid(personUuid)
|
||||
private void validateOnCreate(final HsCredentialsEntity newCredentialsEntity) {
|
||||
validateReferencedPersonToBeRepresentedByLoginUserPerson(newCredentialsEntity);
|
||||
validateNormalUsersOnlyAccessPublicContexts(newCredentialsEntity);
|
||||
validateNaturalPersonRequirementOfContexts(newCredentialsEntity);
|
||||
}
|
||||
|
||||
private void validateOnUpdate(final HsCredentialsEntity current) {
|
||||
validateNormalUsersOnlyAccessPublicContexts(current);
|
||||
validateNaturalPersonRequirementOfContexts(current);
|
||||
validateOwnHsadminCredentialsMustNotBeRemoved(current);
|
||||
}
|
||||
|
||||
private void validateOnDelete(final HsCredentialsEntity credentialsEntity) {
|
||||
validateOwnHsadminCredentialsMustNotBeRemoved(credentialsEntity);
|
||||
}
|
||||
|
||||
private void validateReferencedPersonToBeRepresentedByLoginUserPerson(final HsCredentialsEntity newCredentialsEntity) {
|
||||
if (context.isGlobalAdmin()) {
|
||||
return;
|
||||
}
|
||||
val referredPersonUuid = newCredentialsEntity.getPerson().getUuid();
|
||||
val currentSubjectUuid = context.fetchCurrentSubjectUuid();
|
||||
val loginPersonUuid = credentialsRepo.findByUuid(currentSubjectUuid)
|
||||
.map(HsCredentialsEntity::getPerson)
|
||||
.map(HsOfficePerson::getUuid)
|
||||
.orElseThrow();
|
||||
val representedPersonUuids = realPersonRepo.findPersonsRepresentedByPersonWithUuid(loginPersonUuid)
|
||||
.stream().map(HsOfficePerson::getUuid).toList();
|
||||
if ( !representedPersonUuids.contains(personUuid)) {
|
||||
if ( !representedPersonUuids.contains(referredPersonUuid)) {
|
||||
throw new ValidationException(
|
||||
messageTranslator.translate(
|
||||
"credentials.access-denied-person-uuid-{0}-not-represented-by-currently-logged-in-person",
|
||||
personUuid));
|
||||
"credentials.access-denied-to-person-with-uuid-{0}-not-represented-by-currently-logged-in-person",
|
||||
loginPersonUuid));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateNormalUsersOnlyAccessPublicContexts(final HsCredentialsEntity newCredentialsEntity) {
|
||||
val forbiddenContexts = newCredentialsEntity.getLoginContexts().stream()
|
||||
.filter(c -> !c.isPublicAccess() && !context.isGlobalAdmin() )
|
||||
.toList();
|
||||
if (!forbiddenContexts.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
messageTranslator.translate(
|
||||
"credentials.access-denied-for-contexts-{0}",
|
||||
toDisplay(forbiddenContexts)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateNaturalPersonRequirementOfContexts(final HsCredentialsEntity newCredentialsEntity) {
|
||||
if (newCredentialsEntity.getPerson().getPersonType().equals(HsOfficePersonType.NATURAL_PERSON)) {
|
||||
return;
|
||||
}
|
||||
val contextsWhichRequireNaturalPerson = newCredentialsEntity.getLoginContexts().stream()
|
||||
.filter(HsCredentialsContext::isOnlyForNaturalPersons)
|
||||
.toList();
|
||||
if (!contextsWhichRequireNaturalPerson.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
messageTranslator.translate(
|
||||
"credentials.context-requires-natural-person-{0}",
|
||||
toDisplay(contextsWhichRequireNaturalPerson)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOwnHsadminCredentialsMustNotBeRemoved(final HsCredentialsEntity newCredentialsEntity) {
|
||||
if (!newCredentialsEntity.getSubject().getUuid().equals(context.fetchCurrentSubjectUuid())) {
|
||||
return;
|
||||
}
|
||||
val hsadminCredentialsContext = newCredentialsEntity.getLoginContexts().stream()
|
||||
.filter(HsCredentialsContext::isHsadminContext)
|
||||
.toList();
|
||||
if (hsadminCredentialsContext.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
messageTranslator.translate(
|
||||
"credentials.own-hsadmin-credentials-must-not-be-removed"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private static String toDisplay(final List<HsCredentialsContextRealEntity> contextsWhichRequireNaturalPerson) {
|
||||
return contextsWhichRequireNaturalPerson.stream()
|
||||
.map(HsCredentialsContext::toShortString)
|
||||
.sorted()
|
||||
.map(s -> "'" + s + "'")
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
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-service subject", null, nickname, null);
|
||||
}
|
||||
return subjectRepo.findByUuid(newRbacSubject.getUuid()); // now attached to EM
|
||||
val rbacSubjectEntity = new RbacSubjectEntity(null, nickname);
|
||||
val newRbacSubject = subjectRepo.create(rbacSubjectEntity);
|
||||
return newRbacSubject;
|
||||
}
|
||||
|
||||
private List<HsCredentialsEntity> findByPersonUuid(final UUID personUuid) {
|
||||
final var person = rbacPersonRepo.findByUuid(personUuid).orElseThrow(
|
||||
val person = realPersonRepo.findByUuid(personUuid).orElseThrow(
|
||||
() -> new EntityNotFoundException(
|
||||
messageTranslator.translate("general.{0}-{1}-not-found-or-not-accessible", "personUuid", personUuid)
|
||||
)
|
||||
@@ -236,7 +316,7 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
final RbacSubjectEntity currentSubject,
|
||||
final HsOfficePerson<?> person,
|
||||
final boolean isGlobalAdmin) {
|
||||
final var result = new CurrentLoginUserResource();
|
||||
val result = new CurrentLoginUserResource();
|
||||
result.setSubject(mapper.map(currentSubject, RbacSubjectResource.class));
|
||||
result.setPerson(mapper.map(person, HsOfficePersonResource.class));
|
||||
result.setGlobalAdmin(isGlobalAdmin);
|
||||
@@ -267,7 +347,7 @@ public class HsCredentialsController implements CredentialsApi {
|
||||
}
|
||||
|
||||
final BiConsumer<CredentialsInsertResource, HsCredentialsEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||
final var person = rbacPersonRepo.findByUuid(resource.getPersonUuid()).orElseThrow(
|
||||
val person = realPersonRepo.findByUuid(resource.getPersonUuid()).orElseThrow(
|
||||
() -> new EntityNotFoundException(
|
||||
messageTranslator.translate("general.{0}-{1}-not-found-or-not-accessible", "personUuid", resource.getPersonUuid())
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.accounts;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
|
||||
import net.hostsharing.hsadminng.persistence.BaseEntity; // Assuming BaseEntity exists
|
||||
import net.hostsharing.hsadminng.rbac.subject.RbacSubjectEntity;
|
||||
import net.hostsharing.hsadminng.repr.Stringify;
|
||||
@@ -46,7 +46,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 HsOfficePersonRbacEntity person;
|
||||
private HsOfficePersonRealEntity person; // TODO.impl: add RBAC-Support to CredentialsEntity, see Story #
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
+16
@@ -23,6 +23,22 @@ public interface HsOfficePersonRealRepository extends Repository<HsOfficePersonR
|
||||
@Timed("app.office.persons.repo.findPersonByOptionalNameLike.real")
|
||||
List<HsOfficePersonRealEntity> findPersonByOptionalNameLike(String name);
|
||||
|
||||
@Query(value = """
|
||||
WITH RECURSIVE
|
||||
represented_persons AS (
|
||||
SELECT relation.anchorUuid person_uuid
|
||||
FROM hs_office.relation relation
|
||||
WHERE relation.type = 'REPRESENTATIVE'
|
||||
AND relation.holderUuid = :personUuid
|
||||
)
|
||||
SELECT person.*
|
||||
FROM hs_office.person person
|
||||
WHERE person.uuid IN (SELECT person_uuid FROM represented_persons)
|
||||
OR person.uuid = :personUuid
|
||||
""", nativeQuery = true)
|
||||
@Timed("app.office.persons.repo.findRepresentedPersons.real")
|
||||
List<HsOfficePersonRealEntity> findPersonsRepresentedByPersonWithUuid(UUID personUuid);
|
||||
|
||||
@Timed("app.office.persons.repo.save.real")
|
||||
HsOfficePersonRealEntity save(final HsOfficePersonRealEntity entity);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public class PingController implements TestApi {
|
||||
public ResponseEntity<String> pong() {
|
||||
final var userName = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
// HOWTO translate text with placeholders - also see in resource files i18n/messages_*.properties.
|
||||
final var translatedMessage = messageTranslator.translate("ping {0} - in English", userName);
|
||||
final var translatedMessage = messageTranslator.translate("test.ponged-{0}--in-your-language", userName);
|
||||
return ResponseEntity.ok(translatedMessage + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ public class RbacSubjectController implements RbacSubjectsApi {
|
||||
if (body.getUuid() == null) {
|
||||
body.setUuid(UUID.randomUUID());
|
||||
}
|
||||
final var saved = mapper.map(body, RbacSubjectEntity.class);
|
||||
rbacSubjectRepository.create(saved);
|
||||
final var saved = rbacSubjectRepository.create(mapper.map(body, RbacSubjectEntity.class));
|
||||
final var uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/rbac/subjects/{id}")
|
||||
|
||||
@@ -45,6 +45,10 @@ public interface RbacSubjectRepository extends Repository<RbacSubjectEntity, UUI
|
||||
rbacSubjectEntity.setUuid(UUID.randomUUID());
|
||||
}
|
||||
insert(rbacSubjectEntity);
|
||||
// RbacSubjectEntity binds to 'rbac.subject_rv',
|
||||
// but the current user might not be allowed to read the newly created row from the restricted view,
|
||||
// only the newly created subject (or a global admin) is allowed to read the new subject.
|
||||
// Thus, the code which calls this method needs to switch the login user and fetch an attached entity.
|
||||
return rbacSubjectEntity; // Not yet attached to EM!
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ post:
|
||||
description: 'Is called when credentials got used for a login.'
|
||||
operationId: credentialsUsed
|
||||
parameters:
|
||||
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: credentialsUuid
|
||||
in: path
|
||||
required: true
|
||||
|
||||
@@ -15,8 +15,11 @@ general.{0}-{1}-not-found-or-not-accessible={0} "{1}" nicht gefunden oder nicht
|
||||
general.but-is=ist aber
|
||||
|
||||
# credentials validations
|
||||
credentials.existing-{0}-does-not-match-given-resource-{1}=existierender Credentials-Context {0} passt nicht zum angegebenen {1}
|
||||
credentials.access-denied-person-uuid-{0}-not-represented-by-currently-logged-in-person=Zugriff verweigert: personUuid "{0}" wird von der eingeloggten Person nicht repräsentiert
|
||||
credentials.existing-credentials-context-{0}-does-not-match-given-resource-{1}=existierender Credentials-Context {0} passt nicht zum angegebenen {1}
|
||||
credentials.access-denied-to-person-with-uuid-{0}-not-represented-by-currently-logged-in-person=Zugriff verweigert: personUuid "{0}" wird von der eingeloggten Person nicht repräsentiert
|
||||
credentials.access-denied-for-contexts-{0}=Kontext-Zugriff verweigert: {0}
|
||||
credentials.context-requires-natural-person-{0}=Kontext verlangt eine natürliche Person: {0}
|
||||
credentials.own-hsadmin-credentials-must-not-be-removed=die eigenen hsadmin-Credentials dürfen nicht entfernt werden
|
||||
|
||||
# office.coop-shares
|
||||
office.coop-shares.for-transactiontype-{0}-sharecount-must-be-positive-but-is-{1}=für transactionType={0}, muss shareCount positiv sein, ist aber {1}
|
||||
|
||||
@@ -15,8 +15,11 @@ general.{0}-{1}-not-found-or-not-accessible={0} "{1}" not found or not accessibl
|
||||
general.but-is=but is
|
||||
|
||||
# credentials validations
|
||||
credentials.existing-{0}-does-not-match-given-resource-{1}=existing {0} does not match given resource {1}
|
||||
credentials.access-denied-person-uuid-{0}-not-represented-by-currently-logged-in-person=access denied: personUuid "{0}" not represented by currently logged in person
|
||||
credentials.existing-credentials-context-{0}-does-not-match-given-resource-{1}=existing {0} does not match given resource {1}
|
||||
credentials.access-denied-to-person-with-uuid-{0}-not-represented-by-currently-logged-in-person=access denied: personUuid "{0}" not represented by currently logged in person
|
||||
credentials.access-denied-for-contexts-{0}=context-access denied: {0}
|
||||
credentials.context-requires-natural-person-{0}=context requires natural person: {0}
|
||||
credentials.own-hsadmin-credentials-must-not-be-removed=own hsadmin-credentials must not be removed
|
||||
|
||||
# office.coop-shares
|
||||
office.coop-shares.for-transactiontype-{0}-sharecount-must-be-positive-but-is-{1}=for transactiontType {0} shareCount must be positive but is {1}
|
||||
|
||||
@@ -15,8 +15,11 @@ general.{0}-{1}-not-found-or-not-accessible={0} "{1}" non trouvé ou non accessi
|
||||
general.but-is=mais c'est
|
||||
|
||||
# credentials validations
|
||||
credentials.existing-{0}-does-not-match-given-resource-{1}={0} existant ne correspond pas à la ressource donnée {1}
|
||||
credentials.access-denied-person-uuid-{0}-not-represented-by-currently-logged-in-person=accès refusé : personUuid "{0}" non représenté par la personne actuellement connectée
|
||||
credentials.existing-credentials-context-{0}-does-not-match-given-resource-{1}={0} existant ne correspond pas à la ressource donnée {1}
|
||||
credentials.access-denied-to-person-with-uuid-{0}-not-represented-by-currently-logged-in-person=accès refusé : personUuid "{0}" non représenté par la personne actuellement connectée
|
||||
credentials.access-denied-for-contexts-{0}=accès au contexte refusé : {0}
|
||||
credentials.context-requires-natural-person-{0}=le contexte requiert une personne physique : {0}
|
||||
credentials.own-hsadmin-credentials-must-not-be-removed=suppression des identifiants hsadmin propres interdite
|
||||
|
||||
# office.coop-shares
|
||||
office.coop-shares.for-transactiontype-{0}-sharecount-must-be-positive-but-is-{1}=pour le type de transaction {0}, shareCount doit être positif mais est {1}
|
||||
|
||||
Reference in New Issue
Block a user