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>
This commit is contained in:
parent
f31dafe4a8
commit
6a40dce138
|
@ -30,6 +30,7 @@ pipeline:
|
||||||
image: nextcloudci/php7.0:php7.0-7
|
image: nextcloudci/php7.0:php7.0-7
|
||||||
commands:
|
commands:
|
||||||
- ./occ app:check-code admin_audit
|
- ./occ app:check-code admin_audit
|
||||||
|
- ./occ app:check-code bruteforcesettings
|
||||||
- ./occ app:check-code comments
|
- ./occ app:check-code comments
|
||||||
- ./occ app:check-code federation
|
- ./occ app:check-code federation
|
||||||
- ./occ app:check-code sharebymail
|
- ./occ app:check-code sharebymail
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
/apps/files_external/3rdparty/irodsphp/prods/tutorials
|
/apps/files_external/3rdparty/irodsphp/prods/tutorials
|
||||||
/apps/files_external/3rdparty/irodsphp/prods/test*
|
/apps/files_external/3rdparty/irodsphp/prods/test*
|
||||||
/apps/files_external/tests/config.*.php
|
/apps/files_external/tests/config.*.php
|
||||||
|
!/apps/bruteforcesettings
|
||||||
|
|
||||||
|
|
||||||
# ignore themes except the example and the README
|
# ignore themes except the example and the README
|
||||||
|
|
|
@ -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>
|
|
@ -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' ],
|
||||||
|
]
|
||||||
|
];
|
|
@ -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();
|
||||||
|
});
|
|
@ -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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
|
@ -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({
|
||||||
|
});
|
||||||
|
})();
|
|
@ -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()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
|
@ -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([]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
|
@ -282,6 +282,7 @@ Feature: provisioning
|
||||||
Then the OCS status code should be "100"
|
Then the OCS status code should be "100"
|
||||||
And the HTTP status code should be "200"
|
And the HTTP status code should be "200"
|
||||||
And apps returned are
|
And apps returned are
|
||||||
|
| bruteforcesettings |
|
||||||
| comments |
|
| comments |
|
||||||
| dav |
|
| dav |
|
||||||
| federatedfilesharing |
|
| federatedfilesharing |
|
||||||
|
|
|
@ -118,6 +118,19 @@ module.exports = function(config) {
|
||||||
'settings/tests/js/appsSpec.js',
|
'settings/tests/js/appsSpec.js',
|
||||||
'settings/tests/js/users/deleteHandlerSpec.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'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<directory suffix=".php">..</directory>
|
<directory suffix=".php">..</directory>
|
||||||
<exclude>
|
<exclude>
|
||||||
<directory suffix=".php">../3rdparty</directory>
|
<directory suffix=".php">../3rdparty</directory>
|
||||||
|
<directory suffix=".php">../apps/bruteforcesettings/tests</directory>
|
||||||
<directory suffix=".php">../apps/dav/tests</directory>
|
<directory suffix=".php">../apps/dav/tests</directory>
|
||||||
<directory suffix=".php">../apps/encryption/tests</directory>
|
<directory suffix=".php">../apps/encryption/tests</directory>
|
||||||
<directory suffix=".php">../apps/federatedfilesharing/tests</directory>
|
<directory suffix=".php">../apps/federatedfilesharing/tests</directory>
|
||||||
|
|
Loading…
Reference in New Issue