import {Component, ElementRef, ViewChild} from '@angular/core'; import {UsersService} from '../../services/users.service'; import {Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; import {ToastsService, ToastType} from '../../services/toasts.service'; import {AuthService} from '../../services/auth.service'; class PasswordRequirements { sixLong: {title: string, value: boolean} = {title: 'Is 6 characters or longer' , value: false} lowercase: {title: string, value: boolean} = {title: 'Includes lowercase letter' , value: false} uppercase: {title: string, value: boolean} = {title: 'Includes uppercase letter' , value: false} number: {title: string, value: boolean} = {title: 'Includes number' , value: false} symbol: {title: string, value: boolean} = {title: 'Includes symbol' , value: false} } @Component({ selector: 'app-signup', standalone: false, templateUrl: './signup.component.html', styleUrl: './signup.component.css' }) export class SignupComponent { protected passwordStatusText = new BehaviorSubject("") protected passwordsMatch = new BehaviorSubject(false) protected usernameStatusText = new BehaviorSubject("") protected passwordStrongEnough = new BehaviorSubject(false) protected ableToCreateAccount = new BehaviorSubject(false) protected passwordRequirements: PasswordRequirements = new PasswordRequirements() protected strength = new BehaviorSubject(0) @ViewChild("username") usernameInput!: ElementRef constructor( protected usersService: UsersService, protected router: Router, protected toastService: ToastsService, protected authService: AuthService ) {} signup(username: string | null, password: string | null) { console.log(`attempting to sign up with ${username} ${password}`) if (!username || !password) { return; } this.usersService.createUser(username, password).then(() => { // let action = {label: 'Proceed to login', onAction: () => this.router.navigate(["/login"])} this.toastService.sendToast(ToastType.INFO, "Account successfully created") this.authService.login(username, password) this.router.navigate(["/"]) }).catch(ex => { this.toastService.sendToast(ToastType.ERROR, "Unable to create account: " + friendlyHttpStatus[ex.status]) console.log(ex) }) } validate(username: string, passConfirm:string, password: string) { this.passwordsMatch.next(false) this.usernameInput.nativeElement.setAttribute("style", "") this.checkPasswordStrength(password); if (username === "") { this.usernameInput.nativeElement.setAttribute("style", "border-color: #ff0000") } if (passConfirm && password === passConfirm) { this.passwordsMatch.next(true) } this.ableToCreateAccount.next(this.passwordStrongEnough.getValue() && password === passConfirm && !!username) } checkPasswordStrength(password: string) { this.strength.next(0) this.passwordRequirements = new PasswordRequirements() this.passwordStrongEnough.next(false) if (password.match(/[^!-~]/g)) { this.passwordStatusText.next("Invalid characters") return } if (password.length > 6) { this.passwordRequirements.sixLong.value = true } if (password.match(/[a-z]/g)) { this.passwordRequirements.lowercase.value = true } if (password.match(/[A-Z]/g)) { this.passwordRequirements.uppercase.value = true } if (password.match(/[0-9]/g)) { this.passwordRequirements.number.value = true } if (password.match(/[^A-Za-z0-9]/g)) { this.passwordRequirements.symbol.value = true } let strength = 0 Object.values(this.passwordRequirements).forEach(k => { k.value && strength++ }) if (strength >= 5) { this.passwordStrongEnough.next(true) this.passwordStatusText.next("") } else if (strength == 0) { this.passwordStatusText.next("") } this.strength.next(strength) } getColor() { return `rgba(${(this.strength.getValue()/7) * 255}, ${255 - (this.strength.getValue()/7) * 255}, 0)` } protected readonly length = length; protected readonly Object = Object; } let friendlyHttpStatus: {[key: number]: string} = { 200: 'OK', 201: 'Created', 202: 'Accepted', 203: 'Non-Authoritative Information', 204: 'No Content', 205: 'Reset Content', 206: 'Partial Content', 300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found', 303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy', 306: 'Unused', 307: 'Temporary Redirect', 400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden', 404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable', 407: 'Proxy Authentication Required', 408: 'Request Timeout', 409: 'Conflict', 410: 'Gone', 411: 'Length Required', 412: 'Precondition Required', 413: 'Request Entry Too Large', 414: 'Request-URI Too Long', 415: 'Unsupported Media Type', 416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed', 418: 'I\'m a teapot', 429: 'Too Many Requests', 500: 'Internal Server Error', 501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout', 505: 'HTTP Version Not Supported', };