LibreChat/packages/data-schemas/src/schema/session.ts

26 lines
456 B
TypeScript
Raw Normal View History

🏗️ refactor: Extract DB layers to `data-schemas` for shared use (#7650) * refactor: move model definitions and database-related methods to packages/data-schemas * ci: update tests due to new DB structure fix: disable mocking `librechat-data-provider` feat: Add schema exports to data-schemas package - Introduced a new schema module that exports various schemas including action, agent, and user schemas. - Updated index.ts to include the new schema exports for better modularity and organization. ci: fix appleStrategy tests fix: Agent.spec.js ci: refactor handleTools tests to use MongoMemoryServer for in-memory database fix: getLogStores imports ci: update banViolation tests to use MongoMemoryServer and improve session mocking test: refactor samlStrategy tests to improve mock configurations and user handling ci: fix crypto mock in handleText tests for improved accuracy ci: refactor spendTokens tests to improve model imports and setup ci: refactor Message model tests to use MongoMemoryServer and improve database interactions * refactor: streamline IMessage interface and move feedback properties to types/message.ts * refactor: use exported initializeRoles from `data-schemas`, remove api workspace version (this serves as an example of future migrations that still need to happen) * refactor: update model imports to use destructuring from `~/db/models` for consistency and clarity * refactor: remove unused mongoose imports from model files for cleaner code * refactor: remove unused mongoose imports from Share, Prompt, and Transaction model files for cleaner code * refactor: remove unused import in Transaction model for cleaner code * ci: update deploy workflow to reference new Docker Dev Branch Images Build and add new workflow for building Docker images on dev branch * chore: cleanup imports
2025-05-30 22:18:13 -04:00
import mongoose, { Schema } from 'mongoose';
import { ISession } from '~/types';
const sessionSchema: Schema<ISession> = new Schema({
refreshTokenHash: {
type: String,
required: true,
},
expiration: {
type: Date,
required: true,
expires: 0,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
🏢 feat: Multi-Tenant Data Isolation Infrastructure (#12091) * chore: imports * chore: optional chaining in `spendTokens.spec.ts` * feat: Add tenantId field to all MongoDB schemas for multi-tenant isolation - Add AsyncLocalStorage-based tenant context (`tenantContext.ts`) for request-scoped tenantId propagation without modifying method signatures - Add Mongoose `applyTenantIsolation` plugin that injects `{ tenantId }` into all query filters when tenant context is present, with `TENANT_ISOLATION_STRICT` env var for fail-closed production mode - Add optional `tenantId` field to all 28 collection schemas - Update all compound unique indexes to include tenantId (email, OAuth IDs, role names, serverName, conversationId+user, messageId+user, etc.) - Apply tenant isolation plugin in all 28 model factories - Add `tenantId?: string` to all TypeScript document interfaces Behaviorally inert — transitional mode (default) passes through all queries unchanged. No migration required for existing deployments. * refactor: Update tenant context and enhance tenant isolation plugin - Changed `tenantId` in `TenantContext` to be optional, allowing for more flexible usage. - Refactored `runAsSystem` function to accept synchronous functions, improving usability. - Introduced comprehensive tests for the `applyTenantIsolation` plugin, ensuring correct tenant filtering in various query scenarios. - Enhanced the plugin to handle aggregate queries and save operations with tenant context, improving data isolation capabilities. * docs: tenant context documentation and improve tenant isolation tests - Added detailed documentation for the `tenantStorage` AsyncLocalStorage instance in `tenantContext.ts`, clarifying its usage for async tenant context propagation. - Updated tests in `tenantIsolation.spec.ts` to improve clarity and coverage, including new tests for strict mode behavior and tenant context propagation through await boundaries. - Refactored existing test cases for better readability and consistency, ensuring robust validation of tenant isolation functionality. * feat: Enhance tenant isolation by preventing tenantId mutations in update operations - Added a new function to assert that tenantId cannot be modified through update operators in Mongoose queries. - Implemented middleware to enforce this restriction during findOneAndUpdate, updateOne, and updateMany operations. - Updated documentation to reflect the new behavior regarding tenantId modifications, ensuring clarity on tenant isolation rules. * feat: Enhance tenant isolation tests and enforce tenantId restrictions - Updated existing tests to clarify behavior regarding tenantId preservation during save and insertMany operations. - Introduced new tests to validate that tenantId cannot be modified through update operations, ensuring strict adherence to tenant isolation rules. - Added checks for mismatched tenantId scenarios, reinforcing the integrity of tenant context propagation. - Enhanced test coverage for async context propagation and mutation guards, improving overall robustness of tenant isolation functionality. * fix: Remove duplicate re-exports in utils/index.ts Merge artifact caused `string` and `tempChatRetention` to be exported twice, which produces TypeScript compile errors for duplicate bindings. * fix: Resolve admin capability gap in multi-tenant mode (TODO #12091) - hasCapabilityForPrincipals now queries both tenant-scoped AND platform-level grants when tenantId is set, so seeded ADMIN grants remain effective in tenant mode. - Add applyTenantIsolation to SystemGrant model factory. * fix: Harden tenant isolation plugin - Add replaceGuard for replaceOne/findOneAndReplace to prevent cross-tenant document reassignment via replacement documents. - Cache isStrict() result to avoid process.env reads on every query. Export _resetStrictCache() for test teardown. - Replace console.warn with project logger (winston). - Add 5 new tests for replace guard behavior (46 total). * style: Fix import ordering in convo.ts and message.ts Move type imports after value imports per project style guide. * fix: Remove tenant isolation from SystemGrant, stamp tenantId in replaceGuard - SystemGrant is a cross-tenant control plane whose methods handle tenantId conditions explicitly. Applying the isolation plugin injects a hard equality filter that overrides the $and/$or logic in hasCapabilityForPrincipals, making platform-level ADMIN grants invisible in tenant mode. - replaceGuard now stamps tenantId into replacement documents when absent, preventing replaceOne from silently stripping tenant context. Replacements with a matching tenantId are allowed; mismatched tenantId still throws. * test: Add multi-tenant unique constraint and replace stamping tests - Verify same name/email can exist in different tenants (compound unique index allows it). - Verify duplicate within same tenant is rejected (E11000). - Verify tenant-scoped query returns only the correct document. - Update replaceOne test to assert tenantId is stamped into replacement document. - Add test for replacement with matching tenantId. * style: Reorder imports in message.ts to align with project style guide * feat: Add migration to drop superseded unique indexes for multi-tenancy Existing deployments have single-field unique indexes (e.g. { email: 1 }) that block multi-tenant operation — same email in different tenants triggers E11000. Mongoose autoIndex creates the new compound indexes but never drops the old ones. dropSupersededTenantIndexes() drops all 19 superseded indexes across 11 collections. It is idempotent, skips missing indexes/collections, and is a no-op on fresh databases. Must be called before enabling multi-tenant middleware on an existing deployment. Single-tenant deployments are unaffected (old indexes coexist harmlessly until migration runs). Includes 11 tests covering: - Full upgrade simulation (create old indexes, drop them, verify gone) - Multi-tenant writes work after migration (same email, different tenant) - Intra-tenant uniqueness preserved (duplicate within tenant rejected) - Fresh database (no-op, no errors) - Partial migration (some collections exist, some don't) - SUPERSEDED_INDEXES coverage validation * fix: Update systemGrant test — platform grants now satisfy tenant queries The TODO #12091 fix intentionally changed hasCapabilityForPrincipals to match both tenant-scoped AND platform-level grants. The test expected the old behavior (platform grant invisible to tenant query). Updated test name and expectation to match the new semantics. * fix: Align getCapabilitiesForPrincipal with hasCapabilityForPrincipals tenant query getCapabilitiesForPrincipal used a hard tenantId equality filter while hasCapabilityForPrincipals uses $and/$or to match both tenant-scoped and platform-level grants. This caused the two functions to disagree on what grants a principal holds in tenant mode. Apply the same $or pattern: when tenantId is provided, match both { tenantId } and { tenantId: { $exists: false } }. Adds test verifying platform-level ADMIN grants appear in getCapabilitiesForPrincipal when called with a tenantId. * fix: Remove categories from tenant index migration categoriesSchema is exported but never used to create a Mongoose model. No Category model factory exists, no code constructs a model from it, and no categories collection exists in production databases. Including it in the migration would attempt to drop indexes from a non-existent collection (harmlessly skipped) but implies the collection is managed. * fix: Restrict runAsSystem to async callbacks only Sync callbacks returning Mongoose thenables silently lose ALS context — the system bypass does nothing and strict mode throws with no indication runAsSystem was involved. Narrowing to () => Promise<T> makes the wrong pattern a compile error. All existing call sites already use async. * fix: Use next(err) consistently in insertMany pre-hook The hook accepted a next callback but used throw for errors. Standardize on next(err) for all error paths so the hook speaks one language — callback-style throughout. * fix: Replace optional chaining with explicit null assertions in spendTokens tests Optional chaining on test assertions masks failures with unintelligible error messages. Add expect(result).not.toBeNull() before accessing properties, so a null result produces a clear diagnosis instead of "received value must be a number".
2026-03-07 16:37:10 -05:00
tenantId: {
type: String,
index: true,
},
});
export default sessionSchema;