Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

m1dnxt404/Multi-Tenant-AI-Analytics-Platform

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

19 Commits

Repository files navigation

Multi-Tenant AI Analytics Platform

A production-grade SaaS analytics platform with multi-tenant architecture, AI-powered insights, and role-based access control.

Tech Stack

Backend

  • Java 17 + Spring Boot 4.0.1
  • Spring Security 6 (JWT via HttpOnly cookies)
  • Hibernate 7 (multi-tenancy via BeanContainer provider resolution)
  • PostgreSQL + Flyway 12 migrations
  • Redis (caching, feature flags, usage counters) — Spring Data Redis 4.x with GenericJacksonJsonRedisSerializer
  • Lombok, SpringDoc OpenAPI 3 (springdoc-openapi 3.0.1)

Frontend

  • Next.js 14 (App Router)
  • TypeScript
  • TailwindCSS + ShadCN UI (Radix primitives)
  • Zustand (auth state)
  • Recharts (data visualization)
  • React Hook Form + Zod (validation)

Architecture Overview

Multi-Tenancy

Each organization gets its own PostgreSQL schema (tenant_{slug}). The public schema holds shared entities (users, organizations, memberships, invitations). Tenant routing happens per-request via:

JWT cookie → JwtAuthFilter → TenantResolutionFilter → TenantContextHolder → TenantIdentifierResolver → Hibernate SET search_path

TenantConnectionProvider and TenantIdentifierResolver are @Component beans registered with Hibernate 7 via class-name properties in application.yml. Hibernate resolves them through Spring's BeanContainer — no separate MultiTenancyConfig class required.

AI Insights

AiInsightEngine is the core interface. MockAiInsightEngine is active by default (@Primary). Claude and OpenAI engines are available as @Profile stubs — swap by activating the appropriate Spring profile and providing API keys.


Project Structure

.
├── backend/ # Spring Boot application
│ └── src/main/java/com/platform/analytics/
│ ├── ai/ # AI engine interface + implementations
│ ├── config/ # Security, CORS, OpenAPI, JPA config
│ ├── controller/ # REST controllers
│ ├── dto/ # Request/response DTOs
│ ├── exception/ # Custom exceptions + global handler
│ ├── model/ # JPA entities
│ ├── repository/ # Spring Data JPA repositories
│ ├── security/ # JWT filter, tenant filter, UserPrincipal
│ ├── seeder/ # Dev seed data (DataSeeder)
│ ├── service/ # Business logic
│ └── tenant/ # Multi-tenancy infrastructure
│ └── src/main/resources/
│ ├── application.yml # Base configuration
│ ├── application-dev.yml # Dev overrides (seed enabled, SQL logging)
│ └── db/migration/ # Flyway SQL migrations
│
└── frontend/ # Next.js application
 ├── app/
 │ ├── (auth)/ # Login, Register pages
 │ └── (dashboard)/ # Protected dashboard pages
 │ ├── page.tsx # Overview / KPI dashboard
 │ ├── datasets/ # Dataset list + detail
 │ ├── insights/ # AI insight list + detail
 │ ├── users/ # User management
 │ └── settings/ # Organization settings
 ├── components/
 │ ├── layout/ # Header, Sidebar, PageContainer
 │ ├── ui/ # ShadCN base components
 │ ├── dashboard/ # KpiCard, RevenueChart
 │ ├── datasets/ # UploadModal, DatasetTable
 │ ├── insights/ # InsightCard, GenerateInsightModal
 │ └── users/ # UserTable, InviteUserModal, RoleSelector
 ├── lib/api.ts # Typed API client (fetch + credentials)
 ├── store/useAuthStore.ts # Zustand auth store
 └── types/index.ts # Shared TypeScript types

Prerequisites

  • Java 17+
  • Maven 3.6.3+ (tested with 3.9.12)
  • Node.js 18+ and npm
  • PostgreSQL 14+
  • Redis 6+ (run via Docker: docker run -d -p 6379:6379 --name redis redis:alpine)

Getting Started

1. Database Setup

Create the database and user:

CREATE USER analytics WITH PASSWORD 'analytics';
CREATE DATABASE analytics_platform OWNER analytics;
GRANT ALL PRIVILEGES ON DATABASE analytics_platform TO analytics;

