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

cadc-vos: default to node.lastModified if no date property #211

Merged
merged 5 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions cadc-vos-client/src/main/java/org/opencadc/vospace/client/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
import ca.nrc.cadc.reg.Standards;
import ca.nrc.cadc.util.ArgumentMap;
import ca.nrc.cadc.util.Log4jInit;
import ca.nrc.cadc.util.MultiValuedProperties;
import ca.nrc.cadc.util.PropertiesReader;
import ca.nrc.cadc.util.StringUtil;
import ca.nrc.cadc.uws.ErrorSummary;
import ca.nrc.cadc.uws.ExecutionPhase;
Expand Down Expand Up @@ -1234,22 +1236,22 @@ private void validateCommandArguments(ArgumentMap argMap)
File f = new File(propFile);
if (f.exists()) {
if (f.canRead()) {
try {
Properties p = new Properties();
p.load(new FileReader(f));
for (String key : p.stringPropertyNames()) {
URI keyURI;
try {
keyURI = new URI(key);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("invalid node properties key: " + key);
}
String val = p.getProperty(key);
PropertiesReader pr = new PropertiesReader(f);
MultiValuedProperties mvp = pr.getAllProperties();
for (String key : mvp.keySet()) {
URI keyURI;
try {
keyURI = new URI(key);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("invalid node properties key: " + key);
}
String val = mvp.getFirstPropertyValue(key);
NodeProperty np = new NodeProperty(keyURI, val);
if (val == null || val.trim().isEmpty()) {
properties.add(new NodeProperty(keyURI));
} else {
properties.add(new NodeProperty(keyURI, val));
}
} catch (IOException ex) {
log.info("failed to read properties file: " + f.getAbsolutePath()
+ "(" + ex.getMessage() + ", skipping)");
}
} else {
log.info("cannot read properties file: " + f.getAbsolutePath()
Expand Down
2 changes: 1 addition & 1 deletion cadc-vos-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ sourceCompatibility = 1.8

group = 'org.opencadc'

version = '2.0.5'
version = '2.0.6'

description = 'OpenCADC VOSpace server'
def git_url = 'https://github.com/opencadc/vos'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,9 @@ public boolean hasSingleNodeReadPermission(Node node, Subject subject) {
"Checking group read permission on node \"%s\" (groupRead=\"%s\")",
node.getName(), node.getReadOnlyGroup()));
}
if (applyMaskOnGroupRead(node)) {
if (hasMembership(node.getReadOnlyGroup(), subject)) {
return true; // OK
}

if (hasMembership(node.getReadOnlyGroup(), subject)) {
return true; // OK
}

// the GROUPWRITE property means the user has read+write permission
Expand All @@ -202,9 +201,7 @@ public boolean hasSingleNodeReadPermission(Node node, Subject subject) {
"Checking group write permission on node \"%s\" (groupWrite=\"%s\")",
node.getName(), node.getReadWriteGroup()));
}
if (applyMaskOnGroupReadWrite(node)) {
return hasMembership(node.getReadWriteGroup(), subject); // OK
}
return hasMembership(node.getReadWriteGroup(), subject); // OK
}

return false;
Expand Down Expand Up @@ -238,9 +235,7 @@ public boolean hasSingleNodeWritePermission(Node node, Subject subject) {
"Checking group write permission on node \"%s\" (groupWrite=\"%s\")",
node.getName(), node.getReadWriteGroup()));
}
if (applyMaskOnGroupReadWrite(node)) {
return hasMembership(node.getReadWriteGroup(), subject); // OK
}
return hasMembership(node.getReadWriteGroup(), subject); // OK
}
return false;
}
Expand Down Expand Up @@ -344,50 +339,6 @@ private boolean isOwner(Node node, Subject subject) {
return false;
}

/**
* Return false if mask blocks read
*/
boolean applyMaskOnGroupRead(Node n) {
NodeProperty np = n.getProperty(VOS.PROPERTY_URI_GROUPMASK);
if (np == null || np.getValue() == null) {
return true;
}
String mask = np.getValue();
// format is rwx, each of which can also be -
if (mask.length() != 3) {
log.debug("invalid mask format: " + mask);
return true;
}
if (mask.charAt(0) == 'r') {
log.debug("mask allows read: " + mask);
return true;
}
log.debug("mask disallows read: " + mask);
return false;
}

/**
* Return false if mask blocks write
*/
boolean applyMaskOnGroupReadWrite(Node n) {
NodeProperty np = n.getProperty(VOS.PROPERTY_URI_GROUPMASK);
if (np == null || np.getValue() == null) {
return true;
}
String mask = np.getValue();
// format is rwx, each of which can also be -
if (mask.length() != 3) {
log.debug("invalid mask format: " + mask);
return true;
}
if (mask.charAt(0) == 'r' && mask.charAt(1) == 'w') {
log.debug("mask allows write: " + mask);
return true;
}
log.debug("mask disallows write: " + mask);
return false;
}

