@lacrous/omnicloud 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +161 -0
- package/package.json +20 -7
- package/server/index.js +4912 -0
- package/server/prisma/migrations/0_init/migration.sql +106 -0
- package/server/prisma/migrations/1_v02_reliability/migration.sql +120 -0
- package/server/prisma/migrations/2_v02_trash_batch/migration.sql +6 -0
- package/server/prisma/migrations/3_browser_sessions/migration.sql +27 -0
- package/server/prisma/migrations/4_upload_operations/migration.sql +26 -0
- package/server/prisma/migrations/migration_lock.toml +3 -0
- package/server/prisma/schema.prisma +194 -0
- package/server/web/assets/index-Caa-mAUw.js +339 -0
- package/server/web/assets/index-kc0MNEkT.css +1 -0
- package/server/web/favicon.svg +10 -0
- package/server/web/index.html +189 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
-- CreateSchema
|
|
2
|
+
CREATE SCHEMA IF NOT EXISTS "public";
|
|
3
|
+
|
|
4
|
+
-- CreateTable
|
|
5
|
+
CREATE TABLE "User" (
|
|
6
|
+
"id" TEXT NOT NULL,
|
|
7
|
+
"telegramUserId" BIGINT NOT NULL,
|
|
8
|
+
"username" TEXT,
|
|
9
|
+
"firstName" TEXT,
|
|
10
|
+
"lastName" TEXT,
|
|
11
|
+
"phone" TEXT,
|
|
12
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
13
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
14
|
+
|
|
15
|
+
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- CreateTable
|
|
19
|
+
CREATE TABLE "TelegramSession" (
|
|
20
|
+
"id" TEXT NOT NULL,
|
|
21
|
+
"userId" TEXT NOT NULL,
|
|
22
|
+
"stringSession" TEXT NOT NULL,
|
|
23
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
24
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
25
|
+
|
|
26
|
+
CONSTRAINT "TelegramSession_pkey" PRIMARY KEY ("id")
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
-- CreateTable
|
|
30
|
+
CREATE TABLE "Storage" (
|
|
31
|
+
"id" TEXT NOT NULL,
|
|
32
|
+
"userId" TEXT NOT NULL,
|
|
33
|
+
"provider" TEXT NOT NULL DEFAULT 'telegram',
|
|
34
|
+
"title" TEXT NOT NULL,
|
|
35
|
+
"telegramChatId" BIGINT NOT NULL,
|
|
36
|
+
"telegramAccessHash" BIGINT NOT NULL,
|
|
37
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
38
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
39
|
+
|
|
40
|
+
CONSTRAINT "Storage_pkey" PRIMARY KEY ("id")
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
-- CreateTable
|
|
44
|
+
CREATE TABLE "Folder" (
|
|
45
|
+
"id" TEXT NOT NULL,
|
|
46
|
+
"userId" TEXT NOT NULL,
|
|
47
|
+
"parentId" TEXT,
|
|
48
|
+
"name" TEXT NOT NULL,
|
|
49
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
50
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
51
|
+
|
|
52
|
+
CONSTRAINT "Folder_pkey" PRIMARY KEY ("id")
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
-- CreateTable
|
|
56
|
+
CREATE TABLE "File" (
|
|
57
|
+
"id" TEXT NOT NULL,
|
|
58
|
+
"userId" TEXT NOT NULL,
|
|
59
|
+
"folderId" TEXT,
|
|
60
|
+
"name" TEXT NOT NULL,
|
|
61
|
+
"size" BIGINT NOT NULL,
|
|
62
|
+
"mimeType" TEXT NOT NULL,
|
|
63
|
+
"sha256" TEXT NOT NULL,
|
|
64
|
+
"telegramMessageId" BIGINT NOT NULL,
|
|
65
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
66
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
67
|
+
|
|
68
|
+
CONSTRAINT "File_pkey" PRIMARY KEY ("id")
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
-- CreateIndex
|
|
72
|
+
CREATE UNIQUE INDEX "User_telegramUserId_key" ON "User"("telegramUserId");
|
|
73
|
+
|
|
74
|
+
-- CreateIndex
|
|
75
|
+
CREATE UNIQUE INDEX "TelegramSession_userId_key" ON "TelegramSession"("userId");
|
|
76
|
+
|
|
77
|
+
-- CreateIndex
|
|
78
|
+
CREATE UNIQUE INDEX "Storage_userId_provider_key" ON "Storage"("userId", "provider");
|
|
79
|
+
|
|
80
|
+
-- CreateIndex
|
|
81
|
+
CREATE INDEX "Folder_userId_parentId_idx" ON "Folder"("userId", "parentId");
|
|
82
|
+
|
|
83
|
+
-- CreateIndex
|
|
84
|
+
CREATE INDEX "File_userId_folderId_idx" ON "File"("userId", "folderId");
|
|
85
|
+
|
|
86
|
+
-- CreateIndex
|
|
87
|
+
CREATE INDEX "File_userId_name_idx" ON "File"("userId", "name");
|
|
88
|
+
|
|
89
|
+
-- AddForeignKey
|
|
90
|
+
ALTER TABLE "TelegramSession" ADD CONSTRAINT "TelegramSession_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
91
|
+
|
|
92
|
+
-- AddForeignKey
|
|
93
|
+
ALTER TABLE "Storage" ADD CONSTRAINT "Storage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
94
|
+
|
|
95
|
+
-- AddForeignKey
|
|
96
|
+
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
97
|
+
|
|
98
|
+
-- AddForeignKey
|
|
99
|
+
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Folder"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
100
|
+
|
|
101
|
+
-- AddForeignKey
|
|
102
|
+
ALTER TABLE "File" ADD CONSTRAINT "File_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
103
|
+
|
|
104
|
+
-- AddForeignKey
|
|
105
|
+
ALTER TABLE "File" ADD CONSTRAINT "File_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
106
|
+
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
-- DropIndex
|
|
2
|
+
DROP INDEX "File_userId_folderId_idx";
|
|
3
|
+
|
|
4
|
+
-- DropIndex
|
|
5
|
+
DROP INDEX "Folder_userId_parentId_idx";
|
|
6
|
+
|
|
7
|
+
-- AlterTable
|
|
8
|
+
ALTER TABLE "File" ADD COLUMN "currentVersionId" TEXT,
|
|
9
|
+
ADD COLUMN "deletedAt" TIMESTAMP(3),
|
|
10
|
+
ADD COLUMN "starred" BOOLEAN NOT NULL DEFAULT false,
|
|
11
|
+
ADD COLUMN "versionCount" INTEGER NOT NULL DEFAULT 0;
|
|
12
|
+
|
|
13
|
+
-- AlterTable
|
|
14
|
+
ALTER TABLE "Folder" ADD COLUMN "deletedAt" TIMESTAMP(3),
|
|
15
|
+
ADD COLUMN "starred" BOOLEAN NOT NULL DEFAULT false;
|
|
16
|
+
|
|
17
|
+
-- CreateTable
|
|
18
|
+
CREATE TABLE "FileVersion" (
|
|
19
|
+
"id" TEXT NOT NULL,
|
|
20
|
+
"fileId" TEXT NOT NULL,
|
|
21
|
+
"userId" TEXT NOT NULL,
|
|
22
|
+
"versionNumber" INTEGER NOT NULL,
|
|
23
|
+
"size" BIGINT NOT NULL,
|
|
24
|
+
"mimeType" TEXT NOT NULL,
|
|
25
|
+
"sha256" TEXT NOT NULL,
|
|
26
|
+
"telegramMessageId" BIGINT NOT NULL,
|
|
27
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
28
|
+
|
|
29
|
+
CONSTRAINT "FileVersion_pkey" PRIMARY KEY ("id")
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
-- CreateTable
|
|
33
|
+
CREATE TABLE "ActivityEvent" (
|
|
34
|
+
"id" TEXT NOT NULL,
|
|
35
|
+
"userId" TEXT NOT NULL,
|
|
36
|
+
"action" TEXT NOT NULL,
|
|
37
|
+
"resourceType" TEXT NOT NULL,
|
|
38
|
+
"resourceId" TEXT NOT NULL,
|
|
39
|
+
"resourceName" TEXT,
|
|
40
|
+
"metadata" JSONB,
|
|
41
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
42
|
+
|
|
43
|
+
CONSTRAINT "ActivityEvent_pkey" PRIMARY KEY ("id")
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- CreateIndex
|
|
47
|
+
CREATE INDEX "FileVersion_fileId_idx" ON "FileVersion"("fileId");
|
|
48
|
+
|
|
49
|
+
-- CreateIndex
|
|
50
|
+
CREATE INDEX "FileVersion_userId_idx" ON "FileVersion"("userId");
|
|
51
|
+
|
|
52
|
+
-- CreateIndex
|
|
53
|
+
CREATE UNIQUE INDEX "FileVersion_fileId_versionNumber_key" ON "FileVersion"("fileId", "versionNumber");
|
|
54
|
+
|
|
55
|
+
-- CreateIndex
|
|
56
|
+
CREATE INDEX "ActivityEvent_userId_createdAt_idx" ON "ActivityEvent"("userId", "createdAt");
|
|
57
|
+
|
|
58
|
+
-- CreateIndex
|
|
59
|
+
CREATE INDEX "ActivityEvent_userId_resourceId_createdAt_idx" ON "ActivityEvent"("userId", "resourceId", "createdAt");
|
|
60
|
+
|
|
61
|
+
-- CreateIndex
|
|
62
|
+
CREATE INDEX "ActivityEvent_createdAt_idx" ON "ActivityEvent"("createdAt");
|
|
63
|
+
|
|
64
|
+
-- CreateIndex
|
|
65
|
+
CREATE INDEX "File_userId_folderId_deletedAt_idx" ON "File"("userId", "folderId", "deletedAt");
|
|
66
|
+
|
|
67
|
+
-- CreateIndex
|
|
68
|
+
CREATE INDEX "File_userId_deletedAt_idx" ON "File"("userId", "deletedAt");
|
|
69
|
+
|
|
70
|
+
-- CreateIndex
|
|
71
|
+
CREATE INDEX "File_userId_starred_idx" ON "File"("userId", "starred");
|
|
72
|
+
|
|
73
|
+
-- CreateIndex
|
|
74
|
+
CREATE INDEX "File_userId_size_idx" ON "File"("userId", "size");
|
|
75
|
+
|
|
76
|
+
-- CreateIndex
|
|
77
|
+
CREATE INDEX "File_userId_mimeType_idx" ON "File"("userId", "mimeType");
|
|
78
|
+
|
|
79
|
+
-- CreateIndex
|
|
80
|
+
CREATE INDEX "Folder_userId_parentId_deletedAt_idx" ON "Folder"("userId", "parentId", "deletedAt");
|
|
81
|
+
|
|
82
|
+
-- CreateIndex
|
|
83
|
+
CREATE INDEX "Folder_userId_deletedAt_idx" ON "Folder"("userId", "deletedAt");
|
|
84
|
+
|
|
85
|
+
-- CreateIndex
|
|
86
|
+
CREATE INDEX "Folder_userId_name_idx" ON "Folder"("userId", "name");
|
|
87
|
+
|
|
88
|
+
-- CreateIndex
|
|
89
|
+
CREATE INDEX "Folder_userId_starred_idx" ON "Folder"("userId", "starred");
|
|
90
|
+
|
|
91
|
+
-- AddForeignKey
|
|
92
|
+
ALTER TABLE "FileVersion" ADD CONSTRAINT "FileVersion_fileId_fkey" FOREIGN KEY ("fileId") REFERENCES "File"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
93
|
+
|
|
94
|
+
-- AddForeignKey
|
|
95
|
+
ALTER TABLE "FileVersion" ADD CONSTRAINT "FileVersion_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
96
|
+
|
|
97
|
+
-- AddForeignKey
|
|
98
|
+
ALTER TABLE "ActivityEvent" ADD CONSTRAINT "ActivityEvent_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
-- Backfill: give every pre-v0.2 file a version 1 row so its version history is
|
|
102
|
+
-- complete, then point the file at it. Safe to run on an empty table.
|
|
103
|
+
INSERT INTO "FileVersion" ("id", "fileId", "userId", "versionNumber", "size", "mimeType", "sha256", "telegramMessageId", "createdAt")
|
|
104
|
+
SELECT
|
|
105
|
+
'v1_' || f."id",
|
|
106
|
+
f."id",
|
|
107
|
+
f."userId",
|
|
108
|
+
1,
|
|
109
|
+
f."size",
|
|
110
|
+
f."mimeType",
|
|
111
|
+
f."sha256",
|
|
112
|
+
f."telegramMessageId",
|
|
113
|
+
f."createdAt"
|
|
114
|
+
FROM "File" f
|
|
115
|
+
WHERE NOT EXISTS (SELECT 1 FROM "FileVersion" v WHERE v."fileId" = f."id");
|
|
116
|
+
|
|
117
|
+
UPDATE "File" f
|
|
118
|
+
SET "currentVersionId" = 'v1_' || f."id", "versionCount" = 1
|
|
119
|
+
WHERE f."versionCount" = 0
|
|
120
|
+
AND EXISTS (SELECT 1 FROM "FileVersion" v WHERE v."id" = 'v1_' || f."id");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "BrowserSession" (
|
|
3
|
+
"id" TEXT NOT NULL,
|
|
4
|
+
"userId" TEXT NOT NULL,
|
|
5
|
+
"tokenHash" TEXT NOT NULL,
|
|
6
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
7
|
+
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
8
|
+
"revokedAt" TIMESTAMP(3),
|
|
9
|
+
"lastUsedAt" TIMESTAMP(3),
|
|
10
|
+
"userAgent" TEXT,
|
|
11
|
+
"ip" TEXT,
|
|
12
|
+
|
|
13
|
+
CONSTRAINT "BrowserSession_pkey" PRIMARY KEY ("id")
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- CreateIndex
|
|
17
|
+
CREATE UNIQUE INDEX "BrowserSession_tokenHash_key" ON "BrowserSession"("tokenHash");
|
|
18
|
+
|
|
19
|
+
-- CreateIndex
|
|
20
|
+
CREATE INDEX "BrowserSession_userId_revokedAt_idx" ON "BrowserSession"("userId", "revokedAt");
|
|
21
|
+
|
|
22
|
+
-- CreateIndex
|
|
23
|
+
CREATE INDEX "BrowserSession_expiresAt_idx" ON "BrowserSession"("expiresAt");
|
|
24
|
+
|
|
25
|
+
-- AddForeignKey
|
|
26
|
+
ALTER TABLE "BrowserSession" ADD CONSTRAINT "BrowserSession_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
27
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "UploadOperation" (
|
|
3
|
+
"id" TEXT NOT NULL,
|
|
4
|
+
"userId" TEXT NOT NULL,
|
|
5
|
+
"operationId" TEXT NOT NULL,
|
|
6
|
+
"status" TEXT NOT NULL,
|
|
7
|
+
"telegramMessageId" BIGINT,
|
|
8
|
+
"sha256" TEXT,
|
|
9
|
+
"size" BIGINT,
|
|
10
|
+
"fileId" TEXT,
|
|
11
|
+
"error" TEXT,
|
|
12
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
13
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
14
|
+
|
|
15
|
+
CONSTRAINT "UploadOperation_pkey" PRIMARY KEY ("id")
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- CreateIndex
|
|
19
|
+
CREATE INDEX "UploadOperation_status_updatedAt_idx" ON "UploadOperation"("status", "updatedAt");
|
|
20
|
+
|
|
21
|
+
-- CreateIndex
|
|
22
|
+
CREATE UNIQUE INDEX "UploadOperation_userId_operationId_key" ON "UploadOperation"("userId", "operationId");
|
|
23
|
+
|
|
24
|
+
-- AddForeignKey
|
|
25
|
+
ALTER TABLE "UploadOperation" ADD CONSTRAINT "UploadOperation_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
26
|
+
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// OmniCloud metadata schema (v0.2).
|
|
2
|
+
//
|
|
3
|
+
// Telegram stores the actual binary file content; PostgreSQL stores the
|
|
4
|
+
// logical representation of the user's cloud (users, folders, file metadata,
|
|
5
|
+
// versions, trash state, stars, activity events, storage registrations and
|
|
6
|
+
// Telegram sessions).
|
|
7
|
+
|
|
8
|
+
generator client {
|
|
9
|
+
provider = "prisma-client-js"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
datasource db {
|
|
13
|
+
provider = "postgresql"
|
|
14
|
+
url = env("DATABASE_URL")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
model User {
|
|
18
|
+
id String @id @default(cuid())
|
|
19
|
+
telegramUserId BigInt @unique
|
|
20
|
+
username String?
|
|
21
|
+
firstName String?
|
|
22
|
+
lastName String?
|
|
23
|
+
phone String?
|
|
24
|
+
createdAt DateTime @default(now())
|
|
25
|
+
updatedAt DateTime @updatedAt
|
|
26
|
+
|
|
27
|
+
telegramSession TelegramSession?
|
|
28
|
+
storages Storage[]
|
|
29
|
+
folders Folder[]
|
|
30
|
+
files File[]
|
|
31
|
+
fileVersions FileVersion[]
|
|
32
|
+
activityEvents ActivityEvent[]
|
|
33
|
+
browserSessions BrowserSession[]
|
|
34
|
+
uploadOperations UploadOperation[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// A signed-in browser session. Only the SHA-256 of the cookie token is stored,
|
|
38
|
+
/// so revoking the row ends the session on the next request.
|
|
39
|
+
model BrowserSession {
|
|
40
|
+
id String @id @default(cuid())
|
|
41
|
+
userId String
|
|
42
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
43
|
+
tokenHash String @unique
|
|
44
|
+
createdAt DateTime @default(now())
|
|
45
|
+
expiresAt DateTime
|
|
46
|
+
revokedAt DateTime?
|
|
47
|
+
lastUsedAt DateTime?
|
|
48
|
+
userAgent String?
|
|
49
|
+
ip String?
|
|
50
|
+
|
|
51
|
+
@@index([userId, revokedAt])
|
|
52
|
+
@@index([expiresAt])
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// One logical upload, keyed by a client-supplied id so a retry never stores a
|
|
56
|
+
/// second Telegram object. `telegramMessageId` is recorded as soon as Telegram
|
|
57
|
+
/// accepts the object, so recovery can commit the file without uploading again.
|
|
58
|
+
model UploadOperation {
|
|
59
|
+
id String @id @default(cuid())
|
|
60
|
+
userId String
|
|
61
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
62
|
+
operationId String
|
|
63
|
+
status String
|
|
64
|
+
telegramMessageId BigInt?
|
|
65
|
+
sha256 String?
|
|
66
|
+
size BigInt?
|
|
67
|
+
fileId String?
|
|
68
|
+
error String?
|
|
69
|
+
createdAt DateTime @default(now())
|
|
70
|
+
updatedAt DateTime @updatedAt
|
|
71
|
+
|
|
72
|
+
@@unique([userId, operationId])
|
|
73
|
+
@@index([status, updatedAt])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// MTProto session string for the user's connected Telegram account.
|
|
77
|
+
/// Never exposed through the API and never logged.
|
|
78
|
+
model TelegramSession {
|
|
79
|
+
id String @id @default(cuid())
|
|
80
|
+
userId String @unique
|
|
81
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
82
|
+
stringSession String
|
|
83
|
+
createdAt DateTime @default(now())
|
|
84
|
+
updatedAt DateTime @updatedAt
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// The user's private storage channel used as the backing object store.
|
|
88
|
+
model Storage {
|
|
89
|
+
id String @id @default(cuid())
|
|
90
|
+
userId String
|
|
91
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
92
|
+
provider String @default("telegram")
|
|
93
|
+
title String
|
|
94
|
+
telegramChatId BigInt
|
|
95
|
+
telegramAccessHash BigInt
|
|
96
|
+
createdAt DateTime @default(now())
|
|
97
|
+
updatedAt DateTime @updatedAt
|
|
98
|
+
|
|
99
|
+
@@unique([userId, provider])
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// Folders are virtual OmniCloud objects — they have no physical
|
|
103
|
+
/// representation on Telegram. `deletedAt` is the Trash marker.
|
|
104
|
+
model Folder {
|
|
105
|
+
id String @id @default(cuid())
|
|
106
|
+
userId String
|
|
107
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
108
|
+
parentId String?
|
|
109
|
+
parent Folder? @relation("FolderTree", fields: [parentId], references: [id], onDelete: Restrict)
|
|
110
|
+
children Folder[] @relation("FolderTree")
|
|
111
|
+
name String
|
|
112
|
+
starred Boolean @default(false)
|
|
113
|
+
deletedAt DateTime?
|
|
114
|
+
/// Groups everything one trash operation moved, for exact restore.
|
|
115
|
+
trashBatchId String?
|
|
116
|
+
createdAt DateTime @default(now())
|
|
117
|
+
updatedAt DateTime @updatedAt
|
|
118
|
+
files File[]
|
|
119
|
+
|
|
120
|
+
@@index([userId, parentId, deletedAt])
|
|
121
|
+
@@index([userId, deletedAt])
|
|
122
|
+
@@index([userId, name])
|
|
123
|
+
@@index([userId, starred])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// File metadata. `telegramMessageId` points at the current version's message
|
|
127
|
+
/// in the user's storage channel; `currentVersionId` links the version row
|
|
128
|
+
/// that content is served from.
|
|
129
|
+
model File {
|
|
130
|
+
id String @id @default(cuid())
|
|
131
|
+
userId String
|
|
132
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
133
|
+
folderId String?
|
|
134
|
+
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
135
|
+
name String
|
|
136
|
+
size BigInt
|
|
137
|
+
mimeType String
|
|
138
|
+
sha256 String
|
|
139
|
+
telegramMessageId BigInt
|
|
140
|
+
starred Boolean @default(false)
|
|
141
|
+
deletedAt DateTime?
|
|
142
|
+
/// Groups everything one trash operation moved, for exact restore.
|
|
143
|
+
trashBatchId String?
|
|
144
|
+
currentVersionId String?
|
|
145
|
+
versionCount Int @default(0)
|
|
146
|
+
createdAt DateTime @default(now())
|
|
147
|
+
updatedAt DateTime @updatedAt
|
|
148
|
+
|
|
149
|
+
versions FileVersion[]
|
|
150
|
+
|
|
151
|
+
@@index([userId, folderId, deletedAt])
|
|
152
|
+
@@index([userId, deletedAt])
|
|
153
|
+
@@index([userId, name])
|
|
154
|
+
@@index([userId, starred])
|
|
155
|
+
@@index([userId, size])
|
|
156
|
+
@@index([userId, mimeType])
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/// Version foundation for v0.3's version history. Every upload creates a row;
|
|
160
|
+
/// replacing a file appends a version and repoints the file's current version.
|
|
161
|
+
model FileVersion {
|
|
162
|
+
id String @id @default(cuid())
|
|
163
|
+
fileId String
|
|
164
|
+
file File @relation(fields: [fileId], references: [id], onDelete: Cascade)
|
|
165
|
+
userId String
|
|
166
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
167
|
+
versionNumber Int
|
|
168
|
+
size BigInt
|
|
169
|
+
mimeType String
|
|
170
|
+
sha256 String
|
|
171
|
+
telegramMessageId BigInt
|
|
172
|
+
createdAt DateTime @default(now())
|
|
173
|
+
|
|
174
|
+
@@unique([fileId, versionNumber])
|
|
175
|
+
@@index([fileId])
|
|
176
|
+
@@index([userId])
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// Structured activity/audit events. Metadata never contains credentials.
|
|
180
|
+
model ActivityEvent {
|
|
181
|
+
id String @id @default(cuid())
|
|
182
|
+
userId String
|
|
183
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
184
|
+
action String
|
|
185
|
+
resourceType String
|
|
186
|
+
resourceId String
|
|
187
|
+
resourceName String?
|
|
188
|
+
metadata Json?
|
|
189
|
+
createdAt DateTime @default(now())
|
|
190
|
+
|
|
191
|
+
@@index([userId, createdAt])
|
|
192
|
+
@@index([userId, resourceId, createdAt])
|
|
193
|
+
@@index([createdAt])
|
|
194
|
+
}
|