Commit 480de999 authored by Mario's avatar Mario
Browse files

implement permissions so that remote visitors can upload files and delete,...

implement permissions so that remote visitors can upload files and delete, rename, move, copy and categorise their own files
parent 1fbbed52
Pipeline #369692 passed with stage
in 3 minutes and 15 seconds
......@@ -14,45 +14,107 @@ class Attach_edit extends Controller {
function post() {
if (! local_channel()) {
notice( t('Permission denied.') . EOL);
if (!local_channel() && !remote_channel()) {
return;
}
$attach_id = ((x($_POST, 'attach_id')) ? intval($_POST['attach_id']) : '');
$resource = ((x($_POST, 'resource')) ? notags($_POST['resource']) : '');
$folder = ((x($_POST, 'folder')) ? notags($_POST['folder']) : '');
$attach_id = ((x($_POST, 'attach_id')) ? intval($_POST['attach_id']) : null);
$nick = ((x($_POST, 'nick')) ? notags($_POST['nick']) : '');
$delete = ((x($_POST, 'delete')) ? intval($_POST['delete']) : 0);
$newfolder = ((x($_POST, 'newfolder_' . $attach_id)) ? notags($_POST['newfolder_' . $attach_id]) : '');
$filename = ((x($_POST, 'filename')) ? notags($_POST['filename']) : '');
$newfilename = ((x($_POST, 'newfilename_' . $attach_id)) ? notags($_POST['newfilename_' . $attach_id]) : '');
$recurse = ((x($_POST, 'recurse_' . $attach_id)) ? intval($_POST['recurse_' . $attach_id]) : 0);
$notify = ((x($_POST, 'notify_edit_' . $attach_id)) ? intval($_POST['notify_edit_' . $attach_id]) : 0);
$copy = ((x($_POST, 'copy_' . $attach_id)) ? intval($_POST['copy_' . $attach_id]) : 0);
$categories = ((x($_POST, 'categories_' . $attach_id)) ? notags($_POST['categories_' . $attach_id]) : '');
$channel = App::get_channel();
if (! $attach_id) {
notice(t('File not found.') . EOL);
return;
}
$channel = channelx_by_nick($nick);
if ($copy) {
$x = attach_copy($channel['channel_id'], $resource, $newfolder, $newfilename);
if (! $channel) {
notice(t('Channel not found.') . EOL);
return;
}
elseif ($folder !== $newfolder || $filename !== $newfilename) {
$x = attach_move($channel['channel_id'], $resource, $newfolder, $newfilename);
$nick = $channel['channel_address'];
$channel_id = $channel['channel_id'];
$observer = App::get_observer();
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
$r = q("SELECT uid, hash, creator, folder, filename, is_photo FROM attach WHERE id = %d AND uid = %d",
intval($attach_id),
intval($channel_id)
);
if (! $r) {
notice(t('File not found.') . EOL);
return;
}
if ($x['success'])
$resource = $x['resource_id'];
$resource = $r[0]['hash'];
$creator = $r[0]['creator'];
$folder = $r[0]['folder'];
$filename = $r[0]['filename'];
$is_photo = intval($r[0]['is_photo']);
$admin_delete = false;
$is_owner = ((local_channel() == $channel_id) ? true : false);
$is_creator = (($creator == $observer_hash) ? true : false);
$acl = new AccessList($channel);
$acl->set_from_array($_POST);
$x = $acl->get();
$perms = get_all_perms($channel_id, $observer_hash);
$url = get_cloud_url($channel['channel_id'], $channel['channel_address'], $resource);
if (! ($perms['view_storage'] || is_site_admin())){
notice( t('Permission denied.') . EOL);
return;
}
attach_change_permissions($channel['channel_id'], $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
if (! $perms['write_storage']) {
if (is_site_admin()) {
$admin_delete = true;
}
else {
notice( t('Permission denied.') . EOL);
return;
}
}
if(!$is_owner && !$admin_delete) {
if(! $is_creator) {
notice( t('Permission denied.') . EOL);
return;
}
}
if ($delete) {
attach_delete($channel_id, $resource, $is_photo);
if (! $admin_delete) {
$sync = attach_export_data($channel, $resource, true);
if ($sync) {
Libsync::build_sync_packet($channel_id, ['file' => [$sync]]);
}
}
json_return_and_die([ 'success' => true ]);
}
if ($copy) {
$x = attach_copy($channel_id, $resource, $newfolder, $newfilename);
if ($x['success'])
$resource = $x['resource_id'];
}
elseif ($folder !== $newfolder || $filename !== $newfilename) {
$x = attach_move($channel_id, $resource, $newfolder, $newfilename);
}
if ($categories) {
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
intval($channel['channel_id']),
intval($channel_id),
intval($attach_id),
intval(TERM_OBJ_FILE)
);
......@@ -61,31 +123,40 @@ class Attach_edit extends Controller {
foreach($cat as $term) {
$term = trim(escape_tags($term));
if ($term) {
$term_link = z_root() . '/cloud/' . $channel['channel_address'] . '/?cat=' . $term;
store_item_tag($channel['channel_id'], $attach_id, TERM_OBJ_FILE, TERM_CATEGORY, $term, $term_link);
$term_link = z_root() . '/cloud/' . $nick . '/?cat=' . $term;
store_item_tag($channel_id, $attach_id, TERM_OBJ_FILE, TERM_CATEGORY, $term, $term_link);
}
}
}
}
else {
q("DELETE FROM term WHERE uid = %d AND oid = %d AND otype = %d",
intval($channel['channel_id']),
intval($channel_id),
intval($attach_id),
intval(TERM_OBJ_FILE)
);
}
$sync = attach_export_data($channel, $resource, false);
if ($sync) {
Libsync::build_sync_packet($channel['channel_id'], ['file' => [$sync]]);
if($is_owner) {
$acl = new AccessList($channel);
$acl->set_from_array($_REQUEST);
$x = $acl->get();
attach_change_permissions($channel_id, $resource, $x['allow_cid'], $x['allow_gid'], $x['deny_cid'], $x['deny_gid'], $recurse, true);
if ($notify) {
attach_store_item($channel, $observer, $resource);
}
}
if ($notify) {
$observer = App::get_observer();
attach_store_item($channel, $observer, $resource);
$sync = attach_export_data($channel, $resource, false);
if ($sync) {
Libsync::build_sync_packet($channel_id, ['file' => [$sync]]);
}
$url = get_cloud_url($channel_id, $nick, $resource);
goaway(dirname($url));
}
......
......@@ -88,7 +88,7 @@ class Filestorage extends \Zotlabs\Web\Controller {
}
else {
notice( t('Permission denied.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
return;
}
......@@ -102,24 +102,23 @@ class Filestorage extends \Zotlabs\Web\Controller {
if(! $r) {
notice( t('File not found.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
goaway(z_root() . '/cloud/' . $which);
}
if(local_channel() !== $owner) {
if((local_channel() !== $owner) && !$admin_delete) {
if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
notice( t('Permission denied.') . EOL);
if($json_return)
if($json_return)
json_return_and_die([ 'success' => false ]);
goaway(z_root() . '/cloud/' . $which);
}
}
$f = $r[0];
$channel = channelx_by_n($owner);
......
......@@ -109,6 +109,7 @@ class Browser extends DAV\Browser\Plugin {
}
$folder_list = attach_folder_select_list($this->auth->owner_id);
$nick = $this->auth->owner_nick;
$owner = $this->auth->owner_id;
......@@ -231,6 +232,7 @@ class Browser extends DAV\Browser\Plugin {
);
$categories = [];
$terms_str = '';
if($terms) {
foreach($terms as $t) {
$term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
......@@ -334,7 +336,6 @@ class Browser extends DAV\Browser\Plugin {
'$edit' => t('Submit'),
'$delete' => t('Delete'),
'$nick' => $nick,
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
......
......@@ -43,7 +43,6 @@ $(document).ready(function () {
e.preventDefault();
let id = $(this).data('id');
$('.cloud-tool').hide();
$('.cloud-index').removeClass('cloud-index-active');
$('#id_categories_' + id).tagsinput({
tagClass: 'badge badge-pill badge-warning text-dark'
......@@ -58,6 +57,35 @@ $(document).ready(function () {
$('.cloud-tool').hide();
});
$('.cloud-tool-delete-btn').on('click', function (e) {
e.preventDefault();
let id = $(this).data('id');
$('.cloud-tool').hide();
$('.cloud-index').removeClass('cloud-index-active');
$('#cloud-index-' + id).addClass('cloud-index-active');
let confirm = confirmDelete();
if (confirm) {
$('body').css('cursor', 'wait');
$('#cloud-index-' + id).css('opacity', 0.33);
let form = $('#attach_edit_form_' + id).serializeArray();
form.push({name: 'delete', value: 1});
$.post('attach_edit', form, function (data) {
if (data.success) {
$('#cloud-index-' + id).remove();
$('body').css('cursor', 'auto');
}
return true;
});
}
return false;
});
$('.cloud-tool-cancel-btn').on('click', function (e) {
e.preventDefault();
let id = $(this).data('id');
......
......@@ -67,25 +67,29 @@
<td>{{$item.terms}}</td>
<td class="cloud-index-tool p-2">{{if $item.lockstate == 'lock'}}<i class="fa fa-fw fa-{{$item.lockstate}}"></i>{{/if}}</td>
<td class="cloud-index-tool">
{{if $item.is_owner && $item.attach_id}}
{{if ($item.is_owner || $item.is_creator) && $item.attach_id}}
<div class="dropdown">
<button class="btn btn-link btn-sm" id="dropdown-button-{{$item.attach_id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-button-{{$item.attach_id}}">
{{if $item.is_owner}}
<a id="cloud-tool-perms-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-perms-btn" href="#" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-{{$item.lockstate}}"></i> Adjust permissions</a>
{{/if}}
<a id="cloud-tool-rename-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-rename-btn" href="#" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-pencil"></i> Rename</a>
<a id="cloud-tool-move-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-move-btn" href="#" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-copy"></i> Move or copy</a>
<a id="cloud-tool-categories-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-categories-btn" href="#" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-asterisk"></i> Categories</a>
{{if !$item.collection}}
{{if $item.is_owner}}
<a id="cloud-tool-share-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-share-btn" href="/rpost?attachment=[attachment]{{$item.resource}},{{$item.revision}}[/attachment]&acl[allow_cid]={{$item.raw_allow_cid}}&acl[allow_gid]={{$item.raw_allow_gid}}&acl[deny_cid]={{$item.raw_deny_cid}}&acl[deny_gid]={{$item.raw_deny_gid}}" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-share-square-o"></i> Post</a>
{{/if}}
<a id="cloud-tool-download-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-download-btn" href="/attach/{{$item.resource}}" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-cloud-download"></i> Download</a>
{{/if}}
<a id="cloud-tool-delete-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-delete-btn" href="#" data-id="{{$item.attach_id}}" onclick="dropItem('{{$item.fileStorageUrl}}/{{$item.attach_id}}/delete/json', '#cloud-index-{{$item.attach_id}},#cloud-tools-{{$item.attach_id}}'); return false;"><i class="fa fa-fw fa-trash-o"></i> {{$delete}}</a>
<a id="cloud-tool-delete-btn-{{$item.attach_id}}" class="dropdown-item cloud-tool-delete-btn" href="#" data-id="{{$item.attach_id}}"><i class="fa fa-fw fa-trash-o"></i> {{$delete}}</a>
</div>
</div>
{{else}}
{{if ($item.is_creator || $is_admin || !$item.collection) && $item.attach_id}}
{{if ($is_admin || !$item.collection) && $item.attach_id}}
<div class="dropdown">
<button class="btn btn-link btn-sm" id="dropdown-button-{{$item.attach_id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-ellipsis-v"></i>
......@@ -107,11 +111,12 @@
</tr>
<tr id="cloud-tools-{{$item.attach_id}}" class="cloud-tools">
<td id="attach-edit-panel-{{$item.attach_id}}" colspan="7">
<form id="attach_edit_form_{{$item.attach_id}}" action="attach_edit/{{$nick}}/{{$item.attach_id}}" method="post" class="acl-form" data-form_id="attach_edit_form_{{$item.attach_id}}" data-allow_cid='{{$item.allow_cid}}' data-allow_gid='{{$item.allow_gid}}' data-deny_cid='{{$item.deny_cid}}' data-deny_gid='{{$item.deny_gid}}'>
<form id="attach_edit_form_{{$item.attach_id}}" action="attach_edit" method="post" class="acl-form" data-form_id="attach_edit_form_{{$item.attach_id}}" data-allow_cid='{{$item.allow_cid}}' data-allow_gid='{{$item.allow_gid}}' data-deny_cid='{{$item.deny_cid}}' data-deny_gid='{{$item.deny_gid}}'>
<input type="hidden" name="attach_id" value="{{$item.attach_id}}" />
<input type="hidden" name="resource" value="{{$item.resource}}" />
<input type="hidden" name="nick" value="{{$nick}}" />
<!--input type="hidden" name="resource" value="{{$item.resource}}" />
<input type="hidden" name="filename" value="{{$item.name}}" />
<input type="hidden" name="folder" value="{{$item.folder}}" />
<input type="hidden" name="folder" value="{{$item.folder}}" /-->
<div id="cloud-tool-rename-{{$item.attach_id}}" class="cloud-tool">
{{include file="field_input.tpl" field=$item.newfilename}}
</div>
......@@ -123,16 +128,20 @@
{{include file="field_input.tpl" field=$item.categories}}
</div>
<div id="cloud-tool-submit-{{$item.attach_id}}" class="cloud-tool">
{{if $item.is_owner}}
{{if !$item.collection}}{{include file="field_checkbox.tpl" field=$item.notify}}{{/if}}
{{if $item.collection}}{{include file="field_checkbox.tpl" field=$item.recurse}}{{/if}}
{{/if}}
<div id="attach-submit-{{$item.attach_id}}" class="form-group">
<button id="cloud-tool-cancel-btn-{{$item.attach_id}}" class="btn btn-outline-secondary btn-sm cloud-tool-cancel-btn" type="button" data-id="{{$item.attach_id}}">
Cancel
</button>
<div id="attach-edit-perms-{{$item.attach_id}}" class="btn-group float-right">
{{if $item.is_owner}}
<button id="dbtn-acl-{{$item.attach_id}}" class="btn btn-outline-secondary btn-sm" data-toggle="modal" data-target="#aclModal" title="{{$permset}}" type="button">
<i id="jot-perms-icon-{{$item.attach_id}}" class="fa fa-{{$item.lockstate}} jot-icons jot-perms-icon"></i>
</button>
{{/if}}
<button id="dbtn-submit-{{$item.attach_id}}" class="btn btn-primary btn-sm" type="submit" name="submit">
{{$edit}}
</button>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment