How to apply a password policy validation on custom form in drupal 8? - drupal-8

I want to apply password policy module functionality on custom password reset form on drupal 8.
Its not working for my reset form.
Note:
'#type' => 'password_confirm' has set to the form as below,
"#type" => "password_confirm"
"#size" => 25
"#description" => Drupal\Core\StringTranslation\TranslatableMarkup {#1612 ▶}
"#attributes" => array:1 [▶]
]```
still its not working.
And, one point I noticed, Custom form act as Anonymous user.

function hook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id == 'user_pass_reset') {
$form['#validate'][] = '_form_custom_validation';
}
}
//CUSTOM FUNCTION TO CHECK PASSWORD COMPLEXITY
function _form_custom_validation(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
if ($form_state->hasValue('pass')) {
$pass = $form_state->getValue('pass');
$pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[-+_!##$%^&*.,?]).+$";
if (!preg_match('/[a-z]+/', $pass)) {
$form_state->setErrorByName('title', t('Your password must contain Uppercase, lowercase, numeric and special character.'));
}
if (!preg_match('/[A-Z]+/', $pass)) {
$form_state->setErrorByName('title', t('Your password must contain Uppercase, lowercase, numeric and special character.'));
}
if (!preg_match('/[0-9]/', $pass)) {
$form_state->setErrorByName('title', t('Your password must contain Uppercase, lowercase, numeric and special character.'));
}
if (!preg_match('/[\'^£$%&*()}{##~?><>,|=_+¬-]/', $pass)) {
$form_state->setErrorByName('title', t('Your password must contain Uppercase, lowercase, numeric and special character.'));
}
if (strlen($pass) < 8) {
$form_state->setErrorByName('title', t('Your password must contain atleast 8 characters.'));
}
}
}

Related

Laravel Livewire custom validation throws unexpected error "The given data was invalid"

I have a class in which default validation works just fine, but i have additional validation needs. All of the code is working fine including the default validation rules and messages defined in rules and messages function. for the sake of simplicity i'm providing the relevant code only.
The Problem:
In the store method i have a custom validator which should validate the uniquness of custom permission name. The validation rules returns this message "The given data was invalid."
I have tried different scenarios, for example: using different supposed name i.e. "permission_name", I have also tried rules in string instead of array.
$rules = ['permission_name' => 'unique:permissions,name'];
This does'nt work. Can anyone please point me in the right direct what is wrong here. Any help is appreciated in advance.
class CreatePermissionComponent extends Component
{
public $resource_name, $permission_type;
protected $validationAttributes = [
'resource_name' => 'resource name',
'permission_type' => 'permission type',
];
public function store()
{
$this->validate($this->rules(), $this->messages());
DB::beginTransaction();
try
{
// The problem
$input = ['name' => $this->resource_name . '.' . $this->permission_type];
$rules = ['name' => Rule::unique('permissions', 'name')];
$messages = ['name.unique' => 'The permission name ' . $this->resource_name . '.' . $this->permission_type . 'already exists.'];
$validatedData = Validator::make($input, $rules, $messages)->validate();
DB::commit();
ToasterHelperLivewire::toasterSuccess($this, $this->notifyMessage . ' Created Successfully.');
}
catch (\Exception $exception)
{
DB::rollback();
ToasterHelperLivewire::toasterErrorShort($this, $exception->getMessage());
}
}
public function updated($key, $value)
{
$this->validateOnly($key, $this->rules(), $this->messages());
}
protected function rules()
{
$rules = [
'resource_name' => ['required', 'alpha', 'min:3', 'max:50'],
];
if($this->permission_mode == 'single')
{
$rules['permission_type'] = ['required'];
}
else
{
$rules['permission_resource'] = ['min:1', 'array'];
}
return $rules;
}
protected function messages()
{
return [
'resource_name.alpha' => ':attribute may only contain alphabet and must be in this format. ex: users',
'permission_resource.min' => 'Please select at-least on checkbox from :attribute.',
];
}
}

How to accept comma-separated values in regex pattern Angular

I have a textarea component which accepts these regex patterns:
UserExamble.com,user#,#examble.com,#examble.com
Now i have implemented all above patterns but in textarea, there are supposed to be multiple values seperated by comma, for ex. UserExamble.com,user# or UserExamble.com,user#,#examble.com,#examble.com. This is what i am not able to implement, how can i do this?
Below is my code:
this.userPolicyForm = this.fb.group({
senderRadioBtn: ['Any'],
senderEmailaddress: ['', [Validators.required, Validators.pattern(ValidationPatternConfig.userPolicyEmailAddressPattern)]]
});
and
ValidationPatternConfig.userPolicyEmailAddressPattern=
"^(([^<>()\\[\\]\\\\,;:\\s#\\\"]+(\\.[^<>()\\[\\]\\\\,;:\\s#\\\"]+)*)|(\\\".+\\\")){1,64}#(\\[ipv6:){1}(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\]$"
+"|"+
"^[A-Za-z0-9+.!#$%&'*+/=?^_`{|}~-]{1,64}#\\[(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\]$"
+"|"+
"^(([^<>()\\[\\]\\\\,;:\\s#\\\"]+(\\.[^<>()\\[\\]\\\\,;:\\s#\\\"]+)*)|(\\\".+\\\")){1,64}#((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"
+"|"+
"^$|^((?!\\.)[\\w-_.]*[^.])(#\\w+)(\\.\\w+(\\.\\w+)?[^.\\W])$"
+"|"+
"^([a-zA-Z0-9!#$%&'*+\\/=?^_`\\{|\\}~\\-.]*[^#,\\]\\[<>:;\"()])#$"
+"|"+
"^#(([a-zA-Z0-9]*([-a-zA-Z0-9]*[a-zA-Z0-9]*)\\.)+[a-zA-Z0-9]*([-a-zA-Z0-9]*[a-zA-Z0-9]))$"
I am using reactive forms in angular.
I have seen few stackoverflow answers, but none of them work. I am new to angular and regex, need help.
One thing you can do is to create custom email validator
this.userPolicyForm = this.fb.group({
senderRadioBtn: ['Any'],
senderEmailaddress: ['', [Validators.required, CustomValidators.validateEmail()]]
});
Create a new file for custom-validator.ts
import { AbstractControl, FormControl } from '#angular/forms';
export class CustomValidators {
// validating array of emails
static validateEmail() {
return (control: FormControl) => {
const pattern = new RegExp('^([a-z0-9\\+_\\-]+)(\\.[a-z0-9\\+_\\-]+)*#([a-z0-9\\-]+\\.)+[a-z]{2,6}$', 'i');
let validEmail = true;
if (control.value !== null) {
const emails = control.value.replace(/\s/g, '').split(',').filter((mail: any) => mail.trim());
for (const email of emails) {
if (email && !pattern.test(email)) {
validEmail = false;
}
}
}
return validEmail ? null : { invalid_email: true };
};
}
}
In html, you can add
<div *ngIf="userPolicyForm.controls.senderEmailaddress.hasError('invalid_email')">
Email address must be valid
</div>
From this you can validate in reactive form. Also when you are submitting array of emails, you can trim it to send to API.
You can decide on the patterns which you want to pass in your textbox and then create regex in 2 parts, one containing the pattern with a comma at the end and a greedy + and second part with just the pattern
like this:
let pattern = "(?:[A-z0-9]+#[A-z]+\.[A-z]{2,6})|(?:[A-z0-9]+#[A-z]+)|(?:#[A-z0-9]+\.[A-z]{2,6})|(?:[A-z0-9]\.[A-z]{2,6})"
var regexPattern = '/(?:' + pattern + '[,])+' + pattern + '/'
var regex = new RegExp(regexPattern)
console.log("UserExamble.com,user#some.com,#examble.com,run.com", regex.test("UserExamble.com,user#some.com,#examble.com,run.com"))
you can use this single regex to validate the input.

