From 1cd98e638ca788b2ce93c3fa5b15be6f528ed19a Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Thu, 7 Oct 2021 14:05:32 +0200 Subject: [PATCH] refactor(groups): refactor groups route using value objects (DEV-66) (#1913) * refactor: add comments + move projects file in right place * feat: add groups payloads and value objects * update responder, messages, sparql and tests * fix: sparql, responder + tests * refactor: move valueObjects to proper package * refactor: reduce valuObject package usage * refactor: fix description name * fixes * test: update test data + docs * cleanup * build fix --- docs/03-apis/api-admin/groups.md | 2 +- knora-ontologies/knora-admin.ttl | 6 +- test_data/all_data/admin-data.ttl | 4 +- .../drawings-gods_admin-data.ttl | 8 +- .../lumieres-lausanne_admin.ttl | 12 +- .../webapi/messages/OntologyConstants.scala | 2 +- .../webapi/messages/StringFormatter.scala | 2 +- .../groupsmessages/GroupsMessagesADM.scala | 84 +++++++------ .../groupsmessages/GroupsPayloadsADM.scala | 38 ++++++ .../ProjectPayloadsADM.scala | 14 ++- .../ProjectsMessagesADM.scala | 2 +- .../usersmessages/UserPayloadsADM.scala | 10 ++ .../usersmessages/UsersMessagesADM.scala | 10 ++ .../ValueObjectsADM.scala | 114 +++++++++--------- .../responders/admin/GroupsResponderADM.scala | 80 ++++++------ .../admin/ProjectsResponderADM.scala | 1 - .../responders/admin/UsersResponderADM.scala | 4 +- .../webapi/routing/admin/GroupsRouteADM.scala | 16 ++- .../routing/admin/ProjectsRouteADM.scala | 7 +- .../webapi/routing/admin/UsersRouteADM.scala | 10 ++ .../admin/lists/NewListsRouteADMFeature.scala | 2 +- .../admin/lists/OldListsRouteADMFeature.scala | 2 +- .../sparql/admin/createNewGroup.scala.txt | 25 ++-- .../sparql/admin/updateGroup.scala.txt | 37 +++--- .../webapi/e2e/admin/GroupsADME2ESpec.scala | 17 +-- .../GroupsMessagesADMSpec.scala | 3 +- .../valueObjects/ValueObjectsADMSpec.scala | 2 +- .../admin/GroupsResponderADMSpec.scala | 91 +++++++------- .../admin/ProjectsResponderADMSpec.scala | 12 +- .../admin/UsersResponderADMSpec.scala | 13 +- .../sharedtestdata/SharedTestDataADM.scala | 8 +- 31 files changed, 381 insertions(+), 257 deletions(-) create mode 100644 webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala rename webapi/src/main/scala/org/knora/webapi/messages/admin/responder/{usersmessages => projectsmessages}/ProjectPayloadsADM.scala (75%) rename webapi/src/main/scala/org/knora/webapi/messages/admin/responder/{usersmessages => valueObjects}/ValueObjectsADM.scala (85%) diff --git a/docs/03-apis/api-admin/groups.md b/docs/03-apis/api-admin/groups.md index 0f9d28ac13..7a0848f252 100644 --- a/docs/03-apis/api-admin/groups.md +++ b/docs/03-apis/api-admin/groups.md @@ -117,7 +117,7 @@ Example Group Information stored in admin named graph: : rdf:type knora-admin:UserGroup ; knora-admin:groupName "Name of the group" ; - knora-admin:groupDescription "A description of the group" ; + knora-admin:groupDescriptions "A description of the group" ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . diff --git a/knora-ontologies/knora-admin.ttl b/knora-ontologies/knora-admin.ttl index 5e44d8bb5a..d030c16837 100644 --- a/knora-ontologies/knora-admin.ttl +++ b/knora-ontologies/knora-admin.ttl @@ -165,9 +165,9 @@ -### http://www.knora.org/ontology/knora-admin#groupDescription +### http://www.knora.org/ontology/knora-admin#groupDescriptions -:groupDescription rdf:type owl:DatatypeProperty ; +:groupDescriptions rdf:type owl:DatatypeProperty ; rdfs:subPropertyOf knora-base:objectCannotBeMarkedAsDeleted ; @@ -568,7 +568,7 @@ owl:cardinality "1"^^xsd:nonNegativeInteger ] , [ rdf:type owl:Restriction ; - owl:onProperty :groupDescription ; + owl:onProperty :groupDescriptions ; owl:maxCardinality "1"^^xsd:nonNegativeInteger ] , [ rdf:type owl:Restriction ; diff --git a/test_data/all_data/admin-data.ttl b/test_data/all_data/admin-data.ttl index b439a1c8ac..c07a58f042 100644 --- a/test_data/all_data/admin-data.ttl +++ b/test_data/all_data/admin-data.ttl @@ -204,7 +204,7 @@ knora-admin:groupName "Image reviewer"^^xsd:string ; - knora-admin:groupDescription "A group for image reviewers."^^xsd:string ; + knora-admin:groupDescriptions "A group for image reviewers."^^xsd:string ; knora-admin:belongsToProject ; @@ -433,7 +433,7 @@ Die Internetpublikation macht das digitalisierte Korpus dieser Frühdrucke durc rdf:type knora-admin:UserGroup ; knora-admin:groupName "Thing searcher"^^xsd:string ; - knora-admin:groupDescription "A group for thing searchers."^^xsd:string ; + knora-admin:groupDescriptions "A group for thing searchers."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "true"^^xsd:boolean . diff --git a/test_data/other.v1.DrawingsGodsV1Spec/drawings-gods_admin-data.ttl b/test_data/other.v1.DrawingsGodsV1Spec/drawings-gods_admin-data.ttl index 61c3ee6196..991a0a1abd 100644 --- a/test_data/other.v1.DrawingsGodsV1Spec/drawings-gods_admin-data.ttl +++ b/test_data/other.v1.DrawingsGodsV1Spec/drawings-gods_admin-data.ttl @@ -20,28 +20,28 @@ rdf:type knora-admin:UserGroup ; knora-admin:groupName "Meta-annotators"^^xsd:string ; - knora-admin:groupDescription "A group of users allowed to annotate data. Does not upload images nor files. Does not access to personal data."^^xsd:string ; + knora-admin:groupDescriptions "A group of users allowed to annotate data. Does not upload images nor files. Does not access to personal data."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Drawings contributors"^^xsd:string ; - knora-admin:groupDescription "A group of users allowed to upload images, files and annotate data. Does not access to personal data."^^xsd:string ; + knora-admin:groupDescriptions "A group of users allowed to upload images, files and annotate data. Does not access to personal data."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "SNF team"^^xsd:string ; - knora-admin:groupDescription "A core group of members from the SNF project. Access to any data, including sensitive."^^xsd:string ; + knora-admin:groupDescriptions "A core group of members from the SNF project. Access to any data, including sensitive."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Administrators"^^xsd:string ; - knora-admin:groupDescription "A custom admin group created to apply permission precedence rules. Replaces the built-in knora-admin:ProjectAdmin group, not used for this project."^^xsd:string ; + knora-admin:groupDescriptions "A custom admin group created to apply permission precedence rules. Replaces the built-in knora-admin:ProjectAdmin group, not used for this project."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . diff --git a/test_data/other.v2.LumieresLausanneV2E2ESpec/lumieres-lausanne_admin.ttl b/test_data/other.v2.LumieresLausanneV2E2ESpec/lumieres-lausanne_admin.ttl index 62d0c96378..e2a43c3ffb 100644 --- a/test_data/other.v2.LumieresLausanneV2E2ESpec/lumieres-lausanne_admin.ttl +++ b/test_data/other.v2.LumieresLausanneV2E2ESpec/lumieres-lausanne_admin.ttl @@ -25,42 +25,42 @@ rdf:type knora-admin:UserGroup ; knora-admin:groupName "Utilisateur"^^xsd:string ; - knora-admin:groupDescription """Statut permanent. Attribué à toute personne désireuse de s'enregistrer. N'est membre d'aucun autre groupe (étudiant, chercheur). Par rapport au visiteur anonyme sans login, accès supplémentaire à la gestion des collections, aux transcriptions/documents joints/projets slmt si autorisation."""^^xsd:string ; + knora-admin:groupDescriptions """Statut permanent. Attribué à toute personne désireuse de s'enregistrer. N'est membre d'aucun autre groupe (étudiant, chercheur). Par rapport au visiteur anonyme sans login, accès supplémentaire à la gestion des collections, aux transcriptions/documents joints/projets slmt si autorisation."""^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Etudiant"^^xsd:string ; - knora-admin:groupDescription """Statut temporaire. Uniquement les étudiants UNIL liés à un séminaire donné dans le cadre du projet Lumières.Lausanne. Ont reçu les consignes ainsi qu'une initiation (obligatoire). A la fin du séminaire, leur statut est changé en statut "Utilisateur", sauf demande particulière."""^^xsd:string ; + knora-admin:groupDescriptions """Statut temporaire. Uniquement les étudiants UNIL liés à un séminaire donné dans le cadre du projet Lumières.Lausanne. Ont reçu les consignes ainsi qu'une initiation (obligatoire). A la fin du séminaire, leur statut est changé en statut "Utilisateur", sauf demande particulière."""^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Chercheur"^^xsd:string ; - knora-admin:groupDescription "Statut permanent. Doctorants, professeurs, autres chercheurs qui ont reçu préalablement l'autorisation d'un directeur. Ont reçu les consignes (obligatoire), et si possible une initiation."^^xsd:string ; + knora-admin:groupDescriptions "Statut permanent. Doctorants, professeurs, autres chercheurs qui ont reçu préalablement l'autorisation d'un directeur. Ont reçu les consignes (obligatoire), et si possible une initiation."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Doctorant"^^xsd:string ; - knora-admin:groupDescription "Statut temporaire. Doctorants et étudiants-assistants directement liés au Projet Lumières.Lausanne. Ont reçu les consignes ainsi qu'une initiation (obligatoire). Une fois leur mandat terminé, passent en statut Chercheur."^^xsd:string ; + knora-admin:groupDescriptions "Statut temporaire. Doctorants et étudiants-assistants directement liés au Projet Lumières.Lausanne. Ont reçu les consignes ainsi qu'une initiation (obligatoire). Une fois leur mandat terminé, passent en statut Chercheur."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Directeur"^^xsd:string ; - knora-admin:groupDescription "Béla Kapossy, Béatrice Lovis."^^xsd:string ; + knora-admin:groupDescriptions "Béla Kapossy, Béatrice Lovis."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . rdf:type knora-admin:UserGroup ; knora-admin:groupName "Administrateur"^^xsd:string ; - knora-admin:groupDescription "Béatrice Lovis."^^xsd:string ; + knora-admin:groupDescriptions "Béatrice Lovis."^^xsd:string ; knora-admin:belongsToProject ; knora-admin:status "true"^^xsd:boolean ; knora-admin:hasSelfJoinEnabled "false"^^xsd:boolean . diff --git a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala index ae06919ac6..134bda3ec9 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala @@ -490,7 +490,7 @@ object OntologyConstants { /* Group */ val UserGroup: IRI = KnoraAdminPrefixExpansion + "UserGroup" val GroupName: IRI = KnoraAdminPrefixExpansion + "groupName" - val GroupDescription: IRI = KnoraAdminPrefixExpansion + "groupDescription" + val GroupDescriptions: IRI = KnoraAdminPrefixExpansion + "groupDescriptions" val BelongsToProject: IRI = KnoraAdminPrefixExpansion + "belongsToProject" /* Built-In Groups */ diff --git a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala index 516d0d3565..d1d84c92a2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala @@ -1673,7 +1673,7 @@ class StringFormatter private ( * IRI. * @return the same optional string. */ - def toOptionalIri(maybeString: Option[String], errorFun: => Nothing): Option[IRI] = + def validateAndEscapeOptionalIri(maybeString: Option[String], errorFun: => Nothing): Option[IRI] = maybeString match { case Some(s) => Some(validateAndEscapeIri(s, errorFun)) case None => None diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala index 5d57d73363..b5c8f891aa 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala @@ -20,7 +20,6 @@ package org.knora.webapi.messages.admin.responder.groupsmessages import java.util.UUID - import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.knora.webapi.IRI import org.knora.webapi.exceptions.BadRequestException @@ -29,6 +28,7 @@ import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectsADMJsonProtocol} import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.admin.responder.{KnoraRequestADM, KnoraResponseADM} +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import spray.json.{DefaultJsonProtocol, JsValue, JsonFormat, RootJsonFormat} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -37,17 +37,17 @@ import spray.json.{DefaultJsonProtocol, JsValue, JsonFormat, RootJsonFormat} /** * Represents an API request payload that asks the Knora API server to create a new group. * - * @param id the optional IRI of the group to be created (unique). - * @param name the name of the group to be created (unique). - * @param description the description of the group to be created. - * @param project the project inside which the group will be created. - * @param status the status of the group to be created (active = true, inactive = false). - * @param selfjoin the status of self-join of the group to be created. + * @param id the optional IRI of the group to be created (unique). + * @param name the name of the group to be created (unique). + * @param descriptions the descriptions of the group to be created. + * @param project the project inside which the group will be created. + * @param status the status of the group to be created (active = true, inactive = false). + * @param selfjoin the status of self-join of the group to be created. */ case class CreateGroupApiRequestADM( id: Option[IRI] = None, name: String, - description: Option[String], + descriptions: Seq[StringLiteralV2], project: IRI, status: Boolean, selfjoin: Boolean @@ -65,24 +65,24 @@ case class CreateGroupApiRequestADM( * Represents an API request payload that asks the Knora API server to update * an existing group. There are two change cases that are covered with this * data structure: - * (1) change of name, description, and selfjoin + * (1) change of name, descriptions, and selfjoin * (2) change of status * - * @param name the new group's name. - * @param description the new group's description. - * @param status the new group's status. - * @param selfjoin the new group's self-join status. + * @param name the new group's name. + * @param descriptions the new group's descriptions. + * @param status the new group's status. + * @param selfjoin the new group's self-join status. */ case class ChangeGroupApiRequestADM( name: Option[String] = None, - description: Option[String] = None, + descriptions: Option[Seq[StringLiteralV2]] = None, status: Option[Boolean] = None, selfjoin: Option[Boolean] = None ) extends GroupsADMJsonProtocol { private val parametersCount = List( name, - description, + descriptions, status, selfjoin ).flatten.size @@ -181,13 +181,13 @@ case class GroupMembersGetRequestADM(groupIri: IRI, featureFactoryConfig: Featur /** * Requests the creation of a new group. * - * @param createRequest the [[CreateGroupApiRequestADM]] information for creating the new group. + * @param createRequest the [[GroupCreatePayloadADM]] information for creating the new group. * @param featureFactoryConfig the feature factory configuration. * @param requestingUser the user initiating the request. * @param apiRequestID the ID of the API request. */ case class GroupCreateRequestADM( - createRequest: CreateGroupApiRequestADM, + createRequest: GroupCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -279,15 +279,21 @@ case class GroupOperationResponseADM(group: GroupADM) extends KnoraResponseADM w /** * The information describing a group. * - * @param id the IRI if the group. - * @param name the name of the group. - * @param description the description of the group. - * @param project the project this group belongs to. - * @param status the group's status. - * @param selfjoin the group's self-join status. + * @param id the IRI if the group. + * @param name the name of the group. + * @param descriptions the descriptions of the group. + * @param project the project this group belongs to. + * @param status the group's status. + * @param selfjoin the group's self-join status. */ -case class GroupADM(id: IRI, name: String, description: String, project: ProjectADM, status: Boolean, selfjoin: Boolean) - extends Ordered[GroupADM] { +case class GroupADM( + id: IRI, + name: String, + descriptions: Seq[StringLiteralV2], + project: ProjectADM, + status: Boolean, + selfjoin: Boolean +) extends Ordered[GroupADM] { /** * Allows to sort collections of GroupADM. Sorting is done by the id. @@ -298,7 +304,7 @@ case class GroupADM(id: IRI, name: String, description: String, project: Project GroupShortADM( id = id, name = name, - description = description, + descriptions = descriptions, status = status, selfjoin = selfjoin ) @@ -307,25 +313,25 @@ case class GroupADM(id: IRI, name: String, description: String, project: Project /** * The information describing a group (without project). * - * @param id the IRI if the group. - * @param name the name of the group. - * @param description the description of the group. - * @param status the group's status. - * @param selfjoin the group's self-join status. + * @param id the IRI if the group. + * @param name the name of the group. + * @param descriptions the descriptions of the group. + * @param status the group's status. + * @param selfjoin the group's self-join status. */ -case class GroupShortADM(id: IRI, name: String, description: String, status: Boolean, selfjoin: Boolean) +case class GroupShortADM(id: IRI, name: String, descriptions: Seq[StringLiteralV2], status: Boolean, selfjoin: Boolean) /** * Payload used for updating of an existing group. * - * @param name the name of the group. - * @param description the description of the group. - * @param status the group's status. - * @param selfjoin the group's self-join status. + * @param name the name of the group. + * @param descriptions the descriptions of the group. + * @param status the group's status. + * @param selfjoin the group's self-join status. */ case class GroupUpdatePayloadADM( name: Option[String] = None, - description: Option[String] = None, + descriptions: Option[Seq[StringLiteralV2]] = None, status: Option[Boolean] = None, selfjoin: Option[Boolean] = None ) @@ -348,9 +354,9 @@ trait GroupsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol wi implicit val groupMembersResponseADMFormat: RootJsonFormat[GroupMembersGetResponseADM] = jsonFormat(GroupMembersGetResponseADM, "members") implicit val createGroupApiRequestADMFormat: RootJsonFormat[CreateGroupApiRequestADM] = - jsonFormat(CreateGroupApiRequestADM, "id", "name", "description", "project", "status", "selfjoin") + jsonFormat(CreateGroupApiRequestADM, "id", "name", "descriptions", "project", "status", "selfjoin") implicit val changeGroupApiRequestADMFormat: RootJsonFormat[ChangeGroupApiRequestADM] = - jsonFormat(ChangeGroupApiRequestADM, "name", "description", "status", "selfjoin") + jsonFormat(ChangeGroupApiRequestADM, "name", "descriptions", "status", "selfjoin") implicit val groupOperationResponseADMFormat: RootJsonFormat[GroupOperationResponseADM] = jsonFormat(GroupOperationResponseADM, "group") } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala new file mode 100644 index 0000000000..95112bef13 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsPayloadsADM.scala @@ -0,0 +1,38 @@ +package org.knora.webapi.messages.admin.responder.groupsmessages + +import org.knora.webapi.IRI +import org.knora.webapi.messages.admin.responder.valueObjects.{Name, Description, Selfjoin, Status} + +/** + * Group payload + */ +sealed abstract case class GroupCreatePayloadADM private ( + // TODO: shouldn't IRI be a value object too - since it's just String synonym? + id: Option[IRI], + name: Name, + descriptions: Description, + project: IRI, + status: Status, + selfjoin: Selfjoin +) + +object GroupCreatePayloadADM { + + /** The create constructor */ + def create( + id: Option[IRI], + name: Name, + descriptions: Description, + project: IRI, + status: Status, + selfjoin: Selfjoin + ): GroupCreatePayloadADM = + new GroupCreatePayloadADM( + id = id, + name = name, + descriptions = descriptions, + project = project, + status = status, + selfjoin = selfjoin + ) {} +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ProjectPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectPayloadsADM.scala similarity index 75% rename from webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ProjectPayloadsADM.scala rename to webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectPayloadsADM.scala index f9f1562674..bd98347dab 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ProjectPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectPayloadsADM.scala @@ -1,6 +1,18 @@ -package org.knora.webapi.messages.admin.responder.usersmessages +package org.knora.webapi.messages.admin.responder.projectsmessages import org.knora.webapi.IRI +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Shortname, + Longname, + Shortcode, + Description, + Keywords, + Logo, + Status, + Selfjoin +} + +// TODO: https://github.com/dasch-swiss/dsp-api/pull/1909#discussion_r718330669 /** * Project payload diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala index c1a60679d7..bb7f4018f3 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADM.scala @@ -28,7 +28,7 @@ import org.knora.webapi.annotation.{ApiMayChange, ServerUnique} import org.knora.webapi.exceptions.{BadRequestException, DataConversionException, OntologyConstraintException} import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.usersmessages.{ProjectCreatePayloadADM, UserADM} +import org.knora.webapi.messages.admin.responder.usersmessages.UserADM import org.knora.webapi.messages.admin.responder.{KnoraRequestADM, KnoraResponseADM} import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralV2, TriplestoreJsonProtocol} import org.knora.webapi.messages.v1.responder.projectmessages.ProjectInfoV1 diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UserPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UserPayloadsADM.scala index 457b32923d..0ec8a8da82 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UserPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UserPayloadsADM.scala @@ -1,6 +1,16 @@ package org.knora.webapi.messages.admin.responder.usersmessages import org.knora.webapi.IRI +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Username, + Email, + GivenName, + FamilyName, + Password, + Status, + LanguageCode, + SystemAdmin +} /** * User entity representing the payload for the create user request diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersMessagesADM.scala index b0c530ff24..c9ec95cce6 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersMessagesADM.scala @@ -29,6 +29,16 @@ import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, P import org.knora.webapi.messages.admin.responder.{KnoraRequestADM, KnoraResponseADM} import org.knora.webapi.messages.v1.responder.projectmessages.ProjectInfoV1 import org.knora.webapi.messages.v1.responder.usermessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Username, + Email, + GivenName, + FamilyName, + Password, + Status, + LanguageCode, + SystemAdmin +} import org.knora.webapi.messages.{OntologyConstants, StringFormatter} import spray.json._ diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala similarity index 85% rename from webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ValueObjectsADM.scala rename to webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala index 015a8e7131..93c3d1c663 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/ValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala @@ -1,4 +1,4 @@ -package org.knora.webapi.messages.admin.responder.usersmessages +package org.knora.webapi.messages.admin.responder.valueObjects import org.knora.webapi.LanguageCodes import org.knora.webapi.exceptions.{AssertionException, BadRequestException} @@ -7,16 +7,14 @@ import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import scala.util.matching.Regex -//trait ValueObject[T, K] { -// val stringFormatter = StringFormatter.getGeneralInstance -// def create(value: K): Either[Throwable, T] -//} +// TODO: this is so far shared value object file, consider to slice it + +/** User value objects */ /** - * Username value object. + * User Username value object. */ sealed abstract case class Username private (value: String) - object Username { /** @@ -39,14 +37,12 @@ object Username { case None => Left(BadRequestException("Invalid username")) } } - } /** - * Email value object. + * User Email value object. */ sealed abstract case class Email private (value: String) - object Email { private val EmailRegex: Regex = """^.+@.+$""".r // TODO use proper validation @@ -62,10 +58,9 @@ object Email { } /** - * Password value object. + * User Password value object. */ sealed abstract case class Password private (value: String) - object Password { private val PasswordRegex: Regex = """^[\s\S]*$""".r //TODO: add password validation @@ -81,10 +76,9 @@ object Password { } /** - * GivenName value object. + * User GivenName value object. */ sealed abstract case class GivenName private (value: String) - object GivenName { // TODO use proper validation for value def create(value: String): Either[Throwable, GivenName] = @@ -96,10 +90,9 @@ object GivenName { } /** - * FamilyName value object. + * User FamilyName value object. */ sealed abstract case class FamilyName private (value: String) - object FamilyName { // TODO use proper validation for value def create(value: String): Either[Throwable, FamilyName] = @@ -111,10 +104,9 @@ object FamilyName { } /** - * LanguageCode value object. + * User LanguageCode value object. */ sealed abstract case class LanguageCode private (value: String) - object LanguageCode { def create(value: String): Either[Throwable, LanguageCode] = if (value.isEmpty) { @@ -127,30 +119,20 @@ object LanguageCode { } /** - * Status value object. - */ -sealed abstract case class Status private (value: Boolean) - -object Status { - def create(value: Boolean): Either[Throwable, Status] = - Right(new Status(value) {}) -} - -/** - * SystemAdmin value object. + * User SystemAdmin value object. */ sealed abstract case class SystemAdmin private (value: Boolean) - object SystemAdmin { def create(value: Boolean): Either[Throwable, SystemAdmin] = Right(new SystemAdmin(value) {}) } +/** Project value objects */ + /** - * Project shortcode value object. + * Project Shortcode value object. */ sealed abstract case class Shortcode private (value: String) - object Shortcode { val stringFormatter = StringFormatter.getGeneralInstance @@ -164,10 +146,9 @@ object Shortcode { } /** - * Project shortname value object. + * Project Shortname value object. */ sealed abstract case class Shortname private (value: String) - object Shortname { val stringFormatter = StringFormatter.getGeneralInstance @@ -181,10 +162,9 @@ object Shortname { } /** - * Project longname value object. + * Project Longname value object. */ sealed abstract case class Longname private (value: String) - object Longname { def create(value: String): Either[Throwable, Longname] = if (value.isEmpty) { @@ -195,24 +175,9 @@ object Longname { } /** - * Project description value object. - */ -sealed abstract case class Description private (value: Seq[StringLiteralV2]) - -object Description { - def create(value: Seq[StringLiteralV2]): Either[Throwable, Description] = - if (value.isEmpty) { - Left(BadRequestException("Missing description")) - } else { - Right(new Description(value) {}) - } -} - -/** - * Project keywords value object. + * Project Keywords value object. */ sealed abstract case class Keywords private (value: Seq[String]) - object Keywords { def create(value: Seq[String]): Either[Throwable, Keywords] = if (value.isEmpty) { @@ -223,10 +188,9 @@ object Keywords { } /** - * Project logo value object. + * Project Logo value object. */ sealed abstract case class Logo private (value: String) - object Logo { def create(value: String): Either[Throwable, Logo] = if (value.isEmpty) { @@ -236,12 +200,50 @@ object Logo { } } +/** Groups value objects */ + /** - * selfjoin value object. + * Group Name value object. */ -sealed abstract case class Selfjoin private (value: Boolean) +sealed abstract case class Name private (value: String) +object Name { + def create(value: String): Either[Throwable, Name] = + if (value.isEmpty) { + Left(BadRequestException("Missing Name")) + } else { + Right(new Name(value) {}) + } +} +/** Shared value objects */ + +/** + * Selfjoin value object. + */ +sealed abstract case class Selfjoin private (value: Boolean) object Selfjoin { def create(value: Boolean): Either[Throwable, Selfjoin] = Right(new Selfjoin(value) {}) } + +/** + * Status value object. + */ +sealed abstract case class Status private (value: Boolean) +object Status { + def create(value: Boolean): Either[Throwable, Status] = + Right(new Status(value) {}) +} + +/** + * Description value object. + */ +sealed abstract case class Description private (value: Seq[StringLiteralV2]) +object Description { + def create(value: Seq[StringLiteralV2]): Either[Throwable, Description] = + if (value.isEmpty) { + Left(BadRequestException("Missing description")) + } else { + Right(new Description(value) {}) + } +} diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala index cb417383af..2ca15f7e95 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala @@ -151,14 +151,16 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond .head .asInstanceOf[StringLiteralV2] .value, - description = propsMap + descriptions = propsMap .getOrElse( - OntologyConstants.KnoraAdmin.GroupDescription.toSmartIri, - throw InconsistentRepositoryDataException(s"Group $groupIri has no description attached") + OntologyConstants.KnoraAdmin.GroupDescriptions.toSmartIri, + throw InconsistentRepositoryDataException(s"Group $groupIri has no descriptions attached") ) - .head - .asInstanceOf[StringLiteralV2] - .value, + .map(l => + l.asStringLiteral( + throw InconsistentRepositoryDataException(s"Expected StringLiteralV2 but got ${l.getClass}") + ) + ), project = projectADM, status = propsMap .getOrElse( @@ -339,7 +341,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond org.knora.webapi.messages.twirl.queries.sparql.v1.txt .getGroupMembersByIri( triplestore = settings.triplestoreType, - groupIri = groupIri + groupIri ) .toString() ) @@ -415,7 +417,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond * @return a [[GroupOperationResponseADM]] */ private def createGroupADM( - createRequest: CreateGroupApiRequestADM, + createRequest: GroupCreatePayloadADM, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -424,13 +426,13 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond log.debug("createGroupADM - createRequest: {}", createRequest) def createGroupTask( - createRequest: CreateGroupApiRequestADM, + createRequest: GroupCreatePayloadADM, requestingUser: UserADM, apiRequestID: UUID ): Future[GroupOperationResponseADM] = for { /* check if username or password are not empty */ - _ <- Future(if (createRequest.name.isEmpty) throw BadRequestException("Group name cannot be empty")) + _ <- Future(if (createRequest.name.value.isEmpty) throw BadRequestException("Group name cannot be empty")) _ = if (createRequest.project.isEmpty) throw BadRequestException("Project IRI cannot be empty") /* check if the requesting user is allowed to create group */ @@ -441,9 +443,9 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond throw ForbiddenException("A new group can only be created by a project or system admin.") } - nameExists <- groupByNameAndProjectExists(name = createRequest.name, projectIri = createRequest.project) + nameExists <- groupByNameAndProjectExists(name = createRequest.name.value, projectIri = createRequest.project) _ = if (nameExists) { - throw DuplicateValueException(s"Group with the name '${createRequest.name}' already exists") + throw DuplicateValueException(s"Group with the name '${createRequest.name.value}' already exists") } maybeProjectADM: Option[ProjectADM] <- (responderManager ? ProjectGetADM( @@ -472,21 +474,20 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond .createNewGroup( adminNamedGraphIri = OntologyConstants.NamedGraphs.AdminNamedGraph, triplestore = settings.triplestoreType, - groupIri = groupIri, + groupIri, groupClassIri = OntologyConstants.KnoraAdmin.UserGroup, - name = createRequest.name, - maybeDescription = createRequest.description, + name = createRequest.name.value, + descriptions = createRequest.descriptions.value, projectIri = createRequest.project, - status = createRequest.status, - hasSelfJoinEnabled = createRequest.selfjoin + status = createRequest.status.value, + hasSelfJoinEnabled = createRequest.selfjoin.value ) .toString - //_ = log.debug(s"createGroupV1 - createNewGroup: $createNewGroupSparqlString") - createGroupResponse <- (storeManager ? SparqlUpdateRequest(createNewGroupSparqlString)) + + _ <- (storeManager ? SparqlUpdateRequest(createNewGroupSparqlString)) .mapTo[SparqlUpdateResponse] - /* Verify that the group was created */ - /* Verify that the project was updated. */ + /* Verify that the group was created and updated */ maybeCreatedGroup <- groupGetADM( groupIri = groupIri, featureFactoryConfig = featureFactoryConfig, @@ -564,7 +565,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond /* create the update request */ groupUpdatePayload = GroupUpdatePayloadADM( name = changeGroupRequest.name, - description = changeGroupRequest.description, + descriptions = changeGroupRequest.descriptions, status = changeGroupRequest.status, selfjoin = changeGroupRequest.selfjoin ) @@ -694,7 +695,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond val parametersCount: Int = List( groupUpdatePayload.name, - groupUpdatePayload.description, + groupUpdatePayload.descriptions, groupUpdatePayload.status, groupUpdatePayload.selfjoin ).flatten.size @@ -728,14 +729,14 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond } /* Update group */ - updateProjectSparqlString <- Future( + updateGroupSparqlString <- Future( org.knora.webapi.messages.twirl.queries.sparql.admin.txt .updateGroup( adminNamedGraphIri = "http://www.knora.org/data/admin", triplestore = settings.triplestoreType, - groupIri = groupIri, + groupIri, maybeName = groupUpdatePayload.name, - maybeDescription = groupUpdatePayload.description, + maybeDescriptions = groupUpdatePayload.descriptions, maybeProject = None, // maybe later we want to allow moving of a group to another project maybeStatus = groupUpdatePayload.status, maybeSelfjoin = groupUpdatePayload.selfjoin @@ -744,7 +745,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond ) //_ = log.debug(s"updateProjectV1 - query: {}",updateProjectSparqlString) - updateGroupResponse <- (storeManager ? SparqlUpdateRequest(updateProjectSparqlString)).mapTo[SparqlUpdateResponse] + _ <- (storeManager ? SparqlUpdateRequest(updateGroupSparqlString)).mapTo[SparqlUpdateResponse] /* Verify that the project was updated. */ maybeUpdatedGroup <- groupGetADM( @@ -764,10 +765,10 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond throw UpdateNotPerformedException("Group's 'name' was not updated. Please report this as a possible bug.") } - _ = if (groupUpdatePayload.description.isDefined) { - if (updatedGroup.description != groupUpdatePayload.description.get) + _ = if (groupUpdatePayload.descriptions.isDefined) { + if (updatedGroup.descriptions != groupUpdatePayload.descriptions.get) throw UpdateNotPerformedException( - "Group's 'description' was not updated. Please report this as a possible bug." + "Group's 'descriptions' was not updated. Please report this as a possible bug." ) } @@ -848,14 +849,16 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond .head .asInstanceOf[StringLiteralV2] .value, - description = propsMap + descriptions = propsMap .getOrElse( - OntologyConstants.KnoraAdmin.GroupDescription.toSmartIri, - throw InconsistentRepositoryDataException(s"Group $groupIri has no description attached") + OntologyConstants.KnoraAdmin.GroupDescriptions.toSmartIri, + throw InconsistentRepositoryDataException(s"Group $groupIri has no descriptions attached") ) - .head - .asInstanceOf[StringLiteralV2] - .value, + .map(l => + l.asStringLiteral( + throw InconsistentRepositoryDataException(s"Expected StringLiteralV2 but got ${l.getClass}") + ) + ), project = project, status = propsMap .getOrElse( @@ -889,7 +892,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond private def groupExists(groupIri: IRI): Future[Boolean] = for { askString <- Future( - org.knora.webapi.messages.twirl.queries.sparql.admin.txt.checkGroupExistsByIri(groupIri = groupIri).toString + org.knora.webapi.messages.twirl.queries.sparql.admin.txt.checkGroupExistsByIri(groupIri).toString ) //_ = log.debug("groupExists - query: {}", askString) @@ -909,7 +912,7 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond for { askString <- Future( org.knora.webapi.messages.twirl.queries.sparql.admin.txt - .checkGroupExistsByName(projectIri = projectIri, name = name) + .checkGroupExistsByName(projectIri, name) .toString ) //_ = log.debug("groupExists - query: {}", askString) @@ -961,5 +964,4 @@ class GroupsResponderADM(responderData: ResponderData) extends Responder(respond } yield GroupOperationResponseADM(group = changedGroup) } - } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala index 297616aa4b..91723f3382 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala @@ -32,7 +32,6 @@ import org.knora.webapi.instrumentation.InstrumentationSupport import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.{ - ProjectCreatePayloadADM, UserADM, UserGetADM, UserIdentifierADM, diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/UsersResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/UsersResponderADM.scala index c148660d3f..407d14898b 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/UsersResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/UsersResponderADM.scala @@ -29,7 +29,8 @@ import org.knora.webapi.messages.IriConversions._ import org.knora.webapi.messages.admin.responder.groupsmessages.{GroupADM, GroupGetADM} import org.knora.webapi.messages.admin.responder.permissionsmessages.{PermissionDataGetADM, PermissionsDataADM} import org.knora.webapi.messages.admin.responder.projectsmessages.{ProjectADM, ProjectGetADM, ProjectIdentifierADM} -import org.knora.webapi.messages.admin.responder.usersmessages.{Password, UserChangeRequestADM, _} +import org.knora.webapi.messages.admin.responder.usersmessages.{UserChangeRequestADM, _} +import org.knora.webapi.messages.admin.responder.valueObjects.{Username, Email, Password, Status, SystemAdmin} import org.knora.webapi.messages.store.cacheservicemessages.{ CacheServiceGetUserADM, CacheServicePutUserADM, @@ -38,7 +39,6 @@ import org.knora.webapi.messages.store.cacheservicemessages.{ import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.rdf.SparqlSelectResult import org.knora.webapi.messages.util.{KnoraSystemInstances, ResponderData} -import org.knora.webapi.messages.v1.responder.usermessages._ import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala index b182c41c1a..038a117211 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/GroupsRouteADM.scala @@ -20,14 +20,15 @@ package org.knora.webapi.routing.admin import java.util.UUID - import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{PathMatcher, Route} import io.swagger.annotations._ + import javax.ws.rs.Path import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.admin.responder.groupsmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{Description, Name, Selfjoin, Status} import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} object GroupsRouteADM { @@ -91,13 +92,24 @@ class GroupsRouteADM(routeData: KnoraRouteData) post { /* create a new group */ entity(as[CreateGroupApiRequestADM]) { apiRequest => requestContext => + val groupCreatePayloadADM: GroupCreatePayloadADM = GroupCreatePayloadADM.create( + id = stringFormatter + .validateAndEscapeOptionalIri(apiRequest.id, throw BadRequestException(s"Invalid group IRI")), + name = Name.create(apiRequest.name).fold(e => throw e, v => v), + descriptions = Description.create(apiRequest.descriptions).fold(e => throw e, v => v), + project = stringFormatter + .validateAndEscapeProjectIri(apiRequest.project, throw BadRequestException(s"Invalid project IRI")), + status = Status.create(apiRequest.status).fold(e => throw e, v => v), + selfjoin = Selfjoin.create(apiRequest.selfjoin).fold(e => throw e, v => v) + ) + val requestMessage = for { requestingUser <- getUserADM( requestContext = requestContext, featureFactoryConfig = featureFactoryConfig ) } yield GroupCreateRequestADM( - createRequest = apiRequest, + createRequest = groupCreatePayloadADM, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteADM.scala index 3c2bf242ac..3f1c77390f 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ProjectsRouteADM.scala @@ -31,26 +31,23 @@ import akka.stream.IOResult import akka.stream.scaladsl.{FileIO, Source} import akka.util.ByteString import io.swagger.annotations._ - import javax.ws.rs.Path import org.knora.webapi.IRI import org.knora.webapi.annotation.ApiMayChange import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.admin.responder.projectsmessages._ -import org.knora.webapi.messages.admin.responder.usersmessages.{ +import org.knora.webapi.messages.admin.responder.valueObjects.{ Description, Keywords, Logo, Longname, - ProjectCreatePayloadADM, Selfjoin, Shortcode, Shortname, Status } import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} - import scala.concurrent.Future import scala.util.Try @@ -165,7 +162,7 @@ class ProjectsRouteADM(routeData: KnoraRouteData) val projectCreatePayload: ProjectCreatePayloadADM = ProjectCreatePayloadADM.create( id = stringFormatter - .validateAndEscapeOptionalProjectIri(apiRequest.id, throw BadRequestException(s"Invalid user IRI")), + .validateAndEscapeOptionalProjectIri(apiRequest.id, throw BadRequestException(s"Invalid project IRI")), shortname = Shortname.create(apiRequest.shortname).fold(error => throw error, value => value), shortcode = Shortcode.create(apiRequest.shortcode).fold(error => throw error, value => value), longname = maybeLongname, diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/UsersRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/UsersRouteADM.scala index d72e4411f3..cbaba332bb 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/UsersRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/UsersRouteADM.scala @@ -27,6 +27,16 @@ import org.knora.webapi.exceptions.{BadRequestException} import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol._ import org.knora.webapi.messages.admin.responder.usersmessages.{UserUpdatePasswordPayloadADM, _} +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Username, + Email, + GivenName, + FamilyName, + Password, + Status, + LanguageCode, + SystemAdmin +} import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala index 88954de1a0..086b4ef97b 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/NewListsRouteADMFeature.scala @@ -96,7 +96,7 @@ class NewListsRouteADMFeature(routeData: KnoraRouteData) /* return all lists */ parameters("projectIri".?) { maybeProjectIri: Option[IRI] => requestContext => val projectIri = - stringFormatter.toOptionalIri( + stringFormatter.validateAndEscapeOptionalIri( maybeProjectIri, throw BadRequestException(s"Invalid param project IRI: $maybeProjectIri") ) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala index 6d47540623..a670d70953 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/lists/OldListsRouteADMFeature.scala @@ -74,7 +74,7 @@ class OldListsRouteADMFeature(routeData: KnoraRouteData) /* return all lists */ parameters("projectIri".?) { maybeProjectIri: Option[IRI] => requestContext => val projectIri = - stringFormatter.toOptionalIri( + stringFormatter.validateAndEscapeOptionalIri( maybeProjectIri, throw BadRequestException(s"Invalid param project IRI: $maybeProjectIri") ) diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewGroup.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewGroup.scala.txt index 5f523135b6..e7ad8a7a0c 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewGroup.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/createNewGroup.scala.txt @@ -18,6 +18,7 @@ *@ @import org.knora.webapi.IRI +@import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 @* * Creates a new group. @@ -28,7 +29,7 @@ * @param groupIri the Iri of the new group * @param groupClassIri the IRI of the OWL class that the new group should belong to. * @param name the new group's name. - * @param description the new group's description. + * @param descriptions the new group's descriptions. * @param projectIri the new group's project association. * @param isActiveGroup the new group's status. * @param hasSelfJoinEnabled the new group's self-join status. @@ -38,7 +39,7 @@ groupIri: IRI, groupClassIri: IRI, name: String, - maybeDescription: Option[String], + descriptions: Seq[StringLiteralV2], projectIri: IRI, status: Boolean, hasSelfJoinEnabled: Boolean) @@ -52,19 +53,25 @@ PREFIX foaf: INSERT { GRAPH ?adminNamedGraphIri { - ?groupIri rdf:type ?groupClassIri ; + ?groupIri rdf:type ?groupClassIri . - knora-admin:groupName "@name"^^xsd:string ; + ?groupIri knora-admin:groupName "@name"^^xsd:string . - @if(maybeDescription.nonEmpty) { - knora-admin:groupDescription """@maybeDescription.get"""^^xsd:string ; + @if(descriptions.nonEmpty) { + @for(d <- descriptions) { + @if(d.language.nonEmpty) { + ?groupIri knora-admin:groupDescriptions """@d.value"""@@@{d.language.get} . + } else { + ?groupIri knora-admin:groupDescriptions """@d.value"""^^xsd:string . + } + } } - knora-admin:belongsToProject ?projectIri ; + ?groupIri knora-admin:belongsToProject ?projectIri . - knora-admin:status "@status"^^xsd:boolean ; + ?groupIri knora-admin:status "@status"^^xsd:boolean . - knora-admin:hasSelfJoinEnabled "@hasSelfJoinEnabled"^^xsd:boolean. + ?groupIri knora-admin:hasSelfJoinEnabled "@hasSelfJoinEnabled"^^xsd:boolean . } } @* diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateGroup.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateGroup.scala.txt index 2fed1fb5d2..0d3b48547f 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateGroup.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateGroup.scala.txt @@ -18,25 +18,26 @@ *@ @import org.knora.webapi.IRI +@import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 @** * Updates an existing group with the provided values. * - * @param dataNamedGraph the named graph to update. - * @param triplestore the name of the triplestore being used. The template uses this value to exclude inferred - results from the WHERE clause of the update. - * @param groupIri the IRI of the group we want to update. - * @param maybeName the new optional value for name. - * @param maybeDescription the new optional value for description. - * @param maybeProject the new optional value for project. - * @param maybeStatus the new optional value for status. - * @param maybeSelfjoin the new optional value for selfjoin. + * @param dataNamedGraph the named graph to update. + * @param triplestore the name of the triplestore being used. The template uses this value to exclude inferred + results from the WHERE clause of the update. + * @param groupIri the IRI of the group we want to update. + * @param maybeName the new optional value for name. + * @param maybeDescriptions the new optional value for descriptions. + * @param maybeProject the new optional value for project. + * @param maybeStatus the new optional value for status. + * @param maybeSelfjoin the new optional value for selfjoin. *@ @(adminNamedGraphIri: IRI, triplestore: String, groupIri: IRI, maybeName: Option[String], - maybeDescription: Option[String], + maybeDescriptions: Option[Seq[StringLiteralV2]], maybeProject: Option[IRI], maybeStatus: Option[Boolean], maybeSelfjoin: Option[Boolean]) @@ -55,8 +56,8 @@ DELETE { ?group knora-admin:groupName ?currentName . } - @if(maybeDescription.nonEmpty) { - ?group knora-admin:groupDescription ?currentDescription . + @if(maybeDescriptions.nonEmpty) { + ?group knora-admin:groupDescriptions ?currentDescriptions . } @if(maybeProject.nonEmpty) { @@ -81,8 +82,14 @@ DELETE { ?group knora-admin:groupName "@maybeName.get"^^xsd:string . } - @if(maybeDescription.nonEmpty) { - ?group knora-admin:groupDescription """@maybeDescription.get"""^^xsd:string . + @if(maybeDescriptions.nonEmpty) { + @for(d <- maybeDescriptions.get) { + @if(d.language.nonEmpty) { + ?group knora-admin:groupDescriptions """@d.value"""@@@{d.language.get} . + } else { + ?group knora-admin:groupDescriptions """@d.value"""^^xsd:string . + } + } } @if(maybeProject.nonEmpty) { @@ -121,7 +128,7 @@ WHERE { ?group knora-admin:groupName ?currentName . - optional {?group knora-admin:groupDescription ?currentDescription .} + optional {?group knora-admin:groupDescriptions ?currentDescriptions .} ?group knora-admin:belongsToProject ?currentProject . diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala index 625c4ea187..8f1f612aa3 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala @@ -28,6 +28,7 @@ import com.typesafe.config.{Config, ConfigFactory} import org.knora.webapi.E2ESpec import org.knora.webapi.e2e.{ClientTestDataCollector, TestDataFileContent, TestDataFilePath} import org.knora.webapi.messages.admin.responder.groupsmessages.{GroupADM, GroupsADMJsonProtocol} +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.v1.responder.sessionmessages.SessionJsonProtocol import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.util.{AkkaHttpUtils, MutableTestIri} @@ -107,7 +108,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val createGroupWithCustomIriRequest: String = s"""{ "id": "$customGroupIri", | "name": "NewGroupWithCustomIri", - | "description": "A new group with a custom Iri", + | "descriptions": [{"value": "A new group with a custom Iri", "language": "en"}], | "project": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", | "status": true, | "selfjoin": false @@ -152,7 +153,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val params = s"""{ "id": "$customGroupIri", | "name": "NewGroupWithDuplicateCustomIri", - | "description": "A new group with a duplicate custom Iri", + | "descriptions": [{"value": "A new group with a duplicate custom Iri", "language": "en"}], | "project": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", | "status": true, | "selfjoin": false @@ -180,7 +181,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val createGroupRequest: String = s"""{ | "name": "NewGroup", - | "description": "NewGroupDescription", + | "descriptions": [{"value": "NewGroupDescription", "language": "en"}], | "project": "${SharedTestDataADM.IMAGES_PROJECT_IRI}", | "status": true, | "selfjoin": false @@ -208,7 +209,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] groupInfo.name should be("NewGroup") - groupInfo.description should be("NewGroupDescription") + groupInfo.descriptions should be(Seq(StringLiteralV2("NewGroupDescription", Some("en")))) groupInfo.project should be(SharedTestDataADM.imagesProject) groupInfo.status should be(true) groupInfo.selfjoin should be(false) @@ -234,7 +235,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val updateGroupRequest: String = s"""{ | "name": "UpdatedGroupName", - | "description": "UpdatedGroupDescription" + | "descriptions": [{"value": "UpdatedGroupDescription", "language": "en"}] |}""".stripMargin clientTestDataCollector.addFile( @@ -259,7 +260,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] groupInfo.name should be("UpdatedGroupName") - groupInfo.description should be("UpdatedGroupDescription") + groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) groupInfo.project should be(SharedTestDataADM.imagesProject) groupInfo.status should be(true) groupInfo.selfjoin should be(false) @@ -289,7 +290,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] groupInfo.name should be("UpdatedGroupName") - groupInfo.description should be("UpdatedGroupDescription") + groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) groupInfo.project should be(SharedTestDataADM.imagesProject) groupInfo.status should be(false) groupInfo.selfjoin should be(false) @@ -337,7 +338,7 @@ class GroupsADME2ESpec extends E2ESpec(GroupsADME2ESpec.config) with GroupsADMJs val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] groupInfo.name should be("UpdatedGroupName") - groupInfo.description should be("UpdatedGroupDescription") + groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) groupInfo.project should be(SharedTestDataADM.imagesProject) groupInfo.status should be(true) groupInfo.selfjoin should be(false) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADMSpec.scala index b13cf667d0..80370d8ca4 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADMSpec.scala @@ -22,6 +22,7 @@ package org.knora.webapi.messages.admin.responder.groupsmessages import com.typesafe.config.ConfigFactory import org.knora.webapi.CoreSpec import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.sharedtestdata.SharedTestDataADM object GroupsMessagesADMSpec { @@ -44,7 +45,7 @@ class GroupsMessagesADMSpec extends CoreSpec(GroupsMessagesADMSpec.config) { CreateGroupApiRequestADM( id = Some("invalid-group-IRI"), name = "NewGroupWithInvalidCustomIri", - description = Some("A new group with an invalid custom Iri"), + descriptions = Seq(StringLiteralV2("A new group created with an invalid custom IRI")), project = SharedTestDataADM.IMAGES_PROJECT_IRI, status = true, selfjoin = false diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADMSpec.scala index 8a5595b59b..77b082cc02 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADMSpec.scala @@ -22,7 +22,7 @@ package org.knora.webapi.messages.admin.responder.valueObjects import com.typesafe.config.{Config, ConfigFactory} import org.knora.webapi.exceptions.BadRequestException import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.usersmessages._ +import org.knora.webapi.messages.admin.responder.usersmessages.{CreateUserApiRequestADM, UserCreatePayloadADM} import org.knora.webapi.{IRI, UnitSpec} import org.scalatest.enablers.Messaging.messagingNatureOfThrowable diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala index cb14ec4656..89e4a6500e 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala @@ -24,7 +24,6 @@ package org.knora.webapi.responders.admin import java.util.UUID - import akka.actor.Status.Failure import akka.testkit.ImplicitSender import com.typesafe.config.{Config, ConfigFactory} @@ -32,6 +31,8 @@ import org.knora.webapi._ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException, NotFoundException} import org.knora.webapi.messages.admin.responder.groupsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserInformationTypeADM +import org.knora.webapi.messages.admin.responder.valueObjects.{Description, Name, Selfjoin, Status} +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.util.MutableTestIri @@ -67,7 +68,6 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit ) val response = expectMsgType[GroupsGetResponseADM](timeout) - // println(response.users) response.groups.nonEmpty should be(true) response.groups.size should be(2) } @@ -102,12 +102,19 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit "CREATE the group and return the group's info if the supplied group name is unique" in { responderManager ! GroupCreateRequestADM( - createRequest = CreateGroupApiRequestADM( - name = "NewGroup", - description = Some("""NewGroupDescription with "quotes" and """), + createRequest = GroupCreatePayloadADM.create( + id = None, + name = Name.create("NewGroup").fold(e => throw e, v => v), + descriptions = Description + .create( + Seq( + StringLiteralV2(value = """NewGroupDescription with "quotes" and """, language = Some("en")) + ) + ) + .fold(e => throw e, v => v), project = SharedTestDataADM.IMAGES_PROJECT_IRI, - status = true, - selfjoin = false + status = Status.create(true).fold(e => throw e, v => v), + selfjoin = Selfjoin.create(false).fold(e => throw e, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -118,7 +125,9 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit val newGroupInfo = received.group newGroupInfo.name should equal("NewGroup") - newGroupInfo.description should equal("""NewGroupDescription with "quotes" and """) + newGroupInfo.descriptions should equal( + Seq(StringLiteralV2("""NewGroupDescription with "quotes" and """, Some("en"))) + ) newGroupInfo.project should equal(imagesProject) newGroupInfo.status should equal(true) newGroupInfo.selfjoin should equal(false) @@ -129,12 +138,15 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit "return a 'DuplicateValueException' if the supplied group name is not unique" in { responderManager ! GroupCreateRequestADM( - createRequest = CreateGroupApiRequestADM( - name = "NewGroup", - description = Some("NewGroupDescription"), + createRequest = GroupCreatePayloadADM.create( + id = Some(imagesReviewerGroup.id), + name = Name.create("NewGroup").fold(e => throw e, v => v), + descriptions = Description + .create(Seq(StringLiteralV2(value = "NewGroupDescription", language = Some("en")))) + .fold(e => throw e, v => v), project = SharedTestDataADM.IMAGES_PROJECT_IRI, - status = true, - selfjoin = false + status = Status.create(true).fold(e => throw e, v => v), + selfjoin = Selfjoin.create(false).fold(e => throw e, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -146,31 +158,17 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit } } - "return 'BadRequestException' if group name or project IRI are missing" in { - - /* missing group name */ + "return 'BadRequestException' if project IRI are missing" in { responderManager ! GroupCreateRequestADM( - createRequest = CreateGroupApiRequestADM( - name = "", - description = Some("NoNameGroupDescription"), - project = SharedTestDataADM.IMAGES_PROJECT_IRI, - status = true, - selfjoin = false - ), - featureFactoryConfig = defaultFeatureFactoryConfig, - requestingUser = SharedTestDataADM.imagesUser01, - apiRequestID = UUID.randomUUID - ) - expectMsg(Failure(BadRequestException("Group name cannot be empty"))) - - /* missing project */ - responderManager ! GroupCreateRequestADM( - createRequest = CreateGroupApiRequestADM( - name = "OtherNewGroup", - description = Some("OtherNewGroupDescription"), + createRequest = GroupCreatePayloadADM.create( + id = Some(""), + name = Name.create("OtherNewGroup").fold(e => throw e, v => v), + descriptions = Description + .create(Seq(StringLiteralV2(value = "OtherNewGroupDescription", language = Some("en")))) + .fold(e => throw e, v => v), project = "", - status = true, - selfjoin = false + status = Status.create(true).fold(e => throw e, v => v), + selfjoin = Selfjoin.create(false).fold(e => throw e, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -184,7 +182,9 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit groupIri = newGroupIri.get, changeGroupRequest = ChangeGroupApiRequestADM( Some("UpdatedGroupName"), - Some("""UpdatedDescription with "quotes" and """) + Some( + Seq(StringLiteralV2(value = """UpdatedDescription with "quotes" and """, Some("en"))) + ) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, @@ -195,7 +195,9 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit val updatedGroupInfo = received.group updatedGroupInfo.name should equal("UpdatedGroupName") - updatedGroupInfo.description should equal("""UpdatedDescription with "quotes" and """) + updatedGroupInfo.descriptions should equal( + Seq(StringLiteralV2("""UpdatedDescription with "quotes" and """, Some("en"))) + ) updatedGroupInfo.project should equal(imagesProject) updatedGroupInfo.status should equal(true) updatedGroupInfo.selfjoin should equal(false) @@ -204,7 +206,10 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit "return 'NotFound' if a not-existing group IRI is submitted during update" in { responderManager ! GroupChangeRequestADM( groupIri = "http://rdfh.ch/groups/notexisting", - ChangeGroupApiRequestADM(Some("UpdatedGroupName"), Some("UpdatedDescription")), + ChangeGroupApiRequestADM( + Some("UpdatedGroupName"), + Some(Seq(StringLiteralV2(value = "UpdatedDescription", language = Some("en")))) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -218,7 +223,10 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit "return 'BadRequest' if the new group name already exists inside the project" in { responderManager ! GroupChangeRequestADM( groupIri = newGroupIri.get, - changeGroupRequest = ChangeGroupApiRequestADM(Some("Image reviewer"), Some("UpdatedDescription")), + changeGroupRequest = ChangeGroupApiRequestADM( + Some("Image reviewer"), + Some(Seq(StringLiteralV2(value = "UpdatedDescription", language = Some("en")))) + ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID @@ -232,7 +240,6 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit "return 'BadRequest' if nothing would be changed during the update" in { an[BadRequestException] should be thrownBy ChangeGroupApiRequestADM(None, None, None, None) } - } "used to query members" should { @@ -293,9 +300,7 @@ class GroupsResponderADMSpec extends CoreSpec(GroupsResponderADMSpec.config) wit expectMsgPF(timeout) { case msg: akka.actor.Status.Failure => msg.cause.isInstanceOf[NotFoundException] should ===(true) } - } } } - } diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala index 8f4d615b3b..fee570ed18 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ProjectsResponderADMSpec.scala @@ -33,28 +33,24 @@ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException import org.knora.webapi.messages.{OntologyConstants, StringFormatter} import org.knora.webapi.messages.admin.responder.permissionsmessages.{ AdministrativePermissionADM, - AdministrativePermissionGetResponseADM, AdministrativePermissionsForProjectGetRequestADM, AdministrativePermissionsForProjectGetResponseADM, DefaultObjectAccessPermissionADM, - DefaultObjectAccessPermissionGetResponseADM, DefaultObjectAccessPermissionsForProjectGetRequestADM, DefaultObjectAccessPermissionsForProjectGetResponseADM, - PermissionADM, - PermissionByIriGetRequestADM + PermissionADM } import org.knora.webapi.messages.admin.responder.projectsmessages._ -import org.knora.webapi.messages.admin.responder.usersmessages.{ +import org.knora.webapi.messages.admin.responder.usersmessages.UserInformationTypeADM +import org.knora.webapi.messages.admin.responder.valueObjects.{ Description, Keywords, Logo, Longname, - ProjectCreatePayloadADM, Selfjoin, Shortcode, Shortname, - Status, - UserInformationTypeADM + Status } import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.sharedtestdata.SharedTestDataADM diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/UsersResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/UsersResponderADMSpec.scala index bc02448b98..5095f75ec7 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/UsersResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/UsersResponderADMSpec.scala @@ -28,7 +28,17 @@ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException import org.knora.webapi.messages.StringFormatter import org.knora.webapi.messages.admin.responder.groupsmessages.{GroupMembersGetRequestADM, GroupMembersGetResponseADM} import org.knora.webapi.messages.admin.responder.projectsmessages._ -import org.knora.webapi.messages.admin.responder.usersmessages.{UserChangeRequestADM, _} +import org.knora.webapi.messages.admin.responder.usersmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects.{ + Username, + Email, + GivenName, + FamilyName, + Password, + Status, + LanguageCode, + SystemAdmin +} import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredentialsV2.KnoraPasswordCredentialsV2 import org.knora.webapi.routing.Authenticator @@ -37,7 +47,6 @@ import org.knora.webapi.sharedtestdata.SharedTestDataADM import scala.concurrent.duration._ object UsersResponderADMSpec { - val config: Config = ConfigFactory.parseString(""" akka.loglevel = "DEBUG" akka.stdout-loglevel = "DEBUG" diff --git a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 194152744d..43d420e21e 100644 --- a/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/webapi/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -327,7 +327,7 @@ object SharedTestDataADM { def imagesProjectAdminGroup: GroupADM = GroupADM( id = "-", name = "ProjectAdmin", - description = "Default Project Admin Group", + descriptions = Seq(StringLiteralV2(value = "Default Project Admin Group", language = Some("en"))), project = imagesProject, status = true, selfjoin = false @@ -337,7 +337,7 @@ object SharedTestDataADM { def imagesProjectMemberGroup: GroupADM = GroupADM( id = "-", name = "ProjectMember", - description = "Default Project Member Group", + descriptions = Seq(StringLiteralV2(value = "Default Project Member Group", language = Some("en"))), project = imagesProject, status = true, selfjoin = false @@ -347,7 +347,7 @@ object SharedTestDataADM { def imagesReviewerGroup: GroupADM = GroupADM( id = "http://rdfh.ch/groups/00FF/images-reviewer", name = "Image reviewer", - description = "A group for image reviewers.", + descriptions = Seq(StringLiteralV2(value = "A group for image reviewers.", language = None)), project = imagesProject, status = true, selfjoin = false @@ -604,7 +604,7 @@ object SharedTestDataADM { def thingSearcherGroup: GroupADM = GroupADM( id = "http://rdfh.ch/groups/0001/thing-searcher", name = "Thing searcher", - description = "A group for thing searchers.", + descriptions = Seq(StringLiteralV2(value = "A group for thing searchers.", language = Some("en"))), project = anythingProject, status = true, selfjoin = true