web server
This commit is contained in:
11
web-server/database/01_create_database.sql
Normal file
11
web-server/database/01_create_database.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
IF DB_ID(N'RobotInstaller') IS NULL
|
||||
BEGIN
|
||||
CREATE DATABASE [RobotInstaller];
|
||||
END;
|
||||
GO
|
||||
|
||||
USE [RobotInstaller];
|
||||
GO
|
||||
|
||||
PRINT N'Database RobotInstaller is ready.';
|
||||
GO
|
||||
291
web-server/database/02_schema.sql
Normal file
291
web-server/database/02_schema.sql
Normal file
@@ -0,0 +1,291 @@
|
||||
USE [RobotInstaller];
|
||||
GO
|
||||
|
||||
SET ANSI_NULLS ON;
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.ApplicationPackages', N'U') IS NOT NULL
|
||||
OR OBJECT_ID(N'dbo.PackageVersions', N'U') IS NOT NULL
|
||||
OR OBJECT_ID(N'dbo.Applications', N'U') IS NOT NULL
|
||||
OR OBJECT_ID(N'dbo.Packages', N'U') IS NOT NULL
|
||||
OR OBJECT_ID(N'dbo.EmailConfirmationTokens', N'U') IS NOT NULL
|
||||
OR OBJECT_ID(N'dbo.Users', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
THROW 50001, 'Schema tables already exist. Review, drop, or migrate existing tables before running 02_schema.sql.', 1;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.Users
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_Users PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_Users_Id DEFAULT NEWSEQUENTIALID(),
|
||||
Username NVARCHAR(100) NOT NULL,
|
||||
Email NVARCHAR(255) NOT NULL,
|
||||
PasswordHash NVARCHAR(500) NOT NULL,
|
||||
FullName NVARCHAR(200) NULL,
|
||||
Role NVARCHAR(50) NOT NULL
|
||||
CONSTRAINT DF_Users_Role DEFAULT N'User',
|
||||
IsActive BIT NOT NULL
|
||||
CONSTRAINT DF_Users_IsActive DEFAULT 1,
|
||||
CreatedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_Users_CreatedAt DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedAt DATETIME2(3) NULL,
|
||||
CONSTRAINT CK_Users_Role CHECK (Role IN (N'Admin', N'User')),
|
||||
CONSTRAINT CK_Users_Username_NotBlank CHECK (LEN(LTRIM(RTRIM(Username))) > 0),
|
||||
CONSTRAINT CK_Users_Email_NotBlank CHECK (LEN(LTRIM(RTRIM(Email))) > 0)
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.EmailConfirmationTokens
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_EmailConfirmationTokens PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_EmailConfirmationTokens_Id DEFAULT NEWSEQUENTIALID(),
|
||||
UserId UNIQUEIDENTIFIER NOT NULL,
|
||||
TokenHash CHAR(64) NOT NULL,
|
||||
ExpiresAt DATETIME2(3) NOT NULL,
|
||||
ConfirmedAt DATETIME2(3) NULL,
|
||||
CreatedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_EmailConfirmationTokens_CreatedAt DEFAULT SYSUTCDATETIME(),
|
||||
CONSTRAINT FK_EmailConfirmationTokens_User
|
||||
FOREIGN KEY (UserId) REFERENCES dbo.Users(Id) ON DELETE CASCADE
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.Packages
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_Packages PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_Packages_Id DEFAULT NEWSEQUENTIALID(),
|
||||
PackageCode NVARCHAR(100) NOT NULL,
|
||||
PackageName NVARCHAR(200) NOT NULL,
|
||||
PackageType NVARCHAR(20) NOT NULL,
|
||||
Description NVARCHAR(MAX) NULL,
|
||||
CreatedByUserId UNIQUEIDENTIFIER NOT NULL,
|
||||
CreatedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_Packages_CreatedAt DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedAt DATETIME2(3) NULL,
|
||||
IsActive BIT NOT NULL
|
||||
CONSTRAINT DF_Packages_IsActive DEFAULT 1,
|
||||
CONSTRAINT FK_Packages_CreatedByUser
|
||||
FOREIGN KEY (CreatedByUserId) REFERENCES dbo.Users(Id),
|
||||
CONSTRAINT CK_Packages_PackageType CHECK (PackageType IN (N'deb', N'docker')),
|
||||
CONSTRAINT CK_Packages_PackageCode_NotBlank CHECK (LEN(LTRIM(RTRIM(PackageCode))) > 0),
|
||||
CONSTRAINT CK_Packages_PackageName_NotBlank CHECK (LEN(LTRIM(RTRIM(PackageName))) > 0)
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.PackageVersions
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_PackageVersions PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_PackageVersions_Id DEFAULT NEWSEQUENTIALID(),
|
||||
PackageId UNIQUEIDENTIFIER NOT NULL,
|
||||
Version NVARCHAR(50) NOT NULL,
|
||||
FilePath NVARCHAR(1000) NULL,
|
||||
DockerImage NVARCHAR(500) NULL,
|
||||
FileChecksumSha256 CHAR(64) NULL,
|
||||
FileSizeBytes BIGINT NULL,
|
||||
ChangeLog NVARCHAR(MAX) NULL,
|
||||
ReleaseDate DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_PackageVersions_ReleaseDate DEFAULT SYSUTCDATETIME(),
|
||||
UploadedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_PackageVersions_UploadedAt DEFAULT SYSUTCDATETIME(),
|
||||
IsLatest BIT NOT NULL
|
||||
CONSTRAINT DF_PackageVersions_IsLatest DEFAULT 0,
|
||||
IsDeprecated BIT NOT NULL
|
||||
CONSTRAINT DF_PackageVersions_IsDeprecated DEFAULT 0,
|
||||
CONSTRAINT FK_PackageVersions_Package
|
||||
FOREIGN KEY (PackageId) REFERENCES dbo.Packages(Id) ON DELETE CASCADE,
|
||||
CONSTRAINT CK_PackageVersions_Version_NotBlank CHECK (LEN(LTRIM(RTRIM(Version))) > 0),
|
||||
CONSTRAINT CK_PackageVersions_FileSizeBytes CHECK (FileSizeBytes IS NULL OR FileSizeBytes >= 0),
|
||||
CONSTRAINT CK_PackageVersions_FileChecksumSha256 CHECK (
|
||||
FileChecksumSha256 IS NULL
|
||||
OR FileChecksumSha256 NOT LIKE '%[^0-9A-Fa-f]%'
|
||||
)
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.Applications
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_Applications PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_Applications_Id DEFAULT NEWSEQUENTIALID(),
|
||||
AppCode NVARCHAR(100) NOT NULL,
|
||||
AppName NVARCHAR(200) NOT NULL,
|
||||
AppVersion NVARCHAR(50) NOT NULL
|
||||
CONSTRAINT DF_Applications_AppVersion DEFAULT N'1.0.0',
|
||||
Description NVARCHAR(MAX) NULL,
|
||||
CreatedByUserId UNIQUEIDENTIFIER NOT NULL,
|
||||
CreatedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_Applications_CreatedAt DEFAULT SYSUTCDATETIME(),
|
||||
UpdatedAt DATETIME2(3) NULL,
|
||||
Status NVARCHAR(50) NOT NULL
|
||||
CONSTRAINT DF_Applications_Status DEFAULT N'Draft',
|
||||
Notes NVARCHAR(500) NULL,
|
||||
CONSTRAINT FK_Applications_CreatedByUser
|
||||
FOREIGN KEY (CreatedByUserId) REFERENCES dbo.Users(Id),
|
||||
CONSTRAINT CK_Applications_Status CHECK (Status IN (N'Draft', N'Released', N'Archived')),
|
||||
CONSTRAINT CK_Applications_AppCode_NotBlank CHECK (LEN(LTRIM(RTRIM(AppCode))) > 0),
|
||||
CONSTRAINT CK_Applications_AppName_NotBlank CHECK (LEN(LTRIM(RTRIM(AppName))) > 0),
|
||||
CONSTRAINT CK_Applications_AppVersion_NotBlank CHECK (LEN(LTRIM(RTRIM(AppVersion))) > 0)
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE TABLE dbo.ApplicationPackages
|
||||
(
|
||||
Id UNIQUEIDENTIFIER NOT NULL
|
||||
CONSTRAINT PK_ApplicationPackages PRIMARY KEY CLUSTERED
|
||||
CONSTRAINT DF_ApplicationPackages_Id DEFAULT NEWSEQUENTIALID(),
|
||||
ApplicationId UNIQUEIDENTIFIER NOT NULL,
|
||||
PackageId UNIQUEIDENTIFIER NOT NULL,
|
||||
SelectedVersionId UNIQUEIDENTIFIER NULL,
|
||||
AddedAt DATETIME2(3) NOT NULL
|
||||
CONSTRAINT DF_ApplicationPackages_AddedAt DEFAULT SYSUTCDATETIME(),
|
||||
Notes NVARCHAR(500) NULL,
|
||||
CONSTRAINT FK_ApplicationPackages_Application
|
||||
FOREIGN KEY (ApplicationId) REFERENCES dbo.Applications(Id) ON DELETE CASCADE,
|
||||
CONSTRAINT FK_ApplicationPackages_Package
|
||||
FOREIGN KEY (PackageId) REFERENCES dbo.Packages(Id) ON DELETE CASCADE
|
||||
);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_Users_Username ON dbo.Users(Username);
|
||||
CREATE UNIQUE INDEX UX_Users_Email ON dbo.Users(Email);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_EmailConfirmationTokens_TokenHash
|
||||
ON dbo.EmailConfirmationTokens(TokenHash);
|
||||
|
||||
CREATE INDEX IX_EmailConfirmationTokens_UserId
|
||||
ON dbo.EmailConfirmationTokens(UserId);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_Packages_PackageCode ON dbo.Packages(PackageCode);
|
||||
CREATE INDEX IX_Packages_CreatedByUserId ON dbo.Packages(CreatedByUserId);
|
||||
CREATE INDEX IX_Packages_PackageType ON dbo.Packages(PackageType);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_PackageVersions_PackageId_Version
|
||||
ON dbo.PackageVersions(PackageId, Version);
|
||||
|
||||
CREATE UNIQUE INDEX UX_PackageVersions_Id_PackageId
|
||||
ON dbo.PackageVersions(Id, PackageId);
|
||||
|
||||
CREATE UNIQUE INDEX UX_PackageVersions_OneLatestPerPackage
|
||||
ON dbo.PackageVersions(PackageId)
|
||||
WHERE IsLatest = 1;
|
||||
|
||||
CREATE INDEX IX_PackageVersions_PackageId_ReleaseDate
|
||||
ON dbo.PackageVersions(PackageId, ReleaseDate DESC);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_Applications_AppCode
|
||||
ON dbo.Applications(AppCode);
|
||||
|
||||
CREATE INDEX IX_Applications_CreatedByUserId ON dbo.Applications(CreatedByUserId);
|
||||
CREATE INDEX IX_Applications_Status ON dbo.Applications(Status);
|
||||
GO
|
||||
|
||||
CREATE UNIQUE INDEX UX_ApplicationPackages_ApplicationId_PackageId
|
||||
ON dbo.ApplicationPackages(ApplicationId, PackageId);
|
||||
|
||||
CREATE INDEX IX_ApplicationPackages_PackageId
|
||||
ON dbo.ApplicationPackages(PackageId);
|
||||
|
||||
CREATE INDEX IX_ApplicationPackages_SelectedVersionId
|
||||
ON dbo.ApplicationPackages(SelectedVersionId);
|
||||
GO
|
||||
|
||||
ALTER TABLE dbo.ApplicationPackages
|
||||
ADD CONSTRAINT FK_ApplicationPackages_SelectedVersionBelongsToPackage
|
||||
FOREIGN KEY (SelectedVersionId, PackageId)
|
||||
REFERENCES dbo.PackageVersions(Id, PackageId);
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.SetLatestPackageVersion
|
||||
@PackageVersionId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
|
||||
DECLARE @PackageId UNIQUEIDENTIFIER;
|
||||
|
||||
SELECT @PackageId = PackageId
|
||||
FROM dbo.PackageVersions
|
||||
WHERE Id = @PackageVersionId;
|
||||
|
||||
IF @PackageId IS NULL
|
||||
BEGIN
|
||||
THROW 50002, 'Package version does not exist.', 1;
|
||||
END;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
UPDATE dbo.PackageVersions
|
||||
SET IsLatest = 0
|
||||
WHERE PackageId = @PackageId;
|
||||
|
||||
UPDATE dbo.PackageVersions
|
||||
SET IsLatest = 1,
|
||||
IsDeprecated = 0
|
||||
WHERE Id = @PackageVersionId;
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.DeletePackageVersion
|
||||
@PackageVersionId UNIQUEIDENTIFIER
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
|
||||
DECLARE @PackageId UNIQUEIDENTIFIER;
|
||||
DECLARE @WasLatest BIT;
|
||||
|
||||
SELECT
|
||||
@PackageId = PackageId,
|
||||
@WasLatest = IsLatest
|
||||
FROM dbo.PackageVersions
|
||||
WHERE Id = @PackageVersionId;
|
||||
|
||||
IF @PackageId IS NULL
|
||||
BEGIN
|
||||
THROW 50003, 'Package version does not exist.', 1;
|
||||
END;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
DELETE FROM dbo.ApplicationPackages
|
||||
WHERE SelectedVersionId = @PackageVersionId;
|
||||
|
||||
DELETE FROM dbo.PackageVersions
|
||||
WHERE Id = @PackageVersionId;
|
||||
|
||||
IF @WasLatest = 1
|
||||
BEGIN
|
||||
DECLARE @NextLatestId UNIQUEIDENTIFIER;
|
||||
|
||||
SELECT TOP (1) @NextLatestId = Id
|
||||
FROM dbo.PackageVersions
|
||||
WHERE PackageId = @PackageId
|
||||
AND IsDeprecated = 0
|
||||
ORDER BY ReleaseDate DESC, UploadedAt DESC;
|
||||
|
||||
IF @NextLatestId IS NOT NULL
|
||||
BEGIN
|
||||
EXEC dbo.SetLatestPackageVersion @NextLatestId;
|
||||
END;
|
||||
END;
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
END;
|
||||
GO
|
||||
|
||||
PRINT N'RobotInstaller schema was created successfully.';
|
||||
GO
|
||||
131
web-server/database/03_views.sql
Normal file
131
web-server/database/03_views.sql
Normal file
@@ -0,0 +1,131 @@
|
||||
USE [RobotInstaller];
|
||||
GO
|
||||
|
||||
CREATE OR ALTER VIEW dbo.vw_PackageList
|
||||
AS
|
||||
SELECT
|
||||
p.Id,
|
||||
p.PackageCode,
|
||||
p.PackageName,
|
||||
p.PackageType,
|
||||
p.Description,
|
||||
p.IsActive,
|
||||
p.CreatedAt,
|
||||
p.UpdatedAt,
|
||||
p.CreatedByUserId,
|
||||
u.Username AS CreatedByUsername,
|
||||
latest.Id AS LatestVersionId,
|
||||
latest.Version AS LatestVersion,
|
||||
latest.ReleaseDate AS LatestReleaseDate,
|
||||
latest.FilePath AS LatestFilePath,
|
||||
latest.DockerImage AS LatestDockerImage,
|
||||
version_count.VersionCount
|
||||
FROM dbo.Packages AS p
|
||||
INNER JOIN dbo.Users AS u
|
||||
ON u.Id = p.CreatedByUserId
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
pv.Id,
|
||||
pv.Version,
|
||||
pv.ReleaseDate,
|
||||
pv.FilePath,
|
||||
pv.DockerImage
|
||||
FROM dbo.PackageVersions AS pv
|
||||
WHERE pv.PackageId = p.Id
|
||||
ORDER BY pv.IsLatest DESC, pv.ReleaseDate DESC, pv.UploadedAt DESC
|
||||
) AS latest
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT COUNT_BIG(*) AS VersionCount
|
||||
FROM dbo.PackageVersions AS pv
|
||||
WHERE pv.PackageId = p.Id
|
||||
) AS version_count;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER VIEW dbo.vw_PackageVersionList
|
||||
AS
|
||||
SELECT
|
||||
pv.Id,
|
||||
pv.PackageId,
|
||||
p.PackageCode,
|
||||
p.PackageName,
|
||||
p.PackageType,
|
||||
pv.Version,
|
||||
pv.FilePath,
|
||||
pv.DockerImage,
|
||||
pv.FileChecksumSha256,
|
||||
pv.FileSizeBytes,
|
||||
pv.ChangeLog,
|
||||
pv.ReleaseDate,
|
||||
pv.UploadedAt,
|
||||
pv.IsLatest,
|
||||
pv.IsDeprecated
|
||||
FROM dbo.PackageVersions AS pv
|
||||
INNER JOIN dbo.Packages AS p
|
||||
ON p.Id = pv.PackageId;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER VIEW dbo.vw_ApplicationList
|
||||
AS
|
||||
SELECT
|
||||
a.Id,
|
||||
a.AppCode,
|
||||
a.AppName,
|
||||
a.AppVersion,
|
||||
a.Description,
|
||||
a.Status,
|
||||
a.Notes,
|
||||
a.CreatedAt,
|
||||
a.UpdatedAt,
|
||||
a.CreatedByUserId,
|
||||
u.Username AS CreatedByUsername,
|
||||
COUNT_BIG(ap.Id) AS PackageCount
|
||||
FROM dbo.Applications AS a
|
||||
INNER JOIN dbo.Users AS u
|
||||
ON u.Id = a.CreatedByUserId
|
||||
LEFT JOIN dbo.ApplicationPackages AS ap
|
||||
ON ap.ApplicationId = a.Id
|
||||
GROUP BY
|
||||
a.Id,
|
||||
a.AppCode,
|
||||
a.AppName,
|
||||
a.AppVersion,
|
||||
a.Description,
|
||||
a.Status,
|
||||
a.Notes,
|
||||
a.CreatedAt,
|
||||
a.UpdatedAt,
|
||||
a.CreatedByUserId,
|
||||
u.Username;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER VIEW dbo.vw_ApplicationPackageDetails
|
||||
AS
|
||||
SELECT
|
||||
ap.Id,
|
||||
ap.ApplicationId,
|
||||
a.AppCode,
|
||||
a.AppName,
|
||||
a.AppVersion,
|
||||
ap.PackageId,
|
||||
p.PackageCode,
|
||||
p.PackageName,
|
||||
p.PackageType,
|
||||
ap.SelectedVersionId,
|
||||
pv.Version AS SelectedVersion,
|
||||
pv.FilePath,
|
||||
pv.DockerImage,
|
||||
ap.AddedAt,
|
||||
ap.Notes
|
||||
FROM dbo.ApplicationPackages AS ap
|
||||
INNER JOIN dbo.Applications AS a
|
||||
ON a.Id = ap.ApplicationId
|
||||
INNER JOIN dbo.Packages AS p
|
||||
ON p.Id = ap.PackageId
|
||||
LEFT JOIN dbo.PackageVersions AS pv
|
||||
ON pv.Id = ap.SelectedVersionId;
|
||||
GO
|
||||
|
||||
PRINT N'RobotInstaller views were created successfully.';
|
||||
GO
|
||||
93
web-server/database/README.md
Normal file
93
web-server/database/README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# RobotInstaller database
|
||||
|
||||
Thiết kế này bám theo `database.md` và sơ đồ database hiện có, sau đó bổ sung vài cột cần cho web server:
|
||||
|
||||
- `PackageType`: phân biệt package `.deb` và `docker`.
|
||||
- `AppVersion`: version hiện tại của app đóng gói.
|
||||
- metadata artifact: `DockerImage`, `FileChecksumSha256`, `FileSizeBytes`, `UploadedAt`.
|
||||
- `Role`, `IsActive` cho tài khoản đăng nhập web.
|
||||
|
||||
## Database
|
||||
|
||||
Tên database được chọn: `RobotInstaller`
|
||||
|
||||
Server:
|
||||
|
||||
```powershell
|
||||
172.20.235.176
|
||||
```
|
||||
|
||||
Không lưu mật khẩu thật vào file cấu hình. Khi chạy local, tạo file `.env` từ `web-server/.env.example` rồi điền mật khẩu thật.
|
||||
|
||||
## Cấu trúc chính
|
||||
|
||||
| Bảng | Vai trò |
|
||||
| --- | --- |
|
||||
| `dbo.Users` | Người dùng web server |
|
||||
| `dbo.Packages` | Danh mục package |
|
||||
| `dbo.PackageVersions` | Các version của từng package |
|
||||
| `dbo.Applications` | App được đóng gói từ nhiều package |
|
||||
| `dbo.ApplicationPackages` | Liên kết app-package, có thể chọn version cụ thể |
|
||||
|
||||
## Ràng buộc quan trọng
|
||||
|
||||
- `Users.Username`, `Users.Email` là duy nhất.
|
||||
- `Packages.PackageCode` là duy nhất.
|
||||
- `Applications.AppCode` là duy nhất.
|
||||
- Mỗi package không được trùng `Version`.
|
||||
- Mỗi app chỉ chứa một dòng cho mỗi package.
|
||||
- Mỗi package chỉ có tối đa một `IsLatest = 1`.
|
||||
- `ApplicationPackages.SelectedVersionId` bắt buộc thuộc đúng `PackageId` trên cùng dòng.
|
||||
|
||||
## View cho API
|
||||
|
||||
| View | Dùng cho màn hình |
|
||||
| --- | --- |
|
||||
| `dbo.vw_PackageList` | Danh sách package kèm latest version |
|
||||
| `dbo.vw_PackageVersionList` | Chi tiết version của package |
|
||||
| `dbo.vw_ApplicationList` | Danh sách app kèm số package |
|
||||
| `dbo.vw_ApplicationPackageDetails` | Chi tiết package/version trong app |
|
||||
|
||||
## Stored procedure
|
||||
|
||||
| Procedure | Mục đích |
|
||||
| --- | --- |
|
||||
| `dbo.SetLatestPackageVersion` | Đặt một version là latest và tự clear latest cũ |
|
||||
| `dbo.DeletePackageVersion` | Xóa version và các liên kết app đang dùng version đó |
|
||||
|
||||
## Triển khai bằng sqlcmd
|
||||
|
||||
```powershell
|
||||
$env:SQLCMDPASSWORD = '<mat-khau-sa>'
|
||||
|
||||
sqlcmd -S 172.20.235.176 -U sa -b -i .\database\01_create_database.sql
|
||||
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\02_schema.sql
|
||||
sqlcmd -S 172.20.235.176 -U sa -d RobotInstaller -b -i .\database\03_views.sql
|
||||
```
|
||||
|
||||
Chạy các lệnh trên từ thư mục `web-server`.
|
||||
|
||||
Khi dùng `sqlcmd` để seed/test dữ liệu, thêm `-I` hoặc bật `SET QUOTED_IDENTIFIER ON` vì schema có filtered index cho ràng buộc một latest version trên mỗi package.
|
||||
|
||||
## Luồng dữ liệu đề xuất
|
||||
|
||||
1. Upload package mới:
|
||||
- nếu package chưa tồn tại, insert vào `Packages`;
|
||||
- insert version vào `PackageVersions`;
|
||||
- gọi `dbo.SetLatestPackageVersion @PackageVersionId`.
|
||||
|
||||
2. Update package:
|
||||
- insert thêm một dòng mới vào `PackageVersions`;
|
||||
- gọi `dbo.SetLatestPackageVersion @PackageVersionId`.
|
||||
|
||||
3. Tạo app:
|
||||
- insert vào `Applications`;
|
||||
- insert các package được chọn vào `ApplicationPackages`;
|
||||
- nếu user chọn version cụ thể, điền `SelectedVersionId`.
|
||||
|
||||
4. Xóa package:
|
||||
- xóa dòng trong `Packages`;
|
||||
- database tự cascade sang `PackageVersions` và `ApplicationPackages`.
|
||||
|
||||
5. Xóa version:
|
||||
- gọi `dbo.DeletePackageVersion @PackageVersionId` để xóa cả liên kết app đang dùng version đó.
|
||||
Reference in New Issue
Block a user