it0/packages/services/referral-service/src/interfaces/rest/controllers/referral-admin.controller.ts

90 lines
3.3 KiB
TypeScript

import {
Controller,
Get,
Query,
Headers,
UnauthorizedException,
ParseIntPipe,
DefaultValuePipe,
} from '@nestjs/common';
import { GetReferralListUseCase } from '../../../application/use-cases/get-referral-list.use-case';
import { ReferralRelationshipRepository } from '../../../infrastructure/repositories/referral-relationship.repository';
import { ReferralRewardRepository } from '../../../infrastructure/repositories/referral-reward.repository';
import { ReferralStatus } from '../../../domain/entities/referral-relationship.entity';
import { RewardStatus } from '../../../domain/entities/referral-reward.entity';
import * as jwt from 'jsonwebtoken';
/**
* Platform-admin endpoints for managing the referral system.
* Requires JWT with platform_admin or platform_super_admin role.
*/
@Controller('api/v1/referral/admin')
export class ReferralAdminController {
constructor(
private readonly getReferralList: GetReferralListUseCase,
private readonly relationshipRepo: ReferralRelationshipRepository,
private readonly rewardRepo: ReferralRewardRepository,
) {}
/** GET /api/v1/referral/admin/relationships — all referral relationships */
@Get('relationships')
async listRelationships(
@Headers('authorization') auth: string,
@Query('status') status: ReferralStatus | undefined,
@Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
@Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
) {
this.requireAdmin(auth);
return this.relationshipRepo.findAll(status, Math.min(limit, 200), offset);
}
/** GET /api/v1/referral/admin/rewards — all reward records */
@Get('rewards')
async listRewards(
@Headers('authorization') auth: string,
@Query('status') status: RewardStatus | undefined,
@Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
@Query('offset', new DefaultValuePipe(0), ParseIntPipe) offset: number,
) {
this.requireAdmin(auth);
return this.rewardRepo.findAll(status, Math.min(limit, 200), offset);
}
/** GET /api/v1/referral/admin/stats — global referral statistics */
@Get('stats')
async getStats(@Headers('authorization') auth: string) {
this.requireAdmin(auth);
const [totalRel, activeRel, pendingRewards] = await Promise.all([
this.relationshipRepo.findAll(undefined, 1, 0).then((r) => r.total),
this.relationshipRepo.findAll('ACTIVE', 1, 0).then((r) => r.total),
this.rewardRepo.findAll('PENDING', 1, 0).then((r) => r.total),
]);
return {
totalReferrals: totalRel,
activeReferrals: activeRel,
pendingRewards,
};
}
private requireAdmin(auth: string) {
if (!auth?.startsWith('Bearer ')) {
throw new UnauthorizedException('Missing authorization header');
}
const token = auth.slice(7);
const secret = process.env.JWT_SECRET || 'dev-secret';
try {
const payload = jwt.verify(token, secret) as any;
const roles: string[] = Array.isArray(payload.roles) ? payload.roles : [];
if (
!roles.includes('platform_admin') &&
!roles.includes('platform_super_admin')
) {
throw new UnauthorizedException('Admin role required');
}
} catch (err) {
if (err instanceof UnauthorizedException) throw err;
throw new UnauthorizedException('Invalid JWT');
}
}
}