update README

This commit is contained in:
Georgiy Syralev
2025-11-26 21:43:57 +03:00
parent c4c2610480
commit 753696cc93
58 changed files with 8674 additions and 3752 deletions

View File

@@ -0,0 +1,18 @@
-- Добавить колонку pricePerGb для расчёта кастомного тарифа
ALTER TABLE storage_plan ADD COLUMN pricePerGb DECIMAL(10, 4) NULL AFTER price;
-- Добавить кастомный тариф
INSERT INTO storage_plan
(code, name, price, pricePerGb, quotaGb, bandwidthGb, requestLimit, `order`, isActive, description)
VALUES
('custom', 'Custom', 0, 0.5, 0, 0, 'Неограниченно', 999, TRUE, 'Кастомный тариф - укажите нужное количество GB')
ON DUPLICATE KEY UPDATE
name = VALUES(name),
price = VALUES(price),
pricePerGb = VALUES(pricePerGb),
quotaGb = VALUES(quotaGb),
bandwidthGb = VALUES(bandwidthGb),
requestLimit = VALUES(requestLimit),
`order` = VALUES(`order`),
isActive = VALUES(isActive),
description = VALUES(description);

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE `storage_console_credential` ADD COLUMN `lastGeneratedAt` DATETIME(3) NULL;

View File

@@ -1,6 +0,0 @@
-- Добавление полей для интеграции с VPS Panel
ALTER TABLE `server` ADD COLUMN `panelVpsId` INT,
ADD COLUMN `panelSyncStatus` VARCHAR(255) DEFAULT 'pending';
-- Создание индекса для быстрого поиска серверов по ID на панели
CREATE INDEX `idx_panelVpsId` ON `server`(`panelVpsId`);

View File

