Skip to content

Commit

Permalink
feat(cs): names for subsystems
Browse files Browse the repository at this point in the history
UI and global conf

Refs: XRDDEV-2762
  • Loading branch information
ovidijusnortal committed Feb 10, 2025
1 parent 43b51c7 commit d0d3b69
Show file tree
Hide file tree
Showing 79 changed files with 4,005 additions and 267 deletions.
3 changes: 2 additions & 1 deletion ansible/vars_files/cs_modules.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
cs_modules:
centralserver-admin-service:
cs-admin-service:
dir: central-server/admin-service/application
build: build
lib: centralserver-admin-service-1.0.jar
target: /usr/share/xroad/jlib
service: xroad-center
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- EDIT_MEMBER_NAME: [ XROAD_REGISTRATION_OFFICER ]
- ADD_MEMBER_SUBSYSTEM: [ XROAD_REGISTRATION_OFFICER ]
- REMOVE_MEMBER_SUBSYSTEM: [ XROAD_REGISTRATION_OFFICER ]
- EDIT_MEMBER_SUBSYSTEM: [ XROAD_REGISTRATION_OFFICER ]
- UNREGISTER_MEMBER: [ XROAD_REGISTRATION_OFFICER ]
- UNREGISTER_SUBSYSTEM: [ XROAD_REGISTRATION_OFFICER ]
- ADD_CLIENT_REGISTRATION_REQUEST: [ XROAD_REGISTRATION_OFFICER, XROAD_MANAGEMENT_SERVICE ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class FlattenedSecurityServerClientView extends Auditable {
private MemberClass memberClass;
private String memberCode;
private String subsystemCode;
private String subsystemName;
private String memberName;
private XRoadObjectType type;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class Subsystem extends SecurityServerClient {
private String subsystemCode;
private String name;

public Subsystem(String name, XRoadMember member, ClientId identifier) {
public Subsystem(XRoadMember member, ClientId identifier, String name) {
super(SubsystemId.create(identifier), name);
if (!identifier.subsystemContainsMember(member.getIdentifier())) {
throw new IllegalArgumentException("Subsystem identifier does not match member");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ public interface SubsystemService {
void deleteSubsystem(ClientId subsystemClientId);


Optional<Subsystem> updateSubsystemName(ClientId clientId, String newName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public class FlattenedSecurityServerClientViewEntity extends AuditableEntity {
@Column(name = "subsystem_code")
private String subsystemCode;

@Column(name = "subsystem_name")
private String subsystemName;

@Column(name = "member_name")
private String memberName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.niis.xroad.cs.admin.core.entity.validation.EntityIdentifier;

import java.util.HashSet;
import java.util.Set;
Expand Down Expand Up @@ -86,15 +85,8 @@ public abstract class SecurityServerClientEntity extends AuditableEntity {
@Setter
private Set<ServerClientEntity> serverClients = new HashSet<>();

@EntityIdentifier
@Column(name = "name")
@Getter
@Setter
private String name;

protected SecurityServerClientEntity(String name, ClientIdEntity identifier) {
protected SecurityServerClientEntity(ClientIdEntity identifier) {
this.identifier = identifier;
this.name = name;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.niis.xroad.cs.admin.core.entity.validation.OptionalEntityIdentifier;

import static org.niis.xroad.cs.admin.core.entity.SubsystemEntity.DISCRIMINATOR_VALUE;

Expand All @@ -60,17 +62,24 @@ public class SubsystemEntity extends SecurityServerClientEntity {
@Getter
private String subsystemCode;

@OptionalEntityIdentifier
@Column(name = "name")
@Getter
@Setter
private String name;

public SubsystemEntity(XRoadMemberEntity member, ClientId identifier) {
this(null, member, identifier);
}

public SubsystemEntity(String name, XRoadMemberEntity member, ClientId identifier) {
super(name, SubsystemIdEntity.ensure(identifier));
super(SubsystemIdEntity.ensure(identifier));
if (!identifier.subsystemContainsMember(member.getIdentifier())) {
throw new IllegalArgumentException("Subsystem identifier does not match member");
}
this.xroadMember = member;
this.subsystemCode = identifier.getSubsystemCode();
this.name = name;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ public class XRoadMemberEntity extends SecurityServerClientEntity {
@Access(AccessType.FIELD)
private String memberCode;

@EntityIdentifier
@Column(name = "name")
@Getter
@Setter
private String name;

@Column(name = "administrative_contact")
@Getter
@Setter
Expand All @@ -88,11 +94,12 @@ public class XRoadMemberEntity extends SecurityServerClientEntity {
private Set<SubsystemEntity> subsystems = new HashSet<>(0);

public XRoadMemberEntity(String name, ClientId identifier, MemberClassEntity memberClass) {
super(MemberIdEntity.ensure(identifier), name);
super(MemberIdEntity.ensure(identifier));
boolean isMemberClassInconsistent = !Objects.equals(identifier.getMemberClass(), memberClass.getCode());
if (isMemberClassInconsistent) {
throw new IllegalArgumentException("identifier and memberClass are not consistent");
}
this.name = name;
this.memberCode = identifier.getMemberCode();
this.memberClass = memberClass;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
Expand All @@ -42,38 +40,12 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@NotBlank
@Length(
max = 255,
message = EntityIdentifier.LENGTH_VIOLATION_MESSAGE
)
@Pattern(
regexp = "^"
+ "\\s*("
+ "(?!"
+ "\\s*" // Don't allow preceding spaces while eliminating
+ "(?:\\.$|\\./|\\.\\.$|\\.\\./)" // Eliminate beginnings ".", "..", "./", "../"
+ ")"
+ "("
+ "(?!/\\.\\s*$|/\\./|/\\.\\.\\s*$|/\\.\\./)" // Eliminate anywhere "/./", "/../" and ending "/.", "/.."
// and don't allow following spaces while eliminating the
// ending
+ "[^\\\\\\u0000-\\u001F\\u007F-\\u009F\\u200B\\uFEFF]" // Allow only printable characters
+ ")*"
+ ")?"
+ "$",
message = EntityIdentifier.PATTERN_VIOLATION_MESSAGE
)
@OptionalEntityIdentifier
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface EntityIdentifier {
String LENGTH_VIOLATION_MESSAGE = "length must be less or equal to {max}";
String PATTERN_VIOLATION_MESSAGE = "must not "
+ "start with \".\", \"./\", \"..\", \"../\", "
+ "contain non-printable characters, \"/./\", \"/../\", "
+ "end with \"/.\", \"/..\"";

String message() default "X-Road identifier is invalid";

Class<?>[] groups() default {};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* The MIT License
* <p>
* Copyright (c) 2019- Nordic Institute for Interoperability Solutions (NIIS)
* Copyright (c) 2018 Estonian Information System Authority (RIA),
* Nordic Institute for Interoperability Solutions (NIIS), Population Register Centre (VRK)
* Copyright (c) 2015-2017 Estonian Information System Authority (RIA), Population Register Centre (VRK)
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.niis.xroad.cs.admin.core.entity.validation;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Length(
max = 255,
message = OptionalEntityIdentifier.LENGTH_VIOLATION_MESSAGE
)
@Pattern(
regexp = "^"
+ "\\s*("
+ "(?!"
+ "\\s*" // Don't allow preceding spaces while eliminating
+ "(?:\\.$|\\./|\\.\\.$|\\.\\./)" // Eliminate beginnings ".", "..", "./", "../"
+ ")"
+ "("
+ "(?!/\\.\\s*$|/\\./|/\\.\\.\\s*$|/\\.\\./)" // Eliminate anywhere "/./", "/../" and ending "/.", "/.."
// and don't allow following spaces while eliminating the
// ending
+ "[^\\\\\\u0000-\\u001F\\u007F-\\u009F\\u200B\\uFEFF]" // Allow only printable characters
+ ")*"
+ ")?"
+ "$",
message = OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE
)
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface OptionalEntityIdentifier {
String LENGTH_VIOLATION_MESSAGE = "length must be less or equal to {max}";
String PATTERN_VIOLATION_MESSAGE = "must not "
+ "start with \".\", \"./\", \"..\", \"../\", "
+ "contain non-printable characters, \"/./\", \"/../\", "
+ "end with \"/.\", \"/..\"";

String message() default "X-Road identifier is invalid";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ public void deleteSubsystem(ClientId subsystemClientId) {
subsystemRepository.deleteById(subsystem.getId());
}

@Override
public Optional<Subsystem> updateSubsystemName(ClientId clientId, String newName) {
auditDataHelper.put(MEMBER_SUBSYSTEM_NAME, newName);
auditDataHelper.put(MEMBER_SUBSYSTEM_CODE, newName);
auditDataHelper.put(MEMBER_CLASS, clientId.getMemberClass());
auditDataHelper.put(MEMBER_CODE, clientId.getMemberCode());
return subsystemRepository.findByIdentifier(clientId)
.map(subsystem -> {
subsystem.setName(newName);
return subsystem;
})
.map(subsystemConverter::toDto);
}

private boolean isRegistered(SubsystemEntity subsystem) {
return !CollectionUtils.isEmpty(subsystem.getServerClients());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ public void shouldHaveInvalid(String input, String expectedFault) {
private static Stream<Arguments> invalidEntityIdentifiers() {
return Stream.of(
Arguments.of("", "must not be blank"),
Arguments.of("./", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("../", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/../", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/.", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/./", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of(">CONTAINS NON-PRINTABLE CHARACTER: \u0000<", EntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("./", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("../", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/../", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/.", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("/./", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of(">CONTAINS NON-PRINTABLE CHARACTER: \u0000<", OptionalEntityIdentifier.PATTERN_VIOLATION_MESSAGE),
Arguments.of("TOO LONG INPUT" + " ".repeat(255), "length must be less or equal to 255")
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public class SubsystemServiceImplTest implements WithInOrder {
@DisplayName("add(Client clientDto)")
class AddMethod {
private final String memberName = "member name";
private final String subsystemName = "subsystem name";
private final MemberId memberId = MemberId.create("TEST", "CLASS", "MEMBER");
private final SubsystemId subsystemId = SubsystemId.create("TEST", "CLASS", "MEMBER", "SUBSYSTEM");
private final SubsystemIdEntity subsystemIdEntity = SubsystemIdEntity.ensure(subsystemId);
Expand All @@ -126,7 +127,7 @@ void shouldCreateClientWhenNotAlreadyPresent() {

when(xRoadMemberRepository.findMember(memberId)).thenReturn(Optional.of(xRoadMember));

SecurityServerClient result = subsystemService.add(new SubsystemCreationRequest(memberId, subsystemId));
SecurityServerClient result = subsystemService.add(new SubsystemCreationRequest(memberId, subsystemId, subsystemName));

assertEquals("MEMBER", result.getIdentifier().getMemberCode());

Expand All @@ -144,7 +145,7 @@ void shouldNotCreateClientWhenAlreadyPresent() {
SubsystemEntity presentSecurityServerClient = mock(SubsystemEntity.class);
when(subsystemRepository.findOneBy(subsystemId)).thenReturn(Optional.of(presentSecurityServerClient));

Executable testable = () -> subsystemService.add(new SubsystemCreationRequest(memberId, subsystemId));
Executable testable = () -> subsystemService.add(new SubsystemCreationRequest(memberId, subsystemId, subsystemName));

DataIntegrityException exception = assertThrows(DataIntegrityException.class, testable);
assertEquals(SUBSYSTEM_EXISTS.getDescription(), exception.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ List<SharedParameters.Member> map(List<FlattenedSecurityServerClientView> flatte

private void addSubSystem(FlattenedSecurityServerClientView client) {
var clientId = toClientId(client);
getSubsystemList(toMemberId(clientId)).add(new SharedParameters.Subsystem(client.getSubsystemCode(), clientId));
getSubsystemList(toMemberId(clientId))
.add(new SharedParameters.Subsystem(client.getSubsystemCode(), client.getSubsystemName(), clientId));
}

private SharedParameters.Member toMember(FlattenedSecurityServerClientView client) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* The MIT License
*
* Copyright (c) 2019- Nordic Institute for Interoperability Solutions (NIIS)
* Copyright (c) 2018 Estonian Information System Authority (RIA),
* Nordic Institute for Interoperability Solutions (NIIS), Population Register Centre (VRK)
* Copyright (c) 2015-2017 Estonian Information System Authority (RIA), Population Register Centre (VRK)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.niis.xroad.cs.admin.globalconf.generator;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.niis.xroad.globalconf.model.SharedParametersV5Marshaller;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
@Slf4j
public class SharedParametersV5Generator {
private final SharedParametersV5Marshaller marshaller = new SharedParametersV5Marshaller();
private final SharedParametersLoader loader;

String generate() {
log.debug("Generating shared parameters");
var parameters = loader.load();
log.trace("Shared parameters loaded: {}", parameters);
return marshaller.marshall(parameters);
}
}
Loading

0 comments on commit d0d3b69

Please sign in to comment.