Protects image upload, delete, and tag-update endpoints behind Bearer token auth. Public read endpoints remain open. Angular SPA gains a login page, auth interceptor, and route guard for /upload. - JWTAuthProvider (HS256, sub/iat/exp, secrets.compare_digest) - POST /api/v1/auth/token login endpoint - require_auth FastAPI dependency on all write routes - AuthService, LoginComponent, authInterceptor, authGuard - Detail page hides write controls for unauthenticated visitors - 43 unit tests passing; integration tests require Docker stack Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
32 lines
1.0 KiB
TypeScript
32 lines
1.0 KiB
TypeScript
import { Component } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { Router, RouterOutlet } from '@angular/router';
|
|
import { AuthService } from './auth/auth.service';
|
|
|
|
@Component({
|
|
selector: 'app-root',
|
|
standalone: true,
|
|
imports: [CommonModule, RouterOutlet],
|
|
template: `
|
|
<header class="app-header" *ngIf="auth.isAuthenticated()">
|
|
<button class="logout-btn" (click)="onLogout()">Sign out</button>
|
|
</header>
|
|
<router-outlet />
|
|
`,
|
|
styles: [`
|
|
.app-header { display: flex; justify-content: flex-end; padding: 8px 16px; background: #1a1a1a; border-bottom: 1px solid #333; }
|
|
.logout-btn { background: none; border: 1px solid #555; color: #aaa; padding: 4px 12px; border-radius: 4px; cursor: pointer; font-size: 0.9rem; }
|
|
.logout-btn:hover { border-color: #aaa; color: #e0e0e0; }
|
|
`],
|
|
})
|
|
export class AppComponent {
|
|
title = 'reactbin-ui';
|
|
|
|
constructor(public auth: AuthService, private router: Router) {}
|
|
|
|
onLogout(): void {
|
|
this.auth.logout();
|
|
this.router.navigate(['/login']);
|
|
}
|
|
}
|