From 2ee97f8c8668a1c343ab8caa6d1e3920778b1289 Mon Sep 17 00:00:00 2001
From: liosha84 <138026690+liosha84@users.noreply.github.com>
Date: Sun, 6 Jul 2025 19:37:32 +0300
Subject: [PATCH] Refactor tutorial service for public access and enhance
authentication handling
---
jambotron-ui/src/app/app.component.html | 55 --------
jambotron-ui/src/app/app.component.scss | 23 ----
jambotron-ui/src/app/app.component.spec.ts | 35 -----
jambotron-ui/src/app/app.component.ts | 124 ------------------
jambotron-ui/src/app/app.ts | 4 +-
.../add-tutorial/add-tutorial.component.ts | 4 +-
.../tutorial-details.component.ts | 16 +--
.../tutorials-list.component.ts | 8 +-
.../tutorials.component.ts | 18 +--
.../src/app/helpers/auth.interceptor.ts | 44 +++++--
.../main.component/main.component.html | 19 +--
.../main.component/main.component.ts | 10 +-
.../src/app/services/tutorial.service.ts | 46 +++----
.../tutorial-add.component.scss | 0
.../tutorial-add.component.spec.ts | 23 ++++
.../tutorial-add.component.ts | 11 ++
.../tutorials-list.component.html | 3 +
.../tutorials-list.component.ts | 54 +++++++-
.../src/app/user-module/user-api.service.ts | 2 +-
.../user.component/user.component.ts | 4 +-
.../src/app/user-module/user.routing.ts | 4 +
.../jambotron/ZhiPuAi/ImageController.java | 6 +-
.../controllers/TutorialController.java | 18 +--
.../jambotron/security/WebSecurityConfig.java | 10 +-
.../security/jwt/AuthEntryPointJwt.java | 1 +
25 files changed, 217 insertions(+), 325 deletions(-)
delete mode 100644 jambotron-ui/src/app/app.component.html
delete mode 100644 jambotron-ui/src/app/app.component.scss
delete mode 100644 jambotron-ui/src/app/app.component.spec.ts
delete mode 100644 jambotron-ui/src/app/app.component.ts
create mode 100644 jambotron-ui/src/app/user-module/tutorial-add.component/tutorial-add.component.scss
create mode 100644 jambotron-ui/src/app/user-module/tutorial-add.component/tutorial-add.component.spec.ts
create mode 100644 jambotron-ui/src/app/user-module/tutorial-add.component/tutorial-add.component.ts
diff --git a/jambotron-ui/src/app/app.component.html b/jambotron-ui/src/app/app.component.html
deleted file mode 100644
index 85204c4..0000000
--- a/jambotron-ui/src/app/app.component.html
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
- @if (showAdminBoard) {
-
- }
-
- @if (showAdminBoard) {
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/jambotron-ui/src/app/app.component.scss b/jambotron-ui/src/app/app.component.scss
deleted file mode 100644
index fee240c..0000000
--- a/jambotron-ui/src/app/app.component.scss
+++ /dev/null
@@ -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%;
-}
diff --git a/jambotron-ui/src/app/app.component.spec.ts b/jambotron-ui/src/app/app.component.spec.ts
deleted file mode 100644
index 98d898f..0000000
--- a/jambotron-ui/src/app/app.component.spec.ts
+++ /dev/null
@@ -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!');
- });
-});
diff --git a/jambotron-ui/src/app/app.component.ts b/jambotron-ui/src/app/app.component.ts
deleted file mode 100644
index b51a698..0000000
--- a/jambotron-ui/src/app/app.component.ts
+++ /dev/null
@@ -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;
-}
-
diff --git a/jambotron-ui/src/app/app.ts b/jambotron-ui/src/app/app.ts
index 649c4a1..23348c4 100644
--- a/jambotron-ui/src/app/app.ts
+++ b/jambotron-ui/src/app/app.ts
@@ -12,5 +12,7 @@ import { RouterOutlet } from '@angular/router';
export class App {
protected title = 'jambotron-ui';
- constructor() { }
+ constructor() {
+
+ }
}
diff --git a/jambotron-ui/src/app/components/add-tutorial/add-tutorial.component.ts b/jambotron-ui/src/app/components/add-tutorial/add-tutorial.component.ts
index 3fe0470..be8a111 100644
--- a/jambotron-ui/src/app/components/add-tutorial/add-tutorial.component.ts
+++ b/jambotron-ui/src/app/components/add-tutorial/add-tutorial.component.ts
@@ -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 {
diff --git a/jambotron-ui/src/app/components/tutorial-details/tutorial-details.component.ts b/jambotron-ui/src/app/components/tutorial-details/tutorial-details.component.ts
index 96a88d3..3991df1 100644
--- a/jambotron-ui/src/app/components/tutorial-details/tutorial-details.component.ts
+++ b/jambotron-ui/src/app/components/tutorial-details/tutorial-details.component.ts
@@ -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);
- });
+ });*/
}
}
diff --git a/jambotron-ui/src/app/components/tutorials-list/tutorials-list.component.ts b/jambotron-ui/src/app/components/tutorials-list/tutorials-list.component.ts
index f1cdb3f..0442b48 100644
--- a/jambotron-ui/src/app/components/tutorials-list/tutorials-list.component.ts
+++ b/jambotron-ui/src/app/components/tutorials-list/tutorials-list.component.ts
@@ -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 {
diff --git a/jambotron-ui/src/app/components/tutorials.component/tutorials.component.ts b/jambotron-ui/src/app/components/tutorials.component/tutorials.component.ts
index 74325b8..d539f0d 100644
--- a/jambotron-ui/src/app/components/tutorials.component/tutorials.component.ts
+++ b/jambotron-ui/src/app/components/tutorials.component/tutorials.component.ts
@@ -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);
+ }
+ );
}
}
diff --git a/jambotron-ui/src/app/helpers/auth.interceptor.ts b/jambotron-ui/src/app/helpers/auth.interceptor.ts
index 6d52bee..390b93c 100644
--- a/jambotron-ui/src/app/helpers/auth.interceptor.ts
+++ b/jambotron-ui/src/app/helpers/auth.interceptor.ts
@@ -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, next: HttpHandler): Observable> {
-
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, 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);
}
}
diff --git a/jambotron-ui/src/app/main-module/main.component/main.component.html b/jambotron-ui/src/app/main-module/main.component/main.component.html
index 19894b2..3f83962 100644
--- a/jambotron-ui/src/app/main-module/main.component/main.component.html
+++ b/jambotron-ui/src/app/main-module/main.component/main.component.html
@@ -27,16 +27,19 @@
@if (showAdminBoard) {
-
+
+ }
+
+ @if (showUserBoard) {
+
}
-