Commit dccdebd3 authored by gsalin's avatar gsalin
Browse files
parent ab933c95
<?php
namespace ng6\Controller;
/***************************************************************
* Copyright notice
*
* (c) 2009 PF bioinformatique de Toulouse <>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* Plugin 'nG6' for the 'nG6' extension.
*
* @author PF bioinformatique de Toulouse <>
*/
//require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('saltedpasswords').'/classes/salts/class.tx_saltedpasswords_salts_factory.php');
class tx_nG6_utils {
/**
* Describe all links between analyzes (and their ancestor) and build a tree. The main Array is the root.
* Example of result : Array( [a] => Array( ["data"] => Array(), ["child"] => Array( ... ) ) )
*
* @param Array $analyzes_map analyze array (for example, result of tx_nG6_db::get_project_analysis(...))
* @return a tree describing the links children-parents of all analyzes
*/
static function trace_hierarchy($analyzes_map) {
$base_tree = array();
foreach(array_values($analyzes_map) as $id => $analyze) {
$base_tree[$analyze['id']] = $analyze['parent_id'];
//$tree_analyze[$analyze['id']] = $analyze;
$tree_analyze[$analyze['id']] = array("data" => $analyze, "child" => array());
}
// Create relationships
$h_analysis = array();
if(is_array($tree_analyze)){
foreach($tree_analyze as $analyze_id => $analyze_infos) {
if ($analyze_infos["data"]["parent_id"] == 0) {
$h_analysis[$analyze_id] = &$tree_analyze[$analyze_id];
} else {
$tree_analyze[$analyze_infos["data"]["parent_id"]]["child"][$analyze_id] = &$tree_analyze[$analyze_id];
}
}
}
return $h_analysis;
}
/**
* Test if the substring ends the string
*
* @param $str : the string to test
* @param $sub : the substring that may ends $str
* @return boolean
*/
static function ends_with($str, $sub) {
return ( substr( $str, strlen( $str ) - strlen( $sub ) ) == $sub );
}
/**
* Returns a string generated randomly
*
* @param $size : the random key size
* @return string
*/
static function create_random_key($size) {
$keyset = "abcdefghijklmABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$randkey = "";
for ($i=0; $i<$size; $i++)
$randkey .= substr($keyset, rand(0, strlen($keyset)-1), 1);
return $randkey;
}
/**
* Delete directories
*
* @param string $user_login
* @param string $user_pwd
* @param string $directory
* @return 0=>everything ok, 1=>user right problem, 2=>wrong authentification, 3=>connection error
*/
static function delete_directory($user_login, $user_pwd, $directory) {
// First try to connect the specified user using ssh
$connection = ssh2_connect('127.0.0.1', 22);
if (!$connection) return 3;
if (!ssh2_auth_password($connection, $user_login, $user_pwd)) return 2;
if ($directory != 'undefined' && $directory != '') {
// And process the directories structure
//TODO BUG NE RETOURNE PAS D'ERREUR si pas supprimer
$stream = ssh2_exec($connection, 'rm -rf '.$directory."/");
$errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
// Enable blocking for both streams
stream_set_blocking($errorStream, true);
stream_set_blocking($stream, true);
// Whichever of the two below commands is listed first will receive its appropriate output. The second command receives nothing
if(stream_get_contents($errorStream)) {
// Close the streams
fclose($errorStream);
fclose($stream);
return 1;
}else{
// Close the streams
fclose($errorStream);
fclose($stream);
return 0;
}
}
return 0;
}
/**
* Purge directories
*
* @param string $user_login
* @param string $user_pwd
* @param string $directory
* @return 0=>everything ok, 1=>user right problem, 2=>wrong authentification, 3=>connection error
*/
static function purge_directory($user_login, $user_pwd, $directory) {
if ($directory != 'undefined' && $directory != '') {
// And process the directories structure, remove all files except .html ans .png
$connection = ssh2_connect('127.0.0.1', 22);
if (!$connection) {
return 3;
}
if (!ssh2_auth_password($connection, $user_login,$user_pwd )){
return 2;
}
$stream = ssh2_exec($connection, 'ls -d '.$directory.'/' );
$errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
// Enable blocking for both streams
stream_set_blocking($errorStream, true);
stream_set_blocking($stream, true);
//if error is raised, $directory does not exist>no problem (in case of an analysis which do not have associated files
if(stream_get_contents($errorStream)) {
// Close the streams
fclose($errorStream);
fclose($stream);
return 0;
}
#Exclusion of the log files from the purge process
$stream = ssh2_exec($connection, 'find '.$directory.' -maxdepth 1 -not -name "*.html" -not -name "*.png" -not -name "*.log" -not -name "*.log.gz" -not -name "*.pdf" -not -name "md5sum.txt" -not -name "*GXB02039*" -not -name "*PCT0078*" -type f -exec rm -f {} \;');
$errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
// Enable blocking for both streams
stream_set_blocking($errorStream, true);
stream_set_blocking($stream, true);
//if error is raised, connected user does not have the right to delete the files
if(stream_get_contents($errorStream)) {
// Close the streams
fclose($errorStream);
fclose($stream);
return 1;
}else{
// Close the streams
fclose($errorStream);
fclose($stream);
return 0;
}
}
}
/**
* Return the string representation of a byte
*
* @param string $size
*/
static function get_octet_string_representation($size) {
$octets_link = array("Bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB");
$p = (int)(ceil((float)(strlen(strval($size)))/(float)(3) - (float)(1)));
$pow_needed = $p * 10;
$pow_needed = pow(2, $pow_needed);
$value = (float)($size)/(float)($pow_needed);
$tmp = explode(".", $value);
$value = $tmp[0].".".substr($tmp[1], 0, 2);
$value = $value." ".$octets_link[$p];
return $value;
}
static function get_purge_mail($project_name, $project_id, $nb_run_purgeable,$nb_analyse_purgeable, $demand_id,
$purgeable_size, $project_size, $purge_delay, $url_price, $min_extention_duration,
$min_extention_size, $emails, $runs_list, $analyse_list, $with_extension) {
$template_mail='
<html>
<head>
<title>Data Purge on nG6</title>
</head>
<body>
<p>Dear user,</p>
<p>The data storage period of part or whole ###PROJECT_NAME### project (###nb_run### run(s) and ###nb_analyse### analyse(s)) is ended.</p>
<p>This purge alert No ###DEMAND_ID### corresponds to ###SIZE_STR### see list of impacted files below.</p>
<p>In ###PURGE_DELAY### days, your data will be deleted.</p>';
if($with_extension){
$template_mail .= '<p>Keep us informed if you wish to extend the storage period,
please have a look at our storage fees (<a href="###URL_PRICE###">###URL_PRICE###</a>) and reply to this email with the following information:</p>
<p>----------------------------------------------</p>
<ul><li>Demand number: ###DEMAND_ID###</li>
<li>Request for extension term: XXX (minimal unit: ###EXTENSION_DURATION###)</li>
<li>Request for extension size: XXX (mininal unit: ###EXTENSION_SIZE###)</li>
<li>Laboratory name/Institution: </li></ul>
<p>----------------------------------------------</p>
<p>###EMAILS###We would appreciate if you could group your demands by laboratory.</p>';
}else{
$template_mail .= '<p>###EMAILS###</p>';
}
$template_mail.='The nG6 purge process is undergoing an important overhaul.</br>
You can visit our FAQ at the following address : https://ng6.toulouse.inra.fr/faq .</br>
If you have any question or demand, do not hesitate to contact our support team at ng6-support@groupes.renater.fr.</br>';
$template_mail.='<p>Yours sincerely</p>
<p>nG6 team (for GeT-Genotoul and Bioinfo-Genotoul facilities)</p>
<p>Files impacted of:</p>
<ul>
<li>Runs : ###RUNS_LIST###
<li>Analyzes : ###ANALYSES_LIST###</li>
</ul>
</body>
</html>
';
$size_str = $purgeable_size . " purgeable data on ". $project_size ." of whole project";
if ($purgeable_size == $project_size) {
$size_str = "whole project (".$purgeable_size . ")";
}
$search=array("###nb_run###","###nb_analyse###","###PROJECT_NAME###","###PROJET_ID###","###DEMAND_ID###",
"###EMAILS###","###RUNS_LIST###","###ANALYSES_LIST###","###SIZE_STR###",
"###EXTENSION_DURATION###","###EXTENSION_SIZE###","###URL_PRICE###","###PURGE_DELAY###");
$replace=array($nb_run_purgeable,$nb_analyse_purgeable,$project_name,$project_id, $demand_id ,
$emails, $runs_list, $analyse_list, $size_str,
$min_extention_duration, $min_extention_size, $url_price, $purge_delay);
$mail=str_replace($search, $replace, $template_mail);
return $mail;
}
/**
* Returns the mail content to warn the nG6 admins that a purge demand already exists for the given project
* @param string $project_name
* @return $mail, a string containing the mail content
*/
static function get_multiple_purge_demand_mail($project_name) {
$template_mail='
<html>
<head>
<title>Data Purge on nG6</title>
</head>
<body>
<p>Dear nG6 admin,</p>
<p>A purge demand already exists for the project ###PROJECT_NAME###.</p>
<p>Please, purge the data corresponding to the previous purge demand before opening a new one.</p></br>
<p>Yours sincerely</p>
<p>nG6 team (for GeT-Genotoul and Bioinfo-Genotoul facilities)</p>
</body>
</html>
';
$mail = str_replace('###PROJECT_NAME###', $project_name, $template_mail);
return $mail;
}
/**
* hash password (using default encryption method)
* @param string $password
* @return hashed password
*/
static function hash_password($password){
$hashInstance = TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory::class)->getDefaultHashInstance('FE');
$hashedPassword = $hashInstance->getHashedPassword($password);
return $hashedPassword;
}
static function get_ssh_connection($user_login, $user_pwd){
$connection = ssh2_connect('127.0.0.1', 22);
if (!$connection) return NULL;
if (!ssh2_auth_password($connection, $user_login, $user_pwd)) return NULL;
return $connection ;
}
static function get_config_content(){
$config_file_path = __DIR__."/../../../application.properties";
$config_file_content = file_get_contents($config_file_path);
return($config_file_content);
}
//Return a php array containing the section relative to the given space_id
static function get_retention_policy_from_space_id($space_id = "default"){
$config_file_content = tx_nG6_utils::get_config_content();
//To explode the file content by line, we use PHP_EOL
$array_config_content = explode(PHP_EOL, $config_file_content);
$space_id_retention_config = array();
$pattern_to_find = "[space_".$space_id."]";
$is_space_id_found = FALSE;
//We want to return the space id config as an array
foreach($array_config_content as $line_id => $line_content){
//if we found the right section
if($line_content == $pattern_to_find){
$is_space_id_found = TRUE;
}
//If we enter a new section, we stop the line copying
if($is_space_id_found && $line_content != $pattern_to_find && strpos($line_content,'[')===0 ){
$is_space_id_found = FALSE;
}
if($is_space_id_found){
$space_id_retention_config[] = $line_content;
}
}
return($space_id_retention_config);
}
static function get_project_retention_policy( $project_id ){
$space_id = tx_nG6_db::get_project_space_id($project_id);
$retention_policy = tx_nG6_utils::get_retention_policy_from_space_id($space_id);
$retention_line = "";
$policy = "";
$retention_value = "";
$return_text = "";
foreach($retention_policy as $line => $line_content){
if( strpos($line_content,"retention") === 0 ){
$retention_line = $line_content;
}
}
if( is_numeric(strpos($retention_line,"date"))){
$policy = "date";
}elseif( is_numeric(strpos($retention_line,"period"))){
$policy = "period";
}
$split_retention_line = explode('=',$retention_line);
$retention_value = $split_retention_line[1];
if($policy == "date"){
$date = date_create_from_format("d/m/Y", $retention_value);
$nice_date = date_format($date, 'l jS \of F Y');
$return_text = " until ".$nice_date;
}elseif($policy == "period"){
$return_text = " for ".$retention_value." months";
}
return($return_text);
}
//Return a php array with array[space_name]=space_name, containing all available space_ids
static function get_available_space_ids (){
$config_file_content = tx_nG6_utils::get_config_content();
//To explode the file content by line, we use PHP_EOL
$array_config_content = explode(PHP_EOL, $config_file_content);
$ret = array();
foreach($array_config_content as $line => $line_content){
//If the current line starts with "[space_"
if( strpos($line_content,'[space_') === 0 ){
$space_id = str_replace('[space_','',$line_content);
$space_id = str_replace(']','',$space_id);
$space_id = trim($space_id);
$ret[$space_id]=$space_id;
}
}
return($ret);
}
static function get_project_data_save_dir($project_id){
$space_id = tx_nG6_db::get_project_space_id($project_id);
$space_config = tx_nG6_utils::get_retention_policy_from_space_id($space_id);
$path_to_space_save_dir = '';
foreach($space_config as $line_id => $line_content){
if(strpos($line_content, 'dir_name') === 0){
//We get the value in the "dir_name = " line
$space_save_dir = trim( substr( $line_content, strpos( $line_content, '=')+1 ) );
}
}
$save_dir = tx_nG6_utils::get_save_dir();
$path_to_space_save_dir = $save_dir.'/'.$space_save_dir;
return($path_to_space_save_dir);
}
static function get_project_purge_msg($project_id){
$space_id = tx_nG6_db::get_project_space_id($project_id);
$space_config = tx_nG6_utils::get_retention_policy_from_space_id($space_id);
$project_purge_msg = '';
foreach($space_config as $line_id => $line_content){
if(strpos($line_content, 'purge_msg') === 0){
//We get the value in the "purge_msg = " line
$project_purge_msg = trim( substr( $line_content, strpos( $line_content, '=')+1 ) );
}
}
return($project_purge_msg);
}
static function get_save_dir(){
$config_file_content = tx_nG6_utils::get_config_content($space_id);
$pattern_to_find = 'save_directory';
$array_config_content = explode(PHP_EOL, $config_file_content);
$path_to_save_dir='';
foreach($array_config_content as $line_id => $line_content){
//if we found the right section
if( strpos($line_content,$pattern_to_find)===0 && ! $is_pattern_found){
//We copy the line from the first '/'
$path_to_save_dir = substr($line_content, strpos( $line_content, '/')) ;
}
}
return($path_to_save_dir);
}
static function get_log_path(){
$config_file_content = tx_nG6_utils::get_config_content();
$array_config_content = explode(PHP_EOL, $config_file_content);
$pattern_to_find = "log_file = ";
$log_file_path_found = FALSE;
//We want to return the log file path
foreach($array_config_content as $line_id => $line_content){
//if we found the right line
if(strpos ( $line_content , $pattern_to_find) === 0){
$log_file_path_found = TRUE;
}
if($log_file_path_found){
$log_file_path = str_replace($pattern_to_find,'',$line_content);
return($log_file_path);
}
}
return('0');
}
static function convert_epoch_timestamp_to_nice_date( $epoch_date ){
//return(gmdate('D, d M Y', $epoch_date));
return(gmdate('l jS \of F Y', $epoch_date));
}
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/nG6/class.tx_nG6_utils.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/nG6/class.tx_nG6_utils.php']);
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/nG6/class.tx_nG6_db.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/nG6/class.tx_nG6_db.php']);
}
?>
This diff is collapsed.
This diff is collapsed.
<?php
return [
'frontend' => [
'typo3/cms-frontend/eid' => [
'disabled' => true
],
'typo3/cms-frontend/eid-new' => [
'target' => \TYPO3\CMS\Frontend\Middleware\EidHandler::class,
'after' => [
'typo3/cms-frontend/tsfe',
],
'before' => [
'typo3/cms-frontend/prepare-tsfe-rendering',
]
]
]
];
\ No newline at end of file
......@@ -55,6 +55,8 @@ exec('chmod 777 '.\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('n
## Added to do some ajax
$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_nG6'] = 'EXT:nG6/class.tx_nG6_eid.php';
$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_nG62'] = \ng6\Controller\tx_nG6_eid::class. '::processRequest';
$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['tx_nG6'] =\ng6\Controller\NG6::class . '::processRequest';
?>
......@@ -95,6 +95,11 @@
</div>
<div class="ng6-content-header-right">
<dl class="dl-horizontal">
<dt>HOW TO...</dt> <dd> <a href="https://genomique.genotoul.fr/e-SIToul-ResetPassword/mail" target="_blanck">recover my username and password</a>?</dd>
<dt></dt> <dd> <a href="https://ng6.toulouse.inra.fr/faq">get my data</a>?</dd>
<dt></dt> <dd> <a href="https://ng6.toulouse.inra.fr/faq">add a user to my project so it can access the data</a>?</dd>
</dl>
<h2><small>Keep up with </small>news</h2>
<dl class="dl-horizontal">
<dt>September 18 2018</dt> <dd>NG6 v3.2 is available on <a href="https://forgemia.inra.fr/genotoul-bioinfo/ng6/tags">https://forgemia.inra.fr/genotoul-bioinfo/ng6/tags</a>. Illumina pipelines were greatly improved (less time to make the data and analysis results available). An Oxford nanopore Technologies pipeline is now available. Can now work with slurm and sge. All runs come with a md5 sum file for raw data. New interface to manage projects and purge associated data is now included.</dd>
......
......@@ -27,6 +27,7 @@
* @author PF bioinformatique de Toulouse <>
*/
require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('nG6').'/lib/class.tx_nG6_db.php');
require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('nG6').'/lib/class.tx_nG6_utils.php');
require_once(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('nG6').'/lib/class.tx_nG6_upgrade.php');
......@@ -48,7 +49,7 @@ class tx_nG6_pi1 extends \TYPO3\CMS\Frontend\Plugin\AbstractPlugin {
* @return The content that should be displayed on the website
*/
function main($content,$conf) {
//error_log("tx_nG6_pi1 \n", 3, "/work/tmp/mes-erreurs.log");
error_log("tx_nG6_pi1 \n", 3, "/work/tmp/mes-erreurs.log");
$context = \TYPO3\CMS\Core\Utility\GeneralUtility ::makeInstance(Context::class);
if (strstr($this->cObj->currentRecord,'tt_content')) {
$conf['pidList'] = $this->cObj->data['pages'];
......@@ -136,11 +137,13 @@ class tx_nG6_pi1 extends \TYPO3\CMS\Frontend\Plugin\AbstractPlugin {
* Return the project view
*/
function pi_project_view() {
$projects = array();
error_log("pi_project_view \n", 3, "/work/tmp/mes-erreurs.log");
$projects = array();
$context = \TYPO3\CMS\Core\Utility\GeneralUtility ::makeInstance(Context::class);
if (!$context->getPropertyFromAspect('frontend.user', 'isLoggedIn')) { $user_id = null; }
else { $user_id = $GLOBALS['TSFE']->fe_user->user['uid']; }
else { $user_id = $context->getPropertyFromAspect('frontend.user', 'id'); }
$is_current_user_superadmin = tx_nG6_db::is_user_ng6_superadmin($user_id);
error_log("pi_project_view user_id = $user_id\n", 3, "/work/tmp/mes-erreurs.log");
$single_project_display = false;
......@@ -176,13 +179,15 @@ class tx_nG6_pi1 extends \TYPO3\CMS\Frontend\Plugin\AbstractPlugin {
$smarty->security_settings['MODIFIER_FUNCS'] = array('count');
// Add some information to the table
$project_ids = "";
$user_id = $context->getPropertyFromAspect('frontend.user', 'id');
$user_name = $context->getPropertyFromAspect('frontend.user', 'username');
foreach($projects as $project_id => $project_values) {
// project admin ?
$projects[$project_id]['is_admin'] = tx_nG6_db::is_project_administrator($GLOBALS['TSFE']->fe_user->user['uid'], $project_values