Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #691 from MG-RAST/develop

develop into master
  • Loading branch information...
commit 7bd52fdf8d4908348b40789a78ebff8843243e3a 2 parents f405016 + 739ee0a
@jaredbischof jaredbischof authored
View
6 src/MGRAST/cgi/api.cgi
@@ -25,7 +25,7 @@ if (lc($request_method) eq 'options') {
-status => 200,
-type => 'text/plain',
-charset => 'UTF-8',
- -Access_Control_Allow_Methods => 'POST, GET, OPTIONS, PUT',
+ -Access_Control_Allow_Methods => 'POST, GET, OPTIONS, PUT, DELETE',
-Access_Control_Allow_Headers => 'AUTH, AUTHORIZATION'
);
print "";
@@ -148,12 +148,12 @@ else {
# check for authentication
my $user;
-if ($cgi->http('HTTP_AUTH') || $cgi->param('auth') || $cgi->http('HTTP_AUTHORIZATION') || $cgi->param('authorization')) {
+if ($cgi->http('HTTP_AUTH') || $cgi->param('auth') || $cgi->http('HTTP_Authorization') || $cgi->param('authorization')) {
eval {
require Auth;
Auth->import();
my $message;
- ($user, $message) = Auth::authenticate($cgi->http('HTTP_AUTH') || $cgi->param('auth') || $cgi->http('HTTP_AUTHORIZATION') || $cgi->param('authorization'));
+ ($user, $message) = Auth::authenticate($cgi->http('HTTP_AUTH') || $cgi->param('auth') || $cgi->http('HTTP_Authorization') || $cgi->param('authorization'));
unless($user) {
unless ($message eq "valid kbase user") {
print $cgi->header( -type => 'application/json',
View
53 src/MGRAST/html/js/Upload.js
@@ -711,26 +711,39 @@ function check_submitable () {
}
function submit_job () {
- document.getElementById("submit_job_button").disabled = true;
- var seq_files = selected_sequence_files.join('|');
- $.ajax({ async: false, type: "POST", url: "metagenomics.cgi", data: { page: "Upload", action: "check_for_duplicates", seqfiles: seq_files }, success: function (result) {
- if (result == "unique") {
- document.forms.submission_form.submit();
- } else if (result.match(/ERROR/) ) {
- alert(result);
- return false;
- } else {
- if ( confirm(result) ) {
- // If the user allows a duplicate to be loaded into the system, we call a perl subroutine that
- // will e-mail mg-rast@mcs.anl.gov if the duplicate is over 1GB in size (or whatever limit is set in Conf.pm)
- $.ajax({ async: false, type: "POST", url: "metagenomics.cgi", data: { page: "Upload", action: "send_email_for_duplicate_submission", seqfiles: seq_files } });
- document.forms.submission_form.submit();
- } else {
- document.getElementById("submit_job_button").disabled = false;
- return false;
- }
- }
- }});
+ // test if AWE and SHOCK are up
+ jQuery.getJSON( "http://api.metagenomics.anl.gov/heartbeat/AWE", function(data) {
+ if (data.status != 1) {
+ alert("Our submission pipeline is currently out of service. Please try again later.");
+ return;
+ }
+ jQuery.getJSON( "http://api.metagenomics.anl.gov/heartbeat/SHOCK", function(data) {
+ if (data.status != 1) {
+ alert("Our submission pipeline is currently out of service. Please try again later.");
+ return;
+ }
+ document.getElementById("submit_job_button").disabled = true;
+ var seq_files = selected_sequence_files.join('|');
+ $.ajax({ async: false, type: "POST", url: "metagenomics.cgi", data: { page: "Upload", action: "check_for_duplicates", seqfiles: seq_files }, success: function (result) {
+ if (result == "unique") {
+ document.forms.submission_form.submit();
+ } else if (result.match(/ERROR/) ) {
+ alert(result);
+ return false;
+ } else {
+ if ( confirm(result) ) {
+ // If the user allows a duplicate to be loaded into the system, we call a perl subroutine that
+ // will e-mail mg-rast@mcs.anl.gov if the duplicate is over 1GB in size (or whatever limit is set in Conf.pm)
+ $.ajax({ async: false, type: "POST", url: "metagenomics.cgi", data: { page: "Upload", action: "send_email_for_duplicate_submission", seqfiles: seq_files } });
+ document.forms.submission_form.submit();
+ } else {
+ document.getElementById("submit_job_button").disabled = false;
+ return false;
+ }
+ }
+ }});
+ });
+ });
}
function toggle (id) {
View
64 src/MGRAST/lib/Auth.pm
@@ -22,31 +22,68 @@ sub authenticate {
$key =~ s/^mggo4711//;
use MIME::Base64;
+ use LWP::UserAgent;
+ use Conf;
my ($u,$p) = split(/\:/, decode_base64($key));
my $us = $master->User->init( { login => $u } );
if (ref $us and crypt($p, $us->password) eq $us->password) {
my $pref = $master->Preferences->get_objects( { name => 'WebServiceKeyTdate', user => $us } );
- if (scalar(@$pref)) {
+ if (scalar(@$pref)) {
if ($pref->[0]->value < time) {
$pref->[0]->value(time + 1209600);
}
+ my $skeytimeout = $pref->[0]->value();
$pref = $master->Preferences->get_objects( { name => 'WebServicesKey', user => $us } );
- my $cgi = new CGI;
- my $verbose = "";
- if ($cgi->param('verbosity') && $cgi->param('verbosity') eq 'verbose') {
- $verbose = ', "login": "'.$us->{login}.'", "firstname": "'.$us->{firstname}.'", "lastname": "'.$us->{lastname}.'", "email": "'.$us->{email}.'"';
- }
+ my $cgi = new CGI;
+ my $verbose = "";
+ if ($cgi->param('verbosity') && $cgi->param('verbosity') eq 'verbose') {
+ $verbose = ', "login":"'.$us->{login}.'", "firstname":"'.$us->{firstname}.'", "lastname":"'.$us->{lastname}.'", "email":"'.$us->{email}.'", "id":"mgu'.$us->{_id}.'"';
+ # SHOCK preferences
+ my $prefs = $master->Preferences->get_objects({ user => $us, name => "shock_pref_node" });
+ if (scalar(@$prefs)) {
+ my $nodeid = $prefs->[0]->{value};
+ my $response = undef;
+ my $json = new JSON;
+ $json = $json->utf8();
+ $json->max_size(0);
+ $json->allow_nonref;
+ my $agent = LWP::UserAgent->new;
+ eval {
+ my @args = ('Authorization', "mgrast ".$pref->[0]->{value});
+ my $url = $Conf::shock_url.'/node/'.$nodeid;
+ my $get = $agent->get($url, @args);
+ $response = $json->decode( $get->content );
+ };
+ if ($@ || (! ref($response))) {
+ print $cgi->header(-type => 'application/json',
+ -status => 500,
+ -charset => 'UTF-8',
+ -Access_Control_Allow_Origin => '*' );
+ print $json->encode({"ERROR" => "Unable to GET node $nodeid from Shock: ".$response->{error}[0]}, $response->{status} );
+ exit;
+ } elsif (exists($response->{error}) && $response->{error}) {
+ print $cgi->header(-type => 'application/json',
+ -status => 500,
+ -charset => 'UTF-8',
+ -Access_Control_Allow_Origin => '*' );
+ print $json->encode({"ERROR" => "Unable to GET node $nodeid from Shock: ".$response->{error}[0]}, $response->{status} );
+ exit;
+ } else {
+ $verbose.=', "preferences": '.$json->encode($response->{data}->{attributes}->{pref});
+ }
+ }
+ }
print $cgi->header(-type => 'application/json',
-status => 200,
- -charset => 'UTF-8',
+ -charset => 'UTF-8',
-Access_Control_Allow_Origin => '*' );
- print '{ "token": "'.$pref->[0]->value.'"'.$verbose.' }';
+ print '{ "token": "'.$pref->[0]->value.'", "expiration": "'.$skeytimeout.'"'.$verbose.' }';
exit;
} else {
- return (undef, "api access not enabled for this user");
- }
+ return (undef, "api access not enabled for this user");
+ }
} else {
- return (undef, "invalid MG-RAST credentials");
+ return (undef, "invalid MG-RAST credentials");
}
}
@@ -176,6 +213,11 @@ sub authenticate {
}
}
}
+
+ # check for MG-RAST default auth header
+ if ($auth_value =~ /^mgrast /) {
+ $auth_value =~ s/^mgrast //;
+ }
# check for the preference setting for the defined authentication source and value
my $preference = $master->Preferences->get_objects( { name => $auth_source, value => $auth_value } );
View
22 src/MGRAST/lib/GoogleAnalytics.pm
@@ -41,24 +41,20 @@ sub track_page_view {
my $visitor_id = $uid || &get_random_number();
- my $utm_gif_location = "http://www.google-analytics.com/__utm.gif";
+ my $url = "http://www.google-analytics.com/collect";
my $remote_address = "";
if (exists($ENV{'REMOTE_ADDR'})) {
$remote_address = $ENV{'REMOTE_ADDR'};
}
- # Construct the gif hit url.
- my $utm_url = $utm_gif_location . '?' .
- 'utmwv=' . VERSION .
- '&utmn=' . get_random_number() .
- '&utmhn=' . uri_escape($domain_name) .
- '&utmr=' . uri_escape($document_referer) .
- '&utmp=' . uri_escape($document_path) .
- '&utmac=' . $account .
- '&utmcc=__utma%3D999.999.999.999.999.1%3B' .
- '&utmvid=' . $visitor_id .
- '&utmip=' . anonymize_ip($remote_address);
+ # Construct the payload
+ my $content = 'v=' . VERSION .
+ '&tid=' . $account .
+ '&cid=' . anonymize_ip($remote_address) .
+ '&t=pageview' .
+ '&vid=' . $visitor_id .
+ '&dl=' . uri_escape($document_path);
my $ua = LWP::UserAgent->new;
@@ -69,7 +65,7 @@ sub track_page_view {
$ua->agent($ENV{'HTTP_USER_AGENT'});
}
- my $ga_output = $ua->get($utm_url);
+ my $ga_output = $ua->post($url, Content => $content);
if (defined($debug) && !$ga_output->is_success) {
print STDERR $ga_output->status_line;
View
10 src/MGRAST/lib/WebPage/Analysis.pm
@@ -600,8 +600,8 @@ sub single_data {
if ($mg_grp_sel eq 'groups') {
my $joined_data = {};
foreach my $row (@$result) {
- my $id_string = join("|", @$row[1..8]);
$row->[0] = $collections->{$row->[0]};
+ my $id_string = join("|", @$row[0..8]);
if (exists($joined_data->{$id_string})) {
$row->[10] = sprintf("%.2f", (($joined_data->{$id_string}->[9] * $joined_data->{$id_string}->[10]) + ($row->[9] * $row->[10])) / ($joined_data->{$id_string}->[9] + $row->[9]));
$row->[11] = sprintf("%.2f", (($joined_data->{$id_string}->[9] * $joined_data->{$id_string}->[11]) + ($row->[9] * $row->[11])) / ($joined_data->{$id_string}->[9] + $row->[9]));
@@ -715,8 +715,8 @@ sub phylogenetic_data {
if ($mg_grp_sel eq 'groups') {
my $joined_data = {};
foreach my $row (@$result) {
- my $id_string = join("|", @$row[1..9]);
$row->[0] = $collections->{$row->[0]};
+ my $id_string = join("|", @$row[0..9]);
if (exists($joined_data->{$id_string})) {
$row->[12] = sprintf("%.2f", (($joined_data->{$id_string}->[10] * $joined_data->{$id_string}->[12]) + ($row->[10] * $row->[12])) / ($joined_data->{$id_string}->[10] + $row->[10]));
$row->[13] = sprintf("%.2f", (($joined_data->{$id_string}->[10] * $joined_data->{$id_string}->[13]) + ($row->[10] * $row->[13])) / ($joined_data->{$id_string}->[10] + $row->[10]));
@@ -861,8 +861,8 @@ sub metabolic_data {
if ($mg_grp_sel eq 'groups') {
my $joined_data = {};
foreach my $row (@$all) {
- my $id_string = join("|", @$row[1..4]);
$row->[0] = $collections->{$row->[0]};
+ my $id_string = join("|", @$row[0..4]);
if (exists($joined_data->{$id_string})) {
$row->[8] = sprintf("%.2f", (($joined_data->{$id_string}->[6] * $joined_data->{$id_string}->[8]) + ($row->[6] * $row->[8])) / ($joined_data->{$id_string}->[6] + $row->[6]));
$row->[9] = sprintf("%.2f", (($joined_data->{$id_string}->[6] * $joined_data->{$id_string}->[9]) + ($row->[6] * $row->[9])) / ($joined_data->{$id_string}->[6] + $row->[6]));
@@ -966,8 +966,8 @@ sub annotation_data {
if ($mg_grp_sel eq 'groups') {
my $joined_data = {};
foreach my $row (@$result) {
- my $id_string = join("|", @$row[1..2]);
$row->[0] = $collections->{$row->[0]};
+ my $id_string = join("|", @$row[0..2]);
if (exists($joined_data->{$id_string})) {
$row->[5] = sprintf("%.2f", (($joined_data->{$id_string}->[3] * $joined_data->{$id_string}->[5]) + ($row->[3] * $row->[5])) / ($joined_data->{$id_string}->[3] + $row->[3]));
$row->[6] = sprintf("%.2f", (($joined_data->{$id_string}->[3] * $joined_data->{$id_string}->[6]) + ($row->[3] * $row->[6])) / ($joined_data->{$id_string}->[3] + $row->[3]));
@@ -1053,8 +1053,8 @@ sub lca_data {
if ($mg_grp_sel eq 'groups') {
my $joined_data = {};
foreach my $row (@$result) {
- my $id_string = join("|", @$row[1..8]);
$row->[0] = $collections->{$row->[0]};
+ my $id_string = join("|", @$row[0..8]);
if (exists($joined_data->{$id_string})) {
$row->[10] = sprintf("%.2f", (($joined_data->{$id_string}->[9] * $joined_data->{$id_string}->[10]) + ($row->[9] * $row->[10])) / ($joined_data->{$id_string}->[9] + $row->[9]));
$row->[11] = sprintf("%.2f", (($joined_data->{$id_string}->[9] * $joined_data->{$id_string}->[11]) + ($row->[9] * $row->[11])) / ($joined_data->{$id_string}->[9] + $row->[9]));
View
2  src/MGRAST/lib/WebPage/Home.pm
@@ -174,7 +174,7 @@ END
$content .= "<p style='color:#8FBC3F;text-align:left;font-size:9px;margin-top:3px;'>This work was supported in part by the Office of Advanced Scientific Computing Research, Office of Science, U.S. Department of Energy, under Contract DE-AC02-06CH11357.</p>";
- $content .= "<a href=\"http://www.biomedcentral.com/1471-2105/9/386\" target=\"_blank\"><p style='border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; color: white; padding: 5px 0px 3px 10px; color: white; font-size:14; background-color: #5281B0; width: 100px; float: left; margin-right: 10px; top: -12px; position: relative;'>cite MG-RAST</p></a>";
+ $content .= "<a href=\"http://www.biomedcentral.com/1471-2105/9/386\" target=\"_blank\"><p style='border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; color: white; padding: 5px 0px 3px 10px; color: white; font-size:14; background-color: #5281B0; width: 100px; float: left; margin-right: 10px; top: -12px; position: relative;'>cite MG-RAST</p></a><a href=\"http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1004008\" target=\"_blank\" style=\"float: right;\"><p style='border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; color: white; padding: 5px 0px 3px 10px; color: white; font-size:14; background-color: #5281B0; width: 120px; float: left; margin-right: 10px; top: -12px; position: relative;'>cite MG-RAST API</p></a>";
#$content .= "<p style='color:#8FBC3F;text-align:left;font-size:9px;margin-top:3px;'><em>The Metagenomics RAST server - A public resource for the automatic phylogenetic and functional analysis of metagenomes</em> F. Meyer, D. Paarmann, M. D'Souza, R. Olson , E. M. Glass, M. Kubal, T. Paczian , A. Rodriguez , R. Stevens, A. Wilke, J. Wilkening, R. A. Edwards<br/><em>BMC Bioinformatics 2008, 9:386
#, [<a href=\"http://www.biomedcentral.com/1471-2105/9/386\" target=\"_blank\">article</a>]</em></p>";
View
3  src/MGRAST/lib/resources/annotation.pm
@@ -345,6 +345,9 @@ sub print_batch {
$fields = [$solr_key, 'md5_id'];
}
} elsif ($type eq 'feature') {
+ $solr_key = 'accession';
+ $fields = [$solr_key, 'md5_id'];
+ } else {
$fields = ['md5_id'];
}
View
131 src/MGRAST/lib/resources/heartbeat.pm
@@ -0,0 +1,131 @@
+package resources::heartbeat;
+
+use strict;
+use warnings;
+no warnings('once');
+
+use parent qw(resources::resource);
+
+# Override parent constructor
+sub new {
+ my ($class, @args) = @_;
+
+ # Call the constructor of the parent class
+ my $self = $class->SUPER::new(@args);
+
+ # Add name / attributes
+ $self->{name} = "heartbeat";
+ $self->{services} = { 'FTP' => 'ftp://ftp.metagenomics.anl.gov',
+ 'website' => 'http://metagenomics.anl.gov/',
+ 'SHOCK' => $Conf::shock_url,
+ 'AWE' => $Conf::awe_url,
+ 'M5NR' => $Conf::m5nr_solr,
+ 'solr' => $Conf::job_solr,
+ 'postgres' => 'db',
+ 'mySQL' => 'db' };
+ $self->{attributes} = { "service" => [ 'string', "cv", [ ['FTP', 'file server'],
+ ['website', 'MG-RAST website'],
+ ['SHOCK', 'object storage'],
+ ['AWE', 'worker engine'],
+ ['M5NR', 'non-redundant sequence database'],
+ ['solr', 'search engine'],
+ ['postgres', 'analysis database'],
+ ['mySQL', 'job database']
+ ] ],
+ "status" => [ 'boolean', 'service is up or not' ],
+ "url" => [ 'url', 'resource location of this resource']
+ };
+ return $self;
+}
+
+# resource is called without any parameters
+# this method must return a description of the resource
+sub info {
+ my ($self) = @_;
+ my $content = { 'name' => $self->name,
+ 'url' => $self->cgi->url."/".$self->name,
+ 'description' => "Status of services",
+ 'type' => 'object',
+ 'documentation' => $self->cgi->url.'/api.html#'.$self->name,
+ 'requests' => [ { 'name' => "info",
+ 'request' => $self->cgi->url."/".$self->name,
+ 'description' => "Returns description of parameters and attributes.",
+ 'method' => "GET" ,
+ 'type' => "synchronous" ,
+ 'attributes' => "self",
+ 'parameters' => { 'options' => {},
+ 'required' => {},
+ 'body' => {} }
+ },
+ { 'name' => "instance",
+ 'request' => $self->cgi->url."/".$self->name."/{SERVICE}",
+ 'description' => "Returns the status of a service.",
+ 'example' => [ 'curl -X GET -H "auth: auth_key" "'.$self->cgi->url."/".$self->name.'/M5NR"',
+ "status of the M5NR service" ],
+ 'method' => "GET" ,
+ 'type' => "synchronous" ,
+ 'attributes' => $self->attributes,
+ 'parameters' => { 'options' => {},
+ 'required' => { "service" => [ "cv", $self->{attributes}->{service}->[2] ] },
+ 'body' => {} }
+ } ]
+ };
+ $self->return_data($content);
+}
+
+# the resource is called with a service parameter
+sub instance {
+ my ($self) = @_;
+
+ # check id format
+ my $rest = $self->rest;
+ my $id = $rest->[0];
+ if (! $self->{services}->{$id}) {
+ $self->return_data( {"ERROR" => "invalid service name: " . $rest->[0]}, 400 );
+ }
+
+ my $status = 0;
+
+ if ($self->{services}->{$id} eq 'db') {
+ if ($id eq 'postgres') {
+ my $dbh = DBI->connect(
+ "DBI:Pg:database=".$Conf::mgrast_db.";host=".$Conf::mgrast_dbhost.";".$Conf::pgsslcert,
+ $Conf::mgrast_dbuser,
+ $Conf::mgrast_dbpass
+ );
+ if ($dbh) {
+ $status = 1;
+ }
+ } else {
+ my $jobcache_db = $Conf::mgrast_jobcache_db;
+ my $jobcache_host = $Conf::mgrast_jobcache_host;
+ my $jobcache_user = $Conf::mgrast_jobcache_user;
+ my $jobcache_password = $Conf::mgrast_jobcache_password;
+ my $dbh = DBI->connect("DBI:mysql:database=".$jobcache_db.";host=".$jobcache_host.";",
+ $jobcache_user,
+ $jobcache_password);
+ if ($dbh) {
+ $status = 1;
+ }
+ }
+ } else {
+ my $ua = $self->agent;
+ $ua->timeout(10);
+
+ my $url = $self->{services}->{$id};
+ my $response = $ua->get($url);
+ if ($response->is_success) {
+ $status = 1;
+ }
+ }
+
+ my $obj = {};
+ $obj->{service} = $id;
+ $obj->{status} = $status;
+ $obj->{url} = $self->cgi->url."/".$self->name."/".$id;
+
+ # check the status service
+ $self->return_data($obj, undef, 1);
+}
+
+1;
View
486 src/MGRAST/lib/resources/inbox.pm
@@ -8,6 +8,7 @@ use POSIX qw(strftime);
use HTTP::Request::StreamingUpload;
use HTTP::Headers;
use LWP::UserAgent;
+use File::Basename;
use Data::Dumper;
use Template;
@@ -21,8 +22,13 @@ sub new {
# Call the constructor of the parent class
my $self = $class->SUPER::new(@args);
- # Add name
+ # Add name / attributes
$self->{name} = "inbox";
+ $self->{states} = ["completed", "deleted", "suspend", "in-progress", "pending", "queued"];
+ $self->{user_auth} = "mgrast";
+ if ($self->token =~ /globusonline/) {
+ $self->{user_auth} = "OAuth";
+ }
return $self;
}
@@ -69,7 +75,26 @@ sub info {
'url' => [ 'uri', "resource location of this object instance" ]
},
'parameters' => {
- 'options' => {},
+ 'options' => { "uuid" => [ "string", "RFC 4122 UUID for file" ] },
+ 'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ] },
+ 'body' => {}
+ }
+ },
+ { 'name' => "view_pending",
+ 'request' => $self->cgi->url."/".$self->name."/pending",
+ 'description' => "view status of AWE inbox actions",
+ 'example' => [ 'curl -X GET -H "auth: auth_key" "'.$self->cgi->url."/".$self->name.'/pending?queued&completed"',
+ "rename file 'sequences.fastq' in user inbox, auth is required" ],
+ 'method' => "GET",
+ 'type' => "synchronous",
+ 'attributes' => {
+ 'id' => [ 'string', "user id" ],
+ 'user' => [ 'string', "user name" ],
+ 'status' => [ 'string', "status message" ],
+ 'timestamp' => [ 'string', "timestamp for return of this query" ]
+ },
+ 'parameters' => {
+ 'options' => { map { $_, ["boolean", "If true show the given state"] } @{$self->{states}} },
'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ] },
'body' => {}
}
@@ -93,6 +118,46 @@ sub info {
'body' => { "upload" => ["file", "file to upload to inbox"] }
}
},
+ { 'name' => "rename",
+ 'request' => $self->cgi->url."/".$self->name."/{UUID}",
+ 'description' => "rename indicated file from inbox",
+ 'example' => [ 'curl -X PUT -H "auth: auth_key" "'.$self->cgi->url."/".$self->name.'/cfb3d9e1-c9ba-4260-95bf-e410c57b1e49"',
+ "rename file 'sequences.fastq' in user inbox, auth is required" ],
+ 'method' => "PUT",
+ 'type' => "synchronous",
+ 'attributes' => {
+ 'id' => [ 'string', "user id" ],
+ 'user' => [ 'string', "user name" ],
+ 'status' => [ 'string', "status message" ],
+ 'timestamp' => [ 'string', "timestamp for return of this query" ]
+ },
+ 'parameters' => {
+ 'options' => {},
+ 'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ],
+ "uuid" => [ "string", "RFC 4122 UUID for file" ] },
+ 'body' => { "name" => [ "string", "new name for file" ] }
+ }
+ },
+ { 'name' => "delete",
+ 'request' => $self->cgi->url."/".$self->name."/{UUID}",
+ 'description' => "delete indicated file from inbox",
+ 'example' => [ 'curl -X DELETE -H "auth: auth_key" "'.$self->cgi->url."/".$self->name.'/cfb3d9e1-c9ba-4260-95bf-e410c57b1e49"',
+ "delete file 'sequences.fastq' from user inbox, auth is required" ],
+ 'method' => "DELETE",
+ 'type' => "synchronous",
+ 'attributes' => {
+ 'id' => [ 'string', "user id" ],
+ 'user' => [ 'string', "user name" ],
+ 'status' => [ 'string', "status message" ],
+ 'timestamp' => [ 'string', "timestamp for return of this query" ]
+ },
+ 'parameters' => {
+ 'options' => {},
+ 'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ],
+ "uuid" => [ "string", "RFC 4122 UUID for file" ] },
+ 'body' => {}
+ }
+ },
{ 'name' => "file_info",
'request' => $self->cgi->url."/".$self->name."/info/{UUID}",
'description' => "get basic file info - returns results and updates shock node",
@@ -173,8 +238,7 @@ sub info {
'options' => {},
'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ] },
'body' => { "seq_file" => [ "string", "RFC 4122 UUID for sequence file" ],
- "barcode_file" => [ "string", "RFC 4122 UUID for barcode file" ],
- "barcode_count" => [ "int", "number of unique barcodes in barcode_file" ] }
+ "barcode_file" => [ "string", "RFC 4122 UUID for barcode file" ] }
}
},
{ 'name' => "pair_join",
@@ -196,7 +260,7 @@ sub info {
'required' => { "auth" => [ "string", "unique string of text generated by MG-RAST for your account" ] },
'body' => { "pair_file_1" => [ "string", "RFC 4122 UUID for pair 1 file" ],
"pair_file_2" => [ "string", "RFC 4122 UUID for pair 2 file" ],
- "output" => [ "string", "name of output file, default is 'pair_file_1'_'pair_file_2'.fastq" ],
+ "output" => [ "string", "prefix for output file, default is 'pair_file_1'_'pair_file_2'" ],
"retain" => [ "boolean", "If true retain non-overlapping sequences, default is false" ] }
}
},
@@ -221,7 +285,7 @@ sub info {
"pair_file_2" => [ "string", "RFC 4122 UUID for pair 2 file" ],
"index_file" => [ "string", "RFC 4122 UUID for optional index (barcode) file" ],
"barcode_count" => [ "int", "number of unique barcodes in index_file" ],
- "prefix" => [ "string", "prefix for output file names, default is 'pair_file_1'_'pair_file_2'" ],
+ "output" => [ "string", "prefix for output file names, default is 'pair_file_1'_'pair_file_2'" ],
"retain" => [ "boolean", "If true retain non-overlapping sequences, default is false" ] }
}
}
@@ -243,6 +307,15 @@ sub request {
} elsif ($self->method eq 'POST') {
$self->upload_file();
}
+ } elsif (($self->method eq 'GET') && (scalar(@{$self->rest}) == 1)) {
+ # view pending actions
+ if ($self->rest->[0] eq 'pending') {
+ $self->view_inbox_actions();
+ }
+ # view one file
+ else {
+ $self->view_inbox($self->rest->[0]);
+ }
# inbox actions that don't make new nodes
} elsif (($self->method eq 'GET') && (scalar(@{$self->rest}) > 1)) {
if ($self->rest->[0] eq 'info') {
@@ -258,19 +331,28 @@ sub request {
$self->demultiplex();
} elsif ($self->rest->[0] eq 'pairjoin') {
$self->pair_join();
- } elsif ($self->rest->[0] eq 'pair_join_demultiplex') {
+ } elsif ($self->rest->[0] eq 'pairjoin_demultiplex') {
$self->pair_join(1);
}
+ # deleting from inbox
+ } elsif (($self->method eq 'DELETE') && (scalar(@{$self->rest}) == 1)) {
+ $self->delete_file($self->rest->[0]);
+ # rename file
+ } elsif (($self->method eq 'PUT') && (scalar(@{$self->rest}) == 1)) {
+ $self->rename_file($self->rest->[0]);
}
}
$self->info();
}
+# this is a standalone request or is ran by other requests if missing
sub file_info {
- my ($self, $uuid) = @_;
+ my ($self, $uuid, $node, $return_node) = @_;
# get and validate file
- my $node = $self->node_from_id($uuid);
+ unless ($node && ref($node)) {
+ $node = $self->node_from_id($uuid);
+ }
my ($file_type, $err_msg, $file_format);
my $file_suffix = (split(/\./, $node->{file}{name}))[-1];
@@ -283,8 +365,8 @@ sub file_info {
# download first 2000 bytes of file for quick stats
my $time = time;
my $tempfile = $Conf::temp."/temp.".$node->{file}{name}.".".$time;
- $self->get_shock_file($uuid, $tempfile, $self->mgrast_token, "length=2000");
- ($file_type, $err_msg) = $self->verify_file_type($tempfile, $node->{file}{name});
+ $self->get_shock_file($uuid, $tempfile, $self->token, "length=2000", $self->{user_auth});
+ ($file_type, $err_msg) = $self->verify_file_type($tempfile, $node->{file}{name}, $file_suffix);
$file_format = $self->get_file_format($tempfile, $file_type, $file_suffix);
unlink($tempfile);
}
@@ -292,11 +374,11 @@ sub file_info {
# get info / update node
my $stats_info = {
type => $file_type,
- suffix => $file_suffix,
- file_type => $file_format,
- file_name => $node->{file}{name},
- file_size => $node->{file}{size},
- checksum => $node->{file}{checksum}{md5}
+ suffix => $file_suffix,
+ file_type => $file_format,
+ file_name => $node->{file}{name},
+ file_size => $node->{file}{size},
+ checksum => $node->{file}{checksum}{md5}
};
my $new_attr = $node->{attributes};
if (exists $new_attr->{stats_info}) {
@@ -304,16 +386,24 @@ sub file_info {
} else {
$new_attr->{stats_info} = $stats_info;
}
- $self->update_shock_node($node->{id}, $new_attr, $self->mgrast_token);
+ $node = $self->update_shock_node($uuid, $new_attr, $self->token, $self->{user_auth});
+ # add mgrast to ACLs
+ foreach my $acl (('read', 'write', 'delete')) {
+ $self->edit_shock_acl($uuid, $self->token, 'mgrast', 'put', $acl, $self->{user_auth});
+ }
# return data
- $self->return_data({
- id => 'mgu'.$self->user->_id,
- user => $self->user->login,
- status => $err_msg ? $err_msg : "file info completed sucessfully",
- stats_info => $stats_info,
- timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
- });
+ if ($return_node) {
+ return $node;
+ } else {
+ $self->return_data({
+ id => 'mgu'.$self->user->_id,
+ user => $self->user->login,
+ status => $err_msg ? $err_msg : $node->{file}{name}." ($uuid) uploaded / updated",
+ stats_info => $stats_info,
+ timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
+ });
+ }
}
sub seq_stats {
@@ -321,10 +411,21 @@ sub seq_stats {
# get and validate file
my $node = $self->node_from_id($uuid);
+ unless (exists $node->{attributes}{stats_info}) {
+ $node = $self->file_info($uuid, $node, 1);
+ }
+ my $user_id = 'mgu'.$self->user->_id;
my $file_type = $self->file_type_from_node($node);
+ if (exists($node->{attributes}{data_type}) && ($node->{attributes}{data_type} eq "sequence")) {
+ $self->return_data({
+ id => $user_id,
+ user => $self->user->login,
+ status => $node->{file}{name}." ($uuid) sequence stats computation has already been ran",
+ timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
+ });
+ }
# Do template replacement of MG-RAST's AWE workflow for sequence stats
- my $user_id = 'mgu'.$self->user->_id;
my $info = {
shock_url => $Conf::shock_url,
job_name => $user_id.'_seqstats',
@@ -335,12 +436,13 @@ sub seq_stats {
seq_file => $node->{file}{name}
};
my $job = $self->submit_awe_template($info, $Conf::mgrast_seq_stats_workflow);
+ $self->add_node_action($node, $job, 'stats');
# return data
$self->return_data({
id => $user_id,
user => $self->user->login,
- status => "stats computation is being run on file id: ".$node->{id},
+ status => $node->{file}{name}." ($uuid) sequence stats computation is being run",
awe_id => $Conf::awe_url.'/job/'.$job->{id},
timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
});
@@ -355,9 +457,13 @@ sub sff_to_fastq {
$self->return_data( {"ERROR" => "this request type requires the sff_file parameter"}, 400 );
}
my $node = $self->node_from_id($uuid);
+ unless (exists $node->{attributes}{stats_info}) {
+ $node = $self->file_info($uuid, $node, 1);
+ }
# Do template replacement of MG-RAST's AWE workflow for sff to fastq
my $user_id = 'mgu'.$self->user->_id;
+ my $basename = fileparse($node->{file}{name}, qr/\.[^.]*/);
my $info = {
shock_url => $Conf::shock_url,
job_name => $user_id.'_sff2fastq',
@@ -367,15 +473,16 @@ sub sff_to_fastq {
clientgroups => $Conf::mgrast_inbox_clientgroups,
sff_file_id => $node->{id},
sff_file => $node->{file}{name},
- fastq_file => $node->{file}{name}.'.fastq'
+ fastq_file => $basename.'.fastq'
};
my $job = $self->submit_awe_template($info, $Conf::mgrast_sff_to_fastq_workflow);
+ $self->add_node_action($node, $job, 'sff2fastq');
# return data
$self->return_data({
id => $user_id,
user => $self->user->login,
- status => "sff to fastq is being run on file id: ".$node->{id},
+ status => $node->{file}{name}." ($uuid) sff to fastq is being run",
awe_id => $Conf::awe_url.'/job/'.$job->{id},
timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
});
@@ -391,44 +498,76 @@ sub demultiplex {
$self->return_data( {"ERROR" => "this request type requires both the seq_file and barcode_file parameters"}, 400 );
}
my $seq_node = $self->node_from_id($seq_file);
+ unless (exists $seq_node->{attributes}{stats_info}) {
+ $seq_node = $self->file_info($seq_file, $seq_node, 1);
+ }
my $bar_node = $self->node_from_id($bar_file);
+ unless (exists $bar_node->{attributes}{stats_info}) {
+ $bar_node = $self->file_info($bar_file, $bar_node, 1);
+ }
my $seq_type = $self->file_type_from_node($seq_node);
# download barcode file to get number and names of barcoded pieces
- my $bc_count = $self->cgi->param('barcode_count') || 0;
- if ($bc_count < 2) {
- $self->return_data( {"ERROR" => "barcode_count value must be greater than 1"}, 400 );
- }
my $outfiles = {};
- my $bar_text = $self->get_shock_file($bar_node->{id}, undef, $self->mgrast_token);
+ my $bar_text = $self->get_shock_file($bar_node->{id}, undef, $self->token, undef, $self->{user_auth});
foreach my $line (split(/\n/, $bar_text)) {
my ($b, $n) = split(/\t/, $line);
my $fname = $n ? $n : $b;
$outfiles->{$fname} = 1;
}
- if (scalar(keys %$outfiles) != $bc_count) {
- $self->return_data( {"ERROR" => "number of unique barcodes in barcode_file does not match barcode_count"}, 404 );
+ if (scalar(keys %$outfiles) < 2) {
+ $self->return_data( {"ERROR" => "number of barcodes in barcode_file must be greater than 1"}, 400 );
}
+ $outfiles->{"nobarcode.".$seq_node->{file}{name}} = 1;
+
+ # build awf parts for output / seq stats
+ my $num = 0;
+ my $shock_url = $Conf::shock_url;
my $output_text = "";
+ my $seq_stats_text = ""
foreach my $fname (keys %$outfiles) {
+ $num += 1;
$output_text .= qq(
"$fname.$seq_type": {
- "host": ").$Conf::shock_url.qq(",
+ "host": "$shock_url",
"node": "-",
"attrfile": "userattr.json"
},);
+ $seq_stats_text .= qq(,
+ {
+ "cmd": {
+ "args": "-input=\@$fname.$seq_type -input_json=input_attr.json -output_json=output_attr.json -type=$seq_type",
+ "description": "sequence stats",
+ "name": "awe_seq_length_stats.pl"
+ },
+ "dependsOn": ["0"],
+ "inputs": {
+ "$fname.$seq_type": {
+ "host": "$shock_url",
+ "origin": "0",
+ "node": "-",
+ "attrfile": "input_attr.json"
+ }
+ },
+ "outputs": {
+ "$fname.$seq_type": {
+ "host": "$shock_url",
+ "origin": "0",
+ "node": "-",
+ "type": "update",
+ "attrfile": "output_attr.json"
+ }
+ },
+ "taskid": "$num",
+ "totalwork": 1
+ });
}
- $output_text .= qq(
- "nobarcode.).$seq_node->{file}{name}.qq(": {
- "host": ").$Conf::shock_url.qq(",
- "node": "-",
- "attrfile": "userattr.json"
- });
+ chop($output_text);
# Do template replacement of MG-RAST's AWE workflow for demultiplex
my $user_id = 'mgu'.$self->user->_id;
my $info = {
- shock_url => $Conf::shock_url,
+ shock_url => $shock_url,
job_name => $user_id.'_demultiplex',
user_id => $user_id,
user_name => $self->user->login,
@@ -439,14 +578,17 @@ sub demultiplex {
seq_file => $seq_node->{file}{name},
bar_file_id => $bar_node->{id},
bar_file => $bar_node->{file}{name},
- outputs => $output_text
+ outputs => $output_text,
+ seq_stats => $seq_stats_text
};
my $job = $self->submit_awe_template($info, $Conf::mgrast_demultiplex_workflow);
+ $self->add_node_action($seq_node, $job, 'demultiplex');
+ $self->add_node_action($bar_node, $job, 'demultiplex');
$self->return_data({
id => $user_id,
user => $self->user->login,
- status => "demultiplex is being run on file id: ".$seq_node->{id},
+ status => $seq_node->{file}{name}." ($seq_file) demultiplex is being run",
awe_id => $Conf::awe_url.'/job/'.$job->{id},
timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
});
@@ -462,16 +604,22 @@ sub pair_join {
$self->return_data( {"ERROR" => "this request type requires both the pair_file_1 and pair_file_2 parameters"}, 400 );
}
my $pair1_node = $self->node_from_id($pair1_file);
+ unless (exists $pair1_node->{attributes}{stats_info}) {
+ $pair1_node = $self->file_info($pair1_file, $pair1_node, 1);
+ }
my $pair2_node = $self->node_from_id($pair2_file);
+ unless (exists $pair2_node->{attributes}{stats_info}) {
+ $pair2_node = $self->file_info($pair2_file, $pair2_node, 1);
+ }
my $p1_type = $self->file_type_from_node($pair1_node);
my $p2_type = $self->file_type_from_node($pair2_node);
unless (($p1_type eq 'fastq') && ($p2_type eq 'fastq')) {
$self->return_data( {"ERROR" => "both input sequence files must be fastq format"}, 400 );
}
- # Do template replacement of MG-RAST's AWE workflow for demultiplex
- my $outfile = $self->cgi->param('output') || $pair1_node->{file}{name}."_".$pair2_node->{file}{name};
+ # Do template replacement of MG-RAST's AWE workflow for pairjoin
my $user_id = 'mgu'.$self->user->_id;
+ my $output = $self->cgi->param('output') || $pair1_node->{file}{name}."_".$pair2_node->{file}{name};
my $info = {
shock_url => $Conf::shock_url,
user_id => $user_id,
@@ -482,53 +630,88 @@ sub pair_join {
p1_file => $pair1_node->{file}{name},
p2_file_id => $pair2_node->{id},
p2_file => $pair2_node->{file}{name},
- retain => $self->cgi->param('retain') ? "" : "-j "
+ retain => $self->cgi->param('retain') ? "" : "-j ",
+ out_file => $output
};
my $job = undef;
my $status = "";
# do pair-join with demultiplex
if ($demultiplex) {
# validate extra options
+ my $shock_url = $Conf::shock_url;
my $index_file = $self->cgi->param('index_file') || "";
my $bc_count = $self->cgi->param('barcode_count') || 0;
- my $prefix = $self->cgi->param('prefix') || $pair1_node->{file}{name}."_".$pair2_node->{file}{name};
unless ($index_file) {
$self->return_data( {"ERROR" => "this request type requires the index_file parameter"}, 400 );
}
if ($bc_count < 2) {
$self->return_data( {"ERROR" => "barcode_count value must be greater than 1"}, 400 );
}
- # update template info
my $index_node = $self->node_from_id($index_file);
+ unless (exists $index_node->{attributes}{stats_info}) {
+ $index_node = $self->file_info($index_file, $index_node, 1);
+ }
+ # update template info
$status = "pair join and demultiplex is being run on files: ".$pair1_node->{id}.", ".$pair2_node->{id}.", ".$index_node->{id};
$info->{job_name} = $user_id.'_pairjoin_demultiplex';
$info->{index_file} = $index_node->{file}{name};
$info->{index_id} = $index_node->{id};
- $info->{prefix} = $prefix;
$info->{outputs} = "";
- # build outputs
- foreach my $i (1..$bc_count) {
+ $info->{seq_stats} = "";
+ # build awf parts for output / seq stats
+ my $num = 3;
+ my @outfiles = map { $output.".".$_.".fastq" } (1..$bc_count);
+ push @outfiles, "nobarcode.".$output.".join.fastq";
+ foreach my $fname (@outfiles) {
+ $num += 1;
$info->{outputs} .= qq(
- "$prefix.$i.fastq": {
- "host": ").$Conf::shock_url.qq(",
+ "$fname": {
+ "host": "$shock_url",
"node": "-",
"attrfile": "userattr.json"
},);
+ $info->{seq_stats} .= qq(,
+ {
+ "cmd": {
+ "args": "-input=\@$fname -input_json=input_attr.json -output_json=output_attr.json -type=fastq",
+ "description": "sequence stats",
+ "name": "awe_seq_length_stats.pl"
+ },
+ "dependsOn": ["3"],
+ "inputs": {
+ "$fname": {
+ "host": "$shock_url",
+ "origin": "0",
+ "node": "-",
+ "attrfile": "input_attr.json"
+ }
+ },
+ "outputs": {
+ "$fname": {
+ "host": "$shock_url",
+ "origin": "0",
+ "node": "-",
+ "type": "update",
+ "attrfile": "output_attr.json"
+ }
+ },
+ "taskid": "$num",
+ "totalwork": 1
+ });
}
- $info->{outputs} .= qq(
- "nobarcode.$prefix.join.fastq": {
- "host": ").$Conf::shock_url.qq(",
- "node": "-",
- "attrfile": "userattr.json"
- });
+ chop($info->{outputs});
$job = $self->submit_awe_template($info, $Conf::mgrast_pair_join_demultiplex_workflow);
+ $self->add_node_action($pair1_node, $job, 'pairjoin_demultiplex');
+ $self->add_node_action($pair2_node, $job, 'pairjoin_demultiplex');
+ $self->add_node_action($pair2_node, $job, 'pairjoin_demultiplex');
}
# do pair-join only
else {
$status = "pair join is being run on files: ".$pair1_node->{id}.", ".$pair2_node->{id};
$info->{job_name} = $user_id.'_pairjoin';
- $info->{out_file} = $self->cgi->param('output') || $pair1_node->{file}{name}."_".$pair2_node->{file}{name}.".fastq";
$job = $self->submit_awe_template($info, $Conf::mgrast_pair_join_workflow);
+ $self->add_node_action($pair1_node, $job, 'pairjoin');
+ $self->add_node_action($pair2_node, $job, 'pairjoin');
}
$self->return_data({
@@ -541,10 +724,18 @@ sub pair_join {
}
sub view_inbox {
- my ($self) = @_;
+ my ($self, $uuid) = @_;
+ my $user_id = 'mgu'.$self->user->_id;
+ # get inbox
+ my $inbox = [];
+ if ($uuid) {
+ $inbox = [ $self->node_from_id($uuid) ];
+ } else {
+ $inbox = $self->get_shock_query({'type' => 'inbox', 'id' => $user_id}, $self->token, $self->{user_auth});
+ }
+ # process inbox
my $files = [];
- my $inbox = $self->get_shock_query({'type' => 'inbox', 'id' => 'mgu'.$self->user->_id}, $self->mgrast_token);
foreach my $node (@$inbox) {
my $info = {
'id' => $node->{id},
@@ -553,13 +744,18 @@ sub view_inbox {
'checksum' => $node->{file}{checksum}{md5},
'timestamp' => $node->{created_on}
};
- if (exists $node->{attributes}{stats_info}) {
- $info->{stats_info} = $node->{attributes}{stats_info};
+ # get file_info / compute if missing
+ unless (exists $node->{attributes}{stats_info}) {
+ $node = $self->file_info($node->{id}, $node, 1);
}
+ $info->{stats_info} = $node->{attributes}{stats_info};
+ # check if any pending actions
+ $self->update_node_actions($node);
+ $info->{actions} = $node->{attributes}{actions};
push @$files, $info;
}
$self->return_data({
- id => 'mgu'.$self->user->_id,
+ id => $user_id,
user => $self->user->login,
timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime),
files => $files,
@@ -567,6 +763,27 @@ sub view_inbox {
});
}
+sub view_inbox_actions {
+ my ($self) = @_;
+
+ my $jobs = [];
+ my $user_id = 'mgu'.$self->user->_id;
+ my $params = {
+ "info.user" => [$user_id],
+ "info.clientgroups" => ["mgrast_inbox"]
+ };
+ my $requestedStates = [];
+ foreach my $state (@{$self->{states}}) {
+ if ($self->cgi->param($state)) {
+ push(@$requestedStates, $state);
+ }
+ }
+ if (scalar(@$requestedStates)) {
+ $params->{state} = $requestedStates;
+ }
+ $self->return_data($self->get_awe_query($params, $self->token, "mgrast"));
+}
+
sub upload_file {
my ($self) = @_;
@@ -587,7 +804,7 @@ sub upload_file {
fh => $io_handle,
headers => HTTP::Headers->new(
'Content_Type' => 'application/octet-stream',
- 'Authorization' => 'OAuth '.$self->mgrast_token
+ 'Authorization' => $self->{user_auth}.' '.$self->token
)
);
my $req = LWP::UserAgent->new->request($post);
@@ -600,7 +817,7 @@ sub upload_file {
}
# PUT file name to node
my $node_id = $response->{data}{id};
- my $node = $self->update_shock_node_file_name($node_id, "".$fn, $self->mgrast_token);
+ my $node = $self->update_shock_node_file_name($node_id, "".$fn, $self->token, $self->{user_auth});
unless ($node && ($node->{id} eq $node_id)) {
$self->return_data({"ERROR" => "storing object failed - unable to set file name"}, 507);
}
@@ -611,18 +828,9 @@ sub upload_file {
email => $self->user->email
};
# PUT attributes to node
- $node = $self->update_shock_node($node_id, $attr, $self->mgrast_token);
- # return info
- if ($node && ($node->{id} eq $node_id)) {
- $self->return_data({
- id => 'mgu'.$self->user->_id,
- user => $self->user->login,
- status => "data received successfully",
- timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
- });
- } else {
- $self->return_data({"ERROR" => "storing object failed - unable to update file with user info"}, 507);
- }
+ $node = $self->update_shock_node($node_id, $attr, $self->token, $self->{user_auth});
+ # get / return file info
+ $self->file_info($node_id, $node);
} else {
$self->return_data( {"ERROR" => "storing object failed - could not obtain filehandle"}, 507 );
}
@@ -631,6 +839,47 @@ sub upload_file {
}
}
+sub delete_file {
+ my ($self, $uuid) = @_;
+ # check that no actions are being performed
+ my $node = $self->node_from_id($uuid);
+ if (exists $node->{attributes}{actions}) {
+ foreach my $act (@{$node->{attributes}{actions}}) {
+ if (($act->{status} eq 'queued') || ($act->{status} eq 'in-progress')) {
+ $self->return_data( {"ERROR" => "unable to delete file, ".$act->{name}." is ".$act->{status}}, 500 );
+ }
+ }
+ }
+ $self->delete_shock_node($uuid, $self->token, $self->{user_auth});
+ $self->return_data({
+ id => 'mgu'.$self->user->_id,
+ user => $self->user->login,
+ status => $node->{file}{name}." ($uuid) deleted",
+ timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
+ });
+}
+
+sub rename_file {
+ my ($self, $uuid) = @_;
+ my $name = $self->cgi->param('name') || "";
+ unless ($name) {
+ $self->return_data( {"ERROR" => "missing 'name' parameter"}, 400 );
+ }
+ my $node = $self->node_from_id($uuid);
+ my $attr = $node->{attributes};
+ $self->update_shock_node_file_name($uuid, $name, $self->token, $self->{user_auth});
+ if (exists($attr->{stats_info}) && exists($attr->{stats_info}{file_name})) {
+ $attr->{stats_info}{file_name} = $name;
+ $node = $self->update_shock_node($uuid, $attr, $self->token, $self->{user_auth});
+ }
+ $self->return_data({
+ id => 'mgu'.$self->user->_id,
+ user => $self->user->login,
+ status => $name." ($uuid) renamed",
+ timestamp => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
+ });
+}
+
sub submit_awe_template {
my ($self, $info, $template) = @_;
@@ -640,29 +889,71 @@ sub submit_awe_template {
$tt->process($template, $info, \$awf) || die $tt->error();
# Submit job to AWE and check for successful submission
- my $job = $self->post_awe_job($awf, $self->mgrast_token, $self->mgrast_token, 1);
- unless ($job && $job->{state} && $job->{state} == "init") {
+ # mgrast owns awe job, user owns shock data
+ my $job = $self->post_awe_job($awf, $self->token, $self->mgrast_token, 1, $self->{user_auth}, "OAuth");
+ unless ($job && $job->{state} && $job->{state} eq "init") {
$self->return_data( {"ERROR" => "job could not be submitted"}, 500 );
}
-
return $job;
}
sub node_from_id {
my ($self, $uuid) = @_;
- my $node = {};
- my $inbox = $self->get_shock_query({'type' => 'inbox', 'id' => 'mgu'.$self->user->_id}, $self->mgrast_token);
- foreach my $n (@$inbox) {
- if ($n->{id} eq $uuid) {
- $node = $n;
- }
- }
- unless (%$node) {
+ my $node = $self->get_shock_node($uuid, $self->token, $self->{user_auth});
+ unless ( exists($node->{attributes}{type}) && ($node->{attributes}{type} eq 'inbox') &&
+ exists($node->{attributes}{id}) && ($node->{attributes}{id} eq 'mgu'.$self->user->_id) ) {
$self->return_data( {"ERROR" => "file id '$uuid' does not exist in your inbox"}, 404 );
}
return $node;
}
+sub add_node_action {
+ my ($self, $node, $job, $name) = @_;
+
+ my $attr = $node->{attributes};
+ my $actions = [];
+ if (exists $attr->{actions}) {
+ $actions = $attr->{actions};
+ }
+ push @$actions, {
+ id => $job->{id},
+ name => $name,
+ status => ($job->{state} eq 'init') ? 'queued' : $job->{state},
+ start => $job->{info}{submittime}
+ };
+ $attr->{actions} = $actions;
+ $self->update_shock_node($node->{id}, $attr, $self->token, $self->{user_auth});
+}
+
+sub update_node_actions {
+ my ($self, $node) = @_;
+
+ # get actions
+ my $attr = $node->{attributes};
+ my $new_actions = [];
+ my $old_actions = [];
+ if (exists $attr->{actions}) {
+ $old_actions = $attr->{actions};
+ }
+ # check and update
+ foreach my $act (@$old_actions) {
+ # do nothing with completed
+ if ($act->{status} eq 'completed') {
+ push @$new_actions, $act;
+ } else {
+ my $job = $self->get_awe_job($act->{id}, $self->token, $self->{user_auth});
+ # drop it if deleted
+ if ($job->{state} ne 'deleted') {
+ $act->{status} = ($job->{state} eq 'init') ? 'queued' : $job->{state};
+ push @$new_actions, $act;
+ }
+ }
+ }
+ # update node
+ $attr->{actions} = $new_actions;
+ $self->update_shock_node($node->{id}, $attr, $self->token, $self->{user_auth});
+}
+
sub file_type_from_node {
my ($self, $node) = @_;
unless ($node->{attributes}{stats_info} && $node->{attributes}{stats_info}{file_type}) {
@@ -676,7 +967,7 @@ sub file_type_from_node {
}
sub verify_file_type {
- my ($self, $tempfile, $fname) = @_;
+ my ($self, $tempfile, $fname, $file_suffix) = @_;
# Need to do the 'safe-open' trick here, file might be hard to escape in the shell
open(P, "-|", "file", "-b", "$tempfile") || $self->return_data( {"ERROR" => "unable to verify file type/format"}, 400 );
my $file_type = <P>;
@@ -714,13 +1005,13 @@ sub verify_file_type {
($file_type eq 'ASCII text, with CR line terminators') ||
($file_type eq 'ASCII text, with CRLF line terminators') ) {
return ($file_type, "");
- } else {
- $file_type = "ASCII text, with invalid line terminators";
+ } elsif (($file_suffix eq 'xls') || ($file_suffix eq 'xlsx')) {
+ return ($file_type, "");
}
return ($file_type, "[error] file '$fname' is of unsupported file type '$file_type'.");
}
-sub file_format {
+sub get_file_format {
my ($self, $tempfile, $file_type, $file_suffix) = @_;
if ($file_suffix eq 'qual') {
@@ -729,6 +1020,9 @@ sub file_format {
if (($file_type =~ /^binary/) && ($file_suffix eq 'sff')) {
return 'sff';
}
+ if (($file_suffix eq 'xls') || ($file_suffix eq 'xlsx')) {
+ return 'excel'
+ }
# identify fasta or fastq
if ($file_type =~ /^ASCII/) {
my @chars;
View
141 src/MGRAST/lib/resources/job.pm
@@ -18,12 +18,13 @@ sub new {
# Add name / attributes
$self->{name} = "job";
$self->{job_actions} = {
- reserve => 1,
- create => 1,
- submit => 1,
- share => 1,
- public => 1,
- delete => 1,
+ reserve => 1,
+ create => 1,
+ submit => 1,
+ resubmit => 1,
+ share => 1,
+ public => 1,
+ delete => 1,
addproject => 1
};
$self->{attributes} = {
@@ -48,14 +49,16 @@ sub new {
};
$self->{create_param} = {
'metagenome_id' => ["string", "unique MG-RAST metagenome identifier"],
- 'input_id' => ["string", "shock node id of input sequence file (optional)"],
- 'sequence_type' => ["cv", [["WGS", "whole genome shotgun sequenceing"],
- ["Amplicon", "amplicon sequenceing"],
- ["MT", "metatranscriptome sequenceing"]] ]
+ 'input_id' => ["string", "shock node id of input sequence file (optional)"]
};
my @input_stats = map { substr($_, 0, -4) } grep { $_ =~ /_raw$/ } @{$self->seq_stats};
map { $self->{create_param}{$_} = ['float', 'sequence statistic'] } grep { $_ !~ /drisee/ } @input_stats;
map { $self->{create_param}{$_} = ['string', 'pipeline option'] } @{$self->pipeline_opts};
+ $self->{create_param}{sequence_type} = [
+ "cv", [["WGS", "whole genome shotgun sequenceing"],
+ ["Amplicon", "amplicon sequenceing"],
+ ["MT", "metatranscriptome sequenceing"]]
+ ];
return $self;
}
@@ -107,7 +110,7 @@ sub info {
},
{ 'name' => "submit",
'request' => $self->cgi->url."/".$self->name."/submit",
- 'description' => "Submit an existing MG-RAST job to AWE pipeline.",
+ 'description' => "Submit a MG-RAST job to AWE pipeline.",
'method' => "POST",
'type' => "synchronous",
'attributes' => $self->{attributes}{submit},
@@ -116,6 +119,17 @@ sub info {
'body' => { "metagenome_id" => ["string", "unique MG-RAST metagenome identifier"],
"input_id" => ["string", "shock node id of input sequence file"] } }
},
+ { 'name' => "resubmit",
+ 'request' => $self->cgi->url."/".$self->name."/resubmit",
+ 'description' => "Re-submit an existing MG-RAST job to AWE pipeline.",
+ 'method' => "PUT",
+ 'type' => "synchronous",
+ 'attributes' => $self->{attributes}{submit},
+ 'parameters' => { 'options' => {},
+ 'required' => {},
+ 'body' => { "metagenome_id" => ["string", "unique MG-RAST metagenome identifier"],
+ "awe_id" => ["string", "awe job id of original job"] } }
+ },
{ 'name' => "share",
'request' => $self->cgi->url."/".$self->name."/share",
'description' => "Share metagenome with another user.",
@@ -272,18 +286,65 @@ sub job_action {
my $nodeid = $post->{input_id};
eval {
my $node = $self->get_shock_node($nodeid, $self->mgrast_token);
- $post = $node->{attributes}{stats_info};
+ # pull from stats_info and pipeline_info in attributes
+ foreach my $x (('stats_info', 'pipeline_info')) {
+ if (exists($node->{attributes}{$x}) && ref($node->{attributes}{$x})) {
+ foreach my $k (keys %{$node->{attributes}{$x}}) {
+ # only add values that are not already given
+ if (! exists($post->{$k})) {
+ $post->{$k} = $node->{attributes}{$x}{$k};
+ }
+ }
+ }
+ }
};
+ delete $post->{input_id};
if ($@ || (! $post)) {
- $self->return_data( {"ERROR" => "unable to obtain sequence file statistics from shock node ".$nodeid}, 500 );
+ $self->return_data( {"ERROR" => "unable to obtain sequence file info from shock node ".$nodeid}, 500 );
+ }
+ }
+ # fix assembly defaults
+ if (exists($post->{sequencing_method_guess}) && ($post->{sequencing_method_guess} eq "assembled")) {
+ $post->{assembled} = 'yes';
+ $post->{filter_ln} = 'no';
+ $post->{filter_ambig} = 'no';
+ $post->{dynamic_trim} = 'no';
+ $post->{dereplicate} = 'no';
+ $post->{bowtie} = 'no';
+ }
+ # set pipeline defaults if missing
+ foreach my $key (@{$self->pipeline_opts}) {
+ if (exists($self->pipeline_defaults->{$key}) && (! exists($post->{$key}))) {
+ $post->{$key} = $self->pipeline_defaults->{$key};
+ }
+ }
+ if ($post->{file_type} eq 'fasta') {
+ $post->{file_type} = 'fna';
+ }
+ # fix booleans
+ foreach my $key (keys %$post) {
+ if ($post->{$key} eq 'yes') {
+ $post->{$key} = 1;
+ } elsif ($post->{$key} eq 'no') {
+ $post->{$key} = 0;
}
}
# check params
+ delete $post->{metagenome_id};
foreach my $key (keys %{$self->{create_param}}) {
- unless (exists $post->{$key}) {
+ if (($key eq 'metagenome_id') || ($key eq 'input_id')) {
+ next;
+ }
+ if (! exists($post->{$key})) {
$self->return_data( {"ERROR" => "Missing required parameter '$key'"}, 404 );
}
}
+ # calculate length trim
+ $post->{max_ln} = int($post->{average_length} + ($post->{filter_ln_mult} * $post->{standard_deviation_length}));
+ $post->{min_ln} = int($post->{average_length} - ($post->{filter_ln_mult} * $post->{standard_deviation_length}));
+ if ($post->{min_ln} < 1) {
+ $post->{min_ln} = 1;
+ }
# create job
$job = $master->Job->initialize($self->user, $post, $job);
$data = {
@@ -299,11 +360,49 @@ sub job_action {
if (@err) {
$self->return_data( {"ERROR" => join("\n", @log)}, 400 );
}
- my (undef, $awe_id) = split(/\t/, $log[1]);
- $data = {
- awe_id => $awe_id,
- log => join("\n", @log)
- };
+ my @aweid = grep { $_ =~ /^awe job/ } @log;
+ if (@aweid) {
+ my (undef, $aid) = split(/\t/, $aweid[0]);
+ $data = {
+ awe_id => $aid,
+ log => join("\n", @log)
+ };
+ # update inbox attributes
+ my $node = $self->get_shock_node($post->{input_id}, $self->mgrast_token);
+ my $attr = $node->{attributes};
+ my $action = {
+ id => $aid,
+ name => "pipeline",
+ status => "queued",
+ start => strftime("%Y-%m-%dT%H:%M:%S", gmtime)
+ };
+ if (exists $attr->{actions}) {
+ push @{$attr->{actions}}, $action;
+ } else {
+ $attr->{actions} = [$action];
+ }
+ $self->update_shock_node($post->{input_id}, $attr, $self->mgrast_token);
+ } else {
+ $self->return_data( {"ERROR" => "Unknown error, missing AWE job ID:\n".join("\n", @log)}, 500 );
+ }
+ } elsif ($action eq 'resubmit') {
+ my $cmd = $Conf::resubmit_to_awe." --job_id ".$job->{job_id}." --awe_id ".$post->{awe_id}." --shock_url ".$Conf::shock_url." --awe_url ".$Conf::awe_url;
+ my @log = `$cmd 2>&1`;
+ chomp @log;
+ my @err = grep { $_ =~ /^ERROR/ } @log;
+ if (@err) {
+ $self->return_data( {"ERROR" => join("\n", @log)}, 400 );
+ }
+ my @aweid = grep { $_ =~ /^awe job/ } @log;
+ if (@aweid) {
+ my (undef, $aid) = split(/\t/, $aweid[0]);
+ $data = {
+ awe_id => $aid,
+ log => join("\n", @log)
+ };
+ } else {
+ $self->return_data( {"ERROR" => "Unknown error, missing AWE job ID"}, 500 );
+ }
} elsif ($action eq 'share') {
# get user to share with
my $share_user = undef;
@@ -362,7 +461,7 @@ sub job_action {
my $attr = $n->{attributes};
$attr->{status} = 'public';
$self->update_shock_node($n->{id}, $attr, $self->mgrast_token);
- $self->edit_shock_acl($n->{id}, $self->mgrast_token, 'mgrast', 'delete', 'read');
+ $self->edit_shock_public_acl($n->{id}, $self->mgrast_token, 'put', 'read');
}
# update db
$job->public(1);
@@ -394,7 +493,7 @@ sub job_action {
# add it
my $status = $project->add_job($job);
$data = {
- project_id => $project->{id},
+ project_id => "mgp".$project->{id},
project_name => $project->{name},
status => $status
};
View
4 src/MGRAST/lib/resources/matrix.pm
@@ -618,11 +618,11 @@ sub prepare_data {
my $bcols = [];
my $r_map = ($type eq 'feature') ? $md52ann : ($prot_func ? {} : $self->get_hierarchy($mgdb, $type, $glvl, $source, $leaf_node));
foreach my $rid (sort {$row_ids->{$a} <=> $row_ids->{$b}} keys %$row_ids) {
- my $rmd = exists($r_map->{$rid}) ? (($type eq 'feature') ? $r_map->{$rid} : { $mtype => $r_map->{$rid} }) : undef;
+ my $rmd = exists($r_map->{$rid}) ? (($type eq 'feature') ? $r_map->{$rid} : { $mtype => $r_map->{$rid} }) : {};
if ($leaf_node && $taxid && ($type eq 'organism') && exists($self->{org2tid}{$rid})) {
push @$brows, { id => $self->{org2tid}{$rid}, metadata => $rmd };
} elsif ($prot_func) {
- push @$brows, { id => $rid, metadata => undef };
+ push @$brows, { id => $rid, metadata => {} };
} else {
push @$brows, { id => $rid, metadata => $rmd };
}
View
15 src/MGRAST/lib/resources/metadata.pm
@@ -442,6 +442,7 @@ sub process_file {
# get metadata file
my $tmp_dir = $Conf::temp;
my $fname = "";
+ my $node = {};
# uploaded
if ($self->cgi->param('upload')) {
@@ -470,10 +471,10 @@ sub process_file {
}
# from shock node
elsif ($self->cgi->param('node_id')) {
- my $nid = $self->cgi->param('node_id');
- my $node = $self->get_shock_node($nid, $self->mgrast_token);
- $fname = $node->{file}{name};
- my $res = $self->get_shock_file($nid, "$tmp_dir/$fname", $self->mgrast_token);
+ my $nid = $self->cgi->param('node_id');
+ $node = $self->get_shock_node($nid, $self->mgrast_token);
+ $fname = $node->{file}{name};
+ my $res = $self->get_shock_file($nid, "$tmp_dir/$fname", $self->mgrast_token);
unless ($res) {
$self->return_data({"ERROR" => "Unable to retrieve file from Shock server"}, 500);
}
@@ -489,6 +490,12 @@ sub process_file {
# run different actions
if ($type eq 'validate') {
if ($is_valid) {
+ if ($node && ref($node)) {
+ # validate shock node
+ my $attr = $node->{attributes};
+ $attr->{data_type} = 'metadata';
+ $self->update_shock_node($node->{id}, $attr, $self->mgrast_token);
+ }
delete $md_obj->{is_valid};
$data = {is_valid => 1, message => undef, metadata => $md_obj};
} else {
View
6 src/MGRAST/lib/resources/metagenome.pm
@@ -305,7 +305,7 @@ sub query {
if ($self->user->has_star_right('view', 'metagenome')) {
$solr_query_str .= "(status:private)";
} else {
- if (scalar(%{$self->rights}) > 0) {
+ if (scalar(keys %{$self->rights}) > 0) {
$solr_query_str .= "(status:private AND (".join(" OR ", map {'id:mgm'.$_} keys %{$self->rights})."))";
} else {
$return_empty_set = 1;
@@ -316,7 +316,7 @@ sub query {
if ($self->user->has_star_right('view', 'metagenome')) {
$solr_query_str .= "(status:*)";
} else {
- if (scalar(%{$self->rights}) > 0) {
+ if (scalar(keys %{$self->rights}) > 0) {
$solr_query_str .= "((status:public) OR (status:private AND (".join(" OR ", map {'id:mgm'.$_} keys %{$self->rights}).")))";
} else {
$solr_query_str .= '(status:public)';
@@ -442,7 +442,7 @@ sub prepare_data {
# add pipeline info
my $pparams = $self->pipeline_defaults;
$pparams->{assembled} = (exists($jdata->{assembled}) && $jdata->{assembled}) ? 'yes' : 'no';
- $pparams->{publish_priority} = (exists($jdata->{priority}) && $jdata->{priority}) ? $jdata->{priority} : 'never';
+ $pparams->{priority} = (exists($jdata->{priority}) && $jdata->{priority}) ? $jdata->{priority} : 'never';
# replace value defaults
foreach my $tag (('max_ambig', 'min_qual', 'max_lqb', 'screen_indexes',
'm5nr_sims_version', 'm5rna_sims_version',
View
2  src/MGRAST/lib/resources/notebook.pm
@@ -429,7 +429,7 @@ sub shock_post_acl {
map { $self->edit_shock_acl($id, $self->{nb_token}, $_, 'put', 'read') } @$access;
} elsif ($self->{nb_token} && $self->{nb_info} && (@$access == 0)) {
# public
- $self->edit_shock_acl($id, $self->{nb_token}, $self->{nb_info}{username}, 'delete', 'read');
+ $self->edit_shock_public_acl($id, $self->{nb_token}, 'put', 'read');
} else {
# missing config
print STDERR "Missing notebook config options\n";
View
44 src/MGRAST/lib/resources/project.pm
@@ -192,8 +192,27 @@ sub query {
if ($limit == 0) {
$limit = 18446744073709551615;
}
+
+ # check if we just want the private projects
+ if ($self->cgi->param('private')) {
+ unless ($self->user) {
+ $self->return_data({"ERROR" => "private option requires authentication"}, 400);
+ }
+ my $ids = [];
+ if ($self->cgi->param('edit')) {
+ $ids = $self->user->has_right_to(undef, 'edit', 'project');
+ } else {
+ $ids = $self->user->has_right_to(undef, 'view', 'project');
+ }
+ if (scalar(@$ids) && $ids->[0] eq '*') {
+ shift @$ids;
+ }
+ my $list = join(",", @$ids);
+ $total = scalar(@$ids);
+ $projects = $master->Project->get_objects( {$order => [undef, "id IN ($list) ORDER BY $order LIMIT $limit OFFSET $offset"]} );
+ }
# get all items the user has access to
- if (exists $self->rights->{'*'}) {
+ elsif (exists $self->rights->{'*'}) {
$total = $master->Project->count_all();
$projects = $master->Project->get_objects( {$order => [undef, "_id IS NOT NULL ORDER BY $order LIMIT $limit OFFSET $offset"]} );
} else {
@@ -239,13 +258,32 @@ sub prepare_data {
$obj->{samples} = \@samples;
$obj->{libraries} = \@libraries;
}
- if (($self->cgi->param('verbosity') eq 'verbose') || ($self->cgi->param('verbosity') eq 'full')) {
+ if (($self->cgi->param('verbosity') eq 'verbose') || ($self->cgi->param('verbosity') eq 'full') || ($self->cgi->param('verbosity') eq 'summary')) {
my $metadata = $project->data();
my $desc = $metadata->{project_description} || $metadata->{study_abstract} || " - ";
my $fund = $metadata->{project_funding} || " - ";
$obj->{metadata} = $metadata;
$obj->{description} = $desc;
- $obj->{funding_source} = $fund;
+ $obj->{funding_source} = $fund;
+
+ if ($self->cgi->param('verbosity') eq 'summary') {
+ my $jdata = $project->metagenomes_summary();
+ $obj->{metagenomes} = [];
+ foreach my $row (@$jdata) {
+ push(@{$obj->{metagenomes}}, { metagenome_id => $row->[0],
+ name => $row->[1],
+ basepairs => $row->[2],
+ sequences => $row->[3],
+ biome => $row->[4],
+ feature => $row->[5],
+ material => $row->[6],
+ location => $row->[7],
+ country => $row->[8],
+ coordinates => $row->[9],
+ sequence_type => $row->[10],
+ sequencing_method => $row->[11] });
+ }
+ }
} elsif ($self->cgi->param('verbosity') ne 'minimal') {
$self->return_data( {"ERROR" => "invalid value for option verbosity"}, 400 );
}
View
262 src/MGRAST/lib/resources/resource.pm
@@ -59,6 +59,13 @@ sub new {
#}
#### changed because globus has hard time handeling multiple tokens
my $mgrast_token = $Conf::mgrast_oauth_token || undef;
+ my $token;
+ if ($params->{cgi}->http('HTTP_AUTH') || $params->{cgi}->http('HTTP_Authorization')) {
+ $token = $params->{cgi}->http('HTTP_AUTH') || $params->{cgi}->http('HTTP_Authorization');
+ if ($params->{cgi}->http('HTTP_Authorization')) {
+ $token =~ s/^mgrast (.+)$/$1/;
+ }
+ }
# create object
my $self = {
@@ -72,7 +79,7 @@ sub new {
submethod => $params->{submethod},
resource => $params->{resource},
user => $params->{user},
- token => $params->{cgi}->http('HTTP_AUTH') || undef,
+ token => $token,
mgrast_token => $mgrast_token,
json_rpc => $params->{json_rpc} ? $params->{json_rpc} : 0,
json_rpc_id => ($params->{json_rpc} && exists($params->{json_rpc_id})) ? $params->{json_rpc_id} : undef,
@@ -218,51 +225,55 @@ sub hierarchy {
};
}
-# hardcoded list of metagenome pipeline option keywords
+# hardcoded list of metagenome pipeline option keywords for submission
sub pipeline_opts {
- return [ 'assembled',
- 'bowtie',
- 'dereplicate',
- 'dynamic_trim',
- 'file_type',
- 'filter_ambig',
- 'filter_ln',
- 'max_ambig',
- 'max_ln',
- 'max_lqb',
- 'min_ln',
- 'min_qual',
- 'priority',
- 'screen_indexes',
- 'sequence_type_guess',
- 'sequencing_method_guess'
+ return [
+ 'aa_pid',
+ 'assembled',
+ 'bowtie',
+ 'dereplicate',
+ 'dynamic_trim',
+ 'fgs_type',
+ 'file_type',
+ 'filter_ambig',
+ 'filter_ln',
+ 'filter_ln_mult',
+ 'max_ambig',
+ 'max_lqb',
+ 'min_qual',
+ 'prefix_length',
+ 'priority',
+ 'rna_pid',
+ 'screen_indexes',
+ 'sequence_type', # not in defaults
+ 'sequencing_method_guess' # not in defaults
];
}
# hardcoded list of metagenome pipeline paramters with defaults
sub pipeline_defaults {
return {
+ 'aa_pid' => '90',
+ 'assembled' => 'no',
+ 'bowtie' => 'yes',
+ 'dereplicate' => 'yes',
+ 'dynamic_trim' => 'yes',
+ 'fgs_type' => '454',
'file_type' => 'fna',
+ 'filter_ambig' => 'yes',
'filter_ln' => 'yes',
'filter_ln_mult' => '2.0',
- 'filter_ambig' => 'yes',
+ 'm5nr_annotation_version' => '1', # not in options
+ 'm5rna_annotation_version' => '1', # not in options
+ 'm5nr_sims_version' => '1', # not in options
+ 'm5rna_sims_version' => '1', # not in options
'max_ambig' => '5',
- 'dynamic_trim' => 'yes',
- 'min_qual' => '15',
'max_lqb' => '5',
- 'dereplicate' => 'yes',
+ 'min_qual' => '15',
'prefix_length' => '50',
- 'bowtie' => 'yes',
- 'screen_indexes' => 'h_sapiens_asm',
- 'fgs_type' => '454',
+ 'priority' => 'never',
'rna_pid' => '97',
- 'aa_pid' => '90',
- 'm5nr_sims_version' => '1',
- 'm5rna_sims_version' => '1',
- 'm5nr_annotation_version' => '1',
- 'm5rna_annotation_version' => '1',
- 'assembled' => 'no',
- 'publish_priority' => 'never'
+ 'screen_indexes' => 'h_sapiens'
};
}
@@ -547,8 +558,12 @@ sub download_text {
# stream a file from shock to browser
sub return_shock_file {
- my ($self, $id, $size, $name, $auth) = @_;
+ my ($self, $id, $size, $name, $auth, $authPrefix) = @_;
+ if (! $authPrefix) {
+ $authPrefix = "OAuth";
+ }
+
my $response = undef;
# print headers
print "Content-Type:application/x-download\n";
@@ -560,7 +575,7 @@ sub return_shock_file {
eval {
my $url = $Conf::shock_url.'/node/'.$id.'?download_raw';
my @args = (
- $auth ? ('Authorization', "OAuth $auth") : (),
+ $auth ? ('Authorization', "$authPrefix $auth") : (),
':read_size_hint', 8192,
':content_cb', sub{ my ($chunk) = @_; print $chunk; }
);
@@ -575,12 +590,16 @@ sub return_shock_file {
## download array of info for metagenome files in shock
sub get_download_set {
- my ($self, $mgid, $auth, $seq_only) = @_;
+ my ($self, $mgid, $auth, $seq_only, $authPrefix) = @_;
+
+ if (! $authPrefix) {
+ $authPrefix = "OAuth";
+ }
my %seen = ();
my %subset = ('preprocess' => 1, 'dereplication' => 1, 'screen' => 1);
my $stages = [];
- my $mgdata = $self->get_shock_query({'type' => 'metagenome', 'id' => 'mgm'.$mgid}, $auth);
+ my $mgdata = $self->get_shock_query({'type' => 'metagenome', 'id' => 'mgm'.$mgid}, $auth, $authPrefix);
@$mgdata = grep { exists($_->{attributes}{stage_id}) && exists($_->{attributes}{data_type}) } @$mgdata;
@$mgdata = sort { ($a->{attributes}{stage_id} cmp $b->{attributes}{stage_id}) ||
($a->{attributes}{data_type} cmp $b->{attributes}{data_type}) } @$mgdata;
@@ -665,16 +684,20 @@ sub get_download_set {
# add or delete an ACL based on username
sub edit_shock_acl {
- my ($self, $id, $auth, $user, $action, $acl) = @_;
+ my ($self, $id, $auth, $user, $action, $acl, $authPrefix) = @_;
+ if (! $authPrefix) {
+ $authPrefix = "OAuth";
+ }
+
my $response = undef;
my $url = $Conf::shock_url.'/node/'.$id.'/acl/'.$acl.'?users='.$user;