Move admin settings to Vue
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
parent
0703c5a069
commit
4301242b85
|
|
@ -0,0 +1,2 @@
|
|||
/js/*
|
||||
/tests/*
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
extends: [
|
||||
'@nextcloud'
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
/js/registration-settings.js binary
|
||||
/js/registration-settings.js.map binary
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
name: Dependabot
|
||||
on: pull_request_target
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Default github action approve
|
||||
- uses: hmarr/auto-approve-action@v2.0.0
|
||||
if: github.ref == 'refs/heads/master' &&
|
||||
(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Nextcloud bot approve and merge request
|
||||
- uses: ahmadnassri/action-dependabot-auto-merge@v2
|
||||
if: github.ref == 'refs/heads/master' &&
|
||||
(github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]')
|
||||
with:
|
||||
target: minor
|
||||
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}
|
||||
|
|
@ -52,6 +52,50 @@ jobs:
|
|||
- name: Run coding standards check
|
||||
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )
|
||||
|
||||
node:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
name: eslint node${{ matrix.node-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
stylelint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
name: stylelint node${{ matrix.node-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run stylelint
|
||||
|
||||
xml-linters:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
name: Node
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- stable*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
name: node${{ matrix.node-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies & build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build --if-present
|
||||
|
||||
- name: Check webpack build changes
|
||||
run: |
|
||||
bash -c "[[ ! \"`git status --porcelain `\" ]] || ( echo 'Uncommited changes in webpack build' && git status && exit 1 )"
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/.php_cs.cache
|
||||
/build
|
||||
/node_modules
|
||||
/tests/clover.xml
|
||||
/tests/coverage-html
|
||||
/tests/.phpunit.result.cache
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# compiled vue templates
|
||||
js/registration-settings.js
|
||||
js/registration-settings.js.map
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
const babelConfig = require('@nextcloud/babel-config')
|
||||
|
||||
module.exports = babelConfig
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,30 +0,0 @@
|
|||
$(document).ready(function() {
|
||||
function saveSettings() {
|
||||
OC.msg.startSaving('#registration_settings_msg');
|
||||
$.ajax({
|
||||
url: OC.generateUrl('/apps/registration/settings'),
|
||||
type: 'POST',
|
||||
data: $('#registration_settings_form').serialize(),
|
||||
success: function(data){
|
||||
OC.msg.finishedSaving('#registration_settings_msg', data);
|
||||
},
|
||||
error: function(data){
|
||||
OC.msg.finishedError('#registration_settings_msg', data.responseJSON.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#registration_settings_form').change(saveSettings);
|
||||
$('#registration').keypress(function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
$('#email_is_login').change(function(event) {
|
||||
if (event.target.checked) {
|
||||
$('.login-name-policy').addClass('hidden');
|
||||
} else {
|
||||
$('.login-name-policy').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
namespace OCA\Registration\Controller;
|
||||
|
||||
use OCP\IGroup;
|
||||
use \OCP\IRequest;
|
||||
use \OCP\AppFramework\Http\DataResponse;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
|
@ -42,7 +43,7 @@ class SettingsController extends Controller {
|
|||
/**
|
||||
* @AdminRequired
|
||||
*
|
||||
* @param string $registered_user_group all newly registered user will be put in this group
|
||||
* @param string|null $registered_user_group all newly registered user will be put in this group
|
||||
* @param string $allowed_domains Registrations are only allowed for E-Mailadresses with these domains
|
||||
* @param string $additional_hint show Text at user-creation form
|
||||
* @param string $email_verification_hint if filled embed Text in Verification mail send to user
|
||||
|
|
@ -53,7 +54,7 @@ class SettingsController extends Controller {
|
|||
* @param bool|null $show_domains should the email list be shown to the user or not
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function admin(string $registered_user_group,
|
||||
public function admin(?string $registered_user_group,
|
||||
string $allowed_domains,
|
||||
string $additional_hint,
|
||||
string $email_verification_hint,
|
||||
|
|
@ -104,13 +105,7 @@ class SettingsController extends Controller {
|
|||
$this->config->setAppValue($this->appName, 'show_domains', $show_domains ? 'yes' : 'no');
|
||||
$this->config->setAppValue($this->appName, 'disable_email_verification', $disable_email_verification ? 'yes' : 'no');
|
||||
|
||||
// handle groups
|
||||
$groups = $this->groupmanager->search('');
|
||||
$group_id_list = [];
|
||||
foreach ($groups as $group) {
|
||||
$group_id_list[] = $group->getGid();
|
||||
}
|
||||
if ($registered_user_group === 'none') {
|
||||
if ($registered_user_group === null) {
|
||||
$this->config->deleteAppValue($this->appName, 'registered_user_group');
|
||||
return new DataResponse([
|
||||
'data' => [
|
||||
|
|
@ -118,7 +113,10 @@ class SettingsController extends Controller {
|
|||
],
|
||||
'status' => 'success',
|
||||
]);
|
||||
} elseif (in_array($registered_user_group, $group_id_list)) {
|
||||
}
|
||||
|
||||
$group = $this->groupmanager->get($registered_user_group);
|
||||
if ($group instanceof IGroup) {
|
||||
$this->config->setAppValue($this->appName, 'registered_user_group', $registered_user_group);
|
||||
return new DataResponse([
|
||||
'data' => [
|
||||
|
|
@ -126,7 +124,8 @@ class SettingsController extends Controller {
|
|||
],
|
||||
'status' => 'success',
|
||||
]);
|
||||
} else {
|
||||
}
|
||||
|
||||
return new DataResponse([
|
||||
'data' => [
|
||||
'message' => $this->l10n->t('No such group'),
|
||||
|
|
@ -135,4 +134,3 @@ class SettingsController extends Controller {
|
|||
], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ namespace OCA\Registration\Settings;
|
|||
|
||||
use OCA\Registration\AppInfo\Application;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\Settings\ISettings;
|
||||
|
||||
|
|
@ -36,15 +38,19 @@ class RegistrationSettings implements ISettings {
|
|||
private $config;
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
/** @var IInitialState */
|
||||
private $initialState;
|
||||
/** @var string */
|
||||
protected $appName;
|
||||
|
||||
public function __construct(string $appName,
|
||||
IConfig $config,
|
||||
IGroupManager $groupManager) {
|
||||
IGroupManager $groupManager,
|
||||
IInitialState $initialState) {
|
||||
$this->appName = $appName;
|
||||
$this->config = $config;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->initialState = $initialState;
|
||||
}
|
||||
|
||||
public function getForm(): TemplateResponse {
|
||||
|
|
@ -54,35 +60,53 @@ class RegistrationSettings implements ISettings {
|
|||
foreach ($groups as $group) {
|
||||
$groupIds[] = $group->getGid();
|
||||
}
|
||||
$assignedGroups = $this->config->getAppValue($this->appName, 'registered_user_group', 'none');
|
||||
|
||||
// handle additional hint
|
||||
$additional_hint = $this->config->getAppValue($this->appName, 'additional_hint', '');
|
||||
$email_verification_hint = $this->config->getAppValue($this->appName, 'email_verification_hint', '');
|
||||
$this->initialState->provideInitialState(
|
||||
'registered_user_group',
|
||||
$this->getGroupDetailArray($this->config->getAppValue($this->appName, 'registered_user_group', 'none'))
|
||||
);
|
||||
|
||||
// handle domains
|
||||
$allowedDomains = $this->config->getAppValue($this->appName, 'allowed_domains', '');
|
||||
$this->initialState->provideInitialState(
|
||||
'admin_approval_required',
|
||||
$this->config->getAppValue($this->appName, 'admin_approval_required', 'no') === 'yes'
|
||||
);
|
||||
|
||||
$username_policy_regex = $this->config->getAppValue($this->appName, 'username_policy_regex', '');
|
||||
$adminApprovalRequired = $this->config->getAppValue($this->appName, 'admin_approval_required', 'no');
|
||||
$emailIsLogin = $this->config->getAppValue($this->appName, 'email_is_login', 'no');
|
||||
$domainsIsBlocklist = $this->config->getAppValue($this->appName, 'domains_is_blocklist', 'no');
|
||||
$showDomains = $this->config->getAppValue($this->appName, 'show_domains', 'no');
|
||||
$disableEmailVerification = $this->config->getAppValue($this->appName, 'disable_email_verification', 'no');
|
||||
$this->initialState->provideInitialState(
|
||||
'allowed_domains',
|
||||
$this->config->getAppValue($this->appName, 'allowed_domains')
|
||||
);
|
||||
$this->initialState->provideInitialState(
|
||||
'domains_is_blocklist',
|
||||
$this->config->getAppValue($this->appName, 'domains_is_blocklist', 'no') === 'yes'
|
||||
);
|
||||
$this->initialState->provideInitialState(
|
||||
'show_domains',
|
||||
$this->config->getAppValue($this->appName, 'show_domains', 'no') === 'yes'
|
||||
);
|
||||
$this->initialState->provideInitialState(
|
||||
'disable_email_verification',
|
||||
$this->config->getAppValue($this->appName, 'disable_email_verification', 'no') === 'yes'
|
||||
);
|
||||
$this->initialState->provideInitialState(
|
||||
'email_is_login',
|
||||
$this->config->getAppValue($this->appName, 'email_is_login', 'no') === 'yes'
|
||||
);
|
||||
|
||||
return new TemplateResponse('registration', 'admin', [
|
||||
'groups' => $groupIds,
|
||||
'current' => $assignedGroups,
|
||||
'additional_hint' => $additional_hint,
|
||||
'email_verification_hint' => $email_verification_hint,
|
||||
'username_policy_regex' => $username_policy_regex,
|
||||
'allowed' => $allowedDomains,
|
||||
'approval_required' => $adminApprovalRequired,
|
||||
'email_is_login' => $emailIsLogin,
|
||||
'domains_is_blocklist' => $domainsIsBlocklist,
|
||||
'show_domains' => $showDomains,
|
||||
'disable_email_verification' => $disableEmailVerification,
|
||||
], '');
|
||||
$this->initialState->provideInitialState(
|
||||
'username_policy_regex',
|
||||
$this->config->getAppValue($this->appName, 'username_policy_regex')
|
||||
);
|
||||
|
||||
$this->initialState->provideInitialState(
|
||||
'additional_hint',
|
||||
$this->config->getAppValue($this->appName, 'additional_hint')
|
||||
);
|
||||
$this->initialState->provideInitialState(
|
||||
'email_verification_hint',
|
||||
$this->config->getAppValue($this->appName, 'email_verification_hint')
|
||||
);
|
||||
|
||||
return new TemplateResponse('registration', 'admin', [], TemplateResponse::RENDER_AS_BLANK);
|
||||
}
|
||||
|
||||
public function getSection(): string {
|
||||
|
|
@ -92,4 +116,16 @@ class RegistrationSettings implements ISettings {
|
|||
public function getPriority(): int {
|
||||
return 50;
|
||||
}
|
||||
|
||||
protected function getGroupDetailArray(string $gid): array {
|
||||
$group = $this->groupManager->get($gid);
|
||||
if ($group instanceof IGroup) {
|
||||
return [
|
||||
'id' => $group->getGID(),
|
||||
'displayname' => $group->getDisplayName(),
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "registration",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production webpack --progress --config webpack.js",
|
||||
"dev": "NODE_ENV=development webpack --progress --config webpack.js",
|
||||
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.js",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"lint:fix": "eslint --ext .js,.vue src --fix",
|
||||
"stylelint": "stylelint src",
|
||||
"stylelint:fix": "stylelint src --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/axios": "^1.6.0",
|
||||
"@nextcloud/dialogs": "^3.1.1",
|
||||
"@nextcloud/initial-state": "^1.2.0",
|
||||
"@nextcloud/router": "^1.2.0",
|
||||
"@nextcloud/vue": "^3.8.0",
|
||||
"debounce": "^1.2.1",
|
||||
"vue": "^2.6.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.13.14",
|
||||
"@nextcloud/babel-config": "^1.0.0-beta.0",
|
||||
"@nextcloud/eslint-config": "^5.0.0",
|
||||
"@nextcloud/eslint-plugin": "^2.0.0",
|
||||
"@nextcloud/webpack-vue-config": "^4.0.1",
|
||||
"babel-loader": "^8.2.2",
|
||||
"css-loader": "^4.3.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-plugin-vue": "^7.8.0",
|
||||
"eslint-webpack-plugin": "^2.5.3",
|
||||
"node-polyfill-webpack-plugin": "^1.1.0",
|
||||
"sass": "^1.32.8",
|
||||
"sass-loader": "^10.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"stylelint": "^13.12.0",
|
||||
"stylelint-config-recommended-scss": "^4.2.0",
|
||||
"stylelint-scss": "^3.19.0",
|
||||
"stylelint-webpack-plugin": "^2.1.1",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"webpack": "^5.28.0",
|
||||
"webpack-cli": "^4.6.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 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/>.
|
||||
-
|
||||
-->
|
||||
<template>
|
||||
<div id="registration_settings_form">
|
||||
<div class="section">
|
||||
<h2>{{ t('registration', 'Registration settings') }}</h2>
|
||||
<p>
|
||||
<input id="admin_approval"
|
||||
v-model="adminApproval"
|
||||
type="checkbox"
|
||||
name="admin_approval"
|
||||
class="checkbox"
|
||||
:disabled="loading"
|
||||
@change="saveData">
|
||||
<label for="admin_approval">{{ t('registration', 'Require admin approval') }}</label>
|
||||
</p>
|
||||
<em>{{ t('registration', 'Enabling "admin approval" will prevent registrations from mobile and desktop clients to complete as the credentials can not be verified by the client until the user was enabled.') }}</em>
|
||||
|
||||
<p>
|
||||
<label for="registered_user_group">
|
||||
{{ t('registration', 'Registered users default group') }}
|
||||
</label>
|
||||
</p>
|
||||
<Multiselect
|
||||
id="registered_user_group"
|
||||
v-model="registeredUserGroup"
|
||||
:placeholder="t('registration', 'Select group')"
|
||||
:options="groups"
|
||||
:disabled="loading"
|
||||
:searchable="true"
|
||||
:tag-width="60"
|
||||
:loading="loadingGroups"
|
||||
:allow-empty="true"
|
||||
:close-on-select="false"
|
||||
track-by="id"
|
||||
label="displayname"
|
||||
@search-change="searchGroup"
|
||||
@change="saveData" />
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>{{ t('registration', 'Email settings') }}</h2>
|
||||
|
||||
<h4>{{ domainListLabel }}</h4>
|
||||
<input v-model="allowedDomains"
|
||||
type="text"
|
||||
name="allowed_domains"
|
||||
:disabled="loading"
|
||||
placeholder="nextcloud.com;*.example.com"
|
||||
:aria-label="t('registration', 'Allowed email domain')"
|
||||
@input="debounceSavingSlow">
|
||||
|
||||
<p>
|
||||
<input id="domains_is_blocklist"
|
||||
v-model="domainsIsBlocklist"
|
||||
type="checkbox"
|
||||
name="domains_is_blocklist"
|
||||
class="checkbox"
|
||||
:disabled="loading"
|
||||
@change="saveData">
|
||||
<label for="domains_is_blocklist">{{ t('registration', 'Block listed email domains instead of allowing them') }}</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input id="show_domains"
|
||||
v-model="showDomains"
|
||||
type="checkbox"
|
||||
name="show_domains"
|
||||
class="checkbox"
|
||||
:disabled="loading"
|
||||
@change="saveData">
|
||||
<label for="show_domains">{{ showDomainListLabel }}</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input id="disable_email_verification"
|
||||
v-model="disableEmailVerification"
|
||||
type="checkbox"
|
||||
name="disable_email_verification"
|
||||
class="checkbox"
|
||||
:disabled="loading"
|
||||
@change="saveData">
|
||||
<label for="disable_email_verification">{{ t('registration', 'Disable email verification') }}</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input id="email_is_login"
|
||||
v-model="emailIsLogin"
|
||||
type="checkbox"
|
||||
name="email_is_login"
|
||||
class="checkbox"
|
||||
:disabled="loading"
|
||||
@change="saveData">
|
||||
<label for="email_is_login">{{ t('registration', 'Force email as login name') }}</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!emailIsLogin"
|
||||
class="section">
|
||||
<h2>{{ t('registration', 'Login name settings') }}</h2>
|
||||
|
||||
<h3>{{ t('registration', 'Login name policy') }}</h3>
|
||||
<p>
|
||||
<input v-model="usernamePolicyRegex"
|
||||
type="text"
|
||||
name="username_policy_regex"
|
||||
:disabled="loading"
|
||||
placeholder="E.g.: /^[a-z-]+\.[a-z-]+$/"
|
||||
:aria-label="t('registration', 'Regular expression to validate login names')"
|
||||
@input="debounceSavingSlow">
|
||||
</p>
|
||||
<em>{{ t('registration', 'If configured, login names will be validated through the regular expression. If the validation fails the user is prompted with a generic error. Make sure your regex is working correctly.') }}</em>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>{{ t('registration', 'User instructions') }}</h2>
|
||||
<em>{{ t('registration', 'Caution: The user instructions will not be translated and will therefore be displayed as configured below for all users regardless of their actual language.') }}</em>
|
||||
|
||||
<h3>{{ t('registration', 'Registration form instructions') }}</h3>
|
||||
<p>
|
||||
<input v-model="additionalHint"
|
||||
type="text"
|
||||
name="additional_hint"
|
||||
:disabled="loading"
|
||||
placeholder="Please create your username following the scheme 'firstname.lastname'."
|
||||
:aria-label="t('registration', 'A short message that is shown to the user in the registration process.')"
|
||||
@input="debounceSavingSlow">
|
||||
</p>
|
||||
<em>{{ t('registration', 'Add additional user instructions (e.g. for choosing their login name). If configured the text is displayed in the account creation step of the registration process.') }}</em>
|
||||
|
||||
<h3>{{ t('registration', 'Verification email instructions') }}</h3>
|
||||
<p>
|
||||
<input v-model="emailVerificationHint"
|
||||
type="text"
|
||||
name="email_verification_hint"
|
||||
:disabled="loading"
|
||||
placeholder="Please create your username following the scheme 'firstname.lastname'."
|
||||
:aria-label="t('registration', 'A short message that is shown to the user in the verification email.')"
|
||||
@input="debounceSavingSlow">
|
||||
</p>
|
||||
<em>{{ t('registration', 'Add additional user instructions (e.g. for choosing their login name). If configured the text is embedded in the verification-email.') }}</em>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
|
||||
import axios from '@nextcloud/axios'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { generateOcsUrl, generateUrl } from '@nextcloud/router'
|
||||
import debounce from 'debounce'
|
||||
|
||||
export default {
|
||||
name: 'AdminSettings',
|
||||
|
||||
components: {
|
||||
Multiselect,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loadingGroups: false,
|
||||
adminApproval: false,
|
||||
registeredUserGroup: '',
|
||||
allowedDomains: '',
|
||||
domainsIsBlocklist: false,
|
||||
showDomains: false,
|
||||
disableEmailVerification: false,
|
||||
emailIsLogin: false,
|
||||
usernamePolicyRegex: '',
|
||||
additionalHint: '',
|
||||
emailVerificationHint: '',
|
||||
groups: [],
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
domainListLabel() {
|
||||
if (this.domainsIsBlocklist) {
|
||||
return t('registration', 'Blocked email domains')
|
||||
}
|
||||
|
||||
return t('registration', 'Allowed email domains')
|
||||
},
|
||||
showDomainListLabel() {
|
||||
if (this.domainsIsBlocklist) {
|
||||
return t('registration', 'Show the blocked email domains to users')
|
||||
}
|
||||
|
||||
return t('registration', 'Show the allowed email domains to users')
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.adminApproval = loadState('registration', 'admin_approval_required')
|
||||
this.registeredUserGroup = loadState('registration', 'registered_user_group')
|
||||
this.allowedDomains = loadState('registration', 'allowed_domains')
|
||||
this.domainsIsBlocklist = loadState('registration', 'domains_is_blocklist')
|
||||
this.showDomains = loadState('registration', 'show_domains')
|
||||
this.disableEmailVerification = loadState('registration', 'disable_email_verification')
|
||||
this.emailIsLogin = loadState('registration', 'email_is_login')
|
||||
this.usernamePolicyRegex = loadState('registration', 'username_policy_regex')
|
||||
this.additionalHint = loadState('registration', 'additional_hint')
|
||||
this.emailVerificationHint = loadState('registration', 'email_verification_hint')
|
||||
|
||||
this.searchGroup('')
|
||||
},
|
||||
methods: {
|
||||
debounceSavingSlow: debounce(function() {
|
||||
this.saveData()
|
||||
}, 2000),
|
||||
|
||||
async saveData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const response = await axios.post(generateUrl('/apps/registration/settings'), {
|
||||
admin_approval_required: this.adminApproval,
|
||||
registered_user_group: this.registeredUserGroup?.id,
|
||||
allowed_domains: this.allowedDomains,
|
||||
domains_is_blocklist: this.domainsIsBlocklist,
|
||||
show_domains: this.showDomains,
|
||||
disable_email_verification: this.disableEmailVerification,
|
||||
email_is_login: this.emailIsLogin,
|
||||
username_policy_regex: this.usernamePolicyRegex,
|
||||
additional_hint: this.additionalHint,
|
||||
email_verification_hint: this.emailVerificationHint,
|
||||
})
|
||||
|
||||
if (response?.data?.status === 'success' && response?.data?.data?.message) {
|
||||
showSuccess(response.data.data.message)
|
||||
} else if (response?.data?.data?.message) {
|
||||
showError(response.data.data.message)
|
||||
} else {
|
||||
showError(t('registration', 'An error occurred while saving the settings'))
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.response?.data?.data?.message) {
|
||||
showError(e.response.data.data.message)
|
||||
} else {
|
||||
showError(t('registration', 'An error occurred while saving the settings'))
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
this.loading = false
|
||||
},
|
||||
|
||||
searchGroup: debounce(async function(query) {
|
||||
this.loadingGroups = true
|
||||
try {
|
||||
const response = await axios.get(generateOcsUrl('cloud', 2) + 'groups/details', {
|
||||
search: query,
|
||||
limit: 20,
|
||||
offset: 0,
|
||||
})
|
||||
this.groups = response.data.ocs.data.groups.sort(function(a, b) {
|
||||
return a.displayname.localeCompare(b.displayname)
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('Could not fetch groups', err)
|
||||
} finally {
|
||||
this.loadingGroups = false
|
||||
}
|
||||
}, 500),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2021 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
import AdminSettings from './AdminSettings.vue'
|
||||
|
||||
Vue.prototype.t = t
|
||||
Vue.prototype.OC = OC
|
||||
|
||||
const app = new Vue({
|
||||
render: h => h(AdminSettings),
|
||||
}).$mount('#registration_settings_form')
|
||||
|
||||
export { app }
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
module.exports = {
|
||||
extends: 'stylelint-config-recommended-scss',
|
||||
rules: {
|
||||
indentation: 'tab',
|
||||
'selector-type-no-unknown': null,
|
||||
'number-leading-zero': null,
|
||||
'rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
ignore: ['after-comment', 'inside-block'],
|
||||
},
|
||||
],
|
||||
'declaration-empty-line-before': [
|
||||
'never',
|
||||
{
|
||||
ignore: ['after-declaration'],
|
||||
},
|
||||
],
|
||||
'comment-empty-line-before': null,
|
||||
'selector-type-case': null,
|
||||
'selector-list-comma-newline-after': null,
|
||||
'no-descending-specificity': null,
|
||||
'string-quotes': 'single',
|
||||
'selector-pseudo-element-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ['v-deep'],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: ['stylelint-scss'],
|
||||
}
|
||||
|
|
@ -1,97 +1,7 @@
|
|||
<?php
|
||||
/** @var array $_ */
|
||||
/** @var \OCP\IL10N $l */
|
||||
script('registration', 'settings');
|
||||
script('registration', 'registration-settings');
|
||||
style('registration', 'settings');
|
||||
?>
|
||||
<form id="registration_settings_form" class="section">
|
||||
<h2><?php p($l->t('Registration')); ?></h2><span id="registration_settings_msg" class="msg"></span>
|
||||
|
||||
<h3><?php p($l->t('Registered users default group')); ?></h3>
|
||||
<p>
|
||||
<label>
|
||||
<select id="registered_user_group" name="registered_user_group">
|
||||
<option value="none" <?php echo $_['current'] === 'none' ? 'selected="selected"' : ''; ?>><?php p($l->t('None')); ?></option>
|
||||
<?php
|
||||
foreach ($_['groups'] as $group) {
|
||||
$selected = $_['current'] === $group ? 'selected="selected"' : '';
|
||||
echo '<option value="'.$group.'" '.$selected.'>'.$group.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<h3><?php p($l->t('Disable Email Verification')); ?></h3>
|
||||
<p>
|
||||
<input type="checkbox" id="disable_email_verification" class="checkbox" name="disable_email_verification" <?php if ($_['disable_email_verification'] === 'yes') {
|
||||
echo ' checked';
|
||||
} ?>>
|
||||
<label for="disable_email_verification"><?php p($l->t('Let user can register directly without email verification')); ?></label>
|
||||
</p>
|
||||
|
||||
<h3><?php p($l->t('Allowed email domains')); ?></h3>
|
||||
<p>
|
||||
<label>
|
||||
<input type="text" id="allowed_domains" name="allowed_domains" value="<?php p($_['allowed']);?>" placeholder="nextcloud.com;*.example.com">
|
||||
</label>
|
||||
</p>
|
||||
<em><?php p($l->t('Enter a semicolon-separated list of allowed email domains, * for wildcard. Example: %s', ['nextcloud.com;*.example.com']));?></em>
|
||||
|
||||
<p>
|
||||
<input type="checkbox" id="domains_is_blocklist" class="checkbox" name="domains_is_blocklist" <?php if ($_['domains_is_blocklist'] === 'yes') {
|
||||
echo ' checked';
|
||||
} ?>>
|
||||
<label for="domains_is_blocklist"><?php p($l->t('Block listed email domains instead of allowing them')); ?></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="checkbox" id="show_domains" class="checkbox" name="show_domains" <?php if ($_['show_domains'] === 'yes') {
|
||||
echo ' checked';
|
||||
} ?>>
|
||||
<label for="show_domains"><?php p($l->t('Show the allowed/blocked email domains to users')); ?></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="checkbox" id="email_is_login" class="checkbox" name="email_is_login" <?php if ($_['email_is_login'] === 'yes') {
|
||||
echo ' checked';
|
||||
} ?>>
|
||||
<label for="email_is_login"><?php p($l->t('Force email as login name')); ?></label>
|
||||
</p>
|
||||
|
||||
<div class="login-name-policy <?php if ($_['email_is_login'] === 'yes') { p('hidden'); } ?>">
|
||||
<h3><?php p($l->t('Login name policy')); ?></h3>
|
||||
<p>
|
||||
<label>
|
||||
<input type="text" id="username_policy_regex" name="username_policy_regex" value="<?php p($_['username_policy_regex']);?>" placeholder="E.g.: /^[a-z-]+\.[a-z-]+$/">
|
||||
</label>
|
||||
</p>
|
||||
<em><?php p($l->t('If configured, login names will be validated through the regular expression. If the validation fails the user is prompted with a generic error. Make sure your regex is working correctly.'));?></em>
|
||||
</div>
|
||||
|
||||
<h3><?php p($l->t('User instructions')); ?></h3>
|
||||
<em><?php p($l->t('Caution: The user instructions will not be translated and will therefore be displayed as configured below for all users regardless of their actual language.'));?></em>
|
||||
<p>
|
||||
<label>
|
||||
<input type="text" id="additional_hint" name="additional_hint" value="<?php p($_['additional_hint']);?>" placeholder="Please create your username following the scheme 'firstname.lastname'.">
|
||||
</label>
|
||||
</p>
|
||||
<em><?php p($l->t('Add additional user instructions (e.g. for choosing their usernames). If configured the text is displayed in the account creation step of the registration process.'));?></em>
|
||||
|
||||
<p>
|
||||
<label>
|
||||
<input type="text" id="email_verification_hint" name="email_verification_hint" value="<?php p($_['email_verification_hint']);?>" placeholder="Please create your username following the scheme 'firstname.lastname'.">
|
||||
</label>
|
||||
</p>
|
||||
<em><?php p($l->t('Add additional user instructions (e.g. for choosing their usernames). If configured the text is embedded in the the verification-Email.'));?></em>
|
||||
|
||||
<h3><?php p($l->t('Admin approval')); ?></h3>
|
||||
<p>
|
||||
<input type="checkbox" id="admin_approval_required" class="checkbox" name="admin_approval_required" <?php if ($_['approval_required'] === 'yes') {
|
||||
echo ' checked';
|
||||
} ?>>
|
||||
<label for="admin_approval_required"><?php p($l->t('Require admin approval')); ?></label>
|
||||
</p>
|
||||
|
||||
<em><?php p($l->t('Enabling "admin approval" will prevent registrations from mobile and desktop clients to complete as the credentials can not be verified by the client until the user was enabled.'));?></em>
|
||||
</form>
|
||||
<div id="registration_settings_form"></div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
const path = require('path')
|
||||
const { merge } = require('webpack-merge')
|
||||
const webpackConfig = require('@nextcloud/webpack-vue-config')
|
||||
|
||||
webpackConfig.entry = {}
|
||||
const config = {
|
||||
entry: {
|
||||
settings: path.join(__dirname, 'src', 'settings'),
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = merge(config, webpackConfig)
|
||||
Loading…
Reference in New Issue