Move admin settings to Vue

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2021-03-31 17:44:47 +02:00
parent 0703c5a069
commit 4301242b85
No known key found for this signature in database
GPG Key ID: 7076EA9751AACDDA
21 changed files with 20679 additions and 165 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
/js/*
/tests/*

5
.eslintrc.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
extends: [
'@nextcloud'
]
};

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
/js/registration-settings.js binary
/js/registration-settings.js.map binary

View File

@ -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 }}

View File

@ -52,6 +52,50 @@ jobs:
- name: Run coding standards check - name: Run coding standards check
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) 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: xml-linters:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

34
.github/workflows/node.yml vendored Normal file
View File

@ -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
.gitignore vendored
View File

@ -1,5 +1,6 @@
/.php_cs.cache /.php_cs.cache
/build /build
/node_modules
/tests/clover.xml /tests/clover.xml
/tests/coverage-html /tests/coverage-html
/tests/.phpunit.result.cache /tests/.phpunit.result.cache

3
.l10nignore Normal file
View File

@ -0,0 +1,3 @@
# compiled vue templates
js/registration-settings.js
js/registration-settings.js.map

3
babel.config.js Normal file
View File

@ -0,0 +1,3 @@
const babelConfig = require('@nextcloud/babel-config')
module.exports = babelConfig

356
js/registration-settings.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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');
}
});
});

View File

@ -12,6 +12,7 @@
namespace OCA\Registration\Controller; namespace OCA\Registration\Controller;
use OCP\IGroup;
use \OCP\IRequest; use \OCP\IRequest;
use \OCP\AppFramework\Http\DataResponse; use \OCP\AppFramework\Http\DataResponse;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
@ -42,7 +43,7 @@ class SettingsController extends Controller {
/** /**
* @AdminRequired * @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 $allowed_domains Registrations are only allowed for E-Mailadresses with these domains
* @param string $additional_hint show Text at user-creation form * @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 * @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 * @param bool|null $show_domains should the email list be shown to the user or not
* @return DataResponse * @return DataResponse
*/ */
public function admin(string $registered_user_group, public function admin(?string $registered_user_group,
string $allowed_domains, string $allowed_domains,
string $additional_hint, string $additional_hint,
string $email_verification_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, 'show_domains', $show_domains ? 'yes' : 'no');
$this->config->setAppValue($this->appName, 'disable_email_verification', $disable_email_verification ? 'yes' : 'no'); $this->config->setAppValue($this->appName, 'disable_email_verification', $disable_email_verification ? 'yes' : 'no');
// handle groups if ($registered_user_group === null) {
$groups = $this->groupmanager->search('');
$group_id_list = [];
foreach ($groups as $group) {
$group_id_list[] = $group->getGid();
}
if ($registered_user_group === 'none') {
$this->config->deleteAppValue($this->appName, 'registered_user_group'); $this->config->deleteAppValue($this->appName, 'registered_user_group');
return new DataResponse([ return new DataResponse([
'data' => [ 'data' => [
@ -118,7 +113,10 @@ class SettingsController extends Controller {
], ],
'status' => 'success', '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); $this->config->setAppValue($this->appName, 'registered_user_group', $registered_user_group);
return new DataResponse([ return new DataResponse([
'data' => [ 'data' => [
@ -126,13 +124,13 @@ class SettingsController extends Controller {
], ],
'status' => 'success', 'status' => 'success',
]); ]);
} else {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('No such group'),
],
'status' => 'error',
], Http::STATUS_NOT_FOUND);
} }
return new DataResponse([
'data' => [
'message' => $this->l10n->t('No such group'),
],
'status' => 'error',
], Http::STATUS_NOT_FOUND);
} }
} }

View File

