mirror of
https://github.com/netzbegruenung/groupfolders.git
synced 2024-05-08 04:03:40 +02:00
Add search and permission setting to frontend
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
parent
b8e0cb16a3
commit
6cc05b152c
57
src/BinaryTools.js
Normal file
57
src/BinaryTools.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
const BinaryTools = {
|
||||
toString(num) {
|
||||
return (num >>> 0).toString(2).padStart(8, '0');
|
||||
},
|
||||
|
||||
firstHigh(num) {
|
||||
let position = 0;
|
||||
while (num !== 0) {
|
||||
if (num & 1 > 0) {
|
||||
return position;
|
||||
}
|
||||
position++;
|
||||
num = num >> 1;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
test(num, bit){
|
||||
return ((num>>bit) % 2 !== 0)
|
||||
},
|
||||
|
||||
set(num, bit){
|
||||
return num | 1<<bit;
|
||||
},
|
||||
|
||||
clear(num, bit){
|
||||
return num & ~(1<<bit);
|
||||
},
|
||||
|
||||
toggle(num, bit){
|
||||
return this.test(num, bit) ? this.clear(num, bit) : this.set(num, bit);
|
||||
}
|
||||
};
|
||||
|
||||
export default BinaryTools;
|
|
@ -1,3 +1,25 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import Vue from 'vue';
|
||||
import SharingSidebarView from './components/SharingSidebarView.vue';
|
||||
import VTooltip from 'v-tooltip';
|
||||
|
|
171
src/client.js
Normal file
171
src/client.js
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import ACL_PROPERTIES from './model/Properties';
|
||||
import Rule from './model/Rule'
|
||||
|
||||
_.extend(OC.Files.Client, ACL_PROPERTIES);
|
||||
|
||||
// Allow nested properties in PROPPATCH
|
||||
// WIP branch at https://github.com/juliushaertl/davclient.js/tree/enhancement/nested-proppatch
|
||||
var patchClientForNestedPropPatch = function (client) {
|
||||
client._client.getPropertyBody = function(key, propValue) {
|
||||
var property = this.parseClarkNotation(key);
|
||||
var propName;
|
||||
|
||||
if (this.xmlNamespaces[property.namespace]) {
|
||||
propName = this.xmlNamespaces[property.namespace] + ':' + property.name;
|
||||
} else {
|
||||
propName = 'x:' + property.name + ' xmlns:x="' + property.namespace + '"';
|
||||
}
|
||||
|
||||
if (Array.isArray(propValue)) {
|
||||
var body = '';
|
||||
for(var ii in propValue) {
|
||||
if ( propValue[ii].hasOwnProperty('type') && propValue[ii].hasOwnProperty('data') ) {
|
||||
body += this.getPropertyBody(propValue[ii].type, propValue[ii].data);
|
||||
} else {
|
||||
body += this.getPropertyBody(ii, propValue[ii]);
|
||||
}
|
||||
}
|
||||
return ' <' + propName + '>' + body + '</' + propName + '>';
|
||||
} else if (typeof propValue === 'object') {
|
||||
var body = '';
|
||||
if ( propValue.hasOwnProperty('type') && propValue.hasOwnProperty('data') ) {
|
||||
return this.getPropertyBody(propValue.type, propValue.data)
|
||||
}
|
||||
for(var ii in propValue) {
|
||||
body += this.getPropertyBody(ii, propValue[ii]);
|
||||
}
|
||||
return ' <' + propName + '>' + body + '</' + propName + '>';
|
||||
} else {
|
||||
// FIXME: hard-coded for now until we allow properties to
|
||||
// specify whether to be escaped or not
|
||||
if (propName !== 'd:resourcetype') {
|
||||
propValue = dav._escapeXml('' + propValue);
|
||||
}
|
||||
|
||||
return ' <' + propName + '>' + propValue + '</' + propName + '>';
|
||||
}
|
||||
}
|
||||
client._client._renderPropSet = function(properties) {
|
||||
var body = ' <d:set>\n' +
|
||||
' <d:prop>\n';
|
||||
|
||||
for(var ii in properties) {
|
||||
if (!properties.hasOwnProperty(ii)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
body += this.getPropertyBody(ii, properties[ii])
|
||||
}
|
||||
body +=' </d:prop>\n';
|
||||
body +=' </d:set>\n';
|
||||
return body;
|
||||
}
|
||||
};
|
||||
|
||||
var client = OCA.Files.App.fileList.filesClient;
|
||||
client.addFileInfoParser(function(response) {
|
||||
var data = {};
|
||||
var props = response.propStat[0].properties;
|
||||
var groupFolderId = props[ACL_PROPERTIES.GROUP_FOLDER_ID];
|
||||
if (typeof groupFolderId !== 'undefined') {
|
||||
data.groupFolderId = groupFolderId;
|
||||
}
|
||||
|
||||
var acls = props[ACL_PROPERTIES.PROPERTY_ACL_LIST];
|
||||
if (!_.isUndefined(acls)) {
|
||||
data.acl = [];
|
||||
for (var i = 0; i < acls.length; i++) {
|
||||
var acl = {};
|
||||
for (var ii in acls[i].children) {
|
||||
var prop = acls[i].children[ii];
|
||||
if (!prop.nodeName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertyName = prop.nodeName.split(':')[1] || '';
|
||||
switch (propertyName) {
|
||||
case 'acl-mapping-id':
|
||||
acl.mappingId = prop.textContent || prop.text;
|
||||
break;
|
||||
case 'acl-mapping-type':
|
||||
acl.mappingType = prop.textContent || prop.text;
|
||||
break;
|
||||
case 'acl-mask':
|
||||
acl.mask = parseInt(prop.textContent || prop.text, 10);
|
||||
break;
|
||||
case 'acl-permissions':
|
||||
acl.permissions = parseInt(prop.textContent || prop.text, 10);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
data.acl.push(acl);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
});
|
||||
patchClientForNestedPropPatch(client);
|
||||
|
||||
class AclDavService {
|
||||
|
||||
propFind(model) {
|
||||
return client.getFileInfo(model.path + '/' + model.name, {
|
||||
properties: [ACL_PROPERTIES.PROPERTY_ACL_LIST, ACL_PROPERTIES.PROPERTY_INHERITED_ACL_LIST, ACL_PROPERTIES.GROUP_FOLDER_ID]
|
||||
} ).then((status, fileInfo) => {
|
||||
if (fileInfo) {
|
||||
let acls = []
|
||||
for ( let i in fileInfo.acl ) {
|
||||
let acl = new Rule()
|
||||
acl.fromValues(
|
||||
fileInfo.acl[i].mappingType,
|
||||
fileInfo.acl[i].mappingId,
|
||||
fileInfo.acl[i].mask,
|
||||
fileInfo.acl[i].permissions,
|
||||
)
|
||||
acls.push(acl);
|
||||
}
|
||||
return {
|
||||
acls,
|
||||
groupFolderId: fileInfo.groupFolderId
|
||||
};
|
||||
}
|
||||
// TODO parse inherited permissions here
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
propPatch(model, acls) {
|
||||
var aclList = [];
|
||||
for (let i in acls) {
|
||||
aclList.push({type: ACL_PROPERTIES.PROPERTY_ACL_ENTRY, data: acls[i].getProperties()})
|
||||
}
|
||||
var props = {};
|
||||
props[OC.Files.Client.PROPERTY_ACL_LIST] = aclList;
|
||||
return client._client.propPatch(client._client.baseUrl + model.path + '/' + model.name, props)
|
||||
}
|
||||
}
|
||||
|
||||
export default new AclDavService();
|
|
@ -1,9 +1,34 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
-
|
||||
- @author Julius Härtl <jus@bitgrid.net>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<div style="position: relative;" v-click-outside="popoverClose">
|
||||
<button @click="open = true" v-if="state === STATES.INHERIT_DENY" class="icon-deny inherited" v-tooltip="t('groupfolders', 'Denied (Inherited permission)')"></button>
|
||||
<button @click="open = true" v-else-if="state === STATES.INHERIT_ALLOW" class="icon-checkmark inherited" v-tooltip="t('groupfolders', 'Allowed (Inherited permission)')"></button>
|
||||
<button @click="open = true" v-else-if="state === STATES.SELF_DENY" class="icon-deny" v-tooltip="t('groupfolders', 'Denied')"></button>
|
||||
<button @click="open = true" v-else-if="state === STATES.SELF_ALLOW" class="icon-checkmark" v-tooltip="t('groupfolders', 'Allowed')"></button>
|
||||
<div v-if="readOnly">
|
||||
<button v-if="!isAllowed" class="icon-deny" v-tooltip="t('groupfolders', 'Denied')"></button>
|
||||
<button v-else class="icon-checkmark" v-tooltip="t('groupfolders', 'Allowed')"></button>
|
||||
</div>
|
||||
<div v-else style="position: relative;" v-click-outside="popoverClose">
|
||||
<button :disabled="disabled" @click="open = true" v-if="state === STATES.INHERIT_DENY" class="icon-deny inherited" v-tooltip="t('groupfolders', 'Denied (Inherited permission)')"></button>
|
||||
<button :disabled="disabled" @click="open = true" v-else-if="state === STATES.INHERIT_ALLOW" class="icon-checkmark inherited" v-tooltip="t('groupfolders', 'Allowed (Inherited permission)')"></button>
|
||||
<button :disabled="disabled" @click="open = true" v-else-if="state === STATES.SELF_DENY" class="icon-deny" v-tooltip="t('groupfolders', 'Denied')"></button>
|
||||
<button :disabled="disabled" @click="open = true" v-else-if="state === STATES.SELF_ALLOW" class="icon-checkmark" v-tooltip="t('groupfolders', 'Allowed')"></button>
|
||||
<div class="popovermenu" :class="{open: open}"><PopoverMenu :menu="menu"></PopoverMenu></div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -25,6 +50,14 @@
|
|||
state: {
|
||||
type: Number,
|
||||
default: STATES.INHERIT_DENY
|
||||
},
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -32,6 +65,11 @@
|
|||
this.open = false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAllowed() {
|
||||
return this.state & 1;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
STATES: STATES,
|
||||
|
@ -42,6 +80,7 @@
|
|||
text: 'Inherit permission',
|
||||
active: this.state === STATES.INHERIT_ALLOW || this.state === STATES.INHERIT_DENY,
|
||||
action: () => {
|
||||
this.$emit('update', STATES.INHERIT_ALLOW);
|
||||
this.popoverClose()
|
||||
}
|
||||
},
|
||||
|
@ -50,6 +89,7 @@
|
|||
text: 'Deny',
|
||||
active: this.state === STATES.SELF_DENY,
|
||||
action: () => {
|
||||
this.$emit('update', STATES.SELF_DENY);
|
||||
this.popoverClose()
|
||||
}
|
||||
},
|
||||
|
@ -58,6 +98,7 @@
|
|||
text: 'Allow',
|
||||
active: this.state === STATES.SELF_ALLOW,
|
||||
action: () => {
|
||||
this.$emit('update', STATES.SELF_ALLOW);
|
||||
this.popoverClose()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +1,219 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
-
|
||||
- @author Julius Härtl <jus@bitgrid.net>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="groupfolder-entry">
|
||||
<div class="avatar icon-group-white"></div>
|
||||
<span class="username">{{ t('groupfolders', 'Groupfolder') }}</span>
|
||||
<span class="username">{{ t('groupfolders', 'Groupfolder') }} {{ groupFolderId }} </span>
|
||||
</div>
|
||||
<table>
|
||||
<table v-if="!loading">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>{{ t('groupfolders', 'Read') }}</th>
|
||||
<th>{{ t('groupfolders', 'Write') }}</th>
|
||||
<th>{{ t('groupfolders', 'Share') }}</th>
|
||||
<th v-if="model.type === 'dir'">{{ t('groupfolders', 'Create') }}</th>
|
||||
<th>{{ t('groupfolders', 'Delete') }}</th>
|
||||
<th>{{ t('groupfolders', 'Share') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<tr v-if="!isAdmin">
|
||||
<td><avatar user="admin" :size="24"></avatar></td>
|
||||
<td class="username">Username</td>
|
||||
<td><AclStateButton :state="0" /></td>
|
||||
<td><AclStateButton :state="1" /></td>
|
||||
<td><AclStateButton :state="2" /></td>
|
||||
<td><AclStateButton :state="3" /></td>
|
||||
<td><a class="icon-close" v-tooltip="t('groupfolders', 'Remove access rule')"></a></td>
|
||||
<td class="username">{{ t('groupfolders', 'You') }}</td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_READ, model.permissions, 1)" :read-only="true" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_UPDATE, model.permissions, 1)" :read-only="true" /></td>
|
||||
<td v-if="model.type === 'dir'"><AclStateButton :state="getState(OC.PERMISSION_CREATE, model.permissions, 1)" :read-only="true" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_DELETE, model.permissions, 1)" :read-only="true" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_SHARE, model.permissions, 1)" :read-only="true" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><avatar user="group" :isNoUser="true" :size="24"></avatar></td>
|
||||
<td>Group</td>
|
||||
<td><AclStateButton :state="0" /></td>
|
||||
<td><AclStateButton :state="1" /></td>
|
||||
<td><AclStateButton :state="2" /></td>
|
||||
<td><AclStateButton :state="3" /></td>
|
||||
<td><a class="icon-close" v-tooltip="t('groupfolders', 'Remove access rule')"></a></td>
|
||||
<tr v-if="isAdmin" v-for="item in list">
|
||||
<td>
|
||||
<avatar :user="item.mappingId" :size="24"></avatar>
|
||||
</td>
|
||||
<td class="username">
|
||||
{{ item.mappingId }}
|
||||
<span v-if="item.mappingType === 'group'"> {{ t('groupfolders', '(Group)') }}</span>
|
||||
</td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_READ, item.permissions, item.mask)" @update="changePermission(item, OC.PERMISSION_READ, $event)" :disabled="loading" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_UPDATE, item.permissions, item.mask)" @update="changePermission(item, OC.PERMISSION_UPDATE, $event)" :disabled="loading" /></td>
|
||||
<td v-if="model.type === 'dir'"><AclStateButton :state="getState(OC.PERMISSION_CREATE, item.permissions, item.mask)" @update="changePermission(item, OC.PERMISSION_CREATE, $event)" :disabled="loading" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_DELETE, item.permissions, item.mask)" @update="changePermission(item, OC.PERMISSION_DELETE, $event)" :disabled="loading" /></td>
|
||||
<td><AclStateButton :state="getState(OC.PERMISSION_SHARE, item.permissions, item.mask)" @update="changePermission(item, OC.PERMISSION_SHARE, $event)" :disabled="loading" /></td>
|
||||
<td><a class="icon-close" v-tooltip="t('groupfolders', 'Remove access rule')" @click="removeAcl(item)"></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button v-if="!showAclCreate" @click="toggleAclCreate"><span class="icon-add"></span> {{ t('groupfolders', 'Add advanced permission rule') }}</button>
|
||||
<multiselect v-if="showAclCreate" ref="multiselect" v-model="value" :options="options"></multiselect>
|
||||
<button v-if="isAdmin && !loading && !showAclCreate" @click="toggleAclCreate"><span class="icon-add"></span> {{ t('groupfolders', 'Add advanced permission rule') }}</button>
|
||||
<multiselect v-if="isAdmin && !loading" v-show="showAclCreate" ref="select"
|
||||
v-model="value" :options="options" @select="createAcl" :reset-after="true" @search-change="searchMappings"
|
||||
:internal-search="false"
|
||||
track-by="unique">
|
||||
<template slot="singleLabel" slot-scope="props">
|
||||
<avatar :user="props.option.id" :isNoUser="props.option.type !== 'user'"/> {{ props.option.id }}
|
||||
<span v-if="props.option.type === 'group'">{{ t('groupfolders', '(Group)') }}</span>
|
||||
</template>
|
||||
<template slot="option" slot-scope="props">
|
||||
<avatar :user="props.option.id" :isNoUser="props.option.type !== 'user'"/> {{ props.option.id }}
|
||||
<span v-if="props.option.type === 'group'">{{ t('groupfolders', '(Group)') }}</span>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import axios from 'nextcloud-axios';
|
||||
import { Avatar, Multiselect } from 'nextcloud-vue';
|
||||
import AclStateButton from './AclStateButton'
|
||||
import Rule from './../model/Rule'
|
||||
import BinaryTools from './../BinaryTools'
|
||||
import client from './../client'
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
name: 'SharingSidebarView',
|
||||
props: ['fileModel'],
|
||||
components: {
|
||||
Avatar, Multiselect, AclStateButton
|
||||
},
|
||||
beforeMount() {
|
||||
this.loading = true;
|
||||
this.model = JSON.parse(JSON.stringify(this.fileModel))
|
||||
client.propFind(this.model).then((data) => {
|
||||
if (data.acls) {
|
||||
this.list = data.acls;
|
||||
}
|
||||
this.groupFolderId = data.groupFolderId;
|
||||
this.loading = false;
|
||||
this.searchMappings('')
|
||||
})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAclCreate: false,
|
||||
options: ['list', 'of', 'options'],
|
||||
value: null
|
||||
groupFolderId: null,
|
||||
loading: false,
|
||||
options: [],
|
||||
value: null,
|
||||
model: null,
|
||||
list: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canShare() {
|
||||
return OC.PERMISSION_SHARE & this.fileModel.permissions !== 0
|
||||
isAdmin() {
|
||||
return OC.isUserAdmin()
|
||||
},
|
||||
isInherited() {
|
||||
return (permission, permissions, mask) => {
|
||||
return (permission & ~mask) === 0
|
||||
}
|
||||
},
|
||||
isAllowed() {
|
||||
return (permission, permissions) => {
|
||||
return (permission & permissions) > 0
|
||||
}
|
||||
},
|
||||
getState() {
|
||||
return (permission, permissions, mask) => {
|
||||
const inheritance = this.isInherited(permission, permissions, mask) << 1
|
||||
const permitted = this.isAllowed(permission, permissions)
|
||||
return inheritance | permitted;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
searchMappings(query) {
|
||||
axios.get(OC.generateUrl(`apps/groupfolders/folders/${this.groupFolderId}/search`) + '?format=json&search=' + query).then((result) => {
|
||||
let groups = result.data.ocs.data.groups.map((group) => {
|
||||
return {
|
||||
unique: 'group:' + group.gid,
|
||||
type: 'group',
|
||||
id: group.gid,
|
||||
displayname: group.displayname
|
||||
}
|
||||
})
|
||||
let users = Object.values(result.data.ocs.data.users).map((user) => {
|
||||
return {
|
||||
unique: 'user:' + user.uid,
|
||||
type: 'user',
|
||||
id: user.uid,
|
||||
displayname: user.displayname
|
||||
}
|
||||
})
|
||||
this.options = [...groups, ...users].filter((entry) => {
|
||||
// filter out existing acl rules
|
||||
return !this.list.find((existingAcl) => entry.unique === existingAcl.getUniqueMappingIdentifier());
|
||||
});
|
||||
})
|
||||
},
|
||||
toggleAclCreate() {
|
||||
this.showAclCreate = !this.showAclCreate;
|
||||
Vue.nextTick(() => {
|
||||
this.$refs.select.$el.focus()
|
||||
});
|
||||
},
|
||||
createAcl(option) {
|
||||
let rule = new Rule();
|
||||
rule.fromValues(option.type, option.id, 0b00000, 0b11111);
|
||||
this.list.push(rule);
|
||||
client.propPatch(this.model, this.list).then(() => {
|
||||
this.showAclCreate = false;
|
||||
});
|
||||
},
|
||||
removeAcl(rule) {
|
||||
const index = this.list.indexOf(rule);
|
||||
let list = JSON.parse(JSON.stringify(this.list))
|
||||
if (index > -1) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
client.propPatch(this.model, this.list).then(() => {
|
||||
this.list.splice(index, 1);
|
||||
});
|
||||
|
||||
},
|
||||
changePermission(item, permission, $event) {
|
||||
let index = this.list.indexOf(item);
|
||||
const inherit = ($event < 2);
|
||||
const allow = ($event & (0b01)) === 1;
|
||||
const bit = BinaryTools.firstHigh(permission);
|
||||
if (inherit) {
|
||||
item.mask = BinaryTools.clear(item.mask, bit)
|
||||
// TODO check if: we can ignore permissions, since they are inherited
|
||||
} else {
|
||||
item.mask = BinaryTools.set(item.mask, bit)
|
||||
if (allow) {
|
||||
item.permissions = BinaryTools.set(item.permissions, bit)
|
||||
} else {
|
||||
item.permissions = BinaryTools.clear(item.permissions, bit)
|
||||
}
|
||||
}
|
||||
Vue.set(this.list, index, item)
|
||||
client.propPatch(this.model, this.list).then(() => {
|
||||
// TODO block UI during save
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +255,7 @@
|
|||
table .avatardiv {
|
||||
margin-top: 6px;
|
||||
}
|
||||
table thead th:nth-child(2),
|
||||
table .username {
|
||||
width: 50%;
|
||||
}
|
||||
|
|
22
src/files.js
22
src/files.js
|
@ -1,3 +1,25 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
(function(OC, OCA) {
|
||||
|
||||
if (OCA.Theming) {
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
const ACL_PROPERTIES = {
|
||||
PROPERTY_ACL_LIST: '{' + OC.Files.Client.NS_NEXTCLOUD + '}acl-list',
|
||||
PROPERTY_ACL_ENTRY: '{' + OC.Files.Client.NS_NEXTCLOUD + '}acl',
|
||||
|
@ -5,6 +27,8 @@ const ACL_PROPERTIES = {
|
|||
PROPERTY_ACL_MAPPING_ID: '{' + OC.Files.Client.NS_NEXTCLOUD + '}acl-mapping-id',
|
||||
PROPERTY_ACL_MASK: '{' + OC.Files.Client.NS_NEXTCLOUD + '}acl-mask',
|
||||
PROPERTY_ACL_PERMISSIONS: '{' + OC.Files.Client.NS_NEXTCLOUD + '}acl-permissions',
|
||||
PROPERTY_INHERITED_ACL_LIST: '{' + OC.Files.Client.NS_NEXTCLOUD + '}inherited-acl-list',
|
||||
GROUP_FOLDER_ID: '{' + OC.Files.Client.NS_NEXTCLOUD + '}group-folder-id',
|
||||
};
|
||||
|
||||
export default ACL_PROPERTIES;
|
||||
|
|
|
@ -1,14 +1,58 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import PROPERTIES from 'Properties'
|
||||
import PROPERTIES from './Properties'
|
||||
|
||||
export default class Rule {
|
||||
|
||||
constructor (props) {
|
||||
constructor () {
|
||||
|
||||
}
|
||||
|
||||
fromProperties(props) {
|
||||
this.mappingType = props[PROPERTIES.PROPERTY_ACL_MAPPING_TYPE];
|
||||
this.mappingType = props[PROPERTIES.PROPERTY_ACL_MAPPING_ID];
|
||||
this.mappingId = props[PROPERTIES.PROPERTY_ACL_MAPPING_ID];
|
||||
this.mask = props[PROPERTIES.PROPERTY_ACL_MASK];
|
||||
this.permissions = props[PROPERTIES.PROPERTY_ACL_PERMISSIONS];
|
||||
}
|
||||
|
||||
fromValues(mappingType, mappingId, mask = 0, permissions = 31) {
|
||||
this.mappingType = mappingType;
|
||||
this.mappingId = mappingId;
|
||||
this.mask = mask;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
getProperties() {
|
||||
var acl = {};
|
||||
acl[PROPERTIES.PROPERTY_ACL_MAPPING_TYPE] = this.mappingType;
|
||||
acl[PROPERTIES.PROPERTY_ACL_MAPPING_ID] = this.mappingId;
|
||||
acl[PROPERTIES.PROPERTY_ACL_MASK] = this.mask;
|
||||
acl[PROPERTIES.PROPERTY_ACL_PERMISSIONS] = this.permissions;
|
||||
return acl;
|
||||
}
|
||||
|
||||
getUniqueMappingIdentifier() {
|
||||
return this.mappingType + ':' + this.mappingId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue