feat(guild): enable CORS and add members listing API

This commit is contained in:
nav
2026-05-14 16:46:30 +00:00
parent fdb661f32b
commit 9ad6ccaa3d
5 changed files with 65 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ import { ChannelsModule } from './channels/channels.module';
import { MessagingModule } from './messaging/messaging.module'; import { MessagingModule } from './messaging/messaging.module';
import { EventsModule } from './events/events.module'; import { EventsModule } from './events/events.module';
import { RealtimeModule } from './realtime/realtime.module'; import { RealtimeModule } from './realtime/realtime.module';
import { MembersModule } from './members/members.module';
@Module({ @Module({
imports: [ imports: [
@@ -19,6 +20,7 @@ import { RealtimeModule } from './realtime/realtime.module';
RealtimeModule, RealtimeModule,
GuildsModule, GuildsModule,
ChannelsModule, ChannelsModule,
MembersModule,
MessagingModule, MessagingModule,
], ],
controllers: [HealthController, MetricsController], controllers: [HealthController, MetricsController],

View File

@@ -24,6 +24,23 @@ async function bootstrap() {
validateEnv(); validateEnv();
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
const corsOrigins = (process.env.FABRIC_BACKEND_GUILD_CORS_ORIGINS ?? '')
.split(',')
.map((x) => x.trim())
.filter(Boolean);
app.enableCors({
origin: (origin, callback) => {
if (!origin) return callback(null, true);
if (origin === 'null') return callback(null, true);
if (!corsOrigins.length) return callback(null, true);
if (corsOrigins.includes(origin)) return callback(null, true);
return callback(new Error('CORS origin not allowed'), false);
},
methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'x-client-name', 'x-request-id', 'x-api-key'],
credentials: false,
});
app.setGlobalPrefix('api'); app.setGlobalPrefix('api');
const metrics = app.get(MetricsService); const metrics = app.get(MetricsService);
app.use(createRequestContextMiddleware('guild', metrics)); app.use(createRequestContextMiddleware('guild', metrics));

View File

@@ -0,0 +1,13 @@
import { Controller, Get, Query } from '@nestjs/common';
import { MembersService } from './members.service';
@Controller('members')
export class MembersController {
constructor(private readonly membersService: MembersService) {}
@Get()
list(@Query('guildId') guildId?: string) {
return this.membersService.list(guildId);
}
}

View File

@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GuildMember } from '../entities/guild-member.entity';
import { MembersController } from './members.controller';
import { MembersService } from './members.service';
@Module({
imports: [TypeOrmModule.forFeature([GuildMember])],
controllers: [MembersController],
providers: [MembersService],
})
export class MembersModule {}

View File

@@ -0,0 +1,20 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { GuildMember } from '../entities/guild-member.entity';
@Injectable()
export class MembersService {
constructor(
@InjectRepository(GuildMember)
private readonly memberRepo: Repository<GuildMember>,
) {}
list(guildId?: string) {
if (guildId) {
return this.memberRepo.find({ where: { guildId, status: 'active' }, order: { createdAt: 'ASC' }, take: 500 });
}
return this.memberRepo.find({ where: { status: 'active' }, order: { createdAt: 'ASC' }, take: 500 });
}
}