feat: reorganize admin settings with tabbed interface and documentation
- Reorganized admin settings into tabbed interface (General, Security, Payment Methods) - Vertical tabs on desktop, horizontal scrollable on mobile - Moved Payment Methods from separate menu to Settings tab - Fixed admin profile reuse and dashboard blocking - Fixed maintenance mode guard to use AppConfig model - Added admin auto-redirect after login (admins → /admin, users → /) - Reorganized documentation into docs/ folder structure - Created comprehensive README and documentation index - Added PWA and Web Push notifications to to-do list
This commit is contained in:
72
apps/api/src/common/guards/maintenance.guard.ts
Normal file
72
apps/api/src/common/guards/maintenance.guard.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import {
|
||||
Injectable,
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
ServiceUnavailableException,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
|
||||
@Injectable()
|
||||
export class MaintenanceGuard implements CanActivate {
|
||||
constructor(
|
||||
private reflector: Reflector,
|
||||
private prisma: PrismaService,
|
||||
private jwtService: JwtService,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
// Check if route is exempt from maintenance mode (auth, health, admin routes)
|
||||
const isExempt = this.reflector.get<boolean>('skipMaintenance', context.getHandler());
|
||||
const isControllerExempt = this.reflector.get<boolean>('skipMaintenance', context.getClass());
|
||||
|
||||
if (isExempt || isControllerExempt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get maintenance mode status from config
|
||||
const maintenanceConfig = await this.prisma.appConfig.findUnique({
|
||||
where: { key: 'maintenance_mode' },
|
||||
});
|
||||
|
||||
const isMaintenanceMode = maintenanceConfig?.value === 'true';
|
||||
|
||||
if (!isMaintenanceMode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to extract user from JWT token (if exists)
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const authHeader = request.headers.authorization;
|
||||
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
try {
|
||||
const token = authHeader.substring(7);
|
||||
const payload = this.jwtService.verify(token);
|
||||
|
||||
// If user is admin, allow access
|
||||
if (payload.role === 'admin') {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
// Invalid token, continue to block
|
||||
}
|
||||
}
|
||||
|
||||
// Get maintenance message
|
||||
const messageConfig = await this.prisma.appConfig.findUnique({
|
||||
where: { key: 'maintenance_message' },
|
||||
});
|
||||
|
||||
const message =
|
||||
messageConfig?.value ||
|
||||
'System is under maintenance. Please try again later.';
|
||||
|
||||
throw new ServiceUnavailableException({
|
||||
statusCode: 503,
|
||||
message: message,
|
||||
maintenanceMode: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user