- 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>
64 lines
1.5 KiB
TypeScript
64 lines
1.5 KiB
TypeScript
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
CreateDateColumn,
|
|
UpdateDateColumn,
|
|
OneToMany,
|
|
} from 'typeorm';
|
|
import { UserOrganization } from '../../organizations/entities/user-organization.entity';
|
|
|
|
@Entity({ schema: 'shared', name: 'users' })
|
|
export class User {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ unique: true })
|
|
email: string;
|
|
|
|
@Column({ name: 'password_hash', nullable: true })
|
|
passwordHash: string;
|
|
|
|
@Column({ name: 'first_name', nullable: true })
|
|
firstName: string;
|
|
|
|
@Column({ name: 'last_name', nullable: true })
|
|
lastName: string;
|
|
|
|
@Column({ nullable: true })
|
|
phone: string;
|
|
|
|
@Column({ name: 'is_email_verified', default: false })
|
|
isEmailVerified: boolean;
|
|
|
|
@Column({ name: 'mfa_enabled', default: false })
|
|
mfaEnabled: boolean;
|
|
|
|
@Column({ name: 'mfa_secret', nullable: true })
|
|
mfaSecret: string;
|
|
|
|
@Column({ name: 'oauth_provider', nullable: true })
|
|
oauthProvider: string;
|
|
|
|
@Column({ name: 'oauth_provider_id', nullable: true })
|
|
oauthProviderId: string;
|
|
|
|
@Column({ name: 'is_superadmin', default: false })
|
|
isSuperadmin: boolean;
|
|
|
|
@Column({ name: 'is_platform_owner', default: false })
|
|
isPlatformOwner: boolean;
|
|
|
|
@Column({ name: 'last_login_at', type: 'timestamptz', nullable: true })
|
|
lastLoginAt: Date;
|
|
|
|
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
createdAt: Date;
|
|
|
|
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
updatedAt: Date;
|
|
|
|
@OneToMany(() => UserOrganization, (uo) => uo.user)
|
|
userOrganizations: UserOrganization[];
|
|
}
|