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:
parent
36087a25c0
commit
c084a05832
5 changed files with 1338 additions and 23 deletions
File diff suppressed because it is too large
Load diff
|
@ -11,19 +11,54 @@ function TestLOD() {
|
|||
this.uri = "lodFacultyMember";
|
||||
|
||||
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");
|
||||
}
|
||||
document.getElementById("N3_button").onclick = function() {
|
||||
document.getElementById("N3_HEADER_button").onclick = function() {
|
||||
requestWithAcceptHeader(self.uri, "text/n3");
|
||||
}
|
||||
document.getElementById("TTL_button").onclick = function() {
|
||||
document.getElementById("TTL_HEADER_button").onclick = function() {
|
||||
requestWithAcceptHeader(self.uri, "text/turtle");
|
||||
}
|
||||
document.getElementById("JSONLD_button").onclick = function() {
|
||||
document.getElementById("JSONLD_HEADER_button").onclick = function() {
|
||||
requestWithAcceptHeader(self.uri, "application/json");
|
||||
}
|
||||
|
||||
<!-- Failure buttons -->
|
||||
|
||||
document.getElementById("BOGUS_URI_button").onclick = function() {
|
||||
requestWithAcceptHeader(self.uri + "XX", "application/rdf+xml");
|
||||
}
|
||||
|
@ -37,40 +72,61 @@ function TestLOD() {
|
|||
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) {
|
||||
$.ajax({
|
||||
var parms = {
|
||||
url: "individual/" + uri,
|
||||
headers: {Accept: mimetype},
|
||||
dataType: "text",
|
||||
complete: displayResult
|
||||
});
|
||||
};
|
||||
displayRequest(parms);
|
||||
$.ajax(parms);
|
||||
}
|
||||
|
||||
function requestWithFormat(uri, format) {
|
||||
$.ajax({
|
||||
var parms = {
|
||||
url: "individual/" + uri + "?format=" + format,
|
||||
dataType: "text",
|
||||
complete: displayResult
|
||||
});
|
||||
};
|
||||
displayRequest(parms);
|
||||
$.ajax(parms);
|
||||
}
|
||||
|
||||
function requestWithExtension(uri, extension) {
|
||||
$.ajax({
|
||||
var parms = {
|
||||
url: "individual/" + uri + "/" + uri + "." + extension,
|
||||
dataType: "text",
|
||||
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) {
|
||||
clearResult();
|
||||
$("#responseCode").text(xhr.status);
|
||||
$("#mimeType").text(getMimeType(xhr));
|
||||
$("#responseText").text(xhr.responseText);
|
||||
}
|
||||
|
||||
function clearRequest() {
|
||||
$("#requestUrl").text("No URL");
|
||||
$("#acceptHeader").text("No header");
|
||||
}
|
||||
|
||||
function clearResult() {
|
||||
$("#responseCode").text("000");
|
||||
$("#mimeType").text("No type");
|
||||
|
@ -95,21 +151,38 @@ $(document).ready(function() {
|
|||
|
||||
<h1>Test the Linked Open Data requests</h1>
|
||||
|
||||
<h3>Try various accept headers</h3>
|
||||
<input type="submit" value="get RDFXML" id="RDFXML_button">
|
||||
<input type="submit" value="get N3" id="N3_button">
|
||||
<input type="submit" value="get TTL" id="TTL_button">
|
||||
<input type="submit" value="get JSONLD" id="JSONLD_button">
|
||||
<h3>Request by extension</h3>
|
||||
<input type="submit" value="get RDFXML by extension" id="RDFXML_EXTENSION_button">
|
||||
<input type="submit" value="get N3 by extension" id="N3_EXTENSION_button">
|
||||
<input type="submit" value="get TTL by extension" id="TTL_EXTENSION_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="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 extension" id="BOGUS_EXTENSION_button">
|
||||
|
||||
<h3>Response data</h3>
|
||||
<input type="submit" value="CLEAR response" id="CLEAR_button">
|
||||
<h2>Request data</h2>
|
||||
<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>MIME type is <b><span id="mimeType">No type</span></b></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>
|
|
@ -1,8 +1,6 @@
|
|||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
||||
@prefix auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> .
|
||||
@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:hasPermission simplePermission:UseSparqlUpdateApi ;
|
||||
|
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue