Create a Nextcloud app to send a user to an external URL to change their password
This commit is contained in:
parent
66d1df4bc5
commit
d82e7c8197
13 changed files with 373 additions and 47 deletions
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## [0.1.0] - 2022-05-16
|
||||
### Added
|
||||
- Create a Nextcloud app to send users to an external URL to change their password
|
|
@ -5,7 +5,7 @@
|
|||
<name>External Password</name>
|
||||
<summary>An app for Nextcloud to allow an administrator to direct a user to an external site for changing their password.</summary>
|
||||
<description><![CDATA[An app for Nextcloud to allow an administrator to direct a user to an external site for changing their password. This is useful in conjunction with an app like external_users.]]></description>
|
||||
<version>0.1.0</version>
|
||||
<version>0.1.1</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="raoul@snyman.info" >Raoul Snyman</author>
|
||||
<namespace>ExternalPassword</namespace>
|
||||
|
@ -15,12 +15,10 @@
|
|||
<repository>https://git.snyman.info/raoul/externalpassword</repository>
|
||||
<bugs>https://git.snyman.info/raoul/externalpassword/issues</bugs>
|
||||
<dependencies>
|
||||
<nextcloud min-version="22"/>
|
||||
<nextcloud min-version="22" max-version="25" />
|
||||
</dependencies>
|
||||
<settings>
|
||||
<admin>OCA\ExternalPassword\Settings\Admin</admin>
|
||||
<admin-section>OCA\ExternalPassword\Settings\AdminSection</admin-section>
|
||||
<personal>OCA\ExternalPassword\Settings\Personal</personal>
|
||||
<personal-section>OCA\ExternalPassword\Settings\PersonalSection</personal-section>
|
||||
</settings>
|
||||
</info>
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
*/
|
||||
return [
|
||||
'routes' => [
|
||||
['name' => 'Settings#save', 'url' => '/settings/admin/security/externalpassword', 'verb' => 'POST'],
|
||||
['name' => 'settings#save', 'url' => '/settings', 'verb' => 'POST'],
|
||||
]
|
||||
];
|
||||
|
|
12
css/admin.css
Normal file
12
css/admin.css
Normal file
|
@ -0,0 +1,12 @@
|
|||
#security-externalpassword label {
|
||||
display: inline-block;
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
#security-externalpassword input[type=text] {
|
||||
width: 30rem;
|
||||
}
|
||||
|
||||
#security-externalpassword input[type=text].small {
|
||||
width: 12rem;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#hello {
|
||||
color: red;
|
||||
}
|
44
js/admin.js
Normal file
44
js/admin.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* global OC */
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
$('#externalpassword-save').click(function () {
|
||||
var formData = $('#externalpassword-form').serialize();
|
||||
$('#externalpassword-error-msg').hide();
|
||||
$('#externalpassword-save').attr('disabled', 'disabled');
|
||||
$.post(OC.generateUrl('apps/externalpassword/settings'), formData, function (response) {
|
||||
if (typeof(response.data) !== "undefined") {
|
||||
OC.msg.finishedSaving('#externalpassword-error-msg', response);
|
||||
} else {
|
||||
OC.msg.finishedSaving('#externalpassword-error-msg', {
|
||||
'status' : 'error',
|
||||
'data' : {
|
||||
'message' : t('externalpassword', 'Unable to save settings')
|
||||
}
|
||||
});
|
||||
}
|
||||
$("#externalpassword-save").removeAttr('disabled');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
|
@ -1,34 +1,62 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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\ExternalPassword\Controller;
|
||||
|
||||
use OCP\IRequest;
|
||||
use OCP\IConfig;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
|
||||
class SettingsController extends Controller {
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param string $AppName
|
||||
* @param IRequest $request
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct($AppName, IRequest $request, IConfig $config) {
|
||||
parent::__construct($AppName, $request);
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string
|
||||
* @param string $changePasswordUrl
|
||||
* @param string $descriptionText
|
||||
* @param string $buttonText
|
||||
*/
|
||||
public function save(string $changePasswordUrl, string $descriptionText, string $buttonText): JSONResponse {
|
||||
$this->config->setAppValue('externalpassword', 'changePasswordUrl', $changePasswordUrl);
|
||||
$this->config->setAppValue('externalpassword', 'descriptionText', $descriptionText);
|
||||
$this->config->setAppValue('externalpassword', 'buttonText', $buttonText);
|
||||
$parameters = [
|
||||
'changePasswordUrl' => $changePasswordUrl,
|
||||
'descriptionText' => $descriptionText,
|
||||
'buttonText' => $buttonText
|
||||
'status' => 'success',
|
||||
'data' => [
|
||||
'message' => 'Saved'
|
||||
]
|
||||
];
|
||||
return new JSONResponse($parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
81
lib/Settings/Admin.php
Normal file
81
lib/Settings/Admin.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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\ExternalPassword\Settings;
|
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\Settings\ISettings;
|
||||
|
||||
class Admin implements ISettings {
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var IL10N */
|
||||
private $l;
|
||||
|
||||
/**
|
||||
* Admin constructor.
|
||||
*
|
||||
* @param IConfig $config
|
||||
* @param IL10N $l
|
||||
*/
|
||||
public function __construct(IConfig $config, IL10N $l) {
|
||||
$this->config = $config;
|
||||
$this->l = $l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getForm() {
|
||||
$changePasswordUrl = $this->config->getAppValue('externalpassword', 'changePasswordUrl', '');
|
||||
$descriptionText = $this->config->getAppValue('externalpassword', 'descriptionText',
|
||||
'Your password is managed externally, please click the button below to change your password.');
|
||||
$buttonText = $this->config->getAppValue('externalpassword', 'buttonText', 'Change password');
|
||||
$parameters = [
|
||||
'changePasswordUrl' => $changePasswordUrl,
|
||||
'descriptionText' => $descriptionText,
|
||||
'buttonText' => $buttonText
|
||||
];
|
||||
return new TemplateResponse('externalpassword', 'settings/admin', $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the section ID, e.g. 'sharing'
|
||||
*/
|
||||
public function getSection() {
|
||||
return 'security';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int whether the form should be rather on the top or bottom of
|
||||
* the admin section. The forms are arranged in ascending order of the
|
||||
* priority values. It is required to return a value between 0 and 100.
|
||||
*/
|
||||
public function getPriority() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
81
lib/Settings/Personal.php
Normal file
81
lib/Settings/Personal.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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\ExternalPassword\Settings;
|
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\Settings\ISettings;
|
||||
|
||||
class Personal implements ISettings {
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/** @var IL10N */
|
||||
private $l;
|
||||
|
||||
/**
|
||||
* Admin constructor.
|
||||
*
|
||||
* @param IConfig $config
|
||||
* @param IL10N $l
|
||||
*/
|
||||
public function __construct(IConfig $config, IL10N $l) {
|
||||
$this->config = $config;
|
||||
$this->l = $l;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getForm() {
|
||||
$changePasswordUrl = $this->config->getAppValue('externalpassword', 'changePasswordUrl', '');
|
||||
$descriptionText = $this->config->getAppValue('externalpassword', 'descriptionText',
|
||||
'Your password is managed externally, please click the button below to change your password.');
|
||||
$buttonText = $this->config->getAppValue('externalpassword', 'buttonText', 'Change password');
|
||||
$parameters = [
|
||||
'changePasswordUrl' => $changePasswordUrl,
|
||||
'descriptionText' => $descriptionText,
|
||||
'buttonText' => $buttonText
|
||||
];
|
||||
return new TemplateResponse('externalpassword', 'settings/personal', $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the section ID, e.g. 'sharing'
|
||||
*/
|
||||
public function getSection() {
|
||||
return 'security';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int whether the form should be rather on the top or bottom of
|
||||
* the admin section. The forms are arranged in ascending order of the
|
||||
* priority values. It is required to return a value between 0 and 100.
|
||||
*/
|
||||
public function getPriority() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
48
templates/settings/admin.php
Normal file
48
templates/settings/admin.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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('externalpassword', 'admin');
|
||||
style('externalpassword', 'admin');
|
||||
?>
|
||||
<div id="security-externalpassword" class="section">
|
||||
<h2 class="inlineblock"><?php p($l->t('External Password'));?></h2>
|
||||
<span id="externalpassword-error-msg" class="msg success hidden">Saved</span>
|
||||
<p class="settings-hint"><?php p($l->t('To direct users to an external website in order to change their password, set the URL below.')); ?></p>
|
||||
<div class="admin-settings-externalpassword">
|
||||
<form id="externalpassword-form" method="POST">
|
||||
<div class="form-section">
|
||||
<label for="change-password-url"><?php p($l->t('External password URL')); ?></label>
|
||||
<input type="text" id="change-password-url" name="changePasswordUrl" value="<?php p($_['changePasswordUrl']); ?>" />
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="description-text"><?php p($l->t('Description')); ?></label>
|
||||
<input type="text" id="description-text" name="descriptionText" value="<?php p($_['descriptionText']); ?>" />
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<label for="button-text"><?php p($l->t('Button text')); ?></label>
|
||||
<input type="text" id="button-text" name="buttonText" value="<?php p($_['buttonText']); ?>" class="small" />
|
||||
</div>
|
||||
<input type="submit" id="externalpassword-save" value="<?php p($l->t('Save')); ?>" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
32
templates/settings/personal.php
Normal file
32
templates/settings/personal.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @author Raoul Snyman <raoul@snyman.info>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
?>
|
||||
<?php if ($_['changePasswordUrl']) { ?>
|
||||
<div id="security-external-password" class="section">
|
||||
<h2><?php p($l->t('Password'));?></h2>
|
||||
<div>
|
||||
<p class="settings-hint"><?php p($_['descriptionText']); ?></p>
|
||||
<p><a href="<?php p($_['changePasswordUrl']); ?>" class="button" target="_blank"><?php p($_['buttonText']); ?></a></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\ExternalPassword\Tests\Unit\Controller;
|
||||
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
|
||||
use OCA\ExternalPassword\Controller\PageController;
|
||||
|
||||
|
||||
class PageControllerTest extends PHPUnit_Framework_TestCase {
|
||||
private $controller;
|
||||
private $userId = 'john';
|
||||
|
||||
public function setUp() {
|
||||
$request = $this->getMockBuilder('OCP\IRequest')->getMock();
|
||||
|
||||
$this->controller = new PageController(
|
||||
'externalpassword', $request, $this->userId
|
||||
);
|
||||
}
|
||||
|
||||
public function testIndex() {
|
||||
$result = $this->controller->index();
|
||||
|
||||
$this->assertEquals('index', $result->getTemplateName());
|
||||
$this->assertTrue($result instanceof TemplateResponse);
|
||||
}
|
||||
|
||||
}
|
33
tests/Unit/Controller/SettingsControllerTest.php
Normal file
33
tests/Unit/Controller/SettingsControllerTest.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\ExternalPassword\Tests\Unit\Controller;
|
||||
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
|
||||
use OCA\ExternalPassword\Controller\SettingsController;
|
||||
|
||||
|
||||
class SettingsControllerTest extends PHPUnit_Framework_TestCase {
|
||||
private $controller;
|
||||
|
||||
public function setUp() {
|
||||
$request = $this->getMockBuilder('OCP\IRequest')->getMock();
|
||||
$config = $this->getMockBuilder('OCP\IConfig')->getMock();
|
||||
|
||||
$this->controller = new SettingsController(
|
||||
'externalpassword', $request, $config
|
||||
);
|
||||
}
|
||||
|
||||
public function testSave() {
|
||||
$changePasswordUrl = 'https://example.com/change-password';
|
||||
$descriptionText = 'Use the link below to change your password';
|
||||
$buttonText = 'Change password';
|
||||
|
||||
$result = $this->controller->saveSettings($changePasswordUrl, $descriptionText, $buttonText);
|
||||
$this->assertTrue($result instanceof JSONResponse);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue