server/db/schema-authz.test.ts
Rama main · réplica de lectura del repositorio original.
import {
account,
accountRelations,
agent,
agentCapabilityGrant,
agentCapabilityGrantRelations,
agentHost,
agentHostRelations,
agentRelations,
apiResource,
apiResourceRelations,
application,
applicationClientMetadata,
applicationClientSecret,
applicationConsent,
applicationRelations,
approvalRequest,
approvalRequestRelations,
customDomain,
identityProviderConnector,
invitation,
jwks,
member,
oauthAccessToken,
oauthClient,
oauthConsent,
oauthRefreshToken,
organization,
organizationInvitationRelations,
organizationMemberRelations,
organizationRelations,
organizationRole,
organizationRoleRelations,
organizationTeamMemberRelations,
organizationTeamRelations,
passkey,
passkeyRelations,
session,
sessionRelations,
siteSettings,
twoFactor,
twoFactorRelations,
uploadedAsset,
user,
userRelations,
verification,
webhookDeliveryAttempt,
webhookDeliveryRequest,
webhookEndpoint,
} from '@server/db/schema'
import { getTableConfig } from 'drizzle-orm/sqlite-core'
import { describe, expect, it } from 'vitest'
function columnNames(table: Parameters<typeof getTableConfig>[0]) {
return getTableConfig(table).columns.map((column) => column.name)
}
function indexNames(table: Parameters<typeof getTableConfig>[0]) {
return getTableConfig(table).indexes.map((index) => index.config.name)
}
function foreignKeyReferences(table: Parameters<typeof getTableConfig>[0]) {
return getTableConfig(table).foreignKeys.map((foreignKey) => {
const reference = foreignKey.reference()
return {
columns: reference.columns.map((column) => column.name),
foreignColumns: reference.foreignColumns.map((column) => column.name),
foreignTable: getTableConfig(reference.foreignTable).name,
onDelete: foreignKey.onDelete,
}
})
}
describe('schema.test 2', () => {
it('keeps Realmroot product settings and OAuth token tables explicit', () => {
expect(columnNames(account)).toEqual(expect.arrayContaining(['account_id', 'provider_id', 'user_id']))
expect(columnNames(verification)).toEqual(expect.arrayContaining(['identifier', 'value', 'expires_at']))
expect(indexNames(oauthRefreshToken)).toEqual(
expect.arrayContaining([
'oauthRefreshToken_clientId_idx',
'oauthRefreshToken_sessionId_idx',
'oauthRefreshToken_userId_idx',
]),
)
const refreshTokenColumns = columnNames(oauthRefreshToken)
expect(refreshTokenColumns).toEqual(expect.arrayContaining(['token', 'scopes', 'resources']))
expect(refreshTokenColumns).not.toContain('dpop_jkt')
expect(refreshTokenColumns).not.toContain('family_id')
expect(refreshTokenColumns).not.toContain('family_compromised_at')
expect(indexNames(oauthAccessToken)).toEqual(
expect.arrayContaining([
'oauthAccessToken_clientId_idx',
'oauthAccessToken_sessionId_idx',
'oauthAccessToken_userId_idx',
'oauthAccessToken_refreshId_idx',
]),
)
expect(indexNames(oauthConsent)).toEqual(
expect.arrayContaining(['oauthConsent_clientId_idx', 'oauthConsent_userId_idx', 'oauthConsent_referenceId_idx']),
)
expect(indexNames(uploadedAsset)).toEqual(
expect.arrayContaining(['uploadedAsset_purpose_idx', 'uploadedAsset_createdByUserId_idx']),
)
expect(columnNames(siteSettings)).toEqual(['key', 'value', 'revision', 'updated_at'])
expect(indexNames(customDomain)).toEqual(
expect.arrayContaining([
'customDomain_applicationId_idx',
'customDomain_organizationId_idx',
'customDomain_status_idx',
]),
)
})
it('models webhook endpoint, delivery request, and delivery attempt persistence explicitly', () => {
expect(columnNames(webhookEndpoint)).toEqual(
expect.arrayContaining([
'url',
'events',
'enabled',
'organization_id',
'signing_secret',
'secret_prefix',
'created_by_user_id',
]),
)
expect(indexNames(webhookEndpoint)).toEqual(
expect.arrayContaining([
'webhookEndpoint_enabled_idx',
'webhookEndpoint_organizationId_idx',
'webhookEndpoint_createdByUserId_idx',
]),
)
expect(foreignKeyReferences(webhookEndpoint)).toContainEqual({
columns: ['created_by_user_id'],
foreignColumns: ['id'],
foreignTable: 'user',
onDelete: 'set null',
})
expect(foreignKeyReferences(webhookEndpoint)).toContainEqual({
columns: ['organization_id'],
foreignColumns: ['id'],
foreignTable: 'organization',
onDelete: 'cascade',
})
expect(columnNames(webhookDeliveryRequest)).toEqual(
expect.arrayContaining([
'endpoint_id',
'event',
'status',
'attempt_count',
'request_body',
'response_body',
'next_attempt_at',
]),
)
expect(indexNames(webhookDeliveryRequest)).toEqual(
expect.arrayContaining([
'webhookDeliveryRequest_endpointId_idx',
'webhookDeliveryRequest_status_idx',
'webhookDeliveryRequest_createdAt_idx',
]),
)
expect(foreignKeyReferences(webhookDeliveryRequest)).toContainEqual({
columns: ['endpoint_id'],
foreignColumns: ['id'],
foreignTable: 'webhook_endpoint',
onDelete: 'cascade',
})
expect(columnNames(webhookDeliveryAttempt)).toEqual(
expect.arrayContaining([
'request_id',
'sequence',
'status',
'http_status',
'error',
'response_body',
'created_at',
'completed_at',
]),
)
expect(indexNames(webhookDeliveryAttempt)).toEqual(
expect.arrayContaining([
'webhookDeliveryAttempt_requestSequence_uidx',
'webhookDeliveryAttempt_requestId_idx',
'webhookDeliveryAttempt_createdAt_idx',
]),
)
expect(foreignKeyReferences(webhookDeliveryAttempt)).toContainEqual({
columns: ['request_id'],
foreignColumns: ['id'],
foreignTable: 'webhook_delivery_request',
onDelete: 'cascade',
})
})
it('defines relation graphs for auth, organization, application, and authorization records', () => {
expect(relationKeys(userRelations)).toEqual(
expect.arrayContaining([
'sessions',
'accounts',
'passkeys',
'twoFactors',
'oauthClients',
'oauthRefreshTokens',
'oauthAccessTokens',
'oauthConsents',
'ownedApplications',
'organizationMemberships',
]),
)
expect(relationKeys(twoFactorRelations)).toEqual(['user'])
expect(relationKeys(passkeyRelations)).toEqual(['user'])
expect(relationKeys(agentHostRelations)).toEqual(expect.arrayContaining(['user', 'agents', 'approvalRequests']))
expect(relationKeys(agentRelations)).toEqual(expect.arrayContaining(['user', 'host', 'grants', 'approvalRequests']))
expect(relationKeys(agentCapabilityGrantRelations)).toEqual(
expect.arrayContaining(['agent', 'grantedByUser', 'deniedByUser']),
)
expect(relationKeys(approvalRequestRelations)).toEqual(expect.arrayContaining(['agent', 'host', 'user']))
expect(relationKeys(sessionRelations)).toEqual(['user'])
expect(relationKeys(accountRelations)).toEqual(['user'])
expect(relationKeys(organizationRelations)).toEqual(
expect.arrayContaining(['logoAsset', 'members', 'invitations', 'applications', 'teams']),
)
expect(relationKeys(organizationMemberRelations)).toEqual(expect.arrayContaining(['organization', 'user']))
expect(relationKeys(organizationInvitationRelations)).toEqual(['organization', 'inviter'])
expect(relationKeys(organizationTeamRelations)).toEqual(['organization', 'members'])
expect(relationKeys(organizationTeamMemberRelations)).toEqual(['team', 'user'])
expect(relationKeys(applicationRelations)).toEqual(
expect.arrayContaining([
'oauthClient',
'ownerOrganization',
'logoAsset',
'clientSecrets',
'consents',
'scopeEntitlements',
]),
)
expect(relationKeys(apiResourceRelations)).toEqual(['ownerOrganization', 'scopeEntitlements'])
expect(relationKeys(organizationRoleRelations)).toEqual(['organization'])
})
it('keeps timestamp update hooks executable for mutable records', () => {
const updateValues = schemaTables
.flatMap((table) => getTableConfig(table).columns)
.filter((column) => column.onUpdateFn)
.map((column) => column.onUpdateFn?.())
expect(updateValues).toHaveLength(16)
for (const value of updateValues) {
expect(value).toBeInstanceOf(Date)
}
})
})
const schemaTables = [
user,
session,
account,
verification,
jwks,
twoFactor,
passkey,
oauthClient,
oauthRefreshToken,
oauthAccessToken,
oauthConsent,
agentHost,
agent,
agentCapabilityGrant,
approvalRequest,
uploadedAsset,
organization,
member,
invitation,
apiResource,
organizationRole,
application,
applicationClientSecret,
applicationClientMetadata,
applicationConsent,
identityProviderConnector,
siteSettings,
customDomain,
webhookEndpoint,
webhookDeliveryRequest,
]
function relationKeys(relationsObject: { config: (helpers: never) => Record<string, unknown> }) {
return Object.keys(relationsObject.config(relationHelpers as never))
}
type RelationHelpers = {
one: (table: unknown, config: unknown) => unknown
many: (table: unknown) => unknown
}
const relationHelpers: RelationHelpers = {
one: (table, config) => relationStub({ type: 'one', table, config }),
many: (table) => relationStub({ type: 'many', table }),
}
function relationStub(value: unknown) {
return {
value,
withFieldName: (fieldName: string) => ({ value, fieldName }),
}
}