From 6dd09ba1a6748db6589f29ecbf0278388415db65 Mon Sep 17 00:00:00 2001 From: xevidos Date: Mon, 1 Jul 2019 09:24:34 -0400 Subject: [PATCH 1/7] Started new permissions module --- common.php | 46 +----- components/filemanager/class.filemanager.php | 15 +- components/filemanager/controller.php | 3 +- components/permissions/class.permissions.php | 146 +++++++++++++++++++ components/project/class.project.php | 38 +++-- components/project/controller.php | 15 +- components/project/dialog.php | 29 +++- components/project/init.js | 39 +++-- 8 files changed, 255 insertions(+), 76 deletions(-) create mode 100644 components/permissions/class.permissions.php diff --git a/common.php b/common.php index f4a7d9e..f4aab00 100755 --- a/common.php +++ b/common.php @@ -5,6 +5,9 @@ * [root]/license.txt for more. This information must remain intact. */ +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); $sql = null; Common::startSession(); @@ -93,6 +96,7 @@ class Common { define( "LANGUAGE", "en" ); } + require_once( COMPONENTS . "/permissions/class.permissions.php" ); require_once( COMPONENTS . "/update/class.update.php" ); require_once( COMPONENTS . "/sql/class.sql.php" ); global $sql; @@ -564,47 +568,7 @@ class Common { public static function checkPath( $path ) { - global $sql; - //$query = "SELECT * FROM projects WHERE LOCATE( path, ? ) > 0 LIMIT 1;"; - //$bind_variables = array( $path ); - //$result = $sql->query( $query, $bind_variables, array() )[0]; - $result = $sql->select( - "projects", - array(), - array( - array( - "find", - "[path]", - $path, - array( - "more than", - 0 - ) - ), - array( - "limit", - 1 - ) - ) - ); - - if( ! empty( $result ) ) { - - $result = $result[0]; - try { - - $users = json_decode( $result["access"] ); - } catch( exception $e ) { - - $users = array(); - } - - if( $result["owner"] == 'nobody' || $result["owner"] == $_SESSION["user"] || ( in_array( $_SESSION["user"], $users ) && ! empty( $users ) ) ) { - - return( true ); - } - } - return( false ); + return Permissions::has_manager( $path ); } diff --git a/components/filemanager/class.filemanager.php b/components/filemanager/class.filemanager.php index 8946de7..5e9fc87 100755 --- a/components/filemanager/class.filemanager.php +++ b/components/filemanager/class.filemanager.php @@ -164,7 +164,7 @@ class Filemanager extends Common { ////////////////////////////////////////////////////////////////// public function index() { - + if ( file_exists( $this->path ) ) { $index = array(); @@ -450,7 +450,7 @@ class Filemanager extends Common { public function delete( $keep_parent = false ) { - if( Common::checkPath( $path ) ) { + if( ! Permissions::has_delete( $this->path ) ) { $this->status = "error"; $this->message = "No access."; @@ -530,7 +530,9 @@ class Filemanager extends Common { if ( ! file_exists( $new_path ) ) { - if ( rename( $this->path, $new_path ) ) { + echo var_dump( Permissions::has_create( $this->path ) ); + + if ( Permissions::has_create( $this->path ) && rename( $this->path, $new_path ) ) { //unlink($this->path); $this->status = "success"; @@ -545,10 +547,10 @@ class Filemanager extends Common { $this->message = "Path Already Exists"; } } else { - + // Change content if ( $this->content || $this->patch ) { - + if ( $this->content == ' ' ) { $this->content = ''; // Blank out file @@ -560,7 +562,8 @@ class Filemanager extends Common { $this->respond(); return; } - if ( is_file( $this->path ) ) { + echo var_dump( Permissions::has_write( $this->path ) ); + if ( is_file( $this->path ) && Permissions::has_write( $this->path ) ) { $serverMTime = filemtime( $this->path ); $fileContents = file_get_contents( $this->path ); diff --git a/components/filemanager/controller.php b/components/filemanager/controller.php index 4822eb3..61b9304 100755 --- a/components/filemanager/controller.php +++ b/components/filemanager/controller.php @@ -39,7 +39,8 @@ if (!isset($_SESSION['project'])) { // Security Check ////////////////////////////////////////////////////////////////// -if (!checkPath($_GET['path'])) { +if ( ! Permissions::has_read( $_GET['path'] ) ) { + die('{"status":"error","message":"Invalid Path"}'); } diff --git a/components/permissions/class.permissions.php b/components/permissions/class.permissions.php new file mode 100644 index 0000000..9e37c41 --- /dev/null +++ b/components/permissions/class.permissions.php @@ -0,0 +1,146 @@ + 0, + "owner" => 1, + "manager" => 2, + "delete" => 3, + "create" => 4, + "write" => 5, + "read" => 6, + ); + + function __construct() { + + + } + + public static function check_path( $level, $path ) { + + $project_path = $_SESSION["project"]; + $project_path = rtrim( $project_path, '/' ) . '/'; + + if( ! in_array( $level, array_keys( self::LEVELS ) ) ) { + + exit( Common::formatJSEND( "error", "Access Level does not exist." ) ); + } + + if( strpos( $path, $project_path ) === 0 ) { + + exit( Common::formatJSEND( "error", "Error with path." ) ); + } + + global $sql; + $pass = false; + //$query = "SELECT * FROM projects WHERE LOCATE( path, ? ) > 0 LIMIT 1;"; + //$bind_variables = array( $path ); + //$result = $sql->query( $query, $bind_variables, array() )[0]; + /*$result = $sql->select( + "projects", + array(), + array( + array( + "find", + $path, + array( + "more than", + 0 + ) + ), + array( + "limit", + 1 + ) + ) + );*/ + + $query = "SELECT * FROM projects WHERE path=? LIMIT 1;"; + $bind_variables = array( $_SESSION["project"] ); + $result = $sql->query( $query, $bind_variables, array() )[0]; + + if( ! empty( $result ) ) { + + $result = $result[0]; + try { + + $users = json_decode( $result["access"], true ); + } catch( exception $e ) { + + $users = array(); + } + + if( $result["owner"] == 'nobody' ) { + + $pass = true; + } elseif( $result["owner"] == $_SESSION["user"] ) { + + $pass = true; + } elseif( in_array( $_SESSION["user"], array_keys( $users ) ) && ! empty( $users ) ) { + + //Only allow the owner to delete the root dir / project + if( $path == $result["path"] && self::LEVELS[$level] == self::LEVELS["delete"] ) { + + $level = "owner"; + } + + $is_assoc = ( array_keys( $users ) !== range( 0, count( $users ) - 1 ) ); + + if( $is_assoc ) { + + $users_access = $users[$_SESSION["user"]]; + } else { + + $users_access = self::LEVELS["delete"]; + } + + echo var_dump( $path, $result, $users_access, $level, ( self::LEVELS[$level] >= $users_access ), self::LEVELS[$level] + " is more than or equal to {$users_access}" ); + + if( self::LEVELS[$level] >= $users_access ) { + + $pass = true; + } + } + } + return( $pass ); + } + + public static function has_owner( $path ) { + + return self::check_path( "owner", $path ); + } + + public static function has_manager( $path ) { + + return self::check_path( "manager", $path ); + } + + public static function has_delete( $path ) { + + return self::check_path( "delete", $path ); + } + + public static function has_create( $path ) { + + return self::check_path( "create", $path ); + } + + public static function has_write( $path ) { + + return self::check_path( "write", $path ); + } + + public static function has_read( $path ) { + + return self::check_path( "read", $path ); + } +} + +?> \ No newline at end of file diff --git a/components/project/class.project.php b/components/project/class.project.php index 1497fa8..3dfcd27 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -14,13 +14,14 @@ class Project extends Common { // PROPERTIES ////////////////////////////////////////////////////////////////// - public $name = ''; - public $path = ''; - public $gitrepo = false; - public $gitbranch = ''; - public $projects = array(); - public $no_return = false; - public $assigned = false; + public $access = 100; + public $name = ''; + public $path = ''; + public $gitrepo = false; + public $gitbranch = ''; + public $projects = array(); + public $no_return = false; + public $assigned = false; public $command_exec = ''; public $public_project = false; public $user = ''; @@ -70,21 +71,32 @@ class Project extends Common { $query = "SELECT access FROM projects WHERE path=? AND owner=?"; $bind_variables = array( $this->path, $_SESSION["user"] ); $result = $sql->query( $query, $bind_variables, array() )[0]; - + if( ! empty( $result ) ) { $access = json_decode( $result["access"] ); - if( is_array( $access ) ) { + if( is_array( $access ) && ! empty( $access ) ) { - if( ! in_array( $this->user, $access ) ) { + $is_assoc = ( array_keys( $access ) !== range( 0, count( $access ) - 1 ) ); + + if( $is_assoc ) { - array_push( $access, $this->user ); + $access[$this->user] = $this->access; + } else { + + $new_access = array(); + foreach( $access as $user ) { + + $new_access[$user] = Permission::LEVELS["delete"]; + } + $access[$this->user] = $this->access; + $access = $new_access; } } else { $access = array( - $this->user + $this->user => $this->access ); } @@ -361,7 +373,7 @@ class Project extends Common { ////////////////////////////////////////////////////////////////// public function Create() { - + if ( $this->name != '' && $this->path != '' ) { $this->path = $this->cleanPath(); diff --git a/components/project/controller.php b/components/project/controller.php index 0af8186..21ea7cc 100755 --- a/components/project/controller.php +++ b/components/project/controller.php @@ -32,8 +32,15 @@ if( $_GET['action'] == 'add_user' ) { "undefined" ); - if( ! in_array( $_GET['username'], $invalid_users ) ) { + if( ! isset( $_GET['access'] ) || in_array( $_GET['access'], $invalid_users ) || ! in_array( $_GET['access'], array_keys( Permissions::LEVELS ) ) ) { + echo formatJSEND( "error", "No access set." ); + return; + } + + if( isset( $_GET['username'] ) && ! in_array( $_GET['username'], $invalid_users ) ) { + + $Project->access = $_GET['access']; $Project->user = $_GET['username']; } else { @@ -110,7 +117,7 @@ if( $_GET['action'] == 'current' ) { if( $_GET['action'] == 'delete' ) { - if( checkPath( $_GET['project_path'] ) ) { + if( isset( $_GET['project_path'] ) ) { $Project->path = $_GET['project_path']; $Project->Delete(); @@ -184,7 +191,7 @@ if( $_GET['action'] == 'get_owner' ) { if( $_GET['action'] == 'open' ) { - if( ! checkPath( $_GET['path'] ) ) { + if( isset( $_GET['path'] ) && ! Permissions::has_read( $_GET['path'] ) ) { die( formatJSEND( "error", "No Access to path " . $_GET['path'] ) ); } @@ -233,7 +240,7 @@ if( $_GET['action'] == 'remove_user' ) { if( $_GET['action'] == 'rename' ) { - if( ! checkPath( $_GET['project_path'] ) ) { + if( ! isset( $_GET['project_path'] ) || ! Permissions::has_owner( $_GET['project_path'] ) ) { die( formatJSEND( "error", "No Access" ) ); } diff --git a/components/project/dialog.php b/components/project/dialog.php index c71e75f..57b8df1 100755 --- a/components/project/dialog.php +++ b/components/project/dialog.php @@ -233,7 +233,19 @@ switch( $_GET['action'] ) { ?> $access_level ) { ?> @@ -241,6 +253,21 @@ switch( $_GET['action'] ) {

diff --git a/components/project/init.js b/components/project/init.js index 705e057..0504d36 100755 --- a/components/project/init.js +++ b/components/project/init.js @@ -53,26 +53,45 @@ add_user: function() { - var _this = this; + let _this = this; $( '#modal-content form' ).live( 'submit', function( e ) { e.preventDefault(); - username = $( '#modal-content form select[name="user_list"]' ).val(); - project_path = $( '#modal-content form input[name="project_path"]' ).val() + let username = $( '#modal-content form select[name="user_list"]' ).val(); + let project_path = $( '#modal-content form input[name="project_path"]' ).val(); - $.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&username=' + encodeURIComponent( username ), function( data ) { + $.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&username=' + encodeURIComponent( username ) + '&access=delete', function( data ) { - response = codiad.jsend.parse( data ); - console.log( response ); - if ( response != 'error' ) { - - codiad.project.manage_access( project_path ); - } + response = codiad.jsend.parse( data ); + console.log( response ); + if ( response != 'error' ) { + + codiad.project.manage_access( project_path ); + } }); }); }, + change_access: function( e ) { + + let _this = codiad.project; + let username = $( '#modal-content form select[name="user_list"]' ).val(); + let project_path = $( '#modal-content form input[name="project_path"]' ).val(); + let access = $( e.target ).children( "option:selected" ).val(); + + console.log( access, username, project_path ); + + $.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&username=' + encodeURIComponent( username ) + '&access=' + encodeURIComponent( access ), function( data ) { + + let response = codiad.jsend.parse( data ); + console.log( response ); + if ( response != 'error' ) { + + codiad.project.manage_access( project_path ); + } + }); + }, ////////////////////////////////////////////////////////////////// // Create Project From d3d96e66f6af862009ddb403466fe74d9c35bb43 Mon Sep 17 00:00:00 2001 From: xevidos Date: Mon, 1 Jul 2019 18:22:33 -0400 Subject: [PATCH 2/7] Started table conversion to new access system --- components/permissions/class.permissions.php | 26 +-- components/project/class.project.php | 33 ++- components/sql/class.sql.php | 201 ++++++++++++++----- components/system/controller.php | 2 + components/update/update.php | 1 + components/user/class.user.php | 9 +- 6 files changed, 188 insertions(+), 84 deletions(-) diff --git a/components/permissions/class.permissions.php b/components/permissions/class.permissions.php index 9e37c41..b3ce214 100644 --- a/components/permissions/class.permissions.php +++ b/components/permissions/class.permissions.php @@ -57,25 +57,19 @@ class Permissions { ), array( "limit", - 1 + 1 ) ) );*/ $query = "SELECT * FROM projects WHERE path=? LIMIT 1;"; $bind_variables = array( $_SESSION["project"] ); - $result = $sql->query( $query, $bind_variables, array() )[0]; + $result = $sql->query( $query, $bind_variables, array() ); if( ! empty( $result ) ) { $result = $result[0]; - try { - - $users = json_decode( $result["access"], true ); - } catch( exception $e ) { - - $users = array(); - } + $users = $sql->query( "SELECT * FOM access WHERE project = ? AND user = ? LIMIT 1", array( $result["id"], $_SESSION["user_id"] ), array() ); if( $result["owner"] == 'nobody' ) { @@ -83,7 +77,7 @@ class Permissions { } elseif( $result["owner"] == $_SESSION["user"] ) { $pass = true; - } elseif( in_array( $_SESSION["user"], array_keys( $users ) ) && ! empty( $users ) ) { + } elseif( ! empty( $users ) ) { //Only allow the owner to delete the root dir / project if( $path == $result["path"] && self::LEVELS[$level] == self::LEVELS["delete"] ) { @@ -91,18 +85,6 @@ class Permissions { $level = "owner"; } - $is_assoc = ( array_keys( $users ) !== range( 0, count( $users ) - 1 ) ); - - if( $is_assoc ) { - - $users_access = $users[$_SESSION["user"]]; - } else { - - $users_access = self::LEVELS["delete"]; - } - - echo var_dump( $path, $result, $users_access, $level, ( self::LEVELS[$level] >= $users_access ), self::LEVELS[$level] + " is more than or equal to {$users_access}" ); - if( self::LEVELS[$level] >= $users_access ) { $pass = true; diff --git a/components/project/class.project.php b/components/project/class.project.php index 3dfcd27..2a39f1d 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -201,8 +201,17 @@ class Project extends Common { $project = $this->path; } global $sql; - $query = "SELECT * FROM projects WHERE path=? AND ( owner=? OR owner='nobody' ) ORDER BY name;"; - $bind_variables = array( $project, $_SESSION["user"] ); + $query = " + SELECT * FROM projects + WHERE path = ? + AND ( + owner=? + OR owner='nobody' + OR id IN ( SELECT project FROM access WHERE user = ? ) + ) ORDER BY name;"; + $bind_variables = array( $project, $_SESSION["user"], $_SESSION["user_id"] ); + //$query = "SELECT * FROM projects WHERE path=? AND ( owner=? OR owner='nobody' ) ORDER BY name;"; + //$bind_variables = array( $project, $_SESSION["user"] ); $return = $sql->query( $query, $bind_variables, array() )[0]; if( ! empty( $return ) ) { @@ -218,8 +227,12 @@ class Project extends Common { public function get_projects() { global $sql; - $query = "SELECT * FROM projects WHERE owner=? OR owner='nobody' OR access LIKE ? ORDER BY name;"; - $bind_variables = array( $_SESSION["user"], '%"' . $_SESSION["user"] . '"%' ); + $query = " + SELECT * FROM projects + WHERE owner=? + OR owner='nobody' + OR path IN ( SELECT path FROM access WHERE user = ? );"; + $bind_variables = array( $_SESSION["user"], $_SESSION["user_id"] ); $return = $sql->query( $query, $bind_variables, array() ); if( empty( $return ) ) { @@ -349,8 +362,15 @@ class Project extends Common { public function Open() { global $sql; - $query = "SELECT * FROM projects WHERE path=? AND ( owner=? OR owner='nobody' OR access LIKE ? );"; - $bind_variables = array( $this->path, $_SESSION["user"], '%"' . $_SESSION["user"] . '"%' ); + $query = " + SELECT * FROM projects + WHERE path = ? + AND ( + owner=? + OR owner='nobody' + OR id IN ( SELECT project FROM access WHERE user = ? ) + ) ORDER BY name;"; + $bind_variables = array( $this->path, $_SESSION["user"], $_SESSION["user_id"] ); $return = $sql->query( $query, $bind_variables, array() )[0]; if( ! empty( $return ) ) { @@ -360,6 +380,7 @@ class Project extends Common { $sql->query( $query, $bind_variables, 0, "rowCount" ); $this->name = $return['name']; $_SESSION['project'] = $return['path']; + $_SESSION['project_id'] = $return['id']; echo formatJSEND( "success", array( "name" => $this->name, "path" => $this->path ) ); } else { diff --git a/components/sql/class.sql.php b/components/sql/class.sql.php index f2b6579..9121245 100755 --- a/components/sql/class.sql.php +++ b/components/sql/class.sql.php @@ -1,6 +1,7 @@ PDO::ERRMODE_EXCEPTION, + ); - $this->connection = new PDO( "{$dbtype}:host={$host};dbname={$dbname}", $username, $password ); + $this->connection = new PDO( "{$dbtype}:host={$host};dbname={$dbname}", $username, $password, $options ); } return( $this->connection ); @@ -65,6 +69,18 @@ class sql { "focused" => array( "not null" ), ) ), + "access" => array( + "fields" => array( + "project" => "int", + "user" => "int", + "level" => "int", + ), + "attributes" => array( + "id" => array( "not null" ), + "user" => array( "not null" ), + "level" => array( "not null" ), + ) + ), "options" => array( "fields" => array( "id" => "int", @@ -83,7 +99,6 @@ class sql { "name" => "string", "path" => "text", "owner" => "string", - "access" => "string", ), "attributes" => array( @@ -91,7 +106,6 @@ class sql { "name" => array( "not null" ), "path" => array( "not null", "unique" ), "owner" => array( "not null", "unique" ), - "access" => array(), ) ), "users" => array( @@ -102,7 +116,7 @@ class sql { "username" => "string", "password" => "text", "email" => "string", - "project" => "string", + "project" => "int", "access" => "string", "groups" => "string", "token" => "string", @@ -131,6 +145,85 @@ class sql { ) ); + if( $result === true ) { + + $sql_conversions = new sql_conversions(); + + try { + + $access_query = "INSERT INTO access( project, user, level ) VALUES "; + $projects = $this->query( "SELECT id, access FROM projects", array(), array(), "fetchAll", "exception" ); + $users = $this->query( "SELECT id, username FROM users", array(), array(), "fetchAll", "exception" ); + $delete = Permissions::LEVELS["delete"]; + + foreach( $users as $row => $user ) { + + foreach( $projects as $row => $project ) { + + $access = json_decode( $project["access"], true ); + if( ! is_array( $access ) || empty( $access ) ) { + + continue; + } + + foreach( $access as $granted_user ) { + + if( $granted_user == $user["username"] ) { + + $access_query .= "( {$project["id"]}, {$user["id"]}, $delete ),"; + } + } + } + } + + if( $access_query !== "INSERT INTO access( project, user, level ) " ) { + + $result = $this->query( substr( $access_query, 0, -1 ), array(), 0, "rowCount", "exception" ); + } + $result = $this->query( "ALTER TABLE projects DROP COLUMN access", array(), 0, "rowCount" ); + } catch( Exception $error ) { + + //The access field is not there. + //echo var_export( $error->getMessage(), $access_query ); + } + + try { + + $update_query = ""; + $projects = $this->query( "SELECT id, path FROM projects", array(), array(), "fetchAll", "exception" ); + $result = $this->query( "SELECT project FROM users", array(), array(), "fetchAll", "exception" ); + $convert = false; + $delete = Permissions::LEVELS["delete"]; + + foreach( $result as $row => $user ) { + + if( ! is_numeric( $user["project"] ) ) { + + $convert = true; + } + + foreach( $projects as $row => $project ) { + + if( $project["path"] == $user["project"] ) { + + $update_query .= "UPDATE users SET project={$project["id"]};"; + } + } + } + + if( $convert ) { + + //change project to users table + $result = $this->query( "ALTER TABLE users DROP COLUMN project", array(), array(), "rowCount", "exception" ); + $result = $this->query( "ALTER TABLE users ADD COLUMN project " . $sql_conversions->data_types["int"][DBTYPE], array(), array(), "rowCount", "exception" ); + $result = $this->query( $update_query, array(), array(), "rowCount", "exception" ); + } + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + } + return $result; } @@ -169,18 +262,15 @@ class sql { ); */ - $query = $this->conversions->tables( $table ); - $connection = $this->connect(); - $result = $connection->exec( $query ); - $error = $connection->errorInfo(); - //echo var_dump( $query, $result, $connection->errorInfo() ) . "
"; - - if ( $result === false || ! $error[0] == "00000" ) { - - return $error; - } else { + try { + $query = $this->conversions->tables( $table ); + $connection = $this->connect(); + $result = $connection->exec( $query ); return true; + } catch( exception $error ) { + + return $error->getMessage(); } } @@ -227,53 +317,58 @@ class sql { $query = $this->conversions->update( $table, $fields, $where ); //echo var_dump( $query ) . "
"; + //return $query; } - public function query( $query, $bind_variables, $default, $action='fetchAll', $show_errors=false ) { + public function query( $query, $bind_variables, $default, $action='fetchAll', $errors="default" ) { - $connection = $this->connect(); - $statement = $connection->prepare( $query ); - $statement->execute( $bind_variables ); - - switch( $action ) { - - case( 'rowCount' ): - - $return = $statement->rowCount(); - break; - - case( 'fetchAll' ): - - $return = $statement->fetchAll( \PDO::FETCH_ASSOC ); - break; - - case( 'fetchColumn' ): - - $return = $statement->fetchColumn(); - break; - - default: - - $return = $statement->fetchAll( \PDO::FETCH_ASSOC ); - break; - } + /** + * Errors: + * default - this value could be anything such as true or foobar + * message + * exception + */ - $error = $statement->errorInfo(); - - if( ! $error[0] == "00000" ) { + try { + + $connection = $this->connect(); + $statement = $connection->prepare( $query ); + $statement->execute( $bind_variables ); + + switch( $action ) { + + case( 'rowCount' ): + + $return = $statement->rowCount(); + break; + + case( 'fetchAll' ): + + $return = $statement->fetchAll( \PDO::FETCH_ASSOC ); + break; + + case( 'fetchColumn' ): + + $return = $statement->fetchColumn(); + break; + + default: + + $return = $statement->fetchAll( \PDO::FETCH_ASSOC ); + break; + } + } catch( exception $error ) { - echo var_export( $error ); - echo var_export( $return ); $return = $default; - } - - if( $show_errors ) { - $return = json_encode( $error ); + if( $errors == "message" ) { + + $return = json_encode( array( $error->getMessage() ) ); + } elseif( $errors == "exception" ) { + + throw $error; + } } - - //echo var_dump( $error, $return ); - $this->close(); return( $return ); } diff --git a/components/system/controller.php b/components/system/controller.php index c1ffdac..4a17882 100644 --- a/components/system/controller.php +++ b/components/system/controller.php @@ -19,6 +19,8 @@ if ( $_POST['action'] == 'create_default_tables' ) { global $sql; $result = $sql->create_default_tables(); + echo var_dump( $result ); + if( $result === true ) { exit( formatJSEND( "success", "Created tables." ) ); diff --git a/components/update/update.php b/components/update/update.php index 0ad8fd5..207fab8 100755 --- a/components/update/update.php +++ b/components/update/update.php @@ -15,6 +15,7 @@ $projects_file = BASE_PATH . "/data/projects.php"; $users_file = BASE_PATH . "/data/users.php"; //checkSession(); if ( ! checkAccess() ) { + echo "Error, you do not have access to update Codiad."; exit(); } diff --git a/components/user/class.user.php b/components/user/class.user.php index 78d2586..cc9db4e 100755 --- a/components/user/class.user.php +++ b/components/user/class.user.php @@ -243,23 +243,26 @@ class User { if( ! empty( $return ) ) { + $user = $return[0]; $pass = true; $token = mb_strtoupper( strval( bin2hex( openssl_random_pseudo_bytes( 16 ) ) ) ); $_SESSION['id'] = SESSION_ID; $_SESSION['user'] = $this->username; + $_SESSION['user_id'] = $user["id"]; $_SESSION['token'] = $token; $_SESSION['lang'] = $this->lang; $_SESSION['theme'] = $this->theme; $_SESSION["login_session"] = true; - $user = $return[0]; $query = "UPDATE users SET token=? WHERE username=?;"; $bind_variables = array( sha1( $token ), $this->username ); $return = $sql->query( $query, $bind_variables, 0, 'rowCount' ); + $projects = $sql->query( "SELECT path FROM projects WHERE id = ?", array( $user["project"] ), array(), 'rowCount' ); - if( isset( $user['project'] ) && $user['project'] != '' ) { + if( isset( $user['project'] ) && $user['project'] != '' && ! empty( $projects ) ) { - $_SESSION['project'] = $user['project']; + $_SESSION['project'] = $projects[0]["path"]; + $_SESSION['project_id'] = $user['project']; } $this->checkDuplicateSessions( $this->username ); From 492e372c5d20dae05053d0558b7e415d02e16e7b Mon Sep 17 00:00:00 2001 From: xevidos Date: Tue, 2 Jul 2019 16:46:32 -0400 Subject: [PATCH 3/7] Continued work on new permissions system, Fixed active file listings bug --- common.php | 54 +++--- components/active/class.active.php | 41 ++--- components/active/controller.php | 175 ++++++++++--------- components/active/init.js | 11 +- components/editor/init.js | 11 +- components/filemanager/class.filemanager.php | 95 +++++----- components/filemanager/controller.php | 7 +- components/filemanager/init.js | 36 ++-- components/permissions/class.permissions.php | 144 +++++++++------ components/project/class.project.php | 145 ++++++--------- components/project/controller.php | 28 +-- components/project/dialog.php | 39 +++-- components/project/init.js | 55 +++--- components/sql/class.sql.php | 5 + 14 files changed, 447 insertions(+), 399 deletions(-) diff --git a/common.php b/common.php index f4aab00..1e6270b 100755 --- a/common.php +++ b/common.php @@ -157,10 +157,25 @@ class Common { self::return( $return, $action ); } + public static function get_user_id( $username ) { + + global $sql; + $user_id = false; + $query = "SELECT id FROM users WHERE username = ? LIMIT 1;"; + $bind_variables = array( $username ); + $return = $sql->query( $query, $bind_variables, array(), "fetch" ); + + if( ! empty( $return ) ) { + + $user_id = $return["id"]; + } + return $user_id; + } + public static function get_users( $return = "return", $exclude_current = false ) { global $sql; - $query = "SELECT username FROM users"; + $query = "SELECT * FROM users"; $bind = ""; $bind_variables = array(); @@ -172,25 +187,19 @@ class Common { } $result = $sql->query( $query, $bind_variables, formatJSEND( "error", "Error checking users." ) ); - $user_list = array(); - - foreach( $result as $row ) { - - array_push( $user_list, $row["username"] ); - } - + if( ! empty( $result ) ) { switch( $return ) { case( "json" ): - $return = json_encode( $user_list ); + $return = json_encode( $result ); break; case( "return" ): - $return = $user_list; + $return = $result; break; } } else { @@ -615,19 +624,20 @@ class Common { // Wrapper for old method names ////////////////////////////////////////////////////////////////// -function is_admin() { return Common::is_admin(); } -function debug($message) { Common::debug($message); } -function i18n($key, $args = array()) { echo Common::i18n($key, $args); } -function get_i18n($key, $args = array()) { return Common::get_i18n($key, $args); } -function checkSession(){ Common::checkSession(); } -function getJSON($file,$namespace=""){ return Common::getJSON($file,$namespace); } -function saveJSON($file,$data,$namespace=""){ Common::saveJSON($file,$data,$namespace); } -function formatJSEND($status,$data=false){ return Common::formatJSEND($status,$data); } function checkAccess() { return Common::checkAccess(); } -function checkPath($path) { return Common::checkPath($path); } -function isAvailable($func) { return Common::isAvailable($func); } -function logout() { return Common::logout(); } +function checkPath( $path ) { return Common::checkPath($path); } +function checkSession() { Common::checkSession(); } +function debug( $message ) { Common::debug( $message ); } +function formatJSEND( $status, $data=false ){ return Common::formatJSEND($status,$data); } +function get_i18n( $key, $args = array() ) { return Common::get_i18n($key, $args); } +function get_user_id( $username ) { return Common::get_user_id( $username ); } function get_users( $return = "return", $exclude_current = false ) { return Common::get_users( $return, $exclude_current ); } -function search_users( $username, $return = "return", $exclude_current = false ) { return Common::search_users( $username, $return, $exclude_current ); } function get_version() { return Common::get_version(); } +function getJSON( $file,$namespace=""){ return Common::getJSON( $file, $namespace ); } +function i18n( $key, $args = array() ) { echo Common::i18n( $key, $args ); } +function is_admin() { return Common::is_admin(); } +function isAvailable( $func ) { return Common::isAvailable( $func ); } +function logout() { return Common::logout(); } +function saveJSON( $file, $data, $namespace="" ){ Common::saveJSON( $file, $data, $namespace ); } +function search_users( $username, $return = "return", $exclude_current = false ) { return Common::search_users( $username, $return, $exclude_current ); } ?> diff --git a/components/active/class.active.php b/components/active/class.active.php index d3e0204..dac9313 100755 --- a/components/active/class.active.php +++ b/components/active/class.active.php @@ -31,6 +31,14 @@ class Active extends Common { public function __construct() { } + public static function remove( $path ) { + + global $sql; + $query = "DELETE FROM active WHERE path=? AND username=?;"; + $bind_variables = array( $path, $_SESSION["user"] ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + } + ////////////////////////////////////////////////////////////////// // List User's Active Files ////////////////////////////////////////////////////////////////// @@ -38,14 +46,14 @@ class Active extends Common { public function ListActive() { global $sql; - $query = "SELECT path,position,focused FROM active WHERE username=?"; + $query = "SELECT path, position, focused FROM active WHERE username=?"; $bind_variables = array( $this->username ); $result = $sql->query( $query, $bind_variables, array() ); $tainted = false; $root = WORKSPACE; $active_list = $result; - if( ! empty( $return ) ) { + if( ! empty( $result ) ) { foreach ( $result as $id => $data ) { @@ -57,20 +65,14 @@ class Active extends Common { $root = $root.'/'; } - if ( ! file_exists( $root . $data['path'] ) ) { + if ( ! is_file( $root . $data['path'] ) ) { - $tainted = true; + self::remove( $data['path'] ); unset( $active_list[$id] ); } } } - - if( $tainted ) { - - $this->update_active( $active_list ); - } - - echo formatJSEND( "success", $active_list ); + exit( formatJSEND( "success", $active_list ) ); } ////////////////////////////////////////////////////////////////// @@ -140,23 +142,6 @@ class Active extends Common { } } - ////////////////////////////////////////////////////////////////// - // Remove File - ////////////////////////////////////////////////////////////////// - - public function Remove() { - - global $sql; - $query = "DELETE FROM active WHERE path=? AND username=?;"; - $bind_variables = array( $this->path, $this->username ); - $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); - - if( $return > 0 ) { - - echo formatJSEND( "success" ); - } - } - ////////////////////////////////////////////////////////////////// // Remove All Files ////////////////////////////////////////////////////////////////// diff --git a/components/active/controller.php b/components/active/controller.php index a5fa7ac..0d1f9ff 100755 --- a/components/active/controller.php +++ b/components/active/controller.php @@ -1,94 +1,101 @@ username = $_SESSION['user']; - $Active->ListActive(); -} - - ////////////////////////////////////////////////////////////////// - // Add active record - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='add') { - $Active->username = $_SESSION['user']; - $Active->path = $_GET['path']; - $Active->Add(); -} - - ////////////////////////////////////////////////////////////////// - // Rename - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='rename') { - $Active->username = $_SESSION['user']; - $Active->path = $_GET['old_path']; - $Active->new_path = $_GET['new_path']; - $Active->Rename(); -} - - ////////////////////////////////////////////////////////////////// - // Check if file is active - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='check') { - $Active->username = $_SESSION['user']; - $Active->path = $_GET['path']; - $Active->Check(); -} - - ////////////////////////////////////////////////////////////////// - // Remove active record - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='remove') { - $Active->username = $_SESSION['user']; - $Active->path = $_GET['path']; - $Active->Remove(); -} - - ////////////////////////////////////////////////////////////////// - // Remove all active record - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='removeall') { - $Active->username = $_SESSION['user']; - $Active->RemoveAll(); -} - - ////////////////////////////////////////////////////////////////// - // Mark file as focused - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='focused') { - $Active->username = $_SESSION['user']; - $Active->path = $_GET['path']; - $Active->MarkFileAsFocused(); -} - -if ($_GET['action']=='save_positions') { +if( $_GET['action'] == 'list' ) { - ignore_user_abort( true ); - $Active->username = $_SESSION['user']; - $Active->savePositions( $_POST["positions"] ); + $Active->username = $_SESSION['user']; + $Active->ListActive(); +} + +////////////////////////////////////////////////////////////////// +// Add active record +////////////////////////////////////////////////////////////////// + +if ( $_GET['action'] == 'add' ) { + + $Active->username = $_SESSION['user']; + $Active->path = $_GET['path']; + $Active->Add(); +} + +////////////////////////////////////////////////////////////////// +// Rename +////////////////////////////////////////////////////////////////// + +if ( $_GET['action'] == 'rename' ) { + + $Active->username = $_SESSION['user']; + $Active->path = $_GET['old_path']; + $Active->new_path = $_GET['new_path']; + $Active->Rename(); +} + +////////////////////////////////////////////////////////////////// +// Check if file is active +////////////////////////////////////////////////////////////////// + +if ( $_GET['action'] == 'check' ) { + + $Active->username = $_SESSION['user']; + $Active->path = $_GET['path']; + $Active->Check(); +} + +////////////////////////////////////////////////////////////////// +// Remove active record +////////////////////////////////////////////////////////////////// + +if ( $_GET['action'] == 'remove' ) { + + $Active->username = $_SESSION['user']; + $Active->path = $_GET['path']; + $Active->remove( $Active->path ); +} + +////////////////////////////////////////////////////////////////// +// Remove all active record +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'removeall' ) { + + $Active->username = $_SESSION['user']; + $Active->RemoveAll(); +} + +////////////////////////////////////////////////////////////////// +// Mark file as focused +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'focused' ) { + + $Active->username = $_SESSION['user']; + $Active->path = $_GET['path']; + $Active->MarkFileAsFocused(); +} + +if( $_GET['action'] == 'save_positions' ) { + + ignore_user_abort( true ); + $Active->username = $_SESSION['user']; + $Active->savePositions( $_POST["positions"] ); } diff --git a/components/active/init.js b/components/active/init.js index 1c5a035..a51a404 100755 --- a/components/active/init.js +++ b/components/active/init.js @@ -51,12 +51,8 @@ return !!this.sessions[path]; }, - open: function( path, content, mtime, inBackground, focus ) { + open: function( path, content, mtime, inBackground, focus, read_only=false ) { - //if( this. ) { - - - //} /* Notify listeners. */ amplify.publish( 'active.onFileWillOpen', { path: path, @@ -64,12 +60,14 @@ }); if( focus === undefined ) { + focus = true; } var _this = this; if( this.isOpen( path ) ) { + if( focus ) this.focus( path ); return; } @@ -98,6 +96,8 @@ session.serverMTime = mtime; _this.sessions[path] = session; session.untainted = content.slice( 0 ); + session.read_only = read_only; + if( !inBackground && focus ) { codiad.editor.setSession( session ); } @@ -275,6 +275,7 @@ // Open saved-state active files on load $.get( _this.controller + '?action=list', function( data ) { + console.log( data ); var listResponse = codiad.jsend.parse( data ); if( listResponse !== null ) { $.each( listResponse, function( index, data ) { diff --git a/components/editor/init.js b/components/editor/init.js index ba78c8b..d5d6e01 100755 --- a/components/editor/init.js +++ b/components/editor/init.js @@ -390,11 +390,16 @@ this.setTabSize( this.settings.tabSize, i ); this.setSoftTabs( this.settings.softTabs, i ); this.setOverScroll( this.settings.overScroll, i ); - i.setOptions( { + i.setOptions({ enableBasicAutocompletion: true, enableSnippets: true, enableLiveAutocompletion: this.settings.autocomplete }); + + if( i.getSession().read_only ) { + + i.setReadOnly( true ); + } }, ////////////////////////////////////////////////////////////////// @@ -718,11 +723,15 @@ ///////////////////////////////////////////////////////////////// setSession: function( session, i ) { + i = i || this.getActive(); if( !this.isOpen( session ) ) { + if( !i ) { + i = this.addInstance( session ); } else { + i.setSession( session ); } } else { diff --git a/components/filemanager/class.filemanager.php b/components/filemanager/class.filemanager.php index 5e9fc87..8ff5239 100755 --- a/components/filemanager/class.filemanager.php +++ b/components/filemanager/class.filemanager.php @@ -15,6 +15,7 @@ class Filemanager extends Common { // PROPERTIES ////////////////////////////////////////////////////////////////// + public $access = 0; public $root = ""; public $project = ""; public $rel_path = ""; @@ -351,8 +352,8 @@ class Filemanager extends Common { if ( is_file( $this->path ) ) { - $output = file_get_contents($this->path); - + $output = file_get_contents( $this->path ); + if ( extension_loaded( 'mbstring' ) ) { if ( ! mb_check_encoding( $output, 'UTF-8' ) ) { @@ -371,6 +372,8 @@ class Filemanager extends Common { $this->data = '"content":' . json_encode( $output ); $mtime = filemtime( $this->path ); $this->data .= ', "mtime":'.$mtime; + $this->data .= ', "access":'. $this->access; + $this->data .= ', "read_only":'. ( Permissions::check_access( "read", $this->access ) && ! Permissions::check_access( "write", $this->access ) ); } else { $this->status = "error"; @@ -562,60 +565,66 @@ class Filemanager extends Common { $this->respond(); return; } - echo var_dump( Permissions::has_write( $this->path ) ); - if ( is_file( $this->path ) && Permissions::has_write( $this->path ) ) { + + if ( is_file( $this->path ) ) { - $serverMTime = filemtime( $this->path ); - $fileContents = file_get_contents( $this->path ); - - if ( $this->patch && $this->mtime != $serverMTime ) { + if( Permissions::has_write( $this->path ) ) { - $this->status = "error"; - $this->message = "Client is out of sync"; - //DEBUG : file_put_contents($this->path.".conflict", "SERVER MTIME :".$serverMTime.", CLIENT MTIME :".$this->mtime); - $this->respond(); - return; - } elseif ( strlen( trim( $this->patch ) ) == 0 && ! $this->content ) { + $serverMTime = filemtime( $this->path ); + $fileContents = file_get_contents( $this->path ); - // Do nothing if the patch is empty and there is no content - $this->status = "success"; - $this->data = '"mtime":' . $serverMTime; - $this->respond(); - return; - } - - if ( $file = fopen( $this->path, 'w' ) ) { - - if ( $this->patch ) { - - $dmp = new diff_match_patch(); - $p = $dmp->patch_apply( $dmp->patch_fromText( $this->patch ), $fileContents ); - $this->content = $p[0]; - //DEBUG : file_put_contents($this->path.".orig",$fileContents ); - //DEBUG : file_put_contents($this->path.".patch", $this->patch); - } - - if ( fwrite( $file, $this->content ) === false ) { + if ( $this->patch && $this->mtime != $serverMTime ) { $this->status = "error"; - $this->message = "could not write to file"; - } else { + $this->message = "Client is out of sync"; + //DEBUG : file_put_contents($this->path.".conflict", "SERVER MTIME :".$serverMTime.", CLIENT MTIME :".$this->mtime); + $this->respond(); + return; + } elseif ( strlen( trim( $this->patch ) ) == 0 && ! $this->content ) { - // Unless stat cache is cleared the pre-cached mtime will be - // returned instead of new modification time after editing - // the file. - clearstatcache(); - $this->data = '"mtime":'.filemtime( $this->path ); + // Do nothing if the patch is empty and there is no content $this->status = "success"; + $this->data = '"mtime":' . $serverMTime; + $this->respond(); + return; } - fclose( $file ); + if ( $file = fopen( $this->path, 'w' ) ) { + + if ( $this->patch ) { + + $dmp = new diff_match_patch(); + $p = $dmp->patch_apply( $dmp->patch_fromText( $this->patch ), $fileContents ); + $this->content = $p[0]; + //DEBUG : file_put_contents($this->path.".orig",$fileContents ); + //DEBUG : file_put_contents($this->path.".patch", $this->patch); + } + + if ( fwrite( $file, $this->content ) === false ) { + + $this->status = "error"; + $this->message = "could not write to file"; + } else { + + // Unless stat cache is cleared the pre-cached mtime will be + // returned instead of new modification time after editing + // the file. + clearstatcache(); + $this->data = '"mtime":'.filemtime( $this->path ); + $this->status = "success"; + } + + fclose( $file ); + } else { + + $this->status = "error"; + $this->message = "Cannot Write to File"; + } } else { $this->status = "error"; - $this->message = "Cannot Write to File"; + $this->message = "Write access is denied."; } - } else { $this->status = "error"; diff --git a/components/filemanager/controller.php b/components/filemanager/controller.php index 61b9304..c474655 100755 --- a/components/filemanager/controller.php +++ b/components/filemanager/controller.php @@ -39,9 +39,11 @@ if (!isset($_SESSION['project'])) { // Security Check ////////////////////////////////////////////////////////////////// -if ( ! Permissions::has_read( $_GET['path'] ) ) { +$access = Permissions::get_access( $_GET['path'] ); + +if ( ! Permissions::check_access( "read", $access ) ) { - die('{"status":"error","message":"Invalid Path"}'); + die( '{"status":"error","message":"Invalid access to ' . $_GET['path'] . '."}' ); } ////////////////////////////////////////////////////////////////// @@ -56,6 +58,7 @@ if ( ! Permissions::has_read( $_GET['path'] ) ) { $Filemanager = new Filemanager($_GET, $_POST, $_FILES); $Filemanager->project = @$_SESSION['project']['path']; + $Filemanager->access = $access; switch ($action) { case 'index': diff --git a/components/filemanager/init.js b/components/filemanager/init.js index ef867a6..a380476 100755 --- a/components/filemanager/init.js +++ b/components/filemanager/init.js @@ -459,35 +459,41 @@ // Open File ////////////////////////////////////////////////////////////////// - openFile: function( path, focus ) { + openFile: function( path, focus=true ) { /* Notify listeners. */ amplify.publish( 'filemanager.onFileWillOpen', { path: path }); - if( focus === undefined ) { - focus = true; - } var node = $( '#file-manager a[data-path="' + path + '"]' ); var ext = this.getExtension( path ); + if( $.inArray( ext.toLowerCase(), this.noOpen ) < 0 ) { + node.addClass( 'loading' ); $.get( this.controller + '?action=open&path=' + encodeURIComponent( path ), function( data ) { + var openResponse = codiad.jsend.parse( data ); if( openResponse != 'error' ) { + node.removeClass( 'loading' ); - codiad.active.open( path, openResponse.content, openResponse.mtime, false, focus ); + codiad.active.open( path, openResponse.content, openResponse.mtime, false, focus, openResponse.read_only ); } }); } else { - if( !codiad.project.isAbsPath( path ) ) { + + if( ! codiad.project.isAbsPath( path ) ) { + if( $.inArray( ext.toLowerCase(), this.noBrowser ) < 0 ) { + this.download( path ); } else { + this.openInModal( path ); } } else { + codiad.message.error( i18n( 'Unable to open file in Browser while using absolute path.' ) ); } } @@ -583,21 +589,26 @@ path: path }); }, - saveModifications: function( path, data, callbacks, save = true ) { + saveModifications: function( path, data, callbacks, messages = true ) { callbacks = callbacks || {}; let _this = this, action; var notifySaveErr = function() { + codiad.message.error( i18n( 'File could not be saved' ) ); if( typeof callbacks.error === 'function' ) { + var context = callbacks.context || _this; callbacks.error.apply( context, [data] ); } } + $.post( this.controller + '?action=modify&path=' + encodeURIComponent( path ), data, function( resp ) { + + console.log( resp ); resp = $.parseJSON( resp ); if( resp.status == 'success' ) { - if( save === true ) { + if( messages === true ) { codiad.message.success( i18n( 'File saved' ) ); } if( typeof callbacks.success === 'function' ) { @@ -621,8 +632,11 @@ session.serverMTime = null; session.untainted = null; } - } else codiad.message.error( i18n( 'File could not be saved' ) ); + //} else codiad.message.error( i18n( 'File could not be saved' ) ); + } else codiad.message.error( i18n( resp.message ) ); + if( typeof callbacks.error === 'function' ) { + var context = callbacks.context || _this; callbacks.error.apply( context, [resp.data] ); } @@ -633,10 +647,10 @@ // Save file ////////////////////////////////////////////////////////////////// - saveFile: function( path, content, callbacks, save = true ) { + saveFile: function( path, content, callbacks, messages = true ) { this.saveModifications( path, { content: content - }, callbacks, save ); + }, callbacks, messages ); }, savePatch: function( path, patch, mtime, callbacks, alerts ) { diff --git a/components/permissions/class.permissions.php b/components/permissions/class.permissions.php index b3ce214..a4fa5c6 100644 --- a/components/permissions/class.permissions.php +++ b/components/permissions/class.permissions.php @@ -5,17 +5,22 @@ * [root]/license.txt for more. This information must remain intact. */ +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + class Permissions { const LEVELS = array( - "admin" => 0, - "owner" => 1, - "manager" => 2, - "delete" => 3, + "none" => 0, + "read" => 1, + "write" => 2, "create" => 4, - "write" => 5, - "read" => 6, + "delete" => 8, + "manager" => 16, + "owner" => 32, + "admin" => 64, ); function __construct() { @@ -23,75 +28,106 @@ class Permissions { } - public static function check_path( $level, $path ) { + public static function check_access( $level, $user_level ) { - $project_path = $_SESSION["project"]; - $project_path = rtrim( $project_path, '/' ) . '/'; + if( ! is_integer( $level ) ) { + + if( in_array( $level, array_keys( self::LEVELS ) ) ) { + + $level = self::LEVELS[$level]; + } else { + + exit( formatJSEND( "error", "Access Level does not exist." ) ); + } + } + + return ( $user_level >= $level ); + } + + public static function check_path( $level, $path ) { if( ! in_array( $level, array_keys( self::LEVELS ) ) ) { - exit( Common::formatJSEND( "error", "Access Level does not exist." ) ); + exit( formatJSEND( "error", "Access Level does not exist." ) ); } - if( strpos( $path, $project_path ) === 0 ) { + $pass = false; + $user_level = self::get_access( $path ); + + if( $user_level >= self::LEVELS[$level] ) { - exit( Common::formatJSEND( "error", "Error with path." ) ); + $pass = true; } + return( $pass ); + } + + public static function get_access( $path ) { global $sql; - $pass = false; - //$query = "SELECT * FROM projects WHERE LOCATE( path, ? ) > 0 LIMIT 1;"; - //$bind_variables = array( $path ); - //$result = $sql->query( $query, $bind_variables, array() )[0]; - /*$result = $sql->select( - "projects", - array(), - array( - array( - "find", - $path, - array( - "more than", - 0 - ) - ), - array( - "limit", - 1 - ) - ) - );*/ + $full_path = Common::isAbsPath( $path ) ? $path : WORKSPACE . "/{$path}"; + $access = 0; + //$query = "SELECT id, path, owner FROM projects WHERE path LIKE ?;"; + //$bind_variables = array( "{$path}%" ); + $query = "SELECT id, path, owner FROM projects;"; + $bind_variables = array(); + $projects = $sql->query( $query, $bind_variables, array() ); - $query = "SELECT * FROM projects WHERE path=? LIMIT 1;"; - $bind_variables = array( $_SESSION["project"] ); - $result = $sql->query( $query, $bind_variables, array() ); - - if( ! empty( $result ) ) { + if( ! empty( $projects ) ) { - $result = $result[0]; - $users = $sql->query( "SELECT * FOM access WHERE project = ? AND user = ? LIMIT 1", array( $result["id"], $_SESSION["user_id"] ), array() ); - - if( $result["owner"] == 'nobody' ) { + foreach( $projects as $row => $data ) { - $pass = true; - } elseif( $result["owner"] == $_SESSION["user"] ) { + $full_project_path = Common::isAbsPath( $data["path"] ) ? $data["path"] : WORKSPACE . "/{$data["path"]}"; + $path_postition = strpos( $full_path, $full_project_path ); - $pass = true; - } elseif( ! empty( $users ) ) { - - //Only allow the owner to delete the root dir / project - if( $path == $result["path"] && self::LEVELS[$level] == self::LEVELS["delete"] ) { + if( $path_postition === false ) { - $level = "owner"; + continue; } - if( self::LEVELS[$level] >= $users_access ) { + if( $data["owner"] == 'nobody' ) { - $pass = true; + $access = self::LEVELS["owner"]; + } elseif( $data["owner"] == $_SESSION["user"] ) { + + $access = self::LEVELS["owner"]; + } else { + + $user = $sql->query( "SELECT * FROM access WHERE project = ? AND user = ? LIMIT 1", array( $data["id"], $_SESSION["user_id"] ), array(), "fetch" ); + + if( ! empty( $user ) ) { + + $access = $user["level"]; + } + } + + //echo var_dump( $full_path, $full_project_path, $path_postition, $user["level"], $pass ); + if( $access > 0 ) { + + break; } } } - return( $pass ); + return $access; + } + + public static function get_level( $i ) { + + $level = 0; + if( is_integer( $i ) ) { + + $level = array_search( $i, self::LEVELS ); + } else { + + if( in_array( $i, array_keys( self::LEVELS ) ) ) { + + $level = self::LEVELS[$i]; + } else { + + exit( formatJSEND( "error", "Access Level does not exist." ) ); + } + } + + return $level; } public static function has_owner( $path ) { diff --git a/components/project/class.project.php b/components/project/class.project.php index 2a39f1d..df1b538 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -14,7 +14,7 @@ class Project extends Common { // PROPERTIES ////////////////////////////////////////////////////////////////// - public $access = 100; + public $access = Permissions::LEVELS["read"]; public $name = ''; public $path = ''; public $gitrepo = false; @@ -68,53 +68,50 @@ class Project extends Common { public function add_user() { global $sql; - $query = "SELECT access FROM projects WHERE path=? AND owner=?"; + $query = "SELECT * FROM projects WHERE path=? AND owner=? LIMIT 1"; $bind_variables = array( $this->path, $_SESSION["user"] ); - $result = $sql->query( $query, $bind_variables, array() )[0]; + $project = $sql->query( $query, $bind_variables, array(), "fetch" ); - if( ! empty( $result ) ) { + if( empty( $project ) ) { - $access = json_decode( $result["access"] ); + exit( formatJSEND( "error", "Error fetching projects." ) ); + } + + $user_id = get_user_id( $this->user ); + + if( $user_id === false ) { - if( is_array( $access ) && ! empty( $access ) ) { - - $is_assoc = ( array_keys( $access ) !== range( 0, count( $access ) - 1 ) ); - - if( $is_assoc ) { - - $access[$this->user] = $this->access; - } else { - - $new_access = array(); - foreach( $access as $user ) { - - $new_access[$user] = Permission::LEVELS["delete"]; - } - $access[$this->user] = $this->access; - $access = $new_access; - } - } else { - - $access = array( - $this->user => $this->access - ); - } + exit( formatJSEND( "error", "Error fetching user information." ) ); + } + + $user = $sql->query( "SELECT * FROM access WHERE project = ? AND user = ?", array( $project["id"], $user_id ), array(), "fetch" ); + + if( ! empty( $user ) ) { - $access = json_encode( $access ); - $query = "UPDATE projects SET access=? WHERE path=? AND owner=?;"; - $bind_variables = array( $access, $this->path, $_SESSION["user"] ); - $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + $query = "UPDATE access SET level=? WHERE project=? AND user=?;"; + $bind_variables = array( $this->access, $project["id"], $user_id ); + $result = $sql->query( $query, $bind_variables, 0, "rowCount" ); if( $result > 0 ) { - - echo( formatJSEND( "success", "Successfully added {$this->user}." ) ); + + echo formatJSEND( "success", "Successfully updated {$this->user}." ); } else { echo formatJSEND( "error", "Error setting access for project." ); } } else { - echo formatJSEND( "error", "Error fetching projects." ); + $query = "INSERT INTO access ( project, user, level ) VALUES ( ?,?,? );"; + $bind_variables = array( $project["id"], $user_id, $this->access ); + $result = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $result > 0 ) { + + echo formatJSEND( "success", "Successfully added {$this->user}." ); + } else { + + echo formatJSEND( "error", "Error setting access for project." ); + } } } @@ -127,7 +124,7 @@ class Project extends Common { global $sql; $query = "SELECT owner FROM projects WHERE path=?"; $bind_variables = array( $path ); - $result = $sql->query( $query, $bind_variables, array() )[0]; + $result = $sql->query( $query, $bind_variables, array(), "fetch" ); $return = false; if( ! empty( $result ) ) { @@ -150,25 +147,12 @@ class Project extends Common { return( $return ); } - public function get_access( $path = null ) { + public function get_access( $project_id = null ) { - if( $path === null ) { - - $path = $this->path; - } global $sql; - $query = "SELECT access FROM projects WHERE path=?"; - $bind_variables = array( $path ); - $return = $sql->query( $query, $bind_variables, array() )[0]; - - if( ! empty( $return ) ) { - - $return = $return["access"]; - } else { - - $return = formatJSEND( "error", "Error fetching project info." ); - } - + $query = "SELECT * FROM access WHERE project=?"; + $bind_variables = array( $project_id ); + $return = $sql->query( $query, $bind_variables, array() ); return( $return ); } @@ -181,7 +165,7 @@ class Project extends Common { global $sql; $query = "SELECT owner FROM projects WHERE path=?"; $bind_variables = array( $path ); - $return = $sql->query( $query, $bind_variables, array() )[0]; + $return = $sql->query( $query, $bind_variables, array(), "fetch" ); if( ! empty( $return ) ) { @@ -200,10 +184,11 @@ class Project extends Common { $project = $this->path; } + global $sql; $query = " SELECT * FROM projects - WHERE path = ? + WHERE path = ? AND ( owner=? OR owner='nobody' @@ -212,7 +197,7 @@ class Project extends Common { $bind_variables = array( $project, $_SESSION["user"], $_SESSION["user_id"] ); //$query = "SELECT * FROM projects WHERE path=? AND ( owner=? OR owner='nobody' ) ORDER BY name;"; //$bind_variables = array( $project, $_SESSION["user"] ); - $return = $sql->query( $query, $bind_variables, array() )[0]; + $return = $sql->query( $query, $bind_variables, array(), "fetch" ); if( ! empty( $return ) ) { @@ -231,7 +216,7 @@ class Project extends Common { SELECT * FROM projects WHERE owner=? OR owner='nobody' - OR path IN ( SELECT path FROM access WHERE user = ? );"; + OR id IN ( SELECT project FROM access WHERE user = ? );"; $bind_variables = array( $_SESSION["user"], $_SESSION["user_id"] ); $return = $sql->query( $query, $bind_variables, array() ); @@ -246,42 +231,24 @@ class Project extends Common { public function remove_user() { global $sql; - $query = "SELECT access FROM projects WHERE path=? AND owner=?"; - $bind_variables = array( $this->path, $_SESSION["user"] ); - $result = $sql->query( $query, $bind_variables, array() )[0]; - - if( ! empty( $result ) ) { + + $user_id = get_user_id( $this->user ); + + if( $user_id === false ) { - $access = json_decode( $result["access"] ); + return formatJSEND( "error", "Error fetching user information." ); + } + + $query = "DELETE FROM access WHERE project=? AND user=?;"; + $bind_variables = array( $this->project_id, $user_id ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { - if( is_array( $access ) ) { - - $key = array_search( $this->user, $access ); - - if ( $key !== false ) { - - unset( $access[$key] ); - } else { - - echo( formatJSEND( "error", "{$this->user} is not in the access list." ) ); - } - } - - $access = json_encode( $access ); - $query = "UPDATE projects SET access=? WHERE path=? AND owner=?;"; - $bind_variables = array( $access, $this->path, $_SESSION["user"] ); - $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); - - if( $return > 0 ) { - - echo( formatJSEND( "success", "Successfully removed {$this->user}." ) ); - } else { - - echo formatJSEND( "error", "Error setting access for project." ); - } + echo( formatJSEND( "success", "Successfully removed {$this->user}." ) ); } else { - echo formatJSEND( "error", "Error fetching projects." ); + echo( formatJSEND( "error", "{$this->user} is not in the access list." ) ); } } diff --git a/components/project/controller.php b/components/project/controller.php index 21ea7cc..1ecaa81 100755 --- a/components/project/controller.php +++ b/components/project/controller.php @@ -34,13 +34,14 @@ if( $_GET['action'] == 'add_user' ) { if( ! isset( $_GET['access'] ) || in_array( $_GET['access'], $invalid_users ) || ! in_array( $_GET['access'], array_keys( Permissions::LEVELS ) ) ) { - echo formatJSEND( "error", "No access set." ); - return; + exit( formatJSEND( "error", "No access set." ) ); + } else { + + $Project->access = Permissions::LEVELS[$_GET['access']]; } if( isset( $_GET['username'] ) && ! in_array( $_GET['username'], $invalid_users ) ) { - $Project->access = $_GET['access']; $Project->user = $_GET['username']; } else { @@ -130,8 +131,7 @@ if( $_GET['action'] == 'delete' ) { if( $_GET['action'] == 'get_access' ) { - $Project->path = $_GET['project_path']; - $access = $Project->get_access( $_GET['project_path'] ); + $access = $Project->get_access( $_GET['project_id'] ); echo formatJSEND( "success", $access ); } @@ -191,7 +191,7 @@ if( $_GET['action'] == 'get_owner' ) { if( $_GET['action'] == 'open' ) { - if( isset( $_GET['path'] ) && ! Permissions::has_read( $_GET['path'] ) ) { + if( isset( $_GET['path'] ) && Permissions::has_read( $_GET['path'] ) ) { die( formatJSEND( "error", "No Access to path " . $_GET['path'] ) ); } @@ -212,8 +212,7 @@ if( $_GET['action'] == 'remove_user' ) { $Project->user = $_GET['username']; } else { - echo formatJSEND( "error", "No username set." ); - return; + exit( formatJSEND( "error", "No username set." ) ); } if( ! in_array( $_GET['project_path'], $invalid ) ) { @@ -221,8 +220,15 @@ if( $_GET['action'] == 'remove_user' ) { $Project->path = $_GET['project_path']; } else { - echo formatJSEND( "error", "No project path set." ); - return; + exit( formatJSEND( "error", "No project path set." ) ); + } + + if( ! in_array( $_GET['project_id'], $invalid ) ) { + + $Project->project_id = $_GET['project_id']; + } else { + + exit( formatJSEND( "error", "No project id set." ) ); } if( $Project->check_owner( $_GET["project_path"], true ) ) { @@ -230,7 +236,7 @@ if( $_GET['action'] == 'remove_user' ) { $Project->remove_user(); } else { - echo formatJSEND( "error", "You can not manage this project." ); + exit( formatJSEND( "error", "You can not manage this project." ) ); } } diff --git a/components/project/dialog.php b/components/project/dialog.php index 57b8df1..16d3af7 100755 --- a/components/project/dialog.php +++ b/components/project/dialog.php @@ -204,11 +204,12 @@ switch( $_GET['action'] ) { // Get projects data $path = $_GET['path']; $project = $Project->get_project( $path ); - $access = json_decode( $project["access"], true ); + $access = $Project->get_access( $project["id"] ); $users = get_users( "return", true ); ?> -
- + + + ">

No users have been given access.

@@ -234,30 +235,30 @@ switch( $_GET['action'] ) {
+
$access_level ) { + foreach( $access as $row => $user_permissions ) { + + foreach( $users as $row => $current_user ) { + + if( $current_user["id"] == $user_permissions["user"] ) { + + $user = $current_user; + break; + } + } ?> rowCount(); break; + case( 'fetch' ): + + $return = $statement->fetch( \PDO::FETCH_ASSOC ); + break; + case( 'fetchAll' ): $return = $statement->fetchAll( \PDO::FETCH_ASSOC ); From 3d5df9aaff249441aaba611901c777eb83f61b2f Mon Sep 17 00:00:00 2001 From: xevidos Date: Thu, 4 Jul 2019 01:50:29 -0400 Subject: [PATCH 4/7] Continued work on new permissions system, Removed unused functions from common, Added initial version specific update function, --- common.php | 50 ----- components/filemanager/class.filemanager.php | 197 +++++++++++-------- components/filemanager/init.js | 3 + components/project/class.project.php | 86 ++++---- components/project/controller.php | 2 +- components/project/init.js | 2 +- components/sql/class.sql.php | 19 ++ components/update/update.php | 97 ++++++++- js/system.js | 7 +- 9 files changed, 280 insertions(+), 183 deletions(-) diff --git a/common.php b/common.php index 1e6270b..bed198f 100755 --- a/common.php +++ b/common.php @@ -107,56 +107,6 @@ class Common { // New Methods ////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////// - // Check access to application - ////////////////////////////////////////////////////////////////// - - public static function check_access( $action = "return" ) { - - /*if( ! self::check_session() ) { - - session_destroy(); - self::return( formatJSEND( "error", "Error fetching project information." ), "exit" ); - }*/ - } - - ////////////////////////////////////////////////////////////////// - // Check access to a project - ////////////////////////////////////////////////////////////////// - public static function check_project_access( $project_path, $action ) { - - global $sql; - $query = "SELECT * FROM projects WHERE name=? AND path=? AND ( owner=? OR owner='nobody' );"; - $bind_variables = array( $project_name, $project_path, $_SESSION["user"] ); - $return = $sql->query( $query, $bind_variables, formatJSEND( "error", "Error checking project access." ) ); - - if( ! empty( $return ) ) { - - try { - - $users = json_decode( $return["access"] ); - } catch( exception $e ) { - - $users = array(); - } - - if( $return["owner"] == 'nobody' || $return["owner"] == $_SESSION["user"] || ( in_array( $_SESSION["user"], $users ) && ! empty( $users ) ) ) { - - $return = true; - } else { - - $return = false; - } - } else { - - $return = false; - } - - self::return( $return, $action ); - } - public static function get_user_id( $username ) { global $sql; diff --git a/components/filemanager/class.filemanager.php b/components/filemanager/class.filemanager.php index 8ff5239..ce6872a 100755 --- a/components/filemanager/class.filemanager.php +++ b/components/filemanager/class.filemanager.php @@ -350,6 +350,8 @@ class Filemanager extends Common { public function open() { + $response = array(); + if ( is_file( $this->path ) ) { $output = file_get_contents( $this->path ); @@ -368,19 +370,22 @@ class Filemanager extends Common { } } - $this->status = "success"; - $this->data = '"content":' . json_encode( $output ); $mtime = filemtime( $this->path ); - $this->data .= ', "mtime":'.$mtime; - $this->data .= ', "access":'. $this->access; - $this->data .= ', "read_only":'. ( Permissions::check_access( "read", $this->access ) && ! Permissions::check_access( "write", $this->access ) ); + $response["status"] = "success"; + $response["data"] = array( + "content" => $output, + "mtime" => $mtime, + "access" => $this->access, + "read_only" => ( Permissions::check_access( "read", $this->access ) && ! Permissions::check_access( "write", $this->access ) ), + ); } else { - $this->status = "error"; - $this->message = "Not A File :" . $this->path; + $response = array( + "status" => "error", + "message" => "Not A File :" . $this->path, + ); } - - $this->respond(); + exit( json_encode( $response ) ); } ////////////////////////////////////////////////////////////////// @@ -388,7 +393,7 @@ class Filemanager extends Common { ////////////////////////////////////////////////////////////////// public function openinbrowser() { - + $protocol = ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] != 'off' ) || $_SERVER['SERVER_PORT'] == 443 ) ? "https://" : "http://"; $domainName = $_SERVER['HTTP_HOST']; $url = $protocol . WSURL . '/' . $this->rel_path; @@ -402,49 +407,64 @@ class Filemanager extends Common { ////////////////////////////////////////////////////////////////// public function create() { - - // Create file - if ( $this->type == "file" ) { + + $response = array(); + if( Permissions::has_create( $this->path ) ) { - if ( ! file_exists( $this->path ) ) { + // Create file + if ( $this->type == "file" ) { - if ( $file = fopen( $this->path, 'w' ) ) { + if ( ! file_exists( $this->path ) ) { - // Write content - if ( $this->content ) { + if ( $file = fopen( $this->path, 'w' ) ) { - fwrite( $file, $this->content ); + // Write content + if ( $this->content ) { + + fwrite( $file, $this->content ); + } + fclose( $file ); + $response["data"] = array( + "content" => $this->content, + "mtime" => filemtime( $this->path ), + "access" => $this->access, + "read_only" => ( Permissions::check_access( "read", $this->access ) && ! Permissions::check_access( "write", $this->access ) ), + ); + $this->status = "success"; + } else { + + $this->status = "error"; + $this->message = "Cannot Create File"; } - $this->data = '"mtime":' . filemtime( $this->path ); - fclose( $file ); + } else { + + $this->status = "error"; + $this->message = "File Already Exists"; + } + } + + // Create directory + if ( $this->type == "directory" ) { + + if ( ! is_dir( $this->path ) ) { + + mkdir( $this->path ); $this->status = "success"; } else { $this->status = "error"; - $this->message = "Cannot Create File"; + $this->message = "Directory Already Exists"; } - } else { - - $this->status = "error"; - $this->message = "File Already Exists"; } - } - - // Create directory - if ( $this->type == "directory" ) { + } else { - if ( ! is_dir( $this->path ) ) { - - mkdir( $this->path ); - $this->status = "success"; - } else { - - $this->status = "error"; - $this->message = "Directory Already Exists"; - } + $this->status = "error"; + $this->message = "No create access."; } - $this->respond(); + $response["status"] = $this->status; + $response["message"] = $this->message; + exit( json_encode( $response ) ); } ////////////////////////////////////////////////////////////////// @@ -453,67 +473,70 @@ class Filemanager extends Common { public function delete( $keep_parent = false ) { - if( ! Permissions::has_delete( $this->path ) ) { - - $this->status = "error"; - $this->message = "No access."; - $this->respond(); - return; - } + $response = array(); - function rrmdir( $path, $follow, $keep_parent = false ) { + if( Permissions::has_delete( $this->path ) ) { - if ( is_file( $path ) ) { - - unlink( $path ); - } else { - - $files = array_diff( scandir( $path ), array( '.', '..' ) ); - foreach ( $files as $file ) { - - if ( is_link( $path . "/" . $file ) ) { - - if ( $follow ) { - - rrmdir( $path . "/" . $file, $follow, false); - } - unlink( $path . "/" . $file ); - } elseif ( is_dir( $path . "/" . $file ) ) { - - rrmdir( $path . "/" . $file, $follow, false ); - } else { - - unlink( $path . "/" . $file ); - } - } - if( $keep_parent === false ) { - - rmdir( $path ); - return; + function rrmdir( $path, $follow, $keep_parent = false ) { + + if ( is_file( $path ) ) { + + unlink( $path ); } else { - return; + $files = array_diff( scandir( $path ), array( '.', '..' ) ); + foreach ( $files as $file ) { + + if ( is_link( $path . "/" . $file ) ) { + + if ( $follow ) { + + rrmdir( $path . "/" . $file, $follow, false); + } + unlink( $path . "/" . $file ); + } elseif ( is_dir( $path . "/" . $file ) ) { + + rrmdir( $path . "/" . $file, $follow, false ); + } else { + + unlink( $path . "/" . $file ); + } + } + if( $keep_parent === false ) { + + rmdir( $path ); + return; + } else { + + return; + } } } - } - - if ( file_exists( $this->path ) ) { - if ( isset( $_GET['follow'] ) ) { - - rrmdir( $this->path, true, $keep_parent ); + if ( file_exists( $this->path ) ) { + + if ( isset( $_GET['follow'] ) ) { + + rrmdir( $this->path, true, $keep_parent ); + } else { + + rrmdir( $this->path, false, $keep_parent ); + } + + $this->status = "success"; } else { - - rrmdir( $this->path, false, $keep_parent ); + + $this->status = "error"; + $this->message = "Path Does Not Exist "; } - - $this->status = "success"; } else { $this->status = "error"; - $this->message = "Path Does Not Exist "; + $this->message = "No delete access."; } - $this->respond(); + $response["status"] = $this->status; + $response["message"] = $this->message; + exit( json_encode( $response ) ); } diff --git a/components/filemanager/init.js b/components/filemanager/init.js index a380476..c9bf88f 100755 --- a/components/filemanager/init.js +++ b/components/filemanager/init.js @@ -884,6 +884,9 @@ .live( 'submit', function( e ) { e.preventDefault(); $.get( _this.controller + '?action=delete&path=' + encodeURIComponent( path ), function( data ) { + + console.log( data ); + var deleteResponse = codiad.jsend.parse( data ); if( deleteResponse != 'error' ) { var node = $( '#file-manager a[data-path="' + path + '"]' ); diff --git a/components/project/class.project.php b/components/project/class.project.php index df1b538..e89ccab 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -115,6 +115,28 @@ class Project extends Common { } } + public function check_duplicate( $full_path ) { + + $pass = true; + $query = "SELECT id, path, owner FROM projects;"; + $result = $sql->query( $query, array(), array(), "fetchAll" ); + + if( ! empty( $result ) ) { + + foreach( $result as $row => $project ) { + + $full_project_path = Common::isAbsPath( $project["path"] ) ? $project["path"] : WORKSPACE . "/{$project["path"]}"; + + if( ! ( strpos( $full_path, $full_project_path ) === FALSE ) ) { + + $pass = false; + break; + } + } + } + return $pass; + } + public function check_owner( $path = null, $exclude_public = false ) { if( $path === null ) { @@ -336,9 +358,9 @@ class Project extends Common { owner=? OR owner='nobody' OR id IN ( SELECT project FROM access WHERE user = ? ) - ) ORDER BY name;"; + ) ORDER BY name LIMIT 1;"; $bind_variables = array( $this->path, $_SESSION["user"], $_SESSION["user_id"] ); - $return = $sql->query( $query, $bind_variables, array() )[0]; + $return = $sql->query( $query, $bind_variables, array(), "fetch" ); if( ! empty( $return ) ) { @@ -375,18 +397,17 @@ class Project extends Common { if( ! $this->public_project && ! $this->isAbsPath( $this->path ) ) { $user_path = WORKSPACE . '/' . preg_replace( '/[^\w-]/', '', strtolower( $_SESSION["user"] ) ); + $this->path = $_SESSION["user"] . '/' . $this->path; + } + + $pass = $this->check_duplicate(); + if ( $pass ) { if( ! is_dir( $user_path ) ) { mkdir( $user_path, 0755, true ); } - $this->path = $_SESSION["user"] . '/' . $this->path; - } - - $pass = $this->checkDuplicate(); - if ( $pass ) { - if ( ! $this->isAbsPath( $this->path ) ) { mkdir( WORKSPACE . '/' . $this->path ); @@ -407,7 +428,7 @@ class Project extends Common { $allowed = true; } } - if ( ! $allowed) { + if ( ! $allowed ) { die( formatJSEND( "error", "Absolute Path Only Allowed for " . WHITEPATHS ) ); } @@ -443,18 +464,18 @@ class Project extends Common { $this->ExecuteCMD(); } - echo formatJSEND( "success", array( "name" => $this->name, "path" => $this->path ) ); + exit( formatJSEND( "success", array( "name" => $this->name, "path" => $this->path ) ) ); } else { - echo formatJSEND( "error", "A Project With the Same Name or Path Exists" ); + exit( formatJSEND( "error", "A Project With the Same Name or Path Exists" ) ); } } else { - echo formatJSEND( "error", "Project Name/Folder not allowed" ); + exit( formatJSEND( "error", "Project Name/Folder not allowed" ) ); } } else { - echo formatJSEND( "error", "Project Name/Folder is empty" ); + exit( formatJSEND( "error", "Project Name/Folder is empty" ) ); } } @@ -495,37 +516,26 @@ class Project extends Common { public function Delete() { - global $sql; - $query = "DELETE FROM projects WHERE path=? AND ( owner=? OR owner='nobody' );"; - $bind_variables = array( $this->path, $_SESSION["user"] ); - $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); - - if( $return > 0 ) { + if( Permissions::has_owner( $this->path ) ) { - echo( formatJSEND( "success", "Successfully deleted $project_name" ) ); + global $sql; + $query = "DELETE FROM projects WHERE path=?"; + $bind_variables = array( $this->path, $_SESSION["user"] ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + exit( formatJSEND( "success", "Successfully deleted project." ) ); + } else { + + exit( formatJSEND( "error", "Error deleting project" ) ); + } } else { - echo formatJSEND( "error", "Error deleting project $project_name" ); + exit( formatJSEND( "error", "You do not have permission to delete this project" ) ); } } - ////////////////////////////////////////////////////////////////// - // Check Duplicate - ////////////////////////////////////////////////////////////////// - - public function CheckDuplicate() { - - $pass = true; - foreach ( $this->projects as $project => $data ) { - - if ( $data['name'] == $this->name || $data['path'] == $this->path ) { - - $pass = false; - } - } - return $pass; - } - ////////////////////////////////////////////////////////////////// // Sanitize Path ////////////////////////////////////////////////////////////////// diff --git a/components/project/controller.php b/components/project/controller.php index 1ecaa81..0d80b12 100755 --- a/components/project/controller.php +++ b/components/project/controller.php @@ -191,7 +191,7 @@ if( $_GET['action'] == 'get_owner' ) { if( $_GET['action'] == 'open' ) { - if( isset( $_GET['path'] ) && Permissions::has_read( $_GET['path'] ) ) { + if( ! isset( $_GET['path'] ) || ! Permissions::has_read( $_GET['path'] ) ) { die( formatJSEND( "error", "No Access to path " . $_GET['path'] ) ); } diff --git a/components/project/init.js b/components/project/init.js index bb23db4..1173226 100755 --- a/components/project/init.js +++ b/components/project/init.js @@ -79,7 +79,7 @@ console.log( access, username, project_path, project_id ); - $.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&project_id=' + encodeURIComponent( project_id ) + '&username=' + encodeURIComponent( username ) + '&access=' + encodeURIComponent( access ), function( data ) { + $.get( _this.controller + '?action=add_user&path=' + encodeURIComponent( project_path ) + '&id=' + encodeURIComponent( project_id ) + '&username=' + encodeURIComponent( username ) + '&access=' + encodeURIComponent( access ), function( data ) { let response = codiad.jsend.parse( data ); console.log( response ); diff --git a/components/sql/class.sql.php b/components/sql/class.sql.php index b370180..b5db269 100755 --- a/components/sql/class.sql.php +++ b/components/sql/class.sql.php @@ -222,6 +222,25 @@ class sql { //echo var_dump( $error->getMessage() ); } + + if( DBTYPE === "mysql" || DBTYPE === "pgsql" ) { + + try { + + $projects = $this->query( "ALTER TABLE projects DROP CONSTRAINT path1500owner255;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + + try { + + $projects = $this->query( "ALTER TABLE active DROP CONSTRAINT username255path1500;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + } } return $result; diff --git a/components/update/update.php b/components/update/update.php index 207fab8..6998c30 100755 --- a/components/update/update.php +++ b/components/update/update.php @@ -178,6 +178,12 @@ class updater { $sql = new sql(); $connection = $sql->connect(); $result = $sql->create_default_tables(); + $upgrade_function = str_replace( ".", "_", $this->update::VERSION ); + + if( is_callable( array( $this, $upgrade_function ) ) ) { + + $this->$upgrade_function(); + } } function check_update() { @@ -454,7 +460,6 @@ class updater { $this->backup(); - try { $sessions = "../../data/sessions"; @@ -592,6 +597,96 @@ class updater { $return = "true"; } } + + function v_2_9_6() { + + //This function should run to upgrade our database version from less than 2.9.6 + $sql_conversions = new sql_conversions(); + + try { + + $access_query = "INSERT INTO access( project, user, level ) VALUES "; + $projects = $this->query( "SELECT id, access FROM projects", array(), array(), "fetchAll", "exception" ); + $users = $this->query( "SELECT id, username FROM users", array(), array(), "fetchAll", "exception" ); + $delete = Permissions::LEVELS["delete"]; + + foreach( $users as $row => $user ) { + + foreach( $projects as $row => $project ) { + + $access = json_decode( $project["access"], true ); + if( ! is_array( $access ) || empty( $access ) ) { + + continue; + } + + foreach( $access as $granted_user ) { + + if( $granted_user == $user["username"] ) { + + $access_query .= "( {$project["id"]}, {$user["id"]}, $delete ),"; + } + } + } + } + + if( $access_query !== "INSERT INTO access( project, user, level ) " ) { + + $result = $this->query( substr( $access_query, 0, -1 ), array(), 0, "rowCount", "exception" ); + } + $result = $this->query( "ALTER TABLE projects DROP COLUMN access", array(), 0, "rowCount" ); + } catch( Exception $error ) { + + //The access field is not there. + //echo var_export( $error->getMessage(), $access_query ); + } + + try { + + $update_query = ""; + $projects = $this->query( "SELECT id, path FROM projects", array(), array(), "fetchAll", "exception" ); + $result = $this->query( "SELECT project FROM users", array(), array(), "fetchAll", "exception" ); + $convert = false; + $delete = Permissions::LEVELS["delete"]; + + foreach( $projects as $row => $project ) { + + if( $project["path"] == $user["project"] ) { + + $update_query .= "UPDATE users SET project={$project["id"]};"; + } + } + + if( $convert ) { + + //change project to users table + $result = $this->query( "ALTER TABLE users DROP COLUMN project", array(), array(), "rowCount", "exception" ); + $result = $this->query( "ALTER TABLE users ADD COLUMN project " . $sql_conversions->data_types["int"][DBTYPE], array(), array(), "rowCount", "exception" ); + $result = $this->query( $update_query, array(), array(), "rowCount", "exception" ); + } + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + + $constraint = ( DBTYPE == "mysql" ) ? "INDEX" : "CONSTRAINT"; + + try { + + $projects = $this->query( "ALTER TABLE projects DROP $constraint path1500owner255;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + + try { + + $projects = $this->query( "ALTER TABLE active DROP $constraint username255path1500;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + } + } } if( isset( $_GET["action"] ) && $_GET["action"] !== '' ) { diff --git a/js/system.js b/js/system.js index 0907b07..5773564 100755 --- a/js/system.js +++ b/js/system.js @@ -126,7 +126,7 @@ create_default_tables: function() { jQuery.ajax({ - + url: this.controller, type: "POST", dataType: 'html', @@ -137,12 +137,9 @@ let response = codiad.jsend.parse( data ); - if( response.status != 'error' ) { + if( response != 'error' ) { codiad.message.success( i18n( 'Created Default Tables' ) ); - } else { - - codiad.message.error( i18n( 'Error Creating Default Tables' ) ); } console.log( data ); }, From 4dab45e0e717bef29def53298c2cff8766e09a19 Mon Sep 17 00:00:00 2001 From: xevidos Date: Thu, 4 Jul 2019 01:52:05 -0400 Subject: [PATCH 5/7] Changed permission denied messages --- components/filemanager/class.filemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/filemanager/class.filemanager.php b/components/filemanager/class.filemanager.php index ce6872a..d7a09e4 100755 --- a/components/filemanager/class.filemanager.php +++ b/components/filemanager/class.filemanager.php @@ -532,7 +532,7 @@ class Filemanager extends Common { } else { $this->status = "error"; - $this->message = "No delete access."; + $this->message = "You do not have permission to delete this file."; } $response["status"] = $this->status; $response["message"] = $this->message; @@ -646,7 +646,7 @@ class Filemanager extends Common { } else { $this->status = "error"; - $this->message = "Write access is denied."; + $this->message = "You do not have write permission to this file."; } } else { From 0dedba59d2645b09b6f1842ff8f3a0e6080ed727 Mon Sep 17 00:00:00 2001 From: xevidos Date: Mon, 8 Jul 2019 13:44:17 -0400 Subject: [PATCH 6/7] Public projects are now created in the user\'s workspace directory instead of the main directory so project directories do not conflict with user folders --- components/permissions/class.permissions.php | 22 ++-- components/project/class.project.php | 35 ++++++- components/project/dialog.php | 104 +++++++++++-------- components/project/init.js | 6 ++ 4 files changed, 104 insertions(+), 63 deletions(-) diff --git a/components/permissions/class.permissions.php b/components/permissions/class.permissions.php index a4fa5c6..0180484 100644 --- a/components/permissions/class.permissions.php +++ b/components/permissions/class.permissions.php @@ -37,6 +37,12 @@ class Permissions { $level = self::LEVELS[$level]; } else { + exit( formatJSEND( "error", "Access Level does not exist." ) ); + } + } else { + + if( ! in_array( $level, self::LEVELS ) ) { + exit( formatJSEND( "error", "Access Level does not exist." ) ); } } @@ -46,19 +52,11 @@ class Permissions { public static function check_path( $level, $path ) { - if( ! in_array( $level, array_keys( self::LEVELS ) ) ) { - - exit( formatJSEND( "error", "Access Level does not exist." ) ); - } - - $pass = false; $user_level = self::get_access( $path ); - if( $user_level >= self::LEVELS[$level] ) { - - $pass = true; - } - return( $pass ); + echo var_dump( $level, $user_level, $path ); + + return self::check_access( $level, $user_level ); } public static function get_access( $path ) { @@ -100,7 +98,7 @@ class Permissions { } } - //echo var_dump( $full_path, $full_project_path, $path_postition, $user["level"], $pass ); + //echo var_dump( $full_path, $full_project_path, $path_postition, $user["level"], $data["owner"], $_SESSION["user"] ); if( $access > 0 ) { break; diff --git a/components/project/class.project.php b/components/project/class.project.php index e89ccab..2350866 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -117,6 +117,7 @@ class Project extends Common { public function check_duplicate( $full_path ) { + global $sql; $pass = true; $query = "SELECT id, path, owner FROM projects;"; $result = $sql->query( $query, array(), array(), "fetchAll" ); @@ -231,6 +232,26 @@ class Project extends Common { return( $return ); } + public function get_all_projects() { + + if( is_admin() ) { + + global $sql; + $query = "SELECT * FROM projects"; + $bind_variables = array(); + $return = $sql->query( $query, $bind_variables, array() ); + + if( empty( $return ) ) { + + $return = formatJSEND( "error", "Error fetching projects." ); + } + } else { + + $return = formatJSEND( "error", "Only admins are allowed to view all projects." ); + } + return( $return ); + } + public function get_projects() { global $sql; @@ -394,13 +415,14 @@ class Project extends Common { } if ( $this->path != '' ) { - if( ! $this->public_project && ! $this->isAbsPath( $this->path ) ) { + $user_path = WORKSPACE . '/' . preg_replace( '/[^\w-]/', '', strtolower( $_SESSION["user"] ) ); + + if( ! $this->isAbsPath( $this->path ) ) { - $user_path = WORKSPACE . '/' . preg_replace( '/[^\w-]/', '', strtolower( $_SESSION["user"] ) ); $this->path = $_SESSION["user"] . '/' . $this->path; } - $pass = $this->check_duplicate(); + $pass = $this->check_duplicate( $this->path ); if ( $pass ) { if( ! is_dir( $user_path ) ) { @@ -410,7 +432,10 @@ class Project extends Common { if ( ! $this->isAbsPath( $this->path ) ) { - mkdir( WORKSPACE . '/' . $this->path ); + if( ! is_dir( WORKSPACE . '/' . $this->path ) ) { + + mkdir( WORKSPACE . '/' . $this->path ); + } } else { if( ! is_admin() ) { @@ -520,7 +545,7 @@ class Project extends Common { global $sql; $query = "DELETE FROM projects WHERE path=?"; - $bind_variables = array( $this->path, $_SESSION["user"] ); + $bind_variables = array( $this->path ); $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); if( $return > 0 ) { diff --git a/components/project/dialog.php b/components/project/dialog.php index 16d3af7..6d1416b 100755 --- a/components/project/dialog.php +++ b/components/project/dialog.php @@ -56,7 +56,12 @@ switch( $_GET['action'] ) { case 'list': //Get projects data - $projects = $Project->get_projects(); + if( isset( $_GET["all"] ) ) { + + $projects = $Project->get_all_projects(); + } else { + $projects = $Project->get_projects(); + } ?>
@@ -72,56 +77,63 @@ switch( $_GET['action'] ) {
-

+

- +
$data ) { + if( is_array( $projects ) ) { - $show = true; - if( $show ) { + foreach( $projects as $project => $data ) { - ?> - - - - - get_owner( $data['path'] ); - if( $owner == 'nobody' ) { - - ?> - - - - - - + + + + + get_owner( $data['path'] ); + if( $owner == 'nobody' ) { + + ?> + + + + + + + + + + + + + + - - - - - - - -
diff --git a/components/project/init.js b/components/project/init.js index 1173226..966dd52 100755 --- a/components/project/init.js +++ b/components/project/init.js @@ -249,6 +249,12 @@ codiad.modal.load( 500, this.dialog + '?action=list' ); }, + list_all: function() { + + $( '#modal-content form' ).die( 'submit' ); // Prevent form bubbling + codiad.modal.load( 500, this.dialog + '?action=list&all=true' ); + }, + /** * Turn the access array into a table. */ From c2d0662a230ceb85d433d3633a3d61ee8a3bc7dc Mon Sep 17 00:00:00 2001 From: xevidos Date: Mon, 8 Jul 2019 22:34:39 -0400 Subject: [PATCH 7/7] Changed error messages, Removed Debug messages, Removed version update function, Updated regex for path, Reformatted user controller, Added server side checks to create user function, Removed unique from active columns in create default tables, Removed groups column from users, Added upgrade table structure function --- components/filemanager/class.filemanager.php | 6 +- components/permissions/class.permissions.php | 3 - components/project/class.project.php | 6 +- components/project/controller.php | 2 +- components/sql/class.sql.php | 248 ++++++++++------- components/system/controller.php | 2 +- components/update/update.php | 92 +------ components/user/class.user.php | 4 +- components/user/controller.php | 274 ++++++++++--------- components/user/init.js | 64 +++-- js/system.js | 6 - 11 files changed, 335 insertions(+), 372 deletions(-) diff --git a/components/filemanager/class.filemanager.php b/components/filemanager/class.filemanager.php index d7a09e4..1f433ee 100755 --- a/components/filemanager/class.filemanager.php +++ b/components/filemanager/class.filemanager.php @@ -434,7 +434,7 @@ class Filemanager extends Common { } else { $this->status = "error"; - $this->message = "Cannot Create File"; + $this->message = "Cannot Create File at " . $this->path; } } else { @@ -556,8 +556,6 @@ class Filemanager extends Common { if ( ! file_exists( $new_path ) ) { - echo var_dump( Permissions::has_create( $this->path ) ); - if ( Permissions::has_create( $this->path ) && rename( $this->path, $new_path ) ) { //unlink($this->path); @@ -817,7 +815,7 @@ class Filemanager extends Common { } elseif( $invalid_characters && ( $_GET['action'] == "modify" || $_GET['action'] == "delete" ) ) { } else { - $path = preg_replace( '/[^A-Za-z0-9\-\._\/\ ]/', '', $path ); + $path = preg_replace( '/[^A-Za-z0-9\-\._@\/\ ]/', '', $path ); } return $path; } diff --git a/components/permissions/class.permissions.php b/components/permissions/class.permissions.php index 0180484..55512f9 100644 --- a/components/permissions/class.permissions.php +++ b/components/permissions/class.permissions.php @@ -53,9 +53,6 @@ class Permissions { public static function check_path( $level, $path ) { $user_level = self::get_access( $path ); - - echo var_dump( $level, $user_level, $path ); - return self::check_access( $level, $user_level ); } diff --git a/components/project/class.project.php b/components/project/class.project.php index 2350866..6a8a969 100755 --- a/components/project/class.project.php +++ b/components/project/class.project.php @@ -226,7 +226,7 @@ class Project extends Common { } else { - $return = formatJSEND( "error", "Error fetching projects." ); + $return = formatJSEND( "error", "No projects found." ); } return( $return ); @@ -243,7 +243,7 @@ class Project extends Common { if( empty( $return ) ) { - $return = formatJSEND( "error", "Error fetching projects." ); + $return = formatJSEND( "error", "No projects found." ); } } else { @@ -265,7 +265,7 @@ class Project extends Common { if( empty( $return ) ) { - $return = formatJSEND( "error", "Error fetching projects." ); + $return = formatJSEND( "error", "No projects found." ); } return( $return ); diff --git a/components/project/controller.php b/components/project/controller.php index 0d80b12..f1481ff 100755 --- a/components/project/controller.php +++ b/components/project/controller.php @@ -73,7 +73,7 @@ if( $_GET['action'] == 'add_user' ) { ////////////////////////////////////////////////////////////////// if( $_GET['action'] == 'create' ) { - + $Project->name = $_GET['project_name']; if( $_GET['public_project'] == 'true' ) { diff --git a/components/sql/class.sql.php b/components/sql/class.sql.php index b5db269..f48c3e6 100755 --- a/components/sql/class.sql.php +++ b/components/sql/class.sql.php @@ -54,7 +54,7 @@ class sql { public function create_default_tables() { - $result = $this->create_tables( + $create_tables = $this->create_tables( array( "active" => array( "fields" => array( @@ -64,8 +64,8 @@ class sql { "focused" => "string" ), "attributes" => array( - "username" => array( "not null", "unique" ), - "path" => array( "not null", "unique" ), + "username" => array( "not null" ), + "path" => array( "not null" ), "focused" => array( "not null" ), ) ), @@ -118,7 +118,6 @@ class sql { "email" => "string", "project" => "int", "access" => "string", - "groups" => "string", "token" => "string", ), "attributes" => array( @@ -144,106 +143,12 @@ class sql { ), ) ); - - if( $result === true ) { - - $sql_conversions = new sql_conversions(); - - try { - - $access_query = "INSERT INTO access( project, user, level ) VALUES "; - $projects = $this->query( "SELECT id, access FROM projects", array(), array(), "fetchAll", "exception" ); - $users = $this->query( "SELECT id, username FROM users", array(), array(), "fetchAll", "exception" ); - $delete = Permissions::LEVELS["delete"]; - - foreach( $users as $row => $user ) { - - foreach( $projects as $row => $project ) { - - $access = json_decode( $project["access"], true ); - if( ! is_array( $access ) || empty( $access ) ) { - - continue; - } - - foreach( $access as $granted_user ) { - - if( $granted_user == $user["username"] ) { - - $access_query .= "( {$project["id"]}, {$user["id"]}, $delete ),"; - } - } - } - } - - if( $access_query !== "INSERT INTO access( project, user, level ) " ) { - - $result = $this->query( substr( $access_query, 0, -1 ), array(), 0, "rowCount", "exception" ); - } - $result = $this->query( "ALTER TABLE projects DROP COLUMN access", array(), 0, "rowCount" ); - } catch( Exception $error ) { - - //The access field is not there. - //echo var_export( $error->getMessage(), $access_query ); - } - - try { - - $update_query = ""; - $projects = $this->query( "SELECT id, path FROM projects", array(), array(), "fetchAll", "exception" ); - $result = $this->query( "SELECT project FROM users", array(), array(), "fetchAll", "exception" ); - $convert = false; - $delete = Permissions::LEVELS["delete"]; - - foreach( $result as $row => $user ) { - - if( ! is_numeric( $user["project"] ) ) { - - $convert = true; - } - - foreach( $projects as $row => $project ) { - - if( $project["path"] == $user["project"] ) { - - $update_query .= "UPDATE users SET project={$project["id"]};"; - } - } - } - - if( $convert ) { - - //change project to users table - $result = $this->query( "ALTER TABLE users DROP COLUMN project", array(), array(), "rowCount", "exception" ); - $result = $this->query( "ALTER TABLE users ADD COLUMN project " . $sql_conversions->data_types["int"][DBTYPE], array(), array(), "rowCount", "exception" ); - $result = $this->query( $update_query, array(), array(), "rowCount", "exception" ); - } - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - - if( DBTYPE === "mysql" || DBTYPE === "pgsql" ) { - - try { - - $projects = $this->query( "ALTER TABLE projects DROP CONSTRAINT path1500owner255;", array(), 0, "rowCount", "exception" ); - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - - try { - - $projects = $this->query( "ALTER TABLE active DROP CONSTRAINT username255path1500;", array(), 0, "rowCount", "exception" ); - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - } - } - - return $result; + $structure_updates = $this->update_table_structure(); + $result = array( + "create_tables" => $create_tables, + "structure_updates" => $structure_updates + ); + exit( json_encode( $result, JSON_PRETTY_PRINT ) ); } public function create_tables( $table ) { @@ -339,6 +244,141 @@ class sql { //return $query; } + public function update_table_structure() { + + $status_updates = array(); + $sql_conversions = new sql_conversions(); + + try { + + $access_query = "INSERT INTO access( project, user, level ) VALUES "; + $projects = $this->query( "SELECT id, access FROM projects", array(), array(), "fetchAll", "exception" ); + $users = $this->query( "SELECT id, username FROM users", array(), array(), "fetchAll", "exception" ); + $delete = Permissions::LEVELS["delete"]; + + foreach( $users as $row => $user ) { + + foreach( $projects as $row => $project ) { + + $access = json_decode( $project["access"], true ); + if( ! is_array( $access ) || empty( $access ) ) { + + continue; + } + + foreach( $access as $granted_user ) { + + if( $granted_user == $user["username"] ) { + + $access_query .= "( {$project["id"]}, {$user["id"]}, $delete ),"; + } + } + } + } + + if( $access_query !== "INSERT INTO access( project, user, level ) VALUES " ) { + + $result = $this->query( substr( $access_query, 0, -1 ), array(), 0, "rowCount", "exception" ); + } + $result = $this->query( "ALTER TABLE projects DROP COLUMN access", array(), 0, "rowCount" ); + $status_updates["access_column"] = "Cached data and removed access column."; + } catch( Exception $error ) { + + //The access field is not there. + //echo var_export( $error->getMessage(), $access_query ); + $status_updates["access_column"] = array( + "error_message" => $error->getMessage(), + "dev_message" => "No access column to convert." + ); + } + + try { + + $update_query = ""; + $projects = $this->query( "SELECT id, path FROM projects", array(), array(), "fetchAll", "exception" ); + $result = $this->query( "SELECT project FROM users", array(), array(), "fetchAll", "exception" ); + $convert = false; + $delete = Permissions::LEVELS["delete"]; + + foreach( $result as $row => $user ) { + + if( ! is_numeric( $user["project"] ) ) { + + $convert = true; + } + + foreach( $projects as $row => $project ) { + + if( $project["path"] == $user["project"] ) { + + $update_query .= "UPDATE users SET project={$project["id"]};"; + } + } + } + + if( $convert && strlen( $update_query ) > 0 ) { + + //change project to users table + $result = $this->query( "ALTER TABLE users DROP COLUMN project", array(), array(), "rowCount", "exception" ); + $result = $this->query( "ALTER TABLE users ADD COLUMN project " . $sql_conversions->data_types["int"][DBTYPE], array(), array(), "rowCount", "exception" ); + $result = $this->query( $update_query, array(), array(), "rowCount", "exception" ); + } else { + + $status_updates["users_current_project"] = array( "dev_message" => "Users current project column to project_id conversion not needed." ); + } + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + $status_updates["users_current_project"] = array( + "error_message" => $error->getMessage(), + "dev_message" => "Users current project column to project_id conversion failed." + ); + } + + try { + + $result = $this->query( "ALTER TABLE users DROP COLUMN groups", array(), array(), "rowCount", "exception" ); + $status_updates["users_groups_column"] = array( "dev_message" => "Removal of the groups column from the users table succeeded." ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + $status_updates["users_groups_column"] = array( + "error_message" => $error->getMessage(), + "dev_message" => "Removal of the groups column from the users table failed. This usually means there was never one to begin with" + ); + } + + if( DBTYPE === "mysql" || DBTYPE === "pgsql" ) { + + $constraint = ( DBTYPE === "mysql" ) ? "INDEX" : "CONSTRAINT"; + + try { + + $projects = $this->query( "ALTER TABLE projects DROP $constraint path1500owner255;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + $status_updates["path_owner_constraint"] = array( + "error_message" => $error->getMessage(), + "dev_message" => "Removal of path1500owner255 constraint in the projects table failed. This usually means there was never one to begin with" + ); + } + + try { + + $projects = $this->query( "ALTER TABLE active DROP $constraint username255path1500;", array(), 0, "rowCount", "exception" ); + } catch( Exception $error ) { + + //echo var_dump( $error->getMessage() ); + $status_updates["username_path_constraint"] = array( + "error_message" => $error->getMessage(), + "dev_message" => "Removal of username255path1500 constraint in the active table failed. This usually means there was never one to begin with" + ); + } + } + return $status_updates; + } + public function query( $query, $bind_variables, $default, $action='fetchAll', $errors="default" ) { /** diff --git a/components/system/controller.php b/components/system/controller.php index 4a17882..9a524ac 100644 --- a/components/system/controller.php +++ b/components/system/controller.php @@ -19,7 +19,7 @@ if ( $_POST['action'] == 'create_default_tables' ) { global $sql; $result = $sql->create_default_tables(); - echo var_dump( $result ); + //echo var_dump( $result ); if( $result === true ) { diff --git a/components/update/update.php b/components/update/update.php index 6998c30..644d6c5 100755 --- a/components/update/update.php +++ b/components/update/update.php @@ -177,7 +177,7 @@ class updater { $sql = new sql(); $connection = $sql->connect(); - $result = $sql->create_default_tables(); + $result = $sql->recreate_default_tables(); $upgrade_function = str_replace( ".", "_", $this->update::VERSION ); if( is_callable( array( $this, $upgrade_function ) ) ) { @@ -597,96 +597,6 @@ class updater { $return = "true"; } } - - function v_2_9_6() { - - //This function should run to upgrade our database version from less than 2.9.6 - $sql_conversions = new sql_conversions(); - - try { - - $access_query = "INSERT INTO access( project, user, level ) VALUES "; - $projects = $this->query( "SELECT id, access FROM projects", array(), array(), "fetchAll", "exception" ); - $users = $this->query( "SELECT id, username FROM users", array(), array(), "fetchAll", "exception" ); - $delete = Permissions::LEVELS["delete"]; - - foreach( $users as $row => $user ) { - - foreach( $projects as $row => $project ) { - - $access = json_decode( $project["access"], true ); - if( ! is_array( $access ) || empty( $access ) ) { - - continue; - } - - foreach( $access as $granted_user ) { - - if( $granted_user == $user["username"] ) { - - $access_query .= "( {$project["id"]}, {$user["id"]}, $delete ),"; - } - } - } - } - - if( $access_query !== "INSERT INTO access( project, user, level ) " ) { - - $result = $this->query( substr( $access_query, 0, -1 ), array(), 0, "rowCount", "exception" ); - } - $result = $this->query( "ALTER TABLE projects DROP COLUMN access", array(), 0, "rowCount" ); - } catch( Exception $error ) { - - //The access field is not there. - //echo var_export( $error->getMessage(), $access_query ); - } - - try { - - $update_query = ""; - $projects = $this->query( "SELECT id, path FROM projects", array(), array(), "fetchAll", "exception" ); - $result = $this->query( "SELECT project FROM users", array(), array(), "fetchAll", "exception" ); - $convert = false; - $delete = Permissions::LEVELS["delete"]; - - foreach( $projects as $row => $project ) { - - if( $project["path"] == $user["project"] ) { - - $update_query .= "UPDATE users SET project={$project["id"]};"; - } - } - - if( $convert ) { - - //change project to users table - $result = $this->query( "ALTER TABLE users DROP COLUMN project", array(), array(), "rowCount", "exception" ); - $result = $this->query( "ALTER TABLE users ADD COLUMN project " . $sql_conversions->data_types["int"][DBTYPE], array(), array(), "rowCount", "exception" ); - $result = $this->query( $update_query, array(), array(), "rowCount", "exception" ); - } - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - - $constraint = ( DBTYPE == "mysql" ) ? "INDEX" : "CONSTRAINT"; - - try { - - $projects = $this->query( "ALTER TABLE projects DROP $constraint path1500owner255;", array(), 0, "rowCount", "exception" ); - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - - try { - - $projects = $this->query( "ALTER TABLE active DROP $constraint username255path1500;", array(), 0, "rowCount", "exception" ); - } catch( Exception $error ) { - - //echo var_dump( $error->getMessage() ); - } - } } if( isset( $_GET["action"] ) && $_GET["action"] !== '' ) { diff --git a/components/user/class.user.php b/components/user/class.user.php index cc9db4e..9622c0b 100755 --- a/components/user/class.user.php +++ b/components/user/class.user.php @@ -53,10 +53,10 @@ class User { if( $return > 0 ) { $this->set_default_options(); - echo formatJSEND( "success", array( "username" => $this->username ) ); + exit( formatJSEND( "success", array( "username" => $this->username ) ) ); } else { - echo formatJSEND( "error", "The Username is Already Taken" ); + exit( formatJSEND( "error", "The Username is Already Taken" ) ); } } diff --git a/components/user/controller.php b/components/user/controller.php index 266d3a6..27c1cea 100755 --- a/components/user/controller.php +++ b/components/user/controller.php @@ -1,164 +1,190 @@ username = User::CleanUsername( $_POST['username'] ); - $User->password = $_POST['password']; - - // check if the asked languages exist and is registered in languages/code.php - require_once '../../languages/code.php'; - if (isset($languages[ $_POST['language'] ])) { - $User->lang = $_POST['language']; - } else { - $User->lang = 'en'; - } - - // theme - $User->theme = $_POST['theme']; - - $User->Authenticate(); +if( $_GET['action'] != 'authenticate' ) { + + checkSession(); } - ////////////////////////////////////////////////////////////////// - // Logout - ////////////////////////////////////////////////////////////////// +$User = new User(); -if ($_GET['action']=='logout') { +////////////////////////////////////////////////////////////////// +// Authenticate +////////////////////////////////////////////////////////////////// + +if($_GET['action']=='authenticate') { + + if( ! isset( $_POST['username'] ) || ! isset( $_POST['password'] ) ) { + + die( formatJSEND( "error", "Missing username or password" ) ); + } + + $User->username = User::CleanUsername( $_POST['username'] ); + $User->password = $_POST['password']; + + // check if the asked languages exist and is registered in languages/code.php + require_once '../../languages/code.php'; + if( isset( $languages[$_POST['language']] ) ) { + + $User->lang = $_POST['language']; + } else { + + $User->lang = 'en'; + } + + // theme + $User->theme = $_POST['theme']; + $User->Authenticate(); +} + +////////////////////////////////////////////////////////////////// +// Logout +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'logout' ) { logout(); } - ////////////////////////////////////////////////////////////////// - // Create User - ////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////// +// Create User +////////////////////////////////////////////////////////////////// -if ($_GET['action']=='create') { - if (checkAccess()) { - if (!isset($_POST['username']) || !isset($_POST['password'])) { - die(formatJSEND("error", "Missing username or password")); - } - - $User->username = User::CleanUsername( $_POST['username'] ); - $User->password = $_POST['password']; - $User->Create(); - } -} - - ////////////////////////////////////////////////////////////////// - // Delete User - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='delete') { - if (checkAccess()) { - if (!isset($_GET['username'])) { - die(formatJSEND("error", "Missing username")); - } - - $User->username = User::CleanUsername( $_GET['username'] ); - $User->Delete(); - } -} - - ////////////////////////////////////////////////////////////////// - // Change Password - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='password') { - if (!isset($_POST['username']) || !isset($_POST['password'])) { - die(formatJSEND("error", "Missing username or password")); - } - - if (checkAccess() || $_POST['username'] == $_SESSION['user']) { - $User->username = User::CleanUsername( $_POST['username'] ); - $User->password = $_POST['password']; - $User->Password(); - } -} - - ////////////////////////////////////////////////////////////////// - // Change Project - ////////////////////////////////////////////////////////////////// - -if ($_GET['action']=='project') { - if (!isset($_GET['project'])) { - die(formatJSEND("error", "Missing project")); - } - - $User->username = $_SESSION['user']; - $User->project = $_GET['project']; - $User->Project(); -} - - ////////////////////////////////////////////////////////////////// - // Search Users - ////////////////////////////////////////////////////////////////// - -if ( $_GET['action'] == 'search_users' ) { +if( $_GET['action'] == 'create' ) { - if ( ! isset( $_GET['search_term'] ) ) { + if( checkAccess() ) { + + if ( ! isset( $_POST['username'] ) || ! isset( $_POST['password'] ) ) { + + exit( formatJSEND( "error", "Missing username or password" ) ); + } + + if ( ! ( $_POST['password'] === $_POST['password2'] ) ) { + + exit( formatJSEND( "error", "Passwords do not match" ) ); + } + + if ( preg_match( '/[^\w\-\._@]/', $_POST['username'] ) ) { + + exit( formatJSEND( "error", "Invalid characters in username" ) ); + } + + $User->username = User::CleanUsername( $_POST['username'] ); + $User->password = $_POST['password']; + $User->Create(); + } +} + +////////////////////////////////////////////////////////////////// +// Delete User +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'delete' ) { + + if( checkAccess() ) { + + if( ! isset( $_GET['username'] ) ) { + + die( formatJSEND( "error", "Missing username" ) ); + } + + $User->username = User::CleanUsername( $_GET['username'] ); + $User->Delete(); + } +} + +////////////////////////////////////////////////////////////////// +// Change Password +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'password' ) { + + if( ! isset( $_POST['username']) || ! isset( $_POST['password'] ) ) { + + die( formatJSEND( "error", "Missing username or password" ) ); + } + + if( $_POST['username'] == $_SESSION['user'] || is_admin() ) { + + $User->username = User::CleanUsername( $_POST['username'] ); + $User->password = $_POST['password']; + $User->Password(); + } +} + +////////////////////////////////////////////////////////////////// +// Change Project +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'project' ) { + + if( ! isset( $_GET['project'] ) ) { + + die( formatJSEND( "error", "Missing project" ) ); + } + + $User->username = $_SESSION['user']; + $User->project = $_GET['project']; + $User->Project(); +} + +////////////////////////////////////////////////////////////////// +// Search Users +////////////////////////////////////////////////////////////////// + +if( $_GET['action'] == 'search_users' ) { + + if( ! isset( $_GET['search_term'] ) ) { die( formatJSEND( "error", "Missing search term" ) ); } + search_users( $_GET['search_term'], "exit", true ); } - ////////////////////////////////////////////////////////////////// - // Verify User Account - ////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////// +// Verify User Account +////////////////////////////////////////////////////////////////// -if ($_GET['action']=='verify') { - - $User->username = $_SESSION['user']; - //$User->Verify(); - checkSession(); +if( $_GET['action'] == 'verify' ) { + + $User->username = $_SESSION['user']; + checkSession(); } -if ( $_GET['action'] == 'update_access' ) { +if( $_GET['action'] == 'update_access' ) { checkSession(); - if ( ! isset( $_GET['access'] ) || ! isset( $_GET['username'] ) ) { + if( ! isset( $_GET['access'] ) || ! isset( $_GET['username'] ) ) { die( formatJSEND( "error", "Could not update access." ) ); } if( ! is_admin() ) { - die( formatJSEND( "error", "You do not have permission to update access." ) ); + die( formatJSEND( "error", "You do not have permission to update user's access." ) ); } $User->username = $_GET["username"]; - $User->access = $_GET["access"]; + $User->access = $_GET["access"]; $User->update_access(); } diff --git a/components/user/init.js b/components/user/init.js index a1a2cd2..97d6fa1 100755 --- a/components/user/init.js +++ b/components/user/init.js @@ -130,41 +130,39 @@ var _this = this; codiad.modal.load(400, this.dialog + '?action=create'); $('#modal-content form') - .live('submit', function(e) { - e.preventDefault(); - var pass = true; - var username = $('#modal-content form input[name="username"]') - .val(); - var password1 = $('#modal-content form input[name="password1"]') - .val(); - var password2 = $('#modal-content form input[name="password2"]') - .val(); + .live('submit', function(e) { + e.preventDefault(); + var pass = true; + var username = $('#modal-content form input[name="username"]') + .val(); + var password1 = $('#modal-content form input[name="password1"]') + .val(); + var password2 = $('#modal-content form input[name="password2"]') + .val(); + + // Check matching passwords + if(password1 != password2) { - // Check matching passwords - if(password1 != password2) { - codiad.message.error(i18n('Passwords Do Not Match')); - pass = false; - } + codiad.message.error(i18n('Passwords Do Not Match')); + pass = false; + } + + if( pass ) { - // Check no spaces in username - if(!/^[a-z0-9]+$/i.test(username) || username.length === 0) { - codiad.message.error(i18n('Username Must Be Alphanumeric String')); - pass = false; - } - - if(pass) { - $.post(_this.controller + '?action=create', { - 'username': username, - 'password': password1 - }, function(data) { - var createResponse = codiad.jsend.parse(data); - if(createResponse != 'error') { - codiad.message.success(i18n('User Account Created')) - _this.list(); - } - }); - } - }); + $.post( _this.controller + '?action=create', { + 'username': username, + 'password': password1, + 'password2': password2, + }, function(data) { + var createResponse = codiad.jsend.parse( data ); + if( createResponse != 'error' ) { + + codiad.message.success( i18n( 'User Account Created' ) ) + _this.list(); + } + }); + } + }); }, ////////////////////////////////////////////////////////////////// diff --git a/js/system.js b/js/system.js index 5773564..ebde2e3 100755 --- a/js/system.js +++ b/js/system.js @@ -135,12 +135,6 @@ }, success: function( data ) { - let response = codiad.jsend.parse( data ); - - if( response != 'error' ) { - - codiad.message.success( i18n( 'Created Default Tables' ) ); - } console.log( data ); }, error: function(jqXHR, textStatus, errorThrown) {