37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import { CanActivate, ExecutionContext, ForbiddenException, Injectable, NotFoundException } from '@nestjs/common';
|
|
import { eq } from 'drizzle-orm';
|
|
import { DrizzleService } from '../../database/drizzle.service';
|
|
import { profile } from '../../database/schema';
|
|
|
|
/**
|
|
* Verifies that the profileId in request body/params belongs to the authenticated user.
|
|
* Expects profileId in: params.profileId OR body.profileId OR query.profileId
|
|
*/
|
|
@Injectable()
|
|
export class ProfileOwnerGuard implements CanActivate {
|
|
constructor(private readonly drizzleService: DrizzleService) {}
|
|
|
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
const request = context.switchToHttp().getRequest();
|
|
const userId = request.user?.id;
|
|
const profileId =
|
|
request.params?.profileId ||
|
|
request.body?.profileId ||
|
|
request.query?.profileId;
|
|
|
|
if (!profileId) return true;
|
|
|
|
const [found] = await this.drizzleService.db
|
|
.select({ id: profile.id, userId: profile.userId })
|
|
.from(profile)
|
|
.where(eq(profile.id, profileId))
|
|
.limit(1);
|
|
|
|
if (!found) throw new NotFoundException('Profile not found');
|
|
if (found.userId !== userId) throw new ForbiddenException('Profile does not belong to you');
|
|
|
|
request.profile = found;
|
|
return true;
|
|
}
|
|
}
|