Continued work on new permissions system, Fixed active file listings bug

This commit is contained in:
xevidos 2019-07-02 16:46:32 -04:00
parent d3d96e66f6
commit 492e372c5d
14 changed files with 447 additions and 399 deletions

View File

@ -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 ); }
?>

View File

@ -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
//////////////////////////////////////////////////////////////////

View File

@ -1,94 +1,101 @@
<?php
/*
* Copyright (c) Codiad & Kent Safranski (codiad.com), distributed
* as-is and without warranty under the MIT License. See
* [root]/license.txt for more. This information must remain intact.
*/
/*
* Copyright (c) Codiad & Kent Safranski (codiad.com), distributed
* as-is and without warranty under the MIT License. See
* [root]/license.txt for more. This information must remain intact.
*/
require_once('../../common.php');
require_once('class.active.php');
require_once('../../common.php');
require_once('class.active.php');
$Active = new Active();
$Active = new Active();
//////////////////////////////////////////////////////////////////
// Verify Session or Key
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Verify Session or Key
//////////////////////////////////////////////////////////////////
checkSession();
checkSession();
//////////////////////////////////////////////////////////////////
// Get user's active files
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Get user's active files
//////////////////////////////////////////////////////////////////
if ($_GET['action']=='list') {
$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();
}
//////////////////////////////////////////////////////////////////
// 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"] );
}

View File

@ -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 ) {

View File

@ -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 {

View File

@ -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";

View File

@ -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':

View File

@ -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 ) {

View File

@ -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 ) {

View File

@ -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." ) );
}
}

View File

@ -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." ) );
}
}

View File

@ -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 );
?>
<form>
<input type="hidden" name="project_path" value="<?php echo( $path );?>">
<form onSubmit="event.preventDefault();">
<input type="hidden" name="project_path" value="<?php echo $path;?>">
<input type="hidden" name="project_id" value="<?php echo $project["id"];?>">
<label><span class="icon-pencil"></span><?php i18n( "Add Users" );?></label>
<input id="search_users" type="text" onkeyup="codiad.project.search_users();" />
<select id="user_list" name="user_list">
@ -216,14 +217,14 @@ switch( $_GET['action'] ) {
foreach( $users as $user ) {
?>
<option value="<?php echo htmlentities( $user );?>"><?php echo htmlentities( $user );?></option>
<option value="<?php echo htmlentities( $user["username"] );?>"><?php echo htmlentities( $user["username"] );?></option>
<?php
}
?>
</select>
<button class="btn-left" onclick="codiad.project.add_user();">Add User</button>
<?php
if( $access == null ) {
if( $access == null || empty( $access ) ) {
?>
<p>No users have been given access.</p>
@ -234,30 +235,30 @@ switch( $_GET['action'] ) {
<table id="access_list">
<?php
$is_assoc = ( array_keys( $access ) !== range( 0, count( $access ) - 1 ) );
if( ! $is_assoc ) {
$temp = array();
foreach( $access as $user ) {
$temp[$user] = "delete";
}
$access = $temp;
}
$user = null;
foreach( $access as $user => $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;
}
}
?>
<tr>
<td>
<p><?php echo htmlentities( $user );?></p>
<p><?php echo htmlentities( $user["username"] );?></p>
</td>
<td>
<select onchange="codiad.project.change_access( event );">
<?php
foreach( Permissions::LEVELS as $level => $id ) {
if( $level == $access_level ) {
if( $id == $user_permissions["level"] ) {
$selected = "selected='selected'";
} else {
@ -268,7 +269,7 @@ switch( $_GET['action'] ) {
}
?>
</select>
<button class="btn-left" onclick="codiad.project.remove_user( '<?php echo htmlentities( $user );?>' );">Remove Access</button>
<button class="btn-left" onclick="codiad.project.remove_user( '<?php echo htmlentities( $user["username"] );?>' );">Remove Access</button>
</td>
</tr>
<?php

View File

@ -54,22 +54,18 @@
add_user: function() {
let _this = this;
let username = $( '#modal-content form select[name="user_list"]' ).val();
let project_path = $( '#modal-content form input[name="project_path"]' ).val();
let project_id = $( '#modal-content form input[name="project_id"]' ).val();
$( '#modal-content form' ).live( 'submit', function( e ) {
e.preventDefault();
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 ) + '&project_id=' + encodeURIComponent( project_id ) + '&username=' + encodeURIComponent( username ) + '&access=delete', 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 );
}
});
},
@ -78,11 +74,12 @@
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 project_id = $( '#modal-content form input[name="project_id"]' ).val();
let access = $( e.target ).children( "option:selected" ).val();
console.log( access, username, project_path );
console.log( access, username, project_path, project_id );
$.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&username=' + encodeURIComponent( username ) + '&access=' + encodeURIComponent( access ), function( data ) {
$.get( _this.controller + '?action=add_user&project_path=' + encodeURIComponent( project_path ) + '&project_id=' + encodeURIComponent( project_id ) + '&username=' + encodeURIComponent( username ) + '&access=' + encodeURIComponent( access ), function( data ) {
let response = codiad.jsend.parse( data );
console.log( response );
@ -309,7 +306,7 @@
//////////////////////////////////////////////////////////////////
manage_access: function( path ) {
var _this = this;
$( '#modal-content form' )
@ -326,7 +323,8 @@
var _this = this;
codiad.finder.contractFinder();
$.get( this.controller + '?action=open&path=' + encodeURIComponent( path ), function( data ) {
console.log( data );
var projectInfo = codiad.jsend.parse(data);
if ( projectInfo != 'error' ) {
@ -372,20 +370,17 @@
var _this = this;
$( '#modal-content form' ).live( 'submit', function( e ) {
let project_path = $( '#modal-content form input[name="project_path"]' ).val();
let project_id = $( '#modal-content form input[name="project_id"]' ).val();
e.preventDefault();
project_path = $( '#modal-content form input[name="project_path"]' ).val()
$.get( _this.controller + '?action=remove_user&project_path=' + encodeURIComponent( project_path ) + '&username=' + encodeURIComponent( user ), function( data ) {
$.get( _this.controller + '?action=remove_user&project_path=' + encodeURIComponent( project_path ) + '&project_id=' + encodeURIComponent( project_id ) + '&username=' + encodeURIComponent( user ), function( data ) {
response = codiad.jsend.parse( data );
console.log( response );
if ( response != 'error' ) {
response = codiad.jsend.parse( data );
console.log( response );
if ( response != 'error' ) {
codiad.project.manage_access( project_path );
}
});
codiad.project.manage_access( project_path );
}
});
},

View File

@ -342,6 +342,11 @@ class sql {
$return = $statement->rowCount();
break;
case( 'fetch' ):
$return = $statement->fetch( \PDO::FETCH_ASSOC );
break;
case( 'fetchAll' ):
$return = $statement->fetchAll( \PDO::FETCH_ASSOC );