@@ -67,7 +67,7 @@ pipeline:
|
||||
matrix:
|
||||
TESTS: syntax-php7.0
|
||||
php5.6:
|
||||
image: nextcloudci/php5.6:php5.6-3
|
||||
image: nextcloudci/php5.6:php5.6-7
|
||||
environment:
|
||||
- APP_NAME=deck
|
||||
- CORE_BRANCH=master
|
||||
@@ -93,7 +93,7 @@ pipeline:
|
||||
matrix:
|
||||
TESTS: php5.6
|
||||
php7.0:
|
||||
image: nextcloudci/php7.0:php7.0-7
|
||||
image: nextcloudci/php7.0:php7.0-8
|
||||
environment:
|
||||
- APP_NAME=deck
|
||||
- CORE_BRANCH=master
|
||||
@@ -170,4 +170,4 @@ matrix:
|
||||
- TESTS: jsbuild
|
||||
- TESTS: integration
|
||||
|
||||
branches: [ master, stable* ]
|
||||
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
<type>boolean</type>
|
||||
<default>false</default>
|
||||
</field>
|
||||
<field>
|
||||
<name>deleted_at</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<length>8</length>
|
||||
<notnull>false</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
💥 This is still alpha software: it may not be stable enough for production!
|
||||
|
||||
</description>
|
||||
<version>0.1.4.1</version>
|
||||
<version>0.1.4.2</version>
|
||||
<licence>agpl</licence>
|
||||
<author>Julius Härtl</author>
|
||||
<namespace>Deck</namespace>
|
||||
@@ -30,6 +30,9 @@
|
||||
<dependencies>
|
||||
<nextcloud min-version="11" max-version="13" />
|
||||
</dependencies>
|
||||
<background-jobs>
|
||||
<job>OCA\Deck\Cron\DeleteCron</job>
|
||||
</background-jobs>
|
||||
<repair-steps>
|
||||
<post-migration>
|
||||
<step>OCA\Deck\Migration\UnknownUsers</step>
|
||||
|
||||
@@ -31,6 +31,7 @@ return [
|
||||
['name' => 'board#read', 'url' => '/boards/{boardId}', 'verb' => 'GET'],
|
||||
['name' => 'board#update', 'url' => '/boards/{boardId}', 'verb' => 'PUT'],
|
||||
['name' => 'board#delete', 'url' => '/boards/{boardId}', 'verb' => 'DELETE'],
|
||||
['name' => 'board#deleteUndo', 'url' => '/boards/{boardId}/deleteUndo', 'verb' => 'POST'],
|
||||
['name' => 'board#getUserPermissions', 'url' => '/boards/{boardId}/permissions', 'verb' => 'GET'],
|
||||
['name' => 'board#addAcl', 'url' => '/boards/{boardId}/acl', 'verb' => 'POST'],
|
||||
['name' => 'board#updateAcl', 'url' => '/boards/{boardId}/acl', 'verb' => 'PUT'],
|
||||
|
||||
@@ -65,6 +65,14 @@ button.button-inline:hover {
|
||||
* Navigation sidebar
|
||||
*/
|
||||
|
||||
.app-navigation-entry-menu ul {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.app-navigation-entry-utils-menu-button {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.app-navigation-entry-utils-menu-share {
|
||||
display: flex !important;
|
||||
padding: 14px;
|
||||
@@ -318,9 +326,9 @@ button.button-inline:hover {
|
||||
.popovermenu {
|
||||
z-index: 999;
|
||||
opacity: 1;
|
||||
margin-top: 25px;
|
||||
margin-right: 3px;
|
||||
display: block;
|
||||
margin-top: 25px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.popovermenu.hidden {
|
||||
@@ -614,23 +622,30 @@ button.button-inline:hover {
|
||||
|
||||
.colorselect {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
padding-top: 4px;
|
||||
padding-left: 4px;
|
||||
border-radius:3px;
|
||||
flex-direction: row;
|
||||
min-width: 240px;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
margin: 3px 3px 3px 0;
|
||||
}
|
||||
|
||||
.colorselect .color {
|
||||
opacity: 0.7;
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
float: left;
|
||||
margin-right: 2px;
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.colorselect .selected {
|
||||
background-image: url(../../../core/img/actions/checkmark.svg);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 1.0;
|
||||
border: 1px solid #333333;
|
||||
}
|
||||
|
||||
.colorselect .dark.selected {
|
||||
background-image: url(../../../core/img/actions/checkmark-white.svg);
|
||||
}
|
||||
|
||||
.labels .colorselect {
|
||||
@@ -662,6 +677,16 @@ button.button-inline:hover {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
#boardlist .app-popover-menu-utils {
|
||||
width: 30px;
|
||||
display: inline;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popovermenu ul {
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#boardlist td {
|
||||
padding: 10px;
|
||||
@@ -680,15 +705,34 @@ button.button-inline:hover {
|
||||
|
||||
.cell-board-title {
|
||||
width: 50%;
|
||||
|
||||
}
|
||||
|
||||
#boardlist .colorselect,
|
||||
#boardlist input {
|
||||
float: left;
|
||||
#boardlist tr.deleted td * {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#boardlist .colorselect {
|
||||
#boardlist td form {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#boardlist td .colorselect {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#boardlist td input[type=text] {
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
#boardlist td input[type=submit] {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
#boardlist td .app-popover-menu-utils {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#boardlist .popovermenu {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
@@ -925,6 +969,10 @@ button.button-inline:hover {
|
||||
* Custom icons
|
||||
*/
|
||||
|
||||
.icon-deck {
|
||||
background-image: url(../img/deck.svg);
|
||||
}
|
||||
|
||||
.icon-group {
|
||||
background-image: url('../../../settings/img/users.svg');
|
||||
}
|
||||
|
||||
1
img/deck.svg
Normal file
1
img/deck.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M432.3 448.1h-348c-13.2 0-24-10.8-24-24V264.6c0-13.2 10.8-24 24-24h348c13.2 0 24 10.8 24 24v159.5c0 13.2-10.8 24-24 24zM380.4 89.8H127.8c-7.7 0-14-6.3-14-14v-6.3c0-7.7 6.3-14 14-14h252.6c7.7 0 14 6.3 14 14v6.3c0 7.7-6.3 14-14 14zm19.4 61.8H110.6c-7.7 0-14-6.3-14-14v-6.3c0-7.7 6.3-14 14-14h289.2c7.7 0 14 6.3 14 14v6.3c0 7.7-6.3 14-14 14zm21.6 61.4H94.6c-7.7 0-14-6.3-14-14v-6.3c0-7.7 6.3-14 14-14h326.8c7.7 0 14 6.3 14 14v6.3c0 7.7-6.3 14-14 14z"/></svg>
|
||||
|
After Width: | Height: | Size: 527 B |
@@ -33,36 +33,40 @@ app.config(function ($provide, $routeProvider, $interpolateProvider, $httpProvid
|
||||
});
|
||||
markdownItConverterProvider.use(markdownitLinkTarget);
|
||||
|
||||
$urlRouterProvider.otherwise("/");
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
$stateProvider
|
||||
.state('list', {
|
||||
url: "/",
|
||||
templateUrl: "/boardlist.mainView.html",
|
||||
controller: 'ListController'
|
||||
url: '/:filter',
|
||||
templateUrl: '/boardlist.mainView.html',
|
||||
controller: 'ListController',
|
||||
reloadOnSearch: false,
|
||||
params: {
|
||||
filter: { value: '', dynamic: true }
|
||||
}
|
||||
})
|
||||
.state('board', {
|
||||
url: "/board/:boardId/:filter",
|
||||
templateUrl: "/board.html",
|
||||
url: '/board/:boardId/:filter',
|
||||
templateUrl: '/board.html',
|
||||
controller: 'BoardController',
|
||||
params: {
|
||||
filter: { value: '', dynamic: true }
|
||||
}
|
||||
})
|
||||
.state('board.detail', {
|
||||
url: "/detail/",
|
||||
url: '/detail/',
|
||||
reloadOnSearch : false,
|
||||
views: {
|
||||
"sidebarView": {
|
||||
templateUrl: "/board.sidebarView.html"
|
||||
'sidebarView': {
|
||||
templateUrl: '/board.sidebarView.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('board.card', {
|
||||
url: "/card/:cardId",
|
||||
url: '/card/:cardId',
|
||||
views: {
|
||||
"sidebarView": {
|
||||
templateUrl: "/card.sidebarView.html",
|
||||
'sidebarView': {
|
||||
templateUrl: '/card.sidebarView.html',
|
||||
controller: 'CardController'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
app.run(function ($document, $rootScope, $transitions) {
|
||||
app.run(function ($document, $rootScope, $transitions, BoardService) {
|
||||
'use strict';
|
||||
$document.click(function (event) {
|
||||
$rootScope.$broadcast('documentClicked', event);
|
||||
});
|
||||
$transitions.onEnter({from: 'list'}, function($state, $transition$) {
|
||||
BoardService.unsetCurrrent();
|
||||
});
|
||||
$transitions.onEnter({to: 'list'}, function($state, $transition$) {
|
||||
BoardService.unsetCurrrent();
|
||||
});
|
||||
$transitions.onEnter({to: 'board.card'}, function ($state, $transition$) {
|
||||
$rootScope.sidebar.show = true;
|
||||
});
|
||||
@@ -40,9 +46,6 @@ app.run(function ($document, $rootScope, $transitions) {
|
||||
$transitions.onExit({from: 'board.detail'}, function ($state) {
|
||||
$rootScope.sidebar.show = false;
|
||||
});
|
||||
$transitions.onEnter({to: 'board.archive'}, function ($state) {
|
||||
//BoardController.loadArchived();
|
||||
});
|
||||
|
||||
$('link[rel="shortcut icon"]').attr(
|
||||
'href',
|
||||
|
||||
@@ -80,7 +80,7 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
||||
}
|
||||
};
|
||||
$scope.checkCanEdit = function () {
|
||||
return !$scope.archived;
|
||||
return !BoardService.getCurrent().archived;
|
||||
};
|
||||
|
||||
// filter cards here, as ng-sortable will not work nicely with html-inline filters
|
||||
@@ -114,7 +114,6 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
||||
|
||||
// Handle initial Loading
|
||||
BoardService.fetchOne($scope.id).then(function (data) {
|
||||
BoardService.getPermissions();
|
||||
$scope.statusservice.releaseWaiting();
|
||||
}, function (error) {
|
||||
$scope.statusservice.setError('Error occured', error);
|
||||
|
||||
@@ -48,9 +48,10 @@ app.controller('CardController', function ($scope, $rootScope, $routeParams, $lo
|
||||
}
|
||||
};
|
||||
$scope.cardEditDescriptionShow = function($event) {
|
||||
if(BoardService.isArchived() || CardService.getCurrent().archived) {
|
||||
return false;
|
||||
}
|
||||
var node = $event.target.nodeName;
|
||||
console.log($event);
|
||||
console.log(BoardService);
|
||||
if($scope.card.archived || !$scope.boardservice.canEdit()) {
|
||||
console.log(node);
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -21,11 +20,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
app.controller('ListController', function ($scope, $location, $filter, BoardService, $element, $timeout) {
|
||||
/* global app angular */
|
||||
|
||||
app.controller('ListController', function ($scope, $location, $filter, BoardService, $element, $timeout, $stateParams, $state) {
|
||||
$scope.boards = [];
|
||||
$scope.newBoard = {};
|
||||
$scope.status = {
|
||||
deleteUndo: []
|
||||
deleteUndo: [],
|
||||
filter: $stateParams.filter ? $stateParams.filter : '',
|
||||
sidebar: false
|
||||
};
|
||||
$scope.colors = ['0082c9', '00c9c6','00c906', 'c92b00', 'F1DB50', '7C31CC', '3A3B3D', 'CACBCD'];
|
||||
$scope.boardservice = BoardService;
|
||||
@@ -42,13 +45,42 @@ app.controller('ListController', function ($scope, $location, $filter, BoardServ
|
||||
|
||||
$scope.filterData = function () {
|
||||
angular.copy($scope.boardservice.getData(), $scope.boardservice.sorted);
|
||||
$scope.boardservice.sorted = $filter('orderBy')($scope.boardservice.sorted, 'title');
|
||||
angular.copy($scope.boardservice.sorted, $scope.boardservice.sidebar);
|
||||
$scope.boardservice.sidebar = $filter('orderBy')($scope.boardservice.sidebar, 'title');
|
||||
$scope.boardservice.sidebar = $filter('cardFilter')($scope.boardservice.sidebar, {archived: false});
|
||||
|
||||
if ($scope.status.filter === 'archived') {
|
||||
var filter = {};
|
||||
filter[$scope.status.filter] = true;
|
||||
$scope.boardservice.sorted = $filter('cardFilter')($scope.boardservice.sorted, filter);
|
||||
} else if ($scope.status.filter === 'shared') {
|
||||
$scope.boardservice.sorted = $filter('cardFilter')($scope.boardservice.sorted, {archived: false});
|
||||
$scope.boardservice.sorted = $filter('boardFilterAcl')($scope.boardservice.sorted);
|
||||
} else {
|
||||
$scope.boardservice.sorted = $filter('cardFilter')($scope.boardservice.sorted, {archived: false});
|
||||
}
|
||||
$scope.boardservice.sorted = $filter('orderBy')($scope.boardservice.sorted, ['deletedAt', 'title']);
|
||||
};
|
||||
|
||||
$scope.$watchCollection(function(){
|
||||
return $state.params;
|
||||
}, function(){
|
||||
$scope.status.filter = $state.params.filter;
|
||||
$scope.filterData();
|
||||
});
|
||||
|
||||
|
||||
$scope.selectColor = function(color) {
|
||||
$scope.newBoard.color = color;
|
||||
};
|
||||
|
||||
$scope.gotoBoard = function(board) {
|
||||
if(board.deletedAt > 0) {
|
||||
return false;
|
||||
}
|
||||
return $state.go('board', {boardId: board.id});
|
||||
};
|
||||
|
||||
$scope.boardCreate = function() {
|
||||
if(!$scope.newBoard.title || !$scope.newBoard.color) {
|
||||
$scope.status.addBoard=false;
|
||||
@@ -72,26 +104,30 @@ app.controller('ListController', function ($scope, $location, $filter, BoardServ
|
||||
board.status.edit = false;
|
||||
};
|
||||
|
||||
$scope.boardArchive = function (board) {
|
||||
board.archived = true;
|
||||
BoardService.update(board).then(function(data) {
|
||||
$scope.filterData();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.boardUnarchive = function (board) {
|
||||
board.archived = false;
|
||||
BoardService.update(board).then(function(data) {
|
||||
$scope.filterData();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.boardDelete = function(board) {
|
||||
var boardId = board.id;
|
||||
$scope.status.deleteUndo[boardId] = 10;
|
||||
$scope.boardDeleteCountdown = function () {
|
||||
console.log($scope.status);
|
||||
if($scope.status.deleteUndo[boardId] > 0) {
|
||||
$scope.status.deleteUndo[boardId]--;
|
||||
$timeout($scope.boardDeleteCountdown, 1000);
|
||||
}
|
||||
if($scope.status.deleteUndo[boardId] === 0) {
|
||||
BoardService.delete(board.id).then(function (data) {
|
||||
$scope.filterData();
|
||||
});
|
||||
}
|
||||
};
|
||||
$timeout($scope.boardDeleteCountdown, 1000);
|
||||
BoardService.delete(board.id).then(function (data) {
|
||||
$scope.filterData();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.boardDeleteUndo = function (board) {
|
||||
delete $scope.status.deleteUndo[board.id];
|
||||
BoardService.deleteUndo(board.id).then(function (data) {
|
||||
$scope.filterData();
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
33
js/filters/boardFilterAcl.js
Normal file
33
js/filters/boardFilterAcl.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
app.filter('boardFilterAcl', function() {
|
||||
return function(boards) {
|
||||
var _result = [];
|
||||
angular.forEach(boards, function(board){
|
||||
if(board.acl !== null && Object.keys(board.acl).length > 0) {
|
||||
_result.push(board);
|
||||
}
|
||||
});
|
||||
return _result;
|
||||
};
|
||||
});
|
||||
@@ -24,15 +24,16 @@
|
||||
|
||||
app.filter('cardFilter', function() {
|
||||
return function(cards, rules) {
|
||||
var _result = {};
|
||||
var _result = [];
|
||||
angular.forEach(cards, function(card){
|
||||
var _card = card;
|
||||
angular.some(rules, function(rule, condition) {
|
||||
if(_card[rule]===condition) {
|
||||
var keys = Object.keys(rules);
|
||||
keys.some(function(key, condition) {
|
||||
if(_card[key]===rules[key]) {
|
||||
_result.push(_card);
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
return _result;
|
||||
};
|
||||
});
|
||||
@@ -24,7 +24,7 @@ app.filter('textColorFilter', function() {
|
||||
return function (hex) {
|
||||
// RGB2HLS by Garry Tan
|
||||
// http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
|
||||
var result = /^([A-Fa-f\d]{2})([A-Fa-f\d]{2})([A-Fa-f\d]{2})$/i.exec(hex);
|
||||
var result = /^#?([A-Fa-f\d]{2})([A-Fa-f\d]{2})([A-Fa-f\d]{2})$/i.exec(hex);
|
||||
var color = result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
|
||||
@@ -145,7 +145,13 @@ app.factory('ApiService', function($http, $q){
|
||||
return this.data[this.id];
|
||||
};
|
||||
|
||||
ApiService.prototype.getData = function() {
|
||||
ApiService.prototype.unsetCurrrent = function () {
|
||||
this.id = null;
|
||||
};
|
||||
|
||||
|
||||
|
||||
ApiService.prototype.getData = function() {
|
||||
return $.map(this.data, function(value, index) {
|
||||
return [value];
|
||||
});
|
||||
|
||||
@@ -26,6 +26,33 @@ app.factory('BoardService', function(ApiService, $http, $q){
|
||||
};
|
||||
BoardService.prototype = angular.copy(ApiService.prototype);
|
||||
|
||||
BoardService.prototype.delete = function (id) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
|
||||
$http.delete(this.baseUrl + '/' + id).then(function (response) {
|
||||
self.data[id].deletedAt = response.data.deletedAt;
|
||||
deferred.resolve(response.data);
|
||||
}, function (error) {
|
||||
deferred.reject('Deleting ' + self.endpoint + ' failed');
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
BoardService.prototype.deleteUndo = function (id) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
var _id = id;
|
||||
$http.post(this.baseUrl + '/' + id + '/deleteUndo').then(function (response) {
|
||||
self.data[_id].deletedAt = 0;
|
||||
console.log(self.data[_id]);
|
||||
deferred.resolve(response.data);
|
||||
}, function (error) {
|
||||
deferred.reject('Deleting ' + self.endpoint + ' failed');
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
BoardService.prototype.searchUsers = function (search) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
@@ -151,44 +178,43 @@ app.factory('BoardService', function(ApiService, $http, $q){
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
BoardService.prototype.getPermissions = function() {
|
||||
var board = this.getCurrent();
|
||||
var deferred = $q.defer();
|
||||
$http.get(this.baseUrl + '/' + board.id + '/permissions').then(function (response) {
|
||||
board.permissions = response.data;
|
||||
deferred.resolve(response.data);
|
||||
}, function (error) {
|
||||
deferred.reject('Error fetching board permissions ' + board);
|
||||
});
|
||||
};
|
||||
|
||||
BoardService.prototype.canRead = function() {
|
||||
if(!this.getCurrent() || !this.getCurrent().permissions) {
|
||||
return false;
|
||||
}
|
||||
return this.getCurrent().permissions['PERMISSION_READ'];
|
||||
}
|
||||
};
|
||||
|
||||
BoardService.prototype.canEdit = function() {
|
||||
if(!this.getCurrent() || !this.getCurrent().permissions) {
|
||||
return false;
|
||||
}
|
||||
return this.getCurrent().permissions['PERMISSION_EDIT'];
|
||||
}
|
||||
};
|
||||
|
||||
BoardService.prototype.canManage = function() {
|
||||
BoardService.prototype.canManage = function(board) {
|
||||
if(board !== null && board !== undefined) {
|
||||
return board.permissions['PERMISSION_MANAGE'];
|
||||
}
|
||||
if(!this.getCurrent() || !this.getCurrent().permissions) {
|
||||
return false;
|
||||
}
|
||||
return this.getCurrent().permissions['PERMISSION_MANAGE'];
|
||||
}
|
||||
};
|
||||
|
||||
BoardService.prototype.canShare = function() {
|
||||
if(!this.getCurrent() || !this.getCurrent().permissions) {
|
||||
return false;
|
||||
}
|
||||
return this.getCurrent().permissions['PERMISSION_SHARE'];
|
||||
}
|
||||
};
|
||||
|
||||
BoardService.prototype.isArchived = function () {
|
||||
if(!this.getCurrent() || this.getCurrent().archived) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
service = new BoardService($http, 'boards', $q);
|
||||
return service;
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
namespace OCA\Deck;
|
||||
|
||||
class CardArchivedException extends \Exception {
|
||||
class ArchivedItemException extends \Exception {
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $msg the error message
|
||||
*/
|
||||
public function __construct($msg = "") {
|
||||
public function __construct($msg = "Operation not allowed. Item is archived.") {
|
||||
parent::__construct($msg);
|
||||
}
|
||||
}
|
||||
@@ -96,8 +96,8 @@ class BoardController extends Controller {
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $color) {
|
||||
return $this->boardService->update($id, $title, $color);
|
||||
public function update($id, $title, $color, $archived) {
|
||||
return $this->boardService->update($id, $title, $color, $archived);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +108,14 @@ class BoardController extends Controller {
|
||||
public function delete($boardId) {
|
||||
return $this->boardService->delete($boardId);
|
||||
}
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function deleteUndo($boardId) {
|
||||
return $this->boardService->deleteUndo($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
|
||||
49
lib/Cron/DeleteCron.php
Normal file
49
lib/Cron/DeleteCron.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jus
|
||||
* Date: 16.05.17
|
||||
* Time: 12:34
|
||||
*/
|
||||
|
||||
namespace OCA\Deck\Cron;
|
||||
|
||||
use OC\BackgroundJob\Job;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
|
||||
class DeleteCron extends Job {
|
||||
|
||||
public function __construct(BoardMapper $boardMapper) {
|
||||
$this->boardMapper = $boardMapper;
|
||||
}
|
||||
|
||||
protected function run($argument) {
|
||||
$boards = $this->boardMapper->findToDelete();
|
||||
foreach ($boards as $board) {
|
||||
$this->boardMapper->delete($board);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,15 +34,19 @@ class Board extends RelationalEntity implements JsonSerializable {
|
||||
protected $archived = false;
|
||||
protected $labels = [];
|
||||
protected $acl = [];
|
||||
protected $permissions = [];
|
||||
protected $shared;
|
||||
protected $deletedAt = 0;
|
||||
|
||||
public function __construct() {
|
||||
$this->addType('id', 'integer');
|
||||
$this->addType('shared', 'integer');
|
||||
$this->addType('archived', 'boolean');
|
||||
$this->addType('deletedAt', 'integer');
|
||||
$this->addRelation('labels');
|
||||
$this->addRelation('acl');
|
||||
$this->addRelation('shared');
|
||||
$this->addRelation('permissions');
|
||||
$this->addResolvable('owner');
|
||||
$this->shared = -1;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @return \OCP\AppFramework\Db\Entity if not found
|
||||
*/
|
||||
public function find($id, $withLabels = false, $withAcl = false) {
|
||||
$sql = 'SELECT id, title, owner, color, archived FROM `*PREFIX*deck_boards` ' .
|
||||
$sql = 'SELECT id, title, owner, color, archived, deleted_at FROM `*PREFIX*deck_boards` ' .
|
||||
'WHERE `id` = ?';
|
||||
$board = $this->findEntity($sql, [$id]);
|
||||
|
||||
@@ -87,8 +87,8 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @return array
|
||||
*/
|
||||
public function findAllByUser($userId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT id, title, owner, color, archived, 0 as shared FROM `*PREFIX*deck_boards` WHERE owner = ? UNION ' .
|
||||
'SELECT boards.id, title, owner, color, archived, 1 as shared FROM `*PREFIX*deck_boards` as boards ' .
|
||||
$sql = 'SELECT id, title, owner, color, archived, deleted_at, 0 as shared FROM `*PREFIX*deck_boards` WHERE owner = ? UNION ' .
|
||||
'SELECT boards.id, title, owner, color, archived, deleted_at, 1 as shared FROM `*PREFIX*deck_boards` as boards ' .
|
||||
'JOIN `*PREFIX*deck_board_acl` as acl ON boards.id=acl.board_id WHERE acl.participant=? AND acl.type=? AND boards.owner != ?';
|
||||
$entries = $this->findEntities($sql, [$userId, $userId, Acl::PERMISSION_TYPE_USER, $userId], $limit, $offset);
|
||||
/* @var Board $entry */
|
||||
@@ -112,7 +112,7 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
||||
if (count($groups) <= 0) {
|
||||
return [];
|
||||
}
|
||||
$sql = 'SELECT boards.id, title, owner, color, archived, 2 as shared FROM `*PREFIX*deck_boards` as boards ' .
|
||||
$sql = 'SELECT boards.id, title, owner, color, archived, deleted_at, 2 as shared 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; $i < count($groups); $i++) {
|
||||
$sql .= 'acl.participant = ? ';
|
||||
@@ -135,6 +135,15 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $this->findEntities($sql, []);
|
||||
}
|
||||
|
||||
public function findToDelete() {
|
||||
// add buffer of 5 min
|
||||
$timeLimit = time()-(60*5);
|
||||
$sql = 'SELECT id, title, owner, color, archived, deleted_at FROM `*PREFIX*deck_boards` ' .
|
||||
'WHERE `deleted_at` > 0 AND `deleted_at` < ?';
|
||||
\OC::$server->getLogger()->error($sql);
|
||||
return $this->findEntities($sql, [$timeLimit]);
|
||||
}
|
||||
|
||||
public function delete(/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
|
||||
\OCP\AppFramework\Db\Entity $entity) {
|
||||
// delete acl
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
|
||||
namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\ArchivedItemException;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\IPermissionMapper;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\IL10N;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
@@ -61,6 +64,13 @@ class BoardService {
|
||||
$this->boardMapper->mapAcl($acl);
|
||||
}
|
||||
}
|
||||
$permissions = $this->permissionService->matchPermissions($item);
|
||||
$item->setPermissions([
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ],
|
||||
'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT],
|
||||
'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE],
|
||||
'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE]
|
||||
]);
|
||||
$result[$item->getId()] = $item;
|
||||
}
|
||||
}
|
||||
@@ -77,9 +87,50 @@ class BoardService {
|
||||
$this->boardMapper->mapAcl($acl);
|
||||
}
|
||||
}
|
||||
$permissions = $this->permissionService->matchPermissions($board);
|
||||
$board->setPermissions([
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ],
|
||||
'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT],
|
||||
'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE],
|
||||
'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE]
|
||||
]);
|
||||
return $board;
|
||||
}
|
||||
|
||||
public function isArchived($mapper, $id) {
|
||||
try {
|
||||
if ($mapper instanceof IPermissionMapper) {
|
||||
$boardId = $mapper->findBoardId($id);
|
||||
} else {
|
||||
$boardId = $id;
|
||||
}
|
||||
if ($boardId === null) {
|
||||
return false;
|
||||
}
|
||||
} catch (DoesNotExistException $exception) {
|
||||
return false;
|
||||
}
|
||||
$board = $this->find($boardId);
|
||||
return $board->getArchived();
|
||||
}
|
||||
|
||||
public function isDeleted($mapper, $id) {
|
||||
try {
|
||||
if ($mapper instanceof IPermissionMapper) {
|
||||
$boardId = $mapper->findBoardId($id);
|
||||
} else {
|
||||
$boardId = $id;
|
||||
}
|
||||
if ($boardId === null) {
|
||||
return false;
|
||||
}
|
||||
} catch (DoesNotExistException $exception) {
|
||||
return false;
|
||||
}
|
||||
$board = $this->find($boardId);
|
||||
return $board->getDeletedAt() > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function create($title, $userId, $color) {
|
||||
@@ -106,20 +157,44 @@ class BoardService {
|
||||
}
|
||||
$new_board->setLabels($labels);
|
||||
$this->boardMapper->mapOwner($new_board);
|
||||
$permissions = $this->permissionService->matchPermissions($new_board);
|
||||
$new_board->setPermissions([
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ],
|
||||
'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT],
|
||||
'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE],
|
||||
'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE]
|
||||
]);
|
||||
return $new_board;
|
||||
|
||||
}
|
||||
|
||||
public function delete($id) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
|
||||
return $this->boardMapper->delete($this->find($id));
|
||||
$board = $this->find($id);
|
||||
$board->setDeletedAt(time());
|
||||
$this->boardMapper->update($board);
|
||||
return $board;
|
||||
}
|
||||
|
||||
public function update($id, $title, $color) {
|
||||
public function deleteUndo($id) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
|
||||
$board = $this->find($id);
|
||||
$board->setDeletedAt(0);
|
||||
$this->boardMapper->update($board);
|
||||
}
|
||||
|
||||
public function deleteForce($id) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
|
||||
$board = $this->find($id);
|
||||
return $this->boardMapper->delete($board);
|
||||
}
|
||||
|
||||
public function update($id, $title, $color, $archived) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
$board = $this->find($id);
|
||||
$board->setTitle($title);
|
||||
$board->setColor($color);
|
||||
$board->setArchived($archived);
|
||||
$this->boardMapper->mapOwner($board);
|
||||
return $this->boardMapper->update($board);
|
||||
}
|
||||
|
||||
@@ -26,18 +26,22 @@ namespace OCA\Deck\Service;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\CardArchivedException;
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use OCA\Deck\StatusException;
|
||||
|
||||
|
||||
class CardService {
|
||||
|
||||
private $cardMapper;
|
||||
private $stackMapper;
|
||||
private $permissionService;
|
||||
private $boardService;
|
||||
|
||||
public function __construct(CardMapper $cardMapper, StackMapper $stackMapper, PermissionService $permissionService) {
|
||||
public function __construct(CardMapper $cardMapper, StackMapper $stackMapper, PermissionService $permissionService, BoardService $boardService) {
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->stackMapper = $stackMapper;
|
||||
$this->permissionService = $permissionService;
|
||||
$this->boardService = $boardService;
|
||||
}
|
||||
|
||||
public function find($cardId) {
|
||||
@@ -51,6 +55,9 @@ class CardService {
|
||||
*/
|
||||
public function create($title, $stackId, $type, $order, $owner) {
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->stackMapper, $stackId)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = new Card();
|
||||
$card->setTitle($title);
|
||||
$card->setStackId($stackId);
|
||||
@@ -63,14 +70,20 @@ class CardService {
|
||||
|
||||
public function delete($id) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
return $this->cardMapper->delete($this->cardMapper->find($id));
|
||||
}
|
||||
|
||||
public function update($id, $title, $stackId, $type, $order, $description, $owner) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
if ($card->getArchived()) {
|
||||
throw new CardArchivedException();
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
$card->setTitle($title);
|
||||
$card->setStackId($stackId);
|
||||
@@ -83,9 +96,12 @@ class CardService {
|
||||
|
||||
public function rename($id, $title) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
if ($card->getArchived()) {
|
||||
throw new CardArchivedException();
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
$card->setTitle($title);
|
||||
return $this->cardMapper->update($card);
|
||||
@@ -93,12 +109,15 @@ class CardService {
|
||||
|
||||
public function reorder($id, $stackId, $order) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$cards = $this->cardMapper->findAll($stackId);
|
||||
$result = [];
|
||||
$i = 0;
|
||||
foreach ($cards as $card) {
|
||||
if ($card->getArchived()) {
|
||||
throw new CardArchivedException();
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
if ($card->id === $id) {
|
||||
$card->setOrder($order);
|
||||
@@ -121,6 +140,9 @@ class CardService {
|
||||
|
||||
public function archive($id) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$card->setArchived(true);
|
||||
return $this->cardMapper->update($card);
|
||||
@@ -128,6 +150,9 @@ class CardService {
|
||||
|
||||
public function unarchive($id) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$card->setArchived(false);
|
||||
return $this->cardMapper->update($card);
|
||||
@@ -135,18 +160,24 @@ class CardService {
|
||||
|
||||
public function assignLabel($cardId, $labelId) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $cardId)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
if ($card->getArchived()) {
|
||||
throw new CardArchivedException();
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
$this->cardMapper->assignLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
public function removeLabel($cardId, $labelId) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
if($this->boardService->isArchived($this->cardMapper, $cardId)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
if ($card->getArchived()) {
|
||||
throw new CardArchivedException();
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
$this->cardMapper->removeLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
@@ -26,15 +26,22 @@ namespace OCA\Deck\Service;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\StatusException;
|
||||
|
||||
|
||||
class LabelService {
|
||||
|
||||
/** @var LabelMapper */
|
||||
private $labelMapper;
|
||||
/** @var PermissionService */
|
||||
private $permissionService;
|
||||
/** @var BoardService */
|
||||
private $boardService;
|
||||
|
||||
public function __construct(LabelMapper $labelMapper, PermissionService $permissionService) {
|
||||
public function __construct(LabelMapper $labelMapper, PermissionService $permissionService, BoardService $boardService) {
|
||||
$this->labelMapper = $labelMapper;
|
||||
$this->permissionService = $permissionService;
|
||||
$this->boardService = $boardService;
|
||||
}
|
||||
|
||||
public function find($labelId) {
|
||||
@@ -44,6 +51,9 @@ class LabelService {
|
||||
|
||||
public function create($title, $color, $boardId) {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
if($this->boardService->isArchived(null, $boardId)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$label = new Label();
|
||||
$label->setTitle($title);
|
||||
$label->setColor($color);
|
||||
@@ -53,11 +63,17 @@ class LabelService {
|
||||
|
||||
public function delete($id) {
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
if($this->boardService->isArchived($this->labelMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
return $this->labelMapper->delete($this->find($id));
|
||||
}
|
||||
|
||||
public function update($id, $title, $color) {
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
if($this->boardService->isArchived($this->labelMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$label = $this->find($id);
|
||||
$label->setTitle($title);
|
||||
$label->setColor($color);
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\IPermissionMapper;
|
||||
use OCA\Deck\NoPermissionException;
|
||||
@@ -50,7 +51,7 @@ class PermissionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user permissions for a board
|
||||
* Get current user permissions for a board by id
|
||||
*
|
||||
* @param $boardId
|
||||
* @return bool|array
|
||||
@@ -66,6 +67,24 @@ class PermissionService {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user permissions for a board
|
||||
*
|
||||
* @param Board $board
|
||||
* @return array|bool
|
||||
* @internal param $boardId
|
||||
*/
|
||||
public function matchPermissions(Board $board) {
|
||||
$owner = $this->userIsBoardOwner($board->getId());
|
||||
$acls = $board->getAcl();
|
||||
return [
|
||||
Acl::PERMISSION_READ => $owner || $this->userCan($acls, Acl::PERMISSION_READ),
|
||||
Acl::PERMISSION_EDIT => $owner || $this->userCan($acls, Acl::PERMISSION_EDIT),
|
||||
Acl::PERMISSION_MANAGE => $owner || $this->userCan($acls, Acl::PERMISSION_MANAGE),
|
||||
Acl::PERMISSION_SHARE => $owner || $this->userCan($acls, Acl::PERMISSION_SHARE),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* check permissions for replacing dark magic middleware
|
||||
*
|
||||
|
||||
@@ -31,6 +31,7 @@ use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Db\Stack;
|
||||
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use OCA\Deck\StatusException;
|
||||
|
||||
|
||||
class StackService {
|
||||
@@ -39,12 +40,14 @@ class StackService {
|
||||
private $cardMapper;
|
||||
private $labelMapper;
|
||||
private $permissionService;
|
||||
private $boardService;
|
||||
|
||||
public function __construct(StackMapper $stackMapper, CardMapper $cardMapper, LabelMapper $labelMapper, PermissionService $permissionService) {
|
||||
public function __construct(StackMapper $stackMapper, CardMapper $cardMapper, LabelMapper $labelMapper, PermissionService $permissionService, BoardService $boardService) {
|
||||
$this->stackMapper = $stackMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->labelMapper = $labelMapper;
|
||||
$this->permissionService = $permissionService;
|
||||
$this->boardService = $boardService;
|
||||
}
|
||||
|
||||
public function findAll($boardId) {
|
||||
@@ -81,6 +84,9 @@ class StackService {
|
||||
|
||||
public function create($title, $boardId, $order) {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
if($this->boardService->isArchived(null, $boardId)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$stack = new Stack();
|
||||
$stack->setTitle($title);
|
||||
$stack->setBoardId($boardId);
|
||||
@@ -96,6 +102,9 @@ class StackService {
|
||||
|
||||
public function update($id, $title, $boardId, $order) {
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
if($this->boardService->isArchived($this->stackMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$stack = $this->stackMapper->find($id);
|
||||
$stack->setTitle($title);
|
||||
$stack->setBoardId($boardId);
|
||||
|
||||
@@ -45,7 +45,7 @@ if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
|
||||
'app' => ['App', 'Config', 'Run'],
|
||||
'controller' => ['AppController', 'BoardController', 'CardController', 'ListController'],
|
||||
'directive' => ['appnavigationentryutils', 'appPopoverMenuUtils', 'autofocusoninsert', 'avatar', 'elastic', 'search'],
|
||||
'filters' => ['cardFilter', 'cardSearchFilter', 'iconWhiteFilter', 'lightenColorFilter', 'orderObjectBy', 'relativeDateFilter', 'textColorFilter'],
|
||||
'filters' => ['boardFilterAcl', 'cardFilter', 'cardSearchFilter', 'iconWhiteFilter', 'lightenColorFilter', 'orderObjectBy', 'relativeDateFilter', 'textColorFilter'],
|
||||
'service' => ['ApiService', 'BoardService', 'CardService', 'LabelService', 'StackService', 'StatusService'],
|
||||
];
|
||||
foreach($js as $folder=>$files) {
|
||||
@@ -58,7 +58,7 @@ if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
|
||||
|
||||
<div id="app" class="app-deck" data-ng-app="Deck" ng-controller="AppController" ng-cloak>
|
||||
|
||||
<div id="app-navigation" data-ng-controller="ListController">
|
||||
<div id="app-navigation" data-ng-controller="ListController" ng-init="initSidebar()">
|
||||
<?php print_unescaped($this->inc('part.navigation')); ?>
|
||||
<?php /* print_unescaped($this->inc('part.settings')); */ ?>
|
||||
</div>
|
||||
|
||||
@@ -64,46 +64,40 @@
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-assignees" ng-if="c.assignees">
|
||||
<!-- <div class="avatar" avatar user="{{c.owner}}" size="24"></div>//-->
|
||||
</div>
|
||||
|
||||
<div class="card-controls">
|
||||
<i class="icon icon-filetype-text" ng-if="c.description" title="{{ c.description }}"></i>
|
||||
<div class="app-popover-menu-utils">
|
||||
<div class="app-popover-menu-utils" ng-if="!boardservice.isArchived()">
|
||||
<button class="button-inline card-options icon-more" ng-model="card"></button>
|
||||
<div class="popovermenu hidden">
|
||||
<ul>
|
||||
<li ng-if="filter!=='archive'">
|
||||
<a class="menuitem action action-rename permanent"
|
||||
data-action="Archive"
|
||||
ng-click="cardArchive(c); $event.stopPropagation();"><span
|
||||
class="icon icon-archive"></span><span><?php p($l->t('Archive')); ?></span></a>
|
||||
data-action="Archive"
|
||||
ng-click="cardArchive(c); $event.stopPropagation();"><span
|
||||
class="icon icon-archive"></span><span><?php p($l->t('Archive')); ?></span></a>
|
||||
</li>
|
||||
<li ng-if="filter==='archive'">
|
||||
<a class="menuitem action action-rename permanent"
|
||||
data-action="Unarchive"
|
||||
ng-click="cardUnarchive(c); $event.stopPropagation();"><span
|
||||
class="icon icon-archive"></span><span><?php p($l->t('Unarchive')); ?></span></a>
|
||||
data-action="Unarchive"
|
||||
ng-click="cardUnarchive(c); $event.stopPropagation();"><span
|
||||
class="icon icon-archive"></span><span><?php p($l->t('Unarchive')); ?></span></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="menuitem action action-delete permanent"
|
||||
data-action="Delete"
|
||||
ng-click="cardDelete(c)"><span
|
||||
class="icon icon-delete"></span><span><?php p($l->t('Delete')); ?></span></a>
|
||||
data-action="Delete"
|
||||
ng-click="cardDelete(c)"><span
|
||||
class="icon icon-delete"></span><span><?php p($l->t('Delete')); ?></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--<span class="info due"><i class="fa fa-clock-o" aria-hidden="true"></i> <span>Today</span></span>
|
||||
<span class="info tasks"><i class="fa fa-list" aria-hidden="true"></i> <span>3/12</span></span>
|
||||
//-->
|
||||
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- CREATE CARD //-->
|
||||
<div class="card create"
|
||||
style="background-color:#{{ boardservice.getCurrent().color }};" ng-if="boardservice.canEdit() && checkCanEdit() && filter!=='archive'">
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<h2>{{ boardservice.getCurrent().title }}</h2>
|
||||
</div>
|
||||
|
||||
{{board=boardservice.getCurrent();""}}
|
||||
|
||||
<ul class="tabHeaders">
|
||||
<li class="tabHeader" ng-class="{'selected': (status.boardtab==0 || !status.boardtab)}" ng-click="status.boardtab=0"><a><?php p($l->t('Sharing')); ?></a></li>
|
||||
@@ -90,7 +91,7 @@
|
||||
<input type="text" class="input-inline" ng-model="newLabel.title" style="color:{{ newLabel.color|textColorFilter }};" autofocus-on-insert maxlength="100" />
|
||||
</span>
|
||||
<div class="colorselect">
|
||||
<div class="color" ng-repeat="c in defaultColors" style="background-color:#{{ c }};" ng-click="newLabel.color=c" ng-class="{'selected': (c == newLabel.color) }"><br /></div>
|
||||
<div class="color" ng-repeat="c in defaultColors" style="background-color:#{{ c }};" ng-click="newLabel.color=c" ng-class="{'selected': (c == newLabel.color), 'dark': (newBoard.color | textColorFilter) === '#ffffff' }"><br /></div>
|
||||
</div>
|
||||
<a ng-click="labelCreate(newLabel)" class="icon"><i class="icon icon-checkmark" ></i></a>
|
||||
<a ng-click="status.createLabel=false" class="icon icon-close"></a>
|
||||
|
||||
@@ -5,31 +5,66 @@
|
||||
<td class="cell-board-bullet"></td>
|
||||
<td class="cell-board-title" width="90%"><?php p($l->t('Title')); ?></td>
|
||||
<td class="cell-board-members"><?php p($l->t('Members')); ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-ng-repeat="b in boardservice.sorted"
|
||||
ui-sref="board({boardId: b.id})">
|
||||
<td>
|
||||
<tr data-ng-repeat="b in boardservice.sorted" ng-class="{deleted: b.deletedAt > 0}">
|
||||
<td ng-click="gotoBoard(b)">
|
||||
<span class="board-bullet"
|
||||
style="background-color:#{{b.color}};"> </span>
|
||||
</td>
|
||||
<td><a href="#/board/{{b.id}}">{{ b.title }}</a></td>
|
||||
<td ng-click="gotoBoard(b)">{{ b.title }}</a></td>
|
||||
<td>
|
||||
<div id="assigned-users">
|
||||
<div class="avatardiv" avatar displayname="{{ b.owner.uid }}" title="{{ b.owner.displayname }}"></div>
|
||||
<div class="avatardiv" avatar displayname="{{ acl.participant.uid }}" title="{{ acl.participant.uid }}" ng-repeat="acl in b.acl | limitTo: 7"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="icon icon-add"></span></td>
|
||||
<td>
|
||||
<div class="hint"></div>
|
||||
<div class="app-popover-menu-utils" ng-if="b.deletedAt == 0">
|
||||
<button class="icon icon-more button-inline" title="More actions"></button>
|
||||
<div class="popovermenu bubble hidden">
|
||||
<ul>
|
||||
<li ng-if="boardservice.canManage(b) && !b.archived" ng-click="boardArchive(b)">
|
||||
<a class="menuitem"><span class="icon-archive"></span> <?php p($l->t('Archive board')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-if="boardservice.canManage(b) && b.archived" ng-click="boardUnarchive(b)">
|
||||
<a class="menuitem"><span class="icon-archive"></span> <?php p($l->t('Unarchive board')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-if="boardservice.canManage(b)" ng-click="boardDelete(b)">
|
||||
<a class="menuitem"><span class="icon-delete"></span> <?php p($l->t('Delete board')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li ui-sref="board.detail({boardId: b.id})">
|
||||
<a class="menuitem"><span class="icon-info"></span> <?php p($l->t('Board details')); ?>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-popover-menu-utils" ng-if="b.deletedAt > 0">
|
||||
<button class="icon icon-history button-inline" ng-click="boardDeleteUndo(b)" title="Undo board deletion - Otherwise the board will be deleted during the next cronjob run."></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="status.filter === '' && !status.addBoard" ng-click="status.addBoard=!status.addBoard">
|
||||
<td><span class="icon icon-add"></span></td>
|
||||
<td colspan="3">
|
||||
<a ng-click="status.addBoard=!status.addBoard"
|
||||
ng-show="!status.addBoard">
|
||||
<?php p($l->t('Create new board')); ?>
|
||||
</a>
|
||||
<form ng-show="status.addBoard" ng-disabled="isAddingList"
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-if="status.filter === '' && status.addBoard">
|
||||
<td><span class="icon icon-add"></span></td>
|
||||
<td>
|
||||
<form ng-disabled="isAddingList"
|
||||
class="ng-pristine ng-valid" ng-submit="boardCreate()">
|
||||
<input id="newTitle" class="edit ng-valid ng-empty"
|
||||
type="text" placeholder="<?php p($l->t('New board title')); ?>"
|
||||
@@ -38,13 +73,13 @@
|
||||
<div class="color" ng-repeat="c in colors"
|
||||
style="background-color:#{{ c }};"
|
||||
ng-click="selectColor(c)"
|
||||
ng-class="{'selected': (c == newBoard.color) }">
|
||||
<br/></div>
|
||||
ng-class="{'selected': (c == newBoard.color), 'dark': (newBoard.color | textColorFilter) === '#ffffff' }"></div>
|
||||
</div>
|
||||
<input type="submit" value="" class="icon-checkmark svg">
|
||||
<input type="submit" value="" class="icon-checkmark svg" />
|
||||
</form>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
<div id="labels">
|
||||
<ui-select multiple tagging="" ng-model="card.labels" theme="select2"
|
||||
ng-disabled="boardservice.isArchived() || card.archived"
|
||||
style="width:100%;" title="Choose a label"
|
||||
placeholder="Add a label"
|
||||
on-select="labelAssign($item, $model)"
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
<ul class="with-icon">
|
||||
|
||||
<li><a href="#" class=""><?php p($l->t('All Boards')); ?></a></li>
|
||||
<li ng-class="{active: status.filter === '' && !boardservice.getCurrent()}"><a ui-sref="list({ filter: ''})" class="icon-deck"><?php p($l->t('All Boards')); ?></a></li>
|
||||
<li ng-class="{active: status.filter === 'archived' || (boardservice.getCurrent() && boardservice.getCurrent().archived)}"><a ui-sref="list({ filter: 'archived' })" class="icon-archive"><?php p($l->t('Archived boards')); ?></a></li>
|
||||
<li ng-class="{active: status.filter === 'shared'}"><a ui-sref="list({ filter: 'shared' })" class="icon-share"><?php p($l->t('Shared boards')); ?></a></li>
|
||||
|
||||
<li class="with-icon with-menu" ng-class="{active: b.id === boardservice.getCurrent().id}" data-ng-repeat="b in boardservice.sorted">
|
||||
<li class="with-icon with-menu" ng-class="{active: b.id === boardservice.getCurrent().id}" data-ng-repeat="b in boardservice.sidebar" ng-if="b.deletedAt == 0">
|
||||
<span class="board-bullet" style="background-color:#{{b.color}};" ng-if="!b.status.edit"> </span>
|
||||
<a href="#!/board/{{b.id}}/" ng-if="!b.status.edit">{{ b.title }}</a>
|
||||
<div class="app-navigation-entry-utils" ng-show="!b.status.edit" style="position:absolute;">
|
||||
<ul>
|
||||
<li class="app-navigation-entry-utils-counter board-delete-undo" ng-show="status.deleteUndo[b.id]" ng-click="boardDeleteUndo(b)" title="Click to undo">Deleting in {{ status.deleteUndo[b.id] }}s X</li>
|
||||
<li class="app-navigation-entry-utils-menu-share svg" ng-show="b.shared>0"><i class="icon icon-share" title="<?php p($l->t('Shared with you')); ?>"> </i></li>
|
||||
<li class="app-navigation-entry-utils-menu-button svg" ng-show="!status.deleteUndo[b.id]"><button class="icon-more"></button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="app-navigation-entry-menu app-navigation-noclose" ng-show="!b.status.edit">
|
||||
<ul>
|
||||
<li ng-show="b.owner.uid===user"><button class="icon-rename svg" title="<?php p($l->t('edit')); ?>" ng-click="b.status.edit=true"></button></li>
|
||||
<li ng-show="b.owner.uid===user"><button class="icon-delete svg" title="<?php p($l->t('delete')); ?>" ng-click="boardDelete(b)"></button></li>
|
||||
<li ng-show="b.owner.uid!==user && false"><button class="icon-delete svg" title="<?php p($l->t('remove share')); ?>" ng-click="boardRemoveShare(b)"></button></li>
|
||||
<li ng-show="boardservice.canManage(b)"><button class="icon-rename svg" title="<?php p($l->t('Edit board')); ?>" ng-click="b.status.edit=true"></button></li>
|
||||
<li ng-show="boardservice.canManage(b)"><button class="icon-archive svg" title="<?php p($l->t('Move board to archive')); ?>" ng-click="boardArchive(b)"></button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="app-navigation-entry-deleted" ng-show="false">
|
||||
<div class="app-navigation-entry-deleted-description">Deleted X</div>
|
||||
<button class="app-navigation-entry-deleted-button icon-history svg" title="Undo"></button>
|
||||
</div>
|
||||
<div class="app-navigation-entry-edit" ng-show="b.status.edit">
|
||||
<form ng-disabled="isAddingList" class="ng-pristine ng-valid" ng-submit="boardUpdate(b)">
|
||||
<input id="newTitle" class="edit ng-valid ng-empty" type="text" autofocus-on-insert ng-model="b.title" maxlength="100">
|
||||
@@ -43,7 +39,7 @@
|
||||
<input id="newTitle" class="edit ng-valid ng-empty" type="text" placeholder="<?php p($l->t('New board title')); ?>" autofocus-on-insert ng-model="newBoard.title" maxlength="100">
|
||||
<input type="submit" value="" class="action icon-checkmark svg">
|
||||
<div class="colorselect">
|
||||
<div class="color" ng-repeat="c in colors" style="background-color:#{{ c }};" ng-click="selectColor(c)" ng-class="{'selected': (c == newBoard.color) }"><br /></div>
|
||||
<div class="color" ng-repeat="c in colors" style="background-color:#{{ c }};" ng-click="selectColor(c)" ng-class="{'selected': (c == newBoard.color), 'dark': (newBoard.color | textColorFilter) === '#ffffff' }"><br /></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/**
|
||||
* @group DB
|
||||
*/
|
||||
class BoardDatabaseTest extends \PHPUnit_Framework_TestCase
|
||||
class BoardDatabaseTest extends \Test\TestCase
|
||||
{
|
||||
const TEST_USER1 = "test-share-user1";
|
||||
const TEST_USER2 = "test-share-user2";
|
||||
@@ -61,6 +61,7 @@ class BoardDatabaseTest extends \PHPUnit_Framework_TestCase
|
||||
\OC::$server->getGroupManager()->addBackend($groupBackend);
|
||||
}
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
\OC::$server->getUserSession()->login(self::TEST_USER1, self::TEST_USER1);
|
||||
$this->boardService = \OC::$server->query("\OCA\Deck\Service\BoardService");
|
||||
}
|
||||
@@ -76,9 +77,10 @@ class BoardDatabaseTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($actual->getTitle(), $board->getTitle());
|
||||
$this->assertEquals($actual->getColor(), $board->getColor());
|
||||
$this->assertEquals($actual->getOwner(), $board->getOwner());
|
||||
$this->boardService->delete($id);
|
||||
$this->boardService->deleteForce($id);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
}
|
||||
}
|
||||
72
tests/unit/Cron/DeleteCronTest.php
Normal file
72
tests/unit/Cron/DeleteCronTest.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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\Cron;
|
||||
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
|
||||
class DeleteCronTest extends \Test\TestCase {
|
||||
|
||||
/** @var BoardMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
protected $boardMapper;
|
||||
/** @var DeleteCron */
|
||||
protected $deleteCron;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->boardMapper = $this->createMock(BoardMapper::class);
|
||||
$this->deleteCron = new DeleteCron($this->boardMapper);
|
||||
}
|
||||
|
||||
protected function getBoard($id) {
|
||||
$board = new Board();
|
||||
$board->setId($id);
|
||||
return $board;
|
||||
}
|
||||
|
||||
public function testDeleteCron() {
|
||||
$boards = [
|
||||
$this->getBoard(1),
|
||||
$this->getBoard(2),
|
||||
$this->getBoard(3),
|
||||
$this->getBoard(4),
|
||||
];
|
||||
$this->boardMapper->expects($this->once())
|
||||
->method('findToDelete')
|
||||
->willReturn($boards);
|
||||
$this->boardMapper->expects($this->at(1))
|
||||
->method('delete')
|
||||
->with($boards[0]);
|
||||
$this->boardMapper->expects($this->at(2))
|
||||
->method('delete')
|
||||
->with($boards[1]);
|
||||
$this->boardMapper->expects($this->at(3))
|
||||
->method('delete')
|
||||
->with($boards[2]);
|
||||
$this->boardMapper->expects($this->at(4))
|
||||
->method('delete')
|
||||
->with($boards[3]);
|
||||
$this->invokePrivate($this->deleteCron, 'run', [null]);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use Test\AppFramework\Db\MapperTestUtility;
|
||||
@@ -32,10 +33,15 @@ use Test\AppFramework\Db\MapperTestUtility;
|
||||
*/
|
||||
class BoardMapperTest extends MapperTestUtility {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $dbConnection;
|
||||
/** @var AclMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $aclMapper;
|
||||
/** @var BoardMapper */
|
||||
private $boardMapper;
|
||||
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $userManager;
|
||||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $groupManager;
|
||||
|
||||
// Data
|
||||
@@ -72,7 +78,7 @@ class BoardMapperTest extends MapperTestUtility {
|
||||
$this->aclMapper->insert($this->getAcl('user','user1', false, false, false, $this->boards[2]->getId()))
|
||||
];
|
||||
|
||||
foreach ($this->acls as $acl) {
|
||||
foreach ($this->acls as $acl) {
|
||||
$acl->resetUpdatedFields();
|
||||
}
|
||||
foreach ($this->boards as $board) {
|
||||
@@ -101,14 +107,55 @@ class BoardMapperTest extends MapperTestUtility {
|
||||
|
||||
public function testFind() {
|
||||
$actual = $this->boardMapper->find($this->boards[0]->getId());
|
||||
$expected = $this->boards[0];
|
||||
/** @var Board $expected */
|
||||
$expected = clone $this->boards[0];
|
||||
$expected->setShared(-1);
|
||||
$expected->resetUpdatedFields();
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testFindAllByUser() {
|
||||
$actual = $this->boardMapper->findAllByUser('user1');
|
||||
$expected = [
|
||||
$this->boards[0],
|
||||
$this->boards[1],
|
||||
$this->boards[2]
|
||||
];
|
||||
foreach ($expected as $e) {
|
||||
foreach ($actual as $a) {
|
||||
if($e->getId() === $a->getId()) {
|
||||
$this->assertEquals($e->getTitle(), $a->getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testFindAll() {
|
||||
$actual = $this->boardMapper->findAll();
|
||||
$this->assertEquals($this->boards[0]->getId(), $actual[0]->getId());
|
||||
$this->assertEquals($this->boards[1]->getId(), $actual[1]->getId());
|
||||
$this->assertEquals($this->boards[2]->getId(), $actual[2]->getId());
|
||||
}
|
||||
|
||||
public function testFindAllToDelete() {
|
||||
$this->boards[0]->setDeletedAt(1);
|
||||
$this->boards[0] = $this->boardMapper->update($this->boards[0]);
|
||||
|
||||
$actual = $this->boardMapper->findToDelete();
|
||||
$this->boards[0]->resetUpdatedFields();
|
||||
$this->assertEquals([$this->boards[0]], $actual);
|
||||
|
||||
$this->boards[0]->setDeletedAt(0);
|
||||
$this->boardMapper->update($this->boards[0]);
|
||||
}
|
||||
|
||||
public function testFindWithLabels() {
|
||||
$actual = $this->boardMapper->find($this->boards[0]->getId(), true, false);
|
||||
$expected = $this->boards[0];
|
||||
$this->assertEquals($expected, $actual);
|
||||
/** @var Board $expected */
|
||||
$expected = $this->boards[0];
|
||||
$this->assertEquals($expected->getLabels(), $actual->getLabels());
|
||||
}
|
||||
|
||||
public function testFindWithAcl() {
|
||||
$actual = $this->boardMapper->find($this->boards[0]->getId(), false, true);
|
||||
$expected = [
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
class BoardTest extends \PHPUnit_Framework_TestCase {
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BoardTest extends TestCase {
|
||||
private function createBoard() {
|
||||
$board = new Board();
|
||||
$board->setId(1);
|
||||
@@ -21,6 +23,8 @@ class BoardTest extends \PHPUnit_Framework_TestCase {
|
||||
'owner' => "admin",
|
||||
'color' => "000000",
|
||||
'labels' => array(),
|
||||
'permissions' => [],
|
||||
'deletedAt' => 0,
|
||||
'acl' => array(),
|
||||
'archived' => false
|
||||
], $board->jsonSerialize());
|
||||
@@ -35,6 +39,8 @@ class BoardTest extends \PHPUnit_Framework_TestCase {
|
||||
'owner' => "admin",
|
||||
'color' => "000000",
|
||||
'labels' => array("foo", "bar"),
|
||||
'permissions' => [],
|
||||
'deletedAt' => 0,
|
||||
'acl' => array(),
|
||||
'archived' => false
|
||||
], $board->jsonSerialize());
|
||||
@@ -56,6 +62,8 @@ class BoardTest extends \PHPUnit_Framework_TestCase {
|
||||
'owner' => "admin",
|
||||
'color' => "000000",
|
||||
'labels' => array(),
|
||||
'permissions' => [],
|
||||
'deletedAt' => 0,
|
||||
'acl' => array(),
|
||||
'archived' => false,
|
||||
'shared' => 1,
|
||||
|
||||
58
tests/unit/Db/GroupTest.php
Normal file
58
tests/unit/Db/GroupTest.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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;
|
||||
|
||||
use OCP\IGroup;
|
||||
|
||||
class GroupTest extends \Test\TestCase {
|
||||
|
||||
public function testGroupObjectSerialize() {
|
||||
/** @var IGroup $group */
|
||||
$group = $this->createMock(IGroup::class);
|
||||
$group->expects($this->any())
|
||||
->method('getGID')
|
||||
->willReturn('mygroup');
|
||||
$groupRelationalObject = new Group($group);
|
||||
$expected = [
|
||||
'uid' => 'mygroup',
|
||||
'displayname' => 'mygroup'
|
||||
];
|
||||
$this->assertEquals($expected, $groupRelationalObject->getObjectSerialization());
|
||||
}
|
||||
|
||||
public function testGroupJSONSerialize() {
|
||||
/** @var IGroup $group */
|
||||
$group = $this->createMock(IGroup::class);
|
||||
$group->expects($this->any())
|
||||
->method('getGID')
|
||||
->willReturn('mygroup');
|
||||
$groupRelationalObject = new Group($group);
|
||||
$expected = [
|
||||
'uid' => 'mygroup',
|
||||
'displayname' => 'mygroup',
|
||||
'primaryKey' => 'mygroup'
|
||||
];
|
||||
$this->assertEquals($expected, $groupRelationalObject->jsonSerialize());
|
||||
}
|
||||
}
|
||||
64
tests/unit/Db/UserTest.php
Normal file
64
tests/unit/Db/UserTest.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?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;
|
||||
|
||||
use OCP\IUser;
|
||||
|
||||
class UserTest extends \Test\TestCase {
|
||||
|
||||
public function testGroupObjectSerialize() {
|
||||
/** @var IUser $user */
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn('myuser');
|
||||
$user->expects($this->any())
|
||||
->method('getDisplayName')
|
||||
->willReturn('myuser displayname');
|
||||
$userRelationalObject = new User($user);
|
||||
$expected = [
|
||||
'uid' => 'myuser',
|
||||
'displayname' => 'myuser displayname'
|
||||
];
|
||||
$this->assertEquals($expected, $userRelationalObject->getObjectSerialization());
|
||||
}
|
||||
|
||||
public function testGroupJSONSerialize() {
|
||||
/** @var IUser $user */
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn('myuser');
|
||||
$user->expects($this->any())
|
||||
->method('getDisplayName')
|
||||
->willReturn('myuser displayname');
|
||||
$userRelationalObject = new User($user);
|
||||
$expected = [
|
||||
'uid' => 'myuser',
|
||||
'displayname' => 'myuser displayname',
|
||||
'primaryKey' => 'myuser'
|
||||
];
|
||||
$this->assertEquals($expected, $userRelationalObject->jsonSerialize());
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
use OCA\Deck\CardArchivedException;
|
||||
use OCA\Deck\ArchivedItemException;
|
||||
use OCA\Deck\Controller\PageController;
|
||||
use OCA\Deck\NoPermissionException;
|
||||
use OCA\Deck\NotFoundException;
|
||||
@@ -45,7 +45,7 @@ class ExceptionsTest extends \PHPUnit_Framework_TestCase {
|
||||
}
|
||||
|
||||
public function testCardArchivedException() {
|
||||
$e = new CardArchivedException('foo');
|
||||
$e = new ArchivedItemException('foo');
|
||||
$this->assertEquals('foo', $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
128
tests/unit/Migration/UnknownUserTest.php
Normal file
128
tests/unit/Migration/UnknownUserTest.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?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\Migration;
|
||||
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
class UnknownUserTest extends \Test\TestCase {
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
/** @var AclMapper */
|
||||
private $aclMapper;
|
||||
/** @var BoardMapper */
|
||||
private $boardMapper;
|
||||
/** @var UnknownUsers */
|
||||
private $unknownUsers;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
$this->aclMapper = $this->createMock(AclMapper::class);
|
||||
$this->boardMapper = $this->createMock(BoardMapper::class);
|
||||
$this->unknownUsers = new UnknownUsers($this->userManager, $this->groupManager, $this->aclMapper, $this->boardMapper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testGetName() {
|
||||
$this->assertEquals('Delete orphaned ACL rules', $this->unknownUsers->getName());
|
||||
}
|
||||
|
||||
public function testRun() {
|
||||
/** @var IOutput $output */
|
||||
$output = $this->createMock(IOutput::class);
|
||||
$boards = [
|
||||
$this->getBoard(1,'Test', 'admin'),
|
||||
];
|
||||
$acl = [
|
||||
$this->getAcl('user', 'existing', 1),
|
||||
$this->getAcl('user', 'not existing', 1),
|
||||
$this->getAcl('group', 'existing', 1),
|
||||
$this->getAcl('group', 'not existing', 1),
|
||||
];
|
||||
$this->aclMapper->expects($this->at(0))
|
||||
->method('findAll')
|
||||
->with(1)
|
||||
->willReturn($acl);
|
||||
|
||||
$this->userManager->expects($this->at(0))
|
||||
->method('get')
|
||||
->with('existing')
|
||||
->willReturn(true);
|
||||
$this->userManager->expects($this->at(1))
|
||||
->method('get')
|
||||
->with('not existing')
|
||||
->willReturn(null);
|
||||
$this->groupManager->expects($this->at(0))
|
||||
->method('get')
|
||||
->with('existing')
|
||||
->willReturn(true);
|
||||
$this->groupManager->expects($this->at(1))
|
||||
->method('get')
|
||||
->with('not existing')
|
||||
->willReturn(null);
|
||||
|
||||
$this->boardMapper->expects($this->once())
|
||||
->method('findAll')
|
||||
->willReturn($boards);
|
||||
|
||||
$this->aclMapper->expects($this->at(1))
|
||||
->method('delete')
|
||||
->with($acl[1]);
|
||||
$this->aclMapper->expects($this->at(2))
|
||||
->method('delete')
|
||||
->with($acl[3]);
|
||||
|
||||
$this->unknownUsers->run($output);
|
||||
}
|
||||
|
||||
|
||||
/** @return Acl */
|
||||
public function getAcl($type='user', $participant='admin', $boardId=123) {
|
||||
$acl = new Acl();
|
||||
$acl->setParticipant($participant);
|
||||
$acl->setType($type);
|
||||
$acl->setBoardId($boardId);
|
||||
return $acl;
|
||||
}
|
||||
|
||||
/** @return Board */
|
||||
public function getBoard($id, $title, $owner) {
|
||||
$board = new Board();
|
||||
$board->setId($id);
|
||||
$board->setTitle($title);
|
||||
$board->setOwner($owner);
|
||||
return $board;
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ class BoardServiceTest extends \Test\TestCase {
|
||||
private $userId = 'admin';
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->l10n = $this->createMock(L10N::class);
|
||||
$this->aclMapper = $this->createMock(AclMapper::class);
|
||||
$this->boardMapper = $this->createMock(BoardMapper::class);
|
||||
@@ -134,11 +135,12 @@ class BoardServiceTest extends \Test\TestCase {
|
||||
->method('update')
|
||||
->with($board)
|
||||
->willReturn($board);
|
||||
$b = $this->service->update(123, 'MyNewNameBoard', 'ffffff');
|
||||
$b = $this->service->update(123, 'MyNewNameBoard', 'ffffff', false);
|
||||
|
||||
$this->assertEquals($b->getTitle(), 'MyNewNameBoard');
|
||||
$this->assertEquals($b->getOwner(), 'admin');
|
||||
$this->assertEquals($b->getColor(), 'ffffff');
|
||||
$this->assertEquals($b->getArchived(), false);
|
||||
}
|
||||
|
||||
public function testDelete() {
|
||||
@@ -147,10 +149,7 @@ class BoardServiceTest extends \Test\TestCase {
|
||||
$this->boardMapper->expects($this->once())
|
||||
->method('find')
|
||||
->willReturn($board);
|
||||
$this->boardMapper->expects($this->once())
|
||||
->method('delete')
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->service->delete(123));
|
||||
$this->assertEquals($board, $this->service->delete(123));
|
||||
}
|
||||
|
||||
public function testAddAcl() {
|
||||
|
||||
@@ -27,9 +27,10 @@ namespace OCA\Deck\Service;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use OCA\Deck\CardArchivedException;
|
||||
use OCA\Deck\StatusException;
|
||||
use Test\TestCase;
|
||||
|
||||
class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
class CardServiceTest extends TestCase {
|
||||
|
||||
/** @var CardService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $cardService;
|
||||
@@ -39,16 +40,19 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
private $stackMapper;
|
||||
/** @var PermissionService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $permissionService;
|
||||
|
||||
/** @var BoardService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $boardService;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->cardMapper = $this->getMockBuilder(CardMapper::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->stackMapper = $this->getMockBuilder(StackMapper::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->permissionService = $this->getMockBuilder(PermissionService::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->cardService = new CardService($this->cardMapper, $this->stackMapper, $this->permissionService);
|
||||
$this->boardService = $this->createMock(BoardService::class);
|
||||
$this->cardService = new CardService($this->cardMapper, $this->stackMapper, $this->permissionService, $this->boardService);
|
||||
}
|
||||
|
||||
public function testFind() {
|
||||
@@ -108,7 +112,7 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$card->setArchived(true);
|
||||
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
|
||||
$this->cardMapper->expects($this->never())->method('update');
|
||||
$this->setExpectedException(CardArchivedException::class);
|
||||
$this->setExpectedException(StatusException::class);
|
||||
$this->cardService->update(123, 'newtitle', 234, 'text', 999, 'foo', 'admin');
|
||||
}
|
||||
|
||||
@@ -128,7 +132,7 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$card->setArchived(true);
|
||||
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
|
||||
$this->cardMapper->expects($this->never())->method('update');
|
||||
$this->setExpectedException(CardArchivedException::class);
|
||||
$this->setExpectedException(StatusException::class);
|
||||
$this->cardService->rename(123, 'newtitle');
|
||||
}
|
||||
|
||||
@@ -168,7 +172,7 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$card->setArchived(true);
|
||||
$this->cardMapper->expects($this->once())->method('findAll')->willReturn([$card]);
|
||||
$this->cardMapper->expects($this->never())->method('update')->willReturnCallback(function($c) { return $c; });
|
||||
$this->setExpectedException(CardArchivedException::class);
|
||||
$this->setExpectedException(StatusException::class);
|
||||
$actual = $this->cardService->reorder(123, 234, 1);
|
||||
}
|
||||
public function testArchive() {
|
||||
@@ -204,7 +208,7 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$card->setArchived(true);
|
||||
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
|
||||
$this->cardMapper->expects($this->never())->method('assignLabel');
|
||||
$this->setExpectedException(CardArchivedException::class);
|
||||
$this->setExpectedException(StatusException::class);
|
||||
$this->cardService->assignLabel(123, 999);
|
||||
}
|
||||
|
||||
@@ -221,7 +225,7 @@ class CardServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$card->setArchived(true);
|
||||
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
|
||||
$this->cardMapper->expects($this->never())->method('removeLabel');
|
||||
$this->setExpectedException(CardArchivedException::class);
|
||||
$this->setExpectedException(StatusException::class);
|
||||
$this->cardService->removeLabel(123, 999);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@ namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use Test\TestCase;
|
||||
|
||||
class LabelServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
class LabelServiceTest extends TestCase {
|
||||
|
||||
/** @var LabelMapper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $labelMapper;
|
||||
@@ -35,15 +36,20 @@ class LabelServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
private $permissionService;
|
||||
/** @var LabelService */
|
||||
private $labelService;
|
||||
/** @var BoardService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $boardService;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->labelMapper = $this->getMockBuilder(LabelMapper::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->permissionService = $this->getMockBuilder(PermissionService::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->boardService = $this->createMock(BoardService::class);
|
||||
$this->labelService = new LabelService(
|
||||
$this->labelMapper,
|
||||
$this->permissionService
|
||||
$this->permissionService,
|
||||
$this->boardService
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ class PermissionServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
private $userId = 'admin';
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->logger = $this->request = $this->getMockBuilder(ILogger::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
@@ -31,8 +31,15 @@ use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use \Test\TestCase;
|
||||
|
||||
class StackServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
/**
|
||||
* Class StackServiceTest
|
||||
*
|
||||
* @package OCA\Deck\Service
|
||||
* @group DB
|
||||
*/
|
||||
class StackServiceTest extends TestCase {
|
||||
|
||||
/** @var StackService */
|
||||
private $stackService;
|
||||
@@ -44,8 +51,11 @@ class StackServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
private $labelMapper;
|
||||
/** @var \PHPUnit_Framework_MockObject_MockObject|PermissionService */
|
||||
private $permissionService;
|
||||
/** @var BoardService|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $boardService;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->stackMapper = $this->getMockBuilder(StackMapper::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->cardMapper = $this->getMockBuilder(CardMapper::class)
|
||||
@@ -54,12 +64,14 @@ class StackServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->permissionService = $this->getMockBuilder(PermissionService::class)
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->boardService = $this->createMock(BoardService::class);
|
||||
|
||||
$this->stackService = new StackService(
|
||||
$this->stackMapper,
|
||||
$this->cardMapper,
|
||||
$this->labelMapper,
|
||||
$this->permissionService
|
||||
$this->permissionService,
|
||||
$this->boardService
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,6 +172,9 @@ class StackServiceTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertEquals($stack, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DB
|
||||
*/
|
||||
public function testReorder() {
|
||||
$this->permissionService->expects($this->once())->method('checkPermission');
|
||||
$a = $this->createStack(1, 0);
|
||||
|
||||
@@ -107,9 +107,9 @@ class BoardControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
public function testUpdate() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('update')
|
||||
->with(1, 2, 3)
|
||||
->with(1, 2, 3, false)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->update(1, 2, 3));
|
||||
$this->assertEquals(1, $this->controller->update(1, 2, 3, false));
|
||||
}
|
||||
|
||||
public function testDelete() {
|
||||
@@ -120,6 +120,14 @@ class BoardControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertEquals(1, $this->controller->delete(123));
|
||||
}
|
||||
|
||||
public function testDeleteUndo() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('deleteUndo')
|
||||
->with(123)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->deleteUndo(123));
|
||||
}
|
||||
|
||||
public function testGetUserPermissions() {
|
||||
$acl = [
|
||||
Acl::PERMISSION_READ => true,
|
||||
|
||||
Reference in New Issue
Block a user