mirror of
https://github.com/saltbo/zpan.git
synced 2026-09-24 23:22:31 +08:00
* refactor: remove custom filePath, enforce tenant-isolated storage path Replace user-customizable filePath template with a hardcoded tenant-isolated pattern ($ORG_ID/$UID/$NOW_DATE/$RAND_16KEY$RAW_EXT). This ensures proper tenant isolation and removes unnecessary complexity. The DB column is preserved to avoid migration; code simply stops reading/writing it. Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f * refactor: clean up dead tokens, locale keys, and simplify path template Remove unused template tokens ($UUID, $RAW_NAME, $NOW_YEAR, $NOW_MONTH, $NOW_DAY) and corresponding TemplateVars fields (uuid, rawName) since the hardcoded template doesn't use them. Remove orphaned i18n keys for fieldFilePath. Update DB schema default to empty string. Add storage service unit tests. Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f --------- Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import { and, asc, count, eq, lt, or } from 'drizzle-orm'
|
|
import { nanoid } from 'nanoid'
|
|
import type { CreateStorageInput, UpdateStorageInput } from '../../shared/schemas'
|
|
import { matters, storages } from '../db/schema'
|
|
import type { Database } from '../platform/interface'
|
|
|
|
export type Storage = typeof storages.$inferSelect
|
|
|
|
export async function listStorages(db: Database): Promise<{ items: Storage[]; total: number }> {
|
|
const items = await db.select().from(storages).orderBy(asc(storages.createdAt))
|
|
return { items, total: items.length }
|
|
}
|
|
|
|
export async function getStorage(db: Database, id: string): Promise<Storage | null> {
|
|
const rows = await db.select().from(storages).where(eq(storages.id, id))
|
|
return rows[0] ?? null
|
|
}
|
|
|
|
export async function createStorage(db: Database, input: CreateStorageInput): Promise<Storage> {
|
|
const now = new Date()
|
|
const row: Storage = {
|
|
id: nanoid(),
|
|
title: input.title,
|
|
mode: input.mode,
|
|
bucket: input.bucket,
|
|
endpoint: input.endpoint,
|
|
region: input.region,
|
|
accessKey: input.accessKey,
|
|
secretKey: input.secretKey,
|
|
filePath: '',
|
|
customHost: input.customHost ?? '',
|
|
capacity: input.capacity ?? 0,
|
|
used: 0,
|
|
status: 'active',
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
}
|
|
|
|
await db.insert(storages).values(row)
|
|
return row
|
|
}
|
|
|
|
export async function updateStorage(db: Database, id: string, input: UpdateStorageInput): Promise<Storage | null> {
|
|
const existing = await getStorage(db, id)
|
|
if (!existing) return null
|
|
|
|
const now = new Date()
|
|
const updated = {
|
|
title: input.title ?? existing.title,
|
|
mode: input.mode ?? existing.mode,
|
|
bucket: input.bucket ?? existing.bucket,
|
|
endpoint: input.endpoint ?? existing.endpoint,
|
|
region: input.region ?? existing.region,
|
|
accessKey: input.accessKey ?? existing.accessKey,
|
|
secretKey: input.secretKey ?? existing.secretKey,
|
|
customHost: input.customHost ?? existing.customHost,
|
|
capacity: input.capacity ?? existing.capacity,
|
|
status: input.status ?? existing.status,
|
|
updatedAt: now,
|
|
}
|
|
|
|
await db.update(storages).set(updated).where(eq(storages.id, id))
|
|
return { ...existing, ...updated }
|
|
}
|
|
|
|
export async function deleteStorage(db: Database, id: string): Promise<'ok' | 'not_found' | 'in_use'> {
|
|
const existing = await getStorage(db, id)
|
|
if (!existing) return 'not_found'
|
|
|
|
const refs = await db.select({ count: count() }).from(matters).where(eq(matters.storageId, id))
|
|
if ((refs[0]?.count ?? 0) > 0) return 'in_use'
|
|
|
|
await db.delete(storages).where(eq(storages.id, id))
|
|
return 'ok'
|
|
}
|
|
|
|
export async function selectStorage(db: Database, mode: 'private' | 'public'): Promise<Storage> {
|
|
const rows = await db
|
|
.select()
|
|
.from(storages)
|
|
.where(
|
|
and(
|
|
eq(storages.mode, mode),
|
|
eq(storages.status, 'active'),
|
|
or(eq(storages.capacity, 0), lt(storages.used, storages.capacity)),
|
|
),
|
|
)
|
|
.orderBy(asc(storages.createdAt))
|
|
.limit(1)
|
|
|
|
if (rows.length === 0) throw new Error('No available storage')
|
|
return rows[0]
|
|
}
|