69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import {
|
|
Controller,
|
|
ForbiddenException,
|
|
Get,
|
|
NotFoundException,
|
|
Param,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { AuthGuard } from '../auth/auth.guard.js';
|
|
import { CurrentUser } from '../auth/current-user.decorator.js';
|
|
import { TeamsService } from './teams.service.js';
|
|
|
|
type RequestUser = { id: string; role?: string };
|
|
|
|
@Controller('api/teams')
|
|
@UseGuards(AuthGuard)
|
|
export class TeamsController {
|
|
constructor(private readonly teams: TeamsService) {}
|
|
|
|
@Get()
|
|
async list(@CurrentUser() user: RequestUser) {
|
|
if (user.role === 'admin') {
|
|
return this.teams.findAll();
|
|
}
|
|
return this.teams.findAllForUser(user.id);
|
|
}
|
|
|
|
@Get(':teamId')
|
|
async findOne(@Param('teamId') teamId: string, @CurrentUser() user: RequestUser) {
|
|
return this.getAccessibleTeam(teamId, user);
|
|
}
|
|
|
|
@Get(':teamId/members')
|
|
async listMembers(@Param('teamId') teamId: string, @CurrentUser() user: RequestUser) {
|
|
await this.getAccessibleTeam(teamId, user);
|
|
return this.teams.listMembers(teamId);
|
|
}
|
|
|
|
@Get(':teamId/members/:userId')
|
|
async checkMembership(
|
|
@Param('teamId') teamId: string,
|
|
@Param('userId') userId: string,
|
|
@CurrentUser() user: RequestUser,
|
|
) {
|
|
// A user may always ask about their own membership; anything else is
|
|
// team-scoped like the other routes.
|
|
if (userId !== user.id) {
|
|
await this.getAccessibleTeam(teamId, user);
|
|
}
|
|
const isMember = await this.teams.isMember(teamId, userId);
|
|
return { isMember };
|
|
}
|
|
|
|
/**
|
|
* Team-scoped access: admins see any team; everyone else only teams they
|
|
* are a member of. NotFoundException when the team does not exist and
|
|
* ForbiddenException when the user lacks access (same convention as the
|
|
* projects controller).
|
|
*/
|
|
private async getAccessibleTeam(teamId: string, user: RequestUser) {
|
|
const team = await this.teams.findById(teamId);
|
|
if (!team) throw new NotFoundException('Team not found');
|
|
if (user.role === 'admin') return team;
|
|
const isMember = await this.teams.isMember(teamId, user.id);
|
|
if (!isMember) throw new ForbiddenException('Not a member of this team');
|
|
return team;
|
|
}
|
|
}
|