@@ -0,0 +1,18 @@
-- CreateTable
CREATE TABLE `storage_plan` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`code` VARCHAR(64) NOT NULL,
`name` VARCHAR(128) NOT NULL,
`price` DOUBLE NOT NULL,
`quotaGb` INTEGER NOT NULL,
`bandwidthGb` INTEGER NOT NULL,
`requestLimit` VARCHAR(64) NOT NULL,
`order` INTEGER NOT NULL DEFAULT 0,
`isActive` BOOLEAN NOT NULL DEFAULT TRUE,
`description` VARCHAR(191) NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updatedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
UNIQUE INDEX `storage_plan_code_key`(`code`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@@ -0,0 +1,4 @@
-- AlterTable
ALTER TABLE `storage_bucket`
ADD CONSTRAINT `storage_bucket_plan_fkey`
FOREIGN KEY (`plan`) REFERENCES `storage_plan`(`code`) ON UPDATE CASCADE ON DELETE RESTRICT;

View File

@@ -0,0 +1,13 @@
-- CreateTable
CREATE TABLE `storage_console_credential` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`bucketId` INTEGER NOT NULL,
`login` VARCHAR(191) NOT NULL,
`passwordHash` VARCHAR(191) NOT NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updatedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
UNIQUE INDEX `storage_console_credential_bucketId_key`(`bucketId`),
PRIMARY KEY (`id`),
CONSTRAINT `storage_console_credential_bucketId_fkey` FOREIGN KEY (`bucketId`) REFERENCES `storage_bucket`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@@ -0,0 +1,22 @@
-- AlterTable
ALTER TABLE `storage_plan` ADD COLUMN `pricePerGb` DECIMAL(10,4) NULL AFTER `price`;
ALTER TABLE `storage_plan` ADD COLUMN `bandwidthPerGb` DECIMAL(10,4) NULL AFTER `pricePerGb`;
ALTER TABLE `storage_plan` ADD COLUMN `requestsPerGb` INT NULL AFTER `bandwidthPerGb`;
-- Add custom storage plan (цена, трафик и операции считаются пропорционально GB)
INSERT INTO `storage_plan`
(`code`, `name`, `price`, `pricePerGb`, `bandwidthPerGb`, `requestsPerGb`, `quotaGb`, `bandwidthGb`, `requestLimit`, `order`, `isActive`, `description`, `createdAt`, `updatedAt`)
VALUES
('custom', 'Custom', 0, 0.5, 1.2, 100000, 0, 0, '', 999, true, 'Кастомный тариф - укажите нужное количество GB', NOW(), NOW())
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`price` = VALUES(`price`),
`pricePerGb` = VALUES(`pricePerGb`),
`bandwidthPerGb` = VALUES(`bandwidthPerGb`),
`requestsPerGb` = VALUES(`requestsPerGb`),
`quotaGb` = VALUES(`quotaGb`),
`bandwidthGb` = VALUES(`bandwidthGb`),
`requestLimit` = VALUES(`requestLimit`),
`order` = VALUES(`order`),
`isActive` = VALUES(`isActive`),
`description` = VALUES(`description`);

View File

@@ -31,6 +31,7 @@ model User {
posts Post[] @relation("PostAuthor") // Статьи блога
comments Comment[] @relation("UserComments") // Комментарии
buckets StorageBucket[] // S3 хранилища пользователя
checkoutSessions StorageCheckoutSession[]
// Новые relations для расширенных настроек
sessions Session[]
@@ -377,7 +378,7 @@ model StorageBucket {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
name String // Уникальное имя бакета в рамках пользователя
plan String // Выбранный тариф (basic, standard, plus, pro, enterprise)
plan String // Код тарифа из StoragePlan
quotaGb Int // Лимит включённого объёма в GB
usedBytes BigInt @default(0) // Текущий объём хранения в байтах
objectCount Int @default(0)
@@ -391,6 +392,10 @@ model StorageBucket {
lastBilledAt DateTime?
autoRenew Boolean @default(true)
usageSyncedAt DateTime?
storagePlan StoragePlan? @relation(fields: [plan], references: [code])
regionConfig StorageRegion @relation("BucketRegion", fields: [region], references: [code])
storageClassConfig StorageClass @relation("BucketClass", fields: [storageClass], references: [code])
consoleCredential StorageConsoleCredential?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -398,6 +403,8 @@ model StorageBucket {
accessKeys StorageAccessKey[]
@@index([userId])
@@index([region])
@@index([storageClass])
@@unique([userId, name]) // Имя уникально в рамках пользователя
@@map("storage_bucket")
}
@@ -416,4 +423,98 @@ model StorageAccessKey {
@@index([bucketId])
@@map("storage_access_key")
}
model StorageConsoleCredential {
id Int @id @default(autoincrement())
bucketId Int @unique
bucket StorageBucket @relation(fields: [bucketId], references: [id], onDelete: Cascade)
login String
passwordHash String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
lastGeneratedAt DateTime? // Для rate limiting (1 раз в неделю)
@@map("storage_console_credential")
}
model StoragePlan {
id Int @id @default(autoincrement())
code String @unique
name String
price Float
pricePerGb Decimal? @db.Decimal(10, 4) // Цена за 1 GB для кастомного тарифа
bandwidthPerGb Decimal? @db.Decimal(10, 4) // GB трафика на 1 GB хранения
requestsPerGb Int? // Количество операций на 1 GB хранения
quotaGb Int // Базовая квота для обычных тарифов (0 для custom)
bandwidthGb Int // Базовый трафик для обычных тарифов (0 для custom)
requestLimit String // Текстовое описание лимита операций
order Int @default(0)
isActive Boolean @default(true)
description String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
buckets StorageBucket[]
checkoutSessions StorageCheckoutSession[]
@@map("storage_plan")
}
model StorageCheckoutSession {
id String @id @default(uuid())
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
planId Int
plan StoragePlan @relation(fields: [planId], references: [id])
planCode String
planName String
planDescription String?
price Float
quotaGb Int
bandwidthGb Int
requestLimit String
createdAt DateTime @default(now())
expiresAt DateTime
consumedAt DateTime?
@@index([userId])
@@index([planId])
@@map("storage_checkout_session")
}
model StorageRegion {
id Int @id @default(autoincrement())
code String @unique
name String
description String?
endpoint String?
isDefault Boolean @default(false)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
buckets StorageBucket[] @relation("BucketRegion")
@@map("storage_region")
}
model StorageClass {
id Int @id @default(autoincrement())
code String @unique
name String
description String?
redundancy String?
performance String?
retrievalFee String?
isDefault Boolean @default(false)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
buckets StorageBucket[] @relation("BucketClass")
@@map("storage_class")
}

View File

@@ -0,0 +1,24 @@
INSERT INTO storage_plan
(code, name, price, quotaGb, bandwidthGb, requestLimit, `order`, isActive, description)
VALUES
('dev-50', 'Developer 50', 99, 50, 100, '100 000 операций', 1, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('dev-100', 'Developer 100', 149, 100, 200, '250 000 операций', 2, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('dev-250', 'Developer 250', 199, 250, 400, '500 000 операций', 3, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('team-500', 'Team 500', 349, 500, 800, '1 000 000 операций', 4, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('team-1000', 'Team 1000', 499, 1000, 1500, '2 000 000 операций', 5, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('team-2000', 'Team 2000', 749, 2000, 3000, '5 000 000 операций', 6, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('scale-5000', 'Scale 5K', 1099, 5000, 6000, '10 000 000 операций', 7, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('scale-10000', 'Scale 10K', 1599, 10000, 12000, '20 000 000 операций', 8, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('scale-20000', 'Scale 20K', 2199, 20000, 25000, '50 000 000 операций', 9, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('enterprise-50000', 'Enterprise 50K', 3999, 50000, 60000, '100 000 000 операций', 10, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('enterprise-100000', 'Enterprise 100K', 6999, 100000, 120000, '250 000 000 операций', 11, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key'),
('enterprise-250000', 'Enterprise 250K', 11999, 250000, 300000, '500 000 000 операций', 12, TRUE, 'ru-central-1 регион | S3-совместимый API | Версионирование и presigned URL | Панель управления и уведомления | Access Key / Secret Key')
ON DUPLICATE KEY UPDATE
name = VALUES(name),
price = VALUES(price),
quotaGb = VALUES(quotaGb),
bandwidthGb = VALUES(bandwidthGb),
requestLimit = VALUES(requestLimit),
`order` = VALUES(`order`),
isActive = VALUES(isActive),
description = VALUES(description);