setup Auth component
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { catchError, throwError } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
interface AuthResponseData {
|
interface AuthResponseData {
|
||||||
@@ -10,6 +11,11 @@ interface AuthResponseData {
|
|||||||
expiresIn: string;
|
expiresIn: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TokenData {
|
||||||
|
access_token: string;
|
||||||
|
token_type: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
@@ -19,11 +25,30 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
signup(email: string, password: string) {
|
signup(email: string, password: string) {
|
||||||
return this.http.post<AuthResponseData>('http://localhost:8800/signup',
|
return this.http.post<TokenData>('http://localhost:8800/signup',
|
||||||
{
|
{
|
||||||
email: email,
|
username: email,
|
||||||
password: password,
|
password: password
|
||||||
returnToken: true
|
}
|
||||||
|
).pipe(catchError(errorRes => {
|
||||||
|
let errorMessage = 'An unknown error occurred!';
|
||||||
|
const err = Error(errorMessage);
|
||||||
|
if (!errorRes.error) {
|
||||||
|
return throwError(() => err);
|
||||||
|
}
|
||||||
|
switch(errorRes.statusText) {
|
||||||
|
case 'ERROR':
|
||||||
|
errorMessage = 'Uups...';
|
||||||
|
}
|
||||||
|
return throwError(() => Error(errorMessage));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
login(email: string, password: string) {
|
||||||
|
return this.http.post<TokenData>('http://127.0.0.1:8800/api/login/token',
|
||||||
|
{
|
||||||
|
username: email,
|
||||||
|
password: password
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div style="margin-top: 16px;">
|
<div style="margin-top: 16px;">
|
||||||
<form (ngSubmit)="onSubmit(authForm)" #authForm="ngForm">
|
@if(error) {
|
||||||
<div class="form-group" style="margin-bottom: 7px;">
|
<div class="alert alter-danger">
|
||||||
<label for="email">E-Mail</label>
|
<p>{{ error }}</p>
|
||||||
<input type="email" id="email" class="form-control" ngModel name="email" required email=""/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="margin-bottom: 7px;">
|
}
|
||||||
<label for="password">Password</label>
|
@if(isLoading) {
|
||||||
<input type="password" id="password" class="form-control" ngModel name="password" required/>
|
<div style="text-align: center;">
|
||||||
|
<app-loading-spinner></app-loading-spinner>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
}
|
||||||
<button class="btn btn-primary" type="submit" [disabled]="!authForm.valid">
|
@else {
|
||||||
{{ isLoginMode ? 'Login' : 'Sign Up' }}
|
<form (ngSubmit)="onSubmit(authForm)" #authForm="ngForm">
|
||||||
</button>
|
<div class="form-group" style="margin-bottom: 7px;">
|
||||||
<button class="btn btn-primary" (click)="onSwitchMode()" type="button">
|
<label for="email">E-Mail</label>
|
||||||
Switch to {{ isLoginMode ? 'Sign Up' : 'Login' }}
|
<input type="email" id="email" class="form-control" ngModel name="email" required email=""/>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<div class="form-group" style="margin-bottom: 7px;">
|
||||||
</form>
|
<label for="password">Password</label>
|
||||||
|
<input type="password" id="password" class="form-control" ngModel name="password" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-primary" type="submit" [disabled]="!authForm.valid">
|
||||||
|
{{ isLoginMode ? 'Login' : 'Sign Up' }}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary" (click)="onSwitchMode()" type="button">
|
||||||
|
Switch to {{ isLoginMode ? 'Sign Up' : 'Login' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,54 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { NgForm } from '@angular/forms';
|
import { NgForm } from '@angular/forms';
|
||||||
|
import { AuthService, TokenData } from './auth-service';
|
||||||
|
import { LoadingSpinner } from "../../shared/loading-spinner/loading-spinner";
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-auth',
|
selector: 'app-auth',
|
||||||
imports: [FormsModule],
|
imports: [FormsModule, LoadingSpinner],
|
||||||
templateUrl: './auth.html',
|
templateUrl: './auth.html',
|
||||||
styleUrl: './auth.css'
|
styleUrl: './auth.css'
|
||||||
})
|
})
|
||||||
export class Auth {
|
export class Auth {
|
||||||
isLoginMode = true;
|
isLoginMode = true;
|
||||||
|
isLoading = false;
|
||||||
|
error: string | null = null;
|
||||||
|
|
||||||
|
constructor(private authService: AuthService) {}
|
||||||
|
|
||||||
onSwitchMode() {
|
onSwitchMode() {
|
||||||
this.isLoginMode =!this.isLoginMode;
|
this.isLoginMode =!this.isLoginMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(form: NgForm) {
|
onSubmit(form: NgForm) {
|
||||||
console.log(form.value);
|
if (!form.valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const email = form.value.email;
|
||||||
|
const password = form.value.password;
|
||||||
|
|
||||||
|
let authObservable: Observable<TokenData>;
|
||||||
|
|
||||||
|
this.isLoading = true;
|
||||||
|
if (this.isLoginMode) {
|
||||||
|
authObservable = this.authService.login(email, password);
|
||||||
|
} else {
|
||||||
|
authObservable = this.authService.signup(email, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
authObservable.subscribe(
|
||||||
|
token => {
|
||||||
|
console.log(token);
|
||||||
|
this.isLoading = false;
|
||||||
|
},
|
||||||
|
(err: HttpErrorResponse) => {
|
||||||
|
console.log(err);
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
form.reset();
|
form.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from "@angular/core"
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-loading-spinner',
|
||||||
|
template: '<div class="lds-ring"><div></div><div></div><div></div><div></div></div>',
|
||||||
|
styleUrls: ['./loading.spinner.css']
|
||||||
|
})
|
||||||
|
export class LoadingSpinner {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
.lds-ring,
|
||||||
|
.lds-ring div {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.lds-ring {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.lds-ring div {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
margin: 8px;
|
||||||
|
border: 8px solid currentColor;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
border-color: currentColor transparent transparent transparent;
|
||||||
|
}
|
||||||
|
.lds-ring div:nth-child(1) {
|
||||||
|
animation-delay: -0.45s;
|
||||||
|
}
|
||||||
|
.lds-ring div:nth-child(2) {
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
.lds-ring div:nth-child(3) {
|
||||||
|
animation-delay: -0.15s;
|
||||||
|
}
|
||||||
|
@keyframes lds-ring {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -45,9 +45,7 @@ class OAuth2PasswordBearerWithCookie(OAuth2):
|
|||||||
super().__init__(flows=flows, scheme_name=scheme_name, auto_error=auto_error)
|
super().__init__(flows=flows, scheme_name=scheme_name, auto_error=auto_error)
|
||||||
|
|
||||||
async def __call__(self, request: Request) -> Optional[str]:
|
async def __call__(self, request: Request) -> Optional[str]:
|
||||||
authorization: str = request.cookies.get(
|
authorization: str = request.cookies.get("access_token") # changed to accept access token from httpOnly Cookie
|
||||||
"access_token"
|
|
||||||
) # changed to accept access token from httpOnly Cookie
|
|
||||||
|
|
||||||
scheme, param = get_authorization_scheme_param(authorization)
|
scheme, param = get_authorization_scheme_param(authorization)
|
||||||
if not authorization or scheme.lower() != "bearer":
|
if not authorization or scheme.lower() != "bearer":
|
||||||
|
|||||||
Reference in New Issue
Block a user