Add modular admin CRUD UI, fix MikroORM migrations/config and update static admin routing
This commit is contained in:
@@ -1,12 +1,113 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Patch, Post, Query } from '@nestjs/common';
|
||||
import { GiftService } from '../gift/services/gift.service';
|
||||
import { GuestService } from '../guest/services/guest.service';
|
||||
import { TodoService } from '../todo/services/todo.service';
|
||||
import { ModuleRegistryService } from '../core/services/module-registry.service';
|
||||
|
||||
const DEFAULT_TENANT = process.env.DEFAULT_TENANT_ID ?? 'default';
|
||||
|
||||
@Controller('admin')
|
||||
export class AdminController {
|
||||
constructor(private readonly moduleRegistry: ModuleRegistryService) {}
|
||||
constructor(
|
||||
private readonly moduleRegistry: ModuleRegistryService,
|
||||
private readonly guestService: GuestService,
|
||||
private readonly giftService: GiftService,
|
||||
private readonly todoService: TodoService,
|
||||
) {}
|
||||
|
||||
@Get('modules')
|
||||
getModules() {
|
||||
return this.moduleRegistry.getModules();
|
||||
}
|
||||
|
||||
private getTenantId(tenantId?: string) {
|
||||
return tenantId ?? DEFAULT_TENANT;
|
||||
}
|
||||
|
||||
// Guests
|
||||
@Get('guest')
|
||||
listGuests(@Query('tenantId') tenantId?: string) {
|
||||
return this.guestService.listGuests(this.getTenantId(tenantId));
|
||||
}
|
||||
|
||||
@Post('guest')
|
||||
createGuest(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Body() body: any,
|
||||
) {
|
||||
return this.guestService.createGuest(this.getTenantId(tenantId), body as any);
|
||||
}
|
||||
|
||||
@Patch('guest/:id/rsvp')
|
||||
updateGuestRsvp(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Param('id') id: string,
|
||||
@Body() body: any,
|
||||
) {
|
||||
return this.guestService.updateRsvp(this.getTenantId(tenantId), id, body as any);
|
||||
}
|
||||
|
||||
// Todos
|
||||
@Get('todo')
|
||||
listTodos(@Query('tenantId') tenantId?: string) {
|
||||
return this.todoService.listTodos(this.getTenantId(tenantId));
|
||||
}
|
||||
|
||||
@Post('todo')
|
||||
createTodo(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Body() body: Record<string, any>,
|
||||
) {
|
||||
return this.todoService.createTodo(this.getTenantId(tenantId), body);
|
||||
}
|
||||
|
||||
@Patch('todo/:id/complete')
|
||||
completeTodo(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
return this.todoService.markComplete(this.getTenantId(tenantId), id);
|
||||
}
|
||||
|
||||
// Gifts
|
||||
@Get('gift')
|
||||
listGifts(@Query('tenantId') tenantId?: string) {
|
||||
return this.giftService.listGifts(this.getTenantId(tenantId));
|
||||
}
|
||||
|
||||
@Post('gift')
|
||||
createGift(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Body() body: any,
|
||||
) {
|
||||
return this.giftService.createGift(this.getTenantId(tenantId), body as any);
|
||||
}
|
||||
|
||||
@Get('gift/:id')
|
||||
getGift(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
return this.giftService.getGiftById(this.getTenantId(tenantId), id);
|
||||
}
|
||||
|
||||
@Post('gift/:id/contribution')
|
||||
createContribution(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Param('id') id: string,
|
||||
@Body() body: any,
|
||||
) {
|
||||
return this.giftService.createContribution(this.getTenantId(tenantId), {
|
||||
...(body as any),
|
||||
giftId: id,
|
||||
});
|
||||
}
|
||||
|
||||
@Get('gift/:id/contributions')
|
||||
listContributions(
|
||||
@Query('tenantId') tenantId: string,
|
||||
@Param('id') id: string,
|
||||
) {
|
||||
return this.giftService.listContributions(this.getTenantId(tenantId), id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MikroOrmModule } from '@mikro-orm/nestjs';
|
||||
import { CoreModule } from '../core/core.module';
|
||||
import { GiftModule } from '../gift/gift.module';
|
||||
import { GuestModule } from '../guest/guest.module';
|
||||
import { TodoModule } from '../todo/todo.module';
|
||||
import { AdminController } from './admin.controller';
|
||||
import { ModuleRegistryService } from '../core/services/module-registry.service';
|
||||
|
||||
@Module({
|
||||
imports: [CoreModule, MikroOrmModule.forFeature([])],
|
||||
imports: [CoreModule, GiftModule, GuestModule, TodoModule],
|
||||
controllers: [AdminController],
|
||||
providers: [ModuleRegistryService],
|
||||
exports: [ModuleRegistryService],
|
||||
})
|
||||
export class AdminModule {}
|
||||
|
||||
@@ -12,6 +12,10 @@ import { AdminModule } from './admin/admin.module';
|
||||
ServeStaticModule.forRoot({
|
||||
rootPath: join(__dirname, '..', 'public'),
|
||||
serveRoot: '/admin',
|
||||
exclude: ['/admin/modules'],
|
||||
serveStaticOptions: {
|
||||
index: 'admin.html',
|
||||
},
|
||||
}),
|
||||
CoreModule,
|
||||
GiftModule,
|
||||
|
||||
@@ -7,6 +7,13 @@ export class AuthGuard implements CanActivate {
|
||||
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
|
||||
// Allow the admin UI endpoints to be accessed without authentication.
|
||||
// The UI is served from /admin and calls /api/admin/modules.
|
||||
if (request.method === 'GET' && request.url?.startsWith('/api/admin')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const authHeader = request.headers['authorization'] || '';
|
||||
const token = Array.isArray(authHeader) ? authHeader[0] : authHeader;
|
||||
if (!token) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { NotificationRuleSchema } from './entities/notification-rule.entity';
|
||||
user: process.env.DB_USER || 'postgres',
|
||||
password: process.env.DB_PASSWORD || 'postgres',
|
||||
dbName: process.env.DB_NAME || 'planner',
|
||||
autoLoadEntities: false,
|
||||
autoLoadEntities: true,
|
||||
migrations: {
|
||||
path: 'dist/migrations',
|
||||
transactional: true,
|
||||
|
||||
Reference in New Issue
Block a user