Routing/menü fejlesztés, SPA fix
- Logout hozzáadva - Read only lista kijelentkezve
This commit is contained in:
parent
7ef0ccadba
commit
91f599645b
14 changed files with 85 additions and 69 deletions
|
@ -1,34 +1,37 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { inject, NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { AuthCheck } from './auth-check';
|
|
||||||
import { ProductListComponent } from './product-list/product-list.component';
|
import { ProductListComponent } from './product-list/product-list.component';
|
||||||
import { LoginComponent } from './login/login.component';
|
import { LoginComponent } from './login/login.component';
|
||||||
import { UserListComponent } from './user-list/user-list.component';
|
import { UserListComponent } from './user-list/user-list.component';
|
||||||
import { ProductEditComponent } from './product-edit/product-edit.component';
|
import { ProductEditComponent } from './product-edit/product-edit.component';
|
||||||
|
import { UserService } from './services/user.service';
|
||||||
|
import { RegisterComponent } from './register/register.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
canActivate: [AuthCheck],
|
canMatch: [() => !!inject(UserService).user],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'users',
|
path: 'users',
|
||||||
component: UserListComponent
|
component: UserListComponent
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: ProductListComponent
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: ':id',
|
path: ':id',
|
||||||
component: ProductEditComponent
|
component: ProductEditComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: ProductListComponent
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
children: [
|
children: [
|
||||||
{path: '', component: LoginComponent}
|
{path: 'login', component: LoginComponent},
|
||||||
|
{path: 'register', component: RegisterComponent},
|
||||||
|
{path: '', component: ProductListComponent}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -39,5 +42,3 @@ const routes: Routes = [
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {
|
export class AppRoutingModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RouteData = { title: string; };
|
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loginbox {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,24 +1,14 @@
|
||||||
<div *ngIf="userService.user; else login" class="loginbox" style="margin: 20px">
|
<div *ngIf="userService.user; else login" class="loginbox">
|
||||||
Üdv {{ userService.user.username }}
|
Üdv {{ userService.user.username }}
|
||||||
<div>
|
<button mat-button class="mat-primary" (click)="router.navigate(['/'])">Termékek</button>
|
||||||
<button mat-button class="mat-primary" (click)="router.navigate(['/'])">Termékek</button>
|
<button mat-button class="mat-primary" (click)="router.navigate(['/users'])">Felhasználók</button>
|
||||||
<button mat-button class="mat-primary" (click)="router.navigate(['/users'])">Felhasználók</button>
|
<button mat-button (click)="logout()">Kijelentkezés</button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ng-template #login>
|
<ng-template #login>
|
||||||
<div class="loginbox">
|
<div class="loginbox">
|
||||||
<form [formGroup]="loginForm">
|
<button mat-button class="mat-primary" (click)="router.navigate(['/'])">Termékek</button>
|
||||||
<mat-form-field appearance="fill">
|
<button routerLink="/login" mat-button class="mat-primary">Bejelentkezés</button>
|
||||||
<mat-label>Felhasználónév</mat-label>
|
<button routerLink="/register" mat-button>Regisztráció</button>
|
||||||
<input matInput formControlName="username">
|
|
||||||
</mat-form-field>
|
|
||||||
<mat-form-field appearance="fill">
|
|
||||||
<mat-label>Jelszó</mat-label>
|
|
||||||
<input matInput type="password" formControlName="password">
|
|
||||||
</mat-form-field>
|
|
||||||
<button mat-button class="mat-primary" (click)="doLogin()">Bejelentkezés</button>
|
|
||||||
<button mat-button (click)="doRegister()">Regisztráció</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|
|
@ -9,11 +9,6 @@ import { Router } from '@angular/router';
|
||||||
styleUrls: ['./app.component.css']
|
styleUrls: ['./app.component.css']
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
loginForm = new FormGroup({
|
|
||||||
username: new FormControl(),
|
|
||||||
password: new FormControl()
|
|
||||||
});
|
|
||||||
|
|
||||||
toggle = false;
|
toggle = false;
|
||||||
|
|
||||||
constructor(public userService: UserService, public router: Router) {
|
constructor(public userService: UserService, public router: Router) {
|
||||||
|
@ -25,15 +20,9 @@ export class AppComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async doLogin() {
|
async logout() {
|
||||||
try {
|
if (await this.userService.logout()) {
|
||||||
await this.userService.login(this.loginForm.value.username, this.loginForm.value.password);
|
await this.router.navigate(['/']);
|
||||||
} catch (e: any) {
|
|
||||||
console.log("Hiba:", e);
|
|
||||||
alert("Hiba: " + (e?.error?.error ?? JSON.stringify(e)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async doRegister() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { HttpClientModule } from '@angular/common/http';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { LoginComponent } from './login/login.component';
|
import { LoginComponent } from './login/login.component';
|
||||||
import { UserListComponent } from './user-list/user-list.component';
|
import { UserListComponent } from './user-list/user-list.component';
|
||||||
import { AuthCheck } from './auth-check';
|
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
import { RegisterComponent } from './register/register.component';
|
import { RegisterComponent } from './register/register.component';
|
||||||
import { ProductEditComponent } from './product-edit/product-edit.component';
|
import { ProductEditComponent } from './product-edit/product-edit.component';
|
||||||
|
@ -44,7 +43,6 @@ import { ProductEditComponent } from './product-edit/product-edit.component';
|
||||||
MatSlideToggleModule
|
MatSlideToggleModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AuthCheck
|
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { UserService } from './services/user.service';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AuthCheck implements CanActivate {
|
|
||||||
constructor(private userService: UserService) {
|
|
||||||
}
|
|
||||||
|
|
||||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
|
||||||
return !!this.userService.user;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +1,14 @@
|
||||||
<h1>Jelentkezz be</h1>
|
<div class="loginbox">
|
||||||
|
<form [formGroup]="loginForm">
|
||||||
|
<mat-form-field appearance="fill">
|
||||||
|
<mat-label>Felhasználónév</mat-label>
|
||||||
|
<input matInput formControlName="username">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field appearance="fill">
|
||||||
|
<mat-label>Jelszó</mat-label>
|
||||||
|
<input matInput type="password" formControlName="password">
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-button class="mat-primary" (click)="doLogin()">Bejelentkezés</button>
|
||||||
|
<button mat-button [routerLink]="'/register'">Regisztráció</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
|
import { UserService } from '../services/user.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
|
@ -6,5 +9,22 @@ import { Component } from '@angular/core';
|
||||||
styleUrls: ['./login.component.css']
|
styleUrls: ['./login.component.css']
|
||||||
})
|
})
|
||||||
export class LoginComponent {
|
export class LoginComponent {
|
||||||
|
loginForm = new FormGroup({
|
||||||
|
username: new FormControl(),
|
||||||
|
password: new FormControl()
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(public userService: UserService, private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async doLogin() {
|
||||||
|
try {
|
||||||
|
await this.userService.login(this.loginForm.value.username, this.loginForm.value.password);
|
||||||
|
await this.router.navigate(['/']);
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log("Hiba:", e);
|
||||||
|
alert("Hiba: " + (e?.error?.error ?? JSON.stringify(e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class ProductEditComponent {
|
||||||
})
|
})
|
||||||
|
|
||||||
constructor(private service: ProductService, route: ActivatedRoute) {
|
constructor(private service: ProductService, route: ActivatedRoute) {
|
||||||
service.get(route.snapshot.params['id']).subscribe(value => this.form.patchValue(value));
|
service.get(route.snapshot.params['id']).subscribe((value: Product) => this.form.patchValue(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Product } from '../model/product.model';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
|
import { UserService } from '../services/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-product-list',
|
selector: 'app-product-list',
|
||||||
|
@ -23,11 +24,14 @@ export class ProductListComponent implements AfterViewInit {
|
||||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||||
displayedColumns = ['name', 'description', 'price', 'actions'];
|
displayedColumns = ['name', 'description', 'price', 'actions'];
|
||||||
|
|
||||||
constructor(private service: ProductService) {
|
constructor(private service: ProductService, public userService: UserService) {
|
||||||
this.products = service.getList().pipe(map(value => value as Product[]));
|
this.products = service.getList().pipe(map(value => value as Product[]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
this.table.dataSource = this.products;
|
this.table.dataSource = this.products;
|
||||||
|
if (!this.userService.user) {
|
||||||
|
this.displayedColumns.pop(); // Műveletek elrejtése, ha nincs bejelentkezve
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,24 @@ export class UserService {
|
||||||
const user = await firstValueFrom(this.http.get('/api/users/status'));
|
const user = await firstValueFrom(this.http.get('/api/users/status'));
|
||||||
this._user = user as User;
|
this._user = user as User;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e?.error?.error?.status !== 'NOTOK') {
|
if (e?.error?.status !== 'NOTOK') {
|
||||||
console.log("Failed to get user:", e);
|
console.log("Failed to get user:", e);
|
||||||
}
|
}
|
||||||
this._user = undefined;
|
this._user = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async logout() {
|
||||||
|
try {
|
||||||
|
await firstValueFrom(this.http.post('/api/users/logout', {}));
|
||||||
|
this._user = undefined;
|
||||||
|
return true;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.log("Failed to log out:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getList() {
|
getList() {
|
||||||
return this.http.get('/api/users')
|
return this.http.get('/api/users')
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ require('./db/bootstrapper')();
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const {mongo} = require("mongoose");
|
const {mongo} = require("mongoose");
|
||||||
|
const path = require("path");
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: false }));
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
|
@ -58,11 +59,12 @@ app.use(passport.session({}));
|
||||||
app.use('/api/users', require('./usersRouter'))
|
app.use('/api/users', require('./usersRouter'))
|
||||||
app.use('/api/products', require('./productsRouter'))
|
app.use('/api/products', require('./productsRouter'))
|
||||||
|
|
||||||
app.use(function (req, _, next) {
|
app.use(function (req, res, next) {
|
||||||
if (!req.url.startsWith('/api') && req.url.indexOf('.') === -1) {
|
if (!req.url.startsWith('/api') && req.url.indexOf('.') === -1) {
|
||||||
req.url = '/';
|
res.sendFile(path.resolve('public', 'index.html'));
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
next();
|
|
||||||
})
|
})
|
||||||
|
|
||||||
app.use('', express.static('public'))
|
app.use('', express.static('public'))
|
||||||
|
|
|
@ -24,9 +24,6 @@ async function getProduct(req, res, next) {
|
||||||
|
|
||||||
// GET /products - összes termék lekérdezése
|
// GET /products - összes termék lekérdezése
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
if (!req.isAuthenticated()) {
|
|
||||||
return res.status(403).json({ message: "Unauthenticated" });
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const products = await Product.find();
|
const products = await Product.find();
|
||||||
res.status(200).json(products.map(product => getProductData(product)));
|
res.status(200).json(products.map(product => getProductData(product)));
|
||||||
|
|
|
@ -31,10 +31,10 @@ router.route('/logout').post((req, res) => {
|
||||||
console.log('Hiba a kijelentkezés során');
|
console.log('Hiba a kijelentkezés során');
|
||||||
return res.status(500).send(err)
|
return res.status(500).send(err)
|
||||||
}
|
}
|
||||||
return res.status(200).send('Kijelentkezes sikeres');
|
return res.status(200).json({status: 'OK'});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return res.status(403).send('Nem is volt bejelentkezve');
|
return res.status(403).json({status: 'NOTOK'});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue