Skip to content

Commit

Permalink
Merge pull request #33420 from owncloud/collaborative-tags-new-catego…
Browse files Browse the repository at this point in the history
…ry-work-stable10

[stable10] Backport of new tag editable added to systemtag
  • Loading branch information
Vincent Petry authored Nov 5, 2018
2 parents f4f25e1 + dd27c3c commit 9839041
Show file tree
Hide file tree
Showing 18 changed files with 474 additions and 101 deletions.
5 changes: 3 additions & 2 deletions apps/dav/lib/SystemTag/SystemTagNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,12 @@ public function setName($name) {
* @param string $name new tag name
* @param bool $userVisible user visible
* @param bool $userAssignable user assignable
* @param bool $userEditable user editable
* @throws NotFound whenever the given tag id does not exist
* @throws Forbidden whenever there is no permission to update said tag
* @throws Conflict whenever a tag already exists with the given attributes
*/
public function update($name, $userVisible, $userAssignable) {
public function update($name, $userVisible, $userAssignable, $userEditable = false) {
try {
if (!$this->tagManager->canUserSeeTag($this->tag, $this->user)) {
throw new NotFound('Tag with id ' . $this->tag->getId() . ' does not exist');
Expand All @@ -134,7 +135,7 @@ public function update($name, $userVisible, $userAssignable) {
}
}

$this->tagManager->updateTag($this->tag->getId(), $name, $userVisible, $userAssignable);
$this->tagManager->updateTag($this->tag->getId(), $name, $userVisible, $userAssignable, $userEditable);
} catch (TagNotFoundException $e) {
throw new NotFound('Tag with id ' . $this->tag->getId() . ' does not exist');
} catch (TagAlreadyExistsException $e) {
Expand Down
35 changes: 32 additions & 3 deletions apps/dav/lib/SystemTag/SystemTagPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
const ID_PROPERTYNAME = '{http://owncloud.org/ns}id';
const DISPLAYNAME_PROPERTYNAME = '{http://owncloud.org/ns}display-name';
const USERVISIBLE_PROPERTYNAME = '{http://owncloud.org/ns}user-visible';
const USEREDITABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-editable';
const USERASSIGNABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-assignable';
const GROUPS_PROPERTYNAME = '{http://owncloud.org/ns}groups';
const CANASSIGN_PROPERTYNAME = '{http://owncloud.org/ns}can-assign';
const WHITELISTEDINGROUP = '{http://owncloud.org/ns}editable-in-group';

/**
* @var \Sabre\DAV\Server $server
Expand Down Expand Up @@ -172,6 +174,7 @@ private function createTag($data, $contentType = 'application/json') {
$tagName = $data['name'];
$userVisible = true;
$userAssignable = true;
$userEditable = false;

if (isset($data['userVisible'])) {
$userVisible = (bool)$data['userVisible'];
Expand All @@ -181,6 +184,10 @@ private function createTag($data, $contentType = 'application/json') {
$userAssignable = (bool)$data['userAssignable'];
}

if (isset($data['userEditable'])) {
$userEditable = (bool)$data['userEditable'];
}

$groups = [];
if (isset($data['groups'])) {
$groups = $data['groups'];
Expand All @@ -196,7 +203,7 @@ private function createTag($data, $contentType = 'application/json') {
}

try {
$tag = $this->tagManager->createTag($tagName, $userVisible, $userAssignable);
$tag = $this->tagManager->createTag($tagName, $userVisible, $userAssignable, $userEditable);
if (!empty($groups)) {
$this->tagManager->setTagGroups($tag, $groups);
}
Expand Down Expand Up @@ -232,6 +239,11 @@ public function handleGetProperties(
return $node->getSystemTag()->isUserVisible() ? 'true' : 'false';
});

$propFind->handle(self::USEREDITABLE_PROPERTYNAME, function () use ($node) {
// this is the tag's inherent property "is user editable"
return $node->getSystemTag()->isUserEditable() ? 'true' : 'false';
});

$propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function () use ($node) {
// this is the tag's inherent property "is user assignable"
return $node->getSystemTag()->isUserAssignable() ? 'true' : 'false';
Expand All @@ -249,11 +261,20 @@ public function handleGetProperties(
}
$groups = [];
// no need to retrieve groups for namespaces that don't qualify
if ($node->getSystemTag()->isUserVisible() && !$node->getSystemTag()->isUserAssignable()) {
$restrictedTagCondition = $node->getSystemTag()->isUserVisible() &&
(!$node->getSystemTag()->isUserAssignable());
$editableTagCondition = $node->getSystemTag()->isUserVisible() &&
$node->getSystemTag()->isUserAssignable() &&
(!$node->getSystemTag()->isUserEditable());
if ($restrictedTagCondition || $editableTagCondition) {
$groups = $this->tagManager->getTagGroups($node->getSystemTag());
}
return \implode('|', $groups);
});

$propFind->handle(self::WHITELISTEDINGROUP, function () use ($node) {
return $this->tagManager->canUserUseStaticTagInGroup($node->getSystemTag(), $this->userSession->getUser()) ? 'true' : 'false';
});
}

/**
Expand All @@ -273,12 +294,14 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
$propPatch->handle([
self::DISPLAYNAME_PROPERTYNAME,
self::USERVISIBLE_PROPERTYNAME,
self::USEREDITABLE_PROPERTYNAME,
self::USERASSIGNABLE_PROPERTYNAME,
self::GROUPS_PROPERTYNAME,
], function ($props) use ($node) {
$tag = $node->getSystemTag();
$name = $tag->getName();
$userVisible = $tag->isUserVisible();
$userEditable = $tag->isUserEditable();
$userAssignable = $tag->isUserAssignable();

$updateTag = false;
Expand All @@ -294,6 +317,12 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
$updateTag = true;
}

if (isset($props[self::USEREDITABLE_PROPERTYNAME])) {
$propValue = $props[self::USEREDITABLE_PROPERTYNAME];
$userEditable = ($propValue !== 'true' && $propValue !== '1');
$updateTag = true;
}

if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) {
$propValue = $props[self::USERASSIGNABLE_PROPERTYNAME];
$userAssignable = ($propValue !== 'false' && $propValue !== '0');
Expand All @@ -312,7 +341,7 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
}

if ($updateTag) {
$node->update($name, $userVisible, $userAssignable);
$node->update($name, $userVisible, $userAssignable, $userEditable);
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/lib/SystemTag/SystemTagsByIdCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function getChildren() {
$visibilityFilter = null;
}

$tags = $this->tagManager->getAllTags($visibilityFilter);
$tags = $this->tagManager->getAllTags($visibilityFilter, null);
return \array_map(function ($tag) {
return $this->makeNode($tag);
}, $tags);
Expand Down
12 changes: 10 additions & 2 deletions apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class SystemTagPluginTest extends \Test\TestCase {
const USERASSIGNABLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME;
const CANASSIGN_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::CANASSIGN_PROPERTYNAME;
const GROUPS_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::GROUPS_PROPERTYNAME;
const USEREDITABLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USEREDITABLE_PROPERTYNAME;
const WHITELISTEDINGROUP = \OCA\DAV\SystemTag\SystemTagPlugin::WHITELISTEDINGROUP;

/**
* @var \Sabre\DAV\Server
Expand Down Expand Up @@ -114,7 +116,7 @@ public function getPropertiesDataProvider() {
self::DISPLAYNAME_PROPERTYNAME,
self::USERVISIBLE_PROPERTYNAME,
self::USERASSIGNABLE_PROPERTYNAME,
self::CANASSIGN_PROPERTYNAME,
self::CANASSIGN_PROPERTYNAME
],
[
self::ID_PROPERTYNAME => '1',
Expand Down Expand Up @@ -155,16 +157,20 @@ public function getPropertiesDataProvider() {
]
],
[
new SystemTag(1, 'Test', true, true),
new SystemTag(1, 'Test', true, true, true),
['group1', 'group2'],
[
self::ID_PROPERTYNAME,
self::GROUPS_PROPERTYNAME,
self::USEREDITABLE_PROPERTYNAME,
self::WHITELISTEDINGROUP,
],
[
self::ID_PROPERTYNAME => '1',
// groups only returned when userAssignable is false
self::GROUPS_PROPERTYNAME => '',
self::USEREDITABLE_PROPERTYNAME => 'true',
self::WHITELISTEDINGROUP => 'false'
]
],
];
Expand Down Expand Up @@ -297,6 +303,7 @@ public function testUpdatePropertiesAdmin() {
$propPatch = new \Sabre\DAV\PropPatch([
self::DISPLAYNAME_PROPERTYNAME => 'Test changed',
self::USERVISIBLE_PROPERTYNAME => 'false',
self::USEREDITABLE_PROPERTYNAME => 'true',
self::USERASSIGNABLE_PROPERTYNAME => 'true',
self::GROUPS_PROPERTYNAME => 'group1|group2',
]);
Expand All @@ -315,6 +322,7 @@ public function testUpdatePropertiesAdmin() {
$this->assertEquals(200, $result[self::DISPLAYNAME_PROPERTYNAME]);
$this->assertEquals(200, $result[self::USERASSIGNABLE_PROPERTYNAME]);
$this->assertEquals(200, $result[self::USERVISIBLE_PROPERTYNAME]);
$this->assertEquals(200, $result[self::USEREDITABLE_PROPERTYNAME]);
}

/**
Expand Down
43 changes: 43 additions & 0 deletions core/Migrations/Version20181017105216.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* @author Sujith Haridasan <[email protected]>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OC\Migrations;

use Doctrine\DBAL\Schema\Schema;
use OCP\Migration\ISchemaMigration;

class Version20181017105216 implements ISchemaMigration {

/** @var string */
private $prefix;

public function changeSchema(Schema $schema, array $options) {
$this->prefix = $options['tablePrefix'];
$table = $schema->getTable("{$this->prefix}systemtag");
if ($schema->hasTable("{$this->prefix}systemtag")) {
if (!$table->hasColumn('assignable')) {
$table->addColumn('assignable', 'integer');
$assignableColumn = $table->getColumn('assignable');
$assignableColumn->setDefault(0);
}
}
}
}
55 changes: 55 additions & 0 deletions core/Migrations/Version20181017120818.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* @author Sujith Haridasan <[email protected]>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OC\Migrations;

use OCP\IDBConnection;
use OCP\Migration\ISqlMigration;

/**
* Added extra column assignable to systemtag table, post 10.0.10.1 version
* this is required to identify editable tag. It is only
* set to "1" for visible and editable tags.
*/
class Version20181017120818 implements ISqlMigration {
public function sql(IDBConnection $connection) {
$valueToUpdate = 1;
$qb = $connection->getQueryBuilder();
$qb->update('systemtag')
->set(
'assignable',
$qb->expr()->literal($valueToUpdate)
)
->where(
$qb->expr()->eq(
'visibility',
$qb->expr()->literal($valueToUpdate)
)
)
->andWhere(
$qb->expr()->eq(
'editable',
$qb->expr()->literal($valueToUpdate)
)
);
return [$qb->getSQL()];
}
}
15 changes: 14 additions & 1 deletion core/js/systemtags/systemtagmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
PROPERTY_CAN_ASSIGN:'{' + OC.Files.Client.NS_OWNCLOUD + '}can-assign',
PROPERTY_DISPLAYNAME: '{' + OC.Files.Client.NS_OWNCLOUD + '}display-name',
PROPERTY_USERVISIBLE: '{' + OC.Files.Client.NS_OWNCLOUD + '}user-visible',
PROPERTY_USEREDITABLE:'{' + OC.Files.Client.NS_OWNCLOUD + '}user-editable',
PROPERTY_USERASSIGNABLE:'{' + OC.Files.Client.NS_OWNCLOUD + '}user-assignable',
PROPERTY_WHITELISTEDINGROUP:'{' + OC.Files.Client.NS_OWNCLOUD + '}editable-in-group'
});

/**
Expand All @@ -39,18 +41,29 @@
'id': OC.Files.Client.PROPERTY_FILEID,
'name': OC.Files.Client.PROPERTY_DISPLAYNAME,
'userVisible': OC.Files.Client.PROPERTY_USERVISIBLE,
'userEditable': OC.Files.Client.PROPERTY_USEREDITABLE,
'userAssignable': OC.Files.Client.PROPERTY_USERASSIGNABLE,
'editableInGroup': OC.Files.Client.PROPERTY_WHITELISTEDINGROUP,
// read-only, effective permissions computed by the server,
'canAssign': OC.Files.Client.PROPERTY_CAN_ASSIGN
},

parse: function(data) {
var userEditable;
//If assignable is false, just set editable to false
if (data.userAssignable === false) {
userEditable = false;
} else {
userEditable = (data.userEditable === true || data.userEditable === 'true');
}
return {
id: data.id,
name: data.name,
userVisible: data.userVisible === true || data.userVisible === 'true',
userEditable: userEditable,
userAssignable: data.userAssignable === true || data.userAssignable === 'true',
canAssign: data.canAssign === true || data.canAssign === 'true'
canAssign: data.canAssign === true || data.canAssign === 'true',
editableInGroup: data.editableInGroup === true || data.editableInGroup === 'true'
};
}
});
Expand Down
7 changes: 7 additions & 0 deletions core/js/systemtags/systemtags.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
// invisible also implicitly means not assignable
scope = t('core', 'invisible');
}
if (tag.userVisible === true && tag.userEditable === false && tag.userAssignable === true) {
/**
* Users can edit the tag, if they are admin or belong to whitelisted
* group by the edit tag.
*/
scope = t('core', 'Static')
}
if (scope) {
var $tag = $('<em>').text(' ' +
t('core', '({scope})', {
Expand Down
Loading

0 comments on commit 9839041

Please sign in to comment.