MOBILE-4400 signup: Check extendedusernamechars setting
parent
5ef95b611f
commit
ae79dc9d27
|
@ -2092,6 +2092,7 @@
|
|||
"core.login.invalidsite": "local_moodlemobileapp",
|
||||
"core.login.invalidtime": "local_moodlemobileapp",
|
||||
"core.login.invalidurl": "scorm",
|
||||
"core.login.invalidusername": "moodle",
|
||||
"core.login.invalidvaluemax": "local_moodlemobileapp",
|
||||
"core.login.invalidvaluemin": "local_moodlemobileapp",
|
||||
"core.login.login": "moodle",
|
||||
|
@ -2155,6 +2156,7 @@
|
|||
"core.login.supplyinfo": "moodle",
|
||||
"core.login.toggleremove": "local_moodlemobileapp",
|
||||
"core.login.username": "moodle",
|
||||
"core.login.usernamelowercase": "moodle",
|
||||
"core.login.usernameoremail": "moodle",
|
||||
"core.login.usernamerequired": "local_moodlemobileapp",
|
||||
"core.login.usernotaddederror": "error",
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
<ng-container *ngIf="control && control.dirty && !control.valid">
|
||||
<ng-container *ngFor="let error of errorKeys">
|
||||
<div *ngIf="control.hasError(error)" class="core-input-error">
|
||||
<span *ngIf="errorMessages && errorMessages[error]">{{ errorMessages[error] | translate }}</span>
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error === 'max' && control.errors?.max">
|
||||
{{ 'core.login.invalidvaluemax' | translate:{$a: control.errors!.max.max} }}
|
||||
</span>
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error === 'min' && control.errors?.min">
|
||||
{{ 'core.login.invalidvaluemin' | translate:{$a: control.errors!.min.min} }}
|
||||
</span>
|
||||
<ng-container *ngIf="error !== 'pattern'">
|
||||
<span *ngIf="errorMessages && errorMessages[error]">{{ errorMessages[error] | translate }}</span>
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error === 'max' && control.errors?.max">
|
||||
{{ 'core.login.invalidvaluemax' | translate:{$a: control.errors!.max.max} }}
|
||||
</span>
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error === 'min' && control.errors?.min">
|
||||
{{ 'core.login.invalidvaluemin' | translate:{$a: control.errors!.min.min} }}
|
||||
</span>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="error === 'pattern' && getPatternErrorMessage() as errorMessage">
|
||||
<span>{{ errorMessage | translate }}</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
|
|
@ -41,7 +41,7 @@ import { FormControl } from '@angular/forms';
|
|||
export class CoreInputErrorsComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input() control?: FormControl<unknown>; // Needed to be able to check the validity of the input.
|
||||
@Input() errorMessages: Record<string, string> = {}; // Error messages to show. Keys must be the name of the error.
|
||||
@Input() errorMessages: CoreInputErrorsMessages = {}; // Error messages to show. Keys must be the name of the error.
|
||||
@Input() errorText = ''; // Set other non automatic errors.
|
||||
errorKeys: string[] = [];
|
||||
|
||||
|
@ -124,4 +124,44 @@ export class CoreInputErrorsComponent implements OnInit, OnChanges {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error message for pattern error.
|
||||
*
|
||||
* @returns Error message, undefined if not found.
|
||||
*/
|
||||
getPatternErrorMessage(): string | undefined {
|
||||
const patternError = this.control?.errors?.pattern;
|
||||
if (!this.errorMessages?.pattern || !patternError) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.errorMessages.pattern === 'string') {
|
||||
return this.errorMessages.pattern;
|
||||
}
|
||||
|
||||
return this.errorMessages.pattern[patternError.requiredPattern];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Error messages for each type of error.
|
||||
* Error messages will be translated in the template, they don't need to be translated already.
|
||||
*/
|
||||
export type CoreInputErrorsMessages = {
|
||||
required?: string;
|
||||
requiredTrue?: string;
|
||||
email?: string;
|
||||
date?: string;
|
||||
datetime?: string;
|
||||
datetimelocal?: string;
|
||||
time?: string;
|
||||
url?: string;
|
||||
max?: string;
|
||||
min?: string;
|
||||
maxlength?: string;
|
||||
minlength?: string;
|
||||
// For pattern errors you can define an error for all patterns (string), or one error per pattern.
|
||||
// In the latter case, the key of the object is the pattern and the value is the error message identifier.
|
||||
pattern?: string | Record<string,string>;
|
||||
};
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"invalidsite": "The site URL is not valid.",
|
||||
"invalidtime": "Time not valid",
|
||||
"invalidurl": "Invalid URL specified",
|
||||
"invalidusername": "The username can only contain alphanumeric lowercase characters (letters and numbers), underscore (_), hyphen (-), period (.) or at symbol (@).",
|
||||
"invalidvaluemax": "The maximum value is {{$a}}",
|
||||
"invalidvaluemin": "The minimum value is {{$a}}",
|
||||
"login": "Log in",
|
||||
|
@ -125,6 +126,7 @@
|
|||
"supplyinfo": "More details",
|
||||
"toggleremove": "Edit accounts list",
|
||||
"username": "Username",
|
||||
"usernamelowercase": "Only lowercase letters allowed",
|
||||
"usernameoremail": "Enter either username or email address",
|
||||
"usernamerequired": "Username required",
|
||||
"usernotaddederror": "User not added - error",
|
||||
|
|
|
@ -35,6 +35,7 @@ import { CorePath } from '@singletons/path';
|
|||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreSitesFactory } from '@services/sites-factory';
|
||||
import { EMAIL_SIGNUP_FEATURE_NAME } from '@features/login/constants';
|
||||
import { CoreInputErrorsMessages } from '@components/input-errors/input-errors';
|
||||
|
||||
/**
|
||||
* Page to signup using email.
|
||||
|
@ -46,6 +47,10 @@ import { EMAIL_SIGNUP_FEATURE_NAME } from '@features/login/constants';
|
|||
})
|
||||
export class CoreLoginEmailSignupPage implements OnInit {
|
||||
|
||||
// Accept A-Z in strict chars pattern to be able to differentiate it from the lowercase pattern.
|
||||
protected static readonly USERNAME_STRICT_CHARS_PATTERN = '^[A-Z-.@_a-z0-9]*$';
|
||||
protected static readonly USERNAME_LOWERCASE_PATTERN = '^[^A-Z]*$';
|
||||
|
||||
@ViewChild(CoreRecaptchaComponent) recaptchaComponent?: CoreRecaptchaComponent;
|
||||
@ViewChild('ageForm') ageFormElement?: ElementRef;
|
||||
@ViewChild('signupFormEl') signupFormElement?: ElementRef;
|
||||
|
@ -77,12 +82,12 @@ export class CoreLoginEmailSignupPage implements OnInit {
|
|||
supportEmail?: string;
|
||||
|
||||
// Validation errors.
|
||||
usernameErrors: Record<string, string>;
|
||||
passwordErrors: Record<string, string>;
|
||||
emailErrors: Record<string, string>;
|
||||
email2Errors: Record<string, string>;
|
||||
policyErrors: Record<string, string>;
|
||||
namefieldsErrors?: Record<string, Record<string, string>>;
|
||||
usernameErrors: CoreInputErrorsMessages;
|
||||
passwordErrors: CoreInputErrorsMessages;
|
||||
emailErrors: CoreInputErrorsMessages;
|
||||
email2Errors: CoreInputErrorsMessages;
|
||||
policyErrors: CoreInputErrorsMessages;
|
||||
namefieldsErrors?: Record<string, CoreInputErrorsMessages>;
|
||||
|
||||
constructor(
|
||||
protected fb: FormBuilder,
|
||||
|
@ -98,14 +103,19 @@ export class CoreLoginEmailSignupPage implements OnInit {
|
|||
|
||||
// Create the signupForm with the basic controls. More controls will be added later.
|
||||
this.signupForm = this.fb.group({
|
||||
username: ['', Validators.required],
|
||||
password: ['', Validators.required],
|
||||
email: ['', Validators.compose([Validators.required, Validators.email])],
|
||||
email2: ['', Validators.compose([Validators.required, Validators.email])],
|
||||
});
|
||||
|
||||
// Setup validation errors.
|
||||
this.usernameErrors = { required: 'core.login.usernamerequired' };
|
||||
this.usernameErrors = {
|
||||
required: 'core.login.usernamerequired',
|
||||
pattern: {
|
||||
[CoreLoginEmailSignupPage.USERNAME_STRICT_CHARS_PATTERN]: 'core.login.invalidusername',
|
||||
[CoreLoginEmailSignupPage.USERNAME_LOWERCASE_PATTERN]: 'core.login.usernamelowercase',
|
||||
},
|
||||
};
|
||||
this.passwordErrors = { required: 'core.login.passwordrequired' };
|
||||
this.emailErrors = { required: 'core.login.missingemail' };
|
||||
this.policyErrors = { required: 'core.login.policyagree' };
|
||||
|
@ -140,6 +150,13 @@ export class CoreLoginEmailSignupPage implements OnInit {
|
|||
* Complete the FormGroup using the settings received from server.
|
||||
*/
|
||||
protected completeFormGroup(): void {
|
||||
const checkStrictChars = this.settings?.extendedusernamechars === false;
|
||||
this.signupForm.addControl('username', this.fb.control('', Validators.compose([
|
||||
Validators.required,
|
||||
Validators.pattern(CoreLoginEmailSignupPage.USERNAME_LOWERCASE_PATTERN),
|
||||
checkStrictChars ? Validators.pattern(CoreLoginEmailSignupPage.USERNAME_STRICT_CHARS_PATTERN) : undefined,
|
||||
])));
|
||||
|
||||
this.signupForm.addControl('city', this.fb.control(this.settings?.defaultcity || ''));
|
||||
this.signUpCountryControl = this.fb.control(this.settings?.country || '', { nonNullable: true });
|
||||
this.signupForm.addControl('country', this.signUpCountryControl);
|
||||
|
|
|
@ -1553,6 +1553,7 @@ export type AuthEmailSignupSettings = {
|
|||
sitepolicyhandler?: string; // Site policy handler.
|
||||
defaultcity?: string; // Default city.
|
||||
country?: string; // Default country.
|
||||
extendedusernamechars?: boolean; // @since 4.4. Extended characters in usernames or no.
|
||||
profilefields?: AuthEmailSignupProfileField[]; // Required profile fields.
|
||||
recaptchapublickey?: string; // Recaptcha public key.
|
||||
recaptchachallengehash?: string; // Recaptcha challenge hash.
|
||||
|
|
|
@ -184,3 +184,44 @@ Feature: Test signup in app
|
|||
And I should find "1 January 2010, 11:45 AM" in the app
|
||||
And I should find "This is my description" in the app
|
||||
And I should find "https://moodle.com" in the app
|
||||
|
||||
@lms_from4.4
|
||||
Scenario: Check extended characters in usernames show error if setting is disabled
|
||||
Given the following config values are set as admin:
|
||||
| extendedusernamechars | 0 |
|
||||
When I launch the app
|
||||
And I set the field "Your site" to "$WWWROOT" in the app
|
||||
And I press "Connect to your site" in the app
|
||||
And I press "Create new account" in the app
|
||||
And I set the following fields to these values in the app:
|
||||
| Username | u1$ |
|
||||
Then I should find "The username can only contain alphanumeric" in the app
|
||||
|
||||
When I set the following fields to these values in the app:
|
||||
| Username | u1 |
|
||||
Then I should not find "The username can only contain alphanumeric" in the app
|
||||
|
||||
@lms_from4.4
|
||||
Scenario: Check can include extended characters in usernames if setting is enabled
|
||||
Given the following config values are set as admin:
|
||||
| extendedusernamechars | 1 |
|
||||
When I launch the app
|
||||
And I set the field "Your site" to "$WWWROOT" in the app
|
||||
And I press "Connect to your site" in the app
|
||||
And I press "Create new account" in the app
|
||||
And I set the following fields to these values in the app:
|
||||
| Username | u1U |
|
||||
Then I should find "Only lowercase letters allowed" in the app
|
||||
|
||||
When I set the following fields to these values in the app:
|
||||
| Username | u1$ |
|
||||
Then I should not find "The username can only contain alphanumeric" in the app
|
||||
|
||||
When I set the following fields to these values in the app:
|
||||
| Password | pu1 |
|
||||
| Email address | u1@u1.com |
|
||||
| Email (again) | u1@u1.com |
|
||||
| First name | User |
|
||||
| Last name | Test |
|
||||
And I press "Create my new account" in the app
|
||||
Then I should find "An email should have been sent to your address" in the app
|
||||
|
|
Loading…
Reference in New Issue