Skip to content

Commit

Permalink
#1380: Permission resolving for groups-within-groups for a given dvob…
Browse files Browse the repository at this point in the history
…ject implemented. Additional fixes to logic of group containments and accessing of restricted files
  • Loading branch information
michbarsinai committed Aug 11, 2016
1 parent 86178db commit 05137a0
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 80 deletions.
24 changes: 11 additions & 13 deletions src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ public enum DisplayMode {
private List<Template> dataverseTemplates = new ArrayList();
private Template defaultTemplate;
private Template selectedTemplate;
private String globalId;
private String persistentId;
private String version;
private String protocol = "";
Expand Down Expand Up @@ -318,11 +317,7 @@ public Long getMaxFileUploadSizeInBytes(){
}

public boolean isUnlimitedUploadFileSize(){

if (this.maxFileUploadSizeInBytes == null){
return true;
}
return false;
return (this.maxFileUploadSizeInBytes == null);
}

public boolean isMetadataExportEnabled() {
Expand Down Expand Up @@ -451,9 +446,8 @@ public boolean isNoDVsRemaining() {
* Convenience method for "Download File" button display logic
*
* Used by the dataset.xhtml render logic when listing files
* > Assume user already has view access to the file list
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!
*
* <b>Assumes user already has view access to the file list.</b>
*
* @param fileMetadata
* @return boolean
*/
Expand Down Expand Up @@ -510,13 +504,17 @@ public boolean canDownloadFile(FileMetadata fileMetadata){
// that the User is not an instance of GuestUser, which is similar in
// spirit to the previous check.
// --------------------------------------------------------------------
if (session.getUser() instanceof GuestUser){
this.fileDownloadPermissionMap.put(fid, false);
return false;
}
// Michael: Removeing this for now, might come back later in some version prior
// to releasing this code.
// if (session.getUser() instanceof GuestUser){
// this.fileDownloadPermissionMap.put(fid, false);
// return false;
// }

// --------------------------------------------------------------------
// (3) Does the User have DownloadFile Permission at the **Dataset** level
// Michael: Leaving this in for now, but shouldn't this be alredy resolved
// by the premission system, given that files are never permission roots?
// --------------------------------------------------------------------
if (this.doesSessionUserHaveDataSetPermission(Permission.DownloadFile)){
// Yes, save answer and return true
Expand Down
17 changes: 2 additions & 15 deletions src/main/java/edu/harvard/iq/dataverse/DataversePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,10 @@ public class DataversePage implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(DataversePage.class.getCanonicalName());

public enum EditMode {

CREATE, INFO, FEATURED
}

public enum LinkMode {

SAVEDSEARCH, LINKDATAVERSE
}

Expand Down Expand Up @@ -111,8 +109,8 @@ public enum LinkMode {
private LinkMode linkMode;

private Long ownerId;
private DualListModel<DatasetFieldType> facets = new DualListModel<>(new ArrayList<DatasetFieldType>(), new ArrayList<DatasetFieldType>());
private DualListModel<Dataverse> featuredDataverses = new DualListModel<>(new ArrayList<Dataverse>(), new ArrayList<Dataverse>());
private DualListModel<DatasetFieldType> facets = new DualListModel<>(new ArrayList<>(), new ArrayList<>());
private DualListModel<Dataverse> featuredDataverses = new DualListModel<>(new ArrayList<>(), new ArrayList<>());
private List<Dataverse> dataversesForLinking;
private Long linkingDataverseId;
private List<SelectItem> linkingDVSelectItems;
Expand Down Expand Up @@ -173,10 +171,8 @@ public void setDataverseSubjectControlledVocabularyValues(List<ControlledVocabul
private void updateDataverseSubjectSelectItems() {
DatasetFieldType subjectDatasetField = datasetFieldService.findByName(DatasetFieldConstant.subject);
setDataverseSubjectControlledVocabularyValues(controlledVocabularyValueServiceBean.findByDatasetFieldTypeId(subjectDatasetField.getId()));

}


public LinkMode getLinkMode() {
return linkMode;
}
Expand All @@ -185,7 +181,6 @@ public void setLinkMode(LinkMode linkMode) {
this.linkMode = linkMode;
}


public void setupLinkingPopup (String popupSetting){
if (popupSetting.equals("link")){
setLinkMode(LinkMode.LINKDATAVERSE);
Expand Down Expand Up @@ -242,7 +237,6 @@ public void updateLinkableDataverses() {
public void updateSelectedLinkingDV(ValueChangeEvent event) {
linkingDataverseId = (Long) event.getNewValue();
}
// private TreeNode treeWidgetRootNode = new DefaultTreeNode("Root", null);

public Dataverse getDataverse() {
return dataverse;
Expand All @@ -268,13 +262,6 @@ public void setOwnerId(Long ownerId) {
this.ownerId = ownerId;
}

// public TreeNode getTreeWidgetRootNode() {
// return treeWidgetRootNode;
// }
//
// public void setTreeWidgetRootNode(TreeNode treeWidgetRootNode) {
// this.treeWidgetRootNode = treeWidgetRootNode;
// }
public String init() {
if (dataverse.getAlias() != null || dataverse.getId() != null || ownerId == null) {// view mode for a dataverse
if (dataverse.getAlias() != null) {
Expand Down
45 changes: 28 additions & 17 deletions src/main/java/edu/harvard/iq/dataverse/PermissionServiceBean.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package edu.harvard.iq.dataverse;

import edu.harvard.iq.dataverse.api.datadeposit.SwordAuth;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.authorization.DataverseRole;
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUserServiceBean;
Expand All @@ -10,7 +9,7 @@
import edu.harvard.iq.dataverse.authorization.groups.Group;
import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean;
import edu.harvard.iq.dataverse.authorization.groups.GroupUtil;
import edu.harvard.iq.dataverse.authorization.groups.impl.builtin.AuthenticatedUsers;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.engine.command.Command;
Expand All @@ -28,7 +27,9 @@
import javax.persistence.PersistenceContext;
import static edu.harvard.iq.dataverse.engine.command.CommandHelper.CH;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.stream.Collectors;
import javax.persistence.Query;

/**
Expand All @@ -45,15 +46,10 @@ public class PermissionServiceBean {

private static final Logger logger = Logger.getLogger(PermissionServiceBean.class.getName());

private static final EnumSet<Permission> PERMISSIONS_FOR_AUTHENTICATED_USERS_ONLY = EnumSet.noneOf( Permission.class );

static {
for ( Permission p : Permission.values() ) {
if ( p.requiresAuthenticatedUser() ) {
PERMISSIONS_FOR_AUTHENTICATED_USERS_ONLY.add(p);
}
}
}
private static final Set<Permission> PERMISSIONS_FOR_AUTHENTICATED_USERS_ONLY =
EnumSet.copyOf(Arrays.asList(Permission.values()).stream()
.filter( Permission::requiresAuthenticatedUser )
.collect( Collectors.toList() ));

@EJB
BuiltinUserServiceBean userService;
Expand Down Expand Up @@ -210,9 +206,11 @@ public Set<Permission> permissionsFor( DataverseRequest req, DvObject dvo ) {
// Add permissions specifically given to the user
permissions.addAll( permissionsForSingleRoleAssignee(req.getUser(),dvo) );
Set<Group> groups = groupService.groupsFor(req,dvo);

// Add permissions gained from groups
for ( Group g : groups ) {
permissions.addAll( permissionsForSingleRoleAssignee(g,dvo) );
final Set<Permission> groupPremissions = permissionsForSingleRoleAssignee(g,dvo);
permissions.addAll(groupPremissions);
}

if ( ! req.getUser().isAuthenticated() ) {
Expand Down Expand Up @@ -252,15 +250,18 @@ public Set<Permission> permissionsFor(RoleAssignee ra, DvObject dvo) {


private Set<Permission> permissionsForSingleRoleAssignee(RoleAssignee ra, DvObject d) {
logger.info("PSB:pfsra: "+ ra + " on " + d );
// super user check
// @todo for 4.0, we are allowing superusers all permissions
// for 4.0, we are allowing superusers all permissions
// for secure data, we may need to restrict some of the permissions
if (ra instanceof AuthenticatedUser && ((AuthenticatedUser) ra).isSuperuser()) {
return EnumSet.allOf(Permission.class);
}


// Start with no permissions, build from there.
Set<Permission> retVal = EnumSet.noneOf(Permission.class);

// File special case.
if (d instanceof DataFile) {
// unrestricted files that are part of a release dataset
// automatically get download permission for everybody:
Expand All @@ -274,17 +275,27 @@ private Set<Permission> permissionsForSingleRoleAssignee(RoleAssignee ra, DvObje
for (FileMetadata fm : df.getOwner().getReleasedVersion().getFileMetadatas()) {
if (df.equals(fm.getDataFile())) {
retVal.add(Permission.DownloadFile);
break;
}
}
}
}
}
}

for (RoleAssignment asmnt : assignmentsFor(ra, d)) {
retVal.addAll(asmnt.getRole().permissions());
}
// Direct assignments to ra on d
assignmentsFor(ra, d).forEach(
asmnt -> retVal.addAll(asmnt.getRole().permissions())
);

// Recurse up the group containment hierarchy.
groupService.groupsFor(ra, d).forEach(
grp -> {
logger.info("PSB:pfsra: groups containing "+ ra + ": " + grp );
retVal.addAll(permissionsForSingleRoleAssignee(grp, d));
});

logger.info("PSB: /pfsra" );
return retVal;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/edu/harvard/iq/dataverse/api/TestApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public Response getIpGroupsContaining( @PathParam("address") String addrStr ) {

JsonObjectBuilder r = NullSafeJsonBuilder.jsonObjectBuilder();
r.add( "address", addr.toString() );
r.add( "addressRaw", (addr instanceof IPv4Address) ? ((IPv4Address)addr).toLong() : null);
r.add( "addressRaw", (addr instanceof IPv4Address) ? ((IPv4Address)addr).toBigInteger().toString(): null);
r.add("groups", ipGroupsSvc.findAllIncludingIp(addr).stream()
.map( IpGroup::toString )
.collect(stringsToJsonArray()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ public interface GroupProvider<T extends Group> {

/**
* Looks up the groups this provider has for a role assignee, in the context of a {@link DvObject}.
* This method should be used for group management. Groups for actual requests should be determined
* by calling {@link #groupsFor(edu.harvard.iq.dataverse.engine.command.DataverseRequest, edu.harvard.iq.dataverse.DvObject)}.
* <B>This method should be used for group management. Groups for actual requests should be determined
* by calling {@link #groupsFor(edu.harvard.iq.dataverse.engine.command.DataverseRequest, edu.harvard.iq.dataverse.DvObject)}.</B>
* @param ra
* @param dvo the DvObject which is the context for the groups. May be {@code null}
* @return The set of groups the role assignee is a member of.
* @see #groupsFor(edu.harvard.iq.dataverse.engine.command.DataverseRequest, edu.harvard.iq.dataverse.DvObject)
*/
public Set<T> groupsFor( RoleAssignee ra, DvObject dvo );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.stream.Collectors.toSet;
import java.util.stream.Stream;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Stateless;
Expand Down Expand Up @@ -75,15 +77,19 @@ public ShibGroupProvider getShibGroupProvider() {
return shibGroupProvider;
}

/**
* Finds all the groups {@code req} is part of in {@code dvo}'s context.
* Recurses upwards in {@link ExplicitGroup}s, as needed.
* @param req The request whose group memberships we seek.
* @param dvo The {@link DvObject} we determining the context fo the membership.
* @return The groups {@code req} is part of under {@code dvo}.
*/
public Set<Group> groupsFor( DataverseRequest req, DvObject dvo ) {
Set<Group> groups = new HashSet<>();
// first, get all groups the user directly belongs to
for ( GroupProvider gp : groupProviders.values() ) {
final Set newGroups = gp.groupsFor(req, dvo);
groups.addAll(newGroups);
}

return groupTransitiveClosure(groups, dvo);
return groupTransitiveClosure(
groupProviders.values().stream()
.flatMap(gp->(Stream<Group>)gp.groupsFor(req, dvo).stream())
.collect(toSet()),
dvo);
}

/**
Expand All @@ -94,14 +100,11 @@ public Set<Group> groupsFor( DataverseRequest req, DvObject dvo ) {
* @return
*/
public Set<Group> groupsFor( RoleAssignee ra, DvObject dvo ) {
Set<Group> groups = new HashSet<>();

// first, get all groups the user directly belongs to
for ( GroupProvider gp : groupProviders.values() ) {
groups.addAll( gp.groupsFor(ra, dvo) );
}

return groupTransitiveClosure(groups, dvo);
return groupTransitiveClosure(
groupProviders.values().stream()
.flatMap(gp->(Stream<Group>)gp.groupsFor(ra, dvo).stream())
.collect( toSet() ),
dvo);
}

/**
Expand Down Expand Up @@ -158,11 +161,9 @@ private Set<Group> groupTransitiveClosure(Set<Group> groups, DvObject dvo) {
Set<ExplicitGroup> perimeter = new HashSet<>();
Set<ExplicitGroup> visited = new HashSet<>();

for ( Group g : groups ) {
if ( g instanceof ExplicitGroup ) {
perimeter.add((ExplicitGroup) g);
}
}
groups.stream()
.filter((g) -> ( g instanceof ExplicitGroup ))
.forEachOrdered((g) -> perimeter.add((ExplicitGroup) g));
visited.addAll(perimeter);

while ( ! perimeter.isEmpty() ) {
Expand All @@ -184,9 +185,8 @@ private Set<Group> groupTransitiveClosure(Set<Group> groups, DvObject dvo) {

public Set<Group> findGlobalGroups() {
Set<Group> groups = new HashSet<>();
for ( GroupProvider gp : groupProviders.values() ) {
groups.addAll( gp.findGlobalGroups() );
}
groupProviders.values().forEach(
gp-> groups.addAll( gp.findGlobalGroups() ));
return groups;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import edu.harvard.iq.dataverse.authorization.groups.Group;
import edu.harvard.iq.dataverse.authorization.groups.GroupProvider;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import java.util.Collections;
import java.util.Set;
Expand Down Expand Up @@ -44,9 +45,13 @@ public Set<Group> groupsFor(DataverseRequest req, DvObject dvo ) {

@Override
public Set<Group> groupsFor( RoleAssignee ra, DvObject dvo ) {
return (Set<Group>) ((ra instanceof AuthenticatedUser)
? CollectionHelper.asSet(AllUsers.get(), AuthenticatedUsers.get())
: Collections.singleton(AllUsers.get()));
if ( ra instanceof User) {
return (Set<Group>) ((ra instanceof AuthenticatedUser)
? CollectionHelper.asSet(AllUsers.get(), AuthenticatedUsers.get())
: Collections.singleton(AllUsers.get()));
} else {
return Collections.emptySet();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,21 @@ public Set<ExplicitGroup> findGroups( RoleAssignee ra ) {
public Set<ExplicitGroup> findDirectGroups( RoleAssignee ra ) {
if ( ra instanceof AuthenticatedUser ) {
return provider.updateProvider(
new HashSet<ExplicitGroup>(
new HashSet<>(
em.createNamedQuery("ExplicitGroup.findByAuthenticatedUserIdentifier", ExplicitGroup.class)
.setParameter("authenticatedUserIdentifier", ra.getIdentifier().substring(1))
.getResultList()
));
} else if ( ra instanceof ExplicitGroup ) {
return provider.updateProvider(
new HashSet<ExplicitGroup>(
new HashSet<>(
em.createNamedQuery("ExplicitGroup.findByContainedExplicitGroupId", ExplicitGroup.class)
.setParameter("containedExplicitGroupId", ((ExplicitGroup) ra).getId())
.getResultList()
));
} else {
return provider.updateProvider(
new HashSet<ExplicitGroup>(
new HashSet<>(
em.createNamedQuery("ExplicitGroup.findByRoleAssgineeIdentifier", ExplicitGroup.class)
.setParameter("roleAssigneeIdentifier", ra.getIdentifier())
.getResultList()
Expand Down
Loading

0 comments on commit 05137a0

Please sign in to comment.