Merge pull request #37 from liosha84/35-angular-17-logout-when-token-is-expired-like-as-bezkoder
35 angular 17 logout when token is expired like as bezkoder
This commit is contained in:
@@ -1,55 +0,0 @@
|
||||
|
||||
<mat-toolbar class="fixed-top">
|
||||
<button mat-raised-button routerLink="/" href="#">
|
||||
My App
|
||||
</button>
|
||||
<span class="example-spacer"></span>
|
||||
<button mat-raised-button routerLink="tutorials">
|
||||
Tutorials
|
||||
</button>
|
||||
<button mat-raised-button routerLink="add" *ngIf="isLoggedIn">
|
||||
Add tutorial
|
||||
</button>
|
||||
<span class="example-spacer"></span>
|
||||
@if (showAdminBoard) {
|
||||
<button mat-raised-button routerLink="admin" >
|
||||
<mat-icon>manage_accounts</mat-icon>
|
||||
Admin Bord
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (showAdminBoard) {
|
||||
<button mat-raised-button routerLink="system" >
|
||||
<mat-icon>settings_applications</mat-icon>
|
||||
System
|
||||
</button>
|
||||
}
|
||||
|
||||
<span class="example-spacer"></span>
|
||||
<button mat-raised-button routerLink="register" *ngIf="!isLoggedIn">
|
||||
<mat-icon>app_registration</mat-icon>
|
||||
Register
|
||||
</button>
|
||||
|
||||
<button mat-raised-button (click)="openDialog('100ms', '5ms')" *ngIf="!isLoggedIn">
|
||||
<mat-icon>login</mat-icon>
|
||||
Login
|
||||
</button>
|
||||
|
||||
<button mat-raised-button routerLink="profile" *ngIf="isLoggedIn">
|
||||
<mat-icon>account_circle</mat-icon>
|
||||
{{ username }}
|
||||
</button>
|
||||
|
||||
<button mat-raised-button (click)="logout()"*ngIf="isLoggedIn">
|
||||
<mat-icon>logout</mat-icon>
|
||||
Logout
|
||||
</button>
|
||||
|
||||
</mat-toolbar>
|
||||
|
||||
|
||||
<div class="router_outlet_padding">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
//#header_panel{
|
||||
// background-color: #181d1f;
|
||||
//}
|
||||
.example-spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
mat-toolbar{
|
||||
background-color: rgba(153,153,153,0.16);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.fixed-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1000; // Ensure toolbar stays above other content
|
||||
}
|
||||
.router_outlet_padding{
|
||||
padding-top: 60px;
|
||||
scroll-padding-inline: 40%;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
// it(`should have as title 'spring-angular-ui'`, () => {
|
||||
// const fixture = TestBed.createComponent(AppComponent);
|
||||
// const app = fixture.componentInstance;
|
||||
// expect(app.title).toEqual('spring-angular-ui');
|
||||
// });
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('spring-angular-ui app is running!');
|
||||
});
|
||||
});
|
||||
@@ -1,124 +0,0 @@
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit} from '@angular/core';
|
||||
import { TokenStorageService } from './services/token-storage.service';
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {DialogComponent} from "./components/dialog/dialog.component";
|
||||
import {AuthService} from "./services/auth.service";
|
||||
import {Subscription} from "rxjs";
|
||||
import {EventBusService} from "./_shared/event-bus.service";
|
||||
import {RouterLink, RouterOutlet} from '@angular/router';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {MatToolbar} from '@angular/material/toolbar';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
imports: [
|
||||
RouterOutlet,
|
||||
MatIcon,
|
||||
MatButton,
|
||||
RouterLink,
|
||||
MatToolbar
|
||||
],
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
readonly dialog = inject(MatDialog);
|
||||
//private authService = new AuthService(provideHttpClient())
|
||||
public dialogData : DialogData = {password: "", username: ""};
|
||||
|
||||
private roles: string[] = [];
|
||||
isLoggedIn = false;
|
||||
showAdminBoard = false;
|
||||
showModeratorBoard = false;
|
||||
username?: string;
|
||||
|
||||
eventBusSub?: Subscription;
|
||||
private errorMessage: any;
|
||||
private isLoginFailed: boolean = false;
|
||||
|
||||
constructor(
|
||||
private storageService: TokenStorageService,
|
||||
private authService: AuthService,
|
||||
private eventBusService: EventBusService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.isLoggedIn = this.storageService.isLoggedIn();
|
||||
|
||||
if (this.isLoggedIn) {
|
||||
const user = this.storageService.getUser();
|
||||
this.roles = user.roles;
|
||||
|
||||
this.showAdminBoard = true;//this.roles.includes('ROLE_ADMIN');
|
||||
this.showModeratorBoard = this.roles.includes('ROLE_MODERATOR');
|
||||
|
||||
this.username = user.username;
|
||||
}
|
||||
|
||||
this.eventBusSub = this.eventBusService.on('logout', () => {
|
||||
this.logout();
|
||||
});
|
||||
}
|
||||
|
||||
logout(): void {
|
||||
this.authService.logout().subscribe({
|
||||
next: res => {
|
||||
console.log(res);
|
||||
this.storageService.clean();
|
||||
|
||||
window.location.reload();
|
||||
},
|
||||
error: err => {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openDialog(enterAnimationDuration: string, exitAnimationDuration: string) {
|
||||
|
||||
let dialogRef = this.dialog.open(DialogComponent, {
|
||||
width: '350px',
|
||||
enterAnimationDuration,
|
||||
exitAnimationDuration,
|
||||
data: {username: this.dialogData.username, password: this.dialogData.password}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed');
|
||||
if(result== null){
|
||||
return;
|
||||
}
|
||||
this.dialogData = result;
|
||||
|
||||
this.authService.login(this.dialogData.username, this.dialogData.password).subscribe(
|
||||
data => {
|
||||
this.storageService.saveToken(data.accessToken);
|
||||
this.storageService.saveUser(data);
|
||||
|
||||
this.isLoginFailed = false;
|
||||
this.isLoggedIn = true;
|
||||
let user = this.storageService.getUser();
|
||||
this.roles = user.roles;
|
||||
//this.username = user.username;
|
||||
this.reloadPage();
|
||||
},
|
||||
err => {
|
||||
this.errorMessage = err.error.message;
|
||||
this.isLoginFailed = true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
reloadPage(): void {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
}
|
||||
export interface DialogData {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
@@ -12,5 +12,7 @@ import { RouterOutlet } from '@angular/router';
|
||||
export class App {
|
||||
protected title = 'jambotron-ui';
|
||||
|
||||
constructor() { }
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const language = 'typescript';
|
||||
description: this.tutorial.description
|
||||
};
|
||||
|
||||
this.tutorialService.create(data)
|
||||
/* this.tutorialService.create(data)
|
||||
.subscribe(
|
||||
response => {
|
||||
console.log(response);
|
||||
@@ -82,7 +82,7 @@ const language = 'typescript';
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
newTutorial(): void {
|
||||
|
||||
@@ -36,7 +36,7 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
}
|
||||
|
||||
getTutorial(id: string): void {
|
||||
this.tutorialService.get(id)
|
||||
/* this.tutorialService.get(id)
|
||||
.subscribe(
|
||||
data => {
|
||||
this.currentTutorial = data;
|
||||
@@ -44,7 +44,7 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
updatePublished(status: boolean): void {
|
||||
@@ -56,7 +56,7 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
|
||||
this.message = '';
|
||||
|
||||
this.tutorialService.update(this.currentTutorial.id, data)
|
||||
/* this.tutorialService.update(this.currentTutorial.id, data)
|
||||
.subscribe(
|
||||
response => {
|
||||
this.currentTutorial.published = status;
|
||||
@@ -65,11 +65,11 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
updateTutorial(): void {
|
||||
this.message = '';
|
||||
/* this.message = '';
|
||||
|
||||
this.tutorialService.update(this.currentTutorial.id, this.currentTutorial)
|
||||
.subscribe(
|
||||
@@ -79,11 +79,11 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
deleteTutorial(): void {
|
||||
this.tutorialService.delete(this.currentTutorial.id)
|
||||
/* this.tutorialService.delete(this.currentTutorial.id)
|
||||
.subscribe(
|
||||
response => {
|
||||
console.log(response);
|
||||
@@ -91,6 +91,6 @@ export class TutorialDetailsComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ export class TutorialsListComponent implements OnInit {
|
||||
}
|
||||
|
||||
retrieveTutorials(): void {
|
||||
this.tutorialService.getAll()
|
||||
this.tutorialService.getAllPublic()
|
||||
.subscribe(
|
||||
data => {
|
||||
(data: Tutorial[] ) => {
|
||||
this.tutorials = data;
|
||||
console.log(data);
|
||||
},
|
||||
@@ -54,7 +54,7 @@ export class TutorialsListComponent implements OnInit {
|
||||
}
|
||||
|
||||
removeAllTutorials(): void {
|
||||
this.tutorialService.deleteAll()
|
||||
/* this.tutorialService.deleteAll()
|
||||
.subscribe(
|
||||
response => {
|
||||
console.log(response);
|
||||
@@ -62,7 +62,7 @@ export class TutorialsListComponent implements OnInit {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
searchTitle(): void {
|
||||
|
||||
@@ -36,14 +36,14 @@ export class TutorialsComponent {
|
||||
// }
|
||||
|
||||
retrieveTutorials(): void {
|
||||
this.tutorialService.getAll()
|
||||
.subscribe(
|
||||
data => {
|
||||
this.tutorials = data;
|
||||
console.log(data);
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
});
|
||||
this.tutorialService.getAllPublic().subscribe(
|
||||
(data : Tutorial[]) =>{
|
||||
this.tutorials = data;
|
||||
console.log(data);
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,57 @@
|
||||
import { HTTP_INTERCEPTORS, HttpEvent } from '@angular/common/http';
|
||||
import {HTTP_INTERCEPTORS, HttpErrorResponse, HttpEvent} from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
|
||||
|
||||
import { TokenStorageService } from '../services/token-storage.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import {catchError, Observable, throwError} from 'rxjs';
|
||||
import {EventBusService} from '../_shared/event-bus.service';
|
||||
import {EventData} from '../_shared/event.class';
|
||||
import {environment} from '../../environments/environment';
|
||||
|
||||
const TOKEN_HEADER_KEY = 'Authorization'; // for Spring Boot back-end
|
||||
|
||||
@Injectable()
|
||||
export class AuthInterceptor implements HttpInterceptor {
|
||||
constructor(private token: TokenStorageService) { }
|
||||
private isRefreshing = false;
|
||||
enviorment = environment;
|
||||
|
||||
constructor(private tokenStorageService: TokenStorageService, private eventBusService: EventBusService) { }
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
|
||||
|
||||
req = req.clone({
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
return next.handle(req);
|
||||
return next.handle(req).pipe(
|
||||
catchError((error) => {
|
||||
if (
|
||||
error instanceof HttpErrorResponse &&
|
||||
!req.url.includes('auth/signin') &&
|
||||
(error.status === 401
|
||||
|| error.status === 500
|
||||
|| error.status === 0
|
||||
|
||||
) /// must be only 401 without 500 and 0
|
||||
) {
|
||||
return this.handle401Error(req, next);
|
||||
}
|
||||
|
||||
/*let authReq = req;
|
||||
const token = this.token.getToken();
|
||||
if (token != null) {
|
||||
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) });
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
|
||||
if (!this.isRefreshing) {
|
||||
this.isRefreshing = true;
|
||||
|
||||
if (this.tokenStorageService.isLoggedIn()) {
|
||||
this.eventBusService.emit(new EventData('logout', null));
|
||||
}
|
||||
}
|
||||
return next.handle(authReq);*/
|
||||
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,19 @@
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
@if (showAdminBoard) {
|
||||
<button mat-menu-item routerLink="admin/welcome">
|
||||
<mat-icon>admin_panel_settings</mat-icon>
|
||||
Admin Panel
|
||||
</button>
|
||||
<button mat-menu-item routerLink="admin/welcome">
|
||||
<mat-icon>admin_panel_settings</mat-icon>
|
||||
Admin Panel
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (showUserBoard) {
|
||||
<button mat-menu-item routerLink="user/user-welcome">
|
||||
<mat-icon>space_dashboard</mat-icon>
|
||||
User tools
|
||||
</button>
|
||||
}
|
||||
|
||||
<button mat-menu-item routerLink="user/user-welcome">
|
||||
<mat-icon>space_dashboard</mat-icon>
|
||||
User tools
|
||||
</button>
|
||||
<button mat-menu-item routerLink="profile">
|
||||
<mat-icon>person</mat-icon>
|
||||
Profile
|
||||
|
||||
@@ -61,6 +61,7 @@ export class MainComponent implements OnInit{
|
||||
isLoggedIn = false;
|
||||
showAdminBoard = false;
|
||||
showModeratorBoard = false;
|
||||
showUserBoard = false;
|
||||
username?: string;
|
||||
|
||||
eventBusSub?: Subscription;
|
||||
@@ -74,12 +75,9 @@ export class MainComponent implements OnInit{
|
||||
constructor(private router: Router,private http: HttpClient) {
|
||||
|
||||
}
|
||||
goToHome() {
|
||||
this.router.navigate(['main/home']);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.isLoggedIn = this.storageService.isLoggedIn();
|
||||
|
||||
|
||||
this.refreshToolbar();
|
||||
|
||||
@@ -89,12 +87,14 @@ export class MainComponent implements OnInit{
|
||||
}
|
||||
|
||||
refreshToolbar() {
|
||||
this.isLoggedIn = this.storageService.isLoggedIn();
|
||||
if (this.isLoggedIn) {
|
||||
const user = this.storageService.getUser();
|
||||
this.roles = user.roles;
|
||||
|
||||
this.showAdminBoard = true;//this.roles.includes('ROLE_ADMIN');
|
||||
this.showAdminBoard = this.roles.includes('ROLE_ADMIN');
|
||||
this.showModeratorBoard = this.roles.includes('ROLE_MODERATOR');
|
||||
this.showUserBoard = this.roles.includes('ROLE_USER');
|
||||
|
||||
this.username = user.username;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Observable } from 'rxjs';
|
||||
import { Tutorial } from '../models/tutorial.model';
|
||||
import {text} from 'node:stream/consumers';
|
||||
|
||||
const baseUrl = 'http://localhost:8080/api/tutorials';
|
||||
const baseUrl = 'http://localhost:8080/api/public/tutorials';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -13,31 +13,31 @@ export class TutorialService {
|
||||
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getAll(): Observable<Tutorial[]> {
|
||||
getAllPublic(): Observable<Tutorial[]> {
|
||||
return this.http.get<Tutorial[]>(baseUrl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
get(id: any): Observable<Tutorial> {
|
||||
return this.http.get(`${baseUrl}/${id}`);
|
||||
}
|
||||
|
||||
create(data: any): Observable<any> {
|
||||
return this.http.post(baseUrl, data);
|
||||
}
|
||||
|
||||
update(id: any, data: any): Observable<any> {
|
||||
return this.http.put(`${baseUrl}/${id}`, data);
|
||||
}
|
||||
|
||||
delete(id: any): Observable<any> {
|
||||
return this.http.delete(`${baseUrl}/${id}`);
|
||||
}
|
||||
|
||||
deleteAll(): Observable<any> {
|
||||
return this.http.delete(baseUrl);
|
||||
}
|
||||
//
|
||||
// get(id: any): Observable<Tutorial> {
|
||||
// return this.http.get(`${baseUrl}/${id}`);
|
||||
// }
|
||||
//
|
||||
// create(data: any): Observable<any> {
|
||||
// return this.http.post(baseUrl, data);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// update(id: any, data: any): Observable<any> {
|
||||
// return this.http.put(`${baseUrl}/${id}`, data);
|
||||
// }
|
||||
//
|
||||
// delete(id: any): Observable<any> {
|
||||
// return this.http.delete(`${baseUrl}/${id}`);
|
||||
// }
|
||||
//
|
||||
// deleteAll(): Observable<any> {
|
||||
// return this.http.delete(baseUrl);
|
||||
// }
|
||||
|
||||
findByTitle(title: any): Observable<Tutorial[]> {
|
||||
return this.http.get<Tutorial[]>(`${baseUrl}?title=${title}`);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<p>tutorial-add.component works!</p>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TutorialAddComponent } from './tutorial-add.component';
|
||||
|
||||
describe('TutorialAddComponent', () => {
|
||||
let component: TutorialAddComponent;
|
||||
let fixture: ComponentFixture<TutorialAddComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TutorialAddComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(TutorialAddComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tutorial-add.component',
|
||||
imports: [],
|
||||
templateUrl: './tutorial-add.component.html',
|
||||
styleUrl: './tutorial-add.component.scss'
|
||||
})
|
||||
export class TutorialAddComponent {
|
||||
|
||||
}
|
||||
+3
@@ -1,4 +1,7 @@
|
||||
<p>tutorials-list.component works!</p>
|
||||
|
||||
<button mat-raised-button routerLink="../tutorial-add">Add tutorial</button>
|
||||
|
||||
<mat-list role="list">
|
||||
@for (tutorial of tutorials; track tutorial) {
|
||||
<!--
|
||||
|
||||
+49
-5
@@ -1,4 +1,4 @@
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit} from '@angular/core';
|
||||
import {MatList, MatListItem} from '@angular/material/list';
|
||||
import {Tutorial} from '../../models/tutorial.model';
|
||||
import {TutorialService} from '../../services/tutorial.service';
|
||||
@@ -6,6 +6,11 @@ import {UserApiService} from '../user-api.service';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {MatLine, MatOption} from '@angular/material/core';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {TokenStorageService} from '../../services/token-storage.service';
|
||||
import {EventBusService} from '../../_shared/event-bus.service';
|
||||
import {EventData} from '../../_shared/event.class';
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {AuthService} from '../../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tutorials-list.component',
|
||||
@@ -15,16 +20,27 @@ import {MatIcon} from '@angular/material/icon';
|
||||
MatLine,
|
||||
MatButton,
|
||||
MatIcon,
|
||||
MatOption
|
||||
MatOption,
|
||||
RouterLink
|
||||
],
|
||||
schemas:[CUSTOM_ELEMENTS_SCHEMA],
|
||||
templateUrl: './tutorials-list.component.html',
|
||||
styleUrl: './tutorials-list.component.scss'
|
||||
})
|
||||
export class TutorialsListComponent {
|
||||
export class TutorialsListComponent implements OnInit {
|
||||
tutorials?: Tutorial[];
|
||||
|
||||
constructor(private userApiService: UserApiService) {
|
||||
constructor(private userApiService: UserApiService,
|
||||
private storageService: TokenStorageService,
|
||||
private eventBusService: EventBusService,
|
||||
private router: Router, private authService: AuthService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.eventBusService.on('logout', () => {
|
||||
this.logout();
|
||||
})
|
||||
this.retrieveTutorials();
|
||||
}
|
||||
|
||||
@@ -37,10 +53,38 @@ export class TutorialsListComponent {
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
if (
|
||||
(
|
||||
error.status === 401
|
||||
|| error.status === 500
|
||||
|| error.status === 0
|
||||
)
|
||||
&& this.storageService.isLoggedIn()
|
||||
) {
|
||||
this.eventBusService.emit(new EventData('logout', null));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteOption($event: MouseEvent, option: any) {
|
||||
|
||||
|
||||
}
|
||||
logout(): void {
|
||||
this.authService.logout().subscribe({
|
||||
next: res => {
|
||||
console.log(res);
|
||||
this.storageService.clean();
|
||||
|
||||
//window.location.reload();
|
||||
this.router.navigate(['main/generate-image']).then(() => {
|
||||
window.location.reload();
|
||||
})
|
||||
|
||||
},
|
||||
error: err => {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ export class UserApiService {
|
||||
}
|
||||
|
||||
getUserAllTutorials(): Observable<Tutorial[]> {
|
||||
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`);
|
||||
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`,{withCredentials: true});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,9 @@ export class UserComponent implements OnInit {
|
||||
ngOnInit(): void {
|
||||
this.observer.observe(['(max-width: 800px)']).subscribe((screenSize) => {
|
||||
this.isMobile = screenSize.matches;
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
toggleMenu() {
|
||||
if(this.isMobile){
|
||||
|
||||
@@ -16,6 +16,10 @@ const USER_ROUTES: Routes = [
|
||||
path: 'tutorials-list',
|
||||
loadComponent: () => import('../user-module/tutorials-list.component/tutorials-list.component').then((c) => c.TutorialsListComponent)
|
||||
},
|
||||
{
|
||||
path: 'tutorial-add',
|
||||
loadComponent: () => import('../user-module/tutorial-add.component/tutorial-add.component').then((c) => c.TutorialAddComponent)
|
||||
},
|
||||
{
|
||||
path: 'ai-models',
|
||||
loadComponent: () => import('../user-module/ai-models.component/ai-models.component').then((c) => c.AiModelsComponent)
|
||||
|
||||
@@ -12,7 +12,11 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CrossOrigin(origins = "http://localhost:4200, https://pony-sincere-chimp.ngrok-free.app/", maxAge = 3600, allowCredentials="true")
|
||||
@CrossOrigin(origins = "http://localhost:4200, https://pony-sincere-chimp.ngrok-free.app/",
|
||||
maxAge = 3600,
|
||||
allowCredentials="true",
|
||||
allowedHeaders = {"Content-Type", "Authorization", "X-Requested-With"}
|
||||
)
|
||||
@RestController
|
||||
@RequestMapping("/api/zhipuai")
|
||||
public class ImageController {
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.Optional;
|
||||
|
||||
|
||||
|
||||
@CrossOrigin(origins = "${app.origin}", maxAge = 3600, allowCredentials="true")
|
||||
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600, allowCredentials="true")
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class TutorialController {
|
||||
@@ -65,23 +65,25 @@ public class TutorialController {
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/tutorials")
|
||||
@GetMapping("/public/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getAllTutorials(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
/* Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
String name = authenticationFacade.getAuthentication().getName();
|
||||
|
||||
User user = userRepository.findById(((UserDetailsImpl)userDetails).getId()).get();
|
||||
if (user.getRoles().stream().anyMatch(role -> role.getName().name().equals("ROLE_ADMIN"))) {
|
||||
if (user.getRoles().stream().anyMatch(role -> role.getName().name().equals("ROLE_ADMIN"))) {*/
|
||||
/*
|
||||
if (title == null)
|
||||
tutorialRepository.findAll().forEach(tutorials::add);
|
||||
else
|
||||
tutorialRepository.findByTitleContaining(title).forEach(tutorials::add);
|
||||
*/
|
||||
|
||||
} else {
|
||||
/* } else {
|
||||
|
||||
// If the user is not an admin, filter tutorials by user
|
||||
tutorialRepository.findByUserId(user.getId()).forEach(tutorials::add);
|
||||
@@ -89,10 +91,10 @@ public class TutorialController {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
//all published tutorials without authentication
|
||||
tutorialRepository.findByPublished(true).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.csrf(csrf -> csrf.disable())
|
||||
http.csrf(csrf -> csrf.disable()).cors(cors -> cors.disable())
|
||||
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth ->
|
||||
@@ -116,7 +116,7 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
.requestMatchers("/main/**").permitAll()
|
||||
.requestMatchers("/api/test/**").permitAll()
|
||||
|
||||
//.requestMatchers("/api/tutorials").hasRole("ADMIN")
|
||||
.requestMatchers("/api/tutorials").permitAll()
|
||||
|
||||
.requestMatchers("/api/zhipuai/image/**").permitAll()
|
||||
|
||||
@@ -130,6 +130,12 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
||||
|
||||
.requestMatchers("/api/settings").permitAll()
|
||||
.requestMatchers("/api/system/**").permitAll()
|
||||
|
||||
// Allow public access to tutorials (without login)
|
||||
.requestMatchers("/api/public/tutorials").permitAll()
|
||||
|
||||
.requestMatchers("/api/user").permitAll()
|
||||
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ public class AuthEntryPointJwt implements AuthenticationEntryPoint {
|
||||
throws IOException, ServletException {
|
||||
logger.error("Unauthorized error: {}", authException.getMessage());
|
||||
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user