From 2283332ed236dd363145ed067e0f075ca2ff3751 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Thu, 5 May 2022 11:19:43 +0300 Subject: extended formats --- lib/appconfig.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/appconfig.php b/lib/appconfig.php index 620c4ca..4b2b68a 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -1100,8 +1100,8 @@ class AppConfig { "csv" => [ "mime" => "text/csv", "type" => "cell", "edit" => true, "editable" => true, "saveas" => ["ods", "pdf", "xlsx"] ], "doc" => [ "mime" => "application/msword", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ], "docm" => [ "mime" => "application/vnd.ms-word.document.macroEnabled.12", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ], - "docx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "type" => "word", "edit" => true, "def" => true, "saveas" => ["odt", "pdf", "rtf", "txt", "docxf"] ], - "docxf" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf", "type" => "word", "edit" => true, "def" => true, "saveas" => ["odt", "pdf", "rtf", "txt"], "createForm" => true ], + "docx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt", "docxf"] ], + "docxf" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.docxf", "type" => "word", "edit" => true, "def" => true, "review" => true, "comment" => true, "saveas" => ["odt", "pdf", "rtf", "txt"], "createForm" => true ], "oform" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document.oform", "type" => "word", "fillForms" => true, "def" => true ], "dot" => [ "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ], "dotx" => [ "mime" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "type" => "word", "conv" => true, "saveas" => ["docx", "odt", "pdf", "rtf", "txt"] ], @@ -1123,12 +1123,12 @@ class AppConfig { "ppsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ], "ppt" => [ "mime" => "application/vnd.ms-powerpoint", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ], "pptm" => [ "mime" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12", "type" => "slide", "conv" => true, "saveas" => ["pdf", "pptx", "odp"] ], - "pptx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", "type" => "slide", "edit" => true, "def" => true, "saveas" => ["pdf", "odp"] ], + "pptx" => [ "mime" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", "type" => "slide", "edit" => true, "def" => true, "comment" => true, "saveas" => ["pdf", "odp"] ], "rtf" => [ "mime" => "text/rtf", "type" => "word", "conv" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "txt"] ], "txt" => [ "mime" => "text/plain", "type" => "word", "edit" => true, "editable" => true, "saveas" => ["docx", "odt", "pdf", "rtf"] ], "xls" => [ "mime" => "application/vnd.ms-excel", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ], "xlsm" => [ "mime" => "application/vnd.ms-excel.sheet.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ], - "xlsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "type" => "cell", "edit" => true, "def" => true, "saveas" => ["csv", "ods", "pdf"] ], + "xlsx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "type" => "cell", "edit" => true, "def" => true, "comment" => true, "modifyFilter" => true, "saveas" => ["csv", "ods", "pdf"] ], "xlt" => [ "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ], "xltm" => [ "mime" => "application/vnd.ms-excel.template.macroEnabled.12", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ], "xltx" => [ "mime" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "type" => "cell", "conv" => true, "saveas" => ["csv", "ods", "pdf", "xlsx"] ] -- cgit v1.2.3 From 2ac37457cebba68c0b3f0cffd532d3b9de7c7581 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Wed, 11 May 2022 18:36:31 +0300 Subject: added sharing tab --- css/share.css | 24 ++++++++++++++++++ js/main.js | 8 ++++++ js/share.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ templates/share.html | 8 ++++++ 4 files changed, 110 insertions(+) create mode 100644 css/share.css create mode 100644 js/share.js create mode 100644 templates/share.html diff --git a/css/share.css b/css/share.css new file mode 100644 index 0000000..a7b7822 --- /dev/null +++ b/css/share.css @@ -0,0 +1,24 @@ +/** + * + * (c) Copyright Ascensio System SIA 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +.icon-onlyoffice-sharing { + background-image: url("../img/app-dark.svg"); +} +.onlyoffice-share-item { + display: inline-flex; +} \ No newline at end of file diff --git a/js/main.js b/js/main.js index 797a767..3226d64 100644 --- a/js/main.js +++ b/js/main.js @@ -472,6 +472,12 @@ } }; + OCA.Onlyoffice.TabView = { + attach(fileList) { + fileList.registerTabView(new OCA.Onlyoffice.SharingTabView()) + } + } + var getFileExtension = function (fileName) { var extension = fileName.substr(fileName.lastIndexOf(".") + 1).toLowerCase(); return extension; @@ -561,6 +567,8 @@ } else { OC.Plugins.register("OCA.Files.NewFileMenu", OCA.Onlyoffice.NewFileMenu); + OC.Plugins.register("OCA.Files.FileList", OCA.Onlyoffice.TabView); + OCA.Onlyoffice.registerAction(); OCA.Onlyoffice.bindVersionClick(); diff --git a/js/share.js b/js/share.js new file mode 100644 index 0000000..704dc76 --- /dev/null +++ b/js/share.js @@ -0,0 +1,70 @@ +/** + * + * (c) Copyright Ascensio System SIA 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + (function ($, OC) { + + OCA.Onlyoffice = _.extend({ + AppName: "onlyoffice", + }, OCA.Onlyoffice); + + OCA.Onlyoffice.SharingTabView = OCA.Files.DetailTabView.extend({ + id: "onlyofficeSharingTabView", + className: "tab onlyofficeSharingTabView", + + template: null, + + initialize() { + OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments); + }, + + getLabel() { + return t(OCA.Onlyoffice.AppName, "Onlyoffice sharing") + }, + + getIcon() { + return "icon-onlyoffice-sharing" + }, + + render() { + var that = this; + + $("
").html(t(OCA.Onlyoffice.AppName, "Share files with ONLYOFFICE")).prependTo(that.$el); + $.get(OC.filePath(OCA.Onlyoffice.AppName, "templates", "share.html"), + function (tmpl) { + that.template = $(tmpl); + + that.$el.append(that.template); + }); + }, + + setFileInfo(fileInfo) { + if(fileInfo) { + this.render(); + } + }, + + canDisplay: function(fileInfo) { + if (fileInfo.isDirectory()) { + return false; + }; + + return true; + }, + }); + +})(jQuery, OC); \ No newline at end of file diff --git a/templates/share.html b/templates/share.html new file mode 100644 index 0000000..0194984 --- /dev/null +++ b/templates/share.html @@ -0,0 +1,8 @@ +
    +
  • +
    +
    + +
    +
  • +
\ No newline at end of file -- cgit v1.2.3 From 861c7bb7441fe34a4eb70221b165a94f913a494d Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Thu, 12 May 2022 19:16:06 +0300 Subject: display available shares list to tab --- appinfo/application.php | 14 +++ appinfo/routes.php | 3 +- controller/sharingapicontroller.php | 192 ++++++++++++++++++++++++++++++++++++ css/share.css | 22 ++++- js/share.js | 175 ++++++++++++++++++++++++++++++-- lib/extrapermissions.php | 117 ++++++++++++++++++++++ lib/listeners/fileslistener.php | 2 + templates/share.html | 17 ++-- 8 files changed, 525 insertions(+), 17 deletions(-) create mode 100644 controller/sharingapicontroller.php create mode 100644 lib/extrapermissions.php diff --git a/appinfo/application.php b/appinfo/application.php index c5c1ec8..fbbc7f6 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -44,6 +44,7 @@ use OCA\Onlyoffice\AppConfig; use OCA\Onlyoffice\Controller\CallbackController; use OCA\Onlyoffice\Controller\EditorController; use OCA\Onlyoffice\Controller\EditorApiController; +use OCA\Onlyoffice\Controller\SharingApiController; use OCA\Onlyoffice\Controller\SettingsController; use OCA\Onlyoffice\Controller\TemplateController; use OCA\Onlyoffice\Listeners\FilesListener; @@ -158,6 +159,19 @@ class Application extends App implements IBootstrap { ); }); + $context->registerService("SharingApiController", function (ContainerInterface $c) { + return new SharingApiController( + $c->get("AppName"), + $c->get("Request"), + $c->get("RootStorage"), + $c->get("Logger"), + $c->get("UserSession"), + $c->get("UserManager"), + $c->get("IManager"), + $this->appConfig + ); + }); + $context->registerService("EditorApiController", function (ContainerInterface $c) { return new EditorApiController( $c->get("AppName"), diff --git a/appinfo/routes.php b/appinfo/routes.php index 958be88..80ecd7e 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -48,6 +48,7 @@ return [ "ocs" => [ ["name" => "federation#key", "url" => "/api/v1/key", "verb" => "POST"], ["name" => "federation#keylock", "url" => "/api/v1/keylock", "verb" => "POST"], - ["name" => "editorapi#config", "url" => "/api/v1/config/{fileId}", "verb" => "GET"] + ["name" => "editorapi#config", "url" => "/api/v1/config/{fileId}", "verb" => "GET"], + ["name" => "sharingapi#get_shares", "url" => "/api/v1/shares/{fileId}", "verb" => "GET"] ] ]; \ No newline at end of file diff --git a/controller/sharingapicontroller.php b/controller/sharingapicontroller.php new file mode 100644 index 0000000..b317044 --- /dev/null +++ b/controller/sharingapicontroller.php @@ -0,0 +1,192 @@ +root = $root; + $this->logger = $logger; + $this->userSession = $userSession; + $this->userManager = $userManager; + $this->shareManager = $shareManager; + $this->appConfig = $appConfig; + } + + /** + * Get shares for file + * + * @param integer $fileId - file identifier + * + * @return DataResponse + * + * @NoAdminRequired + * @NoCSRFRequired + */ + public function getShares($fileId) { + $result = []; + + $userId = null; + $user = $this->userSession->getUser(); + if (!empty($user)) { + $userId = $user->getUID(); + } + + $file = null; + $userFolder = $this->root->getUserFolder($userId); + if (!empty($userFolder)) { + $files = $userFolder->getById($fileId); + if (!empty($files)) { + $file = $files[0]; + } + } + + if (empty($file)) { + $this->logger->error("getShares: file not found: " . $fileId, ["app" => $this->appName]); + return new DataResponse($result); + } + + $extension = pathinfo($file->getName())["extension"]; + + $formats = $this->appConfig->FormatsSetting(); + $format = $formats[$extension]; + + $shares = $this->shareManager->getSharesBy($userId, IShare::TYPE_USER, $file); + foreach ($shares as $share) { + + $available = false; + if (($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { + if (array_key_exists(ExtraPermissions::ModifyFilterName, $format)) { + $available = true; + } + } + if (($share->getPermissions() & Constants::PERMISSION_UPDATE) !== Constants::PERMISSION_UPDATE) { + if (array_key_exists(ExtraPermissions::ReviewName, $format) + || array_key_exists(ExtraPermissions::CommentName, $format) + || array_key_exists(ExtraPermissions::FillFormsName, $format)) { + $available = true; + } + } + + if (!$available) { + continue; + } + + $extra = ExtraPermissions::get($share->getId()); + if (empty($extra)) { + $extra["id"] = -1; + $extra["share_id"] = $share->getId(); + $extra["permissions"] = 0; + } + + $extra["shareWith"] = $share->getSharedWith(); + $extra["shareWithName"] = $share->getSharedWithDisplayName(); + + array_push($result, $extra); + } + + return new DataResponse($result); + } +} diff --git a/css/share.css b/css/share.css index a7b7822..bd913c2 100644 --- a/css/share.css +++ b/css/share.css @@ -20,5 +20,25 @@ background-image: url("../img/app-dark.svg"); } .onlyoffice-share-item { - display: inline-flex; + display: flex; + list-style-type: none; +} +.onlyoffice-share-popup { + margin-right: 14px; + margin-top: 44px; +} +.onlyoffice-share-item span { + margin-left: 10px; + margin-top: 5px; +} +#onlyoffice-share-menu { + margin-left: auto; +} +.onlyoffice-share-action { + line-height: 44px; +} +.onlyoffice-share-label { + padding-right: 14px !important; + padding-left: 14px !important; + opacity: .7; } \ No newline at end of file diff --git a/js/share.js b/js/share.js index 704dc76..1fec188 100644 --- a/js/share.js +++ b/js/share.js @@ -22,11 +22,25 @@ AppName: "onlyoffice", }, OCA.Onlyoffice); + OCA.Onlyoffice.Permissions = { + Review: 1, + Comment: 2, + FillForms: 4, + ModifyFilter: 8 + }; + OCA.Onlyoffice.SharingTabView = OCA.Files.DetailTabView.extend({ id: "onlyofficeSharingTabView", className: "tab onlyofficeSharingTabView", - template: null, + templateItem: null, + permissionsMenu: null, + collection: null, + format: null, + + events: { + 'click #onlyoffice-share-action': '_onClickPermissionMenu', + }, initialize() { OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments); @@ -43,18 +57,34 @@ render() { var that = this; - $("
").html(t(OCA.Onlyoffice.AppName, "Share files with ONLYOFFICE")).prependTo(that.$el); - $.get(OC.filePath(OCA.Onlyoffice.AppName, "templates", "share.html"), - function (tmpl) { - that.template = $(tmpl); + this._getTemplate(() => { + var container = this.$el.find(".onlyoffice-share-container"); - that.$el.append(that.template); + container.children().remove(); + this.collection.forEach(extra => { + var itemNode = that.templateItem.clone(); + var descNode = itemNode.find("span"); + var avatar = itemNode.find("img"); + + avatar[0].src = "/index.php/avatar/" + extra["shareWith"] + "/32?v=0"; + itemNode[0].id = extra.share_id; + descNode[0].innerText = extra.shareWithName; + + container.append(itemNode); }); + }); }, setFileInfo(fileInfo) { if(fileInfo) { - this.render(); + OCA.Onlyoffice.GetShares(fileInfo.id, (shares) => { + this.collection = shares; + + var ext = fileInfo.attributes.name.split(".").pop(); + this.format = OCA.Onlyoffice.setting.formats[ext]; + + this.render(); + }); } }, @@ -65,6 +95,137 @@ return true; }, + + _getTemplate: function(callback) { + if (this.templateItem) { + callback(); + return; + } + + var that = this; + $.get(OC.filePath(OCA.Onlyoffice.AppName, "templates", "share.html"), + function (tmpl) { + that.templateItem = $(tmpl); + + $("
    ", {class: "onlyoffice-share-container"}).appendTo(that.$el) + $("
    ").html(t(OCA.Onlyoffice.AppName, "Share files with ONLYOFFICE")).prependTo(that.$el); + + that.$el.append(that.template); + + callback(); + }); + }, + + _onClickPermissionMenu: function(e) { + if (!this.permissionsMenu) { + this.permissionsMenu = this._permissionMenu(); + } + + var shareNode = $(e.target).closest(".onlyoffice-share-item")[0]; + var shareId = shareNode.id; + + + if (this.permissionsMenu.isOpen()) { + var previousId = this.permissionsMenu.getTargetId(); + this.permissionsMenu.close(); + + if (previousId == shareId) return; + } + + var extra = this.collection.find(item => item.share_id == shareId); + + var review = false; + var comment = false; + var fillForms = false; + var modifyFilter = false; + if ("review" in this.format) { + review = (OCA.Onlyoffice.Permissions.Review & extra["permissions"]) === OCA.Onlyoffice.Permissions.Review; + this.permissionsMenu.appendItem(review, OCA.Onlyoffice.Permissions.Review, t(OCA.Onlyoffice.AppName, "Review")); + } + if ("comment" in this.format && !review) { + comment = (OCA.Onlyoffice.Permissions.Comment & extra["permissions"]) === OCA.Onlyoffice.Permissions.Comment; + this.permissionsMenu.appendItem(comment, OCA.Onlyoffice.Permissions.Comment, t(OCA.Onlyoffice.AppName, "Comment")); + } + if ("fillForms" in this.format && !review) { + fillForms = (OCA.Onlyoffice.Permissions.FillForms & extra["permissions"]) === OCA.Onlyoffice.Permissions.FillForms; + this.permissionsMenu.appendItem(fillForms, OCA.Onlyoffice.Permissions.FillForms, t(OCA.Onlyoffice.AppName, "FillForms")); + } + if ("modifyFilter" in this.format) { + modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & extra["permissions"]) === OCA.Onlyoffice.Permissions.ModifyFilter; + this.permissionsMenu.appendItem(modifyFilter, OCA.Onlyoffice.Permissions.ModifyFilter, t(OCA.Onlyoffice.AppName, "ModifyFilter")); + } + + this.permissionsMenu.open(extra.share_id, $(e.target).position()); + }, + + _permissionMenu: function() { + var popup = $("
    ", { + class: "popovermenu onlyoffice-share-popup" + }).append($("
      "), { + id: -1 + }); + + this.$el.append(popup); + + return { + isOpen: function() { + return popup.is(":visible"); + }, + + open: function(id, position) { + if (position) { + popup.css({top: position.top}); + } + + this.setTargetId(id); + popup.show(); + }, + + close: function() { + var items = popup.find("li"); + if (items) { + items.remove(); + } + + this.setTargetId(-1); + popup.hide(); + }, + + appendItem: function(checked, checkboxId, name) { + var item = $("
    • ").append($("", { + class: "onlyoffice-share-action" + }).append($("", { + id: checkboxId, + type: "checkbox", + class: "checkbox action-checkbox__checkbox focusable", + checked: checked + })).append($("
    • +
      + +
      + +
      + +
      +
    • \ No newline at end of file -- cgit v1.2.3 From a29d3ef1cf24b1396e2b5c42afccb2e228bdabb3 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 10:29:31 +0300 Subject: set extra permissions --- css/share.css | 2 +- js/share.js | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/css/share.css b/css/share.css index bd913c2..7d6ded5 100644 --- a/css/share.css +++ b/css/share.css @@ -23,7 +23,7 @@ display: flex; list-style-type: none; } -.onlyoffice-share-popup { +.onlyoffice-share-action { margin-right: 14px; margin-top: 44px; } diff --git a/js/share.js b/js/share.js index 1fec188..123874e 100644 --- a/js/share.js +++ b/js/share.js @@ -39,7 +39,8 @@ format: null, events: { - 'click #onlyoffice-share-action': '_onClickPermissionMenu', + "click #onlyoffice-share-action": "_onClickPermissionMenu", + "change .onlyoffice-share-action input": "_onClickSetPermissions" }, initialize() { @@ -116,6 +117,32 @@ }); }, + _onClickSetPermissions: function(e) { + var permissionValues = this.permissionsMenu.getValues(); + var shareId = this.permissionsMenu.getTargetId(); + var extra = this.collection.find(item => item.share_id == shareId); + + var permissions = 0; + permissionValues.forEach(permission => { + if (permission.value) { + permissions |= permission.id; + } + }); + + OCA.Onlyoffice.SetShares(extra.id, shareId, permissions, (extra) => { + this.collection.forEach(item => { + if (item.share_id == extra.share_id) { + item.id = extra.id; + item.permissions = extra.permissions; + } + }); + + var attributes = this._getPermissionAttributes(extra["permissions"]); + + this.permissionsMenu.refresh(attributes); + }); + }, + _onClickPermissionMenu: function(e) { if (!this.permissionsMenu) { this.permissionsMenu = this._permissionMenu(); @@ -134,28 +161,52 @@ var extra = this.collection.find(item => item.share_id == shareId); + var attributes = this._getPermissionAttributes(extra["permissions"]); + + this.permissionsMenu.open(extra.share_id, attributes, $(e.target).position()); + }, + + _getPermissionAttributes: function(permissions) { + var attributes = []; + var review = false; var comment = false; var fillForms = false; var modifyFilter = false; if ("review" in this.format) { - review = (OCA.Onlyoffice.Permissions.Review & extra["permissions"]) === OCA.Onlyoffice.Permissions.Review; - this.permissionsMenu.appendItem(review, OCA.Onlyoffice.Permissions.Review, t(OCA.Onlyoffice.AppName, "Review")); + review = (OCA.Onlyoffice.Permissions.Review & permissions) === OCA.Onlyoffice.Permissions.Review; + attributes.push({ + checked: review, + inputAttribute: OCA.Onlyoffice.Permissions.Review, + label: t(OCA.Onlyoffice.AppName, "Review") + }); } if ("comment" in this.format && !review) { - comment = (OCA.Onlyoffice.Permissions.Comment & extra["permissions"]) === OCA.Onlyoffice.Permissions.Comment; - this.permissionsMenu.appendItem(comment, OCA.Onlyoffice.Permissions.Comment, t(OCA.Onlyoffice.AppName, "Comment")); + comment = (OCA.Onlyoffice.Permissions.Comment & permissions) === OCA.Onlyoffice.Permissions.Comment; + attributes.push({ + checked: comment, + inputAttribute: OCA.Onlyoffice.Permissions.Comment, + label: t(OCA.Onlyoffice.AppName, "Comment") + }); } if ("fillForms" in this.format && !review) { - fillForms = (OCA.Onlyoffice.Permissions.FillForms & extra["permissions"]) === OCA.Onlyoffice.Permissions.FillForms; - this.permissionsMenu.appendItem(fillForms, OCA.Onlyoffice.Permissions.FillForms, t(OCA.Onlyoffice.AppName, "FillForms")); + fillForms = (OCA.Onlyoffice.Permissions.FillForms & permissions) === OCA.Onlyoffice.Permissions.FillForms; + attributes.push({ + checked: fillForms, + inputAttribute: OCA.Onlyoffice.Permissions.FillForms, + label: t(OCA.Onlyoffice.AppName, "FillForms") + }); } if ("modifyFilter" in this.format) { - modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & extra["permissions"]) === OCA.Onlyoffice.Permissions.ModifyFilter; - this.permissionsMenu.appendItem(modifyFilter, OCA.Onlyoffice.Permissions.ModifyFilter, t(OCA.Onlyoffice.AppName, "ModifyFilter")); + modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & permissions) === OCA.Onlyoffice.Permissions.ModifyFilter; + attributes.push({ + checked: modifyFilter, + inputAttribute: OCA.Onlyoffice.Permissions.ModifyFilter, + label: t(OCA.Onlyoffice.AppName, "ModifyFilter") + }); } - this.permissionsMenu.open(extra.share_id, $(e.target).position()); + return attributes; }, _permissionMenu: function() { @@ -172,11 +223,15 @@ return popup.is(":visible"); }, - open: function(id, position) { + open: function(id, attributes, position) { if (position) { popup.css({top: position.top}); } + attributes.forEach(attr => { + this.appendItem(attr.checked, attr.inputAttribute, attr.label); + }); + this.setTargetId(id); popup.show(); }, @@ -191,6 +246,17 @@ popup.hide(); }, + refresh: function(attributes) { + var items = popup.find("li"); + if (items) { + items.remove(); + } + + attributes.forEach(attr => { + this.appendItem(attr.checked, attr.inputAttribute, attr.label); + }); + }, + appendItem: function(checked, checkboxId, name) { var item = $("
    • ").append($("", { class: "onlyoffice-share-action" @@ -208,12 +274,26 @@ popup.find("ul").append(item); }, + getValues: function() { + var values = []; + + var items = popup.find("input"); + for (var i = 0; i < items.length; i++) { + values.push({ + id: items[i].id, + value: items[i].checked + }); + } + + return values; + }, + setTargetId: function(id) { popup.find("ul").attr("id", id); }, getTargetId: function() { - return Number(popup.find("ul").attr("id")); + return popup.find("ul").attr("id"); }, } } @@ -228,4 +308,21 @@ }) } + OCA.Onlyoffice.SetShares = function(id, shareId, permissions, callback) { + var data = { + extraId: id, + shareId: shareId, + permissions: permissions + } + + $.ajax({ + method: "POST", + url: OC.linkToOCS("apps/" + OCA.Onlyoffice.AppName + "/api/v1", 2) + "shares?format=json", + data: data, + success: function onSuccess(response) { + callback(response.ocs.data); + } + }) + } + })(jQuery, OC); \ No newline at end of file -- cgit v1.2.3 From 24cc77a4c8219426d4882c95fc4d2872a71afd1d Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 13:19:49 +0300 Subject: extended attributes validation for permissions --- js/share.js | 77 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/js/share.js b/js/share.js index 123874e..40cfc28 100644 --- a/js/share.js +++ b/js/share.js @@ -137,7 +137,7 @@ } }); - var attributes = this._getPermissionAttributes(extra["permissions"]); + var attributes = this._getPermissionAttributes(extra); this.permissionsMenu.refresh(attributes); }); @@ -161,49 +161,58 @@ var extra = this.collection.find(item => item.share_id == shareId); - var attributes = this._getPermissionAttributes(extra["permissions"]); + var attributes = this._getPermissionAttributes(extra); this.permissionsMenu.open(extra.share_id, attributes, $(e.target).position()); }, - _getPermissionAttributes: function(permissions) { + _getPermissionAttributes: function(extra) { var attributes = []; var review = false; var comment = false; var fillForms = false; var modifyFilter = false; - if ("review" in this.format) { - review = (OCA.Onlyoffice.Permissions.Review & permissions) === OCA.Onlyoffice.Permissions.Review; - attributes.push({ - checked: review, - inputAttribute: OCA.Onlyoffice.Permissions.Review, - label: t(OCA.Onlyoffice.AppName, "Review") - }); - } - if ("comment" in this.format && !review) { - comment = (OCA.Onlyoffice.Permissions.Comment & permissions) === OCA.Onlyoffice.Permissions.Comment; - attributes.push({ - checked: comment, - inputAttribute: OCA.Onlyoffice.Permissions.Comment, - label: t(OCA.Onlyoffice.AppName, "Comment") - }); - } - if ("fillForms" in this.format && !review) { - fillForms = (OCA.Onlyoffice.Permissions.FillForms & permissions) === OCA.Onlyoffice.Permissions.FillForms; - attributes.push({ - checked: fillForms, - inputAttribute: OCA.Onlyoffice.Permissions.FillForms, - label: t(OCA.Onlyoffice.AppName, "FillForms") - }); + + var read = (OC.PERMISSION_READ & extra["basePermissions"]) === OC.PERMISSION_READ; + var update = (OC.PERMISSION_UPDATE & extra["basePermissions"]) === OC.PERMISSION_UPDATE; + + if (!update && read) { + if ("review" in this.format) { + review = (OCA.Onlyoffice.Permissions.Review & extra["permissions"]) === OCA.Onlyoffice.Permissions.Review; + attributes.push({ + checked: review, + inputAttribute: OCA.Onlyoffice.Permissions.Review, + label: t(OCA.Onlyoffice.AppName, "Review") + }); + } + if ("comment" in this.format && !review) { + comment = (OCA.Onlyoffice.Permissions.Comment & extra["permissions"]) === OCA.Onlyoffice.Permissions.Comment; + attributes.push({ + checked: comment, + inputAttribute: OCA.Onlyoffice.Permissions.Comment, + label: t(OCA.Onlyoffice.AppName, "Comment") + }); + } + if ("fillForms" in this.format && !review) { + fillForms = (OCA.Onlyoffice.Permissions.FillForms & extra["permissions"]) === OCA.Onlyoffice.Permissions.FillForms; + attributes.push({ + checked: fillForms, + inputAttribute: OCA.Onlyoffice.Permissions.FillForms, + label: t(OCA.Onlyoffice.AppName, "FillForms") + }); + } } - if ("modifyFilter" in this.format) { - modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & permissions) === OCA.Onlyoffice.Permissions.ModifyFilter; - attributes.push({ - checked: modifyFilter, - inputAttribute: OCA.Onlyoffice.Permissions.ModifyFilter, - label: t(OCA.Onlyoffice.AppName, "ModifyFilter") - }); + + if (update) { + if ("modifyFilter" in this.format) { + modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & extra["permissions"]) === OCA.Onlyoffice.Permissions.ModifyFilter; + attributes.push({ + checked: modifyFilter, + inputAttribute: OCA.Onlyoffice.Permissions.ModifyFilter, + label: t(OCA.Onlyoffice.AppName, "ModifyFilter") + }); + } } return attributes; @@ -316,7 +325,7 @@ } $.ajax({ - method: "POST", + method: "PUT", url: OC.linkToOCS("apps/" + OCA.Onlyoffice.AppName + "/api/v1", 2) + "shares?format=json", data: data, success: function onSuccess(response) { -- cgit v1.2.3 From 9ece50a914a376b1a6964c84834e710346b3fc64 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 18:24:30 +0300 Subject: save permissions to db --- appinfo/routes.php | 3 ++- controller/sharingapicontroller.php | 42 +++++++++++++++++++++++++++++++++++++ lib/extrapermissions.php | 2 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 80ecd7e..7d1bc51 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -49,6 +49,7 @@ return [ ["name" => "federation#key", "url" => "/api/v1/key", "verb" => "POST"], ["name" => "federation#keylock", "url" => "/api/v1/keylock", "verb" => "POST"], ["name" => "editorapi#config", "url" => "/api/v1/config/{fileId}", "verb" => "GET"], - ["name" => "sharingapi#get_shares", "url" => "/api/v1/shares/{fileId}", "verb" => "GET"] + ["name" => "sharingapi#get_shares", "url" => "/api/v1/shares/{fileId}", "verb" => "GET"], + ["name" => "sharingapi#set_shares", "url" => "/api/v1/shares", "verb" => "PUT"] ] ]; \ No newline at end of file diff --git a/controller/sharingapicontroller.php b/controller/sharingapicontroller.php index b317044..cf1e526 100644 --- a/controller/sharingapicontroller.php +++ b/controller/sharingapicontroller.php @@ -19,6 +19,7 @@ namespace OCA\Onlyoffice\Controller; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\IL10N; @@ -31,6 +32,7 @@ use OCP\Files\IRootFolder; use OCP\IUserManager; use OCP\IUserSession; use OCP\Share\IShare; +use OCP\Share\Exceptions\ShareNotFound; use OCA\Onlyoffice\AppConfig; @@ -183,10 +185,50 @@ class SharingApiController extends OCSController { $extra["shareWith"] = $share->getSharedWith(); $extra["shareWithName"] = $share->getSharedWithDisplayName(); + $extra["basePermissions"] = $share->getPermissions(); array_push($result, $extra); } return new DataResponse($result); } + + /** + * Set shares for file + * + * @param integer $extraId - extra permission identifier + * @param integer $shareId - share identifier + * @param integer $permissions - permissions value + * + * @return DataResponse + * + * @NoAdminRequired + * @NoCSRFRequired + */ + public function setShares($extraId, $shareId, $permissions) { + try { + $share = $this->shareManager->getShareById('ocinternal:' . $shareId); + } catch (ShareNotFound $e) { + $this->logger->logException($e, ["message" => "setShares error", "app" => $this->appName]); + return new DataResponse([], Http::STATUS_NOT_FOUND); + } + + $success = false; + if ($extraId > 0) { + $success = ExtraPermissions::update($shareId, $permissions); + } else { + $success = ExtraPermissions::set($shareId, $permissions); + } + + $extra = null; + if ($success) { + $extra = ExtraPermissions::get($shareId); + } + + $extra["shareWith"] = $share->getSharedWith(); + $extra["shareWithName"] = $share->getSharedWithDisplayName(); + $extra["basePermissions"] = $share->getPermissions(); + + return new DataResponse($extra); + } } diff --git a/lib/extrapermissions.php b/lib/extrapermissions.php index 0ad5dd5..9a1123d 100644 --- a/lib/extrapermissions.php +++ b/lib/extrapermissions.php @@ -87,7 +87,7 @@ class ExtraPermissions { * * @return bool */ - public static function set($shareId, $value) { + public static function set($shareId, $permissions) { $connection = \OC::$server->getDatabaseConnection(); $insert = $connection->prepare(" INSERT INTO `*PREFIX*" . self::TableName_Key . "` -- cgit v1.2.3 From 5ffbd78f5dfe9e4a7797216d09c86352b1c26c1b Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 19:56:25 +0300 Subject: extra permissions to editor config --- controller/editorapicontroller.php | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/controller/editorapicontroller.php b/controller/editorapicontroller.php index 1703e03..334dfe5 100644 --- a/controller/editorapicontroller.php +++ b/controller/editorapicontroller.php @@ -47,6 +47,7 @@ use OCA\Onlyoffice\Crypt; use OCA\Onlyoffice\DocumentService; use OCA\Onlyoffice\FileUtility; use OCA\Onlyoffice\TemplateManager; +use OCA\Onlyoffice\ExtraPermissions; /** * Controller with the main functions @@ -304,6 +305,39 @@ class EditorApiController extends OCSController { $params["document"]["permissions"]["modifyFilter"] = $permissions_modifyFilter; } + $restrictedEditing = false; + $fileStorage = $file->getStorage(); + if (empty($shareToken) && $fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) { + $shareId = $fileStorage->getShareId(); + + $extraPermissions = ExtraPermissions::get($shareId); + if (!empty($extraPermissions)) { + $reviewPermission = ($extraPermissions["permissions"] & ExtraPermissions::Review) === ExtraPermissions::Review; + if ($reviewPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["review"] = $reviewPermission; + } + + $commentPermission = ($extraPermissions["permissions"] & ExtraPermissions::Comment) === ExtraPermissions::Comment; + if ($commentPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["comment"] = $commentPermission; + } + + $fillFormsPermission = ($extraPermissions["permissions"] & ExtraPermissions::FillForms) === ExtraPermissions::FillForms; + if ($fillFormsPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["fillForms"] = $fillFormsPermission; + } + + $modifyFilter = ($extraPermissions["permissions"] & ExtraPermissions::ModifyFilter) === ExtraPermissions::ModifyFilter; + if ($file->isUpdateable()) { + $restrictedEditing = true; + $params["document"]["permissions"]["modifyFilter"] = $modifyFilter; + } + } + } + $isTempLock = false; if ($version < 1 && \OC::$server->getAppManager()->isInstalled("files_lock")) { @@ -334,7 +368,7 @@ class EditorApiController extends OCSController { && !$isTempLock && (empty($shareToken) || ($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE); $params["document"]["permissions"]["edit"] = $editable; - if ($editable && ($canEdit || $canFillForms)) { + if (($editable || $restrictedEditing) && ($canEdit || $canFillForms)) { $hashCallback = $this->crypt->GetHash(["userId" => $userId, "fileId" => $file->getId(), "filePath" => $filePath, "shareToken" => $shareToken, "action" => "track"]); $callback = $this->urlGenerator->linkToRouteAbsolute($this->appName . ".callback.track", ["doc" => $hashCallback]); -- cgit v1.2.3 From b6f25f9ea62a38a288fb68a3a92779cace1e6faf Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 22:10:45 +0300 Subject: block menu when request --- js/share.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/share.js b/js/share.js index 40cfc28..7d273ca 100644 --- a/js/share.js +++ b/js/share.js @@ -129,6 +129,7 @@ } }); + this.permissionsMenu.block(true); OCA.Onlyoffice.SetShares(extra.id, shareId, permissions, (extra) => { this.collection.forEach(item => { if (item.share_id == extra.share_id) { @@ -140,6 +141,7 @@ var attributes = this._getPermissionAttributes(extra); this.permissionsMenu.refresh(attributes); + this.permissionsMenu.block(false); }); }, @@ -266,6 +268,10 @@ }); }, + block: function(value) { + popup.find("input").prop("disabled", value); + }, + appendItem: function(checked, checkboxId, name) { var item = $("
    • ").append($("", { class: "onlyoffice-share-action" -- cgit v1.2.3 From 076aa4fbd9f934718bdfdbb71643c54121563cc1 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Tue, 17 May 2022 22:20:02 +0300 Subject: added db migration for permissions --- lib/Migration/Version070000Date20220516111111.php | 89 +++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 lib/Migration/Version070000Date20220516111111.php diff --git a/lib/Migration/Version070000Date20220516111111.php b/lib/Migration/Version070000Date20220516111111.php new file mode 100644 index 0000000..eaed59b --- /dev/null +++ b/lib/Migration/Version070000Date20220516111111.php @@ -0,0 +1,89 @@ +hasTable('onlyoffice_filekey')) { + $table = $schema->createTable('onlyoffice_filekey'); + $table->addColumn('id', 'integer', [ + 'autoincrement' => true, + 'notnull' => true, + ]); + $table->addColumn('file_id', 'bigint', [ + 'notnull' => false, + 'default' => '-1', + ]); + $table->addColumn('key', 'string', [ + 'notnull' => true, + 'length' => 128, + ]); + $table->addColumn('lock', 'integer', [ + 'notnull' => true, + 'default' => 0, + ]); + $table->addColumn('fs', 'integer', [ + 'notnull' => true, + 'default' => 0, + ]); + $table->setPrimaryKey(['id']); + $table->addUniqueIndex(['file_id'], 'file_id_index'); + } + + if (!$schema->hasTable('onlyoffice_permissions')) { + $table = $schema->createTable('onlyoffice_permissions'); + $table->addColumn('id', 'integer', [ + 'autoincrement' => true, + 'notnull' => true, + ]); + $table->addColumn('share_id', 'bigint', [ + 'notnull' => true, + 'default' => '-1', + ]); + $table->addColumn('permissions', 'integer', [ + 'notnull' => true, + 'default' => 0, + ]); + $table->setPrimaryKey(['id']); + $table->addUniqueIndex(['share_id'], 'share_id_index'); + } + + return $schema; + } + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { + } +} -- cgit v1.2.3 From 1141f45360bf4e8156e320c1fc646efd88ac691f Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Wed, 18 May 2022 19:30:18 +0300 Subject: build default permission if extra permissions isn't set --- controller/editorapicontroller.php | 45 ++++++---- controller/sharingapicontroller.php | 83 ++++++------------- lib/extrapermissions.php | 161 +++++++++++++++++++++++++++++++++--- 3 files changed, 204 insertions(+), 85 deletions(-) diff --git a/controller/editorapicontroller.php b/controller/editorapicontroller.php index 334dfe5..bf6d070 100644 --- a/controller/editorapicontroller.php +++ b/controller/editorapicontroller.php @@ -131,6 +131,13 @@ class EditorApiController extends OCSController { */ private $tagManager; + /** + * Extra permissions + * + * @var ExtraPermissions + */ + private $extraPermissions; + /** * Mobile regex from https://github.com/ONLYOFFICE/CommunityServer/blob/v9.1.1/web/studio/ASC.Web.Studio/web.appsettings.config#L35 */ @@ -186,6 +193,7 @@ class EditorApiController extends OCSController { } $this->fileUtility = new FileUtility($AppName, $trans, $logger, $config, $shareManager, $session); + $this->extraPermissions = new ExtraPermissions($AppName, $logger, $shareManager, $config); } /** @@ -310,29 +318,34 @@ class EditorApiController extends OCSController { if (empty($shareToken) && $fileStorage->instanceOfStorage("\OCA\Files_Sharing\SharedStorage")) { $shareId = $fileStorage->getShareId(); - $extraPermissions = ExtraPermissions::get($shareId); + $extraPermissions = $this->extraPermissions->getByShareId($shareId); if (!empty($extraPermissions)) { - $reviewPermission = ($extraPermissions["permissions"] & ExtraPermissions::Review) === ExtraPermissions::Review; - if ($reviewPermission) { - $restrictedEditing = true; - $params["document"]["permissions"]["review"] = $reviewPermission; + if (isset($format["review"]) && $format["review"]) { + $reviewPermission = ($extraPermissions["permissions"] & ExtraPermissions::Review) === ExtraPermissions::Review; + if ($reviewPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["review"] = true; + } } - $commentPermission = ($extraPermissions["permissions"] & ExtraPermissions::Comment) === ExtraPermissions::Comment; - if ($commentPermission) { - $restrictedEditing = true; - $params["document"]["permissions"]["comment"] = $commentPermission; + if (isset($format["comment"]) && $format["comment"]) { + $commentPermission = ($extraPermissions["permissions"] & ExtraPermissions::Comment) === ExtraPermissions::Comment; + if ($commentPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["comment"] = true; + } } - $fillFormsPermission = ($extraPermissions["permissions"] & ExtraPermissions::FillForms) === ExtraPermissions::FillForms; - if ($fillFormsPermission) { - $restrictedEditing = true; - $params["document"]["permissions"]["fillForms"] = $fillFormsPermission; + if (isset($format["fillForms"]) && $format["fillForms"]) { + $fillFormsPermission = ($extraPermissions["permissions"] & ExtraPermissions::FillForms) === ExtraPermissions::FillForms; + if ($fillFormsPermission) { + $restrictedEditing = true; + $params["document"]["permissions"]["fillForms"] = true; + } } - $modifyFilter = ($extraPermissions["permissions"] & ExtraPermissions::ModifyFilter) === ExtraPermissions::ModifyFilter; - if ($file->isUpdateable()) { - $restrictedEditing = true; + if (isset($format["modifyFilter"]) && $format["modifyFilter"]) { + $modifyFilter = ($extraPermissions["permissions"] & ExtraPermissions::ModifyFilter) === ExtraPermissions::ModifyFilter; $params["document"]["permissions"]["modifyFilter"] = $modifyFilter; } } diff --git a/controller/sharingapicontroller.php b/controller/sharingapicontroller.php index cf1e526..f081da0 100644 --- a/controller/sharingapicontroller.php +++ b/controller/sharingapicontroller.php @@ -88,6 +88,13 @@ class SharingApiController extends OCSController { */ private $shareManager; + /** + * Extra permissions + * + * @var ExtraPermissions + */ + private $extraPermissions; + /** * @param string $AppName - application name * @param IRequest $request - request object @@ -115,6 +122,8 @@ class SharingApiController extends OCSController { $this->userManager = $userManager; $this->shareManager = $shareManager; $this->appConfig = $appConfig; + + $this->extraPermissions = new ExtraPermissions($AppName, $logger, $shareManager, $appConfig); } /** @@ -130,63 +139,31 @@ class SharingApiController extends OCSController { public function getShares($fileId) { $result = []; - $userId = null; $user = $this->userSession->getUser(); - if (!empty($user)) { - $userId = $user->getUID(); - } + $userId = $user->getUID(); - $file = null; - $userFolder = $this->root->getUserFolder($userId); - if (!empty($userFolder)) { - $files = $userFolder->getById($fileId); - if (!empty($files)) { - $file = $files[0]; - } + try { + $folder = $this->root->getUserFolder($userId); + $files = $folder->getById($fileId); + } catch (\Exception $e) { + $this->logger->logException($e, ["message" => "getShares: $fileId", "app" => $this->appName]); + return new DataResponse([], Http::STATUS_BAD_REQUEST); } - if (empty($file)) { + if (empty($files)) { $this->logger->error("getShares: file not found: " . $fileId, ["app" => $this->appName]); - return new DataResponse($result); + return new DataResponse([], Http::STATUS_BAD_REQUEST); } - $extension = pathinfo($file->getName())["extension"]; - - $formats = $this->appConfig->FormatsSetting(); - $format = $formats[$extension]; + $file = $files[0]; $shares = $this->shareManager->getSharesBy($userId, IShare::TYPE_USER, $file); foreach ($shares as $share) { - - $available = false; - if (($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { - if (array_key_exists(ExtraPermissions::ModifyFilterName, $format)) { - $available = true; - } - } - if (($share->getPermissions() & Constants::PERMISSION_UPDATE) !== Constants::PERMISSION_UPDATE) { - if (array_key_exists(ExtraPermissions::ReviewName, $format) - || array_key_exists(ExtraPermissions::CommentName, $format) - || array_key_exists(ExtraPermissions::FillFormsName, $format)) { - $available = true; - } - } - - if (!$available) { + $extra = $this->extraPermissions->getByShare($share); + if ($extra === null) { continue; } - $extra = ExtraPermissions::get($share->getId()); - if (empty($extra)) { - $extra["id"] = -1; - $extra["share_id"] = $share->getId(); - $extra["permissions"] = 0; - } - - $extra["shareWith"] = $share->getSharedWith(); - $extra["shareWithName"] = $share->getSharedWithDisplayName(); - $extra["basePermissions"] = $share->getPermissions(); - array_push($result, $extra); } @@ -210,24 +187,14 @@ class SharingApiController extends OCSController { $share = $this->shareManager->getShareById('ocinternal:' . $shareId); } catch (ShareNotFound $e) { $this->logger->logException($e, ["message" => "setShares error", "app" => $this->appName]); - return new DataResponse([], Http::STATUS_NOT_FOUND); - } - - $success = false; - if ($extraId > 0) { - $success = ExtraPermissions::update($shareId, $permissions); - } else { - $success = ExtraPermissions::set($shareId, $permissions); + return new DataResponse([], Http::STATUS_BAD_REQUEST); } - $extra = null; - if ($success) { - $extra = ExtraPermissions::get($shareId); + if (!$this->extraPermissions->setShare($share, $permissions, $extraId)) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); } - $extra["shareWith"] = $share->getSharedWith(); - $extra["shareWithName"] = $share->getSharedWithDisplayName(); - $extra["basePermissions"] = $share->getPermissions(); + $extra = $this->extraPermissions->getByShare($share); return new DataResponse($extra); } diff --git a/lib/extrapermissions.php b/lib/extrapermissions.php index 9a1123d..15a80f2 100644 --- a/lib/extrapermissions.php +++ b/lib/extrapermissions.php @@ -19,6 +19,14 @@ namespace OCA\Onlyoffice; +use OCP\Constants; +use OCP\ILogger; +use OCP\Share\IShare; +use OCP\Share\IManager; +use OCP\Share\Exceptions\ShareNotFound; + +use OCA\Onlyoffice\AppConfig; + /** * Class expands base permissions * @@ -31,7 +39,28 @@ class ExtraPermissions { * * @var string */ - private const App_Name = "onlyoffice"; + private $appName; + + /** + * Logger + * + * @var ILogger + */ + private $logger; + + /** + * Share manager + * + * @var IManager + */ + private $shareManager; + + /** + * Application configuration + * + * @var AppConfig + */ + private $config; /** * Table name @@ -43,29 +72,139 @@ class ExtraPermissions { * * @var integer */ + public const None = 0; public const Review = 1; public const Comment = 2; public const FillForms = 4; public const ModifyFilter = 8; /** - * Extra permission names + * @param string $AppName - application name + * @param ILogger $logger - logger + * @param AppConfig $config - application configuration + * @param IManager $shareManager - Share manager + */ + public function __construct($AppName, + ILogger $logger, + IManager $shareManager, + AppConfig $config) { + $this->appName = $AppName; + $this->logger = $logger; + $this->shareManager = $shareManager; + $this->config = $config; + } + + /** + * Get extra permissions by shareId * - * @var string + * @param integer $shareId - share identifier + * + * @return array */ - public const ReviewName = "review"; - public const CommentName = "comment"; - public const FillFormsName = "fillForms"; - public const ModifyFilterName = "modifyFilter"; + public function getByShareId($shareId) { + try { + $share = $this->shareManager->getShareById("ocinternal:" . $shareId); + } catch (ShareNotFound $e) { + $this->logger->logException($e, ["message" => "getByShareId error", "app" => $this->appName]); + return null; + } + + return $this->getByShare($share); + } + + /** + * Get extra permissions by share + * + * @param IShare $shareId - share identifier + * + * @return array + */ + public function getByShare($share) { + list($available, $defaultPermissions) = $this->validation($share); + if(!$available) { + $this->logger->debug("Share " . $shareId . " does not support extra permissions", ["app" => $this->appName]); + return null; + } + + $shareId = $share->getId(); + $extra = self::get($shareId); + + if(empty($extra)) { + $extra["id"] = -1; + $extra["share_id"] = $share->getId(); + $extra["permissions"] = $defaultPermissions; + } + + $extra["shareWith"] = $share->getSharedWith(); + $extra["shareWithName"] = $share->getSharedWithDisplayName(); + $extra["basePermissions"] = $share->getPermissions(); + + return $extra; + } + + /** + * Get extra permissions by share + * + * @param IShare $share - share + * @param integer $permissions - value extra permissions + * @param integer $extraId - extra permission identifier + * + * @return bool + */ + public function setShare($share, $permissions, $extraId) { + $result = false; + + if ($extraId > 0) { + $result = self::update($share->getId(), $permissions); + } else { + $result = self::insert($share->getId(), $permissions); + } + + return $result; + } + + /** + * Validation share on extend capability by extra permissions + * + * @param IShare $share - share + * + * @return array + */ + private function validation($share) { + $node = $share->getNode(); + $fileInfo = $node->getFileInfo(); + + $pathinfo = pathinfo($fileInfo->getName()); + $extension = $pathinfo["extension"]; + $format = $this->config->FormatsSetting()[$extension]; + + $available = false; + $defaultPermissions = self::None; + if (($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { + if (isset($format["modifyFilter"]) && $format["modifyFilter"]) { + $available = true; + $defaultPermissions |= self::ModifyFilter; + } + } + if (($share->getPermissions() & Constants::PERMISSION_UPDATE) !== Constants::PERMISSION_UPDATE) { + if (isset($format["review"]) && $format["review"] + || isset($format["comment"]) && $format["comment"] + || isset($format["fillForms"]) && $format["fillForms"]) { + $available = true; + } + } + + return [$available, $defaultPermissions]; + } /** * Get extra permissions for share * * @param integer $shareId - share identifier * - * @return integer + * @return array */ - public static function get($shareId) { + private static function get($shareId) { $connection = \OC::$server->getDatabaseConnection(); $select = $connection->prepare(" SELECT id, share_id, permissions @@ -87,7 +226,7 @@ class ExtraPermissions { * * @return bool */ - public static function set($shareId, $permissions) { + private static function insert($shareId, $permissions) { $connection = \OC::$server->getDatabaseConnection(); $insert = $connection->prepare(" INSERT INTO `*PREFIX*" . self::TableName_Key . "` @@ -105,7 +244,7 @@ class ExtraPermissions { * * @return bool */ - public static function update($shareId, $permissions) { + private static function update($shareId, $permissions) { $connection = \OC::$server->getDatabaseConnection(); $update = $connection->prepare(" UPDATE `*PREFIX*" . self::TableName_Key . "` -- cgit v1.2.3 From 4dcf6dd878f36c232bac5e2bebf7a80452b81448 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Thu, 19 May 2022 18:52:11 +0300 Subject: changed getting shares list --- controller/sharingapicontroller.php | 13 +------ lib/extrapermissions.php | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/controller/sharingapicontroller.php b/controller/sharingapicontroller.php index f081da0..fb204a1 100644 --- a/controller/sharingapicontroller.php +++ b/controller/sharingapicontroller.php @@ -137,8 +137,6 @@ class SharingApiController extends OCSController { * @NoCSRFRequired */ public function getShares($fileId) { - $result = []; - $user = $this->userSession->getUser(); $userId = $user->getUID(); @@ -158,16 +156,9 @@ class SharingApiController extends OCSController { $file = $files[0]; $shares = $this->shareManager->getSharesBy($userId, IShare::TYPE_USER, $file); - foreach ($shares as $share) { - $extra = $this->extraPermissions->getByShare($share); - if ($extra === null) { - continue; - } - - array_push($result, $extra); - } + $extras = $this->extraPermissions->getShares($shares); - return new DataResponse($result); + return new DataResponse($extras); } /** diff --git a/lib/extrapermissions.php b/lib/extrapermissions.php index 15a80f2..75dd2b2 100644 --- a/lib/extrapermissions.php +++ b/lib/extrapermissions.php @@ -142,6 +142,53 @@ class ExtraPermissions { return $extra; } + /** + * Get list extra permissions by shares + * + * @param array $shares - array of shares + * + * @return array + */ + public function getShares($shares) { + $result = []; + + $shareIds = []; + foreach ($shares as $share) { + list($available, $defaultPermissions) = $this->validation($share); + if (!$available) { + $this->logger->debug("Share " . $shareId . " does not support extra permissions", ["app" => $this->appName]); + continue; + } + + array_push($result, [ + "id" => -1, + "share_id" => $share->getId(), + "permissions" => $defaultPermissions, + "shareWith" => $share->getSharedWith(), + "shareWithName" => $share->getSharedWithDisplayName(), + "basePermissions" => $share->getPermissions() + ]); + + array_push($shareIds, $share->getId()); + } + + if (empty($shareIds)) { + return $result; + } + + $extras = self::getList($shareIds); + foreach ($extras as $extra) { + foreach ($result as &$changeExtra) { + if ($extra["share_id"] === $changeExtra["share_id"]) { + $changeExtra["id"] = $extra["id"]; + $changeExtra["permissions"] = $extra["permissions"]; + } + } + } + + return $result; + } + /** * Get extra permissions by share * @@ -218,6 +265,36 @@ class ExtraPermissions { return $values; } + /** + * Get list extra permissions + * + * @param array $shareIds - array of share identifiers + * + * @return array + */ + private static function getList($shareIds) { + $connection = \OC::$server->getDatabaseConnection(); + + $condition = ""; + if (count($shareIds) > 1) { + for($i = 1; $i < count($shareIds); $i++) { + $condition = $condition . " OR `share_id` = ?"; + } + } + + $select = $connection->prepare(" + SELECT id, share_id, permissions + FROM `*PREFIX*" . self::TableName_Key . "` + WHERE `share_id` = ? + " . $condition); + + $result = $select->execute($shareIds); + + $values = $result ? $select->fetchAll() : []; + + return $values; + } + /** * Store extra permissions for share * -- cgit v1.2.3 From c3d2f8d85e0191daeb44dfa3efb9357585116038 Mon Sep 17 00:00:00 2001 From: Antipkin-A Date: Fri, 20 May 2022 12:45:17 +0300 Subject: format tab --- js/share.js | 96 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/js/share.js b/js/share.js index 7d273ca..0c358b6 100644 --- a/js/share.js +++ b/js/share.js @@ -33,6 +33,7 @@ id: "onlyofficeSharingTabView", className: "tab onlyofficeSharingTabView", + fileInfo: null, templateItem: null, permissionsMenu: null, collection: null, @@ -56,34 +57,35 @@ }, render() { - var that = this; + var self = this; this._getTemplate(() => { - var container = this.$el.find(".onlyoffice-share-container"); - - container.children().remove(); this.collection.forEach(extra => { - var itemNode = that.templateItem.clone(); + var itemNode = self.templateItem.clone(); var descNode = itemNode.find("span"); var avatar = itemNode.find("img"); avatar[0].src = "/index.php/avatar/" + extra["shareWith"] + "/32?v=0"; itemNode[0].id = extra.share_id; descNode[0].innerText = extra.shareWithName; - - container.append(itemNode); + + self._getContainer().append(itemNode); }); }); }, setFileInfo(fileInfo) { if(fileInfo) { - OCA.Onlyoffice.GetShares(fileInfo.id, (shares) => { - this.collection = shares; + this.fileInfo = fileInfo; - var ext = fileInfo.attributes.name.split(".").pop(); - this.format = OCA.Onlyoffice.setting.formats[ext]; + this._getContainer().children().remove(); + OCA.Onlyoffice.GetShares(this.fileInfo.id, (shares) => { + this.collection = shares; + + var ext = this.fileInfo.attributes.name.split(".").pop(); + this.format = OCA.Onlyoffice.setting.formats[ext]; + this.render(); }); } @@ -97,21 +99,23 @@ return true; }, + _getContainer: function() { + return this.$el.find(".onlyoffice-share-container"); + }, + _getTemplate: function(callback) { if (this.templateItem) { callback(); return; } - var that = this; + var self = this; $.get(OC.filePath(OCA.Onlyoffice.AppName, "templates", "share.html"), function (tmpl) { - that.templateItem = $(tmpl); - - $("
        ", {class: "onlyoffice-share-container"}).appendTo(that.$el) - $("
        ").html(t(OCA.Onlyoffice.AppName, "Share files with ONLYOFFICE")).prependTo(that.$el); + self.templateItem = $(tmpl); - that.$el.append(that.template); + $("
          ", {class: "onlyoffice-share-container"}).appendTo(self.$el) + $("
          ").html(t(OCA.Onlyoffice.AppName, "Share files with ONLYOFFICE")).prependTo(self.$el); callback(); }); @@ -180,7 +184,7 @@ var update = (OC.PERMISSION_UPDATE & extra["basePermissions"]) === OC.PERMISSION_UPDATE; if (!update && read) { - if ("review" in this.format) { + if (this.format["review"]) { review = (OCA.Onlyoffice.Permissions.Review & extra["permissions"]) === OCA.Onlyoffice.Permissions.Review; attributes.push({ checked: review, @@ -188,7 +192,7 @@ label: t(OCA.Onlyoffice.AppName, "Review") }); } - if ("comment" in this.format && !review) { + if (this.format["comment"] && !review) { comment = (OCA.Onlyoffice.Permissions.Comment & extra["permissions"]) === OCA.Onlyoffice.Permissions.Comment; attributes.push({ checked: comment, @@ -196,7 +200,7 @@ label: t(OCA.Onlyoffice.AppName, "Comment") }); } - if ("fillForms" in this.format && !review) { + if (this.format["fillForms"] && !review) { fillForms = (OCA.Onlyoffice.Permissions.FillForms & extra["permissions"]) === OCA.Onlyoffice.Permissions.FillForms; attributes.push({ checked: fillForms, @@ -207,7 +211,7 @@ } if (update) { - if ("modifyFilter" in this.format) { + if (this.format["modifyFilter"]) { modifyFilter = (OCA.Onlyoffice.Permissions.ModifyFilter & extra["permissions"]) === OCA.Onlyoffice.Permissions.ModifyFilter; attributes.push({ checked: modifyFilter, @@ -227,6 +231,27 @@ id: -1 }); + var appendItem = function(checked, inputAttribute, name) { + var item = $("
        • ").append($("", { + class: "onlyoffice-share-action" + }).append($("", { + id: inputAttribute, + type: "checkbox", + class: "checkbox action-checkbox__checkbox focusable", + checked: checked + })).append($("
        • ").append($("", { - class: "onlyoffice-share-action" - }).append($("", { - id: checkboxId, - type: "checkbox", - class: "checkbox action-checkbox__checkbox focusable", - checked: checked - })).append($("