migrating most FastenAPI logic to FastenDB class.

Update the User object to be just username and password.
This commit is contained in:
Jason Kulatunga 2022-10-08 20:40:15 -07:00
parent f2bb44e8be
commit c209ce681c
11 changed files with 45 additions and 110 deletions

View File

@ -18,7 +18,6 @@ import { AuthSignupComponent } from './pages/auth-signup/auth-signup.component';
import { AuthSigninComponent } from './pages/auth-signin/auth-signin.component';
import { FormsModule } from '@angular/forms';
import { NgxDropzoneModule } from 'ngx-dropzone';
import { AuthInterceptorService } from './services/auth-interceptor.service';
import { CanActivateAuthGuard } from './services/can-activate.auth-guard';
import {FastenApiService} from './services/fasten-api.service';
import {FastenDbService} from './services/fasten-db.service';
@ -52,12 +51,6 @@ import { HighlightModule, HIGHLIGHT_OPTIONS } from 'ngx-highlightjs';
HighlightModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptorService,
multi: true,
deps: [FastenApiService, Router]
},
CanActivateAuthGuard,
{
provide: HIGHLIGHT_OPTIONS,

View File

@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import {FastenApiService} from '../../services/fasten-api.service';
import {FastenDbService} from '../../services/fasten-db.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-header',
@ -8,7 +8,7 @@ import { Router } from '@angular/router';
})
export class HeaderComponent implements OnInit {
constructor(private fastenApi: FastenApiService, private router: Router) { }
constructor(private fastenDb: FastenDbService, private router: Router) { }
ngOnInit() {
}
@ -24,7 +24,7 @@ export class HeaderComponent implements OnInit {
}
signOut(e) {
this.fastenApi.logout()
this.router.navigate(['auth/signin']);
this.fastenDb.Logout()
.then(() => this.router.navigate(['auth/signin']))
}
}

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {User} from '../../models/fasten/user';
import {FastenApiService} from '../../services/fasten-api.service';
import {User} from '../../../lib/models/fasten/user';
import {FastenDbService} from '../../services/fasten-db.service';
import {Router} from '@angular/router';
@Component({
@ -13,7 +13,7 @@ export class AuthSigninComponent implements OnInit {
existingUser: User = new User()
errorMsg: string = ""
constructor(private fastenApi: FastenApiService, private router: Router) { }
constructor(private fastenDb: FastenDbService, private router: Router) { }
ngOnInit(): void {
}
@ -21,11 +21,15 @@ export class AuthSigninComponent implements OnInit {
signinSubmit(){
this.submitted = true;
this.fastenApi.signin(this.existingUser.username, this.existingUser.password).subscribe((tokenResp: any) => {
console.log(tokenResp);
this.router.navigateByUrl('/dashboard');
}, (err)=>{
this.errorMsg = err?.error?.error || "an unknown error occurred during sign-in"
})
this.fastenDb.Signin(this.existingUser.username, this.existingUser.password)
.then(() => this.router.navigateByUrl('/dashboard'))
.catch((err)=>{
if(err?.name){
this.errorMsg = "username or password is incorrect"
} else{
this.errorMsg = "an unknown error occurred during sign-in"
}
})
}
}

View File

@ -19,33 +19,17 @@
<h4>Create an account, and get started.</h4>
<form (ngSubmit)="signupSubmit()" #userForm="ngForm">
<div class="form-group">
<label>Firstname &amp; Lastname</label>
<input [(ngModel)]="newUser.name" name="name" #name="ngModel" required minlength="2" type="text" class="form-control" placeholder="Enter your firstname and lastname">
<div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
<div *ngIf="name.errors?.['required']">
Name is required.
</div>
<div *ngIf="name.errors?.['minlength']">
Name must be at least 4 characters long.
</div>
</div>
</div><!-- form-group -->
<div class="form-group">
<label>Email</label>
<input [(ngModel)]="newUser.username" name="username" #username="ngModel" required email="true" minlength="5" type="text" class="form-control" placeholder="Enter your email">
<label>Username</label>
<input [(ngModel)]="newUser.username" name="username" #username="ngModel" required minlength="5" type="text" class="form-control" placeholder="Enter your username">
<div *ngIf="username.invalid && (username.dirty || username.touched)" class="alert alert-danger">
<div *ngIf="username.errors?.['required']">
Email is required.
Username is required.
</div>
<div *ngIf="username.errors?.['minlength']">
Email must be at least 4 characters long.
</div>
<div *ngIf="username.errors?.['email']">
Email is not a valid email address.
Username must be at least 4 characters long.
</div>
</div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {FastenApiService} from '../../services/fasten-api.service';
import {User} from '../../models/fasten/user';
import {FastenDbService} from '../../services/fasten-db.service';
import {User} from '../../../lib/models/fasten/user';
import {Router} from '@angular/router';
@Component({
@ -13,7 +13,11 @@ export class AuthSignupComponent implements OnInit {
newUser: User = new User()
errorMsg: string = ""
constructor(private fastenApi: FastenApiService, private router: Router) { }
constructor(
// private fastenApi: FastenApiService,
private fastenDb: FastenDbService,
private router: Router
) { }
ngOnInit(): void {
}
@ -21,13 +25,21 @@ export class AuthSignupComponent implements OnInit {
signupSubmit(){
this.submitted = true;
this.fastenApi.signup(this.newUser).subscribe((tokenResp: any) => {
this.fastenDb.Signup(this.newUser).then((tokenResp: any) => {
console.log(tokenResp);
this.router.navigateByUrl('/dashboard');
},
(err)=>{
this.errorMsg = err?.error?.error || "an unknown error occurred during sign-up"
console.error("an error occured while signup",err)
if(err.name === 'conflict') {
// "batman" already exists, choose another username
this.errorMsg = "username already exists"
} else if (err.name === 'forbidden') {
// invalid username
this.errorMsg = "invalid username"
} else {
this.errorMsg = "an unknown error occurred during sign-up"
}
})
}

View File

@ -49,7 +49,7 @@ export class DashboardComponent implements OnInit {
// })
// })
forkJoin([this.fastenDb.GetSummary(), this.fastenApi.getMetadataSources()]).subscribe(results => {
forkJoin([this.fastenDb.GetSummary(), this.fastenApi.GetMetadataSources()]).subscribe(results => {
let summary = results[0] as Summary
let metadataSource = results[1] as { [name: string]: MetadataSource }

View File

@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { AuthInterceptorService } from './auth-interceptor.service';
describe('AuthInterceptorService', () => {
let service: AuthInterceptorService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthInterceptorService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -1,41 +0,0 @@
import { Injectable, Injector } from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import { FastenApiService } from './fasten-api.service';
import {Router} from '@angular/router';
import {Observable, of, throwError} from 'rxjs';
import {catchError} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
// based on https://stackoverflow.com/questions/46017245/how-to-handle-unauthorized-requestsstatus-with-401-or-403-with-new-httpclient
export class AuthInterceptorService implements HttpInterceptor {
constructor(private fastenApiService: FastenApiService, private router: Router) { }
private handleAuthError(err: HttpErrorResponse): Observable<any> {
//handle your auth error or rethrow
if (err.status === 401 || err.status === 403) {
//navigate /delete cookies or whatever
this.fastenApiService.logout()
this.router.navigateByUrl(`/auth/signin`);
// if you've caught / handled the error, you don't want to rethrow it unless you also want downstream consumers to have to handle it as well.
return of(err.message); // or EMPTY may be appropriate here
}
return throwError(err);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//only intercept requests to the fasten API, all other requests should be sent as-is
if(!req.url.startsWith('/api/secure/')){
return next.handle(req)
}
// Clone the request to add the new header.
const authReq = req.clone({headers: req.headers.set('Authorization', 'Bearer ' + this.fastenApiService.token())});
// catch the error, make specific functions for catching specific errors and you can chain through them with more catch operators
return next.handle(authReq).pipe(catchError(x=> this.handleAuthError(x))); //here use an arrow function, otherwise you may get "Cannot read property 'navigate' of undefined" on angular 4.4.2/net core 2/webpack 2.70
}
}

View File

@ -1,16 +1,16 @@
import { Injectable } from '@angular/core';
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router} from '@angular/router';
import { FastenApiService } from './fasten-api.service';
import { FastenDbService } from './fasten-db.service';
@Injectable()
export class CanActivateAuthGuard implements CanActivate {
constructor(private fastenApiService: FastenApiService, private router: Router) {
constructor(private fastenDbService: FastenDbService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise <boolean> {
//check if the user is authenticated, if not, redirect to login
if (!this.fastenApiService.isAuthenticated()) {
if (! await this.fastenDbService.IsAuthenticated()) {
this.router.navigate(['/auth/signin']);
}
// continue as normal

View File

@ -2,6 +2,7 @@ import {Source} from '../models/database/source';
import {ResourceFhir} from '../models/database/resource_fhir';
import {SourceSummary} from '../models/fasten/source-summary';
import {Summary} from '../models/fasten/summary';
import {User} from '../models/fasten/user';
// import {SourceSummary} from '../../app/models/fasten/source-summary';
export interface IDatabaseDocument {

View File

@ -1,6 +1,4 @@
export class User {
user_id?: number
name?: string
username?: string
password?: string
}