Add comprehensive platform administration panel
- Database: Add login_history, ai_recommendation_log tables; is_platform_owner column on users; subscription fields on organizations (payment_date, confirmation_number, renewal_date) - Backend: New AdminAnalyticsService with platform metrics, tenant detail, and health score calculations (0-100 based on activity, budget, transactions, members, AI usage) - Backend: Login/org-switch now records to login_history; AI recommendations logged to ai_recommendation_log; platform owner protected from superadmin toggle - Frontend: 4-tab admin panel (Dashboard, Organizations, Users, Tenant Health) with tenant detail drawer, subscription management, health scoring visualization - Platform owner account (admin@hoaledgeriq.com) auto-redirects to admin panel - Seed data includes platform owner account and sample login history Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, ForbiddenException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { User } from './entities/user.entity';
|
||||
@@ -50,13 +50,19 @@ export class UsersService {
|
||||
const dataSource = this.usersRepository.manager.connection;
|
||||
return dataSource.query(`
|
||||
SELECT o.*,
|
||||
(SELECT COUNT(*) FROM shared.user_organizations WHERE organization_id = o.id) as member_count
|
||||
(SELECT COUNT(*) FROM shared.user_organizations WHERE organization_id = o.id) as member_count,
|
||||
(SELECT MAX(lh.logged_in_at) FROM shared.login_history lh WHERE lh.organization_id = o.id) as last_activity
|
||||
FROM shared.organizations o
|
||||
ORDER BY o.created_at DESC
|
||||
`);
|
||||
}
|
||||
|
||||
async setSuperadmin(userId: string, isSuperadmin: boolean): Promise<void> {
|
||||
// Protect platform owner from having superadmin removed
|
||||
const user = await this.usersRepository.findOne({ where: { id: userId } });
|
||||
if (user?.isPlatformOwner) {
|
||||
throw new ForbiddenException('Cannot modify platform owner superadmin status');
|
||||
}
|
||||
await this.usersRepository.update(userId, { isSuperadmin });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user