frontend auth

This commit is contained in:
Benedek László 2024-04-09 00:03:27 +02:00
parent 0a5a73cecf
commit bc8c7a3a07
8 changed files with 133 additions and 11 deletions

View File

@ -1,10 +1,11 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { CheckTokenCanActivate } from './services/auth/auth.service';
export const routes: Routes = [ export const routes: Routes = [
{ path: 'auth', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule) }, { path: 'auth', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule) },
{ path: 'feed', loadChildren: () => import('./feed/feed.module').then(m => m.FeedModule) }, { path: 'feed', loadChildren: () => import('./feed/feed.module').then(m => m.FeedModule), canActivate: [CheckTokenCanActivate] },
{ path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule) }, { path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule), canActivate: [CheckTokenCanActivate] },
{ path: '', redirectTo: 'feed', pathMatch: 'full'} { path: '', redirectTo: 'feed', pathMatch: 'full'}
]; ];

View File

@ -1,24 +1,36 @@
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms'; import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { AuthService } from '../../services/auth/auth.service';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrls: ['./login.component.scss', '../auth.component.scss'] styleUrls: ['./login.component.scss', '../auth.component.scss']
}) })
export class LoginComponent { export class LoginComponent implements OnInit {
loginForm = new FormGroup({ loginForm = new FormGroup({
username: new FormControl(''), username: new FormControl(''),
password: new FormControl('') password: new FormControl('')
}); });
constructor(private router: Router) { constructor(private router: Router, private auth: AuthService) {
this.loginForm.addValidators([Validators.required]); this.loginForm.addValidators([Validators.required]);
} }
ngOnInit(): void {
this.auth.getToken().then(()=> { this.router.navigateByUrl("/feed") })
}
login() { login() {
if (this.loginForm.valid) this.router.navigateByUrl("/feed"); if (this.loginForm.valid)
else alert("missing username or password"); this.auth.login(
this.loginForm.get('username')?.value as String,
this.loginForm.get('password')?.value as String
)
.then(()=>{ this.router.navigateByUrl("/feed") })
.catch(()=>{ alert("wrong username or password") });
else
alert("missing username or password");
} }
} }

View File

@ -1,5 +1,7 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms'; import { FormControl, FormGroup, Validators } from '@angular/forms';
import { AuthService } from '../../services/auth/auth.service';
import { Router } from '@angular/router';
@Component({ @Component({
selector: 'app-register', selector: 'app-register',
@ -13,11 +15,21 @@ export class RegisterComponent {
rePassword: new FormControl('') rePassword: new FormControl('')
}); });
constructor() { constructor(private router: Router, private auth: AuthService) {
this.registerForm.addValidators([Validators.required, Validators.minLength(3)]); this.registerForm.addValidators([Validators.required, Validators.minLength(3)]);
} }
register() { register() {
if (!this.registerForm.valid) alert("failed to register"); if (this.registerForm.valid)
this.auth.register(
this.registerForm.get('username')?.value as String,
this.registerForm.get('password')?.value as String,
this.registerForm.get('rePassword')?.value as String,
)
.then(()=> { this.router.navigateByUrl('/auth/login') })
.catch(()=> { alert('failed to register') });
// TODO: better error messages
else
alert("failed to register");
} }
} }

View File

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

View File

@ -0,0 +1,70 @@
import { Injectable, inject } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivateFn, GuardResult, MaybeAsync, Router, RouterStateSnapshot } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
token?: String;
constructor(private router: Router) { }
checkAllowed() {
// TODO: check if the token is still valid
if (this.token)
return true;
else {
this.router.navigateByUrl('/auth/login');
return false;
}
}
getToken(): Promise<String> {
// TODO: check if the token is still valid
return new Promise<String>((resolve, reject) => {
if (this.token)
resolve(this.token);
else
reject();
});
}
login(username: String, password: String): Promise<Boolean> {
return new Promise<Boolean>((resolve, reject) => {
// TODO: authenticate
if (username === "test" && password === "test") {
this.token = "valid_token";
resolve(true);
}
else {
this.token = undefined;
reject();
}
});
}
logout(): Promise<Boolean> {
return new Promise<Boolean>((resolve, reject) => {
// TODO: logout
this.token = undefined;
resolve(true);
});
}
register(username: String, password: String, rePassword: String): Promise<Boolean> {
return new Promise<Boolean>((resolve, reject) => {
// TODO: register
if (username !== "test" && password === rePassword)
resolve(true);
else
reject();
});
}
}
export const CheckTokenCanActivate: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
return inject(AuthService).checkAllowed();
}

View File

@ -2,4 +2,5 @@
<button [routerLink]="'/feed'">Feed</button> <button [routerLink]="'/feed'">Feed</button>
<button [routerLink]="'/user'">Profile</button> <button [routerLink]="'/user'">Profile</button>
<button >New Post</button> <button >New Post</button>
<button (click)="logout()">Logout</button>
</menu> </menu>

View File

@ -1,5 +1,6 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { RouterModule } from '@angular/router'; import { Router, RouterModule } from '@angular/router';
import { AuthService } from '../../services/auth/auth.service';
@Component({ @Component({
selector: 'app-side-menu', selector: 'app-side-menu',
@ -9,5 +10,11 @@ import { RouterModule } from '@angular/router';
styleUrl: './side-menu.component.scss' styleUrl: './side-menu.component.scss'
}) })
export class SideMenuComponent { export class SideMenuComponent {
constructor(private router: Router, private auth: AuthService) { }
logout() {
this.auth.logout()
.then(() => { this.router.navigateByUrl('/auth/login') })
.catch(() => { alert('failed to log out') });
}
} }

View File

@ -2,7 +2,10 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { UserComponent } from './user.component'; import { UserComponent } from './user.component';
const routes: Routes = [{ path: '', component: UserComponent }]; const routes: Routes = [
{ path: '', component: UserComponent },
{ path: ':username', component: UserComponent }
];
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],