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 index bdb09a125e..c4ff7ed496 100644 --- 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 @@ -1,3 +1,8 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + package org.knora.webapi.messages.admin.responder.groupsmessages import org.knora.webapi.messages.admin.responder.valueObjects._ diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala index 42fec09558..8c0c755837 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsErrorMessagesADM.scala @@ -10,9 +10,6 @@ object ListsErrorMessagesADM { val LIST_IRI_INVALID_ERROR = "List IRI cannot be empty." val LIST_NODE_IRI_MISSING_ERROR = "List node IRI cannot be empty." val LIST_NODE_IRI_INVALID_ERROR = "List node IRI is invalid." -// TODO-mpro: move project messages - val PROJECT_IRI_MISSING_ERROR = "Project IRI cannot be empty." - val PROJECT_IRI_INVALID_ERROR = "Project IRI is invalid." val LIST_NAME_MISSING_ERROR = "List name cannot be empty." val LIST_NAME_INVALID_ERROR = "List name is invalid." val LABEL_MISSING_ERROR = "At least one label needs to be supplied." diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsPayloadsADM.scala similarity index 91% rename from webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala rename to webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsPayloadsADM.scala index fe6b83def0..d8b3ec8335 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListPayloadsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsPayloadsADM.scala @@ -1,3 +1,8 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + package org.knora.webapi.messages.admin.responder.listsmessages import org.knora.webapi.messages.admin.responder.valueObjects._ diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectCreatePayloadADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectCreatePayloadADM.scala deleted file mode 100644 index ad797c6b31..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectCreatePayloadADM.scala +++ /dev/null @@ -1,28 +0,0 @@ -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 -} - -/** - * Project payload - */ -final case class ProjectCreatePayloadADM( - id: Option[IRI] = None, - shortname: Shortname, - shortcode: Shortcode, - longname: Option[Longname], - description: Description, - keywords: Keywords, - logo: Option[Logo], - status: Status, - selfjoin: Selfjoin -) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsErrorMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsErrorMessagesADM.scala new file mode 100644 index 0000000000..01242d7cd1 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsErrorMessagesADM.scala @@ -0,0 +1,23 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.projectsmessages + +object ProjectsErrorMessagesADM { + val PROJECT_IRI_MISSING_ERROR = "Project IRI cannot be empty." + val PROJECT_IRI_INVALID_ERROR = "Project IRI is invalid." + val SHORTCODE_MISSING_ERROR = "Shortcode cannot be empty." + val SHORTCODE_INVALID_ERROR = "Shortcode is invalid." + val SHORTNAME_MISSING_ERROR = "Shortname cannot be empty." + val SHORTNAME_INVALID_ERROR = "Shortname is invalid." + val LONGNAME_MISSING_ERROR = "Longname cannot be empty." + val LONGNAME_INVALID_ERROR = "Longname is invalid." + val PROJECT_DESCRIPTION_MISSING_ERROR = "Description cannot be empty." + val PROJECT_DESCRIPTION_INVALID_ERROR = "Description is invalid." + val KEYWORDS_MISSING_ERROR = "Keywords cannot be empty." + val KEYWORDS_INVALID_ERROR = "Keywords are invalid." + val LOGO_MISSING_ERROR = "Logo cannot be empty." + val LOGO_INVALID_ERROR = "Logo is invalid." +} 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 954308b39d..cad922d8e2 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 @@ -5,8 +5,6 @@ package org.knora.webapi.messages.admin.responder.projectsmessages -import java.nio.file.Path -import java.util.UUID import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import org.apache.commons.lang3.builder.HashCodeBuilder import org.knora.webapi.IRI @@ -20,6 +18,9 @@ import org.knora.webapi.messages.store.triplestoremessages.{StringLiteralV2, Tri import org.knora.webapi.messages.v1.responder.projectmessages.ProjectInfoV1 import spray.json.{DefaultJsonProtocol, JsValue, JsonFormat, RootJsonFormat} +import java.nio.file.Path +import java.util.UUID + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // API requests @@ -47,67 +48,8 @@ case class CreateProjectApiRequestADM( status: Boolean, selfjoin: Boolean ) extends ProjectsADMJsonProtocol { - implicit protected val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance - - // Check that collection parameters are not empty. - if (description.isEmpty) throw BadRequestException("Project description needs to be supplied.") - if (keywords.isEmpty) throw BadRequestException("At least one keyword must be supplied for a new project.") - if (shortcode.isEmpty) throw BadRequestException("Project shortcode must be supplied.") - if (shortname.isEmpty) throw BadRequestException("Project shortname must be supplied.") - /* Convert to Json */ def toJsValue: JsValue = createProjectApiRequestADMFormat.write(this) - - /* validates and escapes the given values.*/ - def validateAndEscape: CreateProjectApiRequestADM = { - val maybeProjectIri = - stringFormatter.validateAndEscapeOptionalProjectIri(id, throw BadRequestException(s"Invalid project IRI")) - val validatedShortcode = stringFormatter.validateAndEscapeProjectShortcode( - shortcode, - errorFun = throw BadRequestException(s"The supplied short code: '$shortcode' is not valid.") - ) - - val validatedShortname = stringFormatter.validateAndEscapeProjectShortname( - shortname, - errorFun = throw BadRequestException(s"The supplied short name: '$shortname' is not valid.") - ) - - val validatedLongName = stringFormatter.escapeOptionalString( - longname, - errorFun = throw BadRequestException(s"The supplied longname: '$longname' is not valid.") - ) - - val validatedLogo = stringFormatter.escapeOptionalString( - logo, - errorFun = throw BadRequestException(s"The supplied logo: '$logo' is not valid.") - ) - - val validatedDescriptions: Seq[StringLiteralV2] = description.map { des => - val escapedValue = - stringFormatter.toSparqlEncodedString( - des.value, - errorFun = throw BadRequestException(s"The supplied description: '${des.value}' is not valid.") - ) - StringLiteralV2(value = escapedValue, language = des.language) - } - - val validatedKeywords = keywords.map(keyword => - stringFormatter.toSparqlEncodedString( - keyword, - errorFun = throw BadRequestException(s"The supplied keyword: '$keyword' is not valid.") - ) - ) - copy( - id = maybeProjectIri, - shortcode = validatedShortcode, - shortname = validatedShortname, - longname = validatedLongName, - description = validatedDescriptions, - keywords = validatedKeywords, - logo = validatedLogo - ) - } - } /** @@ -350,7 +292,7 @@ case class ProjectDataGetRequestADM( /** * Requests the creation of a new project. * - * @param createRequest the [[ProjectCreatePayloadADM]] information for creation a new project. + * @param createRequest the [[ProjectCreatePayloadADM]] information for the creation of a new project. * @param featureFactoryConfig the feature factory configuration. * @param requestingUser the user making the request. * @param apiRequestID the ID of the API request. diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala new file mode 100644 index 0000000000..e801f16e5a --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsPayloadsADM.scala @@ -0,0 +1,23 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.projectsmessages + +import org.knora.webapi.messages.admin.responder.valueObjects._ + +/** + * Project creation payload + */ +final case class ProjectCreatePayloadADM( + id: Option[ProjectIRI] = None, + shortname: Shortname, + shortcode: Shortcode, + longname: Option[Longname] = None, + description: ProjectDescription, + keywords: Keywords, + logo: Option[Logo] = None, + status: ProjectStatus, + selfjoin: ProjectSelfJoin +) 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 deleted file mode 100644 index 0ec8a8da82..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UserPayloadsADM.scala +++ /dev/null @@ -1,61 +0,0 @@ -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 - */ -sealed abstract case class UserCreatePayloadADM private ( - id: Option[IRI], - username: Option[Username], - email: Option[Email], - givenName: Option[GivenName], - familyName: Option[FamilyName], - password: Option[Password], - status: Option[Status], - lang: Option[LanguageCode], - projects: Option[Seq[IRI]], - projectsAdmin: Option[Seq[IRI]], - groups: Option[Seq[IRI]], - systemAdmin: Option[SystemAdmin] -) - -object UserCreatePayloadADM { - - /** The create constructor needs all attributes but id which is optional */ - def create( - id: Option[IRI] = None, - username: Username, - email: Email, - givenName: GivenName, - familyName: FamilyName, - password: Password, - status: Status, - lang: LanguageCode, - systemAdmin: SystemAdmin - ): UserCreatePayloadADM = - new UserCreatePayloadADM( - id = id, - username = Some(username), - email = Some(email), - givenName = Some(givenName), - familyName = Some(familyName), - password = Some(password), - status = Some(status), - lang = Some(lang), - projects = None, - projectsAdmin = None, - groups = None, - systemAdmin = Some(systemAdmin) - ) {} -} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersErrorMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersErrorMessagesADM.scala new file mode 100644 index 0000000000..d033ecfde2 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersErrorMessagesADM.scala @@ -0,0 +1,23 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.usersmessages + +object UsersErrorMessagesADM { + val USER_IRI_MISSING_ERROR = "User IRI cannot be empty." + val USER_IRI_INVALID_ERROR = "User IRI is invalid." + val USERNAME_MISSING_ERROR = "Username cannot be empty." + val USERNAME_INVALID_ERROR = "Username is invalid." + val EMAIL_MISSING_ERROR = "Email cannot be empty." + val EMAIL_INVALID_ERROR = "Email is invalid." + val PASSWORD_MISSING_ERROR = "Password cannot be empty." + val PASSWORD_INVALID_ERROR = "Password is invalid." + val GIVEN_NAME_MISSING_ERROR = "GivenName cannot be empty." + val GIVEN_NAME_INVALID_ERROR = "GivenName is invalid." + val FAMILY_NAME_MISSING_ERROR = "FamilyName cannot be empty." + val FAMILY_NAME_INVALID_ERROR = "FamilyName is invalid." + val LANGUAGE_CODE_MISSING_ERROR = "LanguageCode cannot be empty." + val LANGUAGE_CODE_INVALID_ERROR = "LanguageCode is invalid." +} 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 b69f8d31a9..f90f308ad0 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 @@ -21,7 +21,7 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ GivenName, FamilyName, Password, - Status, + UserStatus, LanguageCode, SystemAdmin } @@ -244,7 +244,7 @@ case class UserChangePasswordRequestADM( */ case class UserChangeStatusRequestADM( userIri: IRI, - status: Status, + status: UserStatus, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -839,7 +839,7 @@ case class UserChangeRequestADM( email: Option[Email] = None, givenName: Option[GivenName] = None, familyName: Option[FamilyName] = None, - status: Option[Status] = None, + status: Option[UserStatus] = None, lang: Option[LanguageCode] = None, projects: Option[Seq[IRI]] = None, projectsAdmin: Option[Seq[IRI]] = None, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersPayloadsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersPayloadsADM.scala new file mode 100644 index 0000000000..13877370a5 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersPayloadsADM.scala @@ -0,0 +1,23 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.usersmessages + +import org.knora.webapi.messages.admin.responder.valueObjects._ + +/** + * User creation payload + */ +final case class UserCreatePayloadADM( + id: Option[UserIRI] = None, + username: Username, + email: Email, + givenName: GivenName, + familyName: FamilyName, + password: Password, + status: UserStatus, + lang: LanguageCode, + systemAdmin: SystemAdmin +) diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/GroupsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/GroupsValueObjectsADM.scala index b52b48af13..1b5eb07168 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/GroupsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/GroupsValueObjectsADM.scala @@ -16,13 +16,13 @@ import zio.prelude.Validation */ sealed abstract case class GroupIRI private (value: String) object GroupIRI { self => - private val sf = StringFormatter.getGeneralInstance + private val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: String): Validation[Throwable, GroupIRI] = if (value.isEmpty) { Validation.fail(BadRequestException(GROUP_IRI_MISSING_ERROR)) } else { - if (value.nonEmpty && !sf.isKnoraGroupIriStr(value)) { + if (!sf.isKnoraGroupIriStr(value)) { Validation.fail(BadRequestException(GROUP_IRI_INVALID_ERROR)) } else { val validatedValue = Validation( @@ -45,7 +45,7 @@ object GroupIRI { self => */ sealed abstract case class GroupName private (value: String) object GroupName { self => - private val sf = StringFormatter.getGeneralInstance + private val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: String): Validation[Throwable, GroupName] = if (value.isEmpty) { @@ -70,7 +70,7 @@ object GroupName { self => */ sealed abstract case class GroupDescriptions private (value: Seq[StringLiteralV2]) object GroupDescriptions { self => - private val sf = StringFormatter.getGeneralInstance + private val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: Seq[StringLiteralV2]): Validation[Throwable, GroupDescriptions] = if (value.isEmpty) { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADM.scala deleted file mode 100644 index f9dc7f7385..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADM.scala +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.messages.admin.responder.valueObjects - -import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM.{ - PROJECT_IRI_INVALID_ERROR, - PROJECT_IRI_MISSING_ERROR -} -import zio.prelude.Validation - -/** - * ProjectIRI value object. - */ -sealed abstract case class ProjectIRI private (value: String) -object ProjectIRI { - val sf = StringFormatter.getGeneralInstance - - def make(value: String): Validation[Throwable, ProjectIRI] = - if (value.isEmpty) { - Validation.fail(BadRequestException(PROJECT_IRI_MISSING_ERROR)) - } else { - if (value.nonEmpty && !sf.isKnoraProjectIriStr(value)) { - Validation.fail(BadRequestException(PROJECT_IRI_INVALID_ERROR)) - } else { - val validatedValue = Validation( - sf.validateAndEscapeProjectIri(value, throw BadRequestException(PROJECT_IRI_INVALID_ERROR)) - ) - - validatedValue.map(new ProjectIRI(_) {}) - } - } -} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala index f6f5d80b26..817cab5b2f 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ListsValueObjectsADM.scala @@ -22,7 +22,7 @@ object ListIRI { self => if (value.isEmpty) { Validation.fail(BadRequestException(LIST_NODE_IRI_MISSING_ERROR)) } else { - if (value.nonEmpty && !sf.isKnoraListIriStr(value)) { + if (!sf.isKnoraListIriStr(value)) { Validation.fail(BadRequestException(LIST_NODE_IRI_INVALID_ERROR)) } else { val validatedValue = Validation( @@ -45,7 +45,7 @@ object ListIRI { self => */ sealed abstract case class ListName private (value: String) object ListName { self => - val sf = StringFormatter.getGeneralInstance + val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: String): Validation[Throwable, ListName] = if (value.isEmpty) { @@ -89,7 +89,7 @@ object Position { self => */ sealed abstract case class Labels private (value: Seq[StringLiteralV2]) object Labels { self => - val sf = StringFormatter.getGeneralInstance + val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: Seq[StringLiteralV2]): Validation[Throwable, Labels] = if (value.isEmpty) { @@ -116,7 +116,7 @@ object Labels { self => */ sealed abstract case class Comments private (value: Seq[StringLiteralV2]) object Comments { self => - val sf = StringFormatter.getGeneralInstance + val sf: StringFormatter = StringFormatter.getGeneralInstance def make(value: Seq[StringLiteralV2]): Validation[Throwable, Comments] = if (value.isEmpty) { diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADM.scala new file mode 100644 index 0000000000..dd821c7790 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADM.scala @@ -0,0 +1,194 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsErrorMessagesADM._ +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +import zio.prelude.Validation + +/** + * ProjectIRI value object. + */ +sealed abstract case class ProjectIRI private (value: String) +object ProjectIRI { self => + val sf: StringFormatter = StringFormatter.getGeneralInstance + + def make(value: String): Validation[Throwable, ProjectIRI] = + if (value.isEmpty) { + Validation.fail(BadRequestException(PROJECT_IRI_MISSING_ERROR)) + } else { + if (!sf.isKnoraProjectIriStr(value)) { + Validation.fail(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + } else { + val validatedValue = Validation( + sf.validateAndEscapeProjectIri(value, throw BadRequestException(PROJECT_IRI_INVALID_ERROR)) + ) + + validatedValue.map(new ProjectIRI(_) {}) + } + } + + def make(value: Option[String]): Validation[Throwable, Option[ProjectIRI]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Project Shortcode value object. + */ +sealed abstract case class Shortcode private (value: String) +object Shortcode { self => + val sf: StringFormatter = StringFormatter.getGeneralInstance + + def make(value: String): Validation[Throwable, Shortcode] = + if (value.isEmpty) { + Validation.fail(BadRequestException(SHORTCODE_MISSING_ERROR)) + } else { + val validatedValue: Validation[Throwable, String] = Validation( + sf.validateProjectShortcode(value, throw BadRequestException(SHORTCODE_INVALID_ERROR)) + ) + validatedValue.map(new Shortcode(_) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[Shortcode]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Project Shortname value object. + */ +sealed abstract case class Shortname private (value: String) +object Shortname { self => + val sf: StringFormatter = StringFormatter.getGeneralInstance + + def make(value: String): Validation[Throwable, Shortname] = + if (value.isEmpty) { + Validation.fail(BadRequestException(SHORTNAME_MISSING_ERROR)) + } else { + val validatedValue = Validation( + sf.validateAndEscapeProjectShortname(value, throw BadRequestException(SHORTNAME_INVALID_ERROR)) + ) + validatedValue.map(new Shortname(_) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[Shortname]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Project Longname value object. + */ +sealed abstract case class Longname private (value: String) +object Longname { self => + def make(value: String): Validation[Throwable, Longname] = + if (value.isEmpty) { + Validation.fail(BadRequestException(LONGNAME_MISSING_ERROR)) + } else { + Validation.succeed(new Longname(value) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[Longname]] = + value match { + case None => Validation.succeed(None) + case Some(v) => self.make(v).map(Some(_)) + } +} + +/** + * ProjectDescription value object. + */ +sealed abstract case class ProjectDescription private (value: Seq[StringLiteralV2]) +object ProjectDescription { self => + def make(value: Seq[StringLiteralV2]): Validation[Throwable, ProjectDescription] = + if (value.isEmpty) { + Validation.fail(BadRequestException(PROJECT_DESCRIPTION_MISSING_ERROR)) + } else { + Validation.succeed(new ProjectDescription(value) {}) + } + + def make(value: Option[Seq[StringLiteralV2]]): Validation[Throwable, Option[ProjectDescription]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Project Keywords value object. + */ +sealed abstract case class Keywords private (value: Seq[String]) +object Keywords { self => + def make(value: Seq[String]): Validation[Throwable, Keywords] = + if (value.isEmpty) { + Validation.fail(BadRequestException(KEYWORDS_MISSING_ERROR)) + } else { + Validation.succeed(new Keywords(value) {}) + } + + def make(value: Option[Seq[String]]): Validation[Throwable, Option[Keywords]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Project Logo value object. + */ +sealed abstract case class Logo private (value: String) +object Logo { self => + def make(value: String): Validation[Throwable, Logo] = + if (value.isEmpty) { + Validation.fail(BadRequestException(LOGO_MISSING_ERROR)) + } else { + Validation.succeed(new Logo(value) {}) + } + def make(value: Option[String]): Validation[Throwable, Option[Logo]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * ProjectSelfjoin value object. + */ +sealed abstract case class ProjectSelfJoin private (value: Boolean) +object ProjectSelfJoin { self => + def make(value: Boolean): Validation[Throwable, ProjectSelfJoin] = + Validation.succeed(new ProjectSelfJoin(value) {}) + + def make(value: Option[Boolean]): Validation[Throwable, Option[ProjectSelfJoin]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * ProjectStatus value object. + */ +sealed abstract case class ProjectStatus private (value: Boolean) +object ProjectStatus { self => + def make(value: Boolean): Validation[Throwable, ProjectStatus] = + Validation.succeed(new ProjectStatus(value) {}) + + def make(value: Option[Boolean]): Validation[Throwable, Option[ProjectStatus]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADM.scala new file mode 100644 index 0000000000..bf86ad6139 --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADM.scala @@ -0,0 +1,201 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.LanguageCodes +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.StringFormatter +import org.knora.webapi.messages.admin.responder.usersmessages.UsersErrorMessagesADM._ +import zio.prelude.Validation + +import scala.util.matching.Regex + +/** + * UserIRI value object. + */ +sealed abstract case class UserIRI private (value: String) +object UserIRI { self => + private val sf: StringFormatter = StringFormatter.getGeneralInstance + + def make(value: String): Validation[Throwable, UserIRI] = + if (value.isEmpty) { + Validation.fail(BadRequestException(USER_IRI_MISSING_ERROR)) + } else { + if (!sf.isKnoraUserIriStr(value)) { + Validation.fail(BadRequestException(USER_IRI_INVALID_ERROR)) + } else { + val validatedValue = Validation( + sf.validateAndEscapeUserIri(value, throw BadRequestException(USER_IRI_INVALID_ERROR)) + ) + + validatedValue.map(new UserIRI(_) {}) + } + } + + def make(value: Option[String]): Validation[Throwable, Option[UserIRI]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Username value object. + */ +sealed abstract case class Username private (value: String) +object Username { self => + + /** + * A regex that matches a valid username + * - 4 - 50 characters long + * - Only contains alphanumeric characters, underscore and dot. + * - Underscore and dot can't be at the end or start of a username + * - Underscore or dot can't be used multiple times in a row + */ + private val UsernameRegex: Regex = + """^(?=.{4,50}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(? Validation.succeed(new Username(value) {}) + case None => Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + } + } + + def make(value: Option[String]): Validation[Throwable, Option[Username]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Email value object. + */ +sealed abstract case class Email private (value: String) +object Email { self => + private val EmailRegex: Regex = """^.+@.+$""".r + + def make(value: String): Validation[Throwable, Email] = + if (value.isEmpty) { + Validation.fail(BadRequestException(EMAIL_MISSING_ERROR)) + } else { + EmailRegex.findFirstIn(value) match { + case Some(value) => Validation.succeed(new Email(value) {}) + case None => Validation.fail(BadRequestException(EMAIL_INVALID_ERROR)) + } + } + + def make(value: Option[String]): Validation[Throwable, Option[Email]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * GivenName value object. + */ +sealed abstract case class GivenName private (value: String) +object GivenName { self => + def make(value: String): Validation[Throwable, GivenName] = + if (value.isEmpty) { + Validation.fail(BadRequestException(GIVEN_NAME_MISSING_ERROR)) + } else { + Validation.succeed(new GivenName(value) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[GivenName]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * FamilyName value object. + */ +sealed abstract case class FamilyName private (value: String) +object FamilyName { self => + def make(value: String): Validation[Throwable, FamilyName] = + if (value.isEmpty) { + Validation.fail(BadRequestException(FAMILY_NAME_MISSING_ERROR)) + } else { + Validation.succeed(new FamilyName(value) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[FamilyName]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * Password value object. + */ +sealed abstract case class Password private (value: String) +object Password { self => + private val PasswordRegex: Regex = """^[\s\S]*$""".r + + def make(value: String): Validation[Throwable, Password] = + if (value.isEmpty) { + Validation.fail(BadRequestException(PASSWORD_MISSING_ERROR)) + } else { + PasswordRegex.findFirstIn(value) match { + case Some(value) => Validation.succeed(new Password(value) {}) + case None => Validation.fail(BadRequestException(PASSWORD_INVALID_ERROR)) + } + } + + def make(value: Option[String]): Validation[Throwable, Option[Password]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * UserStatus value object. + */ +sealed abstract case class UserStatus private (value: Boolean) +object UserStatus { + def make(value: Boolean): Validation[Throwable, UserStatus] = + Validation.succeed(new UserStatus(value) {}) +} + +/** + * LanguageCode value object. + */ +sealed abstract case class LanguageCode private (value: String) +object LanguageCode { self => + def make(value: String): Validation[Throwable, LanguageCode] = + if (value.isEmpty) { + Validation.fail(BadRequestException(LANGUAGE_CODE_MISSING_ERROR)) + } else if (!LanguageCodes.SupportedLanguageCodes.contains(value)) { + Validation.fail(BadRequestException(LANGUAGE_CODE_INVALID_ERROR)) + } else { + Validation.succeed(new LanguageCode(value) {}) + } + + def make(value: Option[String]): Validation[Throwable, Option[LanguageCode]] = + value match { + case Some(v) => self.make(v).map(Some(_)) + case None => Validation.succeed(None) + } +} + +/** + * SystemAdmin value object. + */ +sealed abstract case class SystemAdmin private (value: Boolean) +object SystemAdmin { + def make(value: Boolean): Validation[Throwable, SystemAdmin] = + Validation.succeed(new SystemAdmin(value) {}) +} diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala deleted file mode 100644 index a11d0003a5..0000000000 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/valueObjects/ValueObjectsADM.scala +++ /dev/null @@ -1,262 +0,0 @@ -package org.knora.webapi.messages.admin.responder.valueObjects - -import org.knora.webapi.LanguageCodes -import org.knora.webapi.exceptions.{AssertionException, BadRequestException} -import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import zio.prelude.Validation - -import scala.util.matching.Regex - -// TODO-mpro: this is so far shared value object file, consider to slice it - -/** User value objects */ - -/** - * User Username value object. - */ -sealed abstract case class Username private (value: String) -object Username { - - /** - * A regex that matches a valid username - * - 4 - 50 characters long - * - Only contains alphanumeric characters, underscore and dot. - * - Underscore and dot can't be at the end or start of a username - * - Underscore or dot can't be used multiple times in a row - */ - private val UsernameRegex: Regex = - """^(?=.{4,50}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(? - Right(new Username(value) {}) - case None => Left(BadRequestException("Invalid username")) - } - } -} - -/** - * User Email value object. - */ -sealed abstract case class Email private (value: String) -object Email { - private val EmailRegex: Regex = """^.+@.+$""".r // TODO use proper validation - - def create(value: String): Either[Throwable, Email] = - if (value.isEmpty) { - Left(BadRequestException("Missing email")) - } else { - EmailRegex.findFirstIn(value) match { - case Some(value) => Right(new Email(value) {}) - case None => Left(BadRequestException("Invalid email")) - } - } -} - -/** - * 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 - - def create(value: String): Either[Throwable, Password] = - if (value.isEmpty) { - Left(BadRequestException("Missing password")) - } else { - PasswordRegex.findFirstIn(value) match { - case Some(value) => Right(new Password(value) {}) - case None => Left(BadRequestException("Invalid password")) - } - } -} - -/** - * 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] = - if (value.isEmpty) { - Left(BadRequestException("Missing given name")) - } else { - Right(new GivenName(value) {}) - } -} - -/** - * 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] = - if (value.isEmpty) { - Left(BadRequestException("Missing family name")) - } else { - Right(new FamilyName(value) {}) - } -} - -/** - * User LanguageCode value object. - */ -sealed abstract case class LanguageCode private (value: String) -object LanguageCode { - def create(value: String): Either[Throwable, LanguageCode] = - if (value.isEmpty) { - Left(BadRequestException("Missing language code")) - } else if (!LanguageCodes.SupportedLanguageCodes.contains(value)) { - Left(BadRequestException("Invalid language code")) - } else { - Right(new LanguageCode(value) {}) - } -} - -/** - * 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. - */ -sealed abstract case class Shortcode private (value: String) -object Shortcode { - val stringFormatter = StringFormatter.getGeneralInstance - - def make(value: String): Validation[Throwable, Shortcode] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing shortcode")) - } else { - val validatedValue: Validation[Throwable, String] = Validation( - stringFormatter.validateProjectShortcode(value, throw AssertionException("not valid")) - ) - validatedValue.map(new Shortcode(_) {}) - } -} - -/** - * Project Shortname value object. - */ -sealed abstract case class Shortname private (value: String) -object Shortname { - val stringFormatter = StringFormatter.getGeneralInstance - - def make(value: String): Validation[Throwable, Shortname] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing shortname")) - } else { - val validatedValue = Validation( - stringFormatter.validateAndEscapeProjectShortname(value, throw AssertionException("not valid")) - ) - validatedValue.map(new Shortname(_) {}) - } -} - -/** - * Project Longname value object. - */ -sealed abstract case class Longname private (value: String) -object Longname { self => - def make(value: String): Validation[Throwable, Longname] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing long name")) - } else { - Validation.succeed(new Longname(value) {}) - } - def make(value: Option[String]): Validation[Throwable, Option[Longname]] = - value match { - case None => Validation.succeed(None) - case Some(v) => self.make(v).map(Some(_)) - } -} - -/** - * Project Keywords value object. - */ -sealed abstract case class Keywords private (value: Seq[String]) -object Keywords { - def make(value: Seq[String]): Validation[Throwable, Keywords] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing keywords")) - } else { - Validation.succeed(new Keywords(value) {}) - } -} - -/** - * Project Logo value object. - */ -sealed abstract case class Logo private (value: String) -object Logo { self => - def make(value: String): Validation[Throwable, Logo] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing logo")) - } else { - Validation.succeed(new Logo(value) {}) - } - def make(value: Option[String]): Validation[Throwable, Option[Logo]] = - value match { - case None => Validation.succeed(None) - case Some(v) => self.make(v).map(Some(_)) - } -} - -/** Shared value objects */ - -/** - * Selfjoin value object. - */ -sealed abstract case class Selfjoin private (value: Boolean) -object Selfjoin { - def make(value: Boolean): Validation[Throwable, Selfjoin] = - Validation.succeed(new Selfjoin(value) {}) -} - -/** - * Status value object. - */ -sealed abstract case class Status private (value: Boolean) -object Status { - def make(value: Boolean): Validation[Throwable, Status] = - Validation.succeed(new Status(value) {}) -} - -/** - * Description value object. - */ -sealed abstract case class Description private (value: Seq[StringLiteralV2]) -object Description { - def make(value: Seq[StringLiteralV2]): Validation[Throwable, Description] = - if (value.isEmpty) { - Validation.fail(BadRequestException("Missing description")) - } else { - Validation.succeed(new Description(value) {}) - } -} - -/** - * Name value object. - */ -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) {}) - } -} 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 a872850c97..c6b55cd4e2 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 @@ -5,9 +5,6 @@ package org.knora.webapi.responders.admin -import java.io.{BufferedInputStream, BufferedOutputStream} -import java.nio.file.{Files, Path} -import java.util.UUID import akka.http.scaladsl.util.FastFuture import akka.pattern._ import org.knora.webapi._ @@ -16,6 +13,7 @@ import org.knora.webapi.exceptions._ import org.knora.webapi.feature.FeatureFactoryConfig import org.knora.webapi.instrumentation.InstrumentationSupport import org.knora.webapi.messages.IriConversions._ +import org.knora.webapi.messages.admin.responder.permissionsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.{ UserADM, @@ -23,12 +21,10 @@ import org.knora.webapi.messages.admin.responder.usersmessages.{ UserIdentifierADM, UserInformationTypeADM } -import org.knora.webapi.messages.admin.responder.permissionsmessages._ import org.knora.webapi.messages.store.cacheservicemessages.{ CacheServiceFlushDB, CacheServiceGetProjectADM, - CacheServicePutProjectADM, - CacheServiceRemoveValues + CacheServicePutProjectADM } import org.knora.webapi.messages.store.triplestoremessages._ import org.knora.webapi.messages.util.rdf._ @@ -38,10 +34,13 @@ import org.knora.webapi.messages.v2.responder.ontologymessages.{ OntologyMetadataGetByProjectRequestV2, ReadOntologyMetadataV2 } -import org.knora.webapi.messages.{OntologyConstants, SmartIri, StringFormatter} +import org.knora.webapi.messages.{OntologyConstants, SmartIri} import org.knora.webapi.responders.Responder.handleUnexpectedMessage import org.knora.webapi.responders.{IriLocker, Responder} +import java.io.{BufferedInputStream, BufferedOutputStream} +import java.nio.file.{Files, Path} +import java.util.UUID import scala.concurrent.Future import scala.util.{Failure, Success, Try} @@ -868,7 +867,6 @@ class ProjectsResponderADM(responderData: ResponderData) extends Responder(respo if (parametersCount == 0) throw BadRequestException("No data would be changed. Aborting update request.") for { - maybeCurrentProject: Option[ProjectADM] <- getSingleProjectADM( identifier = ProjectIdentifierADM(maybeIri = Some(projectIri)), featureFactoryConfig = featureFactoryConfig, @@ -880,7 +878,6 @@ class ProjectsResponderADM(responderData: ResponderData) extends Responder(respo throw NotFoundException(s"Project '$projectIri' not found. Aborting update request.") } // we are changing the project, so lets get rid of the cached copy - // invalidateCachedProjectADM isn't clearing cache as expected _ = storeManager ? CacheServiceFlushDB(KnoraSystemInstances.Users.SystemUser) /* Update project */ @@ -1074,7 +1071,6 @@ class ProjectsResponderADM(responderData: ResponderData) extends Responder(respo requestingUser: UserADM ): Future[ProjectOperationResponseADM] = for { - // check if the supplied shortname is unique shortnameExists <- projectByShortnameExists(createProjectRequest.shortname.value) _ = if (shortnameExists) { @@ -1099,7 +1095,7 @@ class ProjectsResponderADM(responderData: ResponderData) extends Responder(respo } // check the custom IRI; if not given, create an unused IRI - customProjectIri: Option[SmartIri] = createProjectRequest.id.map(iri => iri.toSmartIri) + customProjectIri: Option[SmartIri] = createProjectRequest.id.map(_.value).map(_.toSmartIri) newProjectIRI: IRI <- checkOrCreateEntityIri( customProjectIri, stringFormatter.makeRandomProjectIri(createProjectRequest.shortcode.value) @@ -1440,28 +1436,4 @@ class ProjectsResponderADM(responderData: ResponderData) extends Responder(respo res } } - - /** - * Removes the project from cache. - */ - private def invalidateCachedProjectADM(maybeProject: Option[ProjectADM]): Future[Boolean] = - if (cacheServiceSettings.cacheServiceEnabled) { - val keys: Set[String] = - Seq(maybeProject.map(_.id), maybeProject.map(_.shortname), maybeProject.map(_.shortcode)).flatten.toSet - // only send to Redis if keys are not empty - if (keys.nonEmpty) { - val result = (storeManager ? CacheServiceRemoveValues(keys)).mapTo[Boolean] - result.map { res => - log.debug("invalidateCachedProjectADM - result: {}", res) - res - } - } else { - // since there was nothing to remove, we can immediately return - FastFuture.successful(true) - } - } else { - // caching is turned off, so nothing to do. - FastFuture.successful(true) - } - } 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 76f064b0b9..f2e5ff2186 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 @@ -16,7 +16,7 @@ import org.knora.webapi.messages.admin.responder.groupsmessages.{GroupADM, Group 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.{UserChangeRequestADM, _} -import org.knora.webapi.messages.admin.responder.valueObjects.{Username, Email, Password, Status, SystemAdmin} +import org.knora.webapi.messages.admin.responder.valueObjects.{Username, Email, Password, UserStatus, SystemAdmin} import org.knora.webapi.messages.store.cacheservicemessages.{ CacheServiceGetUserADM, CacheServicePutUserADM, @@ -510,8 +510,8 @@ class UsersResponderADM(responderData: ResponderData) extends Responder(responde // hash the new password encoder = new BCryptPasswordEncoder(settings.bcryptPasswordStrength) newHashedPassword = Password - .create(encoder.encode(userUpdatePasswordPayload.newPassword.value)) - .fold(error => throw error, value => value) + .make(encoder.encode(userUpdatePasswordPayload.newPassword.value)) + .fold(e => throw e.head, value => value) // update the users password as SystemUser result <- updateUserPasswordADM( @@ -548,7 +548,7 @@ class UsersResponderADM(responderData: ResponderData) extends Responder(responde */ private def changeUserStatusADM( userIri: IRI, - status: Status, + status: UserStatus, featureFactoryConfig: FeatureFactoryConfig, requestingUser: UserADM, apiRequestID: UUID @@ -561,7 +561,7 @@ class UsersResponderADM(responderData: ResponderData) extends Responder(responde */ def changeUserStatusTask( userIri: IRI, - status: Status, + status: UserStatus, requestingUser: UserADM, apiRequestID: UUID ): Future[UserOperationResponseADM] = @@ -1687,28 +1687,28 @@ class UsersResponderADM(responderData: ResponderData) extends Responder(responde def createNewUserTask(userCreatePayloadADM: UserCreatePayloadADM) = for { // check if username is unique - usernameTaken: Boolean <- userByUsernameExists(userCreatePayloadADM.username) + usernameTaken: Boolean <- userByUsernameExists(Some(userCreatePayloadADM.username)) _ = if (usernameTaken) { throw DuplicateValueException( - s"User with the username '${userCreatePayloadADM.username.get.value}' already exists" + s"User with the username '${userCreatePayloadADM.username.value}' already exists" ) } // check if email is unique - emailTaken: Boolean <- userByEmailExists(userCreatePayloadADM.email) + emailTaken: Boolean <- userByEmailExists(Some(userCreatePayloadADM.email)) _ = if (emailTaken) { throw DuplicateValueException( - s"User with the email '${userCreatePayloadADM.email.get.value}' already exists" + s"User with the email '${userCreatePayloadADM.email.value}' already exists" ) } // check the custom IRI; if not given, create an unused IRI - customUserIri: Option[SmartIri] = userCreatePayloadADM.id.map(iri => iri.toSmartIri) + customUserIri: Option[SmartIri] = userCreatePayloadADM.id.map(_.value.toSmartIri) userIri: IRI <- checkOrCreateEntityIri(customUserIri, stringFormatter.makeRandomPersonIri) // hash password encoder = new BCryptPasswordEncoder(settings.bcryptPasswordStrength) - hashedPassword = encoder.encode(userCreatePayloadADM.password.get.value) + hashedPassword = encoder.encode(userCreatePayloadADM.password.value) // Create the new user. createNewUserSparqlString = org.knora.webapi.messages.twirl.queries.sparql.admin.txt @@ -1718,38 +1718,38 @@ class UsersResponderADM(responderData: ResponderData) extends Responder(responde userIri = userIri, userClassIri = OntologyConstants.KnoraAdmin.User, username = stringFormatter.toSparqlEncodedString( - userCreatePayloadADM.username.get.value, + userCreatePayloadADM.username.value, errorFun = throw BadRequestException( - s"The supplied username: '${userCreatePayloadADM.username.get.value}' is not valid." + s"The supplied username: '${userCreatePayloadADM.username.value}' is not valid." ) ), email = stringFormatter.toSparqlEncodedString( - userCreatePayloadADM.email.get.value, + userCreatePayloadADM.email.value, errorFun = throw BadRequestException( - s"The supplied email: '${userCreatePayloadADM.email.get.value}' is not valid." + s"The supplied email: '${userCreatePayloadADM.email.value}' is not valid." ) ), password = hashedPassword, givenName = stringFormatter.toSparqlEncodedString( - userCreatePayloadADM.givenName.get.value, + userCreatePayloadADM.givenName.value, errorFun = throw BadRequestException( - s"The supplied given name: '${userCreatePayloadADM.givenName.get.value}' is not valid." + s"The supplied given name: '${userCreatePayloadADM.givenName.value}' is not valid." ) ), familyName = stringFormatter.toSparqlEncodedString( - userCreatePayloadADM.familyName.get.value, + userCreatePayloadADM.familyName.value, errorFun = throw BadRequestException( - s"The supplied family name: '${userCreatePayloadADM.familyName.get.value}' is not valid." + s"The supplied family name: '${userCreatePayloadADM.familyName.value}' is not valid." ) ), - status = userCreatePayloadADM.status.get.value, + status = userCreatePayloadADM.status.value, preferredLanguage = stringFormatter.toSparqlEncodedString( - userCreatePayloadADM.lang.get.value, + userCreatePayloadADM.lang.value, errorFun = throw BadRequestException( - s"The supplied language: '${userCreatePayloadADM.lang.get.value}' is not valid." + s"The supplied language: '${userCreatePayloadADM.lang.value}' is not valid." ) ), - systemAdmin = userCreatePayloadADM.systemAdmin.get.value + systemAdmin = userCreatePayloadADM.systemAdmin.value ) .toString 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 d898909dd0..5270728748 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 @@ -137,12 +137,12 @@ class GroupsRouteADM(routeData: KnoraRouteData) private def createGroup(featureFactoryConfig: FeatureFactoryConfig): Route = path(GroupsBasePath) { post { entity(as[CreateGroupApiRequestADM]) { apiRequest => requestContext => - val id = GroupIRI.make(apiRequest.id) - val name = GroupName.make(apiRequest.name) - val descriptions = GroupDescriptions.make(apiRequest.descriptions) - val project = ProjectIRI.make(apiRequest.project) - val status = GroupStatus.make(apiRequest.status) - val selfjoin = GroupSelfJoin.make(apiRequest.selfjoin) + val id: Validation[Throwable, Option[GroupIRI]] = GroupIRI.make(apiRequest.id) + val name: Validation[Throwable, GroupName] = GroupName.make(apiRequest.name) + val descriptions: Validation[Throwable, GroupDescriptions] = GroupDescriptions.make(apiRequest.descriptions) + val project: Validation[Throwable, ProjectIRI] = ProjectIRI.make(apiRequest.project) + val status: Validation[Throwable, GroupStatus] = GroupStatus.make(apiRequest.status) + val selfjoin: Validation[Throwable, GroupSelfJoin] = GroupSelfJoin.make(apiRequest.selfjoin) val validatedGroupCreatePayload: Validation[Throwable, GroupCreatePayloadADM] = Validation.validateWith(id, name, descriptions, project, status, selfjoin)(GroupCreatePayloadADM) @@ -188,10 +188,11 @@ class GroupsRouteADM(routeData: KnoraRouteData) ) } - val name = GroupName.make(apiRequest.name) - val descriptions = GroupDescriptions.make(apiRequest.descriptions) - val status = GroupStatus.make(apiRequest.status) - val selfjoin = GroupSelfJoin.make(apiRequest.selfjoin) + val name: Validation[Throwable, Option[GroupName]] = GroupName.make(apiRequest.name) + val descriptions: Validation[Throwable, Option[GroupDescriptions]] = + GroupDescriptions.make(apiRequest.descriptions) + val status: Validation[Throwable, Option[GroupStatus]] = GroupStatus.make(apiRequest.status) + val selfjoin: Validation[Throwable, Option[GroupSelfJoin]] = GroupSelfJoin.make(apiRequest.selfjoin) val validatedGroupUpdatePayload: Validation[Throwable, GroupUpdatePayloadADM] = Validation.validateWith(name, descriptions, status, selfjoin)(GroupUpdatePayloadADM) 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 497f27bdc5..6dd5b5f6ad 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 @@ -20,17 +20,7 @@ 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.valueObjects.{ - Description, - Keywords, - Logo, - Longname, - Selfjoin, - Shortcode, - Shortname, - Status -} -import org.knora.webapi.messages.store.cacheservicemessages.CacheServiceFlushDB +import org.knora.webapi.messages.admin.responder.valueObjects._ import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} import zio.prelude.Validation @@ -139,19 +129,15 @@ class ProjectsRouteADM(routeData: KnoraRouteData) post { entity(as[CreateProjectApiRequestADM]) { apiRequest => requestContext => // zio prelude: validation - val id = Validation( - stringFormatter - .validateAndEscapeOptionalProjectIri(apiRequest.id, throw BadRequestException(s"Invalid project IRI")) - ) -// TODO-mpro: why id, longname and logo are not options below? - val shortname = Shortname.make(apiRequest.shortname) - val shortcode = Shortcode.make(apiRequest.shortcode) - val longname = Longname.make(apiRequest.longname) - val description = Description.make(apiRequest.description) - val keywords = Keywords.make(apiRequest.keywords) - val logo = Logo.make(apiRequest.logo) - val status = Status.make(apiRequest.status) - val selfjoin = Selfjoin.make(apiRequest.selfjoin) + val id: Validation[Throwable, Option[ProjectIRI]] = ProjectIRI.make(apiRequest.id) + val shortname: Validation[Throwable, Shortname] = Shortname.make(apiRequest.shortname) + val shortcode: Validation[Throwable, Shortcode] = Shortcode.make(apiRequest.shortcode) + val longname: Validation[Throwable, Option[Longname]] = Longname.make(apiRequest.longname) + val description: Validation[Throwable, ProjectDescription] = ProjectDescription.make(apiRequest.description) + val keywords: Validation[Throwable, Keywords] = Keywords.make(apiRequest.keywords) + val logo: Validation[Throwable, Option[Logo]] = Logo.make(apiRequest.logo) + val status: Validation[Throwable, ProjectStatus] = ProjectStatus.make(apiRequest.status) + val selfjoin: Validation[Throwable, ProjectSelfJoin] = ProjectSelfJoin.make(apiRequest.selfjoin) val projectCreatePayload: Validation[Throwable, ProjectCreatePayloadADM] = Validation.validateWith(id, shortname, shortcode, longname, description, keywords, logo, status, selfjoin)( 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 3b3e78267f..d9812c0c75 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 @@ -9,22 +9,14 @@ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.{PathMatcher, Route} import io.swagger.annotations._ import org.knora.webapi.annotation.ApiMayChange -import org.knora.webapi.exceptions.{BadRequestException} +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.admin.responder.usersmessages._ +import org.knora.webapi.messages.admin.responder.valueObjects._ import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.routing.{Authenticator, KnoraRoute, KnoraRouteData, RouteUtilADM} +import zio.prelude.Validation import java.util.UUID import javax.ws.rs.Path @@ -123,25 +115,34 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit post { entity(as[CreateUserApiRequestADM]) { apiRequest => requestContext => // get all values from request and make value objects from it - val user: UserCreatePayloadADM = - UserCreatePayloadADM.create( - id = stringFormatter.validateOptionalUserIri(apiRequest.id, throw BadRequestException(s"Invalid user IRI")), - username = Username.create(apiRequest.username).fold(error => throw error, value => value), - email = Email.create(apiRequest.email).fold(error => throw error, value => value), - givenName = GivenName.create(apiRequest.givenName).fold(error => throw error, value => value), - familyName = FamilyName.create(apiRequest.familyName).fold(error => throw error, value => value), - password = Password.create(apiRequest.password).fold(error => throw error, value => value), - status = Status.make(apiRequest.status).fold(error => throw error.head, value => value), - lang = LanguageCode.create(apiRequest.lang).fold(error => throw error, value => value), - systemAdmin = SystemAdmin.create(apiRequest.systemAdmin).fold(error => throw error, value => value) - ) + val id: Validation[Throwable, Option[UserIRI]] = UserIRI.make(apiRequest.id) + val username: Validation[Throwable, Username] = Username.make(apiRequest.username) + val email: Validation[Throwable, Email] = Email.make(apiRequest.email) + val givenName: Validation[Throwable, GivenName] = GivenName.make(apiRequest.givenName) + val familyName: Validation[Throwable, FamilyName] = FamilyName.make(apiRequest.familyName) + val password: Validation[Throwable, Password] = Password.make(apiRequest.password) + val status: Validation[Throwable, UserStatus] = UserStatus.make(apiRequest.status) + val languageCode: Validation[Throwable, LanguageCode] = LanguageCode.make(apiRequest.lang) + val systemAdmin: Validation[Throwable, SystemAdmin] = SystemAdmin.make(apiRequest.systemAdmin) + + val validatedUserCreatePayload: Validation[Throwable, UserCreatePayloadADM] = + Validation.validateWith( + id, + username, + email, + givenName, + familyName, + password, + status, + languageCode, + systemAdmin + )(UserCreatePayloadADM) + val requestMessage: Future[UserCreateRequestADM] = for { - requestingUser <- getUserADM( - requestContext = requestContext, - featureFactoryConfig = featureFactoryConfig - ) + payload <- toFuture(validatedUserCreatePayload) + requestingUser <- getUserADM(requestContext, featureFactoryConfig) } yield UserCreateRequestADM( - userCreatePayloadADM = user, + userCreatePayloadADM = payload, featureFactoryConfig = featureFactoryConfig, requestingUser = requestingUser, apiRequestID = UUID.randomUUID() @@ -267,34 +268,21 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit throw BadRequestException("Changes to built-in users are not allowed.") } - val maybeChangedUsername = apiRequest.username match { - case Some(username) => Some(Username.create(username).fold(error => throw error, value => value)) - case None => None - } - val maybeChangedEmail = apiRequest.email match { - case Some(email) => Some(Email.create(email).fold(error => throw error, value => value)) - case None => None - } - val maybeChangedGivenName = apiRequest.givenName match { - case Some(givenName) => Some(GivenName.create(givenName).fold(error => throw error, value => value)) - case None => None - } - val maybeChangedFamilyName = apiRequest.familyName match { - case Some(familyName) => Some(FamilyName.create(familyName).fold(error => throw error, value => value)) - case None => None - } - val maybeChangedLang = apiRequest.lang match { - case Some(lang) => Some(LanguageCode.create(lang).fold(error => throw error, value => value)) - case None => None - } + val maybeUsername: Option[Username] = Username.make(apiRequest.username).fold(e => throw e.head, v => v) + val maybeEmail: Option[Email] = Email.make(apiRequest.email).fold(e => throw e.head, v => v) + val maybeGivenName: Option[GivenName] = GivenName.make(apiRequest.givenName).fold(e => throw e.head, v => v) + val maybeFamilyName: Option[FamilyName] = + FamilyName.make(apiRequest.familyName).fold(e => throw e.head, v => v) + val maybeLanguageCode: Option[LanguageCode] = + LanguageCode.make(apiRequest.lang).fold(e => throw e.head, v => v) val userUpdatePayload: UserUpdateBasicInformationPayloadADM = UserUpdateBasicInformationPayloadADM( - username = maybeChangedUsername, - email = maybeChangedEmail, - givenName = maybeChangedGivenName, - familyName = maybeChangedFamilyName, - lang = maybeChangedLang + maybeUsername, + maybeEmail, + maybeGivenName, + maybeFamilyName, + maybeLanguageCode ) /* the api request is already checked at time of creation. see case class. */ @@ -345,11 +333,11 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit } val requesterPassword = apiRequest.requesterPassword match { - case Some(password) => Password.create(password).fold(error => throw error, value => value) + case Some(password) => Password.make(password).fold(e => throw e.head, v => v) case None => throw BadRequestException("The requester's password is missing.") } val changedPassword = apiRequest.newPassword match { - case Some(password) => Password.create(password).fold(error => throw error, value => value) + case Some(password) => Password.make(password).fold(e => throw e.head, v => v) case None => throw BadRequestException("The new password is missing.") } @@ -400,7 +388,7 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit } val newStatus = apiRequest.status match { - case Some(status) => Status.make(status).fold(error => throw error.head, value => value) + case Some(status) => UserStatus.make(status).fold(error => throw error.head, value => value) case None => throw BadRequestException("The status is missing.") } @@ -450,7 +438,7 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit } /* update existing user's status to false */ - val status = Status.make(false).fold(error => throw error.head, value => value) + val status = UserStatus.make(false).fold(error => throw error.head, value => value) val requestMessage: Future[UserChangeStatusRequestADM] = for { requestingUser <- getUserADM( @@ -498,7 +486,7 @@ class UsersRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit } val newSystemAdmin = apiRequest.systemAdmin match { - case Some(systemAdmin) => SystemAdmin.create(systemAdmin).fold(error => throw error, value => value) + case Some(systemAdmin) => SystemAdmin.make(systemAdmin).fold(e => throw e.head, v => v) case None => throw BadRequestException("The systemAdmin is missing.") } diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala index 7e696d66b1..dbc86c38f8 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala @@ -134,9 +134,7 @@ class UsersADME2ESpec } "The Users Route ('admin/users')" when { - "used to query user information [FUNCTIONALITY]" should { - "return all users" in { val request = Get(baseApiUrl + s"/admin/users") ~> addCredentials(BasicHttpCredentials(rootCreds.email, rootCreds.password)) @@ -198,7 +196,6 @@ class UsersADME2ESpec } "used to query user information [PERMISSIONS]" should { - "return single user for SystemAdmin" in { val request = Get(baseApiUrl + s"/admin/users/iri/$normalUserIriEnc") ~> addCredentials( BasicHttpCredentials(rootCreds.email, rootCreds.password) @@ -327,7 +324,6 @@ class UsersADME2ESpec } "given a custom Iri" should { - "create a user with the provided custom IRI " in { val createUserWithCustomIriRequest: String = s"""{ @@ -404,7 +400,6 @@ class UsersADME2ESpec } "dealing with special characters" should { - "escape special characters when creating the user" in { val createUserWithApostropheRequest: String = s"""{ @@ -475,9 +470,7 @@ class UsersADME2ESpec } "used to create a user" should { - "create the user if the supplied email and username are unique " in { - val createUserRequest: String = s"""{ | "username": "donald.duck", @@ -528,7 +521,6 @@ class UsersADME2ESpec } "return a 'BadRequest' if the supplied username is not unique " in { - val createUserRequest: String = s"""{ | "username": "donald.duck", @@ -569,7 +561,6 @@ class UsersADME2ESpec } "return a 'BadRequest' if the supplied email is not unique " in { - val createUserRequest: String = s"""{ | "username": "new.donald.duck", @@ -610,7 +601,6 @@ class UsersADME2ESpec } "authenticate the newly created user using HttpBasicAuth" in { - val request = Get(baseApiUrl + s"/v2/authentication") ~> addCredentials( BasicHttpCredentials("donald.duck@example.org", "test") ) @@ -620,7 +610,6 @@ class UsersADME2ESpec } "authenticate the newly created user during login" in { - val params = s""" { @@ -638,9 +627,7 @@ class UsersADME2ESpec } "used to modify user information" should { - "update the user's basic information" in { - val updateUserRequest: String = s"""{ | "username": "donald.big.duck", @@ -689,7 +676,6 @@ class UsersADME2ESpec } "return 'BadRequest' if user IRI is None and 'NotFound' if user IRI is '' in update user request" in { - val updateUserRequest: String = s"""{ | "username": "donald.without.iri.duck" @@ -749,7 +735,6 @@ class UsersADME2ESpec } "update the user's password (by himself)" in { - val changeUserPasswordRequest: String = s"""{ | "requesterPassword": "test", @@ -796,7 +781,6 @@ class UsersADME2ESpec } "update the user's password (by a system admin)" in { - val params01 = s""" { @@ -822,7 +806,6 @@ class UsersADME2ESpec } "return 'BadRequest' if new password in change password request is missing" in { - val changeUserPasswordRequest: String = s"""{ | "requesterPassword": "test" @@ -867,7 +850,6 @@ class UsersADME2ESpec } "return 'BadRequest' if requester's password in change password request is missing" in { - val changeUserPasswordRequest: String = s"""{ | "newPassword": "testABC" @@ -950,7 +932,6 @@ class UsersADME2ESpec } "return 'BadRequest' if more than 1 parameter is provided in update status request" in { - val updateUserRequest: String = s"""{ | "status": false, @@ -1047,9 +1028,7 @@ class UsersADME2ESpec } "not allow changing the anonymous user's status" in { - val anonymousUserIriEncoded = java.net.URLEncoder.encode(KnoraSystemInstances.Users.AnonymousUser.id, "utf-8") - val params = s""" { @@ -1106,7 +1085,6 @@ class UsersADME2ESpec } "used to query project memberships" should { - "return all projects the user is a member of" in { val request = Get(baseApiUrl + s"/admin/users/iri/$multiUserIriEnc/project-memberships") ~> addCredentials( BasicHttpCredentials(rootCreds.email, rootCreds.password) @@ -1139,7 +1117,6 @@ class UsersADME2ESpec } "used to modify project membership" should { - "add user to project" in { val membershipsBeforeUpdate = getUserProjectMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq()) @@ -1193,7 +1170,6 @@ class UsersADME2ESpec } "remove user from project" in { - val membershipsBeforeUpdate = getUserProjectMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq(SharedTestDataADM.imagesProject)) @@ -1222,7 +1198,6 @@ class UsersADME2ESpec } "used to query project admin group memberships" should { - "return all projects the user is a member of the project admin group" in { val request = Get( baseApiUrl + s"/admin/users/iri/$multiUserIriEnc/project-admin-memberships" @@ -1255,7 +1230,6 @@ class UsersADME2ESpec } "used to modify project admin group membership" should { - "add user to project admin group" in { val membershipsBeforeUpdate = getUserProjectAdminMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq()) @@ -1284,7 +1258,6 @@ class UsersADME2ESpec } "remove user from project admin group" in { - val membershipsBeforeUpdate = getUserProjectAdminMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq(SharedTestDataADM.imagesProject)) @@ -1315,7 +1288,6 @@ class UsersADME2ESpec } "used to query group memberships" should { - "return all groups the user is a member of" in { val request = Get(baseApiUrl + s"/admin/users/iri/$multiUserIriEnc/group-memberships") ~> addCredentials( BasicHttpCredentials(rootCreds.email, rootCreds.password) @@ -1346,9 +1318,7 @@ class UsersADME2ESpec } "used to modify group membership" should { - "add user to group" in { - val membershipsBeforeUpdate = getUserGroupMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq.empty[GroupADM]) @@ -1375,7 +1345,6 @@ class UsersADME2ESpec } "remove user from group" in { - val membershipsBeforeUpdate = getUserGroupMemberships(normalUserCreds.userIri, rootCreds) membershipsBeforeUpdate should equal(Seq(SharedTestDataADM.imagesReviewerGroup)) @@ -1400,8 +1369,6 @@ class UsersADME2ESpec ) ) } - } - } } diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADMSpec.scala index d8338ce572..1d178bf8d3 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/projectsmessages/ProjectsMessagesADMSpec.scala @@ -23,115 +23,9 @@ object ProjectsMessagesADMSpec { * This spec is used to test subclasses of the [[ProjectsResponderRequestADM]] trait. */ class ProjectsMessagesADMSpec extends CoreSpec(ProjectsMessagesADMSpec.config) { - private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance - "The CreateProjectApiRequestADM case class" should { - - "return a 'BadRequest' when project description is not supplied" in { - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - shortname = "newproject5", - shortcode = "1114", - longname = Some("project longname"), - description = Seq.empty[StringLiteralV2], - keywords = Seq("keywords"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ) - ) - assert(caught.getMessage === "Project description needs to be supplied.") - } - - "return 'BadRequest' if the supplied project IRI is not a valid IRI" in { - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - id = Some("invalid-project-IRI"), - shortname = "newprojectWithInvalidIri", - shortcode = "2222", - longname = Some("new project with a custom invalid IRI"), - description = Seq(StringLiteralV2("a project created with an invalid custom IRI", Some("en"))), - keywords = Seq("projectInvalidIRI"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ).validateAndEscape - ) - assert(caught.getMessage === "Invalid project IRI") - } - - "return 'BadRequestException' if project 'shortname' during creation is missing" in { - - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - shortname = "", - shortcode = "1114", - longname = Some("project longname"), - description = Seq(StringLiteralV2(value = "project description", language = Some("en"))), - keywords = Seq("keywords"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ).validateAndEscape - ) - assert(caught.getMessage === s"Project shortname must be supplied.") - } - - "return 'BadRequestException' if project 'shortcode' during creation is missing" in { - - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - shortname = "newproject4", - shortcode = "", - longname = Some("project longname"), - description = Seq(StringLiteralV2(value = "project description", language = Some("en"))), - keywords = Seq("keywords"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ).validateAndEscape - ) - assert(caught.getMessage === "Project shortcode must be supplied.") - } - - "return 'BadRequestException' if project 'shortname' is not NCName valid" in { - val invalidShortName = "abd%2" - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - shortname = invalidShortName, - shortcode = "1114", - longname = Some("project longname"), - description = Seq(StringLiteralV2(value = "project description", language = Some("en"))), - keywords = Seq("keywords"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ).validateAndEscape - ) - assert(caught.getMessage === s"The supplied short name: '$invalidShortName' is not valid.") - } - - "return 'BadRequestException' if project 'shortname' is not URL safe" in { - val invalidShortName = "äbd2" - val caught = intercept[BadRequestException]( - CreateProjectApiRequestADM( - shortname = invalidShortName, - shortcode = "1114", - longname = Some("project longname"), - description = Seq(StringLiteralV2(value = "project description", language = Some("en"))), - keywords = Seq("keywords"), - logo = Some("/fu/bar/baz.jpg"), - status = true, - selfjoin = false - ).validateAndEscape - ) - assert(caught.getMessage === s"The supplied short name: '$invalidShortName' is not valid.") - } - } - "The ChangeProjectApiRequestADM case class" should { - "return a 'BadRequest' when everything is 'None" in { assertThrows[BadRequestException]( ChangeProjectApiRequestADM( @@ -148,7 +42,6 @@ class ProjectsMessagesADMSpec extends CoreSpec(ProjectsMessagesADMSpec.config) { } "The ProjectADM case class" should { - "return a 'OntologyConstraintException' when project description is not supplied" in { assertThrows[OntologyConstraintException]( ProjectADM( diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel index e366db4100..2e85007fb2 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/BUILD.bazel @@ -8,8 +8,9 @@ scala_test( size = "small", # 60s srcs = [ "GroupsValueObjectsADMSpec.scala", - "IriValueObjectsADMSpec.scala", + "ProjectsValueObjectsADMSpec.scala", "ListsValueObjectsADMSpec.scala", + "UsersValueObjectsADMSpec.scala", "ValueObjectsADMSpec.scala", ], data = [ diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADMSpec.scala deleted file mode 100644 index 1e55be100d..0000000000 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/IriValueObjectsADMSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.knora.webapi.messages.admin.responder.valueObjects - -import org.knora.webapi.UnitSpec -import org.knora.webapi.exceptions.BadRequestException -import org.knora.webapi.messages.admin.responder.listsmessages.ListsErrorMessagesADM._ -import zio.prelude.Validation - -/** - * This spec is used to test the [[IriValueObjectsADM]] value objects creation. - */ -class IriValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { - "ProjectIRI value object" when { -// TODO: check string formatter project iri validation because passing just "http://rdfh.ch/projects/@@@@@@" works - val validProjectIri = "http://rdfh.ch/projects/0001" - - "created using empty value" should { - "throw BadRequestException" in { - ProjectIRI.make("") should equal(Validation.fail(BadRequestException(PROJECT_IRI_MISSING_ERROR))) - } - } - "created using invalid value" should { - "throw BadRequestException" in { - ProjectIRI.make("not a project IRI") should equal( - Validation.fail(BadRequestException(PROJECT_IRI_INVALID_ERROR)) - ) - } - } - "created using valid value" should { - "not throw BadRequestExceptions" in { - ProjectIRI.make(validProjectIri) should not equal Validation.fail( - BadRequestException(PROJECT_IRI_INVALID_ERROR) - ) - } - "return value passed to value object" in { - ProjectIRI.make(validProjectIri).toOption.get.value should equal(validProjectIri) - } - } - } -} diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADMSpec.scala new file mode 100644 index 0000000000..15e4583002 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/ProjectsValueObjectsADMSpec.scala @@ -0,0 +1,207 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.UnitSpec +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsErrorMessagesADM._ +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 +import zio.prelude.Validation + +/** + * This spec is used to test the [[ProjectsValueObjectsADM]] value objects creation. + */ +class ProjectsValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { + "ProjectIRI value object" when { + val validProjectIri = "http://rdfh.ch/projects/0001" + + "created using empty value" should { + "throw BadRequestException" in { + ProjectIRI.make("") should equal(Validation.fail(BadRequestException(PROJECT_IRI_MISSING_ERROR))) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + ProjectIRI.make("not a project IRI") should equal( + Validation.fail(BadRequestException(PROJECT_IRI_INVALID_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + ProjectIRI.make(validProjectIri) should not equal Validation.fail( + BadRequestException(PROJECT_IRI_INVALID_ERROR) + ) + } + "return value passed to value object" in { + ProjectIRI.make(validProjectIri).toOption.get.value should equal(validProjectIri) + ProjectIRI.make(validProjectIri) should not equal Validation.fail( + BadRequestException(PROJECT_IRI_INVALID_ERROR) + ) + } + } + } + + "Shortcode value object" when { + val validShortcode = "1234" + val invalidShortcode = "12345" + + "created using empty value" should { + "throw BadRequestException" in { + Shortcode.make("") should equal( + Validation.fail(BadRequestException(SHORTCODE_MISSING_ERROR)) + ) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + Shortcode.make(invalidShortcode) should equal( + Validation.fail(BadRequestException(SHORTCODE_INVALID_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Shortcode.make(validShortcode).toOption.get.value should not equal + BadRequestException(SHORTCODE_INVALID_ERROR) + } + "return value passed to value object" in { + Shortcode.make(validShortcode).toOption.get.value should equal(validShortcode) + } + } + } + + "Shortname value object" when { + val validShortname = "validShortname" + val invalidShortname = "~!@#$%^&*()_+" + + "created using empty value" should { + "throw BadRequestException" in { + Shortname.make("") should equal( + Validation.fail(BadRequestException(SHORTNAME_MISSING_ERROR)) + ) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + Shortname.make(invalidShortname) should equal( + Validation.fail(BadRequestException(SHORTNAME_INVALID_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Shortname.make(validShortname).toOption.get.value should not equal + BadRequestException(SHORTNAME_INVALID_ERROR) + } + "return value passed to value object" in { + Shortname.make(validShortname).toOption.get.value should equal(validShortname) + } + } + } + + "Longname value object" when { + val validLongname = "That's the project longname" + + "created using empty value" should { + "throw BadRequestException" in { + Longname.make("") should equal( + Validation.fail(BadRequestException(LONGNAME_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Longname.make(validLongname).toOption.get.value should not equal + BadRequestException(LONGNAME_INVALID_ERROR) + } + "return value passed to value object" in { + Longname.make(validLongname).toOption.get.value should equal(validLongname) + } + } + } + + "ProjectDescription value object" when { + val validProjectDescription = Seq(StringLiteralV2(value = "Valid description", language = Some("en"))) + + "created using empty value" should { + "throw BadRequestException" in { + ProjectDescription.make(Seq.empty) should equal( + Validation.fail(BadRequestException(PROJECT_DESCRIPTION_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + ProjectDescription.make(validProjectDescription).toOption.get.value should not equal + BadRequestException(PROJECT_DESCRIPTION_INVALID_ERROR) + } + "return value passed to value object" in { + ProjectDescription.make(validProjectDescription).toOption.get.value should equal(validProjectDescription) + } + } + } + + "Keywords value object" when { + val validKeywords = Seq("key", "word") + + "created using empty value" should { + "throw BadRequestException" in { + Keywords.make(Seq.empty) should equal( + Validation.fail(BadRequestException(KEYWORDS_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Keywords.make(validKeywords).toOption.get.value should not equal + BadRequestException(KEYWORDS_INVALID_ERROR) + } + "return value passed to value object" in { + Keywords.make(validKeywords).toOption.get.value should equal(validKeywords) + } + } + } + + "Logo value object" when { + val validLogo = "/fu/bar/baz.jpg" + + "created using empty value" should { + "throw BadRequestException" in { + Logo.make("") should equal( + Validation.fail(BadRequestException(LOGO_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Logo.make(validLogo).toOption.get.value should not equal + BadRequestException(LOGO_INVALID_ERROR) + } + "return value passed to value object" in { + Logo.make(validLogo).toOption.get.value should equal(validLogo) + } + } + } + + "ProjectSelfJoin value object" when { + "created using valid value" should { + "return value passed to value object" in { + ProjectSelfJoin.make(false).toOption.get.value should equal(false) + ProjectSelfJoin.make(true).toOption.get.value should equal(true) + } + } + } + + "ProjectStatus value object" when { + "created using valid value" should { + "return value passed to value object" in { + ProjectStatus.make(true).toOption.get.value should equal(true) + ProjectStatus.make(false).toOption.get.value should equal(false) + } + } + } +} diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADMSpec.scala new file mode 100644 index 0000000000..8116cc4867 --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/valueObjects/UsersValueObjectsADMSpec.scala @@ -0,0 +1,229 @@ +/* + * Copyright © 2021 Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.messages.admin.responder.valueObjects + +import org.knora.webapi.UnitSpec +import org.knora.webapi.exceptions.BadRequestException +import org.knora.webapi.messages.admin.responder.usersmessages.UsersErrorMessagesADM._ +import zio.prelude.Validation + +/** + * This spec is used to test the [[UsersValueObjectsADM]] value objects creation. + */ +class UsersValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { + "UserIRI value object" when { + val validUserIRI = "http://rdfh.ch/users/jDEEitJESRi3pDaDjjQ1WQ" + + "created using empty value" should { + "throw BadRequestException" in { + UserIRI.make("") should equal(Validation.fail(BadRequestException(USER_IRI_MISSING_ERROR))) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + UserIRI.make("not a user IRI") should equal(Validation.fail(BadRequestException(USER_IRI_INVALID_ERROR))) + } + } + "created using valid value" should { + "not throw BadRequestException" in { + UserIRI.make(validUserIRI) should not equal Validation.fail(BadRequestException(USER_IRI_INVALID_ERROR)) + } + "return value passed to value object" in { + UserIRI.make(validUserIRI).toOption.get.value should equal(validUserIRI) + } + } + } + + "Username value object" when { + val validUsername = "user008" + val invalidUsername = "user!@#$%^&*()_+" + + "created using empty value" should { + "throw BadRequestException" in { + Username.make("") should equal(Validation.fail(BadRequestException(USERNAME_MISSING_ERROR))) + } + } + "created using invalid value" should { + "throw BadRequestException for username less than 4 characters long" in { + Username.make("123") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username containg more than 50 characters" in { + Username.make("01234567890123456789012345678901234567890123456789011") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username started with underscore" in { + Username.make("_123") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username ended with underscore" in { + Username.make("123_") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username started with dot" in { + Username.make(".123") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username ended with dot" in { + Username.make("123.") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username with underscore used multiple times in a row" in { + Username.make("1__23") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username with dot used multiple times in a row" in { + Username.make("1..23") should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + "throw BadRequestException for username created with bad forbidden characters" in { + Username.make(invalidUsername) should equal( + Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + ) + } + } + "created using valid characters" should { + "not throw BadRequestExceptions" in { + Username.make(validUsername) should not equal Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + } + "return value passed to value object" in { + Username.make(validUsername).toOption.get.value should equal(validUsername) + } + } + } + + "Email value object" when { + val validEmailAddress = "address@ch" + val invalidEmailAddress = "invalid_email_address" + + "created using empty value" should { + "throw BadRequestException" in { + Email.make("") should equal( + Validation.fail(BadRequestException(EMAIL_MISSING_ERROR)) + ) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + Email.make(invalidEmailAddress) should equal( + Validation.fail(BadRequestException(EMAIL_INVALID_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + Email.make(validEmailAddress).toOption.get.value should not equal + BadRequestException(EMAIL_INVALID_ERROR) + } + "return value passed to value object" in { + Email.make(validEmailAddress).toOption.get.value should equal(validEmailAddress) + } + } + } + + "Password value object" when { + val validassword = "pass-word" + + "created using empty value" should { + "throw BadRequestException" in { + Password.make("") should equal(Validation.fail(BadRequestException(PASSWORD_MISSING_ERROR))) + } + } + "created using valid characters" should { + "not throw BadRequestExceptions" in { + Password.make(validassword) should not equal Validation.fail(BadRequestException(USERNAME_INVALID_ERROR)) + } + "return value passed to value object" in { + Password.make(validassword).toOption.get.value should equal(validassword) + } + } + } + + "GivenName value object" when { + val validGivenName = "John" + + "created using empty value" should { + "throw BadRequestException" in { + GivenName.make("") should equal( + Validation.fail(BadRequestException(GIVEN_NAME_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + GivenName.make(validGivenName).toOption.get.value should not equal + BadRequestException(GIVEN_NAME_INVALID_ERROR) + } + "return value passed to value object" in { + GivenName.make(validGivenName).toOption.get.value should equal(validGivenName) + } + } + } + + "FamilyName value object" when { + val validFamilyName = "Rambo" + + "created using empty value" should { + "throw BadRequestException" in { + FamilyName.make("") should equal( + Validation.fail(BadRequestException(FAMILY_NAME_MISSING_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + FamilyName.make(validFamilyName).toOption.get.value should not equal + BadRequestException(FAMILY_NAME_INVALID_ERROR) + } + "return value passed to value object" in { + FamilyName.make(validFamilyName).toOption.get.value should equal(validFamilyName) + } + } + } + + "LanguageCode value object" when { + "created using empty value" should { + "throw BadRequestException" in { + LanguageCode.make("") should equal( + Validation.fail(BadRequestException(LANGUAGE_CODE_MISSING_ERROR)) + ) + } + } + "created using invalid value" should { + "throw BadRequestException" in { + LanguageCode.make("kk") should equal( + Validation.fail(BadRequestException(LANGUAGE_CODE_INVALID_ERROR)) + ) + } + } + "created using valid value" should { + "not throw BadRequestExceptions" in { + LanguageCode.make("de").toOption.get.value should not equal + BadRequestException(LANGUAGE_CODE_INVALID_ERROR) + } + "return value passed to value object" in { + LanguageCode.make("en").toOption.get.value should equal("en") + } + } + } + + "SystemAdmin value object" when { + "created using valid value" should { + "return value passed to value object" in { + SystemAdmin.make(true).toOption.get.value should equal(true) + SystemAdmin.make(false).toOption.get.value should equal(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 642923c12a..52e2656c12 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 @@ -4,13 +4,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.{CreateUserApiRequestADM, UserCreatePayloadADM} -import org.knora.webapi.{IRI, UnitSpec} -import org.scalatest.enablers.Messaging.messagingNatureOfThrowable object ValueObjectsADMSpec { val config: Config = ConfigFactory.parseString(""" @@ -18,199 +12,3 @@ object ValueObjectsADMSpec { akka.stdout-loglevel = "DEBUG" """.stripMargin) } - -/** - * This spec is used to test the creation of value objects of the [[ValueObject]] trait. - */ -class ValueObjectsADMSpec extends UnitSpec(ValueObjectsADMSpec.config) { - - private implicit val stringFormatter: StringFormatter = StringFormatter.getInstanceForConstantOntologies - - /** - * Convenience method returning the UserCreatePayloadADM from the [[CreateUserApiRequestADM]] object - * - * @param createUserApiRequestADM the [[CreateUserApiRequestADM]] object - * @return a [[UserCreatePayloadADM]] - */ - private def createUserCreatePayloadADM(createUserApiRequestADM: CreateUserApiRequestADM): UserCreatePayloadADM = - UserCreatePayloadADM.create( - id = stringFormatter - .validateOptionalUserIri(createUserApiRequestADM.id, throw BadRequestException(s"Invalid user IRI")), - username = Username.create(createUserApiRequestADM.username).fold(error => throw error, value => value), - email = Email.create(createUserApiRequestADM.email).fold(error => throw error, value => value), - givenName = GivenName.create(createUserApiRequestADM.givenName).fold(error => throw error, value => value), - familyName = FamilyName.create(createUserApiRequestADM.familyName).fold(error => throw error, value => value), - password = Password.create(createUserApiRequestADM.password).fold(error => throw error, value => value), - status = Status.make(createUserApiRequestADM.status).fold(error => throw error.head, value => value), - lang = LanguageCode.create(createUserApiRequestADM.lang).fold(error => throw error, value => value), - systemAdmin = SystemAdmin.create(createUserApiRequestADM.systemAdmin).fold(error => throw error, value => value) - ) - - /** - * Convenience method returning the [[CreateUserApiRequestADM]] object - * - * @param id the optional IRI of the user to be created (unique). - * @param username the username of the user to be created (unique). - * @param email the email of the user to be created (unique). - * @param givenName the given name of the user to be created. - * @param familyName the family name of the user to be created - * @param password the password of the user to be created. - * @param status the status of the user to be created (active = true, inactive = false). - * @param lang the default language of the user to be created. - * @param systemAdmin the system admin membership. - * @return a [[UserCreatePayloadADM]] - */ - private def createUserApiRequestADM( - id: Option[IRI] = None, - username: String = "donald.duck", - email: String = "donald.duck@example.com", - givenName: String = "Donald", - familyName: String = "Duck", - password: String = "test", - status: Boolean = true, - lang: String = "en", - systemAdmin: Boolean = false - ): CreateUserApiRequestADM = - CreateUserApiRequestADM( - id = id, - username = username, - email = email, - givenName = givenName, - familyName = familyName, - password = password, - status = status, - lang = lang, - systemAdmin = systemAdmin - ) - - "When the UserCreatePayloadADM case class is created it" should { - "create a valid UserCreatePayloadADM" in { - - val request = createUserApiRequestADM() - - val userCreatePayloadADM = createUserCreatePayloadADM(request) - - userCreatePayloadADM.id should equal(request.id) - userCreatePayloadADM.username.get.value should equal(request.username) - userCreatePayloadADM.email.get.value should equal(request.email) - userCreatePayloadADM.password.get.value should equal(request.password) - userCreatePayloadADM.givenName.get.value should equal(request.givenName) - userCreatePayloadADM.familyName.get.value should equal(request.familyName) - userCreatePayloadADM.status.get.value should equal(request.status) - userCreatePayloadADM.lang.get.value should equal(request.lang) - userCreatePayloadADM.systemAdmin.get.value should equal(request.systemAdmin) - - val otherRequest = createUserApiRequestADM( - id = Some("http://rdfh.ch/users/notdonald"), - username = "not.donald.duck", - email = "not.donald.duck@example.com", - givenName = "NotDonald", - familyName = "NotDuck", - password = "notDonaldDuckTest", - status = false, - lang = "de", - systemAdmin = true - ) - - val otherUserCreatePayloadADM = createUserCreatePayloadADM(otherRequest) - - otherUserCreatePayloadADM.id should equal(otherRequest.id) - otherUserCreatePayloadADM.username.get.value should equal(otherRequest.username) - otherUserCreatePayloadADM.email.get.value should equal(otherRequest.email) - otherUserCreatePayloadADM.password.get.value should equal(otherRequest.password) - otherUserCreatePayloadADM.givenName.get.value should equal(otherRequest.givenName) - otherUserCreatePayloadADM.familyName.get.value should equal(otherRequest.familyName) - otherUserCreatePayloadADM.status.get.value should equal(otherRequest.status) - otherUserCreatePayloadADM.lang.get.value should equal(otherRequest.lang) - otherUserCreatePayloadADM.systemAdmin.get.value should equal(otherRequest.systemAdmin) - - otherUserCreatePayloadADM.id should not equal request.id - otherUserCreatePayloadADM.username.get.value should not equal request.username - otherUserCreatePayloadADM.email.get.value should not equal request.email - otherUserCreatePayloadADM.password.get.value should not equal request.password - otherUserCreatePayloadADM.givenName.get.value should not equal request.givenName - otherUserCreatePayloadADM.familyName.get.value should not equal request.familyName - otherUserCreatePayloadADM.status.get.value should not equal request.status - otherUserCreatePayloadADM.lang.get.value should not equal request.lang - otherUserCreatePayloadADM.systemAdmin.get.value should not equal request.systemAdmin - } - - "throw 'BadRequestException' if 'username' is missing" in { - val request = createUserApiRequestADM(username = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing username" - } - - "throw 'BadRequestException' if 'email' is missing" in { - val request = createUserApiRequestADM(email = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing email" - } - - "throw 'BadRequestException' if 'password' is missing" in { - val request = createUserApiRequestADM(password = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing password" - } - - "throw 'BadRequestException' if 'givenName' is missing" in { - val request = createUserApiRequestADM(givenName = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing given name" - } - - "throw 'BadRequestException' if 'familyName' is missing" in { - val request = createUserApiRequestADM(familyName = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing family name" - } - - "throw 'BadRequestException' if 'lang' is missing" in { - val request = createUserApiRequestADM(lang = "") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Missing language code" - } - - "throw 'BadRequestException' if the supplied 'id' is not a valid IRI" in { - val request = createUserApiRequestADM(id = Some("invalid-iri")) - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Invalid user IRI" - - } - - "throw 'BadRequestException' if 'username' is invalid" in { - Set( - createUserApiRequestADM(username = "don"), // too short - createUserApiRequestADM(username = "asdfoiasdfasdnlasdkjflasdjfaskdjflaskdjfaddssdskdfjs"), // too long - createUserApiRequestADM(username = "_donald"), // starts with _ - createUserApiRequestADM(username = ".donald"), // starts with . - createUserApiRequestADM(username = "donald_"), // ends with _ - createUserApiRequestADM(username = "donald."), // ends with . - createUserApiRequestADM(username = "donald__duck"), // contains multiple _ - createUserApiRequestADM(username = "donald..duck"), // contains multiple . - createUserApiRequestADM(username = "donald#duck"), // contains not only alphanumeric characters - createUserApiRequestADM(username = "dönälddück") // contains umlaut characters - ).map(request => - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Invalid username" - ) - } - - "throw 'BadRequestException' if 'email' is invalid" in { - Set( - createUserApiRequestADM(email = "don"), // does not contain @ - createUserApiRequestADM(email = "don@"), // ends with @ - createUserApiRequestADM(email = "@don") // starts with @ - ).map(request => - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Invalid email" - ) - } - - "throw 'BadRequestException' if 'lang' is invalid" in { - val request = createUserApiRequestADM(lang = "xy") - - the[BadRequestException] thrownBy createUserCreatePayloadADM(request) should have message "Invalid language code" - } - - } - -} 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 3f12a536a3..ba7476210d 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 @@ -9,39 +9,21 @@ */ 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} import org.knora.webapi._ import org.knora.webapi.exceptions.{BadRequestException, DuplicateValueException, NotFoundException} - -import org.knora.webapi.messages.{OntologyConstants, StringFormatter} -import org.knora.webapi.messages.admin.responder.permissionsmessages.{ - AdministrativePermissionADM, - AdministrativePermissionsForProjectGetRequestADM, - AdministrativePermissionsForProjectGetResponseADM, - DefaultObjectAccessPermissionADM, - DefaultObjectAccessPermissionsForProjectGetRequestADM, - DefaultObjectAccessPermissionsForProjectGetResponseADM, - PermissionADM -} +import org.knora.webapi.messages.admin.responder.permissionsmessages._ import org.knora.webapi.messages.admin.responder.projectsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.UserInformationTypeADM -import org.knora.webapi.messages.admin.responder.valueObjects.{ - Description, - Keywords, - Logo, - Longname, - Selfjoin, - Shortcode, - Shortname, - Status -} +import org.knora.webapi.messages.admin.responder.valueObjects._ import org.knora.webapi.messages.store.triplestoremessages._ +import org.knora.webapi.messages.{OntologyConstants, StringFormatter} import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.util.MutableTestIri +import java.util.UUID import scala.concurrent.duration._ object ProjectsResponderADMSpec { @@ -63,11 +45,8 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) private val rootUser = SharedTestDataADM.rootUser "The ProjectsResponderADM" when { - "used to query for project information" should { - "return information for every project" in { - responderManager ! ProjectsGetRequestADM( featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = rootUser @@ -79,7 +58,6 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) } "return information about a project identified by IRI" in { - /* Incunabula project */ responderManager ! ProjectGetRequestADM( identifier = ProjectIdentifierADM(maybeIri = Some(SharedTestDataADM.incunabulaProject.id)), @@ -116,7 +94,6 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) } "return 'NotFoundException' when the project IRI is unknown" in { - responderManager ! ProjectGetRequestADM( identifier = ProjectIdentifierADM(maybeIri = Some("http://rdfh.ch/projects/notexisting")), featureFactoryConfig = defaultFeatureFactoryConfig, @@ -146,7 +123,6 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) } "used to query project's restricted view settings" should { - val expectedResult = ProjectRestrictedViewSettingsADM(size = Some("!512,512"), watermark = Some("path_to_image")) "return restricted view settings using project IRI" in { @@ -206,7 +182,6 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) } "used to modify project information" should { - val newProjectIri = new MutableTestIri "CREATE a project and return the project info if the supplied shortname is unique" in { @@ -216,13 +191,13 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) shortname = Shortname.make("newproject").fold(error => throw error.head, value => value), shortcode = Shortcode.make(shortCode).fold(error => throw error.head, value => value), // lower case longname = Longname.make(Some("project longname")).fold(error => throw error.head, value => value), - description = Description + description = ProjectDescription .make(Seq(StringLiteralV2(value = "project description", language = Some("en")))) .fold(error => throw error.head, value => value), keywords = Keywords.make(Seq("keywords")).fold(error => throw error.head, value => value), logo = Logo.make(Some("/fu/bar/baz.jpg")).fold(error => throw error.head, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - selfjoin = Selfjoin.make(false).fold(error => throw error.head, value => value) + status = ProjectStatus.make(true).fold(error => throw error.head, value => value), + selfjoin = ProjectSelfJoin.make(false).fold(error => throw error.head, value => value) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.rootUser, @@ -314,13 +289,13 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) shortname = Shortname.make("newproject2").fold(error => throw error.head, value => value), shortcode = Shortcode.make("1112").fold(error => throw error.head, value => value), // lower case longname = Some(Longname.make("project longname").fold(error => throw error.head, value => value)), - description = Description + description = ProjectDescription .make(Seq(StringLiteralV2(value = "project description", language = Some("en")))) .fold(error => throw error.head, value => value), keywords = Keywords.make(Seq("keywords")).fold(error => throw error.head, value => value), logo = Logo.make(Some("/fu/bar/baz.jpg")).fold(error => throw error.head, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - selfjoin = Selfjoin.make(false).fold(error => throw error.head, value => value) + status = ProjectStatus.make(true).fold(error => throw error.head, value => value), + selfjoin = ProjectSelfJoin.make(false).fold(error => throw error.head, value => value) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.rootUser, @@ -348,13 +323,13 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) shortcode = Shortcode.make("1312").fold(error => throw error.head, value => value), // lower case longname = Longname.make(Some(longnameWithSpecialCharacter)).fold(error => throw error.head, value => value), - description = Description + description = ProjectDescription .make(Seq(StringLiteralV2(value = descriptionWithSpecialCharacter, language = Some("en")))) .fold(error => throw error.head, value => value), keywords = Keywords.make(Seq(keywordWithSpecialCharacter)).fold(error => throw error.head, value => value), logo = Logo.make(Some("/fu/bar/baz.jpg")).fold(error => throw error.head, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - selfjoin = Selfjoin.make(false).fold(error => throw error.head, value => value) + status = ProjectStatus.make(true).fold(error => throw error.head, value => value), + selfjoin = ProjectSelfJoin.make(false).fold(error => throw error.head, value => value) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.rootUser, @@ -381,13 +356,13 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) shortname = Shortname.make("newproject").fold(error => throw error.head, value => value), shortcode = Shortcode.make("111C").fold(error => throw error.head, value => value), // lower case longname = Longname.make(Some("project longname")).fold(error => throw error.head, value => value), - description = Description + description = ProjectDescription .make(Seq(StringLiteralV2(value = "project description", language = Some("en")))) .fold(error => throw error.head, value => value), keywords = Keywords.make(Seq("keywords")).fold(error => throw error.head, value => value), logo = Logo.make(Some("/fu/bar/baz.jpg")).fold(error => throw error.head, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - selfjoin = Selfjoin.make(false).fold(error => throw error.head, value => value) + status = ProjectStatus.make(true).fold(error => throw error.head, value => value), + selfjoin = ProjectSelfJoin.make(false).fold(error => throw error.head, value => value) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.rootUser, @@ -402,13 +377,13 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) shortname = Shortname.make("newproject3").fold(error => throw error.head, value => value), shortcode = Shortcode.make("111C").fold(error => throw error.head, value => value), // lower case longname = Longname.make(Some("project longname")).fold(error => throw error.head, value => value), - description = Description + description = ProjectDescription .make(Seq(StringLiteralV2(value = "project description", language = Some("en")))) .fold(error => throw error.head, value => value), keywords = Keywords.make(Seq("keywords")).fold(error => throw error.head, value => value), logo = Logo.make(Some("/fu/bar/baz.jpg")).fold(error => throw error.head, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - selfjoin = Selfjoin.make(false).fold(error => throw error.head, value => value) + status = ProjectStatus.make(true).fold(error => throw error.head, value => value), + selfjoin = ProjectSelfJoin.make(false).fold(error => throw error.head, value => value) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.rootUser, @@ -724,5 +699,4 @@ class ProjectsResponderADMSpec extends CoreSpec(ProjectsResponderADMSpec.config) } } } - } 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 0e5daf9a27..ebaa53bc68 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 @@ -21,9 +21,9 @@ import org.knora.webapi.messages.admin.responder.valueObjects.{ GivenName, FamilyName, Password, - Status, LanguageCode, - SystemAdmin + SystemAdmin, + UserStatus } import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.messages.v2.routing.authenticationmessages.KnoraCredentialsV2.KnoraPasswordCredentialsV2 @@ -59,7 +59,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance "The UsersResponder " when { - "asked about all users" should { "return a list if asked by SystemAdmin" in { responderManager ! UsersGetRequestADM( @@ -103,7 +102,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked about an user identified by 'iri' " should { - "return a profile if the user (root user) is known" in { responderManager ! UserGetADM( identifier = UserIdentifierADM(maybeIri = Some(rootUser.id)), @@ -146,7 +144,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked about an user identified by 'email'" should { - "return a profile if the user (root user) is known" in { responderManager ! UserGetADM( identifier = UserIdentifierADM(maybeEmail = Some(rootUser.email)), @@ -189,7 +186,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked about an user identified by 'username'" should { - "return a profile if the user (root user) is known" in { responderManager ! UserGetADM( identifier = UserIdentifierADM(maybeUsername = Some(rootUser.username)), @@ -232,20 +228,17 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked to create a new user" should { - "CREATE the user and return it's profile if the supplied email is unique " in { responderManager ! UserCreateRequestADM( - userCreatePayloadADM = UserCreatePayloadADM.create( - username = Username.create("donald.duck").fold(error => throw error, value => value), - email = Email - .create("donald.duck@example.com") - .fold(error => throw error, value => value), - givenName = GivenName.create("Donald").fold(error => throw error, value => value), - familyName = FamilyName.create("Duck").fold(error => throw error, value => value), - password = Password.create("test").fold(error => throw error, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - lang = LanguageCode.create("en").fold(error => throw error, value => value), - systemAdmin = SystemAdmin.create(false).fold(error => throw error, value => value) + userCreatePayloadADM = UserCreatePayloadADM( + username = Username.make("donald.duck").fold(e => throw e.head, v => v), + email = Email.make("donald.duck@example.com").fold(e => throw e.head, v => v), + givenName = GivenName.make("Donald").fold(e => throw e.head, v => v), + familyName = FamilyName.make("Duck").fold(e => throw e.head, v => v), + password = Password.make("test").fold(e => throw e.head, v => v), + status = UserStatus.make(true).fold(error => throw error.head, value => value), + lang = LanguageCode.make("en").fold(e => throw e.head, v => v), + systemAdmin = SystemAdmin.make(false).fold(e => throw e.head, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.anonymousUser, @@ -262,17 +255,15 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with "return a 'DuplicateValueException' if the supplied 'username' is not unique" in { responderManager ! UserCreateRequestADM( - userCreatePayloadADM = UserCreatePayloadADM.create( - username = Username.create("root").fold(error => throw error, value => value), - email = Email - .create("root2@example.com") - .fold(error => throw error, value => value), - givenName = GivenName.create("Donald").fold(error => throw error, value => value), - familyName = FamilyName.create("Duck").fold(error => throw error, value => value), - password = Password.create("test").fold(error => throw error, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - lang = LanguageCode.create("en").fold(error => throw error, value => value), - systemAdmin = SystemAdmin.create(false).fold(error => throw error, value => value) + userCreatePayloadADM = UserCreatePayloadADM( + username = Username.make("root").fold(e => throw e.head, v => v), + email = Email.make("root2@example.com").fold(e => throw e.head, v => v), + givenName = GivenName.make("Donald").fold(e => throw e.head, v => v), + familyName = FamilyName.make("Duck").fold(e => throw e.head, v => v), + password = Password.make("test").fold(e => throw e.head, v => v), + status = UserStatus.make(true).fold(error => throw error.head, value => value), + lang = LanguageCode.make("en").fold(e => throw e.head, v => v), + systemAdmin = SystemAdmin.make(false).fold(e => throw e.head, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.anonymousUser, @@ -283,17 +274,15 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with "return a 'DuplicateValueException' if the supplied 'email' is not unique" in { responderManager ! UserCreateRequestADM( - userCreatePayloadADM = UserCreatePayloadADM.create( - username = Username.create("root2").fold(error => throw error, value => value), - email = Email - .create("root@example.com") - .fold(error => throw error, value => value), - givenName = GivenName.create("Donald").fold(error => throw error, value => value), - familyName = FamilyName.create("Duck").fold(error => throw error, value => value), - password = Password.create("test").fold(error => throw error, value => value), - status = Status.make(true).fold(error => throw error.head, value => value), - lang = LanguageCode.create("en").fold(error => throw error, value => value), - systemAdmin = SystemAdmin.create(false).fold(error => throw error, value => value) + userCreatePayloadADM = UserCreatePayloadADM( + username = Username.make("root2").fold(e => throw e.head, v => v), + email = Email.make("root@example.com").fold(e => throw e.head, v => v), + givenName = GivenName.make("Donald").fold(e => throw e.head, v => v), + familyName = FamilyName.make("Duck").fold(e => throw e.head, v => v), + password = Password.make("test").fold(e => throw e.head, v => v), + status = UserStatus.make(true).fold(error => throw error.head, value => value), + lang = LanguageCode.make("en").fold(e => throw e.head, v => v), + systemAdmin = SystemAdmin.make(false).fold(e => throw e.head, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, SharedTestDataADM.anonymousUser, @@ -304,14 +293,12 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked to update a user" should { - "UPDATE the user's basic information" in { - /* User information is updated by the user */ responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( - givenName = Some(GivenName.create("Donald").fold(error => throw error, value => value)) + givenName = Some(GivenName.make("Donald").fold(e => throw e.head, v => v)) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.normalUser, @@ -325,7 +312,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( - familyName = Some(FamilyName.create("Duck").fold(error => throw error, value => value)) + familyName = Some(FamilyName.make("Duck").fold(e => throw e.head, v => v)) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, @@ -339,11 +326,8 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( - givenName = - Some(GivenName.create(SharedTestDataADM.normalUser.givenName).fold(error => throw error, value => value)), - familyName = Some( - FamilyName.create(SharedTestDataADM.normalUser.familyName).fold(error => throw error, value => value) - ) + givenName = Some(GivenName.make(SharedTestDataADM.normalUser.givenName).fold(e => throw e.head, v => v)), + familyName = Some(FamilyName.make(SharedTestDataADM.normalUser.familyName).fold(e => throw e.head, v => v)) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, @@ -357,7 +341,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with "return a 'DuplicateValueException' if the supplied 'username' is not unique" in { val duplicateUsername = - Some(Username.create(SharedTestDataADM.anythingUser1.username).fold(error => throw error, value => value)) + Some(Username.make(SharedTestDataADM.anythingUser1.username).fold(e => throw e.head, v => v)) responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( @@ -377,8 +361,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return a 'DuplicateValueException' if the supplied 'email' is not unique" in { - val duplicateEmail = - Some(Email.create(SharedTestDataADM.anythingUser1.email).fold(error => throw error, value => value)) + val duplicateEmail = Some(Email.make(SharedTestDataADM.anythingUser1.email).fold(e => throw e.head, v => v)) responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( @@ -396,8 +379,8 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "UPDATE the user's password (by himself)" in { - val requesterPassword = Password.create("test").fold(error => throw error, value => value) - val newPassword = Password.create("test123456").fold(error => throw error, value => value) + val requesterPassword = Password.make("test").fold(e => throw e.head, v => v) + val newPassword = Password.make("test123456").fold(e => throw e.head, v => v) responderManager ! UserChangePasswordRequestADM( userIri = SharedTestDataADM.normalUser.id, userUpdatePasswordPayload = UserUpdatePasswordPayloadADM( @@ -424,8 +407,8 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "UPDATE the user's password (by a system admin)" in { - val requesterPassword = Password.create("test").fold(error => throw error, value => value) - val newPassword = Password.create("test654321").fold(error => throw error, value => value) + val requesterPassword = Password.make("test").fold(e => throw e.head, v => v) + val newPassword = Password.make("test654321").fold(e => throw e.head, v => v) responderManager ! UserChangePasswordRequestADM( userIri = SharedTestDataADM.normalUser.id, @@ -455,7 +438,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with "UPDATE the user's status, (deleting) making him inactive " in { responderManager ! UserChangeStatusRequestADM( userIri = SharedTestDataADM.normalUser.id, - status = Status.make(false).fold(error => throw error.head, value => value), + status = UserStatus.make(false).fold(error => throw error.head, value => value), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -466,7 +449,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with responderManager ! UserChangeStatusRequestADM( userIri = SharedTestDataADM.normalUser.id, - status = Status.make(true).fold(error => throw error.head, value => value), + status = UserStatus.make(true).fold(error => throw error.head, value => value), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -479,7 +462,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with "UPDATE the user's system admin membership" in { responderManager ! UserChangeSystemAdminMembershipStatusRequestADM( userIri = SharedTestDataADM.normalUser.id, - systemAdmin = SystemAdmin.create(true).fold(error => throw error, value => value), + systemAdmin = SystemAdmin.make(true).fold(e => throw e.head, v => v), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -490,7 +473,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with responderManager ! UserChangeSystemAdminMembershipStatusRequestADM( userIri = SharedTestDataADM.normalUser.id, - systemAdmin = SystemAdmin.create(false).fold(error => throw error, value => value), + systemAdmin = SystemAdmin.make(false).fold(e => throw e.head, v => v), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -501,13 +484,12 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return a 'ForbiddenException' if the user requesting update is not the user itself or system admin" in { - /* User information is updated by other normal user */ responderManager ! UserChangeBasicInformationRequestADM( userIri = SharedTestDataADM.superUser.id, userUpdateBasicInformationPayload = UserUpdateBasicInformationPayloadADM( email = None, - givenName = Some(GivenName.create("Donald").fold(error => throw error, value => value)), + givenName = Some(GivenName.make("Donald").fold(e => throw e.head, v => v)), familyName = None, lang = None ), @@ -526,8 +508,8 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with responderManager ! UserChangePasswordRequestADM( userIri = SharedTestDataADM.superUser.id, userUpdatePasswordPayload = UserUpdatePasswordPayloadADM( - requesterPassword = Password.create("test").fold(error => throw error, value => value), - newPassword = Password.create("test123456").fold(error => throw error, value => value) + requesterPassword = Password.make("test").fold(e => throw e.head, v => v), + newPassword = Password.make("test123456").fold(e => throw e.head, v => v) ), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.normalUser, @@ -543,7 +525,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with /* Status is updated by other normal user */ responderManager ! UserChangeStatusRequestADM( userIri = SharedTestDataADM.superUser.id, - status = Status.make(false).fold(error => throw error.head, value => value), + status = UserStatus.make(false).fold(error => throw error.head, value => value), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.normalUser, UUID.randomUUID @@ -556,7 +538,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with /* System admin group membership */ responderManager ! UserChangeSystemAdminMembershipStatusRequestADM( userIri = SharedTestDataADM.normalUser.id, - systemAdmin = SystemAdmin.create(true).fold(error => throw error, value => value), + systemAdmin = SystemAdmin.make(true).fold(e => throw e.head, v => v), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.normalUser, UUID.randomUUID() @@ -568,10 +550,9 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return 'BadRequest' if system user is requested to change" in { - responderManager ! UserChangeStatusRequestADM( userIri = KnoraSystemInstances.Users.SystemUser.id, - status = Status.make(false).fold(error => throw error.head, value => value), + status = UserStatus.make(false).fold(error => throw error.head, value => value), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -581,10 +562,9 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return 'BadRequest' if anonymous user is requested to change" in { - responderManager ! UserChangeStatusRequestADM( userIri = KnoraSystemInstances.Users.AnonymousUser.id, - status = Status.make(false).fold(error => throw error.head, value => value), + status = UserStatus.make(false).fold(error => throw error.head, value => value), featureFactoryConfig = defaultFeatureFactoryConfig, requestingUser = SharedTestDataADM.superUser, UUID.randomUUID() @@ -595,9 +575,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked to update the user's project membership" should { - "ADD user to project" in { - responderManager ! UserProjectMembershipsGetRequestADM(normalUser.id, defaultFeatureFactoryConfig, rootUser) val membershipsBeforeUpdate = expectMsgType[UserProjectMembershipsGetResponseADM](timeout) membershipsBeforeUpdate.projects should equal(Seq()) @@ -626,7 +604,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "DELETE user from project" in { - responderManager ! UserProjectMembershipsGetRequestADM(normalUser.id, defaultFeatureFactoryConfig, rootUser) val membershipsBeforeUpdate = expectMsgType[UserProjectMembershipsGetResponseADM](timeout) membershipsBeforeUpdate.projects should equal(Seq(imagesProject)) @@ -655,7 +632,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return a 'ForbiddenException' if the user requesting update is not the project or system admin" in { - /* User is added to a project by a normal user */ responderManager ! UserProjectMembershipAddRequestADM( normalUser.id, @@ -690,9 +666,7 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked to update the user's project admin group membership" should { - "ADD user to project admin group" in { - responderManager ! UserProjectAdminMembershipsGetRequestADM( normalUser.id, defaultFeatureFactoryConfig, @@ -769,7 +743,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return a 'ForbiddenException' if the user requesting update is not the project or system admin" in { - /* User is added to a project by a normal user */ responderManager ! UserProjectAdminMembershipAddRequestADM( normalUser.id, @@ -808,7 +781,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "asked to update the user's group membership" should { - "ADD user to group" in { responderManager ! UserGroupMembershipsGetRequestADM(normalUser.id, defaultFeatureFactoryConfig, rootUser) val membershipsBeforeUpdate = expectMsgType[UserGroupMembershipsGetResponseADM](timeout) @@ -866,7 +838,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with } "return a 'ForbiddenException' if the user requesting update is not the project or system admin" in { - /* User is added to a project by a normal user */ responderManager ! UserGroupMembershipAddRequestADM( normalUser.id, @@ -897,7 +868,6 @@ class UsersResponderADMSpec extends CoreSpec(UsersResponderADMSpec.config) with ) ) } - } } }