diff --git a/integration/src/test/scala/org/knora/webapi/core/LayersTest.scala b/integration/src/test/scala/org/knora/webapi/core/LayersTest.scala index 16e9143c79..18e6184aa9 100644 --- a/integration/src/test/scala/org/knora/webapi/core/LayersTest.scala +++ b/integration/src/test/scala/org/knora/webapi/core/LayersTest.scala @@ -37,8 +37,8 @@ import org.knora.webapi.slice.admin.api.service.ProjectsADMRestServiceLive import org.knora.webapi.slice.admin.api.service.StoreRestService import org.knora.webapi.slice.admin.api.service.UsersRestService import org.knora.webapi.slice.admin.domain.service.* +import org.knora.webapi.slice.admin.repo.service.KnoraGroupRepoLive import org.knora.webapi.slice.admin.repo.service.KnoraProjectRepoLive -import org.knora.webapi.slice.admin.repo.service.KnoraUserGroupRepoLive import org.knora.webapi.slice.admin.repo.service.KnoraUserRepoLive import org.knora.webapi.slice.common.api.* import org.knora.webapi.slice.common.repo.service.PredicateObjectMapper @@ -103,6 +103,7 @@ object LayersTest { with FilesEndpointsHandler with GravsearchTypeInspectionRunner with GroupsResponderADM + with GroupsService with HttpServer with IIIFRequestMessageHandler with InferenceOptimizationService @@ -173,6 +174,7 @@ object LayersTest { GroupsEndpointsHandler.layer, GroupsResponderADMLive.layer, GroupsRestServiceLive.layer, + GroupsService.layer, HandlerMapper.layer, HttpServer.layer, IIIFRequestMessageHandlerLive.layer, @@ -181,7 +183,7 @@ object LayersTest { IriService.layer, KnoraProjectRepoLive.layer, KnoraResponseRenderer.layer, - KnoraUserGroupRepoLive.layer, + KnoraGroupRepoLive.layer, KnoraUserRepoLive.layer, KnoraUserToUserConverter.layer, ListRestService.layer, diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala index 1570e2d9c0..53cd74bd1f 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/GroupsADME2ESpec.scala @@ -14,10 +14,10 @@ import org.knora.webapi.E2ESpec import org.knora.webapi.e2e.ClientTestDataCollector import org.knora.webapi.e2e.TestDataFileContent import org.knora.webapi.e2e.TestDataFilePath -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsADMJsonProtocol import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.sharedtestdata.SharedTestDataADM +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.util.AkkaHttpUtils import org.knora.webapi.util.MutableTestIri @@ -115,7 +115,7 @@ class GroupsADME2ESpec extends E2ESpec with GroupsADMJsonProtocol { response.status should be(StatusCodes.OK) - val result: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] + val result: Group = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[Group] // check that the custom IRI is correctly assigned result.id should be(customGroupIri) @@ -186,7 +186,7 @@ class GroupsADME2ESpec extends E2ESpec with GroupsADMJsonProtocol { // log.debug(s"response: {}", response) response.status should be(StatusCodes.OK) - val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] + val groupInfo: Group = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[Group] groupInfo.name should be("NewGroup") groupInfo.descriptions should be(Seq(StringLiteralV2("NewGroupDescription", Some("en")))) @@ -236,7 +236,7 @@ class GroupsADME2ESpec extends E2ESpec with GroupsADMJsonProtocol { logger.debug(s"response: {}", response) response.status should be(StatusCodes.OK) - val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] + val groupInfo: Group = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[Group] groupInfo.name should be("UpdatedGroupName") groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) @@ -265,7 +265,7 @@ class GroupsADME2ESpec extends E2ESpec with GroupsADMJsonProtocol { logger.debug(s"response: {}", response) response.status should be(StatusCodes.OK) - val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] + val groupInfo: Group = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[Group] groupInfo.name should be("UpdatedGroupName") groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) @@ -312,7 +312,7 @@ class GroupsADME2ESpec extends E2ESpec with GroupsADMJsonProtocol { logger.debug(s"response: {}", response) response.status should be(StatusCodes.OK) - val groupInfo: GroupADM = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[GroupADM] + val groupInfo: Group = AkkaHttpUtils.httpResponseToJson(response).fields("group").convertTo[Group] groupInfo.name should be("UpdatedGroupName") groupInfo.descriptions should be(Seq(StringLiteralV2("UpdatedGroupDescription", Some("en")))) diff --git a/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala b/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala index eba84f347a..7cca4085ff 100644 --- a/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala +++ b/integration/src/test/scala/org/knora/webapi/e2e/admin/UsersADME2ESpec.scala @@ -15,7 +15,6 @@ import org.knora.webapi.* import org.knora.webapi.e2e.ClientTestDataCollector import org.knora.webapi.e2e.TestDataFileContent import org.knora.webapi.e2e.TestDataFilePath -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsADMJsonProtocol import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol @@ -24,6 +23,7 @@ import org.knora.webapi.messages.store.triplestoremessages.TriplestoreJsonProtoc import org.knora.webapi.messages.util.KnoraSystemInstances import org.knora.webapi.sharedtestdata.SharedTestDataADM import org.knora.webapi.sharedtestdata.SharedTestDataADM2 +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.util.AkkaHttpUtils import org.knora.webapi.util.MutableTestIri @@ -109,7 +109,7 @@ class UsersADME2ESpec val userIriEnc = java.net.URLEncoder.encode(userIri, "utf-8") val request = Get(baseApiUrl + s"/admin/users/iri/$userIriEnc/group-memberships") ~> addRootUserCredentials() val response = singleAwaitingRequest(request) - AkkaHttpUtils.httpResponseToJson(response).fields("groups").convertTo[Seq[GroupADM]] + AkkaHttpUtils.httpResponseToJson(response).fields("groups").convertTo[Seq[Group]] } "The Users Route ('admin/users')" when { @@ -1364,8 +1364,8 @@ class UsersADME2ESpec assert(response.status === StatusCodes.OK) - val groups: Seq[GroupADM] = - AkkaHttpUtils.httpResponseToJson(response).fields("groups").convertTo[List[GroupADM]] + val groups: Seq[Group] = + AkkaHttpUtils.httpResponseToJson(response).fields("groups").convertTo[List[Group]] groups should contain allElementsOf Seq(SharedTestDataADM.imagesReviewerGroupExternal) // testing getUserGroupMemberships method, which should return the same result @@ -1388,7 +1388,7 @@ class UsersADME2ESpec "used to modify group membership" should { "add user to group" in { val membershipsBeforeUpdate = getUserGroupMemberships(normalUser.id) - membershipsBeforeUpdate should equal(Seq.empty[GroupADM]) + membershipsBeforeUpdate should equal(Seq.empty[Group]) val request = Post( baseApiUrl + s"/admin/users/iri/${URLEncoder.encode(normalUser.id, "utf-8")}/group-memberships/$imagesReviewerGroupIriEnc", @@ -1424,7 +1424,7 @@ class UsersADME2ESpec assert(response.status === StatusCodes.OK) val membershipsAfterUpdate = getUserProjectMemberships(normalUserIri) - membershipsAfterUpdate should equal(Seq.empty[GroupADM]) + membershipsAfterUpdate should equal(Seq.empty[Group]) clientTestDataCollector.addFile( TestDataFileContent( 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 fdad9b7315..a6df5dcf90 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 @@ -122,7 +122,7 @@ class GroupsResponderADMSpec extends CoreSpec { name = Some(GroupName.unsafeFrom("UpdatedGroupName")), descriptions = Some( GroupDescriptions.unsafeFrom( - Seq(V2.StringLiteralV2(value = """UpdatedDescription with "quotes" and """, Some("en"))), + Seq(V2.StringLiteralV2("""UpdatedDescription with "quotes" and """, Some("en"))), ), ), status = Some(GroupStatus.active), @@ -216,8 +216,8 @@ class GroupsResponderADMSpec extends CoreSpec { "remove all members when group is deactivated" in { val group = UnsafeZioRun.runOrThrow( - GroupsResponderADM.groupMembersGetRequestADM( - GroupIri.unsafeFrom(imagesReviewerGroup.id).value, + GroupsResponderADM.groupMembersGetRequest( + GroupIri.unsafeFrom(imagesReviewerGroup.id), rootUser, ), ) diff --git a/integration/src/test/scala/org/knora/webapi/responders/admin/UsersRestServiceSpec.scala b/integration/src/test/scala/org/knora/webapi/responders/admin/UsersRestServiceSpec.scala index 24da652e2f..449d59b6be 100644 --- a/integration/src/test/scala/org/knora/webapi/responders/admin/UsersRestServiceSpec.scala +++ b/integration/src/test/scala/org/knora/webapi/responders/admin/UsersRestServiceSpec.scala @@ -15,8 +15,6 @@ import dsp.errors.ForbiddenException import dsp.errors.NotFoundException import dsp.valueobjects.LanguageCode import org.knora.webapi.* -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupMembersGetRequestADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.* import org.knora.webapi.messages.admin.responder.usersmessages.* import org.knora.webapi.messages.util.KnoraSystemInstances @@ -31,6 +29,7 @@ import org.knora.webapi.slice.admin.api.UsersEndpoints.Requests.StatusChangeRequ import org.knora.webapi.slice.admin.api.UsersEndpoints.Requests.SystemAdminChangeRequest import org.knora.webapi.slice.admin.api.UsersEndpoints.Requests.UserCreateRequest import org.knora.webapi.slice.admin.api.service.UsersRestService +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.Username import org.knora.webapi.slice.admin.domain.model.* @@ -572,7 +571,7 @@ class UsersRestServiceSpec extends CoreSpec with ImplicitSender { } "asked to update the user's group membership" should { - def findGroupMembershipsByIri(userIri: UserIri): Seq[GroupADM] = + def findGroupMembershipsByIri(userIri: UserIri): Seq[Group] = UnsafeZioRun.runOrThrow( ZIO.serviceWithZIO[UserService](_.findUserByIri(userIri).map(_.map(_.groups).getOrElse(Seq.empty))), ) @@ -586,12 +585,12 @@ class UsersRestServiceSpec extends CoreSpec with ImplicitSender { val membershipsAfterUpdate = findGroupMembershipsByIri(normalUser.userIri) membershipsAfterUpdate.map(_.id) should equal(Seq(imagesReviewerGroup.id)) - appActor ! GroupMembersGetRequestADM( - groupIri = imagesReviewerGroup.id, - requestingUser = rootUser, + val received = UnsafeZioRun.runOrThrow( + GroupsResponderADM.groupMembersGetRequest( + GroupIri.unsafeFrom(imagesReviewerGroup.id), + rootUser, + ), ) - val received: GroupMembersGetResponseADM = expectMsgType[GroupMembersGetResponseADM](timeout) - received.members.map(_.id) should contain(normalUser.id) } @@ -610,13 +609,13 @@ class UsersRestServiceSpec extends CoreSpec with ImplicitSender { val membershipsAfterUpdate = findGroupMembershipsByIri(normalUser.userIri) membershipsAfterUpdate should equal(Seq()) - appActor ! GroupMembersGetRequestADM( - groupIri = imagesReviewerGroup.id, - requestingUser = rootUser, + val received = UnsafeZioRun.runOrThrow( + GroupsResponderADM.groupMembersGetRequest( + GroupIri.unsafeFrom(imagesReviewerGroup.id), + rootUser, + ), ) - val received: GroupMembersGetResponseADM = expectMsgType[GroupMembersGetResponseADM](timeout) - - received.members.map(_.id) should not contain normalUser.id + received.members.map(_.id) should not contain normalUser } } } diff --git a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala index 55b45ac074..cc1abd352b 100644 --- a/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala +++ b/integration/src/test/scala/org/knora/webapi/sharedtestdata/SharedTestDataADM.scala @@ -11,12 +11,12 @@ import dsp.constants.SalsahGui import dsp.valueobjects.V2 import org.knora.webapi.IRI import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionADM import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsDataADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.messages.util.KnoraSystemInstances +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.User /** @@ -47,7 +47,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Option("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM( groupsPerProject = Map( @@ -68,7 +68,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM( groupsPerProject = Map( @@ -88,7 +88,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) @@ -104,7 +104,7 @@ object SharedTestDataADM { status = false, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) @@ -203,7 +203,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -232,7 +232,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(imagesProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -308,7 +308,7 @@ object SharedTestDataADM { ) /* represents the full GroupADM of the images ProjectAdmin group */ - def imagesProjectAdminGroup: GroupADM = GroupADM( + def imagesProjectAdminGroup: Group = Group( id = "-", name = "ProjectAdmin", descriptions = Seq(StringLiteralV2(value = "Default Project Admin Group", language = Some("en"))), @@ -318,7 +318,7 @@ object SharedTestDataADM { ) /* represents the full GroupADM of the images ProjectMember group */ - def imagesProjectMemberGroup: GroupADM = GroupADM( + def imagesProjectMemberGroup: Group = Group( id = "-", name = "ProjectMember", descriptions = Seq(StringLiteralV2(value = "Default Project Member Group", language = Some("en"))), @@ -328,7 +328,7 @@ object SharedTestDataADM { ) /* represents the full GroupADM of the images project reviewer group */ - def imagesReviewerGroup: GroupADM = GroupADM( + def imagesReviewerGroup: Group = Group( id = "http://rdfh.ch/groups/00FF/images-reviewer", name = "Image reviewer", descriptions = Seq(StringLiteralV2(value = "A group for image reviewers.", language = Some("en"))), @@ -338,7 +338,7 @@ object SharedTestDataADM { ) /* represents the full GroupADM of the images project reviewer group in the external format*/ - def imagesReviewerGroupExternal: GroupADM = GroupADM( + def imagesReviewerGroupExternal: Group = Group( id = "http://rdfh.ch/groups/00FF/images-reviewer", name = "Image reviewer", descriptions = Seq(StringLiteralV2(value = "A group for image reviewers.", language = Some("en"))), @@ -367,7 +367,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -396,7 +396,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -421,7 +421,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(incunabulaProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -535,7 +535,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -563,7 +563,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -590,7 +590,7 @@ object SharedTestDataADM { status = true, lang = "de", password = Some("$2a$12$7XEBehimXN1rbhmVgQsyve08.vtDmKK7VMin4AdgCEtE4DWgfQbTK"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(anythingProject), permissions = PermissionsDataADM( groupsPerProject = Map( @@ -634,7 +634,7 @@ object SharedTestDataADM { ) /* represents the full GroupADM of the Thing searcher group */ - def thingSearcherGroup: GroupADM = GroupADM( + def thingSearcherGroup: Group = Group( id = "http://rdfh.ch/groups/0001/thing-searcher", name = "Thing searcher", descriptions = Seq(StringLiteralV2(value = "A group for thing searchers.", language = Some("en"))), @@ -680,7 +680,7 @@ object SharedTestDataADM { status = true, lang = "en", password = Some("$2a$10$fTEr/xVjPq7UBAy1O6KWKOM1scLhKGeRQdR4GTA997QPqHzXv0MnW"), - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq(beolProject), permissions = PermissionsDataADM( groupsPerProject = Map( diff --git a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala index 679e7484a1..d4e49ba588 100644 --- a/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala @@ -37,8 +37,8 @@ import org.knora.webapi.slice.admin.api.service.ProjectsADMRestServiceLive import org.knora.webapi.slice.admin.api.service.StoreRestService import org.knora.webapi.slice.admin.api.service.UsersRestService import org.knora.webapi.slice.admin.domain.service.* +import org.knora.webapi.slice.admin.repo.service.KnoraGroupRepoLive import org.knora.webapi.slice.admin.repo.service.KnoraProjectRepoLive -import org.knora.webapi.slice.admin.repo.service.KnoraUserGroupRepoLive import org.knora.webapi.slice.admin.repo.service.KnoraUserRepoLive import org.knora.webapi.slice.common.api.* import org.knora.webapi.slice.common.repo.service.PredicateObjectMapper @@ -75,7 +75,7 @@ object LayersLive { ActorSystem & AdminApiEndpoints & ApiRoutes & ApiV2Endpoints & AppConfigurations & AppRouter & AssetPermissionsResponder & Authenticator & AuthorizationRestService & CacheService & CacheServiceRequestMessageHandler & CardinalityHandler & CardinalityService & ConstructResponseUtilV2 & - ConstructTransformer & GravsearchTypeInspectionRunner & GroupsResponderADM & HttpServer & + ConstructTransformer & GravsearchTypeInspectionRunner & GroupsService & GroupsResponderADM & HttpServer & IIIFRequestMessageHandler & InferenceOptimizationService & InstrumentationServerConfig & IriConverter & IriService & JwtService & KnoraProjectRepo & KnoraUserService & ListsResponder & ListsResponderV2 & MessageRelay & OntologyCache & OntologyHelpers & OntologyInferencer & OntologyRepo & OntologyResponderV2 & @@ -116,6 +116,7 @@ object LayersLive { GroupsEndpointsHandler.layer, GroupsResponderADMLive.layer, GroupsRestServiceLive.layer, + GroupsService.layer, HandlerMapper.layer, HttpServer.layer, IIIFRequestMessageHandlerLive.layer, @@ -125,7 +126,7 @@ object LayersLive { JwtServiceLive.layer, KnoraProjectRepoLive.layer, KnoraResponseRenderer.layer, - KnoraUserGroupRepoLive.layer, + KnoraGroupRepoLive.layer, KnoraUserRepoLive.layer, KnoraUserService.layer, KnoraUserToUserConverter.layer, diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala index 865139d611..8da9dd55a2 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/groupsmessages/GroupsMessagesADM.scala @@ -13,11 +13,8 @@ import org.knora.webapi.IRI import org.knora.webapi.core.RelayedMessage import org.knora.webapi.messages.ResponderRequest.KnoraRequestADM import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM -import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol -import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 -import org.knora.webapi.slice.admin.domain.model.GroupIri -import org.knora.webapi.slice.admin.domain.model.User +import org.knora.webapi.slice.admin.domain.model.Group ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Messages @@ -27,11 +24,6 @@ import org.knora.webapi.slice.admin.domain.model.User */ sealed trait GroupsResponderRequestADM extends KnoraRequestADM with RelayedMessage -/** - * Get all information about all groups. the user initiating the request. - */ -case class GroupsGetADM() extends GroupsResponderRequestADM - /** * Get everything about a single group identified through its IRI. A successful response will be * an [[Option[GroupADM] ]], which will be `None` if the group was not found. @@ -50,21 +42,13 @@ case class MultipleGroupsGetRequestADM( groupIris: Set[IRI], ) extends GroupsResponderRequestADM -/** - * Returns all members of the group identified by iri. - * - * @param groupIri IRI of the group. - * @param requestingUser the user initiating the request. - */ -case class GroupMembersGetRequestADM(groupIri: IRI, requestingUser: User) extends GroupsResponderRequestADM - // Responses /** * Represents the Knora API v1 JSON response to a request for information about all groups. * * @param groups information about all existing groups. */ -case class GroupsGetResponseADM(groups: Seq[GroupADM]) extends AdminKnoraResponseADM with GroupsADMJsonProtocol { +case class GroupsGetResponseADM(groups: Seq[Group]) extends AdminKnoraResponseADM with GroupsADMJsonProtocol { def toJsValue = groupsGetResponseADMFormat.write(this) } @@ -73,39 +57,10 @@ case class GroupsGetResponseADM(groups: Seq[GroupADM]) extends AdminKnoraRespons * * @param group all information about the group. */ -case class GroupGetResponseADM(group: GroupADM) extends AdminKnoraResponseADM with GroupsADMJsonProtocol { +case class GroupGetResponseADM(group: Group) extends AdminKnoraResponseADM with GroupsADMJsonProtocol { def toJsValue = groupResponseADMFormat.write(this) } -////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Components of messages - -/** - * The information describing a group. - * - * @param id the IRI if the group. - * @param name the name of the group. - * @param descriptions the descriptions of the group. - * @param project the project this group belongs to. - * @param status the group's status. - * @param selfjoin the group's self-join status. - */ -case class GroupADM( - id: IRI, - name: String, - descriptions: Seq[StringLiteralV2], - project: ProjectADM, - status: Boolean, - selfjoin: Boolean, -) extends Ordered[GroupADM] { - - def groupIri: GroupIri = GroupIri.unsafeFrom(id) - - /** - * Allows to sort collections of GroupADM. Sorting is done by the id. - */ - def compare(that: GroupADM): Int = this.id.compareTo(that.id) -} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // JSON formatting @@ -114,7 +69,7 @@ case class GroupADM( */ trait GroupsADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with ProjectsADMJsonProtocol { - implicit val groupADMFormat: JsonFormat[GroupADM] = jsonFormat6(GroupADM) + implicit val groupADMFormat: JsonFormat[Group] = jsonFormat6(Group) implicit val groupsGetResponseADMFormat: RootJsonFormat[GroupsGetResponseADM] = jsonFormat(GroupsGetResponseADM, "groups") implicit val groupResponseADMFormat: RootJsonFormat[GroupGetResponseADM] = jsonFormat(GroupGetResponseADM, "group") 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 2d34ec85a6..067d39136b 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 @@ -11,11 +11,11 @@ import spray.json.* import org.knora.webapi.core.RelayedMessage import org.knora.webapi.messages.ResponderRequest.KnoraRequestADM import org.knora.webapi.messages.admin.responder.AdminKnoraResponseADM -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupsADMJsonProtocol import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsADMJsonProtocol import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectsADMJsonProtocol +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.* ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -79,7 +79,7 @@ case class UserProjectAdminMembershipsGetResponseADM(projects: Seq[ProjectADM]) * * @param groups a sequence of groups the user is member of. */ -case class UserGroupMembershipsGetResponseADM(groups: Seq[GroupADM]) extends AdminKnoraResponseADM { +case class UserGroupMembershipsGetResponseADM(groups: Seq[Group]) extends AdminKnoraResponseADM { def toJsValue: JsValue = UsersADMJsonProtocol.userGroupMembershipsGetResponseADMFormat.write(this) } diff --git a/webapi/src/main/scala/org/knora/webapi/messages/util/KnoraSystemInstances.scala b/webapi/src/main/scala/org/knora/webapi/messages/util/KnoraSystemInstances.scala index 5f186d1228..432991df73 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/util/KnoraSystemInstances.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/util/KnoraSystemInstances.scala @@ -6,9 +6,9 @@ package org.knora.webapi.messages.util import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsDataADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.User /** @@ -30,7 +30,7 @@ object KnoraSystemInstances { status = true, lang = "en", password = None, - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) @@ -47,7 +47,7 @@ object KnoraSystemInstances { status = true, lang = "en", password = None, - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) 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 620d078ec3..db5de723fe 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 @@ -37,6 +37,7 @@ import org.knora.webapi.slice.admin.AdminConstants import org.knora.webapi.slice.admin.api.GroupsRequests.GroupCreateRequest import org.knora.webapi.slice.admin.api.GroupsRequests.GroupStatusUpdateRequest 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.GroupIri import org.knora.webapi.slice.admin.domain.model.GroupStatus import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode @@ -54,19 +55,19 @@ import org.knora.webapi.util.ZioHelper trait GroupsResponderADM { /** - * Gets all the groups (without built-in groups) and returns them as a sequence of [[GroupADM]]. + * Gets all the groups (without built-in groups) and returns them as a sequence of [[Group]]. * - * @return all the groups as a sequence of [[GroupADM]]. + * @return all the groups as a sequence of [[Group]]. */ - def groupsGetADM: Task[Seq[GroupADM]] + def groupsGetADM: Task[Seq[Group]] /** - * Gets the group with the given group IRI and returns the information as a [[GroupADM]]. + * Gets the group with the given group IRI and returns the information as a [[Group]]. * * @param groupIri the IRI of the group requested. - * @return information about the group as a [[GroupADM]] + * @return information about the group as a [[Group]] */ - def groupGetADM(groupIri: IRI): Task[Option[GroupADM]] + def groupGetADM(groupIri: IRI): Task[Option[Group]] /** * Gets the groups with the given IRIs and returns a set of [[GroupGetResponseADM]] objects. @@ -80,13 +81,11 @@ trait GroupsResponderADM { * Gets the group members with the given group IRI and returns the information as a [[GroupMembersGetResponseADM]]. * Only project and system admins are allowed to access this information. * - * @param groupIri the IRI of the group. - * @param requestingUser the user initiating the request. + * @param iri the IRI of the group. + * @param user the user initiating the request. * @return A [[GroupMembersGetResponseADM]] */ - def groupMembersGetRequestADM(groupIri: IRI, requestingUser: User): Task[GroupMembersGetResponseADM] - final def groupMembersGetRequest(iri: GroupIri, user: User): Task[GroupMembersGetResponseADM] = - groupMembersGetRequestADM(iri.value, user) + def groupMembersGetRequest(iri: GroupIri, user: User): Task[GroupMembersGetResponseADM] /** * Create a new group. @@ -158,19 +157,17 @@ final case class GroupsResponderADMLive( * Receives a message extending [[GroupsResponderRequestADM]], and returns an appropriate response message */ def handle(msg: ResponderRequest): Task[Any] = msg match { - case _: GroupsGetADM => groupsGetADM case r: GroupGetADM => groupGetADM(r.groupIri) case r: MultipleGroupsGetRequestADM => multipleGroupsGetRequestADM(r.groupIris) - case r: GroupMembersGetRequestADM => groupMembersGetRequestADM(r.groupIri, r.requestingUser) case other => Responder.handleUnexpectedMessage(other, this.getClass.getName) } /** - * Gets all the groups (without built-in groups) and returns them as a sequence of [[GroupADM]]. + * Gets all the groups (without built-in groups) and returns them as a sequence of [[Group]]. * - * @return all the groups as a sequence of [[GroupADM]]. + * @return all the groups as a sequence of [[Group]]. */ - override def groupsGetADM: Task[Seq[GroupADM]] = { + override def groupsGetADM: Task[Seq[Group]] = { val query = Construct(sparql.admin.txt.getGroups(None)) for { groupsResponse <- triplestore.query(query).flatMap(_.asExtended) @@ -179,7 +176,7 @@ final case class GroupsResponderADMLive( } yield result.sorted } - private def convertStatementsToGroupADM(statements: (SubjectV2, ConstructPredicateObjects)): Task[GroupADM] = { + private def convertStatementsToGroupADM(statements: (SubjectV2, ConstructPredicateObjects)): Task[Group] = { val groupIri: SubjectV2 = statements._1 val propertiesMap: ConstructPredicateObjects = statements._2 def getOption[A <: LiteralV2](key: IRI): UIO[Option[Seq[A]]] = @@ -201,7 +198,7 @@ final case class GroupsResponderADMLive( descriptions <- getOrFail[StringLiteralV2](GroupDescriptions) status <- getFirstValueOrFail[BooleanLiteralV2](StatusProp).map(_.value) selfjoin <- getFirstValueOrFail[BooleanLiteralV2](HasSelfJoinEnabled).map(_.value) - } yield GroupADM(groupIri.toString, name, descriptions, projectADM, status, selfjoin) + } yield Group(groupIri.toString, name, descriptions, projectADM, status, selfjoin) } private def findProjectByIriOrFail(iri: String, failReason: Throwable): Task[ProjectADM] = @@ -211,12 +208,12 @@ final case class GroupsResponderADMLive( } yield result /** - * Gets the group with the given group IRI and returns the information as a [[GroupADM]]. + * Gets the group with the given group IRI and returns the information as a [[Group]]. * * @param groupIri the IRI of the group requested. - * @return information about the group as a [[GroupADM]] + * @return information about the group as a [[Group]] */ - override def groupGetADM(groupIri: IRI): Task[Option[GroupADM]] = { + override def groupGetADM(groupIri: IRI): Task[Option[Group]] = { val query = Construct(sparql.admin.txt.getGroups(maybeIri = Some(groupIri))) for { statements <- triplestore.query(query).flatMap(_.asExtended).map(_.statements.headOption) @@ -290,12 +287,12 @@ final case class GroupsResponderADMLive( * Gets the group members with the given group IRI and returns the information as a [[GroupMembersGetResponseADM]]. * Only project and system admins are allowed to access this information. * - * @param groupIri the IRI of the group. - * @param requestingUser the user initiating the request. + * @param iri the IRI of the group. + * @param user the user initiating the request. * @return A [[GroupMembersGetResponseADM]] */ - override def groupMembersGetRequestADM(groupIri: IRI, requestingUser: User): Task[GroupMembersGetResponseADM] = - groupMembersGetADM(groupIri, requestingUser).map(GroupMembersGetResponseADM) + override def groupMembersGetRequest(iri: GroupIri, user: User): Task[GroupMembersGetResponseADM] = + groupMembersGetADM(iri.value, user).map(GroupMembersGetResponseADM) /** * Create a new group. @@ -481,7 +478,7 @@ final case class GroupsResponderADMLive( * @param changedGroup the group with the new status. * @return a [[GroupGetResponseADM]] */ - private def removeGroupMembersIfNecessary(changedGroup: GroupADM) = + private def removeGroupMembersIfNecessary(changedGroup: Group) = if (changedGroup.status) { // group active. no need to remove members. logger.debug("removeGroupMembersIfNecessary - group active. no need to remove members.") diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala index a5a1f48b60..c90a0f5c3c 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala @@ -24,7 +24,6 @@ import org.knora.webapi.messages.OntologyConstants.KnoraBase.EntityPermissionAbb import org.knora.webapi.messages.ResponderRequest import org.knora.webapi.messages.SmartIri import org.knora.webapi.messages.StringFormatter -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.groupsmessages.GroupGetADM import org.knora.webapi.messages.admin.responder.permissionsmessages import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsMessagesUtilADM.PermissionTypeAndCodes @@ -40,6 +39,7 @@ import org.knora.webapi.responders.IriLocker import org.knora.webapi.responders.IriService import org.knora.webapi.responders.Responder import org.knora.webapi.slice.admin.AdminConstants +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode @@ -345,7 +345,7 @@ final case class PermissionsResponderADMLive( val groupFutures: Seq[Task[(IRI, IRI)]] = if (groupIris.nonEmpty) { groupIris.map { groupIri => for { - maybeGroup <- messageRelay.ask[Option[GroupADM]](GroupGetADM(groupIri)) + maybeGroup <- messageRelay.ask[Option[Group]](GroupGetADM(groupIri)) group = maybeGroup.getOrElse( throw InconsistentRepositoryDataException( @@ -758,10 +758,10 @@ final case class PermissionsResponderADMLive( ZIO.succeed(createRequest.forGroup) } else { for { - maybeGroup <- messageRelay.ask[Option[GroupADM]](GroupGetADM(createRequest.forGroup)) + maybeGroup <- messageRelay.ask[Option[Group]](GroupGetADM(createRequest.forGroup)) // if it does not exist then throw an error - group: GroupADM = + group: Group = maybeGroup.getOrElse( throw NotFoundException(s"Group '${createRequest.forGroup}' not found. Aborting request."), ) @@ -1577,13 +1577,13 @@ final case class PermissionsResponderADMLive( for { maybeGroup <- messageRelay - .ask[Option[GroupADM]]( + .ask[Option[Group]]( GroupGetADM( groupIri = createRequest.forGroup.get, ), ) - group: GroupADM = + group: Group = maybeGroup.getOrElse( throw NotFoundException(s"Group '${createRequest.forGroup}' not found. Aborting request."), ) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala index 30948b22cc..26aa942b8f 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/RouteUtilADM.scala @@ -27,6 +27,7 @@ import org.knora.webapi.messages.admin.responder.KnoraResponseADM import org.knora.webapi.messages.admin.responder.groupsmessages.* import org.knora.webapi.messages.admin.responder.projectsmessages.* import org.knora.webapi.messages.admin.responder.usersmessages.* +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.User /** @@ -50,7 +51,7 @@ object RouteUtilADM { project.copy(ontologies = ontologiesExternal) } - def groupAsExternalRepresentation(group: GroupADM): GroupADM = { + def groupAsExternalRepresentation(group: Group): Group = { val projectExternal = projectAsExternalRepresentation(group.project) group.copy(project = projectExternal) } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroup.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroup.scala similarity index 85% rename from webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroup.scala rename to webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroup.scala index fdf0b9f420..f241ac07f5 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroup.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroup.scala @@ -12,7 +12,10 @@ import sttp.tapir.CodecFormat import dsp.valueobjects.Iri import dsp.valueobjects.UuidUtil import dsp.valueobjects.V2 +import org.knora.webapi.IRI import org.knora.webapi.messages.OntologyConstants.KnoraAdmin.BuiltInGroups +import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM +import org.knora.webapi.messages.store.triplestoremessages.StringLiteralV2 import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.Shortcode import org.knora.webapi.slice.common.StringValueCompanion @@ -25,7 +28,7 @@ import org.knora.webapi.slice.common.repo.rdf.LangString /** * The user entity as found in the knora-admin ontology. */ -final case class KnoraUserGroup( +final case class KnoraGroup( id: GroupIri, groupName: GroupName, groupDescriptions: GroupDescriptions, @@ -34,6 +37,33 @@ final case class KnoraUserGroup( hasSelfJoinEnabled: GroupSelfJoin, ) +/** + * Represents user's group. + * + * @param id the IRI if the group. + * @param name the name of the group. + * @param descriptions the descriptions of the group. + * @param project the project this group belongs to. + * @param status the group's status. + * @param selfjoin the group's self-join status. + */ +case class Group( + id: IRI, + name: String, + descriptions: Seq[StringLiteralV2], + project: ProjectADM, + status: Boolean, + selfjoin: Boolean, +) extends Ordered[Group] { + + def groupIri: GroupIri = GroupIri.unsafeFrom(id) + + /** + * Allows to sort collections of GroupADM. Sorting is done by the id. + */ + def compare(that: Group): Int = this.id.compareTo(that.id) +} + final case class GroupIri private (override val value: String) extends AnyVal with StringValue object GroupIri extends StringValueCompanion[GroupIri] { @@ -116,7 +146,7 @@ object GroupSelfJoin { def from(enabled: Boolean): GroupSelfJoin = GroupSelfJoin(enabled) } -object KnoraUserGroup { +object KnoraGroup { object Conversions { implicit val groupIriConverter: String => Either[String, GroupIri] = GroupIri.from implicit val groupNameConverter: String => Either[String, GroupName] = GroupName.from diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/User.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/User.scala index 9e4155b174..1887708dc2 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/User.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/model/User.scala @@ -14,11 +14,11 @@ import dsp.valueobjects.Iri import dsp.valueobjects.LanguageCode import dsp.valueobjects.UuidUtil import org.knora.webapi.messages.OntologyConstants -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsDataADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.messages.admin.responder.usersmessages.UserInformationType import org.knora.webapi.messages.admin.responder.usersmessages.UsersADMJsonProtocol +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.common.IntValueCompanion import org.knora.webapi.slice.common.StringValueCompanion @@ -69,7 +69,7 @@ final case class User( status: Boolean, lang: String, password: Option[String] = None, - groups: Seq[GroupADM] = Vector.empty[GroupADM], + groups: Seq[Group] = Vector.empty[Group], projects: Seq[ProjectADM] = Seq.empty[ProjectADM], permissions: PermissionsDataADM = PermissionsDataADM(), ) extends Ordered[User] { self => @@ -97,14 +97,14 @@ final case class User( status = false, lang = "", password = None, - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) case UserInformationType.Short => self.copy( password = None, - groups = Seq.empty[GroupADM], + groups = Seq.empty[Group], projects = Seq.empty[ProjectADM], permissions = PermissionsDataADM(), ) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupsService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupsService.scala new file mode 100644 index 0000000000..60a41ca0ff --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/GroupsService.scala @@ -0,0 +1,16 @@ +/* + * Copyright © 2021 - 2024 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.slice.admin.domain.service + +import zio.ZLayer + +final case class GroupsService( + private val groupRepo: KnoraGroupRepo, +) {} + +object GroupsService { + def layer = ZLayer.derive[GroupsService] +} diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserGroupRepo.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupRepo.scala similarity index 59% rename from webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserGroupRepo.scala rename to webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupRepo.scala index 690f11135c..08a912d7cc 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserGroupRepo.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraGroupRepo.scala @@ -8,16 +8,16 @@ package org.knora.webapi.slice.admin.domain.service import zio.Task import org.knora.webapi.slice.admin.domain.model.GroupIri -import org.knora.webapi.slice.admin.domain.model.KnoraUserGroup +import org.knora.webapi.slice.admin.domain.model.KnoraGroup import org.knora.webapi.slice.common.repo.service.Repository -trait KnoraUserGroupRepo extends Repository[KnoraUserGroup, GroupIri] { +trait KnoraGroupRepo extends Repository[KnoraGroup, GroupIri] { /** * Saves the user group, returns the created data. Updates not supported. * - * @param user The [[KnoraUserGroup]] to be saved, can be an update or a creation. - * @return the saved entity. + * @param group The [[KnoraGroup]] to be saved, can be an update or a creation. + * @return The saved entity. */ - def save(userGroup: KnoraUserGroup): Task[KnoraUserGroup] + def save(group: KnoraGroup): Task[KnoraGroup] } diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala index 523df637ab..9d29d2ed50 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/domain/service/KnoraUserService.scala @@ -14,13 +14,13 @@ import zio.ZLayer import dsp.errors.DuplicateValueException import dsp.valueobjects.LanguageCode -import org.knora.webapi.messages.admin.responder.groupsmessages.GroupADM import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM import org.knora.webapi.responders.IriService import org.knora.webapi.slice.admin.api.UsersEndpoints.Requests.UserCreateRequest import org.knora.webapi.slice.admin.domain.model.Email import org.knora.webapi.slice.admin.domain.model.FamilyName import org.knora.webapi.slice.admin.domain.model.GivenName +import org.knora.webapi.slice.admin.domain.model.Group import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.KnoraUser @@ -109,17 +109,17 @@ case class KnoraUserService( userCreated <- userRepo.save(newUser) } yield userCreated - def addUserToGroup(user: KnoraUser, group: GroupADM): IO[UserServiceError, KnoraUser] = for { + def addUserToGroup(user: KnoraUser, group: Group): IO[UserServiceError, KnoraUser] = for { _ <- ZIO.when(user.isInGroup.contains(group.groupIri))( ZIO.fail(UserServiceError(s"User ${user.id.value} is already member of group ${group.groupIri.value}.")), ) user <- updateUser(user, UserChangeRequest(groups = Some(user.isInGroup :+ group.groupIri))).orDie } yield user - def removeUserFromGroup(user: User, group: GroupADM): IO[UserServiceError, KnoraUser] = + def removeUserFromGroup(user: User, group: Group): IO[UserServiceError, KnoraUser] = userRepo.findById(user.userIri).someOrFailException.orDie.flatMap(removeUserFromGroup(_, group)) - def removeUserFromGroup(user: KnoraUser, group: GroupADM): IO[UserServiceError, KnoraUser] = for { + def removeUserFromGroup(user: KnoraUser, group: Group): IO[UserServiceError, KnoraUser] = for { _ <- ZIO .fail(UserServiceError(s"User ${user.id.value} is not member of group ${group.groupIri.value}.")) .when(!user.isInGroup.contains(group.groupIri)) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLive.scala b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLive.scala similarity index 88% rename from webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLive.scala rename to webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLive.scala index 8c941de167..bc35d7bfb8 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLive.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLive.scala @@ -25,10 +25,10 @@ import org.knora.webapi.messages.OntologyConstants.KnoraAdmin import org.knora.webapi.slice.admin.AdminConstants.adminDataNamedGraph import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.GroupStatus +import org.knora.webapi.slice.admin.domain.model.KnoraGroup.Conversions.* import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri -import org.knora.webapi.slice.admin.domain.model.KnoraUserGroup.Conversions.* import org.knora.webapi.slice.admin.domain.model._ -import org.knora.webapi.slice.admin.domain.service.KnoraUserGroupRepo +import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo import org.knora.webapi.slice.admin.repo.rdf.RdfConversions.projectIriConverter import org.knora.webapi.slice.admin.repo.rdf.Vocabulary import org.knora.webapi.slice.common.repo.rdf.RdfResource @@ -37,24 +37,24 @@ import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Constru import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Update import org.knora.webapi.store.triplestore.errors.TriplestoreResponseException -final case class KnoraUserGroupRepoLive(triplestore: TriplestoreService) extends KnoraUserGroupRepo { - override def findById(id: GroupIri): Task[Option[KnoraUserGroup]] = for { +final case class KnoraGroupRepoLive(triplestore: TriplestoreService) extends KnoraGroupRepo { + override def findById(id: GroupIri): Task[Option[KnoraGroup]] = for { model <- triplestore.queryRdfModel(KnoraUserGroupQueries.findById(id)) resource <- model.getResource(id.value) userGroup <- ZIO.foreach(resource)(toGroup) } yield userGroup - override def findAll(): Task[List[KnoraUserGroup]] = for { + override def findAll(): Task[List[KnoraGroup]] = for { model <- triplestore.queryRdfModel(KnoraUserGroupQueries.findAll) resources <- model.getResourcesRdfType(KnoraAdmin.UserGroup).option.map(_.getOrElse(Iterator.empty)) groups <- ZStream.fromIterator(resources).mapZIO(toGroup).runCollect } yield groups.toList - def save(userGroup: KnoraUserGroup): Task[KnoraUserGroup] = + def save(userGroup: KnoraGroup): Task[KnoraGroup] = triplestore.query(KnoraUserGroupQueries.save(userGroup)).as(userGroup) - private def toGroup(resource: RdfResource): Task[KnoraUserGroup] = { + private def toGroup(resource: RdfResource): Task[KnoraGroup] = { for { id <- resource.iri.flatMap(it => ZIO.fromEither(GroupIri.from(it.value))) groupName <- resource.getStringLiteralOrFail[GroupName](KnoraAdmin.GroupName) @@ -63,7 +63,7 @@ final case class KnoraUserGroupRepoLive(triplestore: TriplestoreService) extends groupStatus <- resource.getBooleanLiteralOrFail[GroupStatus](KnoraAdmin.StatusProp) belongsToProject <- resource.getObjectIrisConvert[ProjectIri](KnoraAdmin.BelongsToProject).map(_.headOption) hasSelfJoinEnabled <- resource.getBooleanLiteralOrFail[GroupSelfJoin](KnoraAdmin.HasSelfJoinEnabled) - } yield KnoraUserGroup( + } yield KnoraGroup( id, groupName, groupDescriptions, @@ -74,8 +74,8 @@ final case class KnoraUserGroupRepoLive(triplestore: TriplestoreService) extends }.mapError(it => TriplestoreResponseException(it.toString)) } -object KnoraUserGroupRepoLive { - val layer = ZLayer.derive[KnoraUserGroupRepoLive] +object KnoraGroupRepoLive { + val layer = ZLayer.derive[KnoraGroupRepoLive] } private object KnoraUserGroupQueries { @@ -122,7 +122,7 @@ private object KnoraUserGroupQueries { p.and(id.has(iri, variable(s"n${index}")).optional()) }) - def save(group: KnoraUserGroup): Update = { + def save(group: KnoraGroup): Update = { val query: ModifyQuery = Queries .MODIFY() @@ -141,7 +141,7 @@ private object KnoraUserGroupQueries { Vocabulary.KnoraAdmin.hasSelfJoinEnabled, ) - private def toTriples(group: KnoraUserGroup) = { + private def toTriples(group: KnoraGroup) = { import Vocabulary.KnoraAdmin.* Rdf .iri(group.id.value) diff --git a/webapi/src/main/scala/org/knora/webapi/slice/common/api/AuthorizationRestService.scala b/webapi/src/main/scala/org/knora/webapi/slice/common/api/AuthorizationRestService.scala index aa296505d1..d6ce8426ec 100644 --- a/webapi/src/main/scala/org/knora/webapi/slice/common/api/AuthorizationRestService.scala +++ b/webapi/src/main/scala/org/knora/webapi/slice/common/api/AuthorizationRestService.scala @@ -13,8 +13,8 @@ import org.knora.webapi.slice.admin.domain.model.GroupIri import org.knora.webapi.slice.admin.domain.model.KnoraProject import org.knora.webapi.slice.admin.domain.model.KnoraProject.ProjectIri import org.knora.webapi.slice.admin.domain.model.User +import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo -import org.knora.webapi.slice.admin.domain.service.KnoraUserGroupRepo import org.knora.webapi.slice.common.api.AuthorizationRestService.isActive import org.knora.webapi.slice.common.api.AuthorizationRestService.isSystemAdmin import org.knora.webapi.slice.common.api.AuthorizationRestService.isSystemAdminOrProjectAdminInAnyProject @@ -90,7 +90,7 @@ object AuthorizationRestService { isSystemUser(user) || isSystemAdmin(user) || user.permissions.isProjectAdminInAnyProject() } -final case class AuthorizationRestServiceLive(projectRepo: KnoraProjectRepo, groupsRepo: KnoraUserGroupRepo) +final case class AuthorizationRestServiceLive(projectRepo: KnoraProjectRepo, groupsRepo: KnoraGroupRepo) extends AuthorizationRestService { override def ensureSystemAdmin(user: User): IO[ForbiddenException, Unit] = { lazy val msg = diff --git a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala index e4c09cb254..6588f42614 100644 --- a/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala +++ b/webapi/src/test/scala/org/knora/webapi/TestDataFactory.scala @@ -65,7 +65,7 @@ object TestDataFactory { } object UserGroup { - val testUserGroup: KnoraUserGroup = KnoraUserGroup( + val testUserGroup: KnoraGroup = KnoraGroup( GroupIri.unsafeFrom("http://rdfh.ch/groups/0001/1234"), GroupName.unsafeFrom("User Group"), GroupDescriptions.unsafeFrom(List(V2.StringLiteralV2("one user group to rule them all", None))), diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/api/service/AuthorizationRestServiceSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/api/service/AuthorizationRestServiceSpec.scala index 6bb22b9713..5eef5b8fb2 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/api/service/AuthorizationRestServiceSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/api/service/AuthorizationRestServiceSpec.scala @@ -18,7 +18,7 @@ import org.knora.webapi.messages.OntologyConstants.KnoraAdmin.SystemProject import org.knora.webapi.messages.admin.responder.permissionsmessages.PermissionsDataADM import org.knora.webapi.slice.admin.domain.model.User import org.knora.webapi.slice.admin.domain.repo.KnoraProjectRepoInMemory -import org.knora.webapi.slice.admin.repo.service.KnoraUserGroupRepoInMemory +import org.knora.webapi.slice.admin.repo.service.KnoraGroupRepoInMemory import org.knora.webapi.slice.common.api.AuthorizationRestService import org.knora.webapi.slice.common.api.AuthorizationRestServiceLive @@ -116,5 +116,5 @@ object AuthorizationRestServiceSpec extends ZIOSpecDefault { } yield assert(exit)(failsWithA[ForbiddenException]) }, ), - ).provide(AuthorizationRestServiceLive.layer, KnoraProjectRepoInMemory.layer, KnoraUserGroupRepoInMemory.layer) + ).provide(AuthorizationRestServiceLive.layer, KnoraProjectRepoInMemory.layer, KnoraGroupRepoInMemory.layer) } diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroupSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroupSpec.scala similarity index 97% rename from webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroupSpec.scala rename to webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroupSpec.scala index c06f8b9243..8525acedf6 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraUserGroupSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/domain/model/KnoraGroupSpec.scala @@ -12,7 +12,7 @@ import org.knora.webapi.slice.admin.domain.model.* /** * This spec is used to test the [[Group]] value objects creation. */ -object KnoraUserGroupSpec extends ZIOSpecDefault { +object KnoraGroupSpec extends ZIOSpecDefault { private val validDescription = Seq(V2.StringLiteralV2(value = "Valid group description", language = Some("en"))) private val invalidDescription = Seq( V2.StringLiteralV2(value = "", language = Some("en")), diff --git a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLiveSpec.scala b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLiveSpec.scala similarity index 72% rename from webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLiveSpec.scala rename to webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLiveSpec.scala index d4aa511197..44fa584e02 100644 --- a/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraUserGroupRepoLiveSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/slice/admin/repo/service/KnoraGroupRepoLiveSpec.scala @@ -16,32 +16,32 @@ import org.knora.webapi.TestDataFactory.UserGroup.* import org.knora.webapi.messages.StringFormatter 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.KnoraUserGroup -import org.knora.webapi.slice.admin.domain.service.KnoraUserGroupRepo +import org.knora.webapi.slice.admin.domain.model.KnoraGroup +import org.knora.webapi.slice.admin.domain.service.KnoraGroupRepo import org.knora.webapi.slice.common.repo.AbstractInMemoryCrudRepository import org.knora.webapi.store.triplestore.api.TriplestoreServiceInMemory -final case class KnoraUserGroupRepoInMemory(groups: Ref[List[KnoraUserGroup]]) - extends AbstractInMemoryCrudRepository[KnoraUserGroup, GroupIri](groups, _.id) - with KnoraUserGroupRepo {} +final case class KnoraGroupRepoInMemory(groups: Ref[List[KnoraGroup]]) + extends AbstractInMemoryCrudRepository[KnoraGroup, GroupIri](groups, _.id) + with KnoraGroupRepo {} -object KnoraUserGroupRepoInMemory { - val layer = ZLayer.fromZIO(Ref.make(List.empty[KnoraUserGroup])) >>> - ZLayer.derive[KnoraUserGroupRepoInMemory] +object KnoraGroupRepoInMemory { + val layer = ZLayer.fromZIO(Ref.make(List.empty[KnoraGroup])) >>> + ZLayer.derive[KnoraGroupRepoInMemory] } -object KnoraUserGroupRepoLiveSpec extends ZIOSpecDefault { +object KnoraGroupRepoLiveSpec extends ZIOSpecDefault { val spec: Spec[Any, Any] = suite("KnoraUserGroupRepoLive")( suite("findById")( test("findById given a non existing user should return None") { - ZIO.serviceWithZIO[KnoraUserGroupRepo](userGroupRepo => + ZIO.serviceWithZIO[KnoraGroupRepo](userGroupRepo => for { userGroup <- userGroupRepo.findById(GroupIri.unsafeFrom("http://rdfh.ch/groups/0001/1234")) } yield assertTrue(userGroup.isEmpty), ) }, test("findById given an existing user should return that user") { - ZIO.serviceWithZIO[KnoraUserGroupRepo](userGroupRepo => + ZIO.serviceWithZIO[KnoraGroupRepo](userGroupRepo => for { _ <- userGroupRepo.save(testUserGroup) userGroup <- userGroupRepo.findById(testUserGroup.id) @@ -49,7 +49,7 @@ object KnoraUserGroupRepoLiveSpec extends ZIOSpecDefault { ) }, test("save should update fields") { - ZIO.serviceWithZIO[KnoraUserGroupRepo](userGroupRepo => + ZIO.serviceWithZIO[KnoraGroupRepo](userGroupRepo => for { _ <- userGroupRepo.save(testUserGroup) testUserGroupModified = @@ -64,7 +64,7 @@ object KnoraUserGroupRepoLiveSpec extends ZIOSpecDefault { }, ), ).provide( - KnoraUserGroupRepoLive.layer, + KnoraGroupRepoLive.layer, TriplestoreServiceInMemory.emptyLayer, StringFormatter.test, )