-
-
Notifications
You must be signed in to change notification settings - Fork 305
feat: Add maintainer organization role #3043
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… - add not maintainer or owner error code
…nization-role-maintainer
WalkthroughThe changes introduce a new organization role, "MAINTAINER," and expand role-based access control throughout the backend and frontend. Backend logic now distinguishes between OWNER, MAINTAINER, and MEMBER roles, updating permission checks, role assignments, and error handling accordingly. The API schema and frontend code are updated to recognize and display the new MAINTAINER role, including translations and UI conditions. Tests are added and adjusted to verify the new role's behavior. The changes also refine member checks, separating owner and member logic, and add a new error code for insufficient organization role permissions. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant API
participant ProjectsController
participant OrganizationRoleService
participant ProjectService
User->>API: Create Project Request (with organizationId)
API->>ProjectsController: createProject(dto)
ProjectsController->>OrganizationRoleService: checkUserIsOwnerOrMaintainer(organizationId)
alt User is OWNER or MAINTAINER
ProjectsController->>ProjectService: createProject(dto)
ProjectService-->>ProjectsController: ProjectModel
alt User is MAINTAINER
ProjectsController->>ProjectService: grantFullAccessToUser(user, project)
end
ProjectsController-->>API: ProjectModel
else User is not OWNER or MAINTAINER
ProjectsController-->>API: Error(USER_IS_NOT_OWNER_OR_MAINTAINER_OF_ORGANIZATION)
end
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
⏰ Context from checks skipped due to timeout of 90000ms (22)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
…not created by org maintainer + update schema
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
webapp/src/translationTools/useOrgRoleTranslation.ts (1)
1-30
: 💡 Verification agent🧩 Analysis chain
Verify translation key existence in translation files
The code correctly adds translation handling for the new MAINTAINER role, but we should ensure the new translation keys exist in all language files.
🏁 Script executed:
#!/bin/bash # Check if translation keys for MAINTAINER role exist in translation files # Find all translation JSON files echo "Searching for translation files..." translation_files=$(find . -path "*/public/i18n/*.json" -type f) if [ -z "$translation_files" ]; then echo "No translation files found in expected locations" # Try alternative locations translation_files=$(find . -name "*.json" | grep -i "i18n\|translations\|locale") fi echo "Found translation files:" echo "$translation_files" echo -e "\nChecking for MAINTAINER role translation keys..." for file in $translation_files; do echo "Checking file: $file" # Check for the regular translation key if grep -q "organization_role_type_MAINTAINER" "$file"; then echo "✓ organization_role_type_MAINTAINER found" else echo "✗ organization_role_type_MAINTAINER NOT found" fi # Check for the hint translation key if grep -q "organization_role_type_MAINTAINER_hint" "$file"; then echo "✓ organization_role_type_MAINTAINER_hint found" else echo "✗ organization_role_type_MAINTAINER_hint NOT found" fi echo "" doneLength of output: 14211
Add missing MAINTAINER translation keys
The new
MAINTAINER
role keys aren’t present in any of our locales. Please add both entries to every translation file:• webapp/src/i18n/.json
• backend/data/src/test/resources/import/i18next/.jsonFor example, in
webapp/src/i18n/en.json
:{ …, "organization_role_type_MEMBER": "Member", "organization_role_type_MEMBER_hint": "Member can view resources", "organization_role_type_OWNER": "Owner", "organization_role_type_OWNER_hint": "Owner can manage settings", "organization_role_type_MAINTAINER": "Maintainer", "organization_role_type_MAINTAINER_hint": "Maintainer can manage workflows" }Repeat and provide appropriate translations in each locale file.
🧹 Nitpick comments (6)
backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt (1)
1-222
: Consider adding tests for the new MAINTAINER roleThe test has been updated for the existing role check changes, but there are no tests specifically verifying the behavior of the new MAINTAINER role. Consider adding test cases for inviting users as MAINTAINERS and verifying their permissions.
You could add a test similar to
testAcceptInvitation
but for the MAINTAINER role:@Test fun testAcceptMaintainerInvitation() { val helloUser = dbPopulator.createUserIfNotExists("hellouser") this.organizationService.create(dummyDto, helloUser).let { organization -> val invitation = invitationService.create( CreateOrganizationInvitationParams( organization = organization, type = OrganizationRoleType.MAINTAINER, ), ) val invitedUser = dbPopulator.createUserIfNotExists("invitedMaintainer") loginAsUser(invitedUser.username) performAuthGet("/v2/invitations/${invitation.code}/accept").andIsOk // Verify the user is a maintainer val isMaintainer = organizationRoleService.isUserMaintainer(invitedUser.id, organization.id) assertThat(isMaintainer).isTrue // Verify the user is not an owner val isOwner = organizationRoleService.isUserOwner(invitedUser.id, organization.id) assertThat(isOwner).isFalse } }backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsController.kt (1)
100-102
: Grant explicit permissions to maintainers creating projects.This conditional block grants full access permissions to maintainers who create projects. This is necessary because unlike owners who inherently have full access to all projects in their organization, maintainers need explicit permission grants.
I recommend adding a comment explaining why this conditional grant is needed for maintainers but not for owners, to clarify the permission model for future developers.
if (organizationRoleService.getType(dto.organizationId) == OrganizationRoleType.MAINTAINER) { + // Unlike owners who inherently have full access to all projects, maintainers need explicit permissions permissionService.grantFullAccessToProject(authenticationFacade.authenticatedUserEntity, project) }
backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt (4)
103-112
: ClarifyMAINTAINER
rank semantics in KDoc / javadoc
isUserOfRole
now treatsMAINTAINER
as inclusive ofOWNER
(i.e. owners satisfy a MAINTAINER-level check). That seems intentional (“equal or higher than a given role”), but is not obvious at call-sites. Please add a short comment to theMAINTAINER
branch (or to the method header) to make this precedence explicit and prevent future misuse.
131-145
: Avoid copy-pasted owner/maintainer check logic
checkUserIsOwnerOrMaintainer
duplicates most of the logic already present incheckUserIsOwner
(server-admin bypass, role evaluation, exception throwing). A tiny util that takes “roles allowed” + “exception message” would keep both code paths DRY and reduce the risk of future divergence.-private fun doRoleCheck( - userId: Long, - requiredRoles: Set<OrganizationRoleType>, - exception: Message -) { - val isServerAdmin = userAccountService.getDto(userId).role == UserAccount.Role.ADMIN - if (!isServerAdmin && !requiredRoles.contains(self.getDto(orgId, userId).type)) { - throw PermissionException(exception) - } -}… and reuse it from both public helpers.
182-188
: Minor: useEnumSet
for role collections
OWNER_OR_MAINTAINER_ROLES
is looked-up on every call; usingEnumSet.of(...)
is a tiny optimisation (backed by bit-vector) and self-documents intent that the set is immutable.-private val OWNER_OR_MAINTAINER_ROLES = setOf( - OrganizationRoleType.OWNER, - OrganizationRoleType.MAINTAINER -) +private val OWNER_OR_MAINTAINER_ROLES: Set<OrganizationRoleType> = + EnumSet.of(OrganizationRoleType.OWNER, OrganizationRoleType.MAINTAINER)
299-304
: Add unit test forgrantMaintainerRoleToUser
workflow
The new helper mirrors the existing member/owner helpers, but there is no guard-rail test ensuring the side-effects (cache eviction, managed-user validation, etc.). Consider adding a happy-path + validation-failure test similar to those for owners to prevent regressions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsController.kt
(2 hunks)backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt
(1 hunks)backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerCreateTest.kt
(2 hunks)backend/data/src/main/kotlin/io/tolgee/constants/Message.kt
(1 hunks)backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt
(1 hunks)backend/data/src/main/kotlin/io/tolgee/security/thirdParty/ThirdPartyUserHandler.kt
(1 hunks)backend/data/src/main/kotlin/io/tolgee/service/invitation/InvitationService.kt
(2 hunks)backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt
(5 hunks)backend/data/src/main/kotlin/io/tolgee/service/security/AuthProviderChangeService.kt
(1 hunks)backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt
(2 hunks)webapp/src/service/apiSchema.generated.ts
(16 hunks)webapp/src/service/response.types.ts
(1 hunks)webapp/src/translationTools/useOrgRoleTranslation.ts
(1 hunks)webapp/src/views/projects/ProjectListView.tsx
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
webapp/src/views/projects/ProjectListView.tsx (1)
webapp/src/globalContext/helpers.tsx (1)
useIsAdmin
(21-22)
🔇 Additional comments (24)
backend/data/src/main/kotlin/io/tolgee/model/enums/OrganizationRoleType.kt (1)
6-6
: Implementation of the new MAINTAINER role looks goodThe MAINTAINER role has been properly added to the OrganizationRoleType enum, positioned between MEMBER and OWNER which reflects its intended permission hierarchy.
webapp/src/service/response.types.ts (1)
51-51
: Frontend implementation of MAINTAINER role looks goodThe MAINTAINER role has been correctly added to the OrganizationRoleType enum in the frontend code, maintaining consistency with the backend implementation.
backend/data/src/main/kotlin/io/tolgee/constants/Message.kt (1)
216-216
: New error message for insufficient role permissionsThe added error message constant
USER_IS_NOT_OWNER_OR_MAINTAINER_OF_ORGANIZATION
provides appropriate feedback when a user attempts an operation that requires either owner or maintainer privileges.backend/data/src/main/kotlin/io/tolgee/security/thirdParty/ThirdPartyUserHandler.kt (1)
82-82
: Refined role check in third-party user handlingThe change from
isUserMemberOrOwner
toisUserMember
appropriately refines the role checking logic to align with the new role structure. This ensures a clearer separation of concerns where member status is checked independently of higher-level roles like maintainer or owner.backend/data/src/main/kotlin/io/tolgee/service/invitation/InvitationService.kt (2)
28-29
: Good imports refactoringThe explicit imports for Date and Optional classes are cleaner than using a wildcard import.
173-173
: Check for membership role refinedChanged from checking if user is a member or owner to checking if user is specifically a member. This aligns with the new MAINTAINER role introduction and provides clearer role distinction.
backend/data/src/main/kotlin/io/tolgee/service/security/AuthProviderChangeService.kt (1)
254-254
: Check for membership role refinedChanged from checking if user is a member or owner to checking if user is specifically a member. This change is consistent with the new role system that differentiates between MEMBER, MAINTAINER, and OWNER roles.
webapp/src/translationTools/useOrgRoleTranslation.ts (2)
14-15
: Support added for MAINTAINER role hint translationAdded case for the new MAINTAINER role to return the appropriate hint translation key.
23-24
: Support added for MAINTAINER role translationAdded case for the new MAINTAINER role to return the appropriate translation key.
backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/organizationController/OrganizationControllerInvitingTest.kt (1)
102-102
: Updated test to match service implementationTest has been updated to verify only membership using
isUserMember
instead of checking for member or owner status. This aligns with the service implementation changes and the new role system.backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/project/ProjectsController.kt (2)
25-25
: Added required import for OrganizationRoleType.The import is necessary to support the newly introduced role check logic for maintainers in the
createProject
method.
98-98
: Updated role check to allow maintainers to create projects.The method call has been updated from
checkUserIsOwner
tocheckUserIsOwnerOrMaintainer
, expanding project creation permissions to maintainers in addition to owners.backend/app/src/test/kotlin/io/tolgee/api/v2/controllers/v2ProjectsController/ProjectsControllerCreateTest.kt (2)
8-8
: Added required import for OrganizationRoleType.This import is necessary for the new test case that verifies project creation by maintainers.
109-126
: Added test to verify project creation by maintainers.This test ensures that users with the MAINTAINER role can create projects in an organization, which is a key part of the new maintainer role functionality. The test properly:
- Creates a test organization and user
- Assigns the MAINTAINER role to the user
- Attempts to create a project as that maintainer
- Verifies the project is created successfully with the correct organization
This provides good coverage for the new feature.
webapp/src/views/projects/ProjectListView.tsx (3)
52-54
: Expanded role check to include maintainers.Renamed
isOrganizationOwner
toisOrganizationOwnerOrMaintainer
and updated the logic to check for both 'OWNER' and 'MAINTAINER' roles. This change aligns with the backend permission changes to allow maintainers to create projects.
60-60
: Updated add button visibility for maintainers.The
addAllowed
flag now uses the expandedisOrganizationOwnerOrMaintainer
check to determine if the add project button should be shown, allowing maintainers to see this option.
102-102
: Updated empty state action for maintainers.The empty state now shows the "add project" button for maintainers in addition to owners, completing the UI updates needed for the new maintainer role.
backend/data/src/main/kotlin/io/tolgee/service/security/PermissionService.kt (2)
228-229
: Extended permission computation to include maintainers.Updated the condition to include
organizationRole == OrganizationRoleType.MAINTAINER
alongsideMEMBER
when determining organization base permissions. This ensures maintainers receive the appropriate base permissions in projects within their organization.
478-478
:❌ Incorrect review comment
Restricted organization base permission setting to members only.
The method call changed from what was likely
checkUserIsOwnerOrMember
tocheckUserIsMember
, restricting who can set organization base permissions to only members, not owners or maintainers.This change appears to narrow the permission check, which might be intentional but should be verified. Let's check if this is consistent with other similar permission checks in the codebase:
🏁 Script executed:
#!/bin/bash # Search for other usages of checkUserIsMember and compare with previous pattern rg -A 2 -B 2 "checkUserIsMember\(" --type kotlinLength of output: 1204
🏁 Script executed:
#!/bin/bash # Display the implementation of checkUserIsMember to verify its behavior rg -A 20 "fun checkUserIsMember" --type kotlinLength of output: 2403
No restriction change –
checkUserIsMember
still allows owners and maintainersThe
checkUserIsMember
implementation treats any non-null role (including OWNER, MAINTAINER, etc.) as membership and also permits server admins. Therefore swapping from a hypotheticalcheckUserIsOwnerOrMember
tocheckUserIsMember
does not exclude owners or maintainers.• In
OrganizationRoleService.kt
,checkUserIsMember
returns ifisUserMember(userId, orgId)
is true, andisUserMember
simply checks for any role (type != null
).
• Server admins are still allowed via theisServerAdmin
branch.You can safely ignore the concern about owners being excluded here.
Likely an incorrect or invalid review comment.
webapp/src/service/apiSchema.generated.ts (5)
1340-1340
: Documentation enhancement clarifies XLIFF-only escapeHtml featureThe documentation clarification that HTML escaping is supported only in XLIFF format provides important usage details for developers. This is a good improvement to prevent incorrect expectations when using other export formats.
Also applies to: 1458-1458, 2093-2093, 10860-10860
1994-1994
: New error code supports the MAINTAINER role permission checksThe addition of the error code "user_is_not_owner_or_maintainer_of_organization" properly supports the new MAINTAINER role and refines permission boundaries in the API. This is consistent with the broader change to introduce role-based permission gradations.
Also applies to: 4512-4512
2917-2918
: New translationsUpdatedAt field supports translation trackingThe addition of an optional timestamp field to track when translations were last updated provides valuable metadata for users. This can help with determining translation freshness and tracking localization progress.
3090-3090
: MAINTAINER role added consistently across all relevant modelsThe "MAINTAINER" role has been consistently added to all organization role type definitions throughout the schema. This ensures the new role is properly supported in all API operations where organization roles are involved.
Also applies to: 3097-3097, 3107-3107, 3515-3515, 3713-3713, 3766-3766, 4117-4117, 4919-4919, 4938-4938
13926-13926
: Search parameter added to namespace listing APIThe addition of an optional search parameter to the namespace listing API enhances the API's filtering capabilities, allowing clients to search for specific namespaces.
backend/data/src/main/kotlin/io/tolgee/service/organization/OrganizationRoleService.kt
Show resolved
Hide resolved
return when (role) { | ||
OrganizationRoleType.MEMBER -> | ||
isUserMemberOrOwner(userId, organizationId) | ||
isUserMember(userId, organizationId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename it to hasAnyOrganizationRole
Supersedes #3016
Summary by CodeRabbit
New Features
Bug Fixes
Tests