Remove tenant parameter from APIs and admin UI (single-tenant mode)

This commit is contained in:
mberlin
2026-03-18 18:21:08 -03:00
parent 5f03c41a82
commit 989b19d338
6 changed files with 66 additions and 99 deletions

View File

@@ -74,10 +74,6 @@
<label>Contraseña</label> <label>Contraseña</label>
<input v-model="login.password" type="password" placeholder="••••••" /> <input v-model="login.password" type="password" placeholder="••••••" />
</div> </div>
<div class="field">
<label>Tenant</label>
<input v-model="login.tenantId" placeholder="default" />
</div>
<button :disabled="loading" @click="loginUser">Iniciar sesión</button> <button :disabled="loading" @click="loginUser">Iniciar sesión</button>
<div :class="{ error: loginError, success: loginSuccess }">{{ loginMessage }}</div> <div :class="{ error: loginError, success: loginSuccess }">{{ loginMessage }}</div>
@@ -96,10 +92,6 @@
<label>Contraseña</label> <label>Contraseña</label>
<input v-model="register.password" type="password" placeholder="••••••" /> <input v-model="register.password" type="password" placeholder="••••••" />
</div> </div>
<div class="field">
<label>Tenant</label>
<input v-model="register.tenantId" placeholder="default" />
</div>
<button :disabled="loading" @click="registerUser">Registrar</button> <button :disabled="loading" @click="registerUser">Registrar</button>
<div :class="{ error: registerError, success: registerSuccess }">{{ registerMessage }}</div> <div :class="{ error: registerError, success: registerSuccess }">{{ registerMessage }}</div>
</div> </div>
@@ -110,7 +102,7 @@
<div style="display:flex; align-items:center; justify-content:space-between;"> <div style="display:flex; align-items:center; justify-content:space-between;">
<div> <div>
<div><strong>{{ user?.name || user?.email }}</strong></div> <div><strong>{{ user?.name || user?.email }}</strong></div>
<div style="font-size:0.85rem; color:#555;">Tenant: {{ tenantId }}</div> <div style="font-size:0.85rem; color:#555;">Tenant: unificado</div>
</div> </div>
<button @click="logout">Salir</button> <button @click="logout">Salir</button>
</div> </div>
@@ -174,15 +166,15 @@
const token = ref(localStorage.getItem(tokenKey) || ''); const token = ref(localStorage.getItem(tokenKey) || '');
const user = ref(null); const user = ref(null);
const tenantId = ref('default'); const tenantId = ref('default'); // kept for compatibility (subdomain / future use)
const status = ref(''); const status = ref('');
const modules = ref([]); const modules = ref([]);
const selectedModule = ref(''); const selectedModule = ref('');
const moduleHtml = ref(''); const moduleHtml = ref('');
const loading = ref(false); const loading = ref(false);
const login = reactive({ email: '', password: '', tenantId: 'default' }); const login = reactive({ email: '', password: '' });
const register = reactive({ name: '', email: '', password: '', tenantId: 'default' }); const register = reactive({ name: '', email: '', password: '' });
const loginMessage = ref(''); const loginMessage = ref('');
const loginError = ref(false); const loginError = ref(false);
@@ -203,8 +195,7 @@
setStatus('Consultando ' + path + '...'); setStatus('Consultando ' + path + '...');
const headers = options.headers || {}; const headers = options.headers || {};
if (token.value) headers.Authorization = `Bearer ${token.value}`; if (token.value) headers.Authorization = `Bearer ${token.value}`;
headers['x-tenant-id'] = tenantId.value || 'default'; const res = await fetch(`${apiRoot}${path}`, {
const res = await fetch(`${apiRoot}${path}?tenantId=${encodeURIComponent(tenantId.value)}`, {
...options, ...options,
headers, headers,
}); });
@@ -236,7 +227,6 @@
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
tenantId: login.tenantId || 'default',
email: login.email, email: login.email,
password: login.password, password: login.password,
}), }),
@@ -270,7 +260,6 @@
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
tenantId: register.tenantId || 'default',
name: register.name, name: register.name,
email: register.email, email: register.email,
password: register.password, password: register.password,

