diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala index 7b41a9b8a9..36de1ed587 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/GroupsResponderADMSpec.scala @@ -127,9 +127,9 @@ class GroupsResponderADMSpec extends CoreSpec { "UPDATE a group" in { val response = UnsafeZioRun.runOrThrow( - ZIO.serviceWithZIO[GroupsResponderADM]( - _.updateGroup( - groupIri = GroupIri.unsafeFrom(newGroupIri.get), + groupRestService( + _.putGroup( + GroupIri.unsafeFrom(newGroupIri.get), GroupUpdateRequest( name = Some(GroupName.unsafeFrom("UpdatedGroupName")), descriptions = Some( @@ -140,26 +140,26 @@ class GroupsResponderADMSpec extends CoreSpec { status = Some(GroupStatus.active), selfjoin = Some(GroupSelfJoin.disabled), ), - UUID.randomUUID, + rootUser, ), ), ) - val updatedGroupInfo = response.group - updatedGroupInfo.name should equal("UpdatedGroupName") - updatedGroupInfo.descriptions should equal( + val group = response.group + group.name should equal("UpdatedGroupName") + group.descriptions should equal( Seq(StringLiteralV2.from("""UpdatedDescription with "quotes" and """, Some("en"))), ) - updatedGroupInfo.project should equal(Some(imagesProject)) - updatedGroupInfo.status should equal(true) - updatedGroupInfo.selfjoin should equal(false) + group.project should equal(Some(imagesProjectExternal)) + group.status should equal(true) + group.selfjoin should equal(false) } "return 'NotFound' if a not-existing group IRI is submitted during update" in { val groupIri = "http://rdfh.ch/groups/0000/notexisting" val exit = UnsafeZioRun.run( - ZIO.serviceWithZIO[GroupsResponderADM]( - _.updateGroup( - groupIri = GroupIri.unsafeFrom(groupIri), + groupRestService( + _.putGroup( + GroupIri.unsafeFrom(groupIri), GroupUpdateRequest( name = Some(GroupName.unsafeFrom("UpdatedGroupName")), descriptions = Some( @@ -169,21 +169,21 @@ class GroupsResponderADMSpec extends CoreSpec { status = Some(GroupStatus.active), selfjoin = Some(GroupSelfJoin.disabled), ), - UUID.randomUUID, + rootUser, ), ), ) assertFailsWithA[NotFoundException]( exit, - s"Group <$groupIri> not found. Aborting update request.", + s"Group <$groupIri> not found.", ) } - "return 'BadRequest' if the new group name already exists inside the project" in { + "return 'DuplicateValueException' if the new group name already exists inside the project" in { val groupName = GroupName.unsafeFrom("Image reviewer") val exit = UnsafeZioRun.run( - ZIO.serviceWithZIO[GroupsResponderADM]( - _.updateGroup( + groupRestService( + _.putGroup( GroupIri.unsafeFrom(newGroupIri.get), GroupUpdateRequest( name = Some(groupName), @@ -194,11 +194,11 @@ class GroupsResponderADMSpec extends CoreSpec { status = Some(GroupStatus.active), selfjoin = Some(GroupSelfJoin.disabled), ), - UUID.randomUUID, + rootUser, ), ), ) - assertFailsWithA[BadRequestException]( + assertFailsWithA[DuplicateValueException]( exit, s"Group with name: '${groupName.value}' already exists.", ) @@ -206,11 +206,11 @@ class GroupsResponderADMSpec extends CoreSpec { "return 'BadRequest' if nothing would be changed during the update" in { val exit = UnsafeZioRun.run( - ZIO.serviceWithZIO[GroupsResponderADM]( - _.updateGroup( + groupRestService( + _.putGroup( GroupIri.unsafeFrom(newGroupIri.get), GroupUpdateRequest(None, None, None, None), - UUID.randomUUID, + rootUser, ), ), ) diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala index 3f74004810..42a8d569ae 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala @@ -181,25 +181,6 @@ final case class GroupsResponderADM( def groupMembersGetRequest(iri: GroupIri, user: User): Task[GroupMembersGetResponseADM] = groupMembersGetADM(iri.value, user).map(GroupMembersGetResponseADM.apply) - /** - * Change group's basic information. - * - * @param groupIri the IRI of the group we want to change. - * @param request the change request. - * @param apiRequestID the unique request ID. - * @return a [[GroupGetResponseADM]]. - */ - def updateGroup( - groupIri: GroupIri, - request: GroupUpdateRequest, - apiRequestID: UUID, - ): Task[GroupGetResponseADM] = { - val task = for { - result <- updateGroupHelper(groupIri, request) - } yield result - IriLocker.runWithIriLock(apiRequestID, groupIri.value, task) - } - /** * Change group's status. * diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupRestService.scala index 64c7d682e5..f616cc58b4 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/api/service/GroupRestService.scala @@ -7,6 +7,7 @@ package org.knora.webapi.slice.admin.api.service import zio._ +import dsp.errors.BadRequestException import dsp.errors.NotFoundException import org.knora.webapi.messages.admin.responder.groupsmessages._ import org.knora.webapi.messages.admin.responder.usersmessages.GroupMembersGetResponseADM @@ -61,9 +62,14 @@ final case class GroupRestService( def putGroup(iri: GroupIri, request: GroupUpdateRequest, user: User): Task[GroupGetResponseADM] = for { + _ <- ZIO + .fail(BadRequestException("No data would be changed. Aborting update request.")) + .when(List(request.name, request.descriptions, request.status, request.selfjoin).flatten.isEmpty) + groupToUpdate <- groupService + .findById(iri) + .someOrFail(NotFoundException(s"Group <${iri.value}> not found.")) _ <- auth.ensureSystemAdminOrProjectAdminOfGroup(user, iri) - uuid <- Random.nextUUID - internal <- responder.updateGroup(iri, request, uuid) + internal <- groupService.updateGroup(groupToUpdate, request).map(GroupGetResponseADM.apply) external <- format.toExternalADM(internal) } yield external diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala index a38d167193..e213c9a561 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupService.scala @@ -9,10 +9,16 @@ import zio.ZIO import zio._ import org.knora.webapi.slice.admin.api.GroupsRequests.GroupCreateRequest +import org.knora.webapi.slice.admin.api.GroupsRequests.GroupUpdateRequest import org.knora.webapi.slice.admin.domain.model.Group +import org.knora.webapi.slice.admin.domain.model.GroupDescriptions import org.knora.webapi.slice.admin.domain.model.GroupIri +import org.knora.webapi.slice.admin.domain.model.GroupName +import org.knora.webapi.slice.admin.domain.model.GroupSelfJoin +import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraGroup import org.knora.webapi.slice.admin.domain.model.KnoraProject +import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri final case class GroupService( private val knoraGroupService: KnoraGroupService, @@ -39,8 +45,21 @@ final case class GroupService( selfjoin = knoraGroup.hasSelfJoinEnabled.value, ) + private def toKnoraGroup(group: Group): KnoraGroup = + KnoraGroup( + id = GroupIri.unsafeFrom(group.id), + groupName = GroupName.unsafeFrom(group.name), + groupDescriptions = GroupDescriptions.unsafeFrom(group.descriptions), + status = GroupStatus.from(group.status), + belongsToProject = group.project.map(it => ProjectIri.unsafeFrom(it.id)), + hasSelfJoinEnabled = GroupSelfJoin.from(group.selfjoin), + ) + def createGroup(request: GroupCreateRequest, project: KnoraProject): Task[Group] = knoraGroupService.createGroup(request, project).flatMap(toGroup) + + def updateGroup(groupToUpdate: Group, request: GroupUpdateRequest): Task[Group] = + knoraGroupService.updateGroup(toKnoraGroup(groupToUpdate), request).flatMap(toGroup) } object GroupService { diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupService.scala index 4f71399f5b..ff6694e958 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupService.scala @@ -13,6 +13,7 @@ import zio.ZLayer import dsp.errors.DuplicateValueException import org.knora.webapi.responders.IriService import org.knora.webapi.slice.admin.api.GroupsRequests.GroupCreateRequest +import org.knora.webapi.slice.admin.api.GroupsRequests.GroupUpdateRequest import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.GroupName import org.knora.webapi.slice.admin.domain.model.KnoraGroup @@ -47,6 +48,24 @@ case class KnoraGroupService( _ <- knoraGroupRepo.save(group) } yield group + def updateGroup(groupToUpdate: KnoraGroup, request: GroupUpdateRequest): Task[KnoraGroup] = + for { + _ <- request.name match { + case Some(value) => ensureGroupNameIsUnique(value) + case None => ZIO.unit + } + + updatedGroup <- + knoraGroupRepo.save( + groupToUpdate.copy( + groupName = request.name.getOrElse(groupToUpdate.groupName), + groupDescriptions = request.descriptions.getOrElse(groupToUpdate.groupDescriptions), + status = request.status.getOrElse(groupToUpdate.status), + hasSelfJoinEnabled = request.selfjoin.getOrElse(groupToUpdate.hasSelfJoinEnabled), + ), + ) + } yield updatedGroup + private def ensureGroupNameIsUnique(name: GroupName) = ZIO.whenZIO(knoraGroupRepo.existsByName(name)) { ZIO.fail(DuplicateValueException(s"Group with name: '${name.value}' already exists."))