-
Notifications
You must be signed in to change notification settings - Fork 85
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
[VIVO-1436] Implementation of Advanced Role Management #80
Conversation
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.
Should AdditionalURIsForClassGroupChangesTest
and VClassGroupCacheTest
be updated to remove reference to "hiddenFromDisplayBelowRoleLevelAnnot and "prohibitedFromUpdateBelowRoleLevelAnnot"?
/** | ||
* Create a list of all known non-public PermissionSets. | ||
*/ | ||
protected static List<PermissionSet> buildListOfSelectableRoles(WebappDaoFactory wadf) { |
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.
Can this method be private
?
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.
Attached comments for substantive issues to a number of files. Additional comments to follow.
} | ||
} finally { | ||
qexec.close(); | ||
query.clone(); |
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.
What purpose does it serve to clone the query?
* Instance fields for each EntityPermission | ||
*/ | ||
private final Set<PropertyDao.FullPropertyKey> authorizedKeys = new HashSet<>(); | ||
private final Set<String> authorizedResources = new HashSet<>(); |
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.
It appears that authorizedResources is never used. Am I missing something?
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.
This is because authorisation checks on resources in the existing code always results in authorisation being granted, and so this branch reflects that behaviour.
It's an open question as to whether we should fully implement resource checks - I can see cases where it would be required, but it may also cause a significant issue for upgrading existing sites.
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.
This isn't a reason to keep a private final variable whose value is never accessed. If we need it in the future, we'll add it.
api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/permissions/EntityPermission.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
public abstract boolean isRelated(OntModel ontModel, List<String> fromUris, List<String> toUris); |
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.
The parameter ontModel
is not documented. What model is being passed in here? The subclasses that are required to implement this method will need to know.
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.
This is true, although the previous version of the class took an ontModel in the constructor and stored it as a field - and it wasn't documented as to what model is being passed in there.
Substantively, the only change to this class has been to have the ontModel passed in as part of the check, rather than to rely on one having been set in the constructor.
Off-hand I can't remember specifically why this change was required, but it will be something to do with needing to move where the construction takes place.
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.
I understand that you can't be responsible for the shortcomings of any code that you touch. But you created this method signature. It should not be a challenge for you to say what it does.
@@ -104,4 +106,5 @@ | |||
*/ | |||
Collection<PermissionSet> getAllPermissionSets(); | |||
|
|||
void setEntityPermissions(String entityKey, Collection<PermissionSet> displaySets, Collection<PermissionSet> editSets, Collection<PermissionSet> publishSets); |
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.
An interface method must be documented, or no-one will know how to implement it. What is entityKey? Is it a URL? What is an entity in this context? Will the method accept null arguments?
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.
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.
That's another interesting question, but not the one that I was raising.
You have modified an interface with 11 public methods, all documented, by adding a 12th method with no documentation. Aside from it being bad practice, what happened to that "consistency with existing code" that you mention in your other responses?
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.
resolved
...n/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/filters/FilterByDisplayPermission.java
Outdated
Show resolved
Hide resolved
...n/java/edu/cornell/mannlib/vitro/webapp/dao/filtering/filters/FilterByDisplayPermission.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
public static boolean anyRelated(OntModel ontModel, List<String> fromUris, List<String> toUris) { |
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.
The parameter ontModel
is not documented, nor is it self-evident. What model do callers need to pass in here?
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.
home/src/main/resources/rdf/tbox/filegraph/vitro-0.7.owl
still contains references to
http://vitro.mannlib.cornell.edu/ns/vitro/0.7#hiddenFromDisplayBelowRoleLevelAnnot
,
http://vitro.mannlib.cornell.edu/ns/vitro/0.7#prohibitedFromUpdateBelowRoleLevelAnnot
, and
http://vitro.mannlib.cornell.edu/ns/vitro/0.7#hiddenFromDisplayBelowRoleLevelAnnot
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.
This is my full list of review points, including comments on unused code, commented code, undocumented methods, and others.
Since the project doesn't have a style guide, these are simply observations. Act on them or not, as you see fit.
General
Documentation | Important classes have no comments at the class level. What is the RelationshipCheckerRegistry? What is an EntityPermission? | |
Documentation | Non-private methods should have comments to establish the semantic contract of the method. What goes in, what comes out, what causes exceptions? This is even more true for abstract methods, where one cannot deduce the contract from the implementation. |
Vitro - main
edu.cornell.mannlib.vedit.controller.BaseEditController
line 215 | Documentation | What is a "permissionsNamespace"? Is this the name of the entity on which permissions are being edited? Comment the arguments, or at least use more descriptive names. |
lines 256-281 | Documentation | The comment says we are creating a list of non-public PermissionSets. The actual list contains both public and non-public PermissionSets. |
line 283 | Style | Why not declare permission as Class<? extends EntityPermission> permission Avoid the compiler warning, and enforce a reasonable restriction. |
line 288 | Style | Surely this line is too long to be easily read. Insert line-breaks or break into smaller statements. |
line 298 | Logic | What purpose does it serve to clone the query? |
edu.cornell.mannlib.vedit.controller.OperationController
OK
edu.cornell.mannlib.vitro.webapp.auth.permissions.BrokenPermission
OK
edu.cornell.mannlib.vitro.webapp.auth.permissions.EntityPermission
General | Documentation | What is an EntityPermission? What do the fields represent? I.e., what are keys and what are resources? What does it mean to be limited to a related user? Related to what? How is an EntityPermission represented in the user accounts model? |
line 45, etc. | Logic | It appears that authorizedResources is never used. Am I missing something? |
lines 88, 122, 152 | Style | When is a line too long to be easily readable? Insert line breaks, or break the line into simpler statements. |
lines 69-71, 83, 86 | Language and Libraries | This check could be done at compile time by changing the method signature to private static void getAllInstances(Class<? extends EntityPermission> clazz) That would permit ctor to be declared as Constructor<? extends EntityPermission> in line 83, and remove the need for a cast in line 86 |
line 88, 203 | Language and Libraries | When testing for the presence of a single statement, simplify the code and clarify the intent by calling contains() instead of listStatements(). |
lines 94-101 | User interaction | These exceptions could arise frequently, simply from a typo in the configuration file. They should be handled with more grace. Create a meaningful message and write to the log instead of sysout. |
line 110 | Documentation | Why is updateAllPermissions() public? When might it be called? |
line 144, 185 | Documentation | Why is update() not private? Might a subclass want to override it? Why is updateFor() not private? |
line 186 | Style | uri should have a more descriptive name, perhaps propertyUri. |
line 253 | Logic | This should read as follows: if (objectUri != null && userUri.equals(objectUri)) { Note: this could also be simplified to: if (userUri.equals(objectUri)) { Since equals() will return false if objectUri is null. |
edu.cornell.mannlib.vitro.webapp.auth.permissions.EntityDisplayPermission
line 10 | Style | Don't use wild cards in import statements |
lines 34-35, 40-43, 47 | Documentation | Either remove the commented code, or explain why it is there. |
edu.cornell.mannlib.vitro.webapp.auth.permissions.EntityPublishPermission
lines 35-36, 41-44, 49 | Documentation | Either remove the commented code, or explain why it is there. |
edu.cornell.mannlib.vitro.webapp.auth.permissions.EntityPublishPermission
OK
edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionRegistry
OK
edu.cornell.mannlib.vitro.webapp.auth.permissions.Permission
line 34 | Documentation | In isAuthorized(), the parameter "userUris" is not documented. If someone wants to create a concrete implementaiton of this method, how are they to know what this parameter is or does? If someone calls this method, how do they know what to pass in this parameter? What do the URIs represent? Is the list permitted to be null, or merely empty? |
edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission
OK
edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionListener
line 12 | Logic | import of FullPropertyKey is not used. |
lines 30, 42, 54 | User interaction | The log message still refers to RoleRestrictedProperty, which is no longer correct. |
edu.cornell.mannlib.vitro.webapp.auth.policy.setup.CommonPolicyFamilySetup
OK
edu.cornell.mannlib.vitro.webapp.auth.policy.specialrelationships.RelationshipChecker
line 45 | Documentation | The parameter ontModel is not documented. What model is being passed in here? The subclasses that are required to implement this method might need to know. |
edu.cornell.mannlib.vitro.webapp.auth.policy.PermissionsPolicy
OK
edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean
OK
edu.cornell.mannlib.vitro.webapp.beans.DataProperty
OK
edu.cornell.mannlib.vitro.webapp.beans.FauxProperty
OK
edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty
OK
edu.cornell.mannlib.vitro.webapp.beans.ResourceBean
OK
edu.cornell.mannlib.vitro.webapp.controller.authenticate.BasicAuthenticator
line 5 | Style | Wild-card import statements are not recommended. |
edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginRedirector
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.utils.RoleLevelOptionsSetup
all lines | Logic | Delete this class. It appears that this class no longer has a purpose. |
edu.cornell.mannlib.vitro.webapp.controller.edit.DatapropEditController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.DatapropRetryController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.EntityEditController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.EntityRetryController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.PropertyEditController
OK | (nice fix of previous erroneous comments) |
edu.cornell.mannlib.vitro.webapp.controller.edit.PropertyRetryController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.VclassEditController
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.VclassRetryController
OK
edu.cornell.mannlib.vitro.webapp.dao.PropertyDao
lines 8, 9 | Logic | These import statements are not used. |
edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDao
lines 6, 10 | Logic | These import statements are not used |
line 109 | Documentation | An interface method must be documented, or no-one will know how to implement it. What is entityKey? Is it a URL? What is an entity in this context? Will the method accept null arguments? |
edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary
lines 58-65 | Documentation | Delete these lines, or explain what they are. |
edu.cornell.mannlib.vitro.webapp.dao.filtering.DataPropertyFiltering
line 9 | Logic | This import statement is not used. |
edu.cornell.mannlib.vitro.webapp.dao.filtering.IndividualFiltering
line 22 | Logic | This import statement is not used. |
edu.cornell.mannlib.vitro.webapp.dao.filtering.ObjectPropertyFiltering
line 9 | Logic | This import statement is not used. |
edu.cornell.mannlib.vitro.webapp.dao.filtering.UserAccountsDaoFiltering
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.DataPropertyDaoJena
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.FauxPropertyDaoJena
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.JenaBaseDao
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.JenaBaseDaoCon
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.ObjectPropertyDaoJena
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.UserAccountsDaoJena
lines 7, 15, 16 | Logic | These import statements are not used. |
edu.cornell.mannlib.vitro.webapp.dao.Jena.VClassDaoJena
OK
edu.cornell.mannlib.vitro.webapp.dao.Jena.VClassJena
lines 14,16,17,20 | Logic | These import statements are not used. |
edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.FilterByDisplayPermission
general | Logic | This is a mystery. permissionSetUri is never used. Is that intentional? Is it used by reflection somewhere? And indeed, this class appears to be referenced only by VitroFilterUtils.getPublicFilter(). If it is not used, then do you need more than one constructor with zero arguments? |
lines 35, 69 | Logic | permissionSetUri is never used |
lines 65-67 | Logic | Given that permissionSetUri is never used, is there any need for this null check? Is there any need to pass the uri parameter at all? |
lines 78-79 | Logic | These lines suggest that this class is incomplete. As a filter, this class seems to have no effect at all. But wouldn't that affect the contents of the search index, and the vclass cache? What am I missing? |
edu.cornell.mannlib.vitro.webapp.migration.auth.AuthMigrator
lines 270-274 | Logic | This method is not used. |
edu.cornell.mannlib.vitro.webapp.utils.RelationshipCheckerRegistry
line 27 | Documentation | The parameter ontModel is not documented, nor is it self-evident. What model do callers need to pass in here? |
edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.FauxObjectPropertyWrapper
OK
edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.PropertyTemplateModel
OK
Vitro - test
edu.cornell.mannlib.vitro.webapp.auth.identifier.factory.HasPermissionFactoryTest
OK
edu.cornell.mannlib.vitro.webapp.controller.edit.AuthenticateTest
OK
edu.cornell.mannlib.vitro.webapp.dao.jena.DataPropertyDaoJenaTest
OK
edu.cornell.mannlib.vitro.webapp.dao.jena.ObjectPropertyDaoJenaTest
OK
edu.cornell.mannlib.vitro.webapp.dao.jena.VClassDaoTest
OK
edu.cornell.mannlib.vitro.webapp.dao.jena.VClassJenaTest
OK
stubs.edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDaoStub
OK
Vitro - home
src/main/resources/rdf/auth/everytime/permission_config.n3
OK
Vitro - webapp
src/main/webapp/templates/edit/specific/dataprop_retry.jsp
OK
src/main/webapp/templates/edit/specific/fauxProperty_retry.jsp
OK
src/main/webapp/templates/edit/specific/property_retry.jsp
OK
src/main/webapp/templates/edit/specific/vclass_retry.jsp
OK
src/main/webapp/templates/freemarker/lib/lib-properties.ftl
OK
src/main/webapp/WEB-INF/resources/startup_listeners.txt
OK
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.
Delete this class: edu.cornell.mannlib.vitro.webapp.controller.edit.utils.RoleLevelOptionsSetup
. It is no longer used.
* Create a list of all known non-public PermissionSets. | ||
*/ | ||
protected static List<PermissionSet> buildListOfSelectableRoles(WebappDaoFactory wadf) { | ||
List<PermissionSet> list = new ArrayList<PermissionSet>(); |
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.
Can safely replace new ArrayList<PermissionSet>()
with new ArrayList<>()
.
} | ||
|
||
/** | ||
* Create a list of all known non-public PermissionSets. |
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.
Is this comment correct? It seems that we are collecting the "public" and "non-public" PermissionSets.
return list; | ||
} | ||
|
||
protected static List<String> getGrantedRolesForEntity(OntModel userAccounts, String key, Class permission) { |
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.
Can this method be private
?
} else if (whatToAuth instanceof DisplayDataPropertyStatement) { | ||
DataPropertyStatement stmt = ((DisplayDataPropertyStatement)whatToAuth).getDataPropertyStatement(); | ||
// Check subject as resource | ||
// String subjectUri = stmt.getIndividualURI(); |
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.
The commented-out sections appear to be a "work-in-progress". Please remove dead code as appropriate.
/** | ||
* Static fields for all EntityPermissions | ||
*/ | ||
private static final Map<String, EntityPermission> allInstances = new HashMap<String, EntityPermission>(); |
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.
Please use diamond operator: new HashMap<>()
return p; | ||
} | ||
for (String uri : HasPermissionSet.getPermissionSetUris(ids)) { | ||
return uri; |
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.
Since this for
loop is not looping, the logic may be more clear to simply return the first element if the permission-set is not empty.
} | ||
|
||
/** Get the DisplayByRolePermission from the request, or use Public. */ | ||
public FilterByRoleLevelPermission(HttpServletRequest req) { | ||
this(getPermissionFromRequest(req)); | ||
public FilterByDisplayPermission(HttpServletRequest req) { |
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.
This method does not appear to be called... and can likely be removed.
public static final String CURATOR = "http://vitro.mannlib.cornell.edu/ns/vitro/role#curator"; | ||
public static final String DB_ADMIN = "http://vitro.mannlib.cornell.edu/ns/vitro/role#dbAdmin"; | ||
public static final String NOBODY = "http://vitro.mannlib.cornell.edu/ns/vitro/role#nobody"; | ||
// public static final String PUBLIC = "http://vitro.mannlib.cornell.edu/ns/vitro/role#public"; |
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.
Any reason not do delete these unused variables?
/** | ||
* Old ROLE defintions that were used by the hidden / prohibited assertions | ||
*/ | ||
public static final String ROLE_PUBLIC = "http://vitro.mannlib.cornell.edu/ns/vitro/role#public"; |
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.
These can all be private
.
} | ||
} | ||
|
||
private InputStream makeN3InputStream(Model m) { |
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.
Method is not used and can be removed.
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.
To reproduce the error, go to a user's profile that has some data, click on the RDF link, the "view profile in RDF format".
...src/main/java/edu/cornell/mannlib/vitro/webapp/auth/permissions/EntityPublishPermission.java
Outdated
Show resolved
Hide resolved
From: - Vitro: vivo-project#80 - VIVO: vivo-project/VIVO#85 Resolves: https://github.com/vivo-project/Vitro/pull/80/files#r227428235 https://github.com/vivo-project/Vitro/pull/80/files#r227892906 https://github.com/vivo-project/Vitro/pull/80/files#r227905400 https://github.com/vivo-project/Vitro/pull/80/files#r227907884 https://github.com/vivo-project/Vitro/pull/80/files#r227909775 https://github.com/vivo-project/Vitro/pull/80/files#r227913953 https://github.com/vivo-project/Vitro/pull/80/files#r227913145 https://github.com/vivo-project/Vitro/pull/80/files#r227913209 https://github.com/vivo-project/Vitro/pull/80/files#r227914673 https://github.com/vivo-project/Vitro/pull/80/files#r227915444 https://github.com/vivo-project/Vitro/pull/80/files#r227960329 Not addresses: https://github.com/vivo-project/Vitro/pull/80/files#r227429141 https://github.com/vivo-project/Vitro/pull/80/files#r227434076
From: - Vitro: vivo-project/Vitro#80 - VIVO: vivo-project#85 Resolves: https://github.com/vivo-project/Vitro/pull/80/files#r227428235 https://github.com/vivo-project/Vitro/pull/80/files#r227892906 https://github.com/vivo-project/Vitro/pull/80/files#r227905400 https://github.com/vivo-project/Vitro/pull/80/files#r227907884 https://github.com/vivo-project/Vitro/pull/80/files#r227909775 https://github.com/vivo-project/Vitro/pull/80/files#r227913953 https://github.com/vivo-project/Vitro/pull/80/files#r227913145 https://github.com/vivo-project/Vitro/pull/80/files#r227913209 https://github.com/vivo-project/Vitro/pull/80/files#r227914673 https://github.com/vivo-project/Vitro/pull/80/files#r227915444 https://github.com/vivo-project/Vitro/pull/80/files#r227960329 Not addresses: https://github.com/vivo-project/Vitro/pull/80/files#r227429141 https://github.com/vivo-project/Vitro/pull/80/files#r227434076
Reopening this pull request. In an effort to follow current best practices, the VIVO project will now be developed against the |
ccb92a4
to
fff18ef
Compare
This is being closed due to inactivity; might be reopened in the future. |
Superseded by #398 |
VIVO-1436:
What does this pull request do?
This pull request provides the framework for permissions to view, edit and publish properties to be assigned discretely to roles, rather than as a hierarchy of super-user > user > public.
What's new?
It replaces the Policy code for granting access to properties such that the roles can be given access to or denied access for properties independent of there being a "hierarchy" of roles.
It includes a migration startup listener that will take any old policies defined on existing properties, and convert them to the equivalent role permissions.
The editing of properties has been updated to provide checkboxes for assigning properties to roles, rather than a drop-down of a role hierarchy.
Property permissions are now stored in the User Accounts model, along with the other role and permission settings.
How should this be tested?
After upgrading, an existing installation should still have the same permissions as before (i.e. the same people should have the same access to view / edit content).
The edit pages for the properties should show checkboxes for the permissions granted, and any changes to the permissions should be honoured.
Creating new properties should default to a "sensible" set of checkboxes being already selected (e.g. all view permissions and editors can update).
Additional Notes:
Documentation will need to be updated for the new permissions.
This should not be merged without also merging the equivalent VIVO pull request.
Interested parties
@VIVO-project/vivo-committers