mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-06-20 18:08:02 +02:00
- new registry attribute "file_access_user" to signal "file_access" method understands new 4th parameter $user
- infolog implementation for it --> allows to check if a given user has access to a files of app/id
This commit is contained in:
parent
9bcc95b3d7
commit
04be4c57fe
@ -290,25 +290,35 @@ class infolog_bo
|
||||
* @param int|array $info data or info_id of infolog entry to check
|
||||
* @param int $required_rights EGW_ACL_{READ|EDIT|ADD|DELETE}
|
||||
* @param int $other uid to check (if info==0) or 0 to check against $this->user
|
||||
* @param int $user=null user whos rights to check, default current user
|
||||
* @return boolean
|
||||
*/
|
||||
function check_access($info,$required_rights,$other=0)
|
||||
function check_access($info,$required_rights,$other=0,$user=null)
|
||||
{
|
||||
static $cache = array();
|
||||
|
||||
if (!$user) $user = $this->user;
|
||||
if ($user == $this->user)
|
||||
{
|
||||
$grants = $this->grants;
|
||||
$access =& $cache[$info_id][$required_rights]; // we only cache the current user!
|
||||
}
|
||||
else
|
||||
{
|
||||
$grants = $GLOBALS['egw']->acl->get_grants('infolog',$this->group_owners ? $this->group_owners : true,$user);
|
||||
}
|
||||
|
||||
if (!$info)
|
||||
{
|
||||
$owner = $other ? $other : $this->user;
|
||||
$grants = $this->grants[$owner];
|
||||
return $grants & $required_rights;
|
||||
$owner = $other ? $other : $user;
|
||||
$grant = $grants[$owner];
|
||||
return $grant & $required_rights;
|
||||
}
|
||||
|
||||
$info_id = is_array($info) ? $info['info_id'] : $info;
|
||||
|
||||
if (isset($cache[$info_id][$required_rights]))
|
||||
if (!isset($access))
|
||||
{
|
||||
return $cache[$info_id][$required_rights];
|
||||
}
|
||||
// handle delete for the various history modes
|
||||
if ($this->history)
|
||||
{
|
||||
@ -318,25 +328,35 @@ class infolog_bo
|
||||
($required_rights == EGW_ACL_EDIT || // no edit rights for deleted entries
|
||||
$required_rights == EGW_ACL_ADD || // no add rights for deleted entries
|
||||
$required_rights == EGW_ACL_DELETE && ($this->history == 'history_no_delete' || // no delete at all!
|
||||
$this->history == 'history_admin_delete' && !isset($GLOBALS['egw_info']['user']['apps']['admin'])))) // delete only for admins
|
||||
$this->history == 'history_admin_delete' && (!isset($GLOBALS['egw_info']['user']['apps']['admin']) || $user!=$this->user)))) // delete only for admins
|
||||
{
|
||||
return $cache[$info_id][$required_rights] = false;
|
||||
$access = false;
|
||||
}
|
||||
if ($required_rights == EGW_ACL_UNDELETE)
|
||||
elseif ($required_rights == EGW_ACL_UNDELETE)
|
||||
{
|
||||
if ($info['info_status'] != 'deleted')
|
||||
{
|
||||
return $cache[$info_id][$required_rights] = false; // can only undelete deleted items
|
||||
$access = false; // can only undelete deleted items
|
||||
}
|
||||
else
|
||||
{
|
||||
// undelete requires edit rights
|
||||
return $cache[$info_id][$required_rights] = $this->so->check_access( $info,EGW_ACL_EDIT,$this->implicit_rights == 'edit' );
|
||||
$access = $this->so->check_access( $info,EGW_ACL_EDIT,$this->implicit_rights == 'edit',$grants,$user );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($required_rights == EGW_ACL_UNDELETE)
|
||||
{
|
||||
return $cache[$info_id][$required_rights] = false;
|
||||
$access = false;
|
||||
}
|
||||
return $cache[$info_id][$required_rights] = $this->so->check_access( $info,$required_rights,$this->implicit_rights == 'edit' );
|
||||
if (!isset($access))
|
||||
{
|
||||
$access = $this->so->check_access( $info,$required_rights,$this->implicit_rights == 'edit',$grants,$user );
|
||||
}
|
||||
}
|
||||
// else $cached = ' (from cache)';
|
||||
// error_log(__METHOD__."($info_id,$required_rights,$other,$user) returning$cached ".array2string($access));
|
||||
return $access;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1204,11 +1224,13 @@ class infolog_bo
|
||||
*
|
||||
* @param int|array $id id of entry or entry array
|
||||
* @param int $check EGW_ACL_READ for read and EGW_ACL_EDIT for write or delete access
|
||||
* @param string $rel_path=null currently not used in InfoLog
|
||||
* @param int $user=null for which user to check, default current user
|
||||
* @return boolean true if access is granted or false otherwise
|
||||
*/
|
||||
function file_access($id,$check,$rel_path=null)
|
||||
function file_access($id,$check,$rel_path=null,$user=null)
|
||||
{
|
||||
return $this->check_access($id,$check);
|
||||
return $this->check_access($id,$check,0,$user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,6 +63,7 @@ class infolog_hooks
|
||||
'add_id' => 'action_id',
|
||||
'add_popup' => '750x550',
|
||||
'file_access'=> 'infolog.infolog_bo.file_access',
|
||||
'file_access_user' => true, // file_access supports 4th parameter $user
|
||||
'edit' => array(
|
||||
'menuaction' => 'infolog.infolog_ui.edit',
|
||||
),
|
||||
|
@ -83,13 +83,16 @@ class infolog_so
|
||||
* @param array $info infolog entry as array
|
||||
* @return boolean
|
||||
*/
|
||||
function is_responsible($info)
|
||||
function is_responsible($info,$user=null)
|
||||
{
|
||||
static $user_and_memberships;
|
||||
if (is_null($user_and_memberships))
|
||||
if (!$user) $user = $this->user;
|
||||
|
||||
static $um_cache = array();
|
||||
$user_and_memberships =& $um_cache[$user];
|
||||
if (!isset($user_and_memberships))
|
||||
{
|
||||
$user_and_memberships = $GLOBALS['egw']->accounts->memberships($this->user,true);
|
||||
$user_and_memberships[] = $this->user;
|
||||
$user_and_memberships = $GLOBALS['egw']->accounts->memberships($user,true);
|
||||
$user_and_memberships[] = $user;
|
||||
}
|
||||
return $info['info_responsible'] && array_intersect((array)$info['info_responsible'],$user_and_memberships);
|
||||
}
|
||||
@ -100,10 +103,15 @@ class infolog_so
|
||||
* @param array|int $info data or info_id of InfoLog entry
|
||||
* @param int $required_rights EGW_ACL_xyz anded together
|
||||
* @param boolean $implicit_edit=false responsible has only implicit read and add rigths, unless this is set to true
|
||||
* @param array $grants=null grants to use, default (null) $this->grants
|
||||
* @param int $user=null user to check, default (null) $this->user
|
||||
* @return boolean True if access is granted else False
|
||||
*/
|
||||
function check_access( $info,$required_rights,$implicit_edit=false )
|
||||
function check_access( $info,$required_rights,$implicit_edit=false,array $grants=null,$user=null )
|
||||
{
|
||||
if (is_null($grants)) $grants = $this->grants;
|
||||
if (!$user) $user = $this->user;
|
||||
|
||||
if (is_array($info))
|
||||
{
|
||||
|
||||
@ -125,14 +133,14 @@ class infolog_so
|
||||
}
|
||||
$owner = $info['info_owner'];
|
||||
|
||||
$access_ok = $owner == $this->user || // user has all rights
|
||||
$access_ok = $owner == $user || // user has all rights
|
||||
// ACL only on public entrys || $owner granted _PRIVATE
|
||||
(!!($this->grants[$owner] & $required_rights) ||
|
||||
$this->is_responsible($info) && // implicite rights for responsible user(s) and his memberships
|
||||
(!!($grants[$owner] & $required_rights) ||
|
||||
$this->is_responsible($info,$user) && // implicite rights for responsible user(s) and his memberships
|
||||
($required_rights == EGW_ACL_READ || $required_rights == EGW_ACL_ADD || $implicit_edit && $required_rights == EGW_ACL_EDIT)); // &&
|
||||
//($info['info_access'] == 'public' || !!($this->grants[$this->user] & EGW_ACL_PRIVATE));
|
||||
|
||||
//echo "<p align=right>check_access(info_id=".$info['info_id'].",required=$required_rights,implicit_edit=$implicit_edit) owner=$owner, responsible=(".implode(',',$info['info_responsible'])."): access".($access_ok?"Ok":"Denied")."</p>\n";
|
||||
// error_log(__METHOD__."($info[info_id],$required_rights,$implicit_edit,".array2string($grants).",$user) returning ".array2string($access_ok));
|
||||
return $access_ok;
|
||||
}
|
||||
|
||||
|
@ -57,8 +57,10 @@
|
||||
* 'add_id' => 'link_id', // --------------------- " ------------------- id
|
||||
* 'add_popup' => '400x300', // size of popup (XxY), if add is in popup
|
||||
* 'notify' => 'app.class.method', // method to be called if an other applications liks or unlinks with app: notify(array $data)
|
||||
* 'file_access' => 'app.class.method', // method to be called to check file access rights, see links_stream_wrapper class
|
||||
* // boolean file_access(string $id,int $check,string $rel_path)
|
||||
* 'file_access' => 'app.class.method', // method to be called to check file access rights of a given user, see links_stream_wrapper class
|
||||
* // boolean file_access(string $id,int $check,string $rel_path=null,int $user=null)
|
||||
* 'file_access_user' => false, // true if file_access method supports 4th parameter $user, if app is NOT supporting it
|
||||
* // egw_link::file_access() returns false for $user != current user!
|
||||
* 'find_extra' => array('name_preg' => '/^(?!.picture.jpg)$/') // extra options to egw_vfs::find, to eg. remove some files from the list of attachments
|
||||
* 'edit' => array(
|
||||
* 'menuaction' => 'app.class.method',
|
||||
@ -1234,32 +1236,46 @@ class egw_link extends solink
|
||||
* @param string $app app-name or null to delete the whole cache
|
||||
* @param int|string $id id or null to delete only file_access cache of given app (keeps title cache, if app implements file_access!)
|
||||
*/
|
||||
public static function delete_cache($app,$id)
|
||||
private static function delete_cache($app,$id)
|
||||
{
|
||||
if (empty($app) || empty($id))
|
||||
{
|
||||
self::$file_access_cache = array();
|
||||
if (empty($app) || !self::get_registry($app, 'file_access'))
|
||||
{
|
||||
self::$title_cache = array();
|
||||
}
|
||||
}
|
||||
unset(self::$title_cache[$app.':'.$id]);
|
||||
unset(self::$file_access_cache[$app.':'.$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the file access perms for $app/id
|
||||
* Check the file access perms for $app/id and given user $user
|
||||
*
|
||||
* If $user given and != current user AND app does not set file_access_user=true,
|
||||
* allways return false, as there's no way to check access for an other user!
|
||||
*
|
||||
* @ToDo $rel_path is not yet implemented, as no app use it currently
|
||||
* @param string $app
|
||||
* @param string|int $id id of entry
|
||||
* @param int $required=EGW_ACL_READ EGW_ACL_{READ|EDIT}
|
||||
* @param string $rel_path
|
||||
* @return boolean
|
||||
* @param string $rel_path=null
|
||||
* @param int $user=null default null = current user
|
||||
* @return boolean true if access granted, false otherwise
|
||||
*/
|
||||
static function file_access($app,$id,$required=EGW_ACL_READ,$rel_path=null)
|
||||
static function file_access($app,$id,$required=EGW_ACL_READ,$rel_path=null,$user=null)
|
||||
{
|
||||
// are we called for an other user
|
||||
if ($user && $user != self::$user)
|
||||
{
|
||||
// check if app supports file_access WITH 4th $user parameter --> return false if not
|
||||
if (!self::get_registry($app,'file_access_user') || !($method = self::get_registry($app,'file_access')))
|
||||
{
|
||||
$ret = false;
|
||||
$err = "(no file_access_user)";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = ExecMethod2($method,$id,$required,$rel_path,$user);
|
||||
$err = "(from $method)";
|
||||
}
|
||||
//error_log(__METHOD__."('$app',$id,$required,'$rel_path',$user) returning $err ".array2string($ret));
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$cache =& self::get_cache($app,$id,'file_access');
|
||||
|
||||
if (!isset($cache) || $required == EGW_ACL_EDIT && !($cache & $required))
|
||||
|
@ -59,26 +59,6 @@ class links_stream_wrapper extends links_stream_wrapper_parent
|
||||
*/
|
||||
const DEBUG = false;
|
||||
|
||||
/**
|
||||
* Clears our stat-cache
|
||||
*
|
||||
* Normaly not necessary, as it is automatically cleared/updated, UNLESS egw_vfs::$user changes!
|
||||
*
|
||||
* We have to clear file_access cache of egw_link, as our ACL depends on it!
|
||||
*
|
||||
* @param string $path='/apps' to be able to clear only file_access cache of a certain app
|
||||
*/
|
||||
public static function clearstatcache($path='/apps')
|
||||
{
|
||||
//error_log(__METHOD__."('$path')");
|
||||
if ($path[0] != '/') $path = parse_url($path, PHP_URL_PATH);
|
||||
list(,,$app) = explode('/',$path);
|
||||
egw_link::delete_cache($app, null); // null = delete only file_access cache, if app implements it, otherwise title cache is deleted too
|
||||
|
||||
// need to call sqlfs clearstatcache too
|
||||
parent::clearstatcache($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ACL based on the access of the user to the entry the files are linked to.
|
||||
*
|
||||
@ -119,9 +99,9 @@ class links_stream_wrapper extends links_stream_wrapper_parent
|
||||
{
|
||||
// vfs & stream-wrapper use posix rights, egw_link::file_access uses EGW_ACL_{EDIT|READ}!
|
||||
$required = $check & egw_vfs::WRITABLE ? EGW_ACL_EDIT : EGW_ACL_READ;
|
||||
$access = egw_link::file_access($app,$id,$required,$rel_path);
|
||||
$access = egw_link::file_access($app,$id,$required,$rel_path,egw_vfs::$user);
|
||||
}
|
||||
if (self::DEBUG) error_log(__METHOD__."($url,$check) ".($access?"access granted ($app:$id:$rel_path)":'no access!!!'));
|
||||
if (self::DEBUG) error_log(__METHOD__."($url,$check) user={egw_vfs::$user} ".($access?"access granted ($app:$id:$rel_path)":'no access!!!'));
|
||||
return $access;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user