/**
* check for delegation cookie and, if present, does an authorization
* against it.
Expand Down
2 changes: 1 addition & 1 deletion cadc-vos/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ sourceCompatibility = 1.8

group = 'org.opencadc'

version = '2.0.1'
version = '2.0.2'

description = 'OpenCADC VOSpace client library'
def git_url = 'https://github.com/opencadc/vos'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public NodeProperty(URI key) {

@Override
public String toString() {
return "NodeProperty[" + this.key + ":" + this.value + ":" + readOnly + "]";
return "NodeProperty[" + this.key + ":" + this.value + ":ro=" + readOnly + ":del=" + markedForDeletion + "]";
}

@Override
Expand Down
132 changes: 70 additions & 62 deletions cadc-vos/src/main/java/org/opencadc/vospace/VOS.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
package org.opencadc.vospace;

import java.net.URI;
import java.util.Set;
import java.util.TreeSet;

/**
* Holder of commonly used constants.
Expand All @@ -80,7 +82,7 @@ public class VOS {

public static final int VOSPACE_20 = 20;
public static final int VOSPACE_21 = 21;

public static enum Detail {
min("min"),
max("max"),
Expand Down Expand Up @@ -115,123 +117,116 @@ public static Detail getValue(String value) {
* Default property delimiter for multi-valued properties
*/
public static final String DEFAULT_PROPERTY_VALUE_DELIM = ",";

/*
* Standard Node Properties defined by the IVOA
*/


public static final String VOSPACE_URI_NAMESPACE = "ivo://ivoa.net/vospace/";

// Denotes a name given to the resource
public static final URI PROPERTY_URI_TITLE = URI.create("ivo://ivoa.net/vospace/core#title");
public static final URI PROPERTY_URI_TITLE = URI.create(VOSPACE_URI_NAMESPACE + "core#title");

// Denotes an entity primarily responsible for making the resource
public static final URI PROPERTY_URI_CREATOR = URI.create("ivo://ivoa.net/vospace/core#creator");
public static final URI PROPERTY_URI_CREATOR = URI.create(VOSPACE_URI_NAMESPACE + "core#creator");

// Denotes the topic of the resource
public static final URI PROPERTY_URI_SUBJECT = URI.create("ivo://ivoa.net/vospace/core#subject");
public static final URI PROPERTY_URI_SUBJECT = URI.create(VOSPACE_URI_NAMESPACE + "core#subject");

// Denotes an account of the resource
public static final URI PROPERTY_URI_DESCRIPTION = URI.create("ivo://ivoa.net/vospace/core#description");
public static final URI PROPERTY_URI_DESCRIPTION = URI.create(VOSPACE_URI_NAMESPACE + "core#description");

// Denotes an entity responsible for making the resource available
public static final URI PROPERTY_URI_PUBLISHER = URI.create("ivo://ivoa.net/vospace/core#publisher");
public static final URI PROPERTY_URI_PUBLISHER = URI.create(VOSPACE_URI_NAMESPACE + "core#publisher");

// Denotes an entity responsible for making contributions to this resource
public static final URI PROPERTY_URI_CONTRIBUTOR = URI.create("ivo://ivoa.net/vospace/core#contributor");
public static final URI PROPERTY_URI_CONTRIBUTOR = URI.create(VOSPACE_URI_NAMESPACE + "core#contributor");

// timestamp of the last modification to the node metadata or stored bytes
public static final URI PROPERTY_URI_DATE = URI.create("ivo://ivoa.net/vospace/core#date");
public static final URI PROPERTY_URI_DATE = URI.create(VOSPACE_URI_NAMESPACE + "core#date");

// Denotes the nature or genre of the resource
public static final URI PROPERTY_URI_TYPE = URI.create("ivo://ivoa.net/vospace/core#type");
public static final URI PROPERTY_URI_TYPE = URI.create(VOSPACE_URI_NAMESPACE + "core#type");

// Denotes the file format, physical medium, or dimensions of the resource
public static final URI PROPERTY_URI_FORMAT = URI.create("ivo://ivoa.net/vospace/core#format");
public static final URI PROPERTY_URI_FORMAT = URI.create(VOSPACE_URI_NAMESPACE + "core#format");

// Denotes an unambiguous reference to the resource within a given context
public static final URI PROPERTY_URI_IDENTIFIER = URI.create("ivo://ivoa.net/vospace/core#identifier");
public static final URI PROPERTY_URI_IDENTIFIER = URI.create(VOSPACE_URI_NAMESPACE + "core#identifier");

