From 904b7a14a2fee6cf05d2ba6b2d23e011ff059180 Mon Sep 17 00:00:00 2001 From: Vladislav Frolov <50615459+Cheshiriks@users.noreply.github.com> Date: Tue, 5 Sep 2023 16:20:41 +0300 Subject: [PATCH] Added user permissions (#2544) * Added user permissions --- .../controllers/UserPermissionController.kt | 47 ++++++++++++++++++ .../LnkUserOrganizationRepository.kt | 8 +++ .../security/UserPermissionEvaluator.kt | 49 +++++++++++++++++++ .../service/LnkUserOrganizationService.kt | 8 +++ .../saveourtool/save/info/UserPermissions.kt | 11 +++++ .../info/UserPermissionsInOrganization.kt | 13 +++++ 6 files changed, 136 insertions(+) create mode 100644 save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/UserPermissionController.kt create mode 100644 save-backend/src/main/kotlin/com/saveourtool/save/backend/security/UserPermissionEvaluator.kt create mode 100644 save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissions.kt create mode 100644 save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissionsInOrganization.kt diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/UserPermissionController.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/UserPermissionController.kt new file mode 100644 index 0000000000..a84bf709fa --- /dev/null +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/UserPermissionController.kt @@ -0,0 +1,47 @@ +package com.saveourtool.save.backend.controllers + +import com.saveourtool.save.backend.security.UserPermissionEvaluator +import com.saveourtool.save.configs.ApiSwaggerSupport +import com.saveourtool.save.info.UserPermissions +import com.saveourtool.save.utils.blockingToMono +import com.saveourtool.save.v1 +import org.springframework.security.core.Authentication +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController +import reactor.core.publisher.Mono + +/** + * Controller for user permissions. + */ +@ApiSwaggerSupport +@RestController +@RequestMapping(path = ["/api/$v1"]) +class UserPermissionController( + private val userPermissionEvaluator: UserPermissionEvaluator, +) { + /** + * @param authentication + * @return UserPermissions + */ + @GetMapping("/users/permissions") + fun getUserPermissions( + authentication: Authentication, + ): Mono = blockingToMono { + userPermissionEvaluator.getUserPermissions(authentication) + } + + /** + * @param authentication + * @param organizationName + * @return UserPermissions + */ + @GetMapping("/users/permissions-by-organization") + fun getUserPermissions( + authentication: Authentication, + @RequestParam organizationName: String, + ): Mono = blockingToMono { + userPermissionEvaluator.getUserPermissionsByOrganizationName(authentication, organizationName) + } +} diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/LnkUserOrganizationRepository.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/LnkUserOrganizationRepository.kt index 93d1aeae36..94c25db320 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/LnkUserOrganizationRepository.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/repository/LnkUserOrganizationRepository.kt @@ -91,6 +91,14 @@ interface LnkUserOrganizationRepository : BaseEntityRepository + /** + * @param userName + * @param organizationName + * @param status status of organization + * @return List of [LnkUserOrganization] in which user with [userName] participates + */ + fun findByUserNameAndOrganizationStatusAndOrganizationName(userName: String, status: OrganizationStatus, organizationName: String): LnkUserOrganization? + /** * @param userId id of user */ diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/security/UserPermissionEvaluator.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/security/UserPermissionEvaluator.kt new file mode 100644 index 0000000000..f8cb771b73 --- /dev/null +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/security/UserPermissionEvaluator.kt @@ -0,0 +1,49 @@ +package com.saveourtool.save.backend.security + +import com.saveourtool.save.authservice.utils.username +import com.saveourtool.save.backend.service.LnkUserOrganizationService +import com.saveourtool.save.info.UserPermissions +import com.saveourtool.save.info.UserPermissionsInOrganization +import org.springframework.security.core.Authentication +import org.springframework.stereotype.Component + +/** + * Class that is capable of assessing user's permissions regarding. + */ +@Component +class UserPermissionEvaluator( + private var lnkUserOrganizationService: LnkUserOrganizationService, +) { + /** + * @param authentication + * @return UserPermissions + */ + fun getUserPermissions( + authentication: Authentication, + ): UserPermissions { + val lnkOrganizations = lnkUserOrganizationService.getOrganizationsByUserNameAndCreatedStatus(authentication.username()) + + return UserPermissions( + lnkOrganizations.associate { it.organization.name to UserPermissionsInOrganization(it.organization.canCreateContests, it.organization.canBulkUpload) }, + ) + } + + /** + * @param authentication + * @param organizationName + * @return UserPermissions + */ + fun getUserPermissionsByOrganizationName( + authentication: Authentication, + organizationName: String, + ): UserPermissions { + val lnkOrganization = lnkUserOrganizationService.getOrganizationsByUserNameAndCreatedStatusAndOrganizationName(authentication.username(), organizationName) + + val isPermittedCreateContest = lnkOrganization?.organization?.canCreateContests ?: false + val isPermittedToBulkUpload = lnkOrganization?.organization?.canBulkUpload ?: false + + return UserPermissions( + mapOf(organizationName to UserPermissionsInOrganization(isPermittedCreateContest, isPermittedToBulkUpload)), + ) + } +} diff --git a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/LnkUserOrganizationService.kt b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/LnkUserOrganizationService.kt index 5352704d7c..81146d0cc7 100644 --- a/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/LnkUserOrganizationService.kt +++ b/save-backend/src/main/kotlin/com/saveourtool/save/backend/service/LnkUserOrganizationService.kt @@ -179,6 +179,14 @@ class LnkUserOrganizationService( */ fun getOrganizationsByUserNameAndCreatedStatus(userName: String) = lnkUserOrganizationRepository.findByUserNameAndOrganizationStatus(userName, OrganizationStatus.CREATED) + /** + * @param userName name of User + * @param organizationName name of organization + * @return list of lnkUserOrganization + */ + fun getOrganizationsByUserNameAndCreatedStatusAndOrganizationName(userName: String, organizationName: String) = + lnkUserOrganizationRepository.findByUserNameAndOrganizationStatusAndOrganizationName(userName, OrganizationStatus.CREATED, organizationName) + /** * @param authentication * @param organization diff --git a/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissions.kt b/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissions.kt new file mode 100644 index 0000000000..a5a50e6ceb --- /dev/null +++ b/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissions.kt @@ -0,0 +1,11 @@ +package com.saveourtool.save.info + +import kotlinx.serialization.Serializable + +/** + * @property inOrganizations user permissions in organizations + */ +@Serializable +data class UserPermissions( + val inOrganizations: Map = emptyMap(), +) diff --git a/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissionsInOrganization.kt b/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissionsInOrganization.kt new file mode 100644 index 0000000000..675af5085b --- /dev/null +++ b/save-cloud-common/src/commonMain/kotlin/com/saveourtool/save/info/UserPermissionsInOrganization.kt @@ -0,0 +1,13 @@ +package com.saveourtool.save.info + +import kotlinx.serialization.Serializable + +/** + * @property canCreateContest permission for create contests in organizations + * @property canDoBulkUpload permission for upload COSV files in organizations + */ +@Serializable +data class UserPermissionsInOrganization( + val canCreateContest: Boolean, + val canDoBulkUpload: Boolean, +)