VIVO-692 Restrict LOD by Publish level, not by Display level

Create a new annotation for properties and classes, HiddenFromPublishBelowRoleLevelAnnot.
Provide the means to initialize these annotations, edit them, and display them in the verbose property display.
Create a Permission and some requested actions so the policies can decide which statements must be filtered out, based on the user's role.
Add unit tests and improve acceptance tests
This commit is contained in:
j2blake 2014-03-10 17:58:26 -04:00
parent 36087a25c0
commit c084a05832
5 changed files with 1338 additions and 23 deletions

File diff suppressed because it is too large Load diff

View file

@ -11,19 +11,54 @@ function TestLOD() {
this.uri = "lodFacultyMember"; this.uri = "lodFacultyMember";
function setupButtons() { function setupButtons() {
document.getElementById("RDFXML_button").onclick = function() {
<!-- Extension buttons -->
document.getElementById("RDFXML_EXTENSION_button").onclick = function() {
requestWithExtension(self.uri, "rdf");
}
document.getElementById("N3_EXTENSION_button").onclick = function() {
requestWithExtension(self.uri, "n3");
}
document.getElementById("TTL_EXTENSION_button").onclick = function() {
requestWithExtension(self.uri, "ttl");
}
document.getElementById("JSONLD_EXTENSION_button").onclick = function() {
requestWithExtension(self.uri, "jsonld");
}
<!-- Format buttons -->
document.getElementById("RDFXML_FORMAT_button").onclick = function() {
requestWithFormat(self.uri, "rdfxml");
}
document.getElementById("N3_FORMAT_button").onclick = function() {
requestWithFormat(self.uri, "n3");
}
document.getElementById("TTL_FORMAT_button").onclick = function() {
requestWithFormat(self.uri, "ttl");
}
document.getElementById("JSONLD_FORMAT_button").onclick = function() {
requestWithFormat(self.uri, "jsonld");
}
<!-- Accept header buttons -->
document.getElementById("RDFXML_HEADER_button").onclick = function() {
requestWithAcceptHeader(self.uri, "application/rdf+xml"); requestWithAcceptHeader(self.uri, "application/rdf+xml");
} }
document.getElementById("N3_button").onclick = function() { document.getElementById("N3_HEADER_button").onclick = function() {
requestWithAcceptHeader(self.uri, "text/n3"); requestWithAcceptHeader(self.uri, "text/n3");
} }
document.getElementById("TTL_button").onclick = function() { document.getElementById("TTL_HEADER_button").onclick = function() {
requestWithAcceptHeader(self.uri, "text/turtle"); requestWithAcceptHeader(self.uri, "text/turtle");
} }
document.getElementById("JSONLD_button").onclick = function() { document.getElementById("JSONLD_HEADER_button").onclick = function() {
requestWithAcceptHeader(self.uri, "application/json"); requestWithAcceptHeader(self.uri, "application/json");
} }
<!-- Failure buttons -->
document.getElementById("BOGUS_URI_button").onclick = function() { document.getElementById("BOGUS_URI_button").onclick = function() {
requestWithAcceptHeader(self.uri + "XX", "application/rdf+xml"); requestWithAcceptHeader(self.uri + "XX", "application/rdf+xml");
} }
@ -37,40 +72,61 @@ function TestLOD() {
requestWithExtension(self.uri, "bogus"); requestWithExtension(self.uri, "bogus");
} }
document.getElementById("CLEAR_button").onclick = clearResult document.getElementById("CLEAR_REQUEST_button").onclick = clearRequest
document.getElementById("CLEAR_RESPONSE_button").onclick = clearResult
} }
function requestWithAcceptHeader(uri, mimetype) { function requestWithAcceptHeader(uri, mimetype) {
$.ajax({ var parms = {
url: "individual/" + uri, url: "individual/" + uri,
headers: {Accept: mimetype}, headers: {Accept: mimetype},
dataType: "text", dataType: "text",
complete: displayResult complete: displayResult
}); };
displayRequest(parms);
$.ajax(parms);
} }
function requestWithFormat(uri, format) { function requestWithFormat(uri, format) {
$.ajax({ var parms = {
url: "individual/" + uri + "?format=" + format, url: "individual/" + uri + "?format=" + format,
dataType: "text", dataType: "text",
complete: displayResult complete: displayResult
}); };
displayRequest(parms);
$.ajax(parms);
} }
function requestWithExtension(uri, extension) { function requestWithExtension(uri, extension) {
$.ajax({ var parms = {
url: "individual/" + uri + "/" + uri + "." + extension, url: "individual/" + uri + "/" + uri + "." + extension,
dataType: "text", dataType: "text",
complete: displayResult complete: displayResult
}); };
displayRequest(parms);
$.ajax(parms);
}
function displayRequest(parms) {
clearRequest();
$("#requestUrl").text(parms.url);
if (parms.headers) {
$("#acceptHeader").text(parms.headers.Accept);
}
} }
function displayResult(xhr, status) { function displayResult(xhr, status) {
clearResult();
$("#responseCode").text(xhr.status); $("#responseCode").text(xhr.status);
$("#mimeType").text(getMimeType(xhr)); $("#mimeType").text(getMimeType(xhr));
$("#responseText").text(xhr.responseText); $("#responseText").text(xhr.responseText);
} }
function clearRequest() {
$("#requestUrl").text("No URL");
$("#acceptHeader").text("No header");
}
function clearResult() { function clearResult() {
$("#responseCode").text("000"); $("#responseCode").text("000");
$("#mimeType").text("No type"); $("#mimeType").text("No type");
@ -95,21 +151,38 @@ $(document).ready(function() {
<h1>Test the Linked Open Data requests</h1> <h1>Test the Linked Open Data requests</h1>
<h3>Try various accept headers</h3> <h3>Request by extension</h3>
<input type="submit" value="get RDFXML" id="RDFXML_button"> <input type="submit" value="get RDFXML by extension" id="RDFXML_EXTENSION_button">
<input type="submit" value="get N3" id="N3_button"> <input type="submit" value="get N3 by extension" id="N3_EXTENSION_button">
<input type="submit" value="get TTL" id="TTL_button"> <input type="submit" value="get TTL by extension" id="TTL_EXTENSION_button">
<input type="submit" value="get JSONLD" id="JSONLD_button"> <input type="submit" value="get JSONLD by extension" id="JSONLD_EXTENSION_button">
<h3>Try non-existent URI with RDFXML accept header</h3> <h3>Request by format parameters</h3>
<input type="submit" value="get RDFXML by format parameter" id="RDFXML_FORMAT_button">
<input type="submit" value="get N3 by format parameter" id="N3_FORMAT_button">
<input type="submit" value="get TTL by format parameter" id="TTL_FORMAT_button">
<input type="submit" value="get JSONLD by format parameter" id="JSONLD_FORMAT_button">
<h3>Request by accept headers</h3>
<input type="submit" value="get RDFXML by accept header" id="RDFXML_HEADER_button">
<input type="submit" value="get N3 by accept header" id="N3_HEADER_button">
<input type="submit" value="get TTL by accept header" id="TTL_HEADER_button">
<input type="submit" value="get JSONLD by accept header" id="JSONLD_HEADER_button">
<h3>An assortment of failures</h3>
<input type="submit" value="get BOGUS Individual" id="BOGUS_URI_button"> <input type="submit" value="get BOGUS Individual" id="BOGUS_URI_button">
<input type="submit" value="use BOGUS Accept header" id="BOGUS_ACCEPT_button"> <input type="submit" value="use BOGUS Accept header" id="BOGUS_ACCEPT_button">
<input type="submit" value="use BOGUS format" id="BOGUS_FORMAT_button"> <input type="submit" value="use BOGUS format" id="BOGUS_FORMAT_button">
<input type="submit" value="use BOGUS extension" id="BOGUS_EXTENSION_button"> <input type="submit" value="use BOGUS extension" id="BOGUS_EXTENSION_button">
<h3>Response data</h3> <h2>Request data</h2>
<input type="submit" value="CLEAR response" id="CLEAR_button"> <input type="submit" value="CLEAR request" id="CLEAR_REQUEST_button">
<div>Request URL is <b><span id="requestUrl">No URL</span></b></div>
<div>Accept header is <b><span id="acceptHeader">No header</span></b></div>
<h2>Response data</h2>
<input type="submit" value="CLEAR response" id="CLEAR_RESPONSE_button">
<div>Response code is <b><span id="responseCode">000</span></b></div> <div>Response code is <b><span id="responseCode">000</span></b></div>
<div>MIME type is <b><span id="mimeType">No type</span></b></div> <div>MIME type is <b><span id="mimeType">No type</span></b></div>
<div>Text is:</div> <div>Text is:</div>
<div id="responseText" style="font-size:small;">No text</div> <div><pre id="responseText" style="font-size:small;">No text</pre></div>

View file

@ -1,8 +1,6 @@
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> . @prefix auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> .
@prefix simplePermission: <java:edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission#> . @prefix simplePermission: <java:edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission#> .
@prefix displayByRole: <java:edu.cornell.mannlib.vitro.webapp.auth.permissions.DisplayByRolePermission#> .
@prefix editByRole: <java:edu.cornell.mannlib.vitro.webapp.auth.permissions.EditByRolePermission#> .
auth:ADMIN auth:ADMIN
auth:hasPermission simplePermission:UseSparqlUpdateApi ; auth:hasPermission simplePermission:UseSparqlUpdateApi ;

View file

@ -0,0 +1,76 @@
=begin
go through the lines of the file.
If you find a line that matches
vitro:hiddenFromDisplayBelowRoleLevelAnnot
and followed by a line that matches
<http://vitro.mannlib.cornell.edu/ns/vitro/role#public> ;
--where "public" may be any string
Insert 2 lines after the second one, replacing Display by Publish on the first, and duplicating the second.
If you find a line that contains
vitro:hiddenFromDisplayBelowRoleLevelAnnot
and does not match it, or is not followed by a line that matches
<http://vitro.mannlib.cornell.edu/ns/vitro/role#public> ;
Issue a warning and continue.
=end
FILE_PATH = "../../rdf/tbox/firsttime/initialTBoxAnnotations.n3"
DISPLAY_URI = "vitro:hiddenFromDisplayBelowRoleLevelAnnot"
DISPLAY_LOCALNAME = "hiddenFromDisplayBelowRoleLevelAnnot"
def read_the_file()
@lines = File.readlines(FILE_PATH);
end
def scan_the_lines()
@lines.each_index do |i|
@line1 = @lines[i]
@line2 = @lines[i+1]
@index = i
if linesContainMatch()
replicateProperty()
else
checkForMismatch()
end
end
end
def linesContainMatch()
return false unless @line1.strip() == DISPLAY_URI
return false unless @line2
return false unless m = @line2.match(/<http:\/\/vitro\.mannlib\.cornell\.edu\/ns\/vitro\/role#(.*)>/)
@role = m[1]
end
def replicateProperty()
newline1 = @line1.gsub(/Display/, "Publish")
newline2 = @line2.gsub(/#.*>/, "##{@role}>")
@lines.insert(@index + 2, newline1, newline2)
end
def checkForMismatch()
return false unless @line1.strip() == DISPLAY_URI
if !@line2
puts "Found display property at end of file"
return
end
if !@line2.match(/^\s*<http:\/\/vitro\.mannlib\.cornell\.edu\/ns\/vitro\/role#(.*)>\s*;\s*$/)
puts "Found bogus clutter in the second line (#{@index}) '#{@line2}'"
return
end
end
def write_the_file()
f = File.new(FILE_PATH+"-modified", "w")
@lines.each() do |line|
f.write(line)
end
f.close()
end
read_the_file()
scan_the_lines()
write_the_file()

View file

@ -0,0 +1,78 @@
=begin
go through the lines of the file.
If you find a line that matches
vitro:hiddenFromDisplayBelowRoleLevelAnnot
and followed by a line that matches
<http://vitro.mannlib.cornell.edu/ns/vitro/role#public> ;
--where "public" may be any string
Insert 2 lines after the second one, replacing Display by Publish on the first, and duplicating the second.
If you find a line that contains
vitro:hiddenFromDisplayBelowRoleLevelAnnot
and does not match it, or is not followed by a line that matches
<http://vitro.mannlib.cornell.edu/ns/vitro/role#public> ;
Issue a warning and continue.
<http://vitro.mannlib.cornell.edu/ns/vitro/0.7#hiddenFromDisplayBelowRoleLevelAnnot>
<http://vitro.mannlib.cornell.edu/ns/vitro/role#public> ;
=end
FILE_PATH = "/Users/jeb228/Documents/EclipseStuff/vivoWorkspace/vivoCornell/productMods/bjl23/ingest/weill/grants/submodels/vivo-tbox2.ttl"
DISPLAY_URI = "<http://vitro.mannlib.cornell.edu/ns/vitro/0.7#hiddenFromDisplayBelowRoleLevelAnnot>"
def read_the_file()
@lines = File.readlines(FILE_PATH);
end
def scan_the_lines()
@lines.each_index do |i|
@line1 = @lines[i]
@line2 = @lines[i+1]
@index = i
if linesContainMatch()
replicateProperty()
else
checkForMismatch()
end
end
end
def linesContainMatch()
return false unless @line1.strip() == DISPLAY_URI
return false unless @line2
return false unless m = @line2.match(/<http:\/\/vitro\.mannlib\.cornell\.edu\/ns\/vitro\/role#(.*)>/)
@role = m[1]
end
def replicateProperty()
newline1 = @line1.gsub(/Display/, "Publish")
newline2 = @line2.gsub(/#.*>/, "##{@role}>")
@lines.insert(@index + 2, newline1, newline2)
end
def checkForMismatch()
return false unless @line1.strip() == DISPLAY_URI
if !@line2
puts "Found display property at end of file"
return
end
if !@line2.match(/^\s*<http:\/\/vitro\.mannlib\.cornell\.edu\/ns\/vitro\/role#(.*)>\s*;\s*$/)
puts "Found bogus clutter in the second line (#{@index}) '#{@line2}'"
return
end
end
def write_the_file()
f = File.new(FILE_PATH+"-modified", "w")
@lines.each() do |line|
f.write(line)
end
f.close()
end
read_the_file()
scan_the_lines()
write_the_file()