// Denotes a related resource from which the described resource is derived
public static final URI PROPERTY_URI_SOURCE = URI.create("ivo://ivoa.net/vospace/core#source");
public static final URI PROPERTY_URI_SOURCE = URI.create(VOSPACE_URI_NAMESPACE + "core#source");

// Denotes a language of the resource
public static final URI PROPERTY_URI_LANGUAGE = URI.create("ivo://ivoa.net/vospace/core#language");
public static final URI PROPERTY_URI_LANGUAGE = URI.create(VOSPACE_URI_NAMESPACE + "core#language");

// Denotes a related resource
public static final URI PROPERTY_URI_RELATION = URI.create("ivo://ivoa.net/vospace/core#relation");
public static final URI PROPERTY_URI_RELATION = URI.create(VOSPACE_URI_NAMESPACE + "core#relation");

// Denotes the spatial or temporal topic of the resource,
// the spatial applicability of the resource,
// or the jurisdiction under which the resource is relevant
public static final URI PROPERTY_URI_COVERAGE = URI.create("ivo://ivoa.net/vospace/core#coverage");
public static final URI PROPERTY_URI_COVERAGE = URI.create(VOSPACE_URI_NAMESPACE + "core#coverage");

// Denotes information about rights held in and over the resource
public static final URI PROPERTY_URI_RIGHTS = URI.create("ivo://ivoa.net/vospace/core#rights");
public static final URI PROPERTY_URI_RIGHTS = URI.create(VOSPACE_URI_NAMESPACE + "core#rights");

// Denotes the amount of space available within a container
public static final URI PROPERTY_URI_AVAILABLESPACE = URI.create("ivo://ivoa.net/vospace/core#availableSpace");
public static final URI PROPERTY_URI_AVAILABLESPACE = URI.create(VOSPACE_URI_NAMESPACE + "core#availableSpace");

// SHALL be used as the protocol URI for a HTTP GET transfer
public static final URI PROTOCOL_HTTP_GET = URI.create("ivo://ivoa.net/vospace/core#httpget");
public static final URI PROTOCOL_HTTP_GET = URI.create(VOSPACE_URI_NAMESPACE + "core#httpget");

// SHALL be used as the protocol URI for a HTTP PUT transfer
public static final URI PROTOCOL_HTTP_PUT = URI.create("ivo://ivoa.net/vospace/core#httpput");
public static final URI PROTOCOL_HTTP_PUT = URI.create(VOSPACE_URI_NAMESPACE + "core#httpput");

// SHALL be used as the protocol URI for a HTTPS GET transfer
public static final URI PROTOCOL_HTTPS_GET = URI.create("ivo://ivoa.net/vospace/core#httpsget");
public static final URI PROTOCOL_HTTPS_GET = URI.create(VOSPACE_URI_NAMESPACE + "core#httpsget");

// SHALL be used as the protocol URI for a HTTPS PUT transfer
public static final URI PROTOCOL_HTTPS_PUT = URI.create("ivo://ivoa.net/vospace/core#httpsput");
public static final URI PROTOCOL_HTTPS_PUT = URI.create(VOSPACE_URI_NAMESPACE + "core#httpsput");

// prototype mount protocol
public static final URI PROTOCOL_SSHFS = URI.create("ivo://cadc.nrc.ca/vospace#SSHFS");

// SHALL be used as the view URI to indicate that a service will accept any view for an import operation
public static final URI VIEW_ANY = URI.create("ivo://ivoa.net/vospace/core#anyview");
public static final URI VIEW_ANY = URI.create(VOSPACE_URI_NAMESPACE + "core#anyview");

// SHALL be used as the view URI to import or export data as a binary file
public static final URI VIEW_BINARY = URI.create("ivo://ivoa.net/vospace/core#binaryview");
public static final URI VIEW_BINARY = URI.create(VOSPACE_URI_NAMESPACE + "core#binaryview");

// SHALL be used by a client to indicate that the service should choose the most appropriate view for a data export
public static final URI VIEW_DEFAULT = URI.create("ivo://ivoa.net/vospace/core#defaultview");
public static final URI VIEW_DEFAULT = URI.create(VOSPACE_URI_NAMESPACE + "core#defaultview");


/*
* Standard Node Properties defined by the CADC
*/

// Property used for identifying a transaction
public static final URI PROPERTY_URI_RUNID = URI.create("ivo://ivoa.net/vospace/core#runid");
public static final URI PROPERTY_URI_RUNID = URI.create(VOSPACE_URI_NAMESPACE + "core#runid");

// The size of the resource
public static final URI PROPERTY_URI_CONTENTLENGTH = URI.create("ivo://ivoa.net/vospace/core#length");
public static final URI PROPERTY_URI_CONTENTLENGTH = URI.create(VOSPACE_URI_NAMESPACE + "core#length");

