mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Some improvements for ACL Support #157
This commit is contained in:
parent
a0f7114a39
commit
b0d4b56cee
9 changed files with 160 additions and 20 deletions
|
|
@ -27,6 +27,9 @@ import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
import { FileInfo } from 'Common/File';
|
import { FileInfo } from 'Common/File';
|
||||||
|
|
||||||
|
import { FolderPopupView } from 'View/Popup/Folder';
|
||||||
|
import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
|
||||||
const
|
const
|
||||||
// isPosNumeric = value => null != value && /^[0-9]*$/.test(value.toString()),
|
// isPosNumeric = value => null != value && /^[0-9]*$/.test(value.toString()),
|
||||||
|
|
||||||
|
|
@ -481,7 +484,8 @@ export class FolderModel extends AbstractModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
edit() {
|
edit() {
|
||||||
this.canBeEdited() && this.editing(true);
|
// this.canBeEdited() && this.editing(true);
|
||||||
|
this.canBeEdited() && showScreenPopup(FolderPopupView, [this]);
|
||||||
}
|
}
|
||||||
|
|
||||||
unedit() {
|
unedit() {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
import { showScreenPopup } from 'Knoin/Knoin';
|
import { showScreenPopup } from 'Knoin/Knoin';
|
||||||
|
|
||||||
|
//import { FolderPopupView } from 'View/Popup/Folder';
|
||||||
import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
|
import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
|
||||||
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
||||||
|
|
||||||
|
|
|
||||||
44
dev/View/Popup/Folder.js
Normal file
44
dev/View/Popup/Folder.js
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { addObservablesTo } from 'External/ko';
|
||||||
|
|
||||||
|
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
|
||||||
|
export class FolderPopupView extends AbstractViewPopup {
|
||||||
|
constructor() {
|
||||||
|
super('Folder');
|
||||||
|
addObservablesTo(this, {
|
||||||
|
folder: null // FolderModel
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ACL = ko.observableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
this.folder().unedit();
|
||||||
|
}
|
||||||
|
|
||||||
|
submitForm(form) {
|
||||||
|
this.folder().rename();
|
||||||
|
console.dir({form});
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeShow(folder) {
|
||||||
|
this.ACL([]);
|
||||||
|
folder.editing(true);
|
||||||
|
this.folder(folder);
|
||||||
|
Remote.request('FolderACL', (iError, data) => {
|
||||||
|
if (!iError && data.Result) {
|
||||||
|
this.ACL(
|
||||||
|
Object.entries(data.Result).map(([key, value]) => {
|
||||||
|
value.identifier = key;
|
||||||
|
return value;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
folder: folder.fullName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,13 +61,18 @@ trait ACL
|
||||||
return $rights->hasRight('i');
|
return $rights->hasRight('i');
|
||||||
case 'EXPUNGE':
|
case 'EXPUNGE':
|
||||||
return $rights->hasRight('e');
|
return $rights->hasRight('e');
|
||||||
|
/*
|
||||||
// case 'SUBSCRIBE':
|
case 'SUBSCRIBE':
|
||||||
// case 'UNSUBSCRIBE':
|
return $rights->hasRight('l') || true;
|
||||||
// case 'CLOSE':
|
case 'UNSUBSCRIBE':
|
||||||
// case 'FETCH':
|
return true;
|
||||||
// case 'STORE':
|
case 'CLOSE':
|
||||||
|
return $rights->hasRight('e') || true;
|
||||||
|
case 'FETCH':
|
||||||
|
return $rights->hasRight('s') || true;
|
||||||
|
case 'STORE':
|
||||||
|
return $rights->hasRight('s') || $rights->hasRight('w') || $rights->hasRight('t');
|
||||||
|
*/
|
||||||
case 'GETACL':
|
case 'GETACL':
|
||||||
case 'SETACL':
|
case 'SETACL':
|
||||||
case 'LISTRIGHTS':
|
case 'LISTRIGHTS':
|
||||||
|
|
@ -104,13 +109,17 @@ trait ACL
|
||||||
$oResponses = $this->SendRequestGetResponse('GETACL', array($this->EscapeFolderName($sFolderName)));
|
$oResponses = $this->SendRequestGetResponse('GETACL', array($this->EscapeFolderName($sFolderName)));
|
||||||
$aResult = array();
|
$aResult = array();
|
||||||
foreach ($oResponses as $oResponse) {
|
foreach ($oResponses as $oResponse) {
|
||||||
|
// * ACL INBOX.shared demo@snappymail.eu akxeilprwtscd foobar@snappymail.eu akxeilprwtscd demo2@snappymail.eu lrwstipekxacd
|
||||||
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oResponse->ResponseType
|
||||||
&& isset($oResponse->ResponseList[4])
|
&& isset($oResponse->ResponseList[4])
|
||||||
&& 'ACL' === $oResponse->ResponseList[1]
|
&& 'ACL' === $oResponse->ResponseList[1]
|
||||||
&& $sFolderName === $oResponse->ResponseList[2]
|
&& $sFolderName === $oResponse->ResponseList[2]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$aResult[$oResponse->ResponseList[3]] = static::aclRightsToClass(\array_slice($oResponse->ResponseList, 4));
|
$c = \count($oResponse->ResponseList);
|
||||||
|
for ($i = 3; $i < $c; $i += 2) {
|
||||||
|
$aResult[$oResponse->ResponseList[$i]] = new ACLResponse(\str_split($oResponse->ResponseList[$i+1]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $aResult;
|
return $aResult;
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ class Folder implements \JsonSerializable
|
||||||
'role' => $this->Role(),
|
'role' => $this->Role(),
|
||||||
|
|
||||||
'rights' => $this->myRights,
|
'rights' => $this->myRights,
|
||||||
'myRights' => $this->myRights ? $this->myRights->JMAP() : [
|
'myRights' => $this->myRights ?: [
|
||||||
'mayReadItems' => $selectable,
|
'mayReadItems' => $selectable,
|
||||||
'mayAddItems' => $selectable,
|
'mayAddItems' => $selectable,
|
||||||
'mayRemoveItems' => $selectable,
|
'mayRemoveItems' => $selectable,
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,6 @@ class ACL implements \JsonSerializable
|
||||||
|
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function jsonSerialize()
|
public function jsonSerialize()
|
||||||
{
|
|
||||||
return $this->rights;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function JMAP() : array
|
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'mayReadItems' => ($this->hasRight('l') && $this->hasRight('r')),
|
'mayReadItems' => ($this->hasRight('l') && $this->hasRight('r')),
|
||||||
|
|
@ -57,7 +52,8 @@ class ACL implements \JsonSerializable
|
||||||
'mayCreateChild' => $this->hasRight('k'),
|
'mayCreateChild' => $this->hasRight('k'),
|
||||||
'mayRename' => $this->hasRight('x'),
|
'mayRename' => $this->hasRight('x'),
|
||||||
'mayDelete' => $this->hasRight('x'),
|
'mayDelete' => $this->hasRight('x'),
|
||||||
'maySubmit' => $this->hasRight('p')
|
'maySubmit' => $this->hasRight('p'),
|
||||||
|
'raw' => \implode('', $this->rights)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,4 +321,39 @@ trait Folders
|
||||||
|
|
||||||
return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
|
return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function DoFolderACL() : array
|
||||||
|
{
|
||||||
|
$this->initMailClientConnection();
|
||||||
|
return $this->DefaultResponse(
|
||||||
|
$this->ImapClient()->FolderGetACL(
|
||||||
|
$this->GetActionParam('folder', '')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function DoFolderDeleteACL() : array
|
||||||
|
{
|
||||||
|
$this->initMailClientConnection();
|
||||||
|
$this->ImapClient()->FolderDeleteACL(
|
||||||
|
$this->GetActionParam('folder', ''),
|
||||||
|
$this->GetActionParam('identifier', '')
|
||||||
|
);
|
||||||
|
return $this->TrueResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function DoFolderSetACL() : array
|
||||||
|
{
|
||||||
|
// $oImapClient->FolderSetACL('INBOX', 'demo@snappymail.eu', 'lrwstipekxacd');
|
||||||
|
// $oImapClient->FolderSetACL($sFolderFullName, 'demo@snappymail.eu', 'lrwstipekxacd');
|
||||||
|
// $oImapClient->FolderSetACL($sFolderFullName, 'foobar@snappymail.eu', 'lr');
|
||||||
|
$this->initMailClientConnection();
|
||||||
|
$this->ImapClient()->FolderSetACL(
|
||||||
|
$this->GetActionParam('folder', ''),
|
||||||
|
$this->GetActionParam('identifier', ''),
|
||||||
|
$this->GetActionParam('rights', '')
|
||||||
|
);
|
||||||
|
return $this->TrueResponse();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
<header>
|
||||||
|
<a href="#" class="close" data-bind="click: close">×</a>
|
||||||
|
<h3 data-bind="text: folder()?.fullName"></h3>
|
||||||
|
</header>
|
||||||
|
<form id="folderform" class="modal-body form-horizontal" autocomplete="off" spellcheck="false" data-bind="submit: submitForm">
|
||||||
|
<div data-bind="with: folder">
|
||||||
|
<div class="control-group">
|
||||||
|
<label data-i18n="GLOBAL/NAME"></label>
|
||||||
|
<input name="folder" type="text"
|
||||||
|
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
|
required="" data-bind="textInput: nameForEdit, hasfocus: editing">
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label data-i18n="POPUPS_FILTER/SELECT_FIELD_SIZE"></label>
|
||||||
|
<span data-bind="text: friendlySize"></span>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label data-i18n="MESSAGE_LIST/MENU_SELECT_UNSEEN"></label>
|
||||||
|
<span data-bind="text: unreadEmails"></span>
|
||||||
|
/ <span data-bind="text: totalEmails"></span>
|
||||||
|
</div>
|
||||||
|
<!-- ko if: canBeSubscribed -->
|
||||||
|
<div class="control-group" data-bind="component: {
|
||||||
|
name: 'Checkbox',
|
||||||
|
params: {
|
||||||
|
name: 'subscribe',
|
||||||
|
label: 'SETTINGS_FOLDERS/BUTTON_SUBSCRIBE',
|
||||||
|
value: isSubscribed
|
||||||
|
}
|
||||||
|
}"></div>
|
||||||
|
<!-- /ko -->
|
||||||
|
</div>
|
||||||
|
<div class="control-group" data-bind="if: ACL">
|
||||||
|
<label>ACL</label>
|
||||||
|
<table class="table table-hover table-bordered" style="width:auto"><tbody data-bind="foreach: ACL">
|
||||||
|
<tr><th colspan="2" data-bind="text: identifier"></th></tr>
|
||||||
|
<tr><td>mayAddItems</td><td data-bind="text: mayAddItems ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>mayCreateChild</td><td data-bind="text: mayCreateChild ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>mayDelete</td><td data-bind="text: mayDelete ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>mayReadItems</td><td data-bind="text: mayReadItems ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>mayRemoveItems</td><td data-bind="text: mayRemoveItems ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>mayRename</td><td data-bind="text: mayRename ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>maySetKeywords</td><td data-bind="text: maySetKeywords ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>maySetSeen</td><td data-bind="text: maySetSeen ? '☑' : '☐'"></td></tr>
|
||||||
|
<tr><td>maySubmit</td><td data-bind="text: maySubmit ? '☑' : '☐'"></td></tr>
|
||||||
|
</tbody></table>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<footer>
|
||||||
|
<button form="folderform" class="btn">
|
||||||
|
<i class="icon-folder-add"></i>
|
||||||
|
<span data-i18n="GLOBAL/SAVE"></span>
|
||||||
|
</button>
|
||||||
|
</footer>
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
<tr data-bind="css: { 'selectable': selectable, 'system': isSystemFolder }">
|
<tr data-bind="css: { 'selectable': selectable, 'system': isSystemFolder }">
|
||||||
<td data-bind="css: 'deep-' + deep">
|
<td data-bind="css: 'deep-' + deep">
|
||||||
<span class="folder-name" data-bind="text: name, visible: !editing(), css: { 'can-be-edited': canBeEdited },
|
<span class="folder-name" data-bind="text: name, css: { 'can-be-edited': canBeEdited },
|
||||||
click: edit,
|
click: edit,
|
||||||
tooltipErrorTip: errorMsg"></span>
|
tooltipErrorTip: errorMsg"></span>
|
||||||
<input type="text"
|
|
||||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
|
||||||
data-bind="textInput: nameForEdit, visible: editing, hasfocus: editing, onEnter: rename, onEsc: unedit">
|
|
||||||
<span class="folder-system-name" data-bind="text: nameInfo, visible: isSystemFolder"></span>
|
<span class="folder-system-name" data-bind="text: nameInfo, visible: isSystemFolder"></span>
|
||||||
<span class="folder-size" data-bind="text: friendlySize, visible: size"></span>
|
<span class="folder-size" data-bind="text: friendlySize, visible: size"></span>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue