Merge branch 'permissions' into 'development'

Permissions

See merge request xevidos/codiad!13
This commit is contained in:
xevidos 2019-07-17 15:56:41 +00:00
commit 51a6642a4f
19 changed files with 1083 additions and 688 deletions

View File

@ -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;
@ -103,60 +107,25 @@ 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 ) {
public static function get_user_id( $username ) {
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." ) );
$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 ) ) {
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;
$user_id = $return["id"];
}
self::return( $return, $action );
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();
@ -168,25 +137,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 {
@ -564,47 +527,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 );
}
@ -651,19 +574,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

@ -227,4 +227,4 @@ switch( $action ) {
break;
}
exit( json_encode( $response ) );
exit( json_encode( $response ) );

View File

@ -457,35 +457,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.' ) );
}
}
@ -581,21 +587,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' ) {
@ -619,8 +630,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] );
}
@ -631,10 +645,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 ) {
@ -866,6 +880,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 + '"]' );

View File

@ -0,0 +1,159 @@
<?php
/*
* Copyright (c) Codiad & Kent Safranski (codiad.com), and Isaac Brown (telaaedifex.com), distributed
* as-is and without warranty under the MIT License. See
* [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(
"none" => 0,
"read" => 1,
"write" => 2,
"create" => 4,
"delete" => 8,
"manager" => 16,
"owner" => 32,
"admin" => 64,
);
function __construct() {
}
public static function check_access( $level, $user_level ) {
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." ) );
}
} else {
if( ! in_array( $level, self::LEVELS ) ) {
exit( formatJSEND( "error", "Access Level does not exist." ) );
}
}
return ( $user_level >= $level );
}
public static function check_path( $level, $path ) {
$user_level = self::get_access( $path );
return self::check_access( $level, $user_level );
}
public static function get_access( $path ) {
global $sql;
$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() );
if( ! empty( $projects ) ) {
foreach( $projects as $row => $data ) {
$full_project_path = Common::isAbsPath( $data["path"] ) ? $data["path"] : WORKSPACE . "/{$data["path"]}";
$path_postition = strpos( $full_path, $full_project_path );
if( $path_postition === false ) {
continue;
}
if( $data["owner"] == 'nobody' ) {
$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"], $data["owner"], $_SESSION["user"] );
if( $access > 0 ) {
break;
}
}
}
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 ) {
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 );
}
}
?>

View File

@ -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 = Permissions::LEVELS["read"];
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 = '';
@ -67,45 +68,76 @@ 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];
if( ! empty( $result ) ) {
$project = $sql->query( $query, $bind_variables, array(), "fetch" );
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 ) ) {
if( ! in_array( $this->user, $access ) ) {
array_push( $access, $this->user );
}
} else {
$access = array(
$this->user
);
}
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." );
}
}
}
public function check_duplicate( $full_path ) {
global $sql;
$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 ) {
@ -115,7 +147,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 ) ) {
@ -138,25 +170,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 );
}
@ -169,7 +188,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 ) ) {
@ -188,31 +207,65 @@ 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"] );
$return = $sql->query( $query, $bind_variables, array() )[0];
$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(), "fetch" );
if( ! empty( $return ) ) {
} else {
$return = formatJSEND( "error", "Error fetching projects." );
$return = formatJSEND( "error", "No projects found." );
}
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", "No projects found." );
}
} else {
$return = formatJSEND( "error", "Only admins are allowed to view all projects." );
}
return( $return );
}
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 id IN ( SELECT project FROM access WHERE user = ? );";
$bind_variables = array( $_SESSION["user"], $_SESSION["user_id"] );
$return = $sql->query( $query, $bind_variables, array() );
if( empty( $return ) ) {
$return = formatJSEND( "error", "Error fetching projects." );
$return = formatJSEND( "error", "No projects found." );
}
return( $return );
@ -221,42 +274,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." ) );
}
}
@ -337,9 +372,16 @@ 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"] . '"%' );
$return = $sql->query( $query, $bind_variables, array() )[0];
$query = "
SELECT * FROM projects
WHERE path = ?
AND (
owner=?
OR owner='nobody'
OR id IN ( SELECT project FROM access WHERE user = ? )
) ORDER BY name LIMIT 1;";
$bind_variables = array( $this->path, $_SESSION["user"], $_SESSION["user_id"] );
$return = $sql->query( $query, $bind_variables, array(), "fetch" );
if( ! empty( $return ) ) {
@ -348,6 +390,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 {
@ -361,7 +404,7 @@ class Project extends Common {
//////////////////////////////////////////////////////////////////
public function Create() {
if ( $this->name != '' && $this->path != '' ) {
$this->path = $this->cleanPath();
@ -372,24 +415,27 @@ 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( $this->path );
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 );
if( ! is_dir( WORKSPACE . '/' . $this->path ) ) {
mkdir( WORKSPACE . '/' . $this->path );
}
} else {
if( ! is_admin() ) {
@ -407,7 +453,7 @@ class Project extends Common {
$allowed = true;
}
}
if ( ! $allowed) {
if ( ! $allowed ) {
die( formatJSEND( "error", "Absolute Path Only Allowed for " . WHITEPATHS ) );
}
@ -443,18 +489,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 +541,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 );
$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
//////////////////////////////////////////////////////////////////

View File

@ -32,7 +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 ) ) ) {
exit( formatJSEND( "error", "No access set." ) );
} else {
$Project->access = Permissions::LEVELS[$_GET['access']];
}
if( isset( $_GET['username'] ) && ! in_array( $_GET['username'], $invalid_users ) ) {
$Project->user = $_GET['username'];
} else {
@ -65,7 +73,7 @@ if( $_GET['action'] == 'add_user' ) {
//////////////////////////////////////////////////////////////////
if( $_GET['action'] == 'create' ) {
$Project->name = $_GET['project_name'];
if( $_GET['public_project'] == 'true' ) {
@ -110,7 +118,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();
@ -123,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 );
}
@ -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'] ) );
}
@ -205,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 ) ) {
@ -214,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 ) ) {
@ -223,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." ) );
}
}
@ -233,7 +246,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" ) );
}

View File

@ -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();
}
?>
<label><?php i18n("Project List"); ?></label>
<div id="project-list">
@ -72,56 +77,63 @@ switch( $_GET['action'] ) {
<div class="project-wrapper">
<table width="100%" style="word-wrap: break-word;word-break: break-all;">
<?php
foreach( $projects as $project => $data ) {
if( is_array( $projects ) ) {
$show = true;
if( $show ) {
foreach( $projects as $project => $data ) {
?>
<tr>
<td width="70"><a onclick="codiad.project.open('<?php echo( $data['path'] );?>');" class="icon-folder bigger-icon"></a></td>
<td width="150"><?php echo($data['name']);?></td>
<td width="250"><?php echo($data['path']);?></td>
<?php
$owner = $Project->get_owner( $data['path'] );
if( $owner == 'nobody' ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Public projects can not be managed'));" class="icon-block bigger-icon"></a></td>
<?php
} elseif( $owner !== $_SESSION["user"] ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Projects owned by others can not be managed'));" class="icon-block bigger-icon"></a></td>
<?php
} else {
?>
<td width="70"><a onclick="codiad.project.manage_access( '<?php echo( $data['path'] );?>' );" class="icon-lock bigger-icon"></a></td>
<?php
}
$show = true;
if( $show ) {
?>
<tr>
<td width="70"><a onclick="codiad.project.open('<?php echo( $data['path'] );?>');" class="icon-folder bigger-icon"></a></td>
<td width="150"><?php echo($data['name']);?></td>
<td width="250"><?php echo($data['path']);?></td>
<?php
$owner = $Project->get_owner( $data['path'] );
if( $owner == 'nobody' ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Public projects can not be managed'));" class="icon-block bigger-icon"></a></td>
<?php
} elseif( $owner !== $_SESSION["user"] ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Projects owned by others can not be managed'));" class="icon-block bigger-icon"></a></td>
<?php
} else {
?>
<td width="70"><a onclick="codiad.project.manage_access( '<?php echo( $data['path'] );?>' );" class="icon-lock bigger-icon"></a></td>
<?php
}
?>
<?php
if( $_SESSION['project'] == $data['path'] ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Active Project Cannot Be Removed'));" class="icon-block bigger-icon"></a></td>
<?php
} elseif( $owner !== $_SESSION["user"] && $owner !== 'nobody' ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Projects owned by others can not be deleted'));" class="icon-block bigger-icon"></a></td>
<?php
} else {
?>
<td width="70"><a onclick="codiad.project.delete('<?php echo($data['name']);?>','<?php echo($data['path']);?>');" class="icon-cancel-circled bigger-icon"></a></td>
<?php
}
?>
</tr>
<?php
if( $_SESSION['project'] == $data['path'] ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Active Project Cannot Be Removed'));" class="icon-block bigger-icon"></a></td>
<?php
} elseif( $owner !== $_SESSION["user"] ) {
?>
<td width="70"><a onclick="codiad.message.error(i18n('Projects owned by others can not be deleted'));" class="icon-block bigger-icon"></a></td>
<?php
} else {
?>
<td width="70"><a onclick="codiad.project.delete('<?php echo($data['name']);?>','<?php echo($data['path']);?>');" class="icon-cancel-circled bigger-icon"></a></td>
<?php
}
?>
</tr>
<?php
}
}
} else {
$error = json_decode( $projects, true );
echo $error["message"];
}
?>
</table>
@ -204,11 +216,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 +229,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>
@ -233,15 +246,42 @@ switch( $_GET['action'] ) {
?>
<table id="access_list">
<?php
foreach( $access as $user ) {
$user = null;
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>
<button class="btn-left" onclick="codiad.project.remove_user( '<?php echo htmlentities( $user );?>' );">Remove Access</button>
<select onchange="codiad.project.change_access( event );">
<?php
foreach( Permissions::LEVELS as $level => $id ) {
if( $id == $user_permissions["level"] ) {
$selected = "selected='selected'";
} else {
$selected = "";
}
?><option value="<?php echo $level;?>" <?php echo $selected;?>><?php echo ucfirst( $level );?></option><?php
}
?>
</select>
<button class="btn-left" onclick="codiad.project.remove_user( '<?php echo htmlentities( $user["username"] );?>' );">Remove Access</button>
</td>
</tr>
<?php

View File

@ -53,26 +53,42 @@
add_user: function() {
var _this = this;
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();
username = $( '#modal-content form select[name="user_list"]' ).val();
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 ), 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 project_id = $( '#modal-content form input[name="project_id"]' ).val();
let access = $( e.target ).children( "option:selected" ).val();
console.log( access, username, project_path, project_id );
$.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 );
if ( response != 'error' ) {
codiad.project.manage_access( project_path );
}
});
},
//////////////////////////////////////////////////////////////////
// Create Project
@ -233,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.
*/
@ -290,7 +312,7 @@
//////////////////////////////////////////////////////////////////
manage_access: function( path ) {
var _this = this;
$( '#modal-content form' )
@ -307,7 +329,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' ) {
@ -353,20 +376,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

@ -1,6 +1,7 @@
<?php
require_once( __DIR__ . "/class.sql.conversions.php" );
require_once( __DIR__ . "/../permissions/class.permissions.php" );
class sql {
@ -35,8 +36,11 @@ class sql {
$dbtype = DBTYPE;
$username = DBUSER;
$password = DBPASS;
$options = array(
PDO::ATTR_ERRMODE => 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 );
@ -50,7 +54,7 @@ class sql {
public function create_default_tables() {
$result = $this->create_tables(
$create_tables = $this->create_tables(
array(
"active" => array(
"fields" => array(
@ -60,11 +64,23 @@ 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" ),
)
),
"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,9 +116,8 @@ class sql {
"username" => "string",
"password" => "text",
"email" => "string",
"project" => "string",
"project" => "int",
"access" => "string",
"groups" => "string",
"token" => "string",
),
"attributes" => array(
@ -130,8 +143,12 @@ class sql {
),
)
);
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 ) {
@ -169,18 +186,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() ) . "<br>";
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 +241,198 @@ class sql {
$query = $this->conversions->update( $table, $fields, $where );
//echo var_dump( $query ) . "<br>";
//return $query;
}
public function query( $query, $bind_variables, $default, $action='fetchAll', $show_errors=false ) {
public function update_table_structure() {
$connection = $this->connect();
$statement = $connection->prepare( $query );
$statement->execute( $bind_variables );
switch( $action ) {
$status_updates = array();
$sql_conversions = new sql_conversions();
try {
case( 'rowCount' ):
$return = $statement->rowCount();
break;
$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"];
case( 'fetchAll' ):
foreach( $users as $row => $user ) {
$return = $statement->fetchAll( \PDO::FETCH_ASSOC );
break;
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 ),";
}
}
}
}
case( 'fetchColumn' ):
if( $access_query !== "INSERT INTO access( project, user, level ) VALUES " ) {
$return = $statement->fetchColumn();
break;
$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 ) {
default:
$return = $statement->fetchAll( \PDO::FETCH_ASSOC );
break;
//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."
);
}
$error = $statement->errorInfo();
if( ! $error[0] == "00000" ) {
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" ) {
/**
* Errors:
* default - this value could be anything such as true or foobar
* message
* exception
*/
try {
$connection = $this->connect();
$statement = $connection->prepare( $query );
$statement->execute( $bind_variables );
switch( $action ) {
case( 'rowCount' ):
$return = $statement->rowCount();
break;
case( 'fetch' ):
$return = $statement->fetch( \PDO::FETCH_ASSOC );
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 );
}

View File

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

View File

@ -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();
}
@ -176,7 +177,13 @@ 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 ) ) ) {
$this->$upgrade_function();
}
}
function check_update() {
@ -453,7 +460,6 @@ class updater {
$this->backup();
try {
$sessions = "../../data/sessions";

View File

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

View File

@ -1,164 +1,190 @@
<?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.user.php');
require_once('../../common.php');
require_once('class.user.php');
if (!isset($_GET['action'])) {
die(formatJSEND("error", "Missing parameter"));
}
//////////////////////////////////////////////////////////////////
// Verify Session or Key
//////////////////////////////////////////////////////////////////
if ($_GET['action']!='authenticate') {
checkSession();
if( ! isset( $_GET['action'] ) ) {
die( formatJSEND( "error", "Missing parameter" ) );
}
$User = new User();
//////////////////////////////////////////////////////////////////
// Verify Session or Key
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// 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();
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();
}

View File

@ -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();
}
});
}
});
},
//////////////////////////////////////////////////////////////////

View File

@ -126,7 +126,7 @@
create_default_tables: function() {
jQuery.ajax({
url: this.controller,
type: "POST",
dataType: 'html',
@ -135,15 +135,6 @@
},
success: function( data ) {
let response = codiad.jsend.parse( data );
if( response.status != 'error' ) {
codiad.message.success( i18n( 'Created Default Tables' ) );
} else {
codiad.message.error( i18n( 'Error Creating Default Tables' ) );
}
console.log( data );
},
error: function(jqXHR, textStatus, errorThrown) {