Flutter firebase email/password error handling doesn't check blank fields properly

Hello Flutter newbie here! I have setup the login and error checking part.
I want to do some checking on the fields, but I realize if the user does the following behavior, my code for error checking won't work:
enter some text in email textfield
enter some text in password textfield
backspace delete the text in email textfield
hit the flat button to submit
the code will pass the if checking and go ahead to sign in...
but I thought since the email textfield is empty by the time I hit the button, it should still follow the if checking?
thanks in advance!
FlatButton(
onPressed: () async {
if (password == null && email == null) {
print('empty sign in info');
setState(() {
alertText = 'You have not entered your login info!';
});
} else if (password == null) {
setState(() {
alertText = 'Password cannot be blank!';
});
} else if (email == null) {
setState(() {
alertText = 'Email cannot be blank!';
});
} else {
setState(() {
showSpinner = true;
});
try {
final newUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (newUser != null) {
Navigator.pushNamed(context, ViewScreen.id);
}
} catch (e) {
print(e);
}
}
},
It looks like when the user did not even tap the username or password text fields, the email and password strings are null. But if the user types something (therefore changing the email and password strings) and then erases what he typed, the strings won't be null, they will be equal to the empty string "", which is different from null. Therefore, your control flow will jump straight to the last else you have there, which is not what you want.
Consider adding checks for when email.isEmpty or when password.isEmpty to capture these events, or initializing your email and password strings to "" in the first place. This way you make sure they won't be null, and you just have to replace email == null by email.isEmpty and password == null by password.isEmpty in your code and everything should work fine.

Or statement in Validators.pattern Regex to match 3 out of 4 password rules for password validation in Angular

I am trying to include the following password rules via Validators.pattern in my angular 4 project using regex.
My external stakeholder would like a users password to be valid if it included a lowercase letter, uppercase letter and a Number OR Special character.
Below is the regex I am using, Pattern 1 works fine as does pattern2, however when I try to do the OR of them in pattern3 it does not work.
//passwordPattern1='^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$';// must include numbers
//passwordPattern2='^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[#?!#$%^&*-]).{8,}$';//must include special characters
passwordPattern3='^(((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[A-Z])(?=.*?[#?!#$%^&*-.])))';//Numbers or Special characters
Below is how I add it to my formGroup. see line 3
this.form = this.fb.group({
username: [null, Validators.compose([Validators.required, Validators.minLength(4), Validators.maxLength(20)])],
password: [null, Validators.compose([Validators.required,Validators.minLength(8), Validators.maxLength(128), Validators.pattern(this.passwordPattern3)])],
confirmPassword: [null, Validators.compose([Validators.required, Validators.minLength(8), Validators.maxLength(128)])]
}, {validator: matchingPasswords('password', 'confirmPassword')});
Does anyone know why the third password pattern does not seem to work in angular, and what I could do to make it work?
I tested the REGEX at http://rubular.com/ in passwordPattern3 and it works as desired. Anything I may be missing in Angulars validators.pattern()?
Regarding the security of these requirements- I am aware these rules are not the best approach for the security of a user. For this effort, I, unfortunately, do not have the influence to change the requirements from the external stakeholder. But I am awarewhy such rules may be ineffective
I know this answer doesn't use RegEx, but you could do this with custom validator functions:
function hasUpperCaseChar(val: string): boolean {
return val.split('')
.reduce((current, next) => current || next === next.toUpperCase(), false);
}
function hasLowerCaseChar(val: string): boolean {
return val.split('')
.reduce((current, next) => current || next === next.toLowerCase(), false);
}
function moreThanOneInteger(val: string): boolean {
return val.split('')
.reduce((current, next) => current || !isNaN(parseInt(next)), false);
}
function moreThanOneSpecialCharacter(val: string): boolean {
return val.split('')
.reduce((current, next) => current || '#?!#$%^&*-'.split('').includes(next), false);
}
// In another function file (e.g. MY_CUSTOM_VALIDATORS)
export const MY_VALIDATORS: any = {
password: {
gtOneInteger: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneInteger(control.value)
? null
: { gtOneInteger: false };
},
gtOneSpecialChar: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneSpecialCharacter(control.value)
? null
: { gtOneSpecialChar: false };
},
gtOneIntegerOrSpecialChar: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneInteger(control.value) && moreThanOneSpecialCharacter(control.value)
? null
: { gtOneIntegerOrSpecialChar: false };
}
}
};
// Updated your current functionality:
this.form = this.fb.group(
{
// The Validators.compose() function is not necessary with Angular 4+.
username: [null, [Validators.required, Validators.minLength(4), Validators.maxLength(20)]],
// Your previous validation:
// password: [null, [Validators.required,Validators.minLength(8), Validators.maxLength(128), Validators.pattern(this.passwordPattern3)]],
// New validation (you can use any of the ones defined above):
password: [null, [Validators.required, Validators.minLength(8), Validators.maxLength(128), MY_VALIDATORS.gtOneIntegerOrSpecialChar]]
confirmPassword: [null, [Validators.required, Validators.minLength(8), Validators.maxLength(128)]]
},
{
validator: matchingPasswords('password', 'confirmPassword')
}
);

Multiple email validation using ko.observable

I'm new to the durandal application. Currently i was trying to validate the multiple email readed from the text area.
<textarea class="fullWidth" id="AddEmailSeparatedByComma" rows="3"
data-bind="value:emailList"></textarea>
I have readed multiple email seperated by "," and i was storing in
emailList = ko.observable("").extend({
email: { message: "Please enter valid email address", params: true }
});
I have provided validation message as above. Currently it is validating one email only, i don't know how to use customized regex here to validate multiple email which is separated by comma. Any help will be much appreciated.
Add another validation rule:
ko.validation.rules['emaillist'] = {
validator: function (val, validate) {
if (!validate) return true;
if (ko.validation.utils.isEmptyVal(val)) return true;
var emailrule = ko.validation.rules['email'];
var vals = val.split(/\s*,\s*/);
for (var i = 0; i < vals.length; i++) {
if (!emailrule.validator(vals[i], true)) {
return false;
}
}
return true;
},
message: 'Please enter proper comma-separated email addresses'
};
ko.validation.addExtender('emaillist');
Fiddle