2. Backend

cd backend
# Run with dev profile (enables seed data)
mvn spring-boot:run -Dspring-boot.run.profiles=dev

The API starts on http://localhost:8080. Swagger UI: http://localhost:8080/swagger-ui.html

Environment variables (optional overrides):

Variable Default Description
DB_USER analytics PostgreSQL username
DB_PASSWORD analytics PostgreSQL password
JWT_SECRET (hardcoded dev secret) JWT signing key
CORS_ORIGINS http://localhost:3000 Allowed frontend origin
COOKIE_SECURE false Set true in production
FILE_UPLOAD_DIR ./uploads CSV upload directory
REDIS_HOST localhost Redis server hostname
REDIS_PORT 6379 Redis server port
REDIS_PASSWORD (empty) Redis password (if any)

3. Frontend

cd frontend
npm install
npm run dev

The app starts on http://localhost:3000.


Seed Data (Dev Profile)

When running with --spring.profiles.active=dev, the DataSeeder creates two organizations with sample users and datasets:

Email Password Role Organization
alice@acme.com Password123! OWNER Acme Corp
carol@acme.com Password123! MEMBER Acme Corp
dave@acme.com Password123! VIEWER Acme Corp
david@techstart.io Password123! OWNER TechStart

API Overview

All endpoints are prefixed with /api. Authentication uses HttpOnly JWT cookies set on login.

Method Endpoint Description Min Role
POST /api/auth/register Register + create organization Public
POST /api/auth/login Login (sets JWT cookie) Public
POST /api/auth/logout Clear JWT cookie Any
GET /api/auth/me Current user + organization Any
GET /api/datasets List datasets (paginated) VIEWER
POST /api/datasets Upload CSV dataset MEMBER
GET /api/datasets/{id} Dataset detail with columns VIEWER
DELETE /api/datasets/{id} Delete dataset ADMIN
GET /api/insights List AI insights (paginated) VIEWER
POST /api/insights/generate Generate insight for dataset MEMBER
GET /api/insights/{id} Insight detail VIEWER
GET /api/users List org members (paginated) ADMIN
POST /api/users/invite Invite user by email ADMIN
PATCH /api/users/{id}/role Update member role ADMIN
DELETE /api/users/{id} Remove member from org OWNER
GET /api/organization Get organization details Any
PUT /api/organization Update organization name/slug OWNER
GET /api/audit Audit log (paginated) ADMIN
GET /api/features List feature flags ADMIN
PUT /api/features/{flag}?enabled= Set feature flag on/off OWNER
DELETE /api/features/{flag} Delete feature flag OWNER
GET /api/usage Today's usage counters ADMIN

Roles

Role Capabilities
OWNER Full access — all admin actions + remove members + delete org
ADMIN Invite/remove members, change roles, manage datasets
MEMBER Upload datasets, generate insights
VIEWER Read-only access to datasets and insights

AI Engines

Switch the active AI engine via Spring profiles:

# Use Claude (requires ANTHROPIC_API_KEY env var)
mvn spring-boot:run -Dspring-boot.run.profiles=dev,claude
# Use OpenAI (requires OPENAI_API_KEY env var)
mvn spring-boot:run -Dspring-boot.run.profiles=dev,openai
# Default: mock engine (no API key needed)
mvn spring-boot:run -Dspring-boot.run.profiles=dev

Production Checklist

  • Set a strong JWT_SECRET (min 256-bit random key)
  • Set REDIS_HOST, REDIS_PORT, REDIS_PASSWORD for production Redis
  • Enable Redis authentication (requirepass) in production
  • Set COOKIE_SECURE=true (HTTPS only)
  • Set CORS_ORIGINS to your production frontend domain
  • Use strong database credentials (not defaults)
  • Disable flyway.clean-disabled=false (it is dev-only)
  • Set app.seed.enabled=false (or omit dev profile)
  • Configure FILE_UPLOAD_DIR to a persistent volume
  • Set logging.level to WARN or ERROR

About

A production-grade SaaS analytics platform with multi-tenant architecture, AI-powered insights, and role-based access control.

Topics

Resources

Stars

Watchers

Forks

Contributors

AltStyle によって変換されたページ (->オリジナル) /