forked from extern/egroupware
sharing ACL: need explicit new ACL or edit rights, to share into an addressbook
This commit is contained in:
parent
6b57ddac00
commit
ff91be903a
@ -471,6 +471,7 @@ class addressbook_hooks
|
||||
Acl::EDIT => 'edit',
|
||||
Acl::ADD => 'add',
|
||||
Acl::DELETE => 'delete',
|
||||
Acl::CUSTOM1 => 'shared with', // allows to share into given AB
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2093,6 +2093,8 @@ class addressbook_ui extends addressbook_bo
|
||||
];
|
||||
}
|
||||
unset($content['shared_values']);
|
||||
// remove invalid shared-with entries (should not happen, as we validate already on client-side)
|
||||
$this->check_shared_with($content['shared']);
|
||||
|
||||
$button = @key($content['button']);
|
||||
unset($content['button']);
|
||||
@ -2440,6 +2442,8 @@ class addressbook_ui extends addressbook_bo
|
||||
];
|
||||
}
|
||||
$content['shared_values'] = array_keys($content['shared_options']);
|
||||
// disable shared with UI for non-SQL backends
|
||||
$content['shared_disabled'] = !is_a($this->get_backend($content['id'], $content['owner']), Api\Contacts\Sql::class);
|
||||
|
||||
if ($content['id'])
|
||||
{
|
||||
@ -2643,6 +2647,46 @@ class addressbook_ui extends addressbook_bo
|
||||
return $this->tmpl->exec('addressbook.addressbook_ui.edit', $content, $sel_options, $readonlys, $preserve, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has right to share with / into given AB
|
||||
*
|
||||
* @param array $_data values for keys "shared_writable" and "shared_values"
|
||||
* @return array of entries removed from $shared_with because current user is not allowed to share into
|
||||
*/
|
||||
public function ajax_check_shared(array $_data)
|
||||
{
|
||||
$response = Api\Json\Response::get();
|
||||
try {
|
||||
$shared = [];
|
||||
foreach($_data['shared_values'] as $value)
|
||||
{
|
||||
if (is_numeric($value))
|
||||
{
|
||||
$shared[$value] = [
|
||||
'shared_with' => $value,
|
||||
'shared_by' => $this->user,
|
||||
'shared_writable' => (int)$_data['shared_writable'],
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$shared[$value] = array_combine(['shared_id', 'shared_with', 'shared_by', 'shared_writable'], explode(':', $value));
|
||||
}
|
||||
}
|
||||
if (($failed = $this->check_shared_with($shared)))
|
||||
{
|
||||
$response->data(array_keys($failed));
|
||||
$response->message(lang('You are not allowed to share into the addressbook of %1',
|
||||
implode(', ', array_map(function ($data) {
|
||||
return Api\Accounts::username($data['shared_with']);
|
||||
}, $failed))), 'error');
|
||||
}
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$response->message($e->getMessage(), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the readonlys for non-admins editing their own account
|
||||
*
|
||||
|
@ -1206,6 +1206,27 @@ var AddressbookApp = /** @class */ (function (_super) {
|
||||
app.status.makeCall(data);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Check if new shared_with value is allowed / user has rights to share into that AB
|
||||
*
|
||||
* Remove the entry again, if user is not allowed
|
||||
*/
|
||||
AddressbookApp.prototype.shared_changed = function () {
|
||||
var _a;
|
||||
var shared = this.et2.getInputWidgetById('shared_values');
|
||||
var value = (_a = shared) === null || _a === void 0 ? void 0 : _a.get_value();
|
||||
if (value) {
|
||||
this.egw.json('addressbook.addressbook_ui.ajax_check_shared', [{
|
||||
shared_values: value,
|
||||
shared_writable: this.et2.getInputWidgetById('shared_writable').get_value()
|
||||
}], function (_data) {
|
||||
if (Array.isArray(_data) && _data.length) {
|
||||
// remove not allowed entries
|
||||
shared.set_value(value.filter(function (val) { return _data.indexOf(val) === -1; }));
|
||||
}
|
||||
}).sendRequest();
|
||||
}
|
||||
};
|
||||
return AddressbookApp;
|
||||
}(egw_app_1.EgwApp));
|
||||
app.classes.addressbook = AddressbookApp;
|
||||
|
@ -1462,6 +1462,30 @@ class AddressbookApp extends EgwApp
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if new shared_with value is allowed / user has rights to share into that AB
|
||||
*
|
||||
* Remove the entry again, if user is not allowed
|
||||
*/
|
||||
public shared_changed()
|
||||
{
|
||||
let shared = this.et2.getInputWidgetById('shared_values');
|
||||
let value = <Array<string>>shared?.get_value();
|
||||
|
||||
if (value)
|
||||
{
|
||||
this.egw.json('addressbook.addressbook_ui.ajax_check_shared', [{
|
||||
shared_values: value,
|
||||
shared_writable: this.et2.getInputWidgetById('shared_writable').get_value()
|
||||
}], _data => {
|
||||
if (Array.isArray(_data) && _data.length)
|
||||
{
|
||||
// remove not allowed entries
|
||||
shared.set_value(value.filter(val => _data.indexOf(val) === -1));
|
||||
}
|
||||
}).sendRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.classes.addressbook = AddressbookApp;
|
||||
|
@ -143,9 +143,10 @@
|
||||
</hbox>
|
||||
<description/>
|
||||
</row>
|
||||
<row>
|
||||
<row disabled="@shared_disabled">
|
||||
<description for="shared" value="Shared with"/>
|
||||
<taglist-account account_type="both" id="shared_values" multiple="true" select_options="@shared_options" span="4"/>
|
||||
<taglist-account account_type="both" id="shared_values" multiple="true"
|
||||
onchange="app.addressbook.shared_changed" select_options="@shared_options" span="4"/>
|
||||
<checkbox id="shared_writable" label="writable" statustext="Create new shares writable"/>
|
||||
</row>
|
||||
</rows>
|
||||
|
@ -30,6 +30,17 @@ class Contacts extends Contacts\Storage
|
||||
*/
|
||||
const BIRTHDAY_CACHE_TIME = 864000; /* 10 days*/
|
||||
|
||||
/**
|
||||
* Custom ACL allowing to share into the AB / setting shared_with
|
||||
*/
|
||||
const ACL_SHARED = Acl::CUSTOM1;
|
||||
/**
|
||||
* Mask to allow to share into the AB, at least one of the following need to be set:
|
||||
* - custom ACL_SHARED
|
||||
* - ACL::EDIT
|
||||
*/
|
||||
const CHECK_ACL_SHARED = Acl::EDIT|self::ACL_SHARED;
|
||||
|
||||
/**
|
||||
* @var int $now_su actual user (!) time
|
||||
*/
|
||||
@ -1250,6 +1261,34 @@ class Contacts extends Contacts\Storage
|
||||
return $access;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has right to share with / into given AB
|
||||
*
|
||||
* @param array[]& $shared_with array of arrays with values for keys "shared_with", "shared_by", ...
|
||||
* @return array of entries removed from $shared_with because current user is not allowed to share into (key is preserved)
|
||||
*/
|
||||
function check_shared_with(array &$shared_with)
|
||||
{
|
||||
$removed = [];
|
||||
foreach($shared_with as $key => $shared)
|
||||
{
|
||||
if (!empty($shared['shared_by']) && $shared['shared_by'] != $this->user)
|
||||
{
|
||||
$grants = $this->get_grants($user);
|
||||
}
|
||||
else
|
||||
{
|
||||
$grants = $this->grants;
|
||||
}
|
||||
if (!($grants[$shared['shared_with']] & self::CHECK_ACL_SHARED))
|
||||
{
|
||||
$removed[$key] = $shared;
|
||||
unset($shared_with[$key]);
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access to the file store
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user