mirror of
https://github.com/filegator/filegator.git
synced 2025-08-12 11:34:30 +02:00
Added chmod perm, modal to change, api with local/ftp/sftp (#399)
Read a fill current permissions for local driver Finished permissions for ftp driver, read and change Read permissions for sftp adapter Created FilegatorFtp for a cleaner permissions integration Implemented recursive chmod options for files/folders Modified tests to cover permissions Lint frontend permissions component
This commit is contained in:
@@ -119,6 +119,17 @@ const api = {
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
},
|
||||
chmodItems(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post('chmoditems', {
|
||||
permissions: params.permissions,
|
||||
items: params.items,
|
||||
recursive: params.recursive,
|
||||
})
|
||||
.then(res => resolve(res.data.data))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
},
|
||||
removeItems(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post('deleteitems', {
|
||||
|
@@ -135,6 +135,9 @@
|
||||
<b-dropdown-item v-if="can(['write', 'zip']) && ! isArchive(props.row)" aria-role="listitem" @click="zip($event, props.row)">
|
||||
<b-icon icon="file-archive" size="is-small" /> {{ lang('Zip') }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item v-if="can(['write', 'chmod']) && props.row.permissions !== -1" aria-role="listitem" @click="chmod($event, props.row)">
|
||||
<b-icon icon="lock" size="is-small" /> {{ lang('Permissions') }} ({{ props.row.permissions }})
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item v-if="can('write')" aria-role="listitem" @click="remove($event, props.row)">
|
||||
<b-icon icon="trash-alt" size="is-small" /> {{ lang('Delete') }}
|
||||
</b-dropdown-item>
|
||||
@@ -164,6 +167,7 @@
|
||||
import Vue from 'vue'
|
||||
import Menu from './partials/Menu'
|
||||
import Tree from './partials/Tree'
|
||||
import Permissions from './partials/Permissions'
|
||||
import Editor from './partials/Editor'
|
||||
import Gallery from './partials/Gallery'
|
||||
import Search from './partials/Search'
|
||||
@@ -491,6 +495,37 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
chmod(event, item) {
|
||||
this.$modal.open({
|
||||
parent: this,
|
||||
hasModalCard: true,
|
||||
component: Permissions,
|
||||
props: {
|
||||
name: item.name,
|
||||
permissions: item.permissions,
|
||||
isDir: item.type == 'dir',
|
||||
},
|
||||
events: {
|
||||
saved: (permissions, recursive = null) => {
|
||||
this.isLoading = true
|
||||
api.chmodItems({
|
||||
items: item ? [item] : this.getSelected(),
|
||||
permissions: permissions,
|
||||
recursive: recursive,
|
||||
})
|
||||
.then(() => {
|
||||
this.isLoading = false
|
||||
this.loadFiles()
|
||||
})
|
||||
.catch(error => {
|
||||
this.isLoading = false
|
||||
this.handleError(error)
|
||||
})
|
||||
this.checked = []
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
rename(event, item) {
|
||||
this.$dialog.prompt({
|
||||
message: this.lang('New name'),
|
||||
|
143
frontend/views/partials/Permissions.vue
Normal file
143
frontend/views/partials/Permissions.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">
|
||||
{{ lang('Change permissions for') }} {{ name }}
|
||||
</p>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="columns permission-item" v-for="(typePermissions, type) in table" :key="type">
|
||||
<div class="column permission-type is-3">
|
||||
{{ type }}
|
||||
</div>
|
||||
<div class="column permission-name is-3" v-for="(value, permission) in typePermissions" :key="permission">
|
||||
<b-checkbox :value="value" @input="changePermission(type, permission, !value)">
|
||||
{{ permission }}
|
||||
</b-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns permission-item">
|
||||
<div class="column permission-type is-3">
|
||||
{{ lang('Permissions') }}
|
||||
</div>
|
||||
<div class="column permission-type is-3 manual-permission-cell">
|
||||
<b-field>
|
||||
<b-input
|
||||
:value="String(newPermissions).padStart(3, '0')"
|
||||
@input="v => newPermissions = parseInt(v.slice(-3))"
|
||||
maxlength="4"
|
||||
required
|
||||
/>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns permission-item" v-if="isDir">
|
||||
<div class="column permission-type is-3">
|
||||
{{ lang('Recursive') }}
|
||||
</div>
|
||||
<div class="column permission-type is-9">
|
||||
<b-field>
|
||||
<b-select v-model="recursive" expanded>
|
||||
<option :value="null">
|
||||
{{ lang('No') }}
|
||||
</option>
|
||||
<option value="all">
|
||||
{{ lang('Both folders and files') }}
|
||||
</option>
|
||||
<option value="folders">
|
||||
{{ lang('Apply only for folders') }}
|
||||
</option>
|
||||
<option value="files">
|
||||
{{ lang('Apply only for files') }}
|
||||
</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<button class="button" type="button" @click="$parent.close()">
|
||||
{{ lang('Cancel') }}
|
||||
</button>
|
||||
<button class="button is-primary" type="button" @click="$emit('saved', newPermissions, recursive) && $parent.close()">
|
||||
{{ lang('Save') }}
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Permissions',
|
||||
props: ['name', 'permissions', 'isDir'],
|
||||
data() {
|
||||
return {
|
||||
newPermissions: 700,
|
||||
/** @type {null | 'all' | 'folders' | 'files'} */
|
||||
recursive: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
table() {
|
||||
// credits to ChatGPT for this function
|
||||
const binary = parseInt(this.newPermissions, 8).toString(2).padStart(9, '0') // Convert octal to binary and pad to 9 digits
|
||||
return {
|
||||
owner: {
|
||||
read: binary[0] === '1',
|
||||
write: binary[1] === '1',
|
||||
execute: binary[2] === '1'
|
||||
},
|
||||
group: {
|
||||
read: binary[3] === '1',
|
||||
write: binary[4] === '1',
|
||||
execute: binary[5] === '1'
|
||||
},
|
||||
other: {
|
||||
read: binary[6] === '1',
|
||||
write: binary[7] === '1',
|
||||
execute: binary[8] === '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.permissions && this.permissions !== -1) {
|
||||
this.newPermissions = this.permissions
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changePermission(type, permission, on) {
|
||||
// credits to ChatGPT for this function
|
||||
let permissionsObject = this.table
|
||||
permissionsObject[type][permission] = on
|
||||
let permissions = 0
|
||||
// Calculate owner permissions
|
||||
if (permissionsObject.owner.read) permissions += 400
|
||||
if (permissionsObject.owner.write) permissions += 200
|
||||
if (permissionsObject.owner.execute) permissions += 100
|
||||
// Calculate group permissions
|
||||
if (permissionsObject.group.read) permissions += 40
|
||||
if (permissionsObject.group.write) permissions += 20
|
||||
if (permissionsObject.group.execute) permissions += 10
|
||||
// Calculate other permissions
|
||||
if (permissionsObject.other.read) permissions += 4
|
||||
if (permissionsObject.other.write) permissions += 2
|
||||
if (permissionsObject.other.execute) permissions += 1
|
||||
this.newPermissions = permissions
|
||||
return permissions
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.permission-type {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.permission-name {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.manual-permission-cell .help.counter {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
@@ -56,6 +56,9 @@
|
||||
<b-checkbox v-model="permissions.zip">
|
||||
{{ lang('Zip') }}
|
||||
</b-checkbox>
|
||||
<b-checkbox v-model="permissions.chmod">
|
||||
{{ lang('Chmod') }}
|
||||
</b-checkbox>
|
||||
</div>
|
||||
</b-field>
|
||||
</form>
|
||||
@@ -96,6 +99,7 @@ export default {
|
||||
download: _.find(this.user.permissions, p => p == 'download') ? true : false,
|
||||
batchdownload: _.find(this.user.permissions, p => p == 'batchdownload') ? true : false,
|
||||
zip: _.find(this.user.permissions, p => p == 'zip') ? true : false,
|
||||
chmod: _.find(this.user.permissions, p => p == 'chmod') ? true : false,
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -107,6 +111,7 @@ export default {
|
||||
this.permissions.write = false
|
||||
this.permissions.batchdownload = false
|
||||
this.permissions.zip = false
|
||||
this.permissions.chmod = false
|
||||
}
|
||||
},
|
||||
'permissions.write' (val) {
|
||||
@@ -114,6 +119,7 @@ export default {
|
||||
this.permissions.read = true
|
||||
} else {
|
||||
this.permissions.zip = false
|
||||
this.permissions.chmod = false
|
||||
}
|
||||
},
|
||||
'permissions.download' (val) {
|
||||
@@ -133,6 +139,12 @@ export default {
|
||||
this.permissions.write = true
|
||||
}
|
||||
},
|
||||
'permissions.chmod' (val) {
|
||||
if (val) {
|
||||
this.permissions.read = true
|
||||
this.permissions.write = true
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
selectDir() {
|
||||
|
Reference in New Issue
Block a user