Skip to content

Commit

Permalink
Implement 'prepare self-editor-account'
Browse files Browse the repository at this point in the history
Refactor some common tasks into args_checker.rb
  • Loading branch information
j2blake committed Jul 22, 2015
1 parent 03909e3 commit 628d174
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 55 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ A group of commands that will allow you to:
## Structures

### URI List
- One URI per line. Blank lines, or lines that begin with '#', are ignored.
- One URI per line.
- White space at the beginning or end of the line is ignored.
- Blank lines, or lines that begin with '#', are ignored.

### Session List
- One request session per line. Blank lines, or lines that begin with '#', are ignored.
- One request session per line.
- Blank lines, or lines that begin with '#', are ignored.
- A request may be a single URL.
- A request may also specify POST or GET, HTTP headers, and parameters.
- A session may contain multiple requests, with an optional login/logout specification.
Expand All @@ -48,11 +51,10 @@ You provide a file of URIs, and the tool will generate the URLs needed to fetch
If you want a login on each session, provide the email address and password of the desired login account.

```
vivosnap.rb prepare self-editor-account [VIVO_homepage_URL] [uri_list_file] [admin_email] [admin_password] [editor_email] [editor_password]
vivosnap.rb prepare self-editor-account [VIVO_homepage_URL] [uri_list_file] [admin_email:admin_password] [editor_email:editor_password]
```
**NOT IMPLEMENTED**
Write triples to the user accounts model of the VIVO to create the self-editor-account (unless it exists already)
and to make it a proxy editor for all of the URLs in the list.
and to make it a proxy editor for each of the URLs in the list.

