package edu.harvard.iq.dataverse.authorization;
import edu.harvard.iq.dataverse.DataFile;
import edu.harvard.iq.dataverse.Dataset;
import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DvObject;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* All the permissions in the system are implemented as enum values in this
* class. For performance, the permissions are stored internally in a bit field
* (in effect, a {@code long}). This brings database fetches to a single action
* rather than a join, and in-memory permission set unions to a bitwise or
* rather than a tree merge. But some caution must be practiced when making
* changes to this class.
*
* =========================================================
* IMPORTANT NOTES, READ BEFORE MAKING CHANGES TO THIS FILE
* =========================================================
*
* 1. Number of permissions must be kept under 64. If more
* than 64 permissions are needed, storage must be updated
* to include two {@code long}s, rather then the current one.
* 2. Do not change the order of the enum values, and add new values only
* after the last enum value. If you wish to change the order or add a
* permission in between existing ones (or at the beginning), ALSO PROVIDE
* A MIGRATION SCRIPT FOR THE DATABASE. Otherwise, permissions in the
* database will be mis-assigned. This may be a major security issue.
*
* @author michael
*/
public enum Permission implements java.io.Serializable {
// Create
AddDataverse("Add a dataverse within another dataverse", true, Dataverse.class),
AddDataset("Add a dataset to a dataverse", true, Dataverse.class),
// Read
ViewUnpublishedDataverse("View an unpublished dataverse", false, Dataverse.class),
ViewUnpublishedDataset("View an unpublished dataset and its files", false, Dataset.class),
DownloadFile("Download a file", false, DataFile.class),
// Update
EditDataverse("Edit a dataverse's metadata, facets, customization, and templates ", true, Dataverse.class),
EditDataset("Edit a dataset's metadata", true, Dataset.class),
ManageDataversePermissions("Manage permissions for a dataverse", true, Dataverse.class),
ManageDatasetPermissions("Manage permissions for a dataset", true, Dataset.class),
PublishDataverse("Publish a dataverse", true, Dataverse.class),
PublishDataset("Publish a dataset", true, Dataset.class),
// Delete
DeleteDataverse("Delete an unpublished dataverse", true, Dataverse.class),
DeleteDatasetDraft("Delete a dataset draft", true, Dataset.class);
// FUTURE:
//RestrictMetadata("Mark metadata as restricted", DvObject.class),
//AccessRestrictedMetadata("Access metadata marked as\"restricted\"", DvObject.class),
/**
* A human readable name for the permission.
*/
private final String humanName;
/**
* Which types of {@link DvObject}s this permission applies to.
*/
private final Set<Class<? extends DvObject>> appliesTo;
/**
* Can this permission be applied only to {@link AuthenticatedUser}s, or to any user?
*/
private final boolean requiresAuthenticatedUser;
Permission(String aHumanName, boolean authenticatedUserRequired, Class<? extends DvObject>... appliesToList) {
humanName = aHumanName;
appliesTo = new HashSet<>(Arrays.asList(appliesToList));
requiresAuthenticatedUser = authenticatedUserRequired;
}
public String getHumanName() {
return humanName;
}
public boolean appliesTo(Class<? extends DvObject> aClass) {
for (Class<? extends DvObject> c : appliesTo) {
if (c.isAssignableFrom(aClass)) {
return true;
}
}
return false;
}
public boolean requiresAuthenticatedUser() {
return requiresAuthenticatedUser;
}
}