Refonte du stockage des données utilisateur en sessionStorage et non avec des cookies

This commit is contained in:
guams 2025-04-17 22:35:39 +02:00
parent 3644414873
commit 3c4053ffcc
14 changed files with 118 additions and 98 deletions

View File

@ -30,12 +30,7 @@
"styles": [
"src/styles.css"
],
"scripts": [],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
"scripts": []
},
"configurations": {
"production": {

View File

@ -16,28 +16,33 @@ export class AuthService {
}
isAuthenticated(): boolean {
return this.cookieService.check("author") &&
this.cookieService.check("token") &&
this.cookieService.check("token-expiration-date") &&
this.cookieService.get("author") !== '' &&
this.cookieService.get("token-expiration-date") !== '' &&
this.cookieService.get("token") !== '';
return sessionStorage.getItem("author") !== null &&
sessionStorage.getItem("token") !== null &&
sessionStorage.getItem("token-expiration-date") !== null;
}
getTokenExpirationDate(): DateTime {
return DateTime.fromISO(this.cookieService.get("token-expiration-date"));
getTokenExpirationDate(): string | null {
return sessionStorage.getItem("token-expiration-date");
}
isSessionExpired(): boolean {
return this.getTokenExpirationDate() < DateTime.now() && this.isAuthenticated();
const tokenExpirationDate = this.getTokenExpirationDate();
if (tokenExpirationDate) {
return DateTime.fromISO(tokenExpirationDate) < DateTime.now() && this.isAuthenticated();
}
return true
}
getAuthenticatedAuthor(): Author {
return JSON.parse(this.cookieService.get('author'));
getAuthenticatedAuthor(): Author | null {
const authorStr = sessionStorage.getItem('author')
if (authorStr) {
return JSON.parse(authorStr);
}
return null;
}
getAuthenticatedAuthorToken(): string {
return this.cookieService.get('token');
getAuthenticatedAuthorToken(): string | null{
return sessionStorage.getItem('token');
}
setSessionExpired(expired: boolean) {

View File

@ -36,8 +36,8 @@ export class CommentFormComponent {
}
onSubmit() {
let token: string = this.authService.getAuthenticatedAuthorToken();
let author: Author = this.authService.getAuthenticatedAuthor();
let token = this.authService.getAuthenticatedAuthorToken();
let author = this.authService.getAuthenticatedAuthor();
if (this.commentForm.valid && author && token && this.commentForm.value.content) {
// get l'image de profile après avoir créé le commentaire
this.subs.push(this.commentService.create(this.commentForm.value.content, this.postId, author.id, token).subscribe({

View File

@ -25,8 +25,9 @@ export class HeaderComponent {
}
private initializeMenu(): void {
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated() && authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
}
if (this.actualAuthor) {

View File

@ -105,9 +105,9 @@ export class PostFormComponent implements OnDestroy {
if (this.isUpdateMode && this.postId) {
this.subs.push(
this.postService.updatePost(this.postId, postData, this.authService.getAuthenticatedAuthorToken()).pipe(
this.postService.updatePost(this.postId, postData, this.authService.getAuthenticatedAuthorToken()!).pipe(
mergeMap((_) => {
return this.postService.changeIllustration(this.postId, this.uploadedFile, this.authService.getAuthenticatedAuthorToken());
return this.postService.changeIllustration(this.postId, this.uploadedFile, this.authService.getAuthenticatedAuthorToken()!);
})
).subscribe({
next: (_) => {
@ -118,11 +118,11 @@ export class PostFormComponent implements OnDestroy {
);
} else {
this.subs.push(
this.postService.createPost(postData, this.authService.getAuthenticatedAuthorToken()).pipe(
this.postService.createPost(postData, this.authService.getAuthenticatedAuthorToken()!).pipe(
mergeMap(post =>
this.authorService.attributePost(this.actualAuthor?.id, post.id, this.authService.getAuthenticatedAuthorToken()).pipe(
this.authorService.attributePost(this.actualAuthor?.id, post.id, this.authService.getAuthenticatedAuthorToken()!).pipe(
mergeMap((_) =>
this.postService.changeIllustration(post.id, this.uploadedFile, this.authService.getAuthenticatedAuthorToken()),
this.postService.changeIllustration(post.id, this.uploadedFile, this.authService.getAuthenticatedAuthorToken()!),
)
)
)

View File

@ -37,7 +37,7 @@ export class RegisterFormComponent implements OnDestroy {
];
subs: Subscription[] = [];
form: FormGroup;
actualAuthor: Author | undefined;
actualAuthor: string | undefined;
constructor(private formBuilder: FormBuilder,
private authorService: AuthorService,
@ -45,8 +45,9 @@ export class RegisterFormComponent implements OnDestroy {
private messageService: MessageService,
private authService: AuthService,
) {
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthorToken();
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated() && authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
}
this.form = this.formBuilder.group({
username: ['', [Validators.required, Validators.maxLength(255)]],
@ -83,7 +84,7 @@ export class RegisterFormComponent implements OnDestroy {
this.username,
this.password,
this.role,
this.authService.getAuthenticatedAuthorToken()).subscribe({
this.authService.getAuthenticatedAuthorToken()!).subscribe({
next: (author: Author) => {
this.successMessage('Succès', `Auteur ${author.name} créé avec succès`);
this.createdAuthor.emit(author);

View File

@ -80,7 +80,7 @@ export class UpdateProfileFormComponent implements OnDestroy {
}
onSubmit() {
const token: string = this.authService.getAuthenticatedAuthorToken();
const token = this.authService.getAuthenticatedAuthorToken();
if (this.form.valid && token && this.password === this.passwordConfirm) {
const newUsername = this.form.value.username;
if (this.uploadedFile) {

View File

@ -1,17 +1,18 @@
import {CanActivateFn, Router} from '@angular/router';
import {inject} from '@angular/core';
import {CookieService} from 'ngx-cookie-service';
import {AuthService} from '../auth.service';
import {Role} from '../models/role';
export const writerGuard: CanActivateFn = (route, state) => {
const router = inject(Router);
const cookieService = inject(CookieService);
const authService = inject(AuthService);
const authorStr = sessionStorage.getItem("author");
if ((authService.isAuthenticated() && JSON.parse(cookieService.get("author")).role !== Role.WRITER) || !authService.isAuthenticated()) {
if (authorStr) {
if ((authService.isAuthenticated() && JSON.parse(authorStr).role !== Role.WRITER) || !authService.isAuthenticated()) {
router.navigate(['/']);
}
return true;
}
return false;
};

View File

@ -29,9 +29,9 @@ export class HomeComponent implements OnDestroy {
constructor(
private postService: PostService,
private authService: AuthService) {
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated() && authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
} else {
this.authService.checkSessionExpiration();
}

View File

@ -35,9 +35,9 @@ export class LoginComponent implements OnDestroy {
constructor(private authorService: AuthorService,
private messageService: MessageService,
private cookieService: CookieService,
private router: Router,
private configurationService: ConfigurationService,) {}
private configurationService: ConfigurationService,) {
}
sendLogins(): void {
if (this.password === this.confirmPassword) {
@ -45,26 +45,15 @@ export class LoginComponent implements OnDestroy {
(
this.authorService.login(this.name, this.password).pipe(
switchMap((tokenObj: any) => {
this.cookieService.delete('token', '/', this.configurationService.getDomain())
this.cookieService.set("token", tokenObj.token, {
domain: this.configurationService.getDomain(),
secure: true,
path: '/'
});
// sessionStorage.removeItem('token');
sessionStorage.setItem('token', tokenObj.token);
return this.authorService.me(tokenObj.token)
}))
.subscribe({
next: (author: Author) => {
this.cookieService.delete('author', '/', this.configurationService.getDomain())
this.cookieService.set("author", JSON.stringify(author), {
domain: this.configurationService.getDomain(),
secure : true,
path: '/' });
this.cookieService.set('token-expiration-date', DateTime.now().plus({millisecond: this.configurationService.getTokenTTL()}).toISO(), {
domain: this.configurationService.getDomain(),
secure: true,
path: '/',
})
// sessionStorage.removeItem('author');
sessionStorage.setItem('author', JSON.stringify(author));
sessionStorage.setItem('token-expiration-date', DateTime.now().plus({millisecond: this.configurationService.getTokenTTL()}).toISO())
this.getAuthorCookie();
this.router.navigate(['/']).then(() => {
this.successMessage('Connecté avec succès', 'Heureux de vous revoir ' + this.actualAuthor?.name)
@ -79,7 +68,10 @@ export class LoginComponent implements OnDestroy {
}
getAuthorCookie(): void {
this.actualAuthor = JSON.parse(this.cookieService.get("author"));
const authorStr = sessionStorage.getItem('author');
if (authorStr) {
this.actualAuthor = JSON.parse(authorStr);
}
}
successMessage(summary: string, detail: string): void {

View File

@ -37,14 +37,17 @@ export class MyPostsComponent implements OnDestroy {
updateDialogVisibility: boolean[] = [];
deleteDialogVisibility: boolean[] = [];
posts: Post[] = [];
actualAuthor: Author;
actualAuthor: Author | undefined;
constructor(private authService: AuthService,
private postService: PostService,
private authorService: AuthorService,
private messageService: MessageService) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
}
this.updatePosts();
}
@ -59,8 +62,9 @@ export class MyPostsComponent implements OnDestroy {
}
updatePosts(): void {
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.authorService.getAuthorsPosts(this.actualAuthor?.id, this.authService.getAuthenticatedAuthorToken()).subscribe({
const authorToken = this.authService.getAuthenticatedAuthorToken()
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated() && authorToken) {
this.authorService.getAuthorsPosts(this.actualAuthor?.id, authorToken).subscribe({
next: posts => this.posts = posts,
error: error => this.failureMessage("Erreur", error.error.message),
}
@ -71,13 +75,16 @@ export class MyPostsComponent implements OnDestroy {
}
deletePost(id: bigint, rowIndex: number) {
this.postService.deletePost(id, this.authService.getAuthenticatedAuthorToken()).subscribe({
const authorToken = this.authService.getAuthenticatedAuthorToken()
if (authorToken) {
this.postService.deletePost(id, authorToken).subscribe({
next: (_) => {
this.updatePosts()
this.successMessage("Post supprimé", "Ce post a été supprimé avec succès")
},
error: error => this.failureMessage("Erreur", error.error.message),
});
}
this.closeDialog(this.deleteDialogVisibility, rowIndex)
}

View File

@ -49,7 +49,10 @@ export class NewPostComponent implements OnDestroy {
category: ['', [Validators.required, Validators.maxLength(50)]],
});
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
}
} else {
this.authService.checkSessionExpiration();
}
@ -72,12 +75,14 @@ export class NewPostComponent implements OnDestroy {
category: formData.category as string
};
const authenticatedAuthor = this.authService.getAuthenticatedAuthorToken();
if (authenticatedAuthor) {
this.subs.push(
this.postService.createPost(postToPost, this.authService.getAuthenticatedAuthorToken()).pipe(
this.postService.createPost(postToPost, authenticatedAuthor).pipe(
mergeMap(post =>
this.authorService.attributePost(this.actualAuthor?.id, post.id, this.authService.getAuthenticatedAuthorToken()).pipe(
this.authorService.attributePost(this.actualAuthor?.id, post.id, authenticatedAuthor).pipe(
mergeMap((_) =>
this.postService.changeIllustration(post.id, this.uploadedFile, this.authService.getAuthenticatedAuthorToken()),
this.postService.changeIllustration(post.id, this.uploadedFile, authenticatedAuthor),
)
)
)
@ -92,6 +97,9 @@ export class NewPostComponent implements OnDestroy {
}
})
);
} else {
console.error("Profil mal chargé")
}
}
}

View File

@ -49,7 +49,12 @@ export class PostComponent {
private authService: AuthService,) {
this.route.paramMap.subscribe(params => {
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
} else {
console.error('Profil mal chargé');
}
} else {
this.authService.checkSessionExpiration();
}

View File

@ -43,7 +43,12 @@ export class ProfileComponent implements OnDestroy {
}));
})
if (!(this.authService.isSessionExpired()) && this.authService.isAuthenticated()) {
this.actualAuthor = this.authService.getAuthenticatedAuthor();
const authenticatedAuthor = this.authService.getAuthenticatedAuthor();
if (authenticatedAuthor) {
this.actualAuthor = authenticatedAuthor;
} else {
console.error("Profil mal chargé");
}
} else {
this.authService.checkSessionExpiration();
}