-
Notifications
You must be signed in to change notification settings - Fork 7
[NAE-1617] Authority Refactor #54
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
base: release/6.4.0
Are you sure you want to change the base?
Changes from all commits
0179f7a
90d3341
a50fd02
a14d450
19befc8
3e6f56e
5d6ee53
6f17119
552cb90
d0c02a2
4c1e918
6e45491
70574f9
f022afc
bd79076
043e478
1de66c7
361e660
1c090f2
d93846c
bf5ae40
d07bb75
81185d3
e8e0efa
3e20ed2
f45da11
af0da4c
8e34591
cb19c59
f6b7fe5
012922a
47044e3
adf1710
6dfca41
c554bfa
534dbdf
8c6fa3f
0240935
dc062f7
aa61971
601ef6b
ce6b750
5575b9b
c9fdc43
03b995a
f1a3d68
378e109
2203dee
71f5e96
f36bd15
2bec5eb
017db43
a60bb47
5a92bf6
07befdd
cac5fb3
7c91908
7f2a38b
b573dfa
8b6bd3f
f89384c
6419576
fc53497
7d77928
6ad9216
0420715
62a8600
74e35cf
5f26dc4
01a5b1a
f41976f
9209a5e
1d9c3bf
c945539
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| # Authority management | ||
| Netgrif Application Engine implements authority objects to manage access | ||
| to resources, to protect resources from unauthorized access. Then these | ||
| authorities can be assigned to users to provide access to those secured | ||
| resources. | ||
|
|
||
| ## Authorizing objects | ||
| Authorizing objects are Java enum values, that represent authorities, | ||
| that are needed to access a resource or use an action. E.g. to be able to import new | ||
| process (Petri Net) into the application, the user must have authority | ||
| created from `AuthorizingObject.PROCESS_UPLOAD` authorizing object. | ||
|
|
||
| These authorizing objects are predefined, and they are used to create the | ||
| `Authority` objects/entities at application startup. There followings are predefined: | ||
|
|
||
| - `PROCESS_UPLOAD`- to import new process | ||
| - `PROCESS_VIEW_ALL`- to retrieve all the processes imported by any user | ||
| - `PROCESS_VIEW_OWN`- to retrieve only processes imported by logged user | ||
| - `PROCESS_DELETE_ALL`- to delete processes imported by any user | ||
| - `PROCESS_DELETE_OWN`- to delete processes imported by logged user | ||
| - `FILTER_UPLOAD`- to upload filter | ||
| - `FILTER_DELETE_OWN`- to delete filter imported by logged user | ||
| - `FILTER_DELETE_ALL`- to delete filter imported by any user | ||
| - `USER_CREATE`- to invite or create user | ||
| - `USER_DELETE`- to remove user | ||
| - `USER_EDIT_ALL`- to edit any user | ||
| - `USER_EDIT_SELF`- to edit only logged user | ||
| - `USER_VIEW_ALL`- to retrieve all users | ||
| - `USER_VIEW_SELF`- to retrieve only logged user | ||
| - `GROUP_CREATE`- to create group | ||
| - `GROUP_DELETE_OWN`- to delete group created by logged user | ||
| - `GROUP_DELETE_ALL`- to delete group create by any user | ||
| - `GROUP_ADD_USER`- to add any user to any group | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about adding users to "my" groups? Do we define the concept of "my" groups?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In demo application the user only can add users to its own group and we have defined concept of "my" groups in case GROUP_VIEW_MY so there is an endpoint to retrieve the groups owned by user. Hence I can define GROUP_ADD_USER_MY for future use. |
||
| - `GROUP_REMOVE_USER`- to remove any user from any group | ||
|
minop marked this conversation as resolved.
|
||
| - `GROUP_VIEW_ALL`- to retrieve any group | ||
| - `GROUP_VIEW_OWN`- to retrieve group of logged user | ||
| - `ROLE_ASSIGN_TO_USER`- to assign role to user | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is role assignment a general authority, or can it be restricted only to a group? Such restrictions might be useful for the demo applications.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a string constant, using this an authority is created at startup. Point 1.: I do not see the way that this string could be used to create authority for managing access to groups. Point 2.: there is no endpoint for assigning roles based on groups, but you can freely implement a method in authorization services to check for current user's group. Point 3.: as far as I know, the process roles and petri nets do not have any info about their group inside which they where created / uploaded. These are only my thoughts, if I am wrong, please correct me, but I would consider a group refactor to update the group system. |
||
| - `ROLE_REMOVE_FROM_USER`- to remove role from user | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as Is it meaningful to separate role assignment, from role removal? What would be the use case?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I am removing this authority. |
||
| - `AUTHORITY_CREATE`- to create authority | ||
| - `AUTHORITY_DELETE`- to delete authority | ||
| - `AUTHORITY_VIEW_ALL`- to retrieve any authority | ||
| - `CASE_VIEW_ALL`- to view all cases | ||
| - `CASE_CREATE`- to create case | ||
| - `CASE_DELETE`- to delete case | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it be meaningful to separate
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only super user has the CASE_DELETE authority by default, the other user's must have some permission (user ref of role) to be able to remove a case. This permission is checked using If you wish, I can implement an authorization for checking authority like CASE_DELETE_OWN |
||
| - `CASE_DATA_GET_ALL`- to get all data of case | ||
| - `TASK_RELOAD`- to reload tasks | ||
| - `TASK_ASSIGN`- to assign task | ||
| - `TASK_FINISH`- to finish task | ||
| - `TASK_CANCEL`- to cancel task | ||
| - `TASK_DELEGATE`- to delegate task | ||
| - `TASK_SAVE_DATA`- to save data on task | ||
| - `ELASTIC_REINDEX` - to reindex Elasticsearch database | ||
| - `LDAP_GROUP_GET_ALL` - to get all LDAP groups | ||
| - `LDAP_GROUP_ASSIGN_ROLES` - to assign roles to LDAP groups | ||
|
|
||
| However, it is possible to add custom authorizing objects using `nae.authority.authorizing-objects` | ||
| property in `application.properties` files as following: | ||
|
|
||
| ``` | ||
| # Authorities | ||
| nae.authority.authorizing-objects=EXAMPLE_AUTHORITY_1,EXAMPLE_AUTHORITY_2 | ||
| ``` | ||
|
|
||
| ## Authorization definition | ||
|
|
||
| You can define authorization for any method in the Netgrif Application Engine project. | ||
| You can use the new `@Authorize` annotation over the method definitions. This annotation can | ||
| be defined once or multiple times over a method: | ||
|
|
||
| ``` | ||
| @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)" | ||
| void importPetriNet(File petriNet) { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| The ``@Authorize`` annotation has two fields: | ||
| - `authority` - an authority, that the authenticated user is needed to be checked for | ||
| - `expression` - an expression that returns boolean and serves as additional authorization | ||
|
|
||
| ## Authorization check | ||
|
|
||
| The statements are evaluated in `BaseAuthorizationServiceAspect` bean that is implemented using AOP. The user will have | ||
| valid authorization if it has the required `authority` AND fulfills additional authorization defined | ||
| in `expression` (authority check returns `true` AND expression check returns `true`). | ||
|
|
||
|
|
||
| If there is no `authority` defined, the authorization method returns `true` for authority check. | ||
| In the following example, user must fulfill addition authorization implemented in `canUpload(String userId)` | ||
| function: | ||
| ``` | ||
| @Authorize(expression = "#canUpload(#userId)) | ||
| void importPetriNet(File petriNet) { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| If there is no `expression` defined, the authorization method always returns`true` for expression check. | ||
| In the following example, user must have `PROCESS_UPLOAD` authority: | ||
| ``` | ||
| @Authorize(authority = "PROCESS_UPLOAD") | ||
| void importPetriNet(File petriNet) { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| If there are more authorizations defined using `@Authorize`, then OR statement is valid | ||
| between the multiple `@Authorize` statements, so user must fulfill at least one `@Authorize` statement. | ||
| In the following example, the logged user must have `PROCESS_UPLOAD` authority AND must fulfill `canUpload(String userId)` | ||
| expression, OR must fulfill `isAdmin(String userId)` expression: | ||
| ``` | ||
| @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)", | ||
| @Authorize(expression = "isAdmin(#userId)") | ||
| void importPetriNet(File petriNet) { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,30 @@ | ||
| package com.netgrif.application.engine.startup | ||
|
|
||
| import com.netgrif.application.engine.auth.domain.Authority | ||
| import com.netgrif.application.engine.auth.domain.AuthorizingObject | ||
| import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService | ||
| import groovy.util.logging.Slf4j | ||
| import org.springframework.beans.factory.annotation.Autowired | ||
| import org.springframework.beans.factory.annotation.Value | ||
| import org.springframework.stereotype.Component | ||
|
|
||
| @Slf4j | ||
| @Component | ||
| class AuthorityRunner extends AbstractOrderedCommandLineRunner { | ||
|
|
||
| @Value('${nae.authority.authorizing-objects:}') | ||
| private String[] additionalAuthorizingObjects | ||
|
|
||
| @Autowired | ||
| private IAuthorityService service | ||
|
|
||
| @Override | ||
| void run(String... strings) throws Exception { | ||
| service.getOrCreate(Authority.user) | ||
| service.getOrCreate(Authority.admin) | ||
| service.getOrCreate(Authority.systemAdmin) | ||
| service.getOrCreate(Authority.anonymous) | ||
| createAll() | ||
| } | ||
|
|
||
| void createAll() { | ||
| AuthorizingObject.values().toList().forEach(authority -> service.getOrCreate(authority.name())) | ||
| additionalAuthorizingObjects.toList().forEach(authority -> service.getOrCreate(authority)) | ||
| log.info("Authorities created.") | ||
| } | ||
| } |
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.
in the demo applications, users are allowed to delete their own accounts. It might be helpful to split this authority into
_MYand_ALLThere 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.
I have split the authority to the required two authorities. In the example app and in the base engine there is no endpoint for deleting users, these authorities are only used over actions in action delegate.
Do we want to enable to delete own accounts on actions? Is there a chance that it will cause a problem, when you are calling delete action for own account over assigned task (the task can be assigned to own user)?