init: scaffold complet Sakuin — backend NestJS + frontend SvelteKit + CI/CD + deploy VPS
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 29s

Backend: 5 modules (auth, user, work, list, health), AniList GraphQL proxy,
SuperOAuth PKCE introspection, XP system, migrations TypeORM.
Frontend: SvelteKit adapter-node, PWA manifest, dark theme, pages home/search/list/profile/callback.
Infra: CI/CD Gitea vps-runner, Apache vhost SSL, pm2 sakuin-backend + sakuin-frontend, port 4002.
License: BSL 1.1 (Apache 2.0 en 2028).
This commit is contained in:
2026-03-25 01:43:32 +01:00
commit f1cff74d83
56 changed files with 9891 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private readonly configService: ConfigService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractToken(request);
if (!token) {
throw new UnauthorizedException('No token provided');
}
const userInfo = await this.introspect(token);
if (!userInfo) {
throw new UnauthorizedException('Invalid token');
}
request.user = userInfo;
return true;
}
private extractToken(request: any): string | null {
const authHeader = request.headers.authorization;
if (authHeader?.startsWith('Bearer ')) {
return authHeader.slice(7);
}
return request.cookies?.access_token || null;
}
private async introspect(token: string): Promise<any> {
const url = this.configService.get('SUPEROAUTH_URL');
try {
const res = await fetch(`${url}/api/v1/user/profile`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) return null;
return res.json();
} catch {
return null;
}
}
}

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Module({
providers: [AuthGuard],
exports: [AuthGuard],
})
export class AuthModule {}