Skip to content

Commit

Permalink
Merge pull request #5 from jaganbishoyi/feature
Browse files Browse the repository at this point in the history
Feature
  • Loading branch information
jaganbishoyi authored Jan 1, 2021
2 parents e5679f6 + 81fbc42 commit 3aa8314
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 84 deletions.
6 changes: 3 additions & 3 deletions ngx-password-validator/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ngx-password-validator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-password-validator",
"version": "0.0.4",
"version": "0.0.5",
"scripts": {
"ng": "ng",
"start": "ng serve",
Expand All @@ -23,7 +23,7 @@
"@angular/platform-browser": "~9.0.6",
"@angular/platform-browser-dynamic": "~9.0.6",
"@angular/router": "~9.0.6",
"ng-password-validator": "0.0.3",
"ng-password-validator": "0.0.4",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
Expand Down
19 changes: 18 additions & 1 deletion ngx-password-validator/projects/ng-password-validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,27 @@ You may pass as an object:
<input type="text" id="password" name="password" placeholder="Password.."
NgPasswordValidator [options]="myOptions">
```
Password type as 'range':
```ts
myOptions = {
'placement': 'top',
'password': {
'type': "range";
'min': 6;
'max': 10;
},
'shadow': false,
'offset': 15,
}
```
Password type as 'number':
```ts
myOptions = {
'placement': 'top',
'password': {
'type': "number";
'length': 8;
},
'shadow': false,
'offset': 15,
}
Expand All @@ -67,7 +85,6 @@ import { NgPasswordValidatorModule, NgPasswordValidatorOptions } from "ng-passwo
export const MyDefaultOptions: NgPasswordValidatorOptions = {
placement: "right",
rules: {
"password-length": 10,
"include-symbol": true,
"include-number": true,
"include-lowercase-characters": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng-password-validator",
"version": "0.0.4",
"version": "0.0.5",
"description": "The password validator is a pop-up window that appears when you start typing in input box. Here you can configure the password acceptance criteria, once your enter characters fullfil the requirement you will get a success message.",
"author": "Jagan Mohan Bishoyi",
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
<div class="popup-window">
<div class="heading">Password Requirement</div>
<div class="rule" [hidden]="!rules['password-length']"
[ngClass]="{'rule-pass':passwordStatus.passwordLength}">
Password length should be {{rules['password-length']}}.
<div *ngIf="rules['password']">
<div class="rule" [hidden]="rules['password'].type !== 'number'"
[ngClass]="{'rule-pass':passwordStatus['password']}">
Password length should be {{rules['password'].length}} characters.
</div>
<div class="rule" [hidden]="rules['password'].type !== 'range'"
[ngClass]="{'rule-pass':passwordStatus['password']}">
Password length should be {{rules['password'].min}} - {{rules['password'].max}}
characters.
</div>
</div>
<div class="rule" [hidden]="!rules['include-symbol']"
[ngClass]="{'rule-pass':passwordStatus.includeSymbol}">
[ngClass]="{'rule-pass':passwordStatus['include-symbol']}">
Include Symbols:( e.g. @#$% )
</div>
<div class="rule" [hidden]="!rules['include-number']"
[ngClass]="{'rule-pass':passwordStatus.includeNumber}">
[ngClass]="{'rule-pass':passwordStatus['include-number']}">
Include Numbers:( e.g.123456 )
</div>
<div class="rule" [hidden]="!rules['include-lowercase-characters']"
[ngClass]="{'rule-pass':passwordStatus.includeLowercaseCharacters}">
[ngClass]="{'rule-pass':passwordStatus['include-lowercase-characters']}">
Include Lowercase Characters:(e.g. abcdefgh )
</div>
<div class="rule" [hidden]="!rules['include-uppercase-characters']"
[ngClass]="{'rule-pass':passwordStatus.includeUppercaseCharacters}">
[ngClass]="{'rule-pass':passwordStatus['include-uppercase-characters']}">
Include Uppercase Characters:(e.g. ABCDEFGH )
</div>
<div class="success-message" [hidden]="!isSecure">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,25 @@ import {

import { DataService } from "./data.service";
import { IElementPosition, IRules, IStatus, NgPasswordValidatorOptions } from "./ng-password-validator.interface";
import { defaultOptions } from "./options";
@Component({
// tslint:disable-next-line: component-selector
selector: "NgPasswordValidator",
templateUrl: "./ng-password-validator.component.html",
// tslint:disable-next-line: no-host-metadata-property
host: { class: "popup" },
styleUrls: ["./ng-password-validator.component.scss"]
})
export class NgPasswordValidatorComponent implements OnInit {
passwordStatus = {
passwordLength: false,
includeSymbol: false,
includeNumber: false,
includeLowercaseCharacters: false,
includeUppercaseCharacters: false,
"password": false,
"include-symbol": false,
"include-number": false,
"include-lowercase-characters": false,
"include-uppercase-characters": false,
};
isSecure = false;
Show = false;
events = new EventEmitter();
passwordOptions: NgPasswordValidatorOptions = defaultOptions;

@Input() data: any;

Expand Down Expand Up @@ -72,7 +72,6 @@ export class NgPasswordValidatorComponent implements OnInit {
return this.data.options.placement;
}

// tslint:disable-next-line: typedef
get element() {
return this.data.element;
}
Expand Down Expand Up @@ -109,6 +108,11 @@ export class NgPasswordValidatorComponent implements OnInit {
this.setStyles();
this.dataService.updatedValue.subscribe((data: IStatus) => {
this.passwordStatus = { ... this.passwordStatus, ...data };
for (const propName in this.passwordOptions.rules) {
if (!this.passwordOptions.rules[propName]) {
delete this.passwordStatus[propName];
}
}
this.isSecure = Object.values(this.passwordStatus).every((value: boolean) => value);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ export interface HostComponent {
}

@Directive({
// tslint:disable-next-line: directive-selector
selector: "[NgPasswordValidator]",
exportAs: "NgPasswordValidator",
})

export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
regExpForLength = /^(.){6}$/;
regExpForLength = /^(.){8}$/;
regExpForOneUpper = /^(?=.*[A-Z])(.*)$/;
regExpForOneLower = /^(?=.*[a-z])(.*)$/;
regExpForOneDigit = /^(?=.*[0-9])(.*)$/;
Expand All @@ -41,8 +40,33 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {

@Input("options") set options(value: NgPasswordValidatorOptions) {
if (value && defaultOptions) {
this.passwordOptions = value;
this.regExpForLength = new RegExp("^(.){" + this.passwordOptions.rules["password-length"] + "}$");

// Merge a `source` object to a `target` recursively
const merge = (target: NgPasswordValidatorOptions, source: NgPasswordValidatorOptions): NgPasswordValidatorOptions => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (const key of Object.keys(source)) {
if (source[key] instanceof Object) { Object.assign(source[key], merge(target[key], source[key])); }
}

// Join `target` and modified `source`
Object.assign(target || {}, source);

return target;
};

this.passwordOptions = merge(defaultOptions, value);
if (this.passwordOptions.rules.password) {
switch (this.passwordOptions.rules["password"].type) {
case "number":
this.regExpForLength = new RegExp(`^(.){${this.passwordOptions.rules["password"].length}}$`);
break;

case "range":
this.regExpForLength =
new RegExp(`^(.){${this.passwordOptions.rules["password"].min},${this.passwordOptions.rules["password"].max}}$`);
}
}

}
}
@Input("NgPasswordValidator") popup: string;
Expand Down Expand Up @@ -155,13 +179,18 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
*/
checkPassword(inputValue: string): void {
const data = {
passwordLength: inputValue.match(this.regExpForLength) ? true : false,
includeSymbol: inputValue.match(this.regExpForSpecialCharacters) ? true : false,
includeNumber: inputValue.match(this.regExpForOneDigit) ? true : false,
includeLowercaseCharacters: inputValue.match(this.regExpForOneLower) ? true : false,
includeUppercaseCharacters: inputValue.match(this.regExpForOneUpper) ? true : false,
password: inputValue.match(this.regExpForLength) ? true : false,
"include-symbol": inputValue.match(this.regExpForSpecialCharacters) ? true : false,
"include-number": inputValue.match(this.regExpForOneDigit) ? true : false,
"include-lowercase-characters": inputValue.match(this.regExpForOneLower) ? true : false,
"include-uppercase-characters": inputValue.match(this.regExpForOneUpper) ? true : false,
};

for (const propName in this.passwordOptions.rules) {
if (!this.passwordOptions.rules[propName]) {
delete data[propName];
}
}
this.isValid = Object.values(data).every((value: boolean) => value);
this.dataService.updateValue(data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ export interface IElementPosition {
}

export interface IRules {
"password-length"?: number | boolean;
"password"?: false | IPassword;
"include-symbol"?: boolean;
"include-number"?: boolean;
"include-lowercase-characters"?: boolean;
"include-uppercase-characters"?: boolean;
}

export interface IStatus {
passwordLength: boolean;
includeSymbol: boolean;
includeNumber: boolean;
includeLowercaseCharacters: boolean;
includeUppercaseCharacters: boolean;
"password": boolean;
"include-symbol": boolean;
"include-number": boolean;
"include-lowercase-characters": boolean;
"include-uppercase-characters": boolean;
}
export interface IPassword {
type?: "number" | "range";
length?: number;
min?: number;
max?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ export const defaultOptions: NgPasswordValidatorOptions = {
theme: "basic",
offset: 8,
rules: {
"password-length": 8,
password: {
type: "range",
length: 8,
min: 6,
max: 10,
},
"include-symbol": true,
"include-number": true,
"include-lowercase-characters": true,
Expand All @@ -17,9 +22,9 @@ export const defaultOptions: NgPasswordValidatorOptions = {
};

export const initializeStage: IStatus = {
passwordLength: false,
includeSymbol: false,
includeNumber: false,
includeLowercaseCharacters: false,
includeUppercaseCharacters: false,
password: false,
"include-symbol": false,
"include-number": false,
"include-lowercase-characters": false,
"include-uppercase-characters": false,
};
10 changes: 4 additions & 6 deletions ngx-password-validator/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";

const routes: Routes = [];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
61 changes: 31 additions & 30 deletions ngx-password-validator/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { async, TestBed } from "@angular/core/testing";
import { RouterTestingModule } from "@angular/router/testing";

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
import { AppComponent } from "./app.component";

it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
describe("AppComponent", () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));

it(`should have as title 'ngx-password-validator'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('ngx-password-validator');
});
it("should create the app", () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});

it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('ngx-password-validator app is running!');
});
it(`should have as title 'ngx-password-validator'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual("ngx-password-validator");
});

it("should render title", () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector(".content span").textContent).toContain("ngx-password-validator app is running!");
});
});
Loading

0 comments on commit 3aa8314

Please sign in to comment.