From 6a40dce138cc91a1a2b3dc51572ddb2babf70301 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Mon, 14 Nov 2016 13:59:52 +0100 Subject: [PATCH 1/9] Initial commit of the bruteforcesettings app This adds the bruteforce settings app that allows to configure (for now) subnets that are to be ignored when doing brute force analysis. This can for example be the LAN since we trust people from there. * Add app * Add php tests * Add js tests Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- .drone.yml | 1 + .gitignore | 2 +- apps/bruteforcesettings/appinfo/info.xml | 21 +++ apps/bruteforcesettings/appinfo/routes.php | 30 +++ apps/bruteforcesettings/js/IPWhitelist.js | 44 +++++ .../js/IPWhitelistCollection.js | 34 ++++ .../bruteforcesettings/js/IPWhitelistModel.js | 29 +++ apps/bruteforcesettings/js/IPWhitelistView.js | 128 +++++++++++++ .../lib/Controller/IPWhitelistController.php | 123 +++++++++++++ .../lib/Settings/IPWhitelist.php | 42 +++++ .../templates/ipwhitelist.php | 48 +++++ .../Controller/IPWhitelistControllerTest.php | 151 +++++++++++++++ .../tests/Settings/IPWhitelistTest.php | 33 ++++ .../tests/js/IPWhitelistSpec.js | 174 ++++++++++++++++++ .../features/provisioning-v1.feature | 1 + tests/karma.config.js | 13 ++ tests/phpunit-autotest.xml | 1 + 17 files changed, 874 insertions(+), 1 deletion(-) create mode 100644 apps/bruteforcesettings/appinfo/info.xml create mode 100644 apps/bruteforcesettings/appinfo/routes.php create mode 100644 apps/bruteforcesettings/js/IPWhitelist.js create mode 100644 apps/bruteforcesettings/js/IPWhitelistCollection.js create mode 100644 apps/bruteforcesettings/js/IPWhitelistModel.js create mode 100644 apps/bruteforcesettings/js/IPWhitelistView.js create mode 100644 apps/bruteforcesettings/lib/Controller/IPWhitelistController.php create mode 100644 apps/bruteforcesettings/lib/Settings/IPWhitelist.php create mode 100644 apps/bruteforcesettings/templates/ipwhitelist.php create mode 100644 apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php create mode 100644 apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php create mode 100644 apps/bruteforcesettings/tests/js/IPWhitelistSpec.js diff --git a/.drone.yml b/.drone.yml index dd4ec40420971..8d3e3551a6e86 100644 --- a/.drone.yml +++ b/.drone.yml @@ -30,6 +30,7 @@ pipeline: image: nextcloudci/php7.0:php7.0-7 commands: - ./occ app:check-code admin_audit + - ./occ app:check-code bruteforcesettings - ./occ app:check-code comments - ./occ app:check-code federation - ./occ app:check-code sharebymail diff --git a/.gitignore b/.gitignore index d8669fed07438..1e0f53a3c076f 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,7 @@ /apps/files_external/3rdparty/irodsphp/prods/tutorials /apps/files_external/3rdparty/irodsphp/prods/test* /apps/files_external/tests/config.*.php - +!/apps/bruteforcesettings # ignore themes except the example and the README diff --git a/apps/bruteforcesettings/appinfo/info.xml b/apps/bruteforcesettings/appinfo/info.xml new file mode 100644 index 0000000000000..2c3e1256e8505 --- /dev/null +++ b/apps/bruteforcesettings/appinfo/info.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<info> + <id>bruteforcesettings</id> + <name>Brute force settings</name> + <description> + This applications allows admins to configure the brute force settings. + </description> + <licence>AGPL</licence> + <author>Roeland Jago Douma</author> + <default_enable/> + <version>1.0.0</version> + <dependencies> + <owncloud min-version="9.2" max-version="9.2" /> + </dependencies> + + <namespace>BruteForceSettings</namespace> + + <settings> + <admin>OCA\BruteForceSettings\Settings\IPWhitelist</admin> + </settings> +</info> diff --git a/apps/bruteforcesettings/appinfo/routes.php b/apps/bruteforcesettings/appinfo/routes.php new file mode 100644 index 0000000000000..28ab6e9cee43f --- /dev/null +++ b/apps/bruteforcesettings/appinfo/routes.php @@ -0,0 +1,30 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +return [ + 'routes' => [ + [ 'name' => 'IPWhitelist#getAll', 'url' => '/ipwhitelist', 'verb' => 'GET' ], + [ 'name' => 'IPWhitelist#add', 'url' => '/ipwhitelist', 'verb' => 'POST' ], + [ 'name' => 'IPWhitelist#remove', 'url' => '/ipwhitelist/{id}', 'verb' => 'DELETE' ], + ] +]; diff --git a/apps/bruteforcesettings/js/IPWhitelist.js b/apps/bruteforcesettings/js/IPWhitelist.js new file mode 100644 index 0000000000000..163d5d2852a62 --- /dev/null +++ b/apps/bruteforcesettings/js/IPWhitelist.js @@ -0,0 +1,44 @@ +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +(function() { + + OCA.BruteForceSettings = OCA.BruteForceSettings || {}; + + OCA.BruteForceSettings.WhiteList = { + + collection: null, + view: null, + + init: function () { + this.collection = new OCA.BruteForceSettings.WhitelistCollection(); + this.view = new OCA.BruteForceSettings.WhitelistView({ + collection: this.collection + }); + this.view.reload(); + } + }; +})(); + +$(document).ready(function() { + OCA.BruteForceSettings.WhiteList.init(); +}); diff --git a/apps/bruteforcesettings/js/IPWhitelistCollection.js b/apps/bruteforcesettings/js/IPWhitelistCollection.js new file mode 100644 index 0000000000000..bf5b34d1ad0dc --- /dev/null +++ b/apps/bruteforcesettings/js/IPWhitelistCollection.js @@ -0,0 +1,34 @@ +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +(function() { + + OCA.BruteForceSettings = OCA.BruteForceSettings || {}; + + OCA.BruteForceSettings.WhitelistCollection = OC.Backbone.Collection.extend({ + model: OCA.BruteForceSettings.WhitelistModel, + + url: function() { + return OC.generateUrl('/apps/bruteforcesettings/ipwhitelist'); + } + }); +})(); diff --git a/apps/bruteforcesettings/js/IPWhitelistModel.js b/apps/bruteforcesettings/js/IPWhitelistModel.js new file mode 100644 index 0000000000000..5c309f5af74ba --- /dev/null +++ b/apps/bruteforcesettings/js/IPWhitelistModel.js @@ -0,0 +1,29 @@ +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +(function() { + + OCA.BruteForceSettings = OCA.BruteForceSettings || {}; + + OCA.BruteForceSettings.WhitelistModel = OC.Backbone.Model.extend({ + }); +})(); diff --git a/apps/bruteforcesettings/js/IPWhitelistView.js b/apps/bruteforcesettings/js/IPWhitelistView.js new file mode 100644 index 0000000000000..da711ae12252e --- /dev/null +++ b/apps/bruteforcesettings/js/IPWhitelistView.js @@ -0,0 +1,128 @@ +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +(function () { + + OCA.BruteForceSettings = OCA.BruteForceSettings || {}; + + var TEMPLATE_WHITELIST = + '<tr data-id="{{id}}">' + + '<td><span>{{ip}}/{{mask}}</span></td>' + + '<td><a class="icon-delete has-tooltip" title="' + t('bruteforcesettings', 'Delete') + '">BAD CSS</a></td>' + + '</tr>'; + + OCA.BruteForceSettings.WhitelistView = OC.Backbone.View.extend({ + collection: null, + + ipInput: undefined, + maskInput: undefined, + submit: undefined, + + list: undefined, + listHeader: undefined, + + initialize: function(options) { + this.collection = options.collection; + + this.ipInput = $('#whitelist_ip'); + this.maskInput = $('#whitelist_mask'); + this.submit = $('#whitelist_submit'); + this.submit.click(_.bind(this._addWhitelist, this)); + + this.list = $('#whitelist-list'); + this.listHeader = $('#whitelist-list-header'); + + this.list.on('click', 'a.icon-delete', _.bind(this._onDeleteRetention, this)); + this.listenTo(this.collection, 'sync', this.render); + }, + + + + reload: function() { + var _this = this; + var loadingWhitelists = this.collection.fetch(); + + $.when(loadingWhitelists).done(function () { + _this.render(); + }); + $.when(loadingWhitelists).fail(function () { + OC.Notification.showTemporary(t('bruteforcesettings', 'Error while whitelists.')); + }); + }, + + template: function (data) { + if (_.isUndefined(this._template)) { + this._template = Handlebars.compile(TEMPLATE_WHITELIST); + } + + return this._template(data); + }, + + render: function () { + var _this = this; + this.list.html(''); + + this.collection.forEach(function (model) { + var data = { + id: model.attributes.id, + ip: model.attributes.ip, + mask: model.attributes.mask + }; + var html = _this.template(data); + var $html = $(html); + _this.list.append($html); + }); + }, + + _onDeleteRetention: function(event) { + var $target = $(event.target); + var $row = $target.closest('tr'); + var id = $row.data('id'); + + var whitelist = this.collection.get(id); + + if (_.isUndefined(whitelist)) { + // Ignore event + return; + } + + var destroyingRetention = whitelist.destroy(); + + $row.find('.icon-delete').tooltip('hide'); + + var _this = this; + $.when(destroyingRetention).fail(function () { + OC.Notification.showTemporary(t('bruteforcesettings', 'Error while deleting a whitelist')); + }); + $.when(destroyingRetention).always(function () { + _this.render(); + }); + }, + + _addWhitelist: function() { + this.collection.create({ + ip: this.ipInput.val(), + mask: this.maskInput.val() + }); + } + }); +})(); diff --git a/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php b/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php new file mode 100644 index 0000000000000..9b5183f7495fb --- /dev/null +++ b/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php @@ -0,0 +1,123 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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\BruteForceSettings\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IConfig; +use OCP\IRequest; + +class IPWhitelistController extends Controller { + + /** @var IConfig */ + private $config; + + /** + * IPWhitelistController constructor. + * + * @param string $appName + * @param IRequest $request + * @param IConfig $config + */ + public function __construct($appName, + IRequest $request, + IConfig $config) { + parent::__construct($appName, $request); + + $this->config = $config; + } + + /** + * @return JSONResponse + */ + public function getAll() { + $keys = $this->config->getAppKeys('bruteForce'); + $keys = array_filter($keys, function($key) { + $regex = '/^whitelist_/S'; + return preg_match($regex, $key) === 1; + }); + + $result = []; + + foreach ($keys as $key) { + $value = $this->config->getAppValue('bruteForce', $key); + $values = explode('/', $value); + + $result[] = [ + 'id' => (int)substr($key, 10), + 'ip' => $values[0], + 'mask' => $values[1], + ]; + } + + return new JSONResponse($result); + } + + /** + * @param string $ip + * @param int $mask + * @return JSONResponse + */ + public function add($ip, $mask) { + if (!filter_var($ip, FILTER_VALIDATE_IP) || + (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && ($mask < 0 || $mask > 32)) || + (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && ($mask < 0 || $mask > 128))) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + + $keys = $this->config->getAppKeys('bruteForce'); + $keys = array_filter($keys, function($key) { + $regex = '/^whitelist_/S'; + return preg_match($regex, $key) === 1; + }); + + $id = 0; + foreach ($keys as $key) { + $tmp = (int)substr($key, 10); + if ($tmp > $id) { + $id = $tmp; + } + } + $id++; + + $value = $ip . '/' . $mask; + $this->config->setAppValue('bruteForce', 'whitelist_'.$id, $value); + return new JSONResponse([ + 'id' => $id, + 'ip' => $ip, + 'mask' => $mask, + ]); + } + + /** + * @param int $id + * @return JSONResponse + */ + public function remove($id) { + $this->config->deleteAppValue('bruteForce', 'whitelist_'.$id); + + return new JSONResponse([]); + } +} diff --git a/apps/bruteforcesettings/lib/Settings/IPWhitelist.php b/apps/bruteforcesettings/lib/Settings/IPWhitelist.php new file mode 100644 index 0000000000000..7e4aab2f22f4f --- /dev/null +++ b/apps/bruteforcesettings/lib/Settings/IPWhitelist.php @@ -0,0 +1,42 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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\BruteForceSettings\Settings; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\Settings\ISettings; + +class IPWhitelist implements ISettings { + + public function getForm() { + return new TemplateResponse('bruteforcesettings', 'ipwhitelist'); + } + + public function getSection() { + return 'security'; + } + + public function getPriority() { + return 50; + } +} diff --git a/apps/bruteforcesettings/templates/ipwhitelist.php b/apps/bruteforcesettings/templates/ipwhitelist.php new file mode 100644 index 0000000000000..69354956168d4 --- /dev/null +++ b/apps/bruteforcesettings/templates/ipwhitelist.php @@ -0,0 +1,48 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +script('core', [ + 'oc-backbone-webdav', +]); +script('bruteforcesettings', [ + 'IPWhitelist', + 'IPWhitelistModel', + 'IPWhitelistCollection', + 'IPWhitelistView', +]); + +/** @var \OCP\IL10N $l */ +?> +<form id="IPWhiteList" class="section"> + <h2><?php p($l->t('Brute force ip whitelist')); ?></h2> + + <table> + <tbody id="whitelist-list"> + + </tbody> + </table> + + <input type="text" name="whitelist_ip" id="whitelist_ip" placeholder="1.2.3.4" style="width: 200px;" />/ + <input type="number" id="whitelist_mask" name="whitelist_mask" placeholder="24" style="width: 50px;"> + <input type="button" id="whitelist_submit" value="<?php p($l->t('Add')); ?>"> +</form> diff --git a/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php b/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php new file mode 100644 index 0000000000000..c45fc6a9417b2 --- /dev/null +++ b/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php @@ -0,0 +1,151 @@ +<?php +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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\BruteForceSettings\Tests\Controller; + +use OCA\BruteForceSettings\Controller\IPWhitelistController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IConfig; +use OCP\IRequest; +use Test\TestCase; + +class IPWhitelistControllerTest extends TestCase { + + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ + private $config; + /** @var IPWhitelistController */ + private $controller; + + public function setUp() { + parent::setUp(); + + $this->config = $this->createMock(IConfig::class); + $this->controller = new IPWhitelistController( + 'bruteforce', + $this->createMock(IRequest::class), + $this->config + ); + } + + public function testGetAll() { + $this->config->method('getAppKeys') + ->with($this->equalTo('bruteForce')) + ->willReturn([ + 'foobar', + 'whitelist_0', + 'whitelist_99', + ]); + + $this->config->method('getAppValue') + ->will($this->returnCallback(function($app, $key) { + if ($app !== 'bruteForce') { + $this->fail(); + } + if ($key === 'whitelist_0') { + return '192.168.2.0/24'; + } else if ($key === 'whitelist_99') { + return 'dead:beef:cafe::/92'; + } + $this->fail(); + })); + + $expected = new JSONResponse([ + [ + 'id' => 0, + 'ip' => '192.168.2.0', + 'mask' => '24', + ], + [ + 'id' => 99, + 'ip' => 'dead:beef:cafe::', + 'mask' => '92', + ] + ]); + + $this->assertEquals($expected, $this->controller->getAll()); + } + + public function dataAdd() { + return [ + ['8.500.2.3', 24, false], + ['1.2.3.4', 24, true], + ['1.2.3.4', -1, false], + ['1.2.3.4', 33, false], + + ['dead:nope::8', 24, false], + ['1234:567:abef::1a2b', 24, true], + ['1234:567:abef::1a2b', -1, false], + ['1234:567:abef::1a2b', 129, false], + ]; + } + + /** + * @dataProvider dataAdd + * + * @param string $ip + * @param int $mask + * @param bool $valid + */ + public function testAdd($ip, $mask, $valid) { + if (!$valid) { + $expected = new JSONResponse([], Http::STATUS_BAD_REQUEST); + } else { + $this->config->method('getAppKeys') + ->with($this->equalTo('bruteForce')) + ->willReturn([ + 'foobar', + 'whitelist_0', + 'whitelist_99', + ]); + + $this->config->expects($this->once()) + ->method('setAppValue') + ->with( + $this->equalTo('bruteForce'), + $this->equalTo('whitelist_100'), + $this->equalTo($ip.'/'.$mask) + ); + + $expected = new JSONResponse([ + 'id' => 100, + 'ip' => $ip, + 'mask' => $mask, + ]); + } + + $this->assertEquals($expected, $this->controller->add($ip, $mask)); + } + + public function testRemove() { + $this->config->expects($this->once()) + ->method('deleteAppValue') + ->with( + $this->equalTo('bruteForce'), + $this->equalTo('whitelist_42') + ); + + $expected = new JSONResponse([]); + $this->assertEquals($expected, $this->controller->remove(42)); + } +} diff --git a/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php b/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php new file mode 100644 index 0000000000000..37d13a86d5627 --- /dev/null +++ b/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php @@ -0,0 +1,33 @@ +<?php + +namespace OCA\BruteForceSettings\Tests\Settings; + +use OCA\BruteForceSettings\Settings\IPWhitelist; +use OCP\AppFramework\Http\TemplateResponse; +use Test\TestCase; + +class IPWhitelistTest extends TestCase { + + /** @var IPWhitelist */ + private $settings; + + public function setUp() { + parent::setUp(); + + $this->settings = new IPWhitelist(); + } + + public function testGetForm() { + $expected = new TemplateResponse('bruteforcesettings', 'ipwhitelist'); + + $this->assertEquals($expected, $this->settings->getForm()); + } + + public function testGetSection() { + $this->assertSame('security', $this->settings->getSection()); + } + + public function testGetPriority() { + $this->assertSame(50, $this->settings->getPriority()); + } +} diff --git a/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js b/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js new file mode 100644 index 0000000000000..21ba32faa3620 --- /dev/null +++ b/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js @@ -0,0 +1,174 @@ +/** + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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/>. + * + */ + +describe('OCA.BruteForceSettings.IPWhiteList tests', function() { + beforeEach(function() { + // init parameters and test table elements + $('#testArea').append( + '<table>'+ + '<tbody id="whitelist-list">' + + '</tbody>' + + '</table>' + + '<input type="text" name="whitelist_ip" id="whitelist_ip" placeholder="1.2.3.4" style="width: 200px;" />/' + + '<input type="number" id="whitelist_mask" name="whitelist_mask" placeholder="24" style="width: 50px;">' + + '<input type="button" id="whitelist_submit" value="Add">' + ); + }); + + it('get intial empty', function() { + OCA.BruteForceSettings.WhiteList.init(); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('GET'); + expect(fakeServer.requests[0].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') + ); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + '[]' + ); + + expect($('#whitelist-list > tr').length).toEqual(0); + }); + it('get intial filled', function() { + OCA.BruteForceSettings.WhiteList.init(); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('GET'); + expect(fakeServer.requests[0].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') + ); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify([ + { + id: 1, + ip: '11.22.0.0', + mask: 16 + }, + { + id: 12, + ip: 'cafe:cafe::', + mask: 80 + } + ]) + ); + + expect($('#whitelist-list > tr').length).toEqual(2); + + var el1 = $($('#whitelist-list > tr').get(0)); + expect(el1.data('id')).toEqual(1); + expect($(el1.find('td > span')[0]).html()).toEqual('11.22.0.0/16'); + + var el2 = $($('#whitelist-list > tr').get(1)); + expect(el2.data('id')).toEqual(12); + expect($(el2.find('td > span')[0]).html()).toEqual('cafe:cafe::/80'); + }); + it('add whitelist', function() { + OCA.BruteForceSettings.WhiteList.init(); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('GET'); + expect(fakeServer.requests[0].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') + ); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + '[]' + ); + + expect($('#whitelist-list > tr').length).toEqual(0); + + $('#whitelist_ip').val('2.4.8.16'); + $('#whitelist_mask').val('8'); + $('#whitelist_submit').click(); + + expect(fakeServer.requests.length).toEqual(2); + expect(fakeServer.requests[1].method).toEqual('POST'); + expect(JSON.parse(fakeServer.requests[1].requestBody)).toEqual({ + ip: '2.4.8.16', + mask: '8' + }); + expect(fakeServer.requests[1].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') + ); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + id: 99, + ip: '2.4.8.16', + mask: 8 + }) + ); + + expect($('#whitelist-list > tr').length).toEqual(1); + + var el1 = $($('#whitelist-list > tr').get(0)); + expect(el1.data('id')).toEqual(99); + expect($(el1.find('td > span')[0]).html()).toEqual('2.4.8.16/8'); + }); + it('delete whitelist', function() { + OCA.BruteForceSettings.WhiteList.init(); + + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].method).toEqual('GET'); + expect(fakeServer.requests[0].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') + ); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify([ + { + id: 1, + ip: '1.2.3.4', + mask: 8 + } + ]) + ); + + expect($('#whitelist-list > tr').length).toEqual(1); + + var el1 = $($('#whitelist-list > tr').get(0)); + expect(el1.data('id')).toEqual(1); + expect($(el1.find('td > span')[0]).html()).toEqual('1.2.3.4/8'); + el1.find('.icon-delete').click(); + + expect(fakeServer.requests.length).toEqual(2); + expect(fakeServer.requests[1].method).toEqual('DELETE'); + expect(fakeServer.requests[1].url).toEqual( + OC.generateUrl('/apps/bruteforcesettings/ipwhitelist/1') + ); + + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + '[]' + ); + + expect($('#whitelist-list > tr').length).toEqual(0); + }); +}); diff --git a/build/integration/features/provisioning-v1.feature b/build/integration/features/provisioning-v1.feature index ad9d901d0515c..856d17e5c106c 100644 --- a/build/integration/features/provisioning-v1.feature +++ b/build/integration/features/provisioning-v1.feature @@ -282,6 +282,7 @@ Feature: provisioning Then the OCS status code should be "100" And the HTTP status code should be "200" And apps returned are + | bruteforcesettings | | comments | | dav | | federatedfilesharing | diff --git a/tests/karma.config.js b/tests/karma.config.js index 91052f62cd2fc..f965738872f3d 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -118,6 +118,19 @@ module.exports = function(config) { 'settings/tests/js/appsSpec.js', 'settings/tests/js/users/deleteHandlerSpec.js' ] + }, + { + name: 'bruteforcesettings', + srcFiles: [ + // need to enforce loading order... + 'apps/bruteforcesettings/js/IPWhitelistModel.js', + 'apps/bruteforcesettings/js/IPWhitelistCollection.js', + 'apps/bruteforcesettings/js/IPWhitelistView.js', + 'apps/bruteforcesettings/js/IPWhitelist.js', + ], + testFiles: [ + 'apps/bruteforcesettings/tests/js/IPWhitelistSpec.js' + ] } ]; } diff --git a/tests/phpunit-autotest.xml b/tests/phpunit-autotest.xml index 9a9c9c957e374..40633aff5aed0 100644 --- a/tests/phpunit-autotest.xml +++ b/tests/phpunit-autotest.xml @@ -21,6 +21,7 @@ <directory suffix=".php">..</directory> <exclude> <directory suffix=".php">../3rdparty</directory> + <directory suffix=".php">../apps/bruteforcesettings/tests</directory> <directory suffix=".php">../apps/dav/tests</directory> <directory suffix=".php">../apps/encryption/tests</directory> <directory suffix=".php">../apps/federatedfilesharing/tests</directory> From dca555b7f34b305062b213f41ca83933b4602c7e Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Mon, 14 Nov 2016 14:02:03 +0100 Subject: [PATCH 2/9] Adds security section to the admin page Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- lib/private/Settings/Manager.php | 1 + tests/lib/Settings/ManagerTest.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index 94df00551d443..2ae1e0682b7e8 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -273,6 +273,7 @@ public function getAdminSections() { $sections = [ 0 => [new Section('server', $this->l->t('Server settings'), 0, $this->url->imagePath('settings', 'admin.svg'))], 5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))], + 10 => [new Section('security', $this->l->t('Security'), 0)], 45 => [new Section('encryption', $this->l->t('Encryption'), 0, $this->url->imagePath('core', 'actions/password.svg'))], 98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))], 99 => [new Section('tips-tricks', $this->l->t('Tips & tricks'), 0, $this->url->imagePath('settings', 'help.svg'))], diff --git a/tests/lib/Settings/ManagerTest.php b/tests/lib/Settings/ManagerTest.php index 2122c8b37502c..e6acafe9b885b 100644 --- a/tests/lib/Settings/ManagerTest.php +++ b/tests/lib/Settings/ManagerTest.php @@ -159,6 +159,7 @@ public function testGetAdminSections() { $this->assertEquals([ 0 => [new Section('server', 'Server settings', 0, '1')], 5 => [new Section('sharing', 'Sharing', 0, '2')], + 10 => [new Section('security', 'Security', 0)], 45 => [new Section('encryption', 'Encryption', 0, '3')], 90 => [\OC::$server->query(\OCA\WorkflowEngine\Settings\Section::class)], 98 => [new Section('additional', 'Additional settings', 0, '4')], @@ -190,6 +191,7 @@ public function testGetAdminSectionsEmptySection() { $this->assertEquals([ 0 => [new Section('server', 'Server settings', 0, '1')], 5 => [new Section('sharing', 'Sharing', 0, '2')], + 10 => [new Section('security', 'Security', 0)], 45 => [new Section('encryption', 'Encryption', 0, '3')], 98 => [new Section('additional', 'Additional settings', 0, '4')], 99 => [new Section('tips-tricks', 'Tips & tricks', 0, '5')], From be674c19a5b78ce87bbd208fea214421d1d811b3 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Mon, 14 Nov 2016 14:05:01 +0100 Subject: [PATCH 3/9] Respect bruteforce settings in the Throttler Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- lib/private/Security/Bruteforce/Throttler.php | 65 ++++++++++++++ .../lib/Security/Bruteforce/ThrottlerTest.php | 90 ++++++++++++++++++- 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php index 765f109fdb3b1..73a27b677b08a 100644 --- a/lib/private/Security/Bruteforce/Throttler.php +++ b/lib/private/Security/Bruteforce/Throttler.php @@ -185,6 +185,67 @@ public function registerAttempt($action, $qb->execute(); } + /** + * Check if the IP is whitelisted + * + * @param string $ip + * @return bool + */ + private function isIPWhitelisted($ip) { + $keys = $this->config->getAppKeys('bruteForce'); + $keys = array_filter($keys, function($key) { + $regex = '/^whitelist_/S'; + return preg_match($regex, $key) === 1; + }); + + if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $type = 4; + } else if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $type = 6; + } else { + return false; + } + + $ip = inet_pton($ip); + + foreach ($keys as $key) { + $cidr = $this->config->getAppValue('bruteForce', $key, null); + + $cx = explode('/', $cidr); + $addr = $cx[0]; + $mask = (int)$cx[1]; + + // Do not compare ipv4 to ipv6 + if (($type === 4 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) || + ($type === 6 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))) { + continue; + } + + $addr = inet_pton($addr); + + $valid = true; + for($i = 0; $i < $mask; $i++) { + $part = ord($addr[(int)($i/8)]); + $orig = ord($ip[(int)($i/8)]); + + $part = $part & (15 << (1 - ($i % 2))); + $orig = $orig & (15 << (1 - ($i % 2))); + + if ($part !== $orig) { + $valid = false; + break; + } + } + + if ($valid === true) { + return true; + } + } + + return false; + + } + /** * Get the throttling delay (in milliseconds) * @@ -193,6 +254,10 @@ public function registerAttempt($action, * @return int */ public function getDelay($ip, $action = '') { + if ($this->isIPWhitelisted($ip)) { + return 0; + } + $cutoffTime = (new \DateTime()) ->sub($this->getCutoff(43200)) ->getTimestamp(); diff --git a/tests/lib/Security/Bruteforce/ThrottlerTest.php b/tests/lib/Security/Bruteforce/ThrottlerTest.php index 604aecd3a65b1..02d5b701679b4 100644 --- a/tests/lib/Security/Bruteforce/ThrottlerTest.php +++ b/tests/lib/Security/Bruteforce/ThrottlerTest.php @@ -40,7 +40,7 @@ class ThrottlerTest extends TestCase { private $dbConnection; /** @var ILogger */ private $logger; - /** @var IConfig */ + /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ private $config; public function setUp() { @@ -120,4 +120,92 @@ public function testSubnet() { $this->invokePrivate($this->throttler, 'getIPv6Subnet', ['2001:0db8:85a3:0000:0000:8a2e:0370:7334', 40]) ); } + + public function dataIsIPWhitelisted() { + return [ + [ + '10.10.10.10', + [ + 'whitelist_0' => '10.10.10.0/24', + ], + true, + ], + [ + '10.10.10.10', + [ + 'whitelist_0' => '192.168.0.0/16', + ], + false, + ], + [ + '10.10.10.10', + [ + 'whitelist_0' => '192.168.0.0/16', + 'whitelist_1' => '10.10.10.0/24', + ], + true, + ], + [ + 'dead:beef:cafe::1', + [ + 'whitelist_0' => '192.168.0.0/16', + 'whitelist_1' => '10.10.10.0/24', + 'whitelist_2' => 'deaf:beef:cafe:1234::/64' + ], + false, + ], + [ + 'dead:beef:cafe::1', + [ + 'whitelist_0' => '192.168.0.0/16', + 'whitelist_1' => '10.10.10.0/24', + 'whitelist_2' => 'deaf:beef::/64' + ], + false, + ], + [ + 'dead:beef:cafe::1', + [ + 'whitelist_0' => '192.168.0.0/16', + 'whitelist_1' => '10.10.10.0/24', + 'whitelist_2' => 'deaf:cafe::/8' + ], + true, + ], + [ + 'invalid', + [], + false, + ], + ]; + } + + /** + * @dataProvider dataIsIPWhitelisted + * + * @param string $ip + * @param string[] $whitelists + * @param bool $isWhiteListed + */ + public function testIsIPWhitelisted($ip, $whitelists, $isWhiteListed) { + $this->config->method('getAppKeys') + ->with($this->equalTo('bruteForce')) + ->willReturn(array_keys($whitelists)); + + $this->config->method('getAppValue') + ->will($this->returnCallback(function($app, $key, $default) use ($whitelists) { + if ($app !== 'bruteForce') { + return $default; + } + if (isset($whitelists[$key])) { + return $whitelists[$key]; + } + return $default; + })); + + $this->assertSame( + $isWhiteListed, + $this->invokePrivate($this->throttler, 'isIPWhitelisted', [$ip]) + ); + } } From c637ff556a99b9677510665d123ddebceae27142 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Fri, 18 Nov 2016 09:27:33 +0100 Subject: [PATCH 4/9] App is always enabled Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- apps/bruteforcesettings/appinfo/info.xml | 3 ++- core/shipped.json | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/bruteforcesettings/appinfo/info.xml b/apps/bruteforcesettings/appinfo/info.xml index 2c3e1256e8505..0407040d8bb35 100644 --- a/apps/bruteforcesettings/appinfo/info.xml +++ b/apps/bruteforcesettings/appinfo/info.xml @@ -9,8 +9,9 @@ <author>Roeland Jago Douma</author> <default_enable/> <version>1.0.0</version> + <category>other</category> <dependencies> - <owncloud min-version="9.2" max-version="9.2" /> + <nextcloud min-version="11" max-version="11" /> </dependencies> <namespace>BruteForceSettings</namespace> diff --git a/core/shipped.json b/core/shipped.json index d325117c67e2f..5bbf79aec8baa 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -2,6 +2,7 @@ "shippedApps": [ "activity", "admin_audit", + "bruteforcesettings", "comments", "dav", "encryption", @@ -41,6 +42,7 @@ "workflowengine" ], "alwaysEnabled": [ + "bruteforcesettings", "files", "dav", "federatedfilesharing", From 4e0479f3a84756c47ce666f682caca511396b525 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Sat, 19 Nov 2016 21:03:39 +0100 Subject: [PATCH 5/9] Update App Manager test Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- tests/lib/App/AppManagerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/lib/App/AppManagerTest.php b/tests/lib/App/AppManagerTest.php index bfb2893955f89..26489cb5b0f8f 100644 --- a/tests/lib/App/AppManagerTest.php +++ b/tests/lib/App/AppManagerTest.php @@ -329,6 +329,7 @@ public function testGetInstalledApps() { $this->appConfig->setValue('test2', 'enabled', 'no'); $this->appConfig->setValue('test3', 'enabled', '["foo"]'); $apps = [ + 'bruteforcesettings', 'dav', 'federatedfilesharing', 'files', @@ -354,6 +355,7 @@ public function testGetAppsForUser() { $this->appConfig->setValue('test3', 'enabled', '["foo"]'); $this->appConfig->setValue('test4', 'enabled', '["asd"]'); $enabled = [ + 'bruteforcesettings', 'dav', 'federatedfilesharing', 'files', From 86022f87107160ac863229fb30edb251deb4ba0c Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Sun, 2 Apr 2017 21:16:22 +0200 Subject: [PATCH 6/9] Fix app Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- apps/bruteforcesettings/appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bruteforcesettings/appinfo/info.xml b/apps/bruteforcesettings/appinfo/info.xml index 0407040d8bb35..f90b9d9fca8b3 100644 --- a/apps/bruteforcesettings/appinfo/info.xml +++ b/apps/bruteforcesettings/appinfo/info.xml @@ -11,7 +11,7 @@ <version>1.0.0</version> <category>other</category> <dependencies> - <nextcloud min-version="11" max-version="11" /> + <nextcloud min-version="12" max-version="12" /> </dependencies> <namespace>BruteForceSettings</namespace> From ed00bab80b95581357666bd0d9fcf103f95b77f0 Mon Sep 17 00:00:00 2001 From: Morris Jobke <hey@morrisjobke.de> Date: Mon, 13 Mar 2017 19:44:10 -0600 Subject: [PATCH 7/9] Fixed layout of bruteforcesettings Signed-off-by: Morris Jobke <hey@morrisjobke.de> --- apps/bruteforcesettings/css/settings.css | 17 +++++++++++++++++ apps/bruteforcesettings/js/IPWhitelistView.js | 2 +- .../templates/ipwhitelist.php | 7 ++++--- lib/private/Settings/Manager.php | 2 +- tests/lib/Settings/ManagerTest.php | 8 ++++---- 5 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 apps/bruteforcesettings/css/settings.css diff --git a/apps/bruteforcesettings/css/settings.css b/apps/bruteforcesettings/css/settings.css new file mode 100644 index 0000000000000..1d2837b00ee9d --- /dev/null +++ b/apps/bruteforcesettings/css/settings.css @@ -0,0 +1,17 @@ + +#whitelist-list { + min-width: 262px; +} + +#whitelist-list td span { + padding: 10px 15px; + display: inline-block; +} + +#whitelist-list .action-column { + width: 46px; +} + +#whitelist-list .action-column a { + display: inline-block; +} \ No newline at end of file diff --git a/apps/bruteforcesettings/js/IPWhitelistView.js b/apps/bruteforcesettings/js/IPWhitelistView.js index da711ae12252e..7341c7d079715 100644 --- a/apps/bruteforcesettings/js/IPWhitelistView.js +++ b/apps/bruteforcesettings/js/IPWhitelistView.js @@ -27,7 +27,7 @@ var TEMPLATE_WHITELIST = '<tr data-id="{{id}}">' + '<td><span>{{ip}}/{{mask}}</span></td>' - + '<td><a class="icon-delete has-tooltip" title="' + t('bruteforcesettings', 'Delete') + '">BAD CSS</a></td>' + + '<td class="action-column"><span><a class="icon-delete has-tooltip" title="' + t('bruteforcesettings', 'Delete') + '"></a></span></td>' + '</tr>'; OCA.BruteForceSettings.WhitelistView = OC.Backbone.View.extend({ diff --git a/apps/bruteforcesettings/templates/ipwhitelist.php b/apps/bruteforcesettings/templates/ipwhitelist.php index 69354956168d4..a4b0292e94298 100644 --- a/apps/bruteforcesettings/templates/ipwhitelist.php +++ b/apps/bruteforcesettings/templates/ipwhitelist.php @@ -30,16 +30,17 @@ 'IPWhitelistCollection', 'IPWhitelistView', ]); +style('bruteforcesettings', [ + 'settings' +]) /** @var \OCP\IL10N $l */ ?> <form id="IPWhiteList" class="section"> <h2><?php p($l->t('Brute force ip whitelist')); ?></h2> - <table> - <tbody id="whitelist-list"> + <table id="whitelist-list"> - </tbody> </table> <input type="text" name="whitelist_ip" id="whitelist_ip" placeholder="1.2.3.4" style="width: 200px;" />/ diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index 2ae1e0682b7e8..080b697b238e1 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -273,7 +273,7 @@ public function getAdminSections() { $sections = [ 0 => [new Section('server', $this->l->t('Server settings'), 0, $this->url->imagePath('settings', 'admin.svg'))], 5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))], - 10 => [new Section('security', $this->l->t('Security'), 0)], + 10 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('core', 'actions/password.svg'))], 45 => [new Section('encryption', $this->l->t('Encryption'), 0, $this->url->imagePath('core', 'actions/password.svg'))], 98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))], 99 => [new Section('tips-tricks', $this->l->t('Tips & tricks'), 0, $this->url->imagePath('settings', 'help.svg'))], diff --git a/tests/lib/Settings/ManagerTest.php b/tests/lib/Settings/ManagerTest.php index e6acafe9b885b..497a0df9f4e97 100644 --- a/tests/lib/Settings/ManagerTest.php +++ b/tests/lib/Settings/ManagerTest.php @@ -146,7 +146,7 @@ public function testGetAdminSections() { ['class' => \OCA\WorkflowEngine\Settings\Section::class, 'priority' => 90] ])); - $this->url->expects($this->exactly(5)) + $this->url->expects($this->exactly(6)) ->method('imagePath') ->willReturnMap([ ['settings', 'admin.svg', '1'], @@ -159,7 +159,7 @@ public function testGetAdminSections() { $this->assertEquals([ 0 => [new Section('server', 'Server settings', 0, '1')], 5 => [new Section('sharing', 'Sharing', 0, '2')], - 10 => [new Section('security', 'Security', 0)], + 10 => [new Section('security', 'Security', 0, '3')], 45 => [new Section('encryption', 'Encryption', 0, '3')], 90 => [\OC::$server->query(\OCA\WorkflowEngine\Settings\Section::class)], 98 => [new Section('additional', 'Additional settings', 0, '4')], @@ -178,7 +178,7 @@ public function testGetAdminSectionsEmptySection() { ->will($this->returnValue([ ])); - $this->url->expects($this->exactly(5)) + $this->url->expects($this->exactly(6)) ->method('imagePath') ->willReturnMap([ ['settings', 'admin.svg', '1'], @@ -191,7 +191,7 @@ public function testGetAdminSectionsEmptySection() { $this->assertEquals([ 0 => [new Section('server', 'Server settings', 0, '1')], 5 => [new Section('sharing', 'Sharing', 0, '2')], - 10 => [new Section('security', 'Security', 0)], + 10 => [new Section('security', 'Security', 0, '3')], 45 => [new Section('encryption', 'Encryption', 0, '3')], 98 => [new Section('additional', 'Additional settings', 0, '4')], 99 => [new Section('tips-tricks', 'Tips & tricks', 0, '5')], From e09c386f700ba7dd8d7366f924fbbcb4bf39b366 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Sun, 2 Apr 2017 21:26:02 +0200 Subject: [PATCH 8/9] Move app to own repo https://github.com/nextcloud/bruteforcesettings Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- apps/bruteforcesettings/appinfo/info.xml | 22 --- apps/bruteforcesettings/appinfo/routes.php | 30 --- apps/bruteforcesettings/css/settings.css | 17 -- apps/bruteforcesettings/js/IPWhitelist.js | 44 ----- .../js/IPWhitelistCollection.js | 34 ---- .../bruteforcesettings/js/IPWhitelistModel.js | 29 --- apps/bruteforcesettings/js/IPWhitelistView.js | 128 ------------- .../lib/Controller/IPWhitelistController.php | 123 ------------- .../lib/Settings/IPWhitelist.php | 42 ----- .../templates/ipwhitelist.php | 49 ----- .../Controller/IPWhitelistControllerTest.php | 151 --------------- .../tests/Settings/IPWhitelistTest.php | 33 ---- .../tests/js/IPWhitelistSpec.js | 174 ------------------ 13 files changed, 876 deletions(-) delete mode 100644 apps/bruteforcesettings/appinfo/info.xml delete mode 100644 apps/bruteforcesettings/appinfo/routes.php delete mode 100644 apps/bruteforcesettings/css/settings.css delete mode 100644 apps/bruteforcesettings/js/IPWhitelist.js delete mode 100644 apps/bruteforcesettings/js/IPWhitelistCollection.js delete mode 100644 apps/bruteforcesettings/js/IPWhitelistModel.js delete mode 100644 apps/bruteforcesettings/js/IPWhitelistView.js delete mode 100644 apps/bruteforcesettings/lib/Controller/IPWhitelistController.php delete mode 100644 apps/bruteforcesettings/lib/Settings/IPWhitelist.php delete mode 100644 apps/bruteforcesettings/templates/ipwhitelist.php delete mode 100644 apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php delete mode 100644 apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php delete mode 100644 apps/bruteforcesettings/tests/js/IPWhitelistSpec.js diff --git a/apps/bruteforcesettings/appinfo/info.xml b/apps/bruteforcesettings/appinfo/info.xml deleted file mode 100644 index f90b9d9fca8b3..0000000000000 --- a/apps/bruteforcesettings/appinfo/info.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0"?> -<info> - <id>bruteforcesettings</id> - <name>Brute force settings</name> - <description> - This applications allows admins to configure the brute force settings. - </description> - <licence>AGPL</licence> - <author>Roeland Jago Douma</author> - <default_enable/> - <version>1.0.0</version> - <category>other</category> - <dependencies> - <nextcloud min-version="12" max-version="12" /> - </dependencies> - - <namespace>BruteForceSettings</namespace> - - <settings> - <admin>OCA\BruteForceSettings\Settings\IPWhitelist</admin> - </settings> -</info> diff --git a/apps/bruteforcesettings/appinfo/routes.php b/apps/bruteforcesettings/appinfo/routes.php deleted file mode 100644 index 28ab6e9cee43f..0000000000000 --- a/apps/bruteforcesettings/appinfo/routes.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -return [ - 'routes' => [ - [ 'name' => 'IPWhitelist#getAll', 'url' => '/ipwhitelist', 'verb' => 'GET' ], - [ 'name' => 'IPWhitelist#add', 'url' => '/ipwhitelist', 'verb' => 'POST' ], - [ 'name' => 'IPWhitelist#remove', 'url' => '/ipwhitelist/{id}', 'verb' => 'DELETE' ], - ] -]; diff --git a/apps/bruteforcesettings/css/settings.css b/apps/bruteforcesettings/css/settings.css deleted file mode 100644 index 1d2837b00ee9d..0000000000000 --- a/apps/bruteforcesettings/css/settings.css +++ /dev/null @@ -1,17 +0,0 @@ - -#whitelist-list { - min-width: 262px; -} - -#whitelist-list td span { - padding: 10px 15px; - display: inline-block; -} - -#whitelist-list .action-column { - width: 46px; -} - -#whitelist-list .action-column a { - display: inline-block; -} \ No newline at end of file diff --git a/apps/bruteforcesettings/js/IPWhitelist.js b/apps/bruteforcesettings/js/IPWhitelist.js deleted file mode 100644 index 163d5d2852a62..0000000000000 --- a/apps/bruteforcesettings/js/IPWhitelist.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -(function() { - - OCA.BruteForceSettings = OCA.BruteForceSettings || {}; - - OCA.BruteForceSettings.WhiteList = { - - collection: null, - view: null, - - init: function () { - this.collection = new OCA.BruteForceSettings.WhitelistCollection(); - this.view = new OCA.BruteForceSettings.WhitelistView({ - collection: this.collection - }); - this.view.reload(); - } - }; -})(); - -$(document).ready(function() { - OCA.BruteForceSettings.WhiteList.init(); -}); diff --git a/apps/bruteforcesettings/js/IPWhitelistCollection.js b/apps/bruteforcesettings/js/IPWhitelistCollection.js deleted file mode 100644 index bf5b34d1ad0dc..0000000000000 --- a/apps/bruteforcesettings/js/IPWhitelistCollection.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -(function() { - - OCA.BruteForceSettings = OCA.BruteForceSettings || {}; - - OCA.BruteForceSettings.WhitelistCollection = OC.Backbone.Collection.extend({ - model: OCA.BruteForceSettings.WhitelistModel, - - url: function() { - return OC.generateUrl('/apps/bruteforcesettings/ipwhitelist'); - } - }); -})(); diff --git a/apps/bruteforcesettings/js/IPWhitelistModel.js b/apps/bruteforcesettings/js/IPWhitelistModel.js deleted file mode 100644 index 5c309f5af74ba..0000000000000 --- a/apps/bruteforcesettings/js/IPWhitelistModel.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -(function() { - - OCA.BruteForceSettings = OCA.BruteForceSettings || {}; - - OCA.BruteForceSettings.WhitelistModel = OC.Backbone.Model.extend({ - }); -})(); diff --git a/apps/bruteforcesettings/js/IPWhitelistView.js b/apps/bruteforcesettings/js/IPWhitelistView.js deleted file mode 100644 index 7341c7d079715..0000000000000 --- a/apps/bruteforcesettings/js/IPWhitelistView.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -(function () { - - OCA.BruteForceSettings = OCA.BruteForceSettings || {}; - - var TEMPLATE_WHITELIST = - '<tr data-id="{{id}}">' - + '<td><span>{{ip}}/{{mask}}</span></td>' - + '<td class="action-column"><span><a class="icon-delete has-tooltip" title="' + t('bruteforcesettings', 'Delete') + '"></a></span></td>' - + '</tr>'; - - OCA.BruteForceSettings.WhitelistView = OC.Backbone.View.extend({ - collection: null, - - ipInput: undefined, - maskInput: undefined, - submit: undefined, - - list: undefined, - listHeader: undefined, - - initialize: function(options) { - this.collection = options.collection; - - this.ipInput = $('#whitelist_ip'); - this.maskInput = $('#whitelist_mask'); - this.submit = $('#whitelist_submit'); - this.submit.click(_.bind(this._addWhitelist, this)); - - this.list = $('#whitelist-list'); - this.listHeader = $('#whitelist-list-header'); - - this.list.on('click', 'a.icon-delete', _.bind(this._onDeleteRetention, this)); - this.listenTo(this.collection, 'sync', this.render); - }, - - - - reload: function() { - var _this = this; - var loadingWhitelists = this.collection.fetch(); - - $.when(loadingWhitelists).done(function () { - _this.render(); - }); - $.when(loadingWhitelists).fail(function () { - OC.Notification.showTemporary(t('bruteforcesettings', 'Error while whitelists.')); - }); - }, - - template: function (data) { - if (_.isUndefined(this._template)) { - this._template = Handlebars.compile(TEMPLATE_WHITELIST); - } - - return this._template(data); - }, - - render: function () { - var _this = this; - this.list.html(''); - - this.collection.forEach(function (model) { - var data = { - id: model.attributes.id, - ip: model.attributes.ip, - mask: model.attributes.mask - }; - var html = _this.template(data); - var $html = $(html); - _this.list.append($html); - }); - }, - - _onDeleteRetention: function(event) { - var $target = $(event.target); - var $row = $target.closest('tr'); - var id = $row.data('id'); - - var whitelist = this.collection.get(id); - - if (_.isUndefined(whitelist)) { - // Ignore event - return; - } - - var destroyingRetention = whitelist.destroy(); - - $row.find('.icon-delete').tooltip('hide'); - - var _this = this; - $.when(destroyingRetention).fail(function () { - OC.Notification.showTemporary(t('bruteforcesettings', 'Error while deleting a whitelist')); - }); - $.when(destroyingRetention).always(function () { - _this.render(); - }); - }, - - _addWhitelist: function() { - this.collection.create({ - ip: this.ipInput.val(), - mask: this.maskInput.val() - }); - } - }); -})(); diff --git a/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php b/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php deleted file mode 100644 index 9b5183f7495fb..0000000000000 --- a/apps/bruteforcesettings/lib/Controller/IPWhitelistController.php +++ /dev/null @@ -1,123 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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\BruteForceSettings\Controller; - -use OCP\AppFramework\Controller; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\JSONResponse; -use OCP\IConfig; -use OCP\IRequest; - -class IPWhitelistController extends Controller { - - /** @var IConfig */ - private $config; - - /** - * IPWhitelistController constructor. - * - * @param string $appName - * @param IRequest $request - * @param IConfig $config - */ - public function __construct($appName, - IRequest $request, - IConfig $config) { - parent::__construct($appName, $request); - - $this->config = $config; - } - - /** - * @return JSONResponse - */ - public function getAll() { - $keys = $this->config->getAppKeys('bruteForce'); - $keys = array_filter($keys, function($key) { - $regex = '/^whitelist_/S'; - return preg_match($regex, $key) === 1; - }); - - $result = []; - - foreach ($keys as $key) { - $value = $this->config->getAppValue('bruteForce', $key); - $values = explode('/', $value); - - $result[] = [ - 'id' => (int)substr($key, 10), - 'ip' => $values[0], - 'mask' => $values[1], - ]; - } - - return new JSONResponse($result); - } - - /** - * @param string $ip - * @param int $mask - * @return JSONResponse - */ - public function add($ip, $mask) { - if (!filter_var($ip, FILTER_VALIDATE_IP) || - (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && ($mask < 0 || $mask > 32)) || - (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && ($mask < 0 || $mask > 128))) { - return new JSONResponse([], Http::STATUS_BAD_REQUEST); - } - - $keys = $this->config->getAppKeys('bruteForce'); - $keys = array_filter($keys, function($key) { - $regex = '/^whitelist_/S'; - return preg_match($regex, $key) === 1; - }); - - $id = 0; - foreach ($keys as $key) { - $tmp = (int)substr($key, 10); - if ($tmp > $id) { - $id = $tmp; - } - } - $id++; - - $value = $ip . '/' . $mask; - $this->config->setAppValue('bruteForce', 'whitelist_'.$id, $value); - return new JSONResponse([ - 'id' => $id, - 'ip' => $ip, - 'mask' => $mask, - ]); - } - - /** - * @param int $id - * @return JSONResponse - */ - public function remove($id) { - $this->config->deleteAppValue('bruteForce', 'whitelist_'.$id); - - return new JSONResponse([]); - } -} diff --git a/apps/bruteforcesettings/lib/Settings/IPWhitelist.php b/apps/bruteforcesettings/lib/Settings/IPWhitelist.php deleted file mode 100644 index 7e4aab2f22f4f..0000000000000 --- a/apps/bruteforcesettings/lib/Settings/IPWhitelist.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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\BruteForceSettings\Settings; - -use OCP\AppFramework\Http\TemplateResponse; -use OCP\Settings\ISettings; - -class IPWhitelist implements ISettings { - - public function getForm() { - return new TemplateResponse('bruteforcesettings', 'ipwhitelist'); - } - - public function getSection() { - return 'security'; - } - - public function getPriority() { - return 50; - } -} diff --git a/apps/bruteforcesettings/templates/ipwhitelist.php b/apps/bruteforcesettings/templates/ipwhitelist.php deleted file mode 100644 index a4b0292e94298..0000000000000 --- a/apps/bruteforcesettings/templates/ipwhitelist.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -script('core', [ - 'oc-backbone-webdav', -]); -script('bruteforcesettings', [ - 'IPWhitelist', - 'IPWhitelistModel', - 'IPWhitelistCollection', - 'IPWhitelistView', -]); -style('bruteforcesettings', [ - 'settings' -]) - -/** @var \OCP\IL10N $l */ -?> -<form id="IPWhiteList" class="section"> - <h2><?php p($l->t('Brute force ip whitelist')); ?></h2> - - <table id="whitelist-list"> - - </table> - - <input type="text" name="whitelist_ip" id="whitelist_ip" placeholder="1.2.3.4" style="width: 200px;" />/ - <input type="number" id="whitelist_mask" name="whitelist_mask" placeholder="24" style="width: 50px;"> - <input type="button" id="whitelist_submit" value="<?php p($l->t('Add')); ?>"> -</form> diff --git a/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php b/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php deleted file mode 100644 index c45fc6a9417b2..0000000000000 --- a/apps/bruteforcesettings/tests/Controller/IPWhitelistControllerTest.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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\BruteForceSettings\Tests\Controller; - -use OCA\BruteForceSettings\Controller\IPWhitelistController; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\JSONResponse; -use OCP\IConfig; -use OCP\IRequest; -use Test\TestCase; - -class IPWhitelistControllerTest extends TestCase { - - /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ - private $config; - /** @var IPWhitelistController */ - private $controller; - - public function setUp() { - parent::setUp(); - - $this->config = $this->createMock(IConfig::class); - $this->controller = new IPWhitelistController( - 'bruteforce', - $this->createMock(IRequest::class), - $this->config - ); - } - - public function testGetAll() { - $this->config->method('getAppKeys') - ->with($this->equalTo('bruteForce')) - ->willReturn([ - 'foobar', - 'whitelist_0', - 'whitelist_99', - ]); - - $this->config->method('getAppValue') - ->will($this->returnCallback(function($app, $key) { - if ($app !== 'bruteForce') { - $this->fail(); - } - if ($key === 'whitelist_0') { - return '192.168.2.0/24'; - } else if ($key === 'whitelist_99') { - return 'dead:beef:cafe::/92'; - } - $this->fail(); - })); - - $expected = new JSONResponse([ - [ - 'id' => 0, - 'ip' => '192.168.2.0', - 'mask' => '24', - ], - [ - 'id' => 99, - 'ip' => 'dead:beef:cafe::', - 'mask' => '92', - ] - ]); - - $this->assertEquals($expected, $this->controller->getAll()); - } - - public function dataAdd() { - return [ - ['8.500.2.3', 24, false], - ['1.2.3.4', 24, true], - ['1.2.3.4', -1, false], - ['1.2.3.4', 33, false], - - ['dead:nope::8', 24, false], - ['1234:567:abef::1a2b', 24, true], - ['1234:567:abef::1a2b', -1, false], - ['1234:567:abef::1a2b', 129, false], - ]; - } - - /** - * @dataProvider dataAdd - * - * @param string $ip - * @param int $mask - * @param bool $valid - */ - public function testAdd($ip, $mask, $valid) { - if (!$valid) { - $expected = new JSONResponse([], Http::STATUS_BAD_REQUEST); - } else { - $this->config->method('getAppKeys') - ->with($this->equalTo('bruteForce')) - ->willReturn([ - 'foobar', - 'whitelist_0', - 'whitelist_99', - ]); - - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('bruteForce'), - $this->equalTo('whitelist_100'), - $this->equalTo($ip.'/'.$mask) - ); - - $expected = new JSONResponse([ - 'id' => 100, - 'ip' => $ip, - 'mask' => $mask, - ]); - } - - $this->assertEquals($expected, $this->controller->add($ip, $mask)); - } - - public function testRemove() { - $this->config->expects($this->once()) - ->method('deleteAppValue') - ->with( - $this->equalTo('bruteForce'), - $this->equalTo('whitelist_42') - ); - - $expected = new JSONResponse([]); - $this->assertEquals($expected, $this->controller->remove(42)); - } -} diff --git a/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php b/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php deleted file mode 100644 index 37d13a86d5627..0000000000000 --- a/apps/bruteforcesettings/tests/Settings/IPWhitelistTest.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -namespace OCA\BruteForceSettings\Tests\Settings; - -use OCA\BruteForceSettings\Settings\IPWhitelist; -use OCP\AppFramework\Http\TemplateResponse; -use Test\TestCase; - -class IPWhitelistTest extends TestCase { - - /** @var IPWhitelist */ - private $settings; - - public function setUp() { - parent::setUp(); - - $this->settings = new IPWhitelist(); - } - - public function testGetForm() { - $expected = new TemplateResponse('bruteforcesettings', 'ipwhitelist'); - - $this->assertEquals($expected, $this->settings->getForm()); - } - - public function testGetSection() { - $this->assertSame('security', $this->settings->getSection()); - } - - public function testGetPriority() { - $this->assertSame(50, $this->settings->getPriority()); - } -} diff --git a/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js b/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js deleted file mode 100644 index 21ba32faa3620..0000000000000 --- a/apps/bruteforcesettings/tests/js/IPWhitelistSpec.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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/>. - * - */ - -describe('OCA.BruteForceSettings.IPWhiteList tests', function() { - beforeEach(function() { - // init parameters and test table elements - $('#testArea').append( - '<table>'+ - '<tbody id="whitelist-list">' + - '</tbody>' + - '</table>' + - '<input type="text" name="whitelist_ip" id="whitelist_ip" placeholder="1.2.3.4" style="width: 200px;" />/' + - '<input type="number" id="whitelist_mask" name="whitelist_mask" placeholder="24" style="width: 50px;">' + - '<input type="button" id="whitelist_submit" value="Add">' - ); - }); - - it('get intial empty', function() { - OCA.BruteForceSettings.WhiteList.init(); - - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') - ); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - '[]' - ); - - expect($('#whitelist-list > tr').length).toEqual(0); - }); - it('get intial filled', function() { - OCA.BruteForceSettings.WhiteList.init(); - - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') - ); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify([ - { - id: 1, - ip: '11.22.0.0', - mask: 16 - }, - { - id: 12, - ip: 'cafe:cafe::', - mask: 80 - } - ]) - ); - - expect($('#whitelist-list > tr').length).toEqual(2); - - var el1 = $($('#whitelist-list > tr').get(0)); - expect(el1.data('id')).toEqual(1); - expect($(el1.find('td > span')[0]).html()).toEqual('11.22.0.0/16'); - - var el2 = $($('#whitelist-list > tr').get(1)); - expect(el2.data('id')).toEqual(12); - expect($(el2.find('td > span')[0]).html()).toEqual('cafe:cafe::/80'); - }); - it('add whitelist', function() { - OCA.BruteForceSettings.WhiteList.init(); - - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') - ); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - '[]' - ); - - expect($('#whitelist-list > tr').length).toEqual(0); - - $('#whitelist_ip').val('2.4.8.16'); - $('#whitelist_mask').val('8'); - $('#whitelist_submit').click(); - - expect(fakeServer.requests.length).toEqual(2); - expect(fakeServer.requests[1].method).toEqual('POST'); - expect(JSON.parse(fakeServer.requests[1].requestBody)).toEqual({ - ip: '2.4.8.16', - mask: '8' - }); - expect(fakeServer.requests[1].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') - ); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - id: 99, - ip: '2.4.8.16', - mask: 8 - }) - ); - - expect($('#whitelist-list > tr').length).toEqual(1); - - var el1 = $($('#whitelist-list > tr').get(0)); - expect(el1.data('id')).toEqual(99); - expect($(el1.find('td > span')[0]).html()).toEqual('2.4.8.16/8'); - }); - it('delete whitelist', function() { - OCA.BruteForceSettings.WhiteList.init(); - - expect(fakeServer.requests.length).toEqual(1); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist') - ); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify([ - { - id: 1, - ip: '1.2.3.4', - mask: 8 - } - ]) - ); - - expect($('#whitelist-list > tr').length).toEqual(1); - - var el1 = $($('#whitelist-list > tr').get(0)); - expect(el1.data('id')).toEqual(1); - expect($(el1.find('td > span')[0]).html()).toEqual('1.2.3.4/8'); - el1.find('.icon-delete').click(); - - expect(fakeServer.requests.length).toEqual(2); - expect(fakeServer.requests[1].method).toEqual('DELETE'); - expect(fakeServer.requests[1].url).toEqual( - OC.generateUrl('/apps/bruteforcesettings/ipwhitelist/1') - ); - - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - '[]' - ); - - expect($('#whitelist-list > tr').length).toEqual(0); - }); -}); From aee2d6318fef503528c94947596bafeb43594ed3 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma <roeland@famdouma.nl> Date: Sun, 2 Apr 2017 21:41:14 +0200 Subject: [PATCH 9/9] Fix tests Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl> --- .drone.yml | 1 - .gitignore | 1 - build/integration/features/provisioning-v1.feature | 1 - core/shipped.json | 1 - tests/karma.config.js | 13 ------------- tests/lib/App/AppManagerTest.php | 2 -- tests/phpunit-autotest.xml | 1 - 7 files changed, 20 deletions(-) diff --git a/.drone.yml b/.drone.yml index 8d3e3551a6e86..dd4ec40420971 100644 --- a/.drone.yml +++ b/.drone.yml @@ -30,7 +30,6 @@ pipeline: image: nextcloudci/php7.0:php7.0-7 commands: - ./occ app:check-code admin_audit - - ./occ app:check-code bruteforcesettings - ./occ app:check-code comments - ./occ app:check-code federation - ./occ app:check-code sharebymail diff --git a/.gitignore b/.gitignore index 1e0f53a3c076f..6a8e6723376a7 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,6 @@ /apps/files_external/3rdparty/irodsphp/prods/tutorials /apps/files_external/3rdparty/irodsphp/prods/test* /apps/files_external/tests/config.*.php -!/apps/bruteforcesettings # ignore themes except the example and the README diff --git a/build/integration/features/provisioning-v1.feature b/build/integration/features/provisioning-v1.feature index 856d17e5c106c..ad9d901d0515c 100644 --- a/build/integration/features/provisioning-v1.feature +++ b/build/integration/features/provisioning-v1.feature @@ -282,7 +282,6 @@ Feature: provisioning Then the OCS status code should be "100" And the HTTP status code should be "200" And apps returned are - | bruteforcesettings | | comments | | dav | | federatedfilesharing | diff --git a/core/shipped.json b/core/shipped.json index 5bbf79aec8baa..679e1c7f706ad 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -42,7 +42,6 @@ "workflowengine" ], "alwaysEnabled": [ - "bruteforcesettings", "files", "dav", "federatedfilesharing", diff --git a/tests/karma.config.js b/tests/karma.config.js index f965738872f3d..91052f62cd2fc 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -118,19 +118,6 @@ module.exports = function(config) { 'settings/tests/js/appsSpec.js', 'settings/tests/js/users/deleteHandlerSpec.js' ] - }, - { - name: 'bruteforcesettings', - srcFiles: [ - // need to enforce loading order... - 'apps/bruteforcesettings/js/IPWhitelistModel.js', - 'apps/bruteforcesettings/js/IPWhitelistCollection.js', - 'apps/bruteforcesettings/js/IPWhitelistView.js', - 'apps/bruteforcesettings/js/IPWhitelist.js', - ], - testFiles: [ - 'apps/bruteforcesettings/tests/js/IPWhitelistSpec.js' - ] } ]; } diff --git a/tests/lib/App/AppManagerTest.php b/tests/lib/App/AppManagerTest.php index 26489cb5b0f8f..bfb2893955f89 100644 --- a/tests/lib/App/AppManagerTest.php +++ b/tests/lib/App/AppManagerTest.php @@ -329,7 +329,6 @@ public function testGetInstalledApps() { $this->appConfig->setValue('test2', 'enabled', 'no'); $this->appConfig->setValue('test3', 'enabled', '["foo"]'); $apps = [ - 'bruteforcesettings', 'dav', 'federatedfilesharing', 'files', @@ -355,7 +354,6 @@ public function testGetAppsForUser() { $this->appConfig->setValue('test3', 'enabled', '["foo"]'); $this->appConfig->setValue('test4', 'enabled', '["asd"]'); $enabled = [ - 'bruteforcesettings', 'dav', 'federatedfilesharing', 'files', diff --git a/tests/phpunit-autotest.xml b/tests/phpunit-autotest.xml index 40633aff5aed0..9a9c9c957e374 100644 --- a/tests/phpunit-autotest.xml +++ b/tests/phpunit-autotest.xml @@ -21,7 +21,6 @@ <directory suffix=".php">..</directory> <exclude> <directory suffix=".php">../3rdparty</directory> - <directory suffix=".php">../apps/bruteforcesettings/tests</directory> <directory suffix=".php">../apps/dav/tests</directory> <directory suffix=".php">../apps/encryption/tests</directory> <directory suffix=".php">../apps/federatedfilesharing/tests</directory>