View File

@@ -4,8 +4,6 @@ import { GuestService } from '../guest/services/guest.service';
import { TodoService } from '../todo/services/todo.service'; import { TodoService } from '../todo/services/todo.service';
import { ModuleRegistryService } from '../core/services/module-registry.service'; import { ModuleRegistryService } from '../core/services/module-registry.service';
const DEFAULT_TENANT = process.env.DEFAULT_TENANT_ID ?? 'default';
@Controller('admin') @Controller('admin')
export class AdminController { export class AdminController {
constructor( constructor(
@@ -20,94 +18,64 @@ export class AdminController {
return this.moduleRegistry.getModules(); return this.moduleRegistry.getModules();
} }
private getTenantId(tenantId?: string) {
return tenantId ?? DEFAULT_TENANT;
}
// Guests // Guests
@Get('guest') @Get('guest')
listGuests(@Query('tenantId') tenantId?: string) { listGuests() {
return this.guestService.listGuests(this.getTenantId(tenantId)); return this.guestService.listGuests();
} }
@Post('guest') @Post('guest')
createGuest( createGuest(@Body() body: any) {
@Query('tenantId') tenantId: string, return this.guestService.createGuest(body as any);
@Body() body: any,
) {
return this.guestService.createGuest(this.getTenantId(tenantId), body as any);
} }
@Patch('guest/:id/rsvp') @Patch('guest/:id/rsvp')
updateGuestRsvp( updateGuestRsvp(@Param('id') id: string, @Body() body: any) {
@Query('tenantId') tenantId: string, return this.guestService.updateRsvp(id, body as any);
@Param('id') id: string,
@Body() body: any,
) {
return this.guestService.updateRsvp(this.getTenantId(tenantId), id, body as any);
} }
// Todos // Todos
@Get('todo') @Get('todo')
listTodos(@Query('tenantId') tenantId?: string) { listTodos() {
return this.todoService.listTodos(this.getTenantId(tenantId)); return this.todoService.listTodos();
} }
@Post('todo') @Post('todo')
createTodo( createTodo(@Body() body: Record<string, any>) {
@Query('tenantId') tenantId: string, return this.todoService.createTodo(body);
@Body() body: Record<string, any>,
) {
return this.todoService.createTodo(this.getTenantId(tenantId), body);
} }
@Patch('todo/:id/complete') @Patch('todo/:id/complete')
completeTodo( completeTodo(@Param('id') id: string) {
@Query('tenantId') tenantId: string, return this.todoService.markComplete(id);
@Param('id') id: string,
) {
return this.todoService.markComplete(this.getTenantId(tenantId), id);
} }
// Gifts // Gifts
@Get('gift') @Get('gift')
listGifts(@Query('tenantId') tenantId?: string) { listGifts() {
return this.giftService.listGifts(this.getTenantId(tenantId)); return this.giftService.listGifts();
} }
@Post('gift') @Post('gift')
createGift( createGift(@Body() body: any) {
@Query('tenantId') tenantId: string, return this.giftService.createGift(body as any);
@Body() body: any,
) {
return this.giftService.createGift(this.getTenantId(tenantId), body as any);
} }
@Get('gift/:id') @Get('gift/:id')
getGift( getGift(@Param('id') id: string) {
@Query('tenantId') tenantId: string, return this.giftService.getGiftById(id);
@Param('id') id: string,
) {
return this.giftService.getGiftById(this.getTenantId(tenantId), id);
} }
@Post('gift/:id/contribution') @Post('gift/:id/contribution')
createContribution( createContribution(@Param('id') id: string, @Body() body: any) {
@Query('tenantId') tenantId: string, return this.giftService.createContribution({
@Param('id') id: string,
@Body() body: any,
) {
return this.giftService.createContribution(this.getTenantId(tenantId), {
...(body as any), ...(body as any),
giftId: id, giftId: id,
}); });
} }
@Get('gift/:id/contributions') @Get('gift/:id/contributions')
listContributions( listContributions(@Param('id') id: string) {
@Query('tenantId') tenantId: string, return this.giftService.listContributions(id);
@Param('id') id: string,
) {
return this.giftService.listContributions(this.getTenantId(tenantId), id);
} }
} }

View File

@@ -13,22 +13,19 @@ export class AuthController {
async register( async register(
@Body() @Body()
body: { body: {
tenantId?: string;
name?: string; name?: string;
email: string; email: string;
password: string; password: string;
}, },
) { ) {
const tenantId = body.tenantId || process.env.DEFAULT_TENANT_ID || 'default'; const tenantId = process.env.DEFAULT_TENANT_ID || 'default';
const user = await this.userService.createUser(tenantId, body.email, body.password, body.name); const user = await this.userService.createUser(tenantId, body.email, body.password, body.name);
return { id: user.id, email: user.email, name: user.name }; return { id: user.id, email: user.email, name: user.name };
} }
@Post('login') @Post('login')
async login( async login(@Body() body: { email: string; password: string }) {
@Body() body: { tenantId?: string; email: string; password: string }, const tenantId = process.env.DEFAULT_TENANT_ID || 'default';
) {
const tenantId = body.tenantId || process.env.DEFAULT_TENANT_ID || 'default';
const user = await this.userService.validateUser(tenantId, body.email, body.password); const user = await this.userService.validateUser(tenantId, body.email, body.password);
if (!user) { if (!user) {
return { message: 'Invalid credentials' }; return { message: 'Invalid credentials' };

View File

@@ -16,9 +16,14 @@ export class GiftService {
return this.orm.em.fork(); return this.orm.em.fork();
} }
async createGift(tenantId: string, dto: CreateGiftDto): Promise<Gift> { private getTenantId(): string {
// Tenant is now fixed; multi-tenant handled by reverse proxy (subdomains)
return process.env.DEFAULT_TENANT_ID || 'default';
}
async createGift(dto: CreateGiftDto): Promise<Gift> {
const gift = this.em.create(Gift, { const gift = this.em.create(Gift, {
tenantId, tenantId: this.getTenantId(),
...dto, ...dto,
} as any); } as any);
this.em.persist(gift); this.em.persist(gift);
@@ -27,9 +32,9 @@ export class GiftService {
return gift; return gift;
} }
async createContribution(tenantId: string, dto: CreateContributionDto): Promise<GiftContribution> { async createContribution(dto: CreateContributionDto): Promise<GiftContribution> {
const contribution = this.em.create(GiftContribution, { const contribution = this.em.create(GiftContribution, {
tenantId, tenantId: this.getTenantId(),
...dto, ...dto,
} as any); } as any);
this.em.persist(contribution); this.em.persist(contribution);
@@ -38,16 +43,15 @@ export class GiftService {
return contribution; return contribution;
} }
async listGifts(tenantId: string): Promise<Gift[]> { async listGifts(): Promise<Gift[]> {
return this.em.find(Gift, { tenantId }); return this.em.find(Gift, { tenantId: this.getTenantId() });
} }
async getGiftById( async getGiftById(
tenantId: string,
id: string, id: string,
requesterId?: string, requesterId?: string,
): Promise<Gift | null> { ): Promise<Gift | null> {
const gift = await this.em.findOne(Gift, { tenantId, id }); const gift = await this.em.findOne(Gift, { tenantId: this.getTenantId(), id });
if (!gift) return null; if (!gift) return null;
if (requesterId && gift.ownerId && gift.ownerId !== requesterId) { if (requesterId && gift.ownerId && gift.ownerId !== requesterId) {
return null; return null;
@@ -56,12 +60,11 @@ export class GiftService {
} }
async listContributions( async listContributions(
tenantId: string,
giftId: string, giftId: string,
requesterId?: string, requesterId?: string,
): Promise<GiftContribution[]> { ): Promise<GiftContribution[]> {
const gift = await this.getGiftById(tenantId, giftId, requesterId); const gift = await this.getGiftById(giftId, requesterId);
if (!gift) return []; if (!gift) return [];
return this.em.find(GiftContribution, { tenantId, giftId }); return this.em.find(GiftContribution, { tenantId: this.getTenantId(), giftId });
} }
} }

View File

@@ -16,9 +16,14 @@ export class GuestService {
return this.orm.em.fork(); return this.orm.em.fork();
} }
async createGuest(tenantId: string, dto: CreateGuestDto): Promise<Guest> { private getTenantId(): string {
// Tenant is now fixed; multi-tenant will be handled by routing (subdomains) later.
return process.env.DEFAULT_TENANT_ID || 'default';
}
async createGuest(dto: CreateGuestDto): Promise<Guest> {
const guest = this.em.create(Guest, { const guest = this.em.create(Guest, {
tenantId, tenantId: this.getTenantId(),
...dto, ...dto,
} as any); } as any);
this.em.persist(guest); this.em.persist(guest);
@@ -27,8 +32,8 @@ export class GuestService {
return guest; return guest;
} }
async updateRsvp(tenantId: string, guestId: string, dto: UpdateRsvpDto): Promise<Guest | null> { async updateRsvp(guestId: string, dto: UpdateRsvpDto): Promise<Guest | null> {
const guest = await this.em.findOne(Guest, { tenantId, id: guestId }); const guest = await this.em.findOne(Guest, { tenantId: this.getTenantId(), id: guestId });
if (!guest) return null; if (!guest) return null;
guest.rsvp = dto.rsvp; guest.rsvp = dto.rsvp;
if (dto.tableId) { if (dto.tableId) {
@@ -40,7 +45,7 @@ export class GuestService {
return guest; return guest;
} }
async listGuests(tenantId: string): Promise<Guest[]> { async listGuests(): Promise<Guest[]> {
return this.em.find(Guest, { tenantId }); return this.em.find(Guest, { tenantId: this.getTenantId() });
} }
} }

View File

@@ -14,9 +14,14 @@ export class TodoService {
return this.orm.em.fork(); return this.orm.em.fork();
} }
async createTodo(tenantId: string, dto: Partial<TodoItem>): Promise<TodoItem> { private getTenantId(): string {
// Tenant is now fixed; multi-tenant handled by reverse proxy (subdomains)
return process.env.DEFAULT_TENANT_ID || 'default';
}
async createTodo(dto: Partial<TodoItem>): Promise<TodoItem> {
const todo = this.em.create(TodoItem, { const todo = this.em.create(TodoItem, {
tenantId, tenantId: this.getTenantId(),
...dto, ...dto,
} as any); } as any);
this.em.persist(todo); this.em.persist(todo);
@@ -25,12 +30,12 @@ export class TodoService {
return todo; return todo;
} }
async listTodos(tenantId: string): Promise<TodoItem[]> { async listTodos(): Promise<TodoItem[]> {
return this.em.find(TodoItem, { tenantId }); return this.em.find(TodoItem, { tenantId: this.getTenantId() });
} }
async markComplete(tenantId: string, id: string): Promise<TodoItem | null> { async markComplete(id: string): Promise<TodoItem | null> {
const todo = await this.em.findOne(TodoItem, { tenantId, id }); const todo = await this.em.findOne(TodoItem, { tenantId: this.getTenantId(), id });
if (!todo) return null; if (!todo) return null;
todo.completed = true; todo.completed = true;
this.em.persist(todo); this.em.persist(todo);