4 SGN::Controller::AJAX::ODK - a REST controller class to provide the
5 backend for ODK services
13 package SGN
::Controller
::AJAX
::ODK
;
16 use List
::MoreUtils qw
/any /;
19 use CXGN
::Phenome
::Schema
;
20 use Bio
::Chado
::Schema
;
22 use SGN
::Model
::Cvterm
;
25 use CXGN
::ODK
::Crosses
;
27 use File
::Spec
::Functions qw
/ catfile catdir/;
28 use File
::Path
qw(make_path);
30 BEGIN { extends
'Catalyst::Controller::REST' }
33 default => 'application/json',
35 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
39 sub get_phenotyping_data
: Path
('/ajax/odk/get_phenotyping_data') : ActionClass
('REST') { }
41 sub get_phenotyping_data_GET
{
42 my ( $self, $c ) = @_;
43 my $odk_phenotyping_data_service_name = $c->config->{odk_phenotyping_data_service_name
};
44 my $odk_phenotyping_data_service_username = $c->config->{odk_phenotyping_data_service_username
};
45 my $odk_phenotyping_data_service_password = $c->config->{odk_phenotyping_data_service_password
};
46 if ($odk_phenotyping_data_service_name eq 'SMAP'){
47 my $ua = LWP
::UserAgent
->new;
48 my $server_endpoint = "https://".$odk_phenotyping_data_service_username.":".$odk_phenotyping_data_service_password."\@bio.smap.com.au/api/v1/data";
49 print STDERR
$server_endpoint."\n";
51 my $resp = $ua->get($server_endpoint);
52 if ($resp->is_success) {
53 my $message = $resp->decoded_content;
54 my $message_hash = decode_json
$message;
55 print STDERR Dumper
$message_hash;
57 print STDERR Dumper
$resp;
61 $c->stash->{rest
} = { error
=> 'Error: We only support SMAP as an ODK phenotyping service for now.' };
64 $c->stash->{rest
} = { success
=> 1 };
67 sub get_crossing_available_forms
: Path
('/ajax/odk/get_crossing_available_forms') : ActionClass
('REST') { }
69 sub get_crossing_available_forms_GET
{
70 my ( $self, $c ) = @_;
71 my $odk_crossing_data_service_name = $c->config->{odk_crossing_data_service_name
};
73 if ($odk_crossing_data_service_name eq 'ONA'){
74 my $ua = LWP
::UserAgent
->new;
75 $ua->credentials( 'api.ona.io:443', 'DJANGO', $c->config->{odk_crossing_data_service_username
}, $c->config->{odk_crossing_data_service_password
} );
76 my $login_resp = $ua->get("https://api.ona.io/api/v1/user.json");
77 my $server_endpoint = "https://api.ona.io/api/v1/data";
78 my $resp = $ua->get($server_endpoint);
80 if ($resp->is_success) {
81 my $message = $resp->decoded_content;
82 $message_hash = decode_json
$message;
85 $c->stash->{rest
} = { error
=> 'Error: We only support ONA as an ODK crossing service for now.' };
88 $c->stash->{rest
} = { success
=> 1, forms
=>$message_hash };
91 sub get_crossing_data
: Path
('/ajax/odk/get_crossing_data') : ActionClass
('REST') { }
93 sub get_crossing_data_GET
{
94 my ( $self, $c ) = @_;
95 my $cross_wishlist_id = $c->req->param('cross_wishlist_md_file_id');
96 my $cross_wishlist_file_name = $c->req->param('cross_wishlist_file_name');
97 my $form_id = $c->req->param('form_id');
98 my $session_id = $c->req->param("sgn_session_id");
103 my $dbh = $c->dbc->dbh;
104 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
106 $c->stash->{rest
} = {error
=>'You must be logged in to request ODK crossing data import!'};
109 $user_id = $user_info[0];
110 $user_role = $user_info[1];
111 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
112 $user_name = $p->get_username;
115 $c->stash->{rest
} = {error
=>'You must be logged in to request ODK crossing data import!'};
118 $user_id = $c->user()->get_object()->get_sp_person_id();
119 $user_name = $c->user()->get_object()->get_username();
120 $user_role = $c->user->get_object->get_user_type();
122 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
123 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
124 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
125 my $tempfiles_dir = $c->tempfiles_subdir('ODK_ONA_cross_info');
126 my ($temp_file, $uri1) = $c->tempfile( TEMPLATE
=> 'ODK_ONA_cross_info/ODK_ONA_cross_info_downloadXXXXX');
127 my $temp_file_path = $temp_file->filename;
129 my $progress_tree_dir = catdir
($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
131 my $odk_crosses = CXGN
::ODK
::Crosses
->new({
132 bcs_schema
=>$bcs_schema,
133 metadata_schema
=>$metadata_schema,
134 phenome_schema
=>$phenome_schema,
135 sp_person_id
=>$user_id,
136 sp_person_username
=>$user_name,
137 sp_person_role
=>$user_role,
138 archive_path
=>$c->config->{archive_path
},
139 temp_file_dir
=>$c->config->{basepath
}.$tempfiles_dir,
140 temp_file_path
=>$temp_file_path,
141 cross_wishlist_md_file_id
=>$cross_wishlist_id,
142 cross_wishlist_file_name
=>$cross_wishlist_file_name,
143 allowed_cross_properties
=>$c->config->{cross_properties
},
144 odk_crossing_data_service_url
=>$c->config->{odk_crossing_data_service_url
},
145 odk_crossing_data_service_username
=>$c->config->{odk_crossing_data_service_username
},
146 odk_crossing_data_service_password
=>$c->config->{odk_crossing_data_service_password
},
147 odk_crossing_data_service_form_id
=>$form_id,
148 odk_cross_progress_tree_file_dir
=>$progress_tree_dir
151 my $odk_crossing_data_service_name = $c->config->{odk_crossing_data_service_name
};
152 if ($odk_crossing_data_service_name eq 'ONA'){
153 my $result = $odk_crosses->save_ona_cross_info($c);
154 if ($result->{error
}){
155 $c->stash->{rest
} = { error
=> $result->{error
} };
157 } elsif ($result->{success
}){
158 $c->stash->{rest
} = { success
=> 1 };
162 $c->stash->{rest
} = { error
=> 'Error: We only support ONA as an ODK crossing service for now.' };
167 sub schedule_get_crossing_data
: Path
('/ajax/odk/schedule_get_crossing_data') : ActionClass
('REST') { }
169 sub schedule_get_crossing_data_GET
{
170 my ( $self, $c ) = @_;
171 if ($c->config->{production_server
}){
172 $c->stash->{rest
} = { error
=>'Please use contact form. Currently this cannot be set through the website.' };
175 my $form_id = $c->req->param('form_id');
176 my $cross_wishlist_id = $c->req->param('cross_wishlist_md_file_id');
177 my $cross_wishlist_file_name = $c->req->param('cross_wishlist_file_name');
178 my $timing_select = $c->req->param('timing');
179 my $session_id = $c->req->param("sgn_session_id");
184 my $dbh = $c->dbc->dbh;
185 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
187 $c->stash->{rest
} = {error
=>'You must be logged in to schedule ODK crossing data import!'};
190 $user_id = $user_info[0];
191 $user_role = $user_info[1];
192 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
193 $user_name = $p->get_username;
196 $c->stash->{rest
} = {error
=>'You must be logged in to schedule ODK crossing data import!'};
199 $user_id = $c->user()->get_object()->get_sp_person_id();
200 $user_name = $c->user()->get_object()->get_username();
201 $user_role = $c->user->get_object->get_user_type();
203 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
204 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
205 my $tempfiles_dir = $c->tempfiles_subdir('ODK_ONA_cross_info');
206 my ($temp_file, $uri1) = $c->tempfile( TEMPLATE
=> 'ODK_ONA_cross_info/ODK_ONA_cross_info_downloadXXXXX');
207 my $temp_file_path = $temp_file->filename;
209 my $progress_tree_dir = catdir
($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
211 my $cross_properties = $c->config->{cross_properties
};
212 my $rootpath = $c->config->{rootpath
};
213 my $basepath = $c->config->{basepath
};
214 my $archive_path = $c->config->{archive_path
};
215 my $ODK_url = $c->config->{odk_crossing_data_service_url
};
216 my $ODk_username = $c->config->{odk_crossing_data_service_username
};
217 my $ODK_password = $c->config->{odk_crossing_data_service_password
};
218 my $database_name = $c->config->{dbname
};
219 my $database_user = $c->config->{dbuser
};
220 my $database_pass = $c->config->{dbpass
};
221 my $database_host = $c->config->{dbhost
};
222 my $www_user = $c->config->{www_user
};
223 my $crontab_log = $c->config->{crontab_log_filepath
};
224 my $include_path = 'export PERL5LIB="$PERL5LIB:'.$basepath.'/lib:'.$rootpath.'/cxgn-corelibs/lib:'.$rootpath.'/Phenome/lib:'.$rootpath.'/local-lib/lib/perl5"';
225 my $perl_command = "$include_path; perl $basepath/bin/ODK/ODK_ONA_get_crosses.pl -u $user_id -i $user_name -r $user_role -a $archive_path -d $basepath.$tempfiles_dir -t $temp_file_path -n $ODk_username -m $ODK_password -o $form_id -w $cross_wishlist_id -x $cross_wishlist_file_name -f $progress_tree_dir -l $ODK_url -c $cross_properties -D $database_name -U $database_user -p $database_pass -H $database_host >> $crontab_log 2>&1";
227 if ($timing_select eq 'everyminute'){
228 $timing = "0-59/1 * * * * ";
229 } elsif ($timing_select eq 'everyday'){
230 $timing = "1 0 * * * ";
231 } elsif ($timing_select eq 'everyhour'){
232 $timing = "0 * * * * ";
233 } elsif ($timing_select eq 'twicedaily'){
234 $timing = "0 0,12 * * * ";
236 my $crontab_line = $timing.$perl_command."\n";
237 #print STDERR $crontab_line;
238 my $crontab_file = $c->config->{crontab_file
};
239 open (my $F, ">", $crontab_file) || die "Could not open $crontab_file: $!\n";
241 print $F $crontab_line;
245 my $enable_new_crontab = "crontab -u $www_user $crontab_file";
246 system($enable_new_crontab);
248 $c->stash->{rest
} = { success
=> 1 };
253 sub get_crossing_data_cronjobs
: Path
('/ajax/odk/get_crossing_data_cronjobs') : ActionClass
('REST') { }
255 sub get_crossing_data_cronjobs_GET
{
256 my ( $self, $c ) = @_;
257 my $session_id = $c->req->param("sgn_session_id");
262 my $dbh = $c->dbc->dbh;
263 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
265 $c->stash->{rest
} = {error
=>'You must be logged in to see scheduled ODK crossing data import!'};
268 $user_id = $user_info[0];
269 $user_role = $user_info[1];
270 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
271 $user_name = $p->get_username;
274 $c->stash->{rest
} = {error
=>'You must be logged in to see scheduled ODK crossing data import!'};
277 $user_id = $c->user()->get_object()->get_sp_person_id();
278 $user_name = $c->user()->get_object()->get_username();
279 $user_role = $c->user->get_object->get_user_type();
283 my $crontab_file = $c->config->{crontab_file
};
284 open(my $fh, '<:encoding(UTF-8)', $crontab_file)
285 or die "Could not open file '$crontab_file' $!";
287 while (my $row = <$fh>) {
289 my @c = split 'export', $row;
290 push @entries, $c[0];
294 $c->stash->{rest
} = { success
=> 1, entries
=>\
@entries };
298 sub get_crossing_available_wishlists
: Path
('/ajax/odk/get_crossing_available_wishlists') : ActionClass
('REST') { }
300 sub get_crossing_available_wishlists_GET
{
301 my ( $self, $c ) = @_;
302 my $session_id = $c->req->param("sgn_session_id");
307 my $dbh = $c->dbc->dbh;
308 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
310 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK cross wishlists!'};
313 $user_id = $user_info[0];
314 $user_role = $user_info[1];
315 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
316 $user_name = $p->get_username;
319 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK cross wishlists!'};
322 $user_id = $c->user()->get_object()->get_sp_person_id();
323 $user_name = $c->user()->get_object()->get_username();
324 $user_role = $c->user->get_object->get_user_type();
326 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
327 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
329 my $wishlist_md_files = $metadata_schema->resultset("MdFiles")->search({filetype
=> { '-like' => 'cross_wishlist_%', }});
331 while (my $r=$wishlist_md_files->next){
332 if (index($r->filetype, 'cross_wishlist_germplasm_info_') == -1) {
333 push @wishlists, [$r->file_id, $r->filetype];
336 #print STDERR Dumper \@wishlists;
338 $c->stash->{rest
} = { success
=> 1, wishlists
=> \
@wishlists };
342 sub get_odk_cross_progress_cached
: Path
('/ajax/odk/get_odk_cross_progress_cached') : ActionClass
('REST') { }
344 sub get_odk_cross_progress_cached_GET
{
345 my ( $self, $c ) = @_;
346 my $wishlist_file_id = $c->req->param("cross_wishlist_file_id");
347 my $session_id = $c->req->param("sgn_session_id");
352 my $dbh = $c->dbc->dbh;
353 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
355 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK crossing data progress!'};
358 $user_id = $user_info[0];
359 $user_role = $user_info[1];
360 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
361 $user_name = $p->get_username;
364 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK crossing data progress!'};
367 $user_id = $c->user()->get_object()->get_sp_person_id();
368 $user_name = $c->user()->get_object()->get_username();
369 $user_role = $c->user->get_object->get_user_type();
371 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
372 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
374 my $dir = catdir
($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
375 eval { make_path
($dir) };
377 print "Couldn't create $dir: $@";
379 my $filename = $dir."/entire_odk_cross_progress_html_".$wishlist_file_id.".txt";
380 print STDERR
"Opening $filename \n";
382 open(my $fh, '<', $filename) or die "cannot open file $filename";
385 $contents = decode_json
<$fh>;
388 my $json = $contents->{top_level_json
};
390 my $top_level_id = $c->req->param('id');
391 print STDERR
"ODK Cross Tree Progress Node: ".$top_level_id."\n";
392 if ($top_level_id eq '#'){
393 $top_level_id = undef;
396 my $top_level_contents = $contents->{top_level_contents
};
397 $json = $top_level_contents->{$top_level_id};
400 #print STDERR Dumper $json;
401 $c->stash->{rest
} = $json;
404 sub get_odk_cross_summary_cached
: Path
('/ajax/odk/get_odk_cross_summary_cached') : ActionClass
('REST') { }
406 sub get_odk_cross_summary_cached_GET
{
407 my ( $self, $c ) = @_;
408 my $wishlist_file_id = $c->req->param("cross_wishlist_file_id");
409 my $session_id = $c->req->param("sgn_session_id");
414 my $dbh = $c->dbc->dbh;
415 my @user_info = CXGN
::Login
->new($dbh)->query_from_cookie($session_id);
417 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK crossing data progress!'};
420 $user_id = $user_info[0];
421 $user_role = $user_info[1];
422 my $p = CXGN
::People
::Person
->new($dbh, $user_id);
423 $user_name = $p->get_username;
426 $c->stash->{rest
} = {error
=>'You must be logged in to see ODK crossing data progress!'};
429 $user_id = $c->user()->get_object()->get_sp_person_id();
430 $user_name = $c->user()->get_object()->get_username();
431 $user_role = $c->user->get_object->get_user_type();
433 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
434 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
436 my $dir = catdir
($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
437 eval { make_path
($dir) };
439 print "Couldn't create $dir: $@";
441 my $filename = $dir."/entire_odk_cross_progress_html_".$wishlist_file_id.".txt";
442 print STDERR
"Opening $filename \n";
444 open(my $fh, '<', $filename) or die "cannot open file $filename";
447 $contents = decode_json
<$fh>;
450 my $summary = $contents->{summary_info
};
451 my $plant_status_summary = $contents->{summary_plant_status_info
};
453 #print STDERR Dumper $summary;
454 $c->stash->{rest
} = { summary
=> $summary, plant_status_summary
=> $plant_status_summary };