mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-29 00:01:42 +08:00
2dca9d9ffb
* feat(db): image hosting schema, apiKey plugin, migration 0011 Adds the DB infrastructure for the v2.4 image hosting feature: - server/db/schema.ts: new `image_hosting_configs` (per-org singleton, custom domain + referer allowlist) and `image_hostings` tables with all required indexes and cascade-delete FKs - server/db/auth-schema.ts: `apikey` table for @better-auth/api-key plugin (referenceId-indexed, rate-limiting fields, permissions column) - server/auth.ts: enable apiKey plugin (references='organization', image-hosting:upload permission declared) - shared/types/index.ts: ImageHostingConfig, ImageHosting, ImageHostingStatus - migrations/0011_image-hosting.sql: generated by drizzle-kit (NOT hand-authored); creates all three new tables + indexes - migrations/meta/0011_snapshot.json: baseline snapshot for future migration generation (repo was missing snapshots 0002–0010) - package.json: add @better-auth/api-key ^1.6.2 dep, bump better-auth to ^1.6.2 Note: migration is tagged 0011_image-hosting (idx=11 in journal) rather than 0012 because the existing 0011_notifications was registered as idx=10 (pre-existing numbering offset from a skipped 0006_ slot). Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f * fix: resolve coverage gap and migration filename collision - Add getTableConfig FK reference tests to cover deferred .references() callbacks in schema.ts (fixes Codecov patch coverage < 94.98%) - Rename 0011_image-hosting → 0012_image-hosting to avoid filename collision with pre-existing 0011_notifications migration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Bob <aibob@mails.agent-kanban.dev> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
214 lines
4.0 KiB
TypeScript
214 lines
4.0 KiB
TypeScript
import type { DirType, ObjectStatus, StorageMode, StorageStatus } from '../constants'
|
|
|
|
export interface StorageObject {
|
|
id: string
|
|
orgId: string
|
|
alias: string
|
|
name: string
|
|
type: string
|
|
size: number
|
|
dirtype: DirType
|
|
parent: string
|
|
object: string
|
|
storageId: string
|
|
status: ObjectStatus
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
export interface Storage {
|
|
id: string
|
|
uid: string
|
|
title: string
|
|
mode: StorageMode
|
|
bucket: string
|
|
endpoint: string
|
|
region: string
|
|
accessKey: string
|
|
secretKey: string
|
|
customHost: string
|
|
capacity: number
|
|
used: number
|
|
status: StorageStatus
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
export interface OrgQuota {
|
|
id: string
|
|
orgId: string
|
|
quota: number
|
|
used: number
|
|
}
|
|
|
|
export interface Organization {
|
|
id: string
|
|
name: string
|
|
slug: string
|
|
logo: string | null
|
|
metadata: string | null
|
|
createdAt: string
|
|
updatedAt: string | null
|
|
}
|
|
|
|
export interface Member {
|
|
id: string
|
|
organizationId: string
|
|
userId: string
|
|
role: string
|
|
createdAt: string
|
|
}
|
|
|
|
export interface Invitation {
|
|
id: string
|
|
organizationId: string
|
|
email: string
|
|
role: string
|
|
status: 'pending' | 'accepted' | 'rejected' | 'canceled'
|
|
expiresAt: string
|
|
inviterId: string
|
|
createdAt: string
|
|
}
|
|
|
|
export interface SystemOption {
|
|
key: string
|
|
value: string
|
|
public: boolean
|
|
}
|
|
|
|
export interface AuthProvider {
|
|
providerId: string
|
|
type: string
|
|
name: string
|
|
icon: string
|
|
}
|
|
|
|
export interface PaginatedResponse<T> {
|
|
items: T[]
|
|
total: number
|
|
page: number
|
|
pageSize: number
|
|
}
|
|
|
|
import type { ShareKind as _ShareKind } from '../schemas/share'
|
|
|
|
export type { ShareKind } from '../schemas/share'
|
|
|
|
// passwordHash is intentionally not part of the shared wire type; it never leaves the server.
|
|
export interface Share {
|
|
id: string
|
|
token: string
|
|
kind: _ShareKind
|
|
matterId: string
|
|
orgId: string
|
|
creatorId: string
|
|
expiresAt: string | null
|
|
downloadLimit: number | null
|
|
views: number
|
|
downloads: number
|
|
status: 'active' | 'revoked'
|
|
createdAt: string
|
|
}
|
|
|
|
export interface ShareRecipient {
|
|
id: string
|
|
shareId: string
|
|
recipientUserId: string | null
|
|
recipientEmail: string | null
|
|
createdAt: string
|
|
}
|
|
|
|
export interface ShareMatter {
|
|
name: string
|
|
type: string
|
|
dirtype: number
|
|
}
|
|
|
|
export interface ShareListItem extends Share {
|
|
matter: ShareMatter
|
|
recipientCount: number
|
|
}
|
|
|
|
export interface ShareView {
|
|
token: string
|
|
kind: _ShareKind
|
|
status: 'active' | 'revoked'
|
|
expiresAt: string | null
|
|
downloadLimit: number | null
|
|
matter: { name: string; type: string; size: number; isFolder: boolean }
|
|
creatorName: string
|
|
requiresPassword: boolean
|
|
expired: boolean
|
|
exhausted: boolean
|
|
accessibleByUser: boolean
|
|
downloads: number
|
|
views: number
|
|
rootRef: string
|
|
|
|
id?: string
|
|
matterId?: string
|
|
orgId?: string
|
|
creatorId?: string
|
|
createdAt?: string
|
|
recipients?: ShareRecipient[]
|
|
}
|
|
|
|
export interface Notification {
|
|
id: string
|
|
userId: string
|
|
type: string
|
|
title: string
|
|
body: string
|
|
refType: string | null
|
|
refId: string | null
|
|
metadata: string | null
|
|
readAt: string | null
|
|
createdAt: string
|
|
}
|
|
|
|
export interface ActivityEvent {
|
|
id: string
|
|
orgId: string
|
|
userId: string
|
|
action: string
|
|
targetType: string
|
|
targetId: string | null
|
|
targetName: string
|
|
metadata: string | null
|
|
createdAt: string
|
|
user: {
|
|
id: string
|
|
name: string
|
|
image: string | null
|
|
}
|
|
}
|
|
|
|
export interface ImageHostingConfig {
|
|
orgId: string
|
|
customDomain: string | null
|
|
cfHostnameId: string | null
|
|
domainVerifiedAt: string | null
|
|
refererAllowlist: string | null // JSON array of strings; null/empty => allow all
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
export type ImageHostingStatus = 'draft' | 'active'
|
|
|
|
export interface ImageHosting {
|
|
id: string
|
|
orgId: string
|
|
token: string
|
|
path: string
|
|
storageId: string
|
|
storageKey: string
|
|
size: number
|
|
mime: string
|
|
width: number | null
|
|
height: number | null
|
|
status: ImageHostingStatus
|
|
accessCount: number
|
|
lastAccessedAt: string | null
|
|
createdAt: string
|
|
}
|