```
vivosnap.rb prepare sub-list [session_list_file] [count] [sub_list_file]
Expand Down
271 changes: 268 additions & 3 deletions cmd_prepare_self_editor_account/cmd_prepare_self_editor_account.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,275 @@
=begin
--------------------------------------------------------------------------------
Write triples to the user accounts model of the VIVO to create the
self-editor-account (unless it exists already), and to make it a proxy editor for
all of the URLs in the list.
--------------------------------------------------------------------------------
Export the user-accounts model and parse it as RDF.
Note whether the editor account already exists, by email.
If so,
get the URI
Complain if not a SELF_EDITOR
Complain if not at least one login
Complain if the md5 password is not the one we were planning to use.
Otherwise,
Generate triples to create the account.
URI is <http://vivosnap.proxy/{timestamp}
Name is VIVOSNAP PROXY
email and password as provided
SELF_EDITOR
lastLoginTime now
loginCount = 1
status = ACTIVE
Generate triples
URI proxyEditorFor each URI in the list
Upload the triples file.
--------------------------------------------------------------------------------
vivosnap.rb prepare self-editor-account [VIVO_homepage_URL] [uri_list_file] [admin_email:admin_password] [editor_email:editor_password]
--------------------------------------------------------------------------------
Annoying: all serialization formats remove the datatype from a String literal,
so the literal becomes plain. It doesn't look like this will cause a problem for
VIVO, but it's still annoying.
--------------------------------------------------------------------------------
Need to be logged in for the query
http://localhost:8080/vivo/[email protected]&password=Password
Need to select the config models or we have a real problem!! Creates an empty
user model in the content triple store.
The query request
http://localhost:8080/vivo/ingest?action=outputModel&modelName=http%3A%2F%2Fvitro.mannlib.cornell.edu%2Fdefault%2Fvitro-kb-userAccounts
http://localhost:8080/vivo/ingest ?
action=outputModel &
modelName=http%3A%2F%2Fvitro.mannlib.cornell.edu%2Fdefault%2Fvitro-kb-userAccounts
Info on parsing and querying here: http://blog.datagraph.org/2010/03/rdf-for-ruby
--------------------------------------------------------------------------------
The upload request
POST http://localhost:8080/vivo/uploadRDF
modelName=http://vitro.mannlib.cornell.edu/default/vitro-kb-userAccounts
action="loadRDFData"
filePath=[file contents]
language="N-TRIPLE"
submit="Load Data"
http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTPHeader.html#method-i-set_form
--------------------------------------------------------------------------------
The account record:
PREFIX auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#>
<http://vivo.mydomain.edu/individual/u3804>
a auth:UserAccount ;
auth:emailAddress "[email protected]"^^xsd:string ;
auth:firstName "Proxy"^^xsd:string ;
auth:hasPermissionSet auth:SELF_EDITOR ;
auth:lastName "Proxy"^^xsd:string ;
auth:loginCount "1"^^xsd:int ;
auth:md5password "DC647EB65E6711E155375218212B3964"^^xsd:string ;
auth:proxyEditorFor <http://vivo.mydomain.edu/individual/n3765> ;
auth:status "ACTIVE"^^xsd:string .
--------------------------------------------------------------------------------
The proxy relationship
<http://vitro.mannlib.cornell.edu/ns/vitro/authorization#proxyEditorFor>
<http://vivo.mydomain.edu/individual/n3236> ;
--------------------------------------------------------------------------------
=end
require 'cgi'
require 'rubygems'
require 'httpclient'
require 'rdf'
require 'rdf/raptor'
require 'tempfile'

class CmdPrepareSelfEditorAccount
include ::ArgsChecker

USAGE = 'prepare self-editor-account [VIVO_homepage_URL] [uri_list_file] [admin_email:admin_password] [editor_email:editor_password]'

USER_MODEL = 'http://vitro.mannlib.cornell.edu/default/vitro-kb-userAccounts'

AUTH_EMAIL_ADDRESS = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#emailAddress')
AUTH_FIRST_NAME = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#firstName')
AUTH_HAS_PERMISSIONS = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#hasPermissionSet')
AUTH_LAST_NAME = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#lastName')
AUTH_LOGIN_COUNT = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#loginCount')
AUTH_MD5_PASSWORD = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#md5password')
AUTH_PROXY_EDITOR_FOR = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#proxyEditorFor')
AUTH_SELF_EDITOR = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#SELF_EDITOR')
AUTH_STATUS = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#status')
AUTH_USER_ACCOUNT = RDF::URI.new('http://vitro.mannlib.cornell.edu/ns/vitro/authorization#UserAccount')
def initialize(args)
bogus "CmdPrepareSelfEditorAccount.initialize NOT IMPLEMENTED"
@args = args

complain("usage: #{USAGE}") unless 4 == args.size

@vivo_home_url = confirm_vivo_home_url(args[0])
@uri_list_file = confirm_file_exists(args[1])
@admin_email, @admin_password = split_credentials(args[2])
@proxy_email, @proxy_password = split_credentials(args[3])
end


def split_credentials(arg)
complain("usage: #{USAGE}") unless 1 == arg.count(':')
arg.split(':')
end

def run()
bogus "CmdPrepareSelfEditorAccount.run NOT IMPLEMENTED"
look_for_existing_self_editor
prepare_upload_rdf_file
upload_rdf
report
end

def look_for_existing_self_editor
export_user_model
parse_user_model
inspect_user_model
end

def export_user_model()
@session = HTTPClient.new

login_parms = { 'email' => @admin_email, 'password' => @admin_password }
res = @session.get(add_to_home_url(@vivo_home_url, 'programLogin'), login_parms, nil, true)
raise UserInputError.new("Invalid admin credentials: #{@admin_email}:#{@admin_password}") unless res.status == 200

parms = {'action' => 'configModels', 'modelName' => USER_MODEL}
res = @session.get(add_to_home_url(@vivo_home_url, 'ingest'), parms, nil, true)
raise "Failed to show configModels." unless res.content.include?(USER_MODEL)

export_parms = {'action' => 'outputModel', 'modelName' => USER_MODEL}
res = @session.get(add_to_home_url(@vivo_home_url, 'ingest'), export_parms, nil, true)
raise "Failed to export the User Accounts model." unless res.status == 200

@user_model_string = res.content
end

def parse_user_model()
@user_model_graph = RDF::Graph() do |graph|
RDF::Reader.for(:turtle).new(@user_model_string) do |reader|
reader.each_statement do |statement|
graph << statement
end
end
end
end

def inspect_user_model()
@editor_uri = nil
@create_editor = true

editor_email_stmt = @user_model_graph.first([nil, AUTH_EMAIL_ADDRESS, RDF::Literal.new(@proxy_email)])
return unless editor_email_stmt

editor = editor_email_stmt.subject

self_editor_stmt = @user_model_graph.first([editor, AUTH_HAS_PERMISSIONS, AUTH_SELF_EDITOR])
raise "An account for #{@proxy_email} already exists, but is not a self-editor." unless self_editor_stmt

login_count = @user_model_graph.first_literal([editor, AUTH_LOGIN_COUNT, nil])
raise "An account for #{@proxy_email} already exists, but has never logged in." unless login_count && login_count.value.to_i > 0

md5_password = @user_model_graph.first_literal([editor, AUTH_MD5_PASSWORD, nil])
raise "An account for #{@proxy_email} already exists, but the password is not '#{@proxy_password}'." unless md5_password && md5_password.to_s == encode_md5(@proxy_password)

@editor_uri = editor.to_s
@create_editor = false
end

def add_to_home_url(home_url, path)
if home_url.end_with?('/')
home_url + path
else
home_url + '/' + path
end
end

def prepare_upload_rdf_file
insert_account_statements unless @editor_uri
insert_proxy_statements
write_graph_to_a_file
end

def insert_account_statements()
@editor_uri = "http://vivosnap.proxy/#{Time.now.to_f}"
editor = RDF::URI.new(@editor_uri)

@user_model_graph << RDF::Statement.new(editor, RDF::type, AUTH_USER_ACCOUNT)
@user_model_graph << RDF::Statement.new(editor, AUTH_EMAIL_ADDRESS, string_literal(@proxy_email))
@user_model_graph << RDF::Statement.new(editor, AUTH_FIRST_NAME, string_literal('VIVOSNAP'))
@user_model_graph << RDF::Statement.new(editor, AUTH_HAS_PERMISSIONS, AUTH_SELF_EDITOR)
@user_model_graph << RDF::Statement.new(editor, AUTH_LAST_NAME, string_literal('PROXY'))
@user_model_graph << RDF::Statement.new(editor, AUTH_LOGIN_COUNT, RDF::Literal.new(1))
@user_model_graph << RDF::Statement.new(editor, AUTH_MD5_PASSWORD, string_literal(encode_md5(@proxy_password)))
@user_model_graph << RDF::Statement.new(editor, AUTH_STATUS, string_literal('ACTIVE'))
end

def insert_proxy_statements
@proxy_count = 0
editor = RDF::URI.new(@editor_uri)
File.open(@uri_list_file) do |f|
f.each_line do |uri|
next if uri.start_with?('#') || uri.strip.empty?
@user_model_graph << RDF::Statement.new(editor, AUTH_PROXY_EDITOR_FOR, RDF::URI.new(uri.strip))
@proxy_count += 1
end
end
end

def write_graph_to_a_file()
@temp_file = Tempfile.new('user_model')
RDF::Writer.for(:ntriples).new(@temp_file) do |writer|
@user_model_graph.each_statement do |statement|
writer << statement
end
end
@temp_file.rewind
end

def upload_rdf
begin
parms = { 'action' => 'loadRDFData', 'modelName' => USER_MODEL, 'filePath' => @temp_file, 'language' => 'N-TRIPLE' }
res = @session.post(add_to_home_url(@vivo_home_url, 'uploadRDF'), parms)
raise "Failed to load the user model: status is #{res.status}." unless res.status == 200
ensure
@temp_file.close
@temp_file.unlink
end
end

def string_literal(s)
RDF::Literal.new(s, :datatype => RDF::XSD.string)
end

def encode_md5(raw)
Digest::MD5.new.digest(raw).each_byte.map { |b| b.to_s(16) }.join.upcase
end

def report()
puts
if @create_editor
puts "Created user account #{@proxy_email}:#{@proxy_password}"
else
puts "Found existing user account #{@proxy_email}:#{@proxy_password}"
end
puts "Set #{@proxy_count} auth:proxyEditorFor statements on #{@editor_uri}"
puts
end

end

35 changes: 15 additions & 20 deletions cmd_prepare_session_list/cmd_prepare_session_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,30 @@ def initialize(args)

complain("usage: #{USAGE}") unless (1..3).include? args.size

@uri_list_file = args[0]
complain("'#{@uri_list_file}' does not exist.") unless File.exist?(@uri_list_file)
@uri_list_file = confirm_file_exists(args[0])
@credential, @session_list_file = parse_remaining_args(args)
@output = set_output_io(@session_list_file, @replace)
end

def parse_remaining_args(args)
case args.size
when 1
@credentials = nil
@session_list_file = nil
[nil, nil]
when 2
if args[1].include?(':')
@credentials = args[1].split(':')
@session_list_file = nil
[split_credentials(args[1]), nil]
else
@credentials = nil
@session_list_file = args[1]
[nil, args[1]]
end
else
@credentials = args[1].split(':')
@session_list_file = args[2]
end

complain("usage: #{USAGE}") if @credentials && @credentials.size != 2

if (@session_list_file)
complain("#{@session_list_file} already exists. Specify REPLACE to overwrite.") if File.exist?(@session_list_file) unless @replace
@output = File.open(@session_list_file, 'w')
else
@output = $stdout
else # 3
[split_credentials(args[1]), args[2]]
end
end

def split_credentials(arg)
complain("usage: #{USAGE}") unless 1 == arg.count(':')
arg.split(':')
end

def run()
write_heading
Expand Down
26 changes: 4 additions & 22 deletions cmd_prepare_uri_list/cmd_prepare_uri_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,13 @@ class CmdPrepareUriList
USAGE = 'prepare uri-list [class_list_file] [VIVO_homepage_URL] {uri_list_file {REPLACE}}'
def initialize(args)
@args = args

@replace = args.delete('REPLACE')

complain("usage: #{USAGE}") unless (2..3).include? args.size

@class_list_file = args[0]
complain("'#{@class_list_file}' does not exist.") unless File.exist?(@class_list_file)

@vivo_home_url = args[1]
begin
HttpRequest.new(@vivo_home_url).exec do |response|
complain("Response from '#{@vivo_home_url}' does not look like VIVO's home page.") unless response.body =~ /body class="home"/
end
rescue
puts "#{$!}\n#{$!.backtrace.join("\n")}"
complain("Can't contact VIVO at '#{@vivo_home_url}': #{$!}")
end

@uri_list_file = args[2]

if @uri_list_file
complain("'#{@uri_list_file}' already exists. Specify REPLACE to replace it.") if File.exist?(@uri_list_file) unless @replace
@output = File.open(@uri_list_file, 'w')
else
@output = $stdout
end
@class_list_file = confirm_file_exists(args[0])
@vivo_home_url = confirm_vivo_home_url(args[1])
@output = set_output_io(args[2], @replace)
end

def run()
Expand Down
Loading

0 comments on commit 628d174

Please sign in to comment.