From d41e03fd09417ad4c7e2c04d4e3a6870eefc1dfc Mon Sep 17 00:00:00 2001 From: hugoamalric Date: Wed, 14 Dec 2022 00:53:24 +0100 Subject: [PATCH 1/3] feat(#5): add infrastructure for group request Signed-off-by: hugoamalric --- .../configuration/BeanConfiguration.kt | 14 +++++++++++- .../postgres/SpringGroupRequestRepository.kt | 7 ++++++ .../postgres/entity/GroupEntity.kt | 8 +++++++ .../postgres/entity/GroupRequestEntity.kt | 22 +++++++++++++++++++ .../postgres/mapper/GroupEntityMapper.kt | 11 +++++++--- .../mapper/GroupRequestEntityMapper.kt | 16 ++++++++++++++ .../persistence/postgres/seed/UserSeeder.kt | 20 +++++++++++++++-- 7 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/SpringGroupRequestRepository.kt create mode 100644 src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupRequestEntity.kt create mode 100644 src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupRequestEntityMapper.kt diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/configuration/BeanConfiguration.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/configuration/BeanConfiguration.kt index 48081cd..6b13d09 100644 --- a/src/main/kotlin/fr/polyflix/user/infrastructure/configuration/BeanConfiguration.kt +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/configuration/BeanConfiguration.kt @@ -2,10 +2,13 @@ package fr.polyflix.user.infrastructure.configuration import fr.polyflix.user.domain.messaging.producer.UserProducer import fr.polyflix.user.domain.persistence.repository.GroupRepository +import fr.polyflix.user.domain.persistence.repository.GroupRequestRepository import fr.polyflix.user.domain.persistence.repository.RoleRepository import fr.polyflix.user.domain.persistence.repository.UserRepository +import fr.polyflix.user.domain.service.GroupRequestService import fr.polyflix.user.domain.service.GroupService import fr.polyflix.user.domain.service.UserService +import fr.polyflix.user.domain.service.impl.GroupRequestServiceImpl import fr.polyflix.user.domain.service.impl.GroupServiceImpl import fr.polyflix.user.domain.service.impl.UserServiceImpl import org.springframework.context.annotation.Bean @@ -15,7 +18,11 @@ import org.springframework.context.annotation.Configuration class BeanConfiguration { @Bean - fun userService(userRepository: UserRepository, roleRepository: RoleRepository, userProducer: UserProducer) : UserService { + fun userService( + userRepository: UserRepository, + roleRepository: RoleRepository, + userProducer: UserProducer + ): UserService { return UserServiceImpl(userRepository, roleRepository, userProducer) } @@ -23,4 +30,9 @@ class BeanConfiguration { fun groupService(userRepository: UserRepository, groupRepository: GroupRepository): GroupService { return GroupServiceImpl(groupRepository, userRepository) } + + @Bean + fun groupRequestService(groupRequestRepository: GroupRequestRepository): GroupRequestService { + return GroupRequestServiceImpl(groupRequestRepository) + } } \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/SpringGroupRequestRepository.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/SpringGroupRequestRepository.kt new file mode 100644 index 0000000..6687396 --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/SpringGroupRequestRepository.kt @@ -0,0 +1,7 @@ +package fr.polyflix.user.infrastructure.persistence.postgres + +import fr.polyflix.user.infrastructure.persistence.postgres.entity.GroupRequestEntity +import org.springframework.data.jpa.repository.JpaRepository +import java.util.* + +interface SpringGroupRequestRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupEntity.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupEntity.kt index 484ea54..4c9b1c4 100644 --- a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupEntity.kt +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupEntity.kt @@ -26,4 +26,12 @@ class GroupEntity( inverseJoinColumns = [JoinColumn(name = "user_id", referencedColumnName = "id")] ) val members: Set, + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable( + name = "groups_requests", + joinColumns = [JoinColumn(name = "group_id", referencedColumnName = "id")], + inverseJoinColumns = [JoinColumn(name = "request_id", referencedColumnName = "id")] + ) + val groupRequests: Set, ) \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupRequestEntity.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupRequestEntity.kt new file mode 100644 index 0000000..2eda54d --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/entity/GroupRequestEntity.kt @@ -0,0 +1,22 @@ +package fr.polyflix.user.infrastructure.persistence.postgres.entity + +import org.springframework.data.annotation.CreatedDate +import java.time.LocalDateTime +import java.util.* +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.Id +import javax.persistence.Table + +@Entity +@Table(name = "groups_requests") +class GroupRequestEntity( + @Id val id: UUID, + + @Column + val reason: String, + + @CreatedDate + @Column(name = "created_date", nullable = false, updatable = false) + var createdDate: LocalDateTime +) \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupEntityMapper.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupEntityMapper.kt index 31e4273..bf9f595 100644 --- a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupEntityMapper.kt +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupEntityMapper.kt @@ -5,14 +5,18 @@ import fr.polyflix.user.infrastructure.persistence.postgres.entity.GroupEntity import org.springframework.stereotype.Component @Component -class GroupEntityMapper(private val userMapper: UserEntityMapper): PersistenceMapper { +class GroupEntityMapper( + private val userMapper: UserEntityMapper, + private val groupRequestMapper: GroupRequestEntityMapper +) : PersistenceMapper { override fun toDomain(entity: GroupEntity): Group { return Group( entity.id, entity.name, entity.slug, userMapper.toDomain(entity.owner), - entity.members.map { userMapper.toDomain(it) }.toMutableSet() + entity.members.map { userMapper.toDomain(it) }.toMutableSet(), + entity.groupRequests.map { groupRequestMapper.toDomain(it) }.toMutableSet() ) } @@ -22,7 +26,8 @@ class GroupEntityMapper(private val userMapper: UserEntityMapper): PersistenceMa domain.name, domain.slug, userMapper.toEntity(domain.owner), - domain.members.map { userMapper.toEntity(it) }.toSet() + domain.members.map { userMapper.toEntity(it) }.toSet(), + domain.groupRequests.map { groupRequestMapper.toEntity(it) }.toSet() ) } } \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupRequestEntityMapper.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupRequestEntityMapper.kt new file mode 100644 index 0000000..4650371 --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/mapper/GroupRequestEntityMapper.kt @@ -0,0 +1,16 @@ +package fr.polyflix.user.infrastructure.persistence.postgres.mapper + +import fr.polyflix.user.domain.entity.GroupRequest +import fr.polyflix.user.infrastructure.persistence.postgres.entity.GroupRequestEntity +import org.springframework.stereotype.Component + +@Component +class GroupRequestEntityMapper : PersistenceMapper { + override fun toDomain(entity: GroupRequestEntity): GroupRequest { + return GroupRequest(entity.id, entity.reason, entity.createdDate) + } + + override fun toEntity(domain: GroupRequest): GroupRequestEntity { + return GroupRequestEntity(domain.id, domain.reason, domain.createdDate) + } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/seed/UserSeeder.kt b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/seed/UserSeeder.kt index d6522a2..e7fabc6 100644 --- a/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/seed/UserSeeder.kt +++ b/src/main/kotlin/fr/polyflix/user/infrastructure/persistence/postgres/seed/UserSeeder.kt @@ -5,12 +5,14 @@ import fr.polyflix.user.infrastructure.persistence.postgres.SpringGroupRepositor import fr.polyflix.user.infrastructure.persistence.postgres.SpringRoleRepository import fr.polyflix.user.infrastructure.persistence.postgres.SpringUserRepository import fr.polyflix.user.infrastructure.persistence.postgres.entity.GroupEntity +import fr.polyflix.user.infrastructure.persistence.postgres.entity.GroupRequestEntity import fr.polyflix.user.infrastructure.persistence.postgres.entity.RoleEntity import fr.polyflix.user.infrastructure.persistence.postgres.entity.UserEntity import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value import org.springframework.boot.CommandLineRunner import org.springframework.stereotype.Component +import java.time.LocalDateTime import java.util.* @Component @@ -66,6 +68,18 @@ class UserSeeder( ) ) + val groupRequestDO3 = GroupRequestEntity( + UUID.fromString("77695670-a8ea-49ec-9c8c-4c9bc26fdf3c"), + "I want to join this group because I am in DO3", + LocalDateTime.now() + ) + + val groupRequestDO4 = GroupRequestEntity( + UUID.fromString("8b9b0aa1-22de-48bb-ae00-622ff007647d"), + "I want to join this group because I am in DO4", + LocalDateTime.now() + ) + val userSeeds = listOf(memberUser, contributorUser, administratorUser) val groupSeeds = listOf( @@ -74,14 +88,16 @@ class UserSeeder( "DO4", "do4", administratorUser, - setOf(memberUser, contributorUser, administratorUser) + setOf(memberUser, contributorUser, administratorUser), + setOf(groupRequestDO4) ), GroupEntity( UUID.fromString("ce3848ce-742f-4467-ab9d-3c5889cf282f"), "DO3", "do3", contributorUser, - setOf(memberUser) + setOf(memberUser), + setOf(groupRequestDO3) ) ) From 328c1a5575347169824ff6e078f56ba5375ae96c Mon Sep 17 00:00:00 2001 From: hugoamalric Date: Wed, 14 Dec 2022 00:54:08 +0100 Subject: [PATCH 2/3] feat(#5): add domain for group request Signed-off-by: hugoamalric --- .../fr/polyflix/user/domain/entity/Group.kt | 5 +++-- .../user/domain/entity/GroupRequest.kt | 10 ++++++++++ .../repository/GroupRequestRepository.kt | 11 ++++++++++ .../domain/service/GroupRequestService.kt | 11 ++++++++++ .../service/impl/GroupRequestServiceImpl.kt | 20 +++++++++++++++++++ .../domain/service/impl/GroupServiceImpl.kt | 5 +++-- 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/fr/polyflix/user/domain/entity/GroupRequest.kt create mode 100644 src/main/kotlin/fr/polyflix/user/domain/persistence/repository/GroupRequestRepository.kt create mode 100644 src/main/kotlin/fr/polyflix/user/domain/service/GroupRequestService.kt create mode 100644 src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupRequestServiceImpl.kt diff --git a/src/main/kotlin/fr/polyflix/user/domain/entity/Group.kt b/src/main/kotlin/fr/polyflix/user/domain/entity/Group.kt index 738f2fc..01c5b8d 100644 --- a/src/main/kotlin/fr/polyflix/user/domain/entity/Group.kt +++ b/src/main/kotlin/fr/polyflix/user/domain/entity/Group.kt @@ -1,13 +1,14 @@ package fr.polyflix.user.domain.entity -import java.util.UUID +import java.util.* class Group( val id: UUID, var name: String, val slug: String, val owner: User, - var members: MutableSet + var members: MutableSet, + var groupRequests: MutableSet ) { override fun toString(): String { return "Group { name = $name, slug = $slug }" diff --git a/src/main/kotlin/fr/polyflix/user/domain/entity/GroupRequest.kt b/src/main/kotlin/fr/polyflix/user/domain/entity/GroupRequest.kt new file mode 100644 index 0000000..9e7581b --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/domain/entity/GroupRequest.kt @@ -0,0 +1,10 @@ +package fr.polyflix.user.domain.entity + +import java.time.LocalDateTime +import java.util.* + +class GroupRequest( + val id: UUID, + val reason: String, + var createdDate: LocalDateTime +) \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/domain/persistence/repository/GroupRequestRepository.kt b/src/main/kotlin/fr/polyflix/user/domain/persistence/repository/GroupRequestRepository.kt new file mode 100644 index 0000000..776a1b3 --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/domain/persistence/repository/GroupRequestRepository.kt @@ -0,0 +1,11 @@ +package fr.polyflix.user.domain.persistence.repository + +import fr.polyflix.user.domain.entity.GroupRequest +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import java.util.* + +interface GroupRequestRepository { + fun findAll(pageable: Pageable): Page + fun findOne(id: UUID): Optional +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/domain/service/GroupRequestService.kt b/src/main/kotlin/fr/polyflix/user/domain/service/GroupRequestService.kt new file mode 100644 index 0000000..3479f0d --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/domain/service/GroupRequestService.kt @@ -0,0 +1,11 @@ +package fr.polyflix.user.domain.service + +import fr.polyflix.user.domain.entity.GroupRequest +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import java.util.* + +interface GroupRequestService { + fun getGroupRequests(pageable: Pageable): Page + fun findGroupRequestById(id: UUID): Optional +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupRequestServiceImpl.kt b/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupRequestServiceImpl.kt new file mode 100644 index 0000000..37375a9 --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupRequestServiceImpl.kt @@ -0,0 +1,20 @@ +package fr.polyflix.user.domain.service.impl + +import fr.polyflix.user.domain.entity.GroupRequest +import fr.polyflix.user.domain.persistence.repository.GroupRequestRepository +import fr.polyflix.user.domain.service.GroupRequestService +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import java.util.* + +class GroupRequestServiceImpl( + private val groupRequestRepository: GroupRequestRepository, +) : GroupRequestService { + override fun getGroupRequests(pageable: Pageable): Page { + return groupRequestRepository.findAll(pageable) + } + + override fun findGroupRequestById(id: UUID): Optional { + return groupRequestRepository.findOne(id) + } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupServiceImpl.kt b/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupServiceImpl.kt index a1ca4d7..06ed3b3 100644 --- a/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupServiceImpl.kt +++ b/src/main/kotlin/fr/polyflix/user/domain/service/impl/GroupServiceImpl.kt @@ -15,7 +15,8 @@ import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import java.util.* -class GroupServiceImpl(private val groupRepository: GroupRepository, private val userRepository: UserRepository): GroupService { +class GroupServiceImpl(private val groupRepository: GroupRepository, private val userRepository: UserRepository) : + GroupService { private val logger = LoggerFactory.getLogger(javaClass) override fun create(props: CreateGroupProps): Group { @@ -32,7 +33,7 @@ class GroupServiceImpl(private val groupRepository: GroupRepository, private val logger.info("Slug '$slug' generated from group '${props.name}'") // Build the group and save it - val group = Group(id, props.name, slug, owner, members.toMutableSet()) + val group = Group(id, props.name, slug, owner, members.toMutableSet(), mutableSetOf()) return groupRepository.save(group) } From ef1d3d55e40cdf265b14433fe09efdb2eaaf5060 Mon Sep 17 00:00:00 2001 From: hugoamalric Date: Wed, 14 Dec 2022 00:54:21 +0100 Subject: [PATCH 3/3] feat(#5): add application for group request Signed-off-by: hugoamalric --- .../http/controller/GroupRequestController.kt | 29 +++++++++++++++++++ .../http/dto/response/group/GroupResponse.kt | 4 ++- .../groupRequest/GroupRequestResponse.kt | 11 +++++++ .../PaginatedGroupRequestResponse.kt | 11 +++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/fr/polyflix/user/application/http/controller/GroupRequestController.kt create mode 100644 src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/GroupRequestResponse.kt create mode 100644 src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/PaginatedGroupRequestResponse.kt diff --git a/src/main/kotlin/fr/polyflix/user/application/http/controller/GroupRequestController.kt b/src/main/kotlin/fr/polyflix/user/application/http/controller/GroupRequestController.kt new file mode 100644 index 0000000..c1bc09f --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/application/http/controller/GroupRequestController.kt @@ -0,0 +1,29 @@ +package fr.polyflix.user.application.http.controller + +import fr.polyflix.user.application.http.dto.response.groupRequest.GroupRequestResponse +import fr.polyflix.user.application.http.dto.response.groupRequest.PaginatedGroupRequestResponse +import fr.polyflix.user.domain.service.GroupRequestService +import org.springframework.data.domain.PageRequest +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping("/groups/{slug}/requests") +class GroupRequestController(private val groupRequestService: GroupRequestService) { + @GetMapping + fun getGroupRequests( + @RequestParam(required = false, defaultValue = "0") page: Int, + @RequestParam(required = false, defaultValue = "10") size: Int + ): ResponseEntity { + val groupRequests = groupRequestService.getGroupRequests(PageRequest.of(page, size)) + return ResponseEntity.ok(PaginatedGroupRequestResponse(groupRequests)) + } + + @GetMapping("/{id}") + fun getGroupById(@PathVariable id: UUID): ResponseEntity { + return groupRequestService.findGroupRequestById(id) + .map { ResponseEntity.ok(GroupRequestResponse(it)) } + .orElseGet { ResponseEntity.notFound().build() } + } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/application/http/dto/response/group/GroupResponse.kt b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/group/GroupResponse.kt index bdf6072..15376af 100644 --- a/src/main/kotlin/fr/polyflix/user/application/http/dto/response/group/GroupResponse.kt +++ b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/group/GroupResponse.kt @@ -1,8 +1,9 @@ package fr.polyflix.user.application.http.dto.response.group +import fr.polyflix.user.application.http.dto.response.groupRequest.GroupRequestResponse import fr.polyflix.user.application.http.dto.response.user.UserResponse import fr.polyflix.user.domain.entity.Group -import java.util.UUID +import java.util.* class GroupResponse(group: Group) { val id: UUID = group.id @@ -10,4 +11,5 @@ class GroupResponse(group: Group) { val slug: String = group.slug val owner: UserResponse = UserResponse(group.owner) val members: List = group.members.map { UserResponse(it) } + val groupRequests: List = group.groupRequests.map { GroupRequestResponse(it) } } \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/GroupRequestResponse.kt b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/GroupRequestResponse.kt new file mode 100644 index 0000000..90f9076 --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/GroupRequestResponse.kt @@ -0,0 +1,11 @@ +package fr.polyflix.user.application.http.dto.response.groupRequest + +import fr.polyflix.user.domain.entity.GroupRequest +import java.time.LocalDateTime +import java.util.* + +class GroupRequestResponse(groupRequest: GroupRequest) { + val id: UUID = groupRequest.id + val reason: String = groupRequest.reason + val createdDate: LocalDateTime = groupRequest.createdDate +} \ No newline at end of file diff --git a/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/PaginatedGroupRequestResponse.kt b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/PaginatedGroupRequestResponse.kt new file mode 100644 index 0000000..6fb120e --- /dev/null +++ b/src/main/kotlin/fr/polyflix/user/application/http/dto/response/groupRequest/PaginatedGroupRequestResponse.kt @@ -0,0 +1,11 @@ +package fr.polyflix.user.application.http.dto.response.groupRequest + +import fr.polyflix.user.domain.entity.GroupRequest +import org.springframework.data.domain.Page + +class PaginatedGroupRequestResponse(data: Page) { + val totalElements: Long = data.totalElements + val totalPages: Int = data.totalPages + val currentPage: Int = data.number + val data: List = data.content.map { GroupRequestResponse(it) } +} \ No newline at end of file