feat: security and auditing

This commit is contained in:
2026-02-04 16:48:08 -08:00
parent 11be34cd21
commit 0a654f423a
42 changed files with 2195 additions and 160 deletions
@@ -10,6 +10,7 @@ import { FormsModule } from '@angular/forms';
import { MangaService } from '../../services/manga.service';
import { AuthService } from '../../services/auth.service';
import { CommentsService } from '../../services/comments.service';
import { SanitizeService } from '../../services/sanitize.service';
import { Manga, MangaStatus, CreateMangaDto, UpdateMangaDto, Comment } from '@library/shared-types';
@Component({
@@ -282,15 +283,21 @@ import { Manga, MangaStatus, CreateMangaDto, UpdateMangaDto, Comment } from '@li
@if (expandedComments()[manga.id]) {
<div class="comments-container">
@if (authService.isAuthenticated()) {
<form (ngSubmit)="addComment(manga.id)" class="comment-form">
<textarea
[(ngModel)]="newCommentContent[manga.id]"
name="comment"
placeholder="Add a comment (Markdown supported)..."
rows="2"
></textarea>
<button type="submit" class="btn btn-primary btn-sm">Post Comment</button>
</form>
@if (authService.user()?.isBanned) {
<div class="banned-notice">
You have been banned from commenting.
</div>
} @else {
<form (ngSubmit)="addComment(manga.id)" class="comment-form">
<textarea
[(ngModel)]="newCommentContent[manga.id]"
name="comment"
placeholder="Add a comment (Markdown supported)..."
rows="2"
></textarea>
<button type="submit" class="btn btn-primary btn-sm">Post Comment</button>
</form>
}
}
@if (commentsLoading()[manga.id]) {
@@ -308,7 +315,7 @@ import { Manga, MangaStatus, CreateMangaDto, UpdateMangaDto, Comment } from '@li
<button (click)="deleteComment(manga.id, comment.id)" class="btn btn-danger btn-xs">Delete</button>
}
</div>
<div class="comment-content" [innerHTML]="comment.content"></div>
<div class="comment-content" [innerHTML]="sanitizeService.sanitizeHtml(comment.content)"></div>
</div>
} @empty {
<div class="no-comments">No comments yet. Be the first to comment!</div>
@@ -584,6 +591,17 @@ import { Manga, MangaStatus, CreateMangaDto, UpdateMangaDto, Comment } from '@li
font-size: 0.9rem;
}
.banned-notice {
background: #fef2f2;
border: 1px solid #fecaca;
color: #991b1b;
padding: 0.75rem 1rem;
border-radius: 4px;
text-align: center;
margin-bottom: 1rem;
font-size: 0.9rem;
}
.image-preview {
margin-top: 0.5rem;
display: flex;
@@ -622,6 +640,7 @@ export class MangaListComponent implements OnInit {
mangaService = inject(MangaService);
authService = inject(AuthService);
commentsService = inject(CommentsService);
sanitizeService = inject(SanitizeService);
mangaList = signal<Manga[]>([]);
loading = signal(true);