Remove multi-tenant company_id scoping from entire codebase
Drop company_id column from all 22 domain tables via migration. Remove companyId from JWT payload, auth plugins, all service method signatures (~215 occurrences), all route handlers (~105 occurrences), test runner, test suites, and frontend auth store/types. The company table stays as store settings (name, timezone). Tenant isolation in a SaaS deployment would be at the database level (one DB per customer) not the application level. All 107 API tests pass. Zero TSC errors across all packages.
This commit is contained in:
@@ -11,7 +11,6 @@ interface User {
|
||||
interface AuthState {
|
||||
token: string | null
|
||||
user: User | null
|
||||
companyId: string | null
|
||||
permissions: Set<string>
|
||||
permissionsLoaded: boolean
|
||||
setAuth: (token: string, user: User) => void
|
||||
@@ -49,12 +48,7 @@ function expandPermissions(slugs: string[]): Set<string> {
|
||||
return expanded
|
||||
}
|
||||
|
||||
function decodeJwtPayload(token: string): { id: string; companyId: string; role: string } {
|
||||
const payload = token.split('.')[1]
|
||||
return JSON.parse(atob(payload))
|
||||
}
|
||||
|
||||
function loadSession(): { token: string; user: User; companyId: string; permissions?: string[] } | null {
|
||||
function loadSession(): { token: string; user: User; permissions?: string[] } | null {
|
||||
try {
|
||||
const raw = sessionStorage.getItem('forte-auth')
|
||||
if (!raw) return null
|
||||
@@ -64,8 +58,8 @@ function loadSession(): { token: string; user: User; companyId: string; permissi
|
||||
}
|
||||
}
|
||||
|
||||
function saveSession(token: string, user: User, companyId: string, permissions?: string[]) {
|
||||
sessionStorage.setItem('forte-auth', JSON.stringify({ token, user, companyId, permissions }))
|
||||
function saveSession(token: string, user: User, permissions?: string[]) {
|
||||
sessionStorage.setItem('forte-auth', JSON.stringify({ token, user, permissions }))
|
||||
}
|
||||
|
||||
function clearSession() {
|
||||
@@ -78,22 +72,19 @@ export const useAuthStore = create<AuthState>((set, get) => {
|
||||
return {
|
||||
token: initial?.token ?? null,
|
||||
user: initial?.user ?? null,
|
||||
companyId: initial?.companyId ?? null,
|
||||
permissions: initialPerms,
|
||||
permissionsLoaded: initialPerms.size > 0,
|
||||
|
||||
setAuth: (token, user) => {
|
||||
const payload = decodeJwtPayload(token)
|
||||
saveSession(token, user, payload.companyId)
|
||||
set({ token, user, companyId: payload.companyId })
|
||||
saveSession(token, user)
|
||||
set({ token, user })
|
||||
},
|
||||
|
||||
setPermissions: (slugs: string[]) => {
|
||||
const expanded = expandPermissions(slugs)
|
||||
// Update session storage to include permissions
|
||||
const { token, user, companyId } = get()
|
||||
if (token && user && companyId) {
|
||||
saveSession(token, user, companyId, slugs)
|
||||
const { token, user } = get()
|
||||
if (token && user) {
|
||||
saveSession(token, user, slugs)
|
||||
}
|
||||
set({ permissions: expanded, permissionsLoaded: true })
|
||||
},
|
||||
@@ -104,6 +95,6 @@ export const useAuthStore = create<AuthState>((set, get) => {
|
||||
|
||||
logout: () => {
|
||||
clearSession()
|
||||
set({ token: null, user: null, companyId: null, permissions: new Set(), permissionsLoaded: false })
|
||||
set({ token: null, user: null, permissions: new Set(), permissionsLoaded: false })
|
||||
},
|
||||
}})
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export interface Account {
|
||||
id: string
|
||||
companyId: string
|
||||
accountNumber: string | null
|
||||
name: string
|
||||
primaryMemberId: string | null
|
||||
@@ -25,7 +24,6 @@ export interface Account {
|
||||
export interface Member {
|
||||
id: string
|
||||
accountId: string
|
||||
companyId: string
|
||||
memberNumber: string | null
|
||||
firstName: string
|
||||
lastName: string
|
||||
@@ -42,7 +40,6 @@ export interface Member {
|
||||
export interface ProcessorLink {
|
||||
id: string
|
||||
accountId: string
|
||||
companyId: string
|
||||
processor: 'stripe' | 'global_payments'
|
||||
processorCustomerId: string
|
||||
isActive: boolean
|
||||
@@ -52,7 +49,6 @@ export interface ProcessorLink {
|
||||
export interface PaymentMethod {
|
||||
id: string
|
||||
accountId: string
|
||||
companyId: string
|
||||
processor: 'stripe' | 'global_payments'
|
||||
processorPaymentMethodId: string
|
||||
cardBrand: string | null
|
||||
@@ -67,7 +63,6 @@ export interface PaymentMethod {
|
||||
export interface MemberIdentifier {
|
||||
id: string
|
||||
memberId: string
|
||||
companyId: string
|
||||
type: 'drivers_license' | 'passport' | 'school_id'
|
||||
label: string | null
|
||||
value: string
|
||||
@@ -85,7 +80,6 @@ export interface MemberIdentifier {
|
||||
export interface TaxExemption {
|
||||
id: string
|
||||
accountId: string
|
||||
companyId: string
|
||||
status: 'none' | 'pending' | 'approved'
|
||||
certificateNumber: string
|
||||
certificateType: string | null
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export interface RepairTicket {
|
||||
id: string
|
||||
companyId: string
|
||||
locationId: string | null
|
||||
repairBatchId: string | null
|
||||
ticketNumber: string | null
|
||||
@@ -42,7 +41,6 @@ export interface RepairLineItem {
|
||||
|
||||
export interface RepairBatch {
|
||||
id: string
|
||||
companyId: string
|
||||
locationId: string | null
|
||||
batchNumber: string | null
|
||||
accountId: string
|
||||
@@ -80,7 +78,6 @@ export interface RepairNote {
|
||||
|
||||
export interface RepairServiceTemplate {
|
||||
id: string
|
||||
companyId: string
|
||||
name: string
|
||||
instrumentType: string | null
|
||||
size: string | null
|
||||
|
||||
Reference in New Issue
Block a user