@ -27,7 +27,9 @@ namespace OCA\Registration\Settings;
use OCA\Registration\AppInfo\Application; use OCA\Registration\AppInfo\Application;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\Settings\ISettings; use OCP\Settings\ISettings;
@ -36,15 +38,19 @@ class RegistrationSettings implements ISettings {
private $config; private $config;
/** @var IGroupManager */ /** @var IGroupManager */
private $groupManager; private $groupManager;
/** @var IInitialState */
private $initialState;
/** @var string */ /** @var string */
protected $appName; protected $appName;
public function __construct(string $appName, public function __construct(string $appName,
IConfig $config, IConfig $config,
IGroupManager $groupManager) { IGroupManager $groupManager,
IInitialState $initialState) {
$this->appName = $appName; $this->appName = $appName;
$this->config = $config; $this->config = $config;
$this->groupManager = $groupManager; $this->groupManager = $groupManager;
$this->initialState = $initialState;
} }
public function getForm(): TemplateResponse { public function getForm(): TemplateResponse {
@ -54,35 +60,53 @@ class RegistrationSettings implements ISettings {
foreach ($groups as $group) { foreach ($groups as $group) {
$groupIds[] = $group->getGid(); $groupIds[] = $group->getGid();
} }
$assignedGroups = $this->config->getAppValue($this->appName, 'registered_user_group', 'none');
// handle additional hint $this->initialState->provideInitialState(
$additional_hint = $this->config->getAppValue($this->appName, 'additional_hint', ''); 'registered_user_group',
$email_verification_hint = $this->config->getAppValue($this->appName, 'email_verification_hint', ''); $this->getGroupDetailArray($this->config->getAppValue($this->appName, 'registered_user_group', 'none'))
);
// handle domains $this->initialState->provideInitialState(
$allowedDomains = $this->config->getAppValue($this->appName, 'allowed_domains', ''); 'admin_approval_required',
$this->config->getAppValue($this->appName, 'admin_approval_required', 'no') === 'yes'
);
$username_policy_regex = $this->config->getAppValue($this->appName, 'username_policy_regex', ''); $this->initialState->provideInitialState(
$adminApprovalRequired = $this->config->getAppValue($this->appName, 'admin_approval_required', 'no'); 'allowed_domains',
$emailIsLogin = $this->config->getAppValue($this->appName, 'email_is_login', 'no'); $this->config->getAppValue($this->appName, 'allowed_domains')
$domainsIsBlocklist = $this->config->getAppValue($this->appName, 'domains_is_blocklist', 'no'); );
$showDomains = $this->config->getAppValue($this->appName, 'show_domains', 'no'); $this->initialState->provideInitialState(
$disableEmailVerification = $this->config->getAppValue($this->appName, 'disable_email_verification', 'no'); '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', [ $this->initialState->provideInitialState(
'groups' => $groupIds, 'username_policy_regex',
'current' => $assignedGroups, $this->config->getAppValue($this->appName, 'username_policy_regex')
'additional_hint' => $additional_hint, );
'email_verification_hint' => $email_verification_hint,
'username_policy_regex' => $username_policy_regex, $this->initialState->provideInitialState(
'allowed' => $allowedDomains, 'additional_hint',
'approval_required' => $adminApprovalRequired, $this->config->getAppValue($this->appName, 'additional_hint')
'email_is_login' => $emailIsLogin, );
'domains_is_blocklist' => $domainsIsBlocklist, $this->initialState->provideInitialState(
'show_domains' => $showDomains, 'email_verification_hint',
'disable_email_verification' => $disableEmailVerification, $this->config->getAppValue($this->appName, 'email_verification_hint')
], ''); );
return new TemplateResponse('registration', 'admin', [], TemplateResponse::RENDER_AS_BLANK);
} }
public function getSection(): string { public function getSection(): string {
@ -92,4 +116,16 @@ class RegistrationSettings implements ISettings {
public function getPriority(): int { public function getPriority(): int {
return 50; 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 [];
}
} }

19708
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

56
package.json Normal file
View File

@ -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"
}
}

289
src/AdminSettings.vue Normal file
View File

@ -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>

31
src/settings.js Normal file
View File

@ -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 }

32
stylelint.config.js Normal file
View File

@ -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'],
}

View File

@ -1,97 +1,7 @@
<?php <?php
/** @var array $_ */ /** @var array $_ */
/** @var \OCP\IL10N $l */ /** @var \OCP\IL10N $l */
script('registration', 'settings'); script('registration', 'registration-settings');
style('registration', 'settings'); style('registration', 'settings');
?> ?>
<form id="registration_settings_form" class="section"> <div id="registration_settings_form"></div>
<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>

12
webpack.js Normal file
View File

@ -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)