зеркало из https://github.com/nextcloud/deck.git
Merge pull request #923 from nextcloud/feature/126/circles
Share with circles
This commit is contained in:
Коммит
8615fe1a40
|
@ -56,6 +56,7 @@
|
|||
@if mixin-exists('icon-black-white') {
|
||||
@include icon-black-white('deck', 'deck', 1);
|
||||
@include icon-black-white('archive', 'deck', 1);
|
||||
@include icon-black-white('circles', 'deck', 1);
|
||||
|
||||
.icon-toggle-compact-collapsed {
|
||||
@include icon-color('toggle-view-expand', 'deck', $color-black);
|
||||
|
@ -68,3 +69,12 @@
|
|||
@include icon-color('activity-dark', 'activity', $color-black);
|
||||
}
|
||||
}
|
||||
|
||||
.avatardiv.circles {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
.icon-circles {
|
||||
opacity: 1;
|
||||
background-size: 20px;
|
||||
background-position: center center;
|
||||
}
|
|
@ -1292,7 +1292,7 @@ input.input-inline {
|
|||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
.icon-group {
|
||||
.icon-group, .icon {
|
||||
padding: 16px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#000"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>
|
После Ширина: | Высота: | Размер: 885 B |
|
@ -429,6 +429,8 @@ app.controller('BoardController', function ($rootScope, $scope, $element, $state
|
|||
return 'user';
|
||||
case OC.Share.SHARE_TYPE_GROUP:
|
||||
return 'group';
|
||||
case OC.Share.SHARE_TYPE_CIRCLE:
|
||||
return 'circles';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
*/
|
||||
import app from '../app/App.js';
|
||||
/* global app OC */
|
||||
/* global app OC angular */
|
||||
app.factory('BoardService', function (ApiService, $http, $q) {
|
||||
var BoardService = function ($http, ep, $q) {
|
||||
ApiService.call(this, $http, ep, $q);
|
||||
|
@ -59,7 +59,7 @@ app.factory('BoardService', function (ApiService, $http, $q) {
|
|||
var searchData = {
|
||||
format: 'json',
|
||||
perPage: 4,
|
||||
itemType: [0, 1]
|
||||
itemType: [0, 1, 7]
|
||||
};
|
||||
if (search !== "") {
|
||||
searchData.search = search;
|
||||
|
@ -79,6 +79,7 @@ app.factory('BoardService', function (ApiService, $http, $q) {
|
|||
|
||||
var users = response.ocs.data.exact.users.concat(response.ocs.data.users.slice(0, 4));
|
||||
var groups = response.ocs.data.exact.groups.concat(response.ocs.data.groups.slice(0, 4));
|
||||
var circles = response.ocs.data.exact.groups.concat(response.ocs.data.circles.slice(0, 4));
|
||||
|
||||
// filter out everyone who is already in the share list
|
||||
angular.forEach(users, function (item) {
|
||||
|
@ -105,6 +106,18 @@ app.factory('BoardService', function (ApiService, $http, $q) {
|
|||
self.sharees.push(acl);
|
||||
}
|
||||
});
|
||||
angular.forEach(circles, function (item) {
|
||||
var acl = self.generateAcl(OC.Share.SHARE_TYPE_CIRCLE, item);
|
||||
var exists = false;
|
||||
angular.forEach(self.getCurrent().acl, function (acl) {
|
||||
if (acl.participant.primaryKey === item.value.shareWith) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
if (!exists) {
|
||||
self.sharees.push(acl);
|
||||
}
|
||||
});
|
||||
|
||||
deferred.resolve(self.sharees);
|
||||
}, function () {
|
||||
|
|
|
@ -32,6 +32,7 @@ class Acl extends RelationalEntity {
|
|||
|
||||
const PERMISSION_TYPE_USER = 0;
|
||||
const PERMISSION_TYPE_GROUP = 1;
|
||||
const PERMISSION_TYPE_CIRCLE = 7;
|
||||
|
||||
protected $participant;
|
||||
protected $type;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
namespace OCA\Deck\Db;
|
||||
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\QueryException;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IGroupManager;
|
||||
|
@ -36,6 +37,8 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
|||
private $userManager;
|
||||
private $groupManager;
|
||||
|
||||
private $circlesEnabled;
|
||||
|
||||
public function __construct(
|
||||
IDBConnection $db,
|
||||
LabelMapper $labelMapper,
|
||||
|
@ -50,6 +53,8 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
|||
$this->stackMapper = $stackMapper;
|
||||
$this->userManager = $userManager;
|
||||
$this->groupManager = $groupManager;
|
||||
|
||||
$this->circlesEnabled = \OC::$server->getAppManager()->isEnabledForUser('circles');
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,6 +141,35 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
|||
return $entries;
|
||||
}
|
||||
|
||||
public function findAllByCircles($userId, $limit = null, $offset = null) {
|
||||
if (!$this->circlesEnabled) {
|
||||
return [];
|
||||
}
|
||||
$circles = array_map(function($circle) {
|
||||
return $circle->getUniqueId();
|
||||
}, \OCA\Circles\Api\v1\Circles::joinedCircles('', true));
|
||||
if (count($circles) === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sql = 'SELECT boards.id, title, owner, color, archived, deleted_at, 2 as shared, last_modified FROM `*PREFIX*deck_boards` as boards ' .
|
||||
'INNER JOIN `*PREFIX*deck_board_acl` as acl ON boards.id=acl.board_id WHERE owner != ? AND type=? AND (';
|
||||
for ($i = 0, $iMax = count($circles); $i < $iMax; $i++) {
|
||||
$sql .= 'acl.participant = ? ';
|
||||
if (count($circles) > 1 && $i < count($circles) - 1) {
|
||||
$sql .= ' OR ';
|
||||
}
|
||||
}
|
||||
$sql .= ');';
|
||||
$entries = $this->findEntities($sql, array_merge([$userId, Acl::PERMISSION_TYPE_CIRCLE], $circles), $limit, $offset);
|
||||
/* @var Board $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$acl = $this->aclMapper->findAll($entry->id);
|
||||
$entry->setAcl($acl);
|
||||
}
|
||||
return $entries;
|
||||
}
|
||||
|
||||
public function findAll() {
|
||||
$sql = 'SELECT id from *PREFIX*deck_boards;';
|
||||
return $this->findEntities($sql);
|
||||
|
@ -200,6 +234,16 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
|||
\OC::$server->getLogger()->debug('Group ' . $acl->getId() . ' not found when mapping acl ' . $acl->getParticipant());
|
||||
return null;
|
||||
}
|
||||
if ($acl->getType() === Acl::PERMISSION_TYPE_CIRCLE) {
|
||||
try {
|
||||
$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($acl->getParticipant(), true);
|
||||
if ($circle) {
|
||||
return new Circle($circle);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
throw new \Exception('Unknown permission type for mapping Acl');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
|
||||
class Circle extends RelationalObject {
|
||||
|
||||
/** @var \OCA\Circles\Model\Circle */
|
||||
protected $object;
|
||||
|
||||
public function __construct(\OCA\Circles\Model\Circle $circle) {
|
||||
$primaryKey = $circle->getUniqueId();
|
||||
parent::__construct($primaryKey, $circle);
|
||||
}
|
||||
|
||||
public function getObjectSerialization() {
|
||||
return [
|
||||
'uid' => $this->object->getUniqueId(),
|
||||
'displayname' => $this->object->getName(),
|
||||
'typeString' => $this->object->getTypeString(),
|
||||
'circleOwner' => $this->object->getOwner()
|
||||
];
|
||||
}
|
||||
}
|
|
@ -98,7 +98,8 @@ class BoardService {
|
|||
$userInfo = $this->getBoardPrerequisites();
|
||||
$userBoards = $this->boardMapper->findAllByUser($userInfo['user'], null, null, $since);
|
||||
$groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups'],null, null, $since);
|
||||
$complete = array_merge($userBoards, $groupBoards);
|
||||
$circleBoards = $this->boardMapper->findAllByCircles($userInfo['user'], null, null, $since);
|
||||
$complete = array_merge($userBoards, $groupBoards, $circleBoards);
|
||||
$result = [];
|
||||
/** @var Board $item */
|
||||
foreach ($complete as &$item) {
|
||||
|
|
|
@ -33,6 +33,7 @@ use OCA\Deck\NoPermissionException;
|
|||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\AppFramework\QueryException;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\ILogger;
|
||||
|
@ -61,6 +62,8 @@ class PermissionService {
|
|||
/** @var array */
|
||||
private $users = [];
|
||||
|
||||
private $circlesEnabled = false;
|
||||
|
||||
public function __construct(
|
||||
ILogger $logger,
|
||||
AclMapper $aclMapper,
|
||||
|
@ -79,6 +82,8 @@ class PermissionService {
|
|||
$this->shareManager = $shareManager;
|
||||
$this->config = $config;
|
||||
$this->userId = $userId;
|
||||
|
||||
$this->circlesEnabled = \OC::$server->getAppManager()->isEnabledForUser('circles');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,6 +193,15 @@ class PermissionService {
|
|||
if ($acl->getType() === Acl::PERMISSION_TYPE_USER && $acl->getParticipant() === $userId) {
|
||||
return $acl->getPermission($permission);
|
||||
}
|
||||
|
||||
if ($this->circlesEnabled && $acl->getType() === Acl::PERMISSION_TYPE_CIRCLE) {
|
||||
try {
|
||||
\OCA\Circles\Api\v1\Circles::getMember($acl->getParticipant(), $this->userId, 1, true);
|
||||
return $acl->getPermission($permission);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->info('Member not found in circle that was accessed. This should not happen.');
|
||||
}
|
||||
}
|
||||
}
|
||||
// check for groups
|
||||
$hasGroupPermission = false;
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
<span class="has-tooltip username" ng-if="sharee.type==OC.Share.SHARE_TYPE_GROUP">
|
||||
{{ sharee.participant.displayname }} (<?php p($l->t('Group')); ?>)
|
||||
</span>
|
||||
<div class="avatardiv circles" ng-if="sharee.type==OC.Share.SHARE_TYPE_CIRCLE"><i class="icon icon-circles icon-white"></i></div>
|
||||
<span class="has-tooltip username" ng-if="sharee.type==OC.Share.SHARE_TYPE_CIRCLE">
|
||||
{{ sharee.participant.displayname }} (<?php p($l->t('Circle')); ?>)
|
||||
</span>
|
||||
<span class="has-tooltip username" ng-if="sharee.type==OC.Share.SHARE_TYPE_USER">
|
||||
{{ sharee.participant.displayname }}
|
||||
</span>
|
||||
|
@ -53,13 +57,17 @@
|
|||
<li ng-repeat="acl in boardservice.getCurrent().acl track by acl.participant.primaryKey">
|
||||
<span class="icon-loading-small" style="display:none;" title="<?php p($l->t('Loading')); ?>"></span>
|
||||
<div class="avatardiv" avatar data-contactsmenu="true" data-user="{{ acl.participant.uid }}" data-displayname="{{ acl.participant.displayname }}" ng-if="acl.type==OC.Share.SHARE_TYPE_USER"></div>
|
||||
<div class="avatardiv" ng-if="acl.type==OC.Share.SHARE_TYPE_GROUP"><i class="icon icon-{{aclTypeString(acl)}}" ></i></div>
|
||||
<div class="avatardiv" ng-if="acl.type!=OC.Share.SHARE_TYPE_USER"><i class="icon icon-{{aclTypeString(acl)}}" ></i></div>
|
||||
|
||||
<span class="has-tooltip username" ng-if="acl.type==OC.Share.SHARE_TYPE_USER">
|
||||
{{ acl.participant.displayname }}
|
||||
</span>
|
||||
<span class="has-tooltip username" ng-if="acl.type==OC.Share.SHARE_TYPE_GROUP">
|
||||
{{ acl.participant.displayname }} (<?php p($l->t('Group')); ?>)
|
||||
</span>
|
||||
<span class="has-tooltip username" ng-if="acl.type==OC.Share.SHARE_TYPE_USER">
|
||||
{{ acl.participant.displayname }}
|
||||
<span class="has-tooltip username" ng-if="acl.type==OC.Share.SHARE_TYPE_CIRCLE">
|
||||
{{ acl.participant.displayname }} (<?php p($l->t('Circle')); ?> {{ acl.participant.typeString }})
|
||||
<div>{{ acl.participant.circleOwner.display_name }}</div>
|
||||
</span>
|
||||
|
||||
<span class="sharingOptionsGroup">
|
||||
|
|
|
@ -123,6 +123,10 @@ class BoardServiceTest extends TestCase {
|
|||
->method('findAllByGroups')
|
||||
->with('admin', ['a', 'b', 'c'])
|
||||
->willReturn([$b2, $b3]);
|
||||
$this->boardMapper->expects($this->once())
|
||||
->method('findAllByCircles')
|
||||
->with('admin')
|
||||
->willReturn([]);
|
||||
$user = $this->createMock(IUser::class);
|
||||
$this->groupManager->method('getUserGroupIds')
|
||||
->willReturn(['a', 'b', 'c']);
|
||||
|
|
Загрузка…
Ссылка в новой задаче