Skip to content
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

1943: Fix permission checks and reuse user checks #1944

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

steffenkleinle
Copy link
Member

@steffenkleinle steffenkleinle commented Feb 24, 2025

Short Description

Create reusable functions for user checks for project, region and role.

Proposed Changes

  • Add user functions to check for project, region and role
  • Refactor Authorizer to use reusable functions
  • Add lots of tests
  • Fix a few permission checks, see side effects

Side Effects

  • Added check to ensure that EXTERNAL_VERIFIED_API_USER is only available for bayern (align with create)
  • Delete user even if role is NO_RIGHTS

Hopefully no other changes. I ran the tests both on the code before and after and all tests succeed in both versions (exception: changing a role to EXTERNAL_VERIFIED_API_USER in koblenz.

Testing

Test that the user permissions still work.

Resolved Issues

Fixes: #1943

Comment on lines +89 to +93
return newAdminRole != Role.EXTERNAL_VERIFIED_API_USER || transaction {
actingAdmin.isProject(
EAK_BAYERN_PROJECT
)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is new, aligns behavior with create user

actingAdmin: AdministratorEntity,
existingAdmin: AdministratorEntity
): Boolean {
if (actingAdmin.projectId.value != existingAdmin.projectId.value && existingAdmin.role != Role.NO_RIGHTS.db_value) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we not delete a user if it has no rights?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, a user has the NO_RIGHTS if and only if the user is deleted. (This might have changed though).
I think, it does not matter too much, whether we allow a deleted user to be deleted again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying 👍

Base automatically changed from 1762-add-agency-id-to-region to main February 28, 2025 09:24
Comment on lines +64 to +65
fun isRole(role: Role, vararg other: Role): Boolean =
this.role == role.db_value || other.any { this.role == it.db_value }
Copy link
Member

@michael-markl michael-markl Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't hasRole make more sense?
Similarly, I'd prefer isInProject and isInRegion?

Or maybe roleIs, projectIs and regionIs?

Comment on lines +67 to 71
return newAdminRole != Role.EXTERNAL_VERIFIED_API_USER || transaction {
actingAdmin.isProject(
EAK_BAYERN_PROJECT
)
}
Copy link
Member

@michael-markl michael-markl Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like negating statements, using disjunctions, and packing everything into a return statement makes it harder to read (at least for me).

Suggested change
return newAdminRole != Role.EXTERNAL_VERIFIED_API_USER || transaction {
actingAdmin.isProject(
EAK_BAYERN_PROJECT
)
}
if (newAdminRole == Role.EXTERNAL_VERIFIED_API_USER && !transaction { actingAdmin.isProject(EAK_BAYERN_PROJECT) }) {
// Currently, we only allow external API users for the EAK Bayern project.
return false
}
return true

Copy link
Member Author

@steffenkleinle steffenkleinle Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, negating should be avoided if possible. Will adjust accordingly.

actingAdmin: AdministratorEntity,
existingAdmin: AdministratorEntity
): Boolean {
if (actingAdmin.projectId.value != existingAdmin.projectId.value && existingAdmin.role != Role.NO_RIGHTS.db_value) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, a user has the NO_RIGHTS if and only if the user is deleted. (This might have changed though).
I think, it does not matter too much, whether we allow a deleted user to be deleted again.

Comment on lines 119 to 124
fun mayAddApiTokensInProject(user: AdministratorEntity): Boolean {
return transaction {
(
user.role == Role.PROJECT_ADMIN.db_value && ProjectEntity.find { Projects.project eq KOBLENZ_PASS_PROJECT }
.single().id.value == user.projectId.value
) ||
(
user.role == Role.EXTERNAL_VERIFIED_API_USER.db_value && ProjectEntity.find { Projects.project eq EAK_BAYERN_PROJECT }
.single().id.value == user.projectId.value
)
(user.isRole(Role.PROJECT_ADMIN) && user.isProject(KOBLENZ_PASS_PROJECT)) ||
(user.isRole(Role.EXTERNAL_VERIFIED_API_USER) && user.isProject(EAK_BAYERN_PROJECT))
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wild :D (not your changes, but the fact that we actually make such distinctions between projects for the roles. I feel like this is going to get confusing very quickly, when we have more than 3 projects)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. @f1sh1918 do you have any more insights whether we actually have to distinguish between projects here?

Copy link
Contributor

@f1sh1918 f1sh1918 Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i'm also not super happy with this implementation. I think the main aspect was not to create a separate role for that because it would be more effort. Which we in the end did for verein360 since we had to ensure that they don't get project admin rights as a third party provider, but that wasn't planned so far when we implemented that for koblenz..

I think it would be easier and cleaner to also use this separate role for koblenz (like for eak)
The problem is that we soon go live with koblenz and we should not break the current implementation.

My suggestion would be to add the ability for koblenz to create EXTERNAL_VERIFIED_API_USER and allow them to use the particular endpoint (entitleduserdata). Then give them the possibility to create a user and a token with the role and adjust their import so everything still works.
If that was done i would remove the token creation from the koblenz project admin role.

As a third step it would probably make sense to add RBAC and also be able to have different roles as a user so someone could be Project_Admin and External_API_User

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants