From d1ff89fb19dafc50e03c63f54f0f57aa14c302d5 Mon Sep 17 00:00:00 2001 From: Derek Holloway Date: Thu, 19 Jun 2025 21:34:33 -0700 Subject: [PATCH] Use www-form instead of json for DTO --- .../forgotpassword.component.html | 2 +- .../forgotpassword.component.ts | 40 ++++++++---- .../pages/account/login/login.component.html | 6 +- .../pages/account/login/login.component.ts | 19 +++--- .../pages/account/logout/logout.component.ts | 1 - .../account/register/register.component.html | 12 ++-- .../account/register/register.component.ts | 62 +++++++++++++------ .../src/app/services/Authentication.ts | 17 +++-- 8 files changed, 101 insertions(+), 58 deletions(-) diff --git a/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.html b/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.html index 84a165e..b13666d 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.html +++ b/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.html @@ -1,7 +1,7 @@
- +
diff --git a/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.ts b/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.ts index e665d4a..681f987 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.ts +++ b/src/MistoxWebsite.Client/src/app/pages/account/forgotpassword/forgotpassword.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { FormsModule } from '@angular/forms'; import { Router, ActivatedRoute } from '@angular/router'; import { Account } from '../../../models/Account'; @@ -12,7 +12,7 @@ import { CommonModule } from '@angular/common'; imports: [ FormsModule, CommonModule ] }) export class ForgotPasswordComponent { - user!: Account; + email: string = ""; errorMsgs: string[] = []; returnURL: string = '/'; @@ -23,21 +23,35 @@ export class ForgotPasswordComponent { }); } + sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + onSubmit() { + // Clear errors this.errorMsgs = []; + + // Send to server and wait for response this.errorMsgs.push("Waiting for login response from server"); - this.http.post( "api/account/sendresetpassword", this.user, { responseType: 'json' } ).subscribe({ - next: data => { - if (data.error.length === 0){ - this.router.navigate([this.returnURL]); - }else{ - this.errorMsgs = []; - this.errorMsgs.push(data.error); + const body = new HttpParams() + .set("Email", this.email) + const headers = new HttpHeaders({ + 'Content-Type': 'application/x-www-form-urlencoded' + }); + this.http.post( "https://mistox.com/api/account/sendresetpassword", body, { headers } ).subscribe({ + next: async (data) => { + if (data.error.length === 0){ + this.errorMsgs = ["Reset password send"]; + await this.sleep(3000); + this.router.navigate([this.returnURL]); + }else{ + this.errorMsgs = []; + this.errorMsgs.push(data.error); + } + }, + error: err => { + console.log("HTTP Error Signing In: ", err); } - }, - error: err => { - this.errorMsgs.push("HTTP Error: ", err); - } }); } } \ No newline at end of file diff --git a/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.html b/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.html index 382a60b..b597317 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.html +++ b/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.html @@ -2,12 +2,12 @@

Login

- +
- +
@@ -19,7 +19,7 @@
Stay Logged In - +
Forgot Password diff --git a/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.ts b/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.ts index 217601f..845e077 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.ts +++ b/src/MistoxWebsite.Client/src/app/pages/account/login/login.component.ts @@ -14,7 +14,9 @@ import { Authentication, SessionType } from '../../../services/Authentication'; standalone: true }) export class LoginComponent { - user: Account = { id: -1, userName: "", email: "", passwordHash: "", emailVerified: false, error: "", siteData: { accountID: -1, failedPasswordLock: false, passwordAttempts: 0, role: "", currentPasswordAttempts: 0, emailToken: "" } }; + UserName: string = ""; + Password: string = ""; + StayLoggedIn: boolean = false; errorMsgs: string[] = []; returnURL: string = '/'; @@ -28,26 +30,21 @@ export class LoginComponent { onSubmit() { this.errorMsgs = []; - if (!this.user.userName) { + if (!this.UserName) { this.errorMsgs.push("The 'username' field is required"); } - if (!this.user.passwordHash) { + if (!this.Password) { this.errorMsgs.push("The 'password' field is required"); } - if (this.user.passwordHash.length < 6) { + if (this.Password.length < 6) { this.errorMsgs.push("Password must be at least 6 Characters long"); } if (this.errorMsgs.length > 0) { return; } - let sType: SessionType = SessionType.Session; - if( this.user.emailVerified ){ - sType = SessionType.Forever; - } - - this.errorMsgs.push("Waiting for login response from server"); - this.auth.Login(this.user, sType).subscribe( + this.errorMsgs.push("Waiting for response from server"); + this.auth.Login(this.UserName, this.Password, this.StayLoggedIn).subscribe( data => { if (data.error.length === 0){ this.router.navigate([this.returnURL]); diff --git a/src/MistoxWebsite.Client/src/app/pages/account/logout/logout.component.ts b/src/MistoxWebsite.Client/src/app/pages/account/logout/logout.component.ts index 824a27a..2c5557e 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/logout/logout.component.ts +++ b/src/MistoxWebsite.Client/src/app/pages/account/logout/logout.component.ts @@ -14,7 +14,6 @@ import { Authentication } from '../../../services/Authentication'; standalone: true }) export class LogoutComponent { - user: Account = { id: -1, userName: "", email: "", passwordHash: "", emailVerified: false, error: "", siteData: { accountID: -1, failedPasswordLock: false, passwordAttempts: 0, role: "", currentPasswordAttempts: 0, emailToken: "" } }; errorMsgs: string[] = []; returnURL: string = '/'; diff --git a/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.html b/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.html index 93c6669..636a68e 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.html +++ b/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.html @@ -2,28 +2,28 @@

Register

- +
- +
- +
- - + +
- +
diff --git a/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.ts b/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.ts index 39c5749..d272116 100644 --- a/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.ts +++ b/src/MistoxWebsite.Client/src/app/pages/account/register/register.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { FormsModule } from '@angular/forms'; import { Router, ActivatedRoute } from '@angular/router'; import { Account } from '../../../models/Account'; @@ -12,7 +12,12 @@ import { CommonModule } from '@angular/common'; imports: [ FormsModule, CommonModule ] }) export class RegisterComponent { - user!: Account; + userName: string = "" + email: string = ""; + passwordHash: string = ""; + passwordHash2: string = ""; + error: string = ""; + errorMsgs: string[] = []; returnURL: string = '/'; @@ -23,39 +28,58 @@ export class RegisterComponent { }); } + sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + onSubmit() { + // Clear errors this.errorMsgs = []; - if (!this.user.userName) { + // Validate data + const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; + if (!regex.test(this.email)){ + this.errorMsgs.push("A valid email is required"); + } + if (!this.userName) { this.errorMsgs.push("The 'username' field is required"); } - if (!this.user.passwordHash) { + if (!this.passwordHash) { this.errorMsgs.push("The 'password' field is required"); } - if (this.user.passwordHash.length < 6) { + if (this.passwordHash.length < 6) { this.errorMsgs.push("Password must be at least 6 Characters long"); } - if (this.user.passwordHash !== this.user.error){ + if (this.passwordHash !== this.passwordHash2){ this.errorMsgs.push("Passwords don't match"); } if (this.errorMsgs.length > 0) { return; } - this.user.error = ""; - this.errorMsgs.push("Waiting for login response from server"); - this.http.post( "api/account/register", this.user, { responseType: 'json' } ).subscribe({ - next: data => { - if (data.error.length === 0){ - this.router.navigate([this.returnURL]); - }else{ - this.errorMsgs = []; - this.errorMsgs.push(data.error); + // Send to server and wait for response + this.errorMsgs.push("Waiting for response from server"); + const body = new HttpParams() + .set("Email", this.email) + .set("UserName", this.userName) + .set("PasswordHash", this.passwordHash); + const headers = new HttpHeaders({ + 'Content-Type': 'application/x-www-form-urlencoded' + }); + this.http.post( "https://mistox.com/api/account/register", body, { headers } ).subscribe({ + next: async (data) => { + if (data.error.length === 0){ + this.errorMsgs = ["Account Created"]; + await this.sleep(3000); + this.router.navigate([this.returnURL]); + }else{ + this.errorMsgs = []; + this.errorMsgs.push(data.error); + } + }, + error: err => { + console.log("HTTP Error Signing In: ", err); } - }, - error: err => { - this.errorMsgs.push("HTTP Error: ", err); - } }); } } \ No newline at end of file diff --git a/src/MistoxWebsite.Client/src/app/services/Authentication.ts b/src/MistoxWebsite.Client/src/app/services/Authentication.ts index 0672809..01c1a0d 100644 --- a/src/MistoxWebsite.Client/src/app/services/Authentication.ts +++ b/src/MistoxWebsite.Client/src/app/services/Authentication.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core"; import { Account } from "../models/Account"; import { BehaviorSubject, Observable } from "rxjs"; -import { HttpClient } from "@angular/common/http"; +import { HttpClient, HttpHandler, HttpHeaders, HttpParams } from "@angular/common/http"; @Injectable({ providedIn: 'root' }) export class Authentication{ @@ -11,13 +11,22 @@ export class Authentication{ constructor( private http: HttpClient){ } - Login(LoginCredentials: Account, StayLoggedIn :SessionType): Observable { - let sub = this.http.post( "https://mistox.com/api/account/login", LoginCredentials, { responseType: 'json' } ); + Login(UserName: string, Password: string, StayLoggedIn: boolean): Observable { + + const body = new HttpParams() + .set("UserName", UserName) + .set("PasswordHash", Password) + .set("StayLoggedIn", StayLoggedIn ); + const headers = new HttpHeaders({ + 'Content-Type': 'application/x-www-form-urlencoded' + }); + + let sub = this.http.post( "https://mistox.com/api/account/login", body, { headers } ); sub.subscribe({ next: data => { if (data.error.length === 0){ this._user.next(data); - this.setUserToStorage(data, StayLoggedIn); + this.setUserToStorage(data, StayLoggedIn == true ? SessionType.Forever : SessionType.Session); } }, error: err => {