// The quota of a Container Node.
public static final URI PROPERTY_URI_QUOTA = URI.create("ivo://ivoa.net/vospace/core#quota");
public static final URI PROPERTY_URI_QUOTA = URI.create(VOSPACE_URI_NAMESPACE + "core#quota");

// The content encoding of the resource
public static final URI PROPERTY_URI_CONTENTENCODING = URI.create("ivo://ivoa.net/vospace/core#encoding");
public static final URI PROPERTY_URI_CONTENTENCODING = URI.create(VOSPACE_URI_NAMESPACE + "core#encoding");

// The MD5 Checksum of the resource
public static final URI PROPERTY_URI_CONTENTMD5 = URI.create("ivo://ivoa.net/vospace/core#MD5");
public static final URI PROPERTY_URI_CONTENTMD5 = URI.create(VOSPACE_URI_NAMESPACE + "core#MD5");

// The groups who can read the resource
public static final URI PROPERTY_URI_GROUPREAD = URI.create("ivo://ivoa.net/vospace/core#groupread");
public static final URI PROPERTY_URI_GROUPREAD = URI.create(VOSPACE_URI_NAMESPACE + "core#groupread");
public static final String PROPERTY_DELIM_GROUPREAD = " ";

// The groups who can write to the resource
public static final URI PROPERTY_URI_GROUPWRITE = URI.create("ivo://ivoa.net/vospace/core#groupwrite");
public static final URI PROPERTY_URI_GROUPWRITE = URI.create(VOSPACE_URI_NAMESPACE + "core#groupwrite");
public static final String PROPERTY_DELIM_GROUPWRITE = " ";

// If not null, the mask that must be applied to the values of groupread and groupwrite to
// determine the effective permissions
public static final URI PROPERTY_URI_GROUPMASK = URI.create("ivo://ivoa.net/vospace/core#groupmask");

// Flag indicating if the Node is public (true/false)
public static final URI PROPERTY_URI_ISPUBLIC = URI.create("ivo://ivoa.net/vospace/core#ispublic");

// proposed to support vofs: timestamp of the last modification to the stored bytes (DataNode only)
public static final URI PROPERTY_URI_CREATION_DATE = URI.create("ivo://ivoa.net/vospace/core#creationDate");
public static final URI PROPERTY_URI_ISPUBLIC = URI.create(VOSPACE_URI_NAMESPACE + "core#ispublic");

// proposed: timestamp of the last modification to the stored bytes (DataNode only)
public static final URI PROPERTY_URI_CONTENTDATE = URI.create(VOSPACE_URI_NAMESPACE + "core#content-date");

/*
* CADC Node Properties
Expand All @@ -248,24 +243,6 @@ public static Detail getValue(String value) {
// Flag indicating that the Node children inherit the parent node permissions
public static final URI PROPERTY_URI_INHERIT_PERMISSIONS = URI.create("ivo://cadc.nrc.ca/vospace/core#inheritPermissions");

// Flag indicating that the Node children inherit the parent node permissions
public static final URI PROPERTY_URI_STORAGEID = URI.create("ivo://cadc.nrc.ca/vospace/core#storageID");


/*
* List of properties that are read-only by the user
*/
public static final URI[] READ_ONLY_PROPERTIES = new URI[] {
PROPERTY_URI_DATE,
PROPERTY_URI_CREATOR,
PROPERTY_URI_QUOTA,
PROPERTY_URI_CONTENTLENGTH,
PROPERTY_URI_CONTENTMD5,
PROPERTY_URI_READABLE,
PROPERTY_URI_WRITABLE,
PROPERTY_URI_GROUPMASK
};

/*
* List of IVOA Standard Faults
*/
Expand Down Expand Up @@ -305,4 +282,35 @@ public static Detail getValue(String value) {
// 503
public static final String CADC_FAULT_SERVICE_BUSY = "ServiceBusy";

public static final Set<URI> VOSPACE_CORE_PROPERTIES = new TreeSet<>();

static {
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_TITLE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CREATOR);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_SUBJECT);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_DESCRIPTION);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_PUBLISHER);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CONTRIBUTOR);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_DATE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_TYPE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_FORMAT);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_IDENTIFIER);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_SOURCE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_LANGUAGE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_RELATION);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_COVERAGE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_RIGHTS);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_AVAILABLESPACE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_RUNID);

VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_QUOTA);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CONTENTDATE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CONTENTLENGTH);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CONTENTENCODING);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_CONTENTMD5);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_GROUPREAD);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_GROUPWRITE);
VOSPACE_CORE_PROPERTIES.add(PROPERTY_URI_ISPUBLIC);

}
}
Loading
Loading