更新前后端代码
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// Role 角色
|
||||
type Role struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:50;uniqueIndex;not null" json:"name"`
|
||||
Code string `gorm:"size:50;uniqueIndex;not null" json:"code"`
|
||||
Description string `gorm:"size:255" json:"description"`
|
||||
IsSystem bool `gorm:"default:false" json:"is_system"`
|
||||
Status int8 `gorm:"default:1" json:"status"` // 1:启用 0:禁用
|
||||
Permissions []Permission `gorm:"many2many:role_permissions;" json:"permissions,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// Permission 权限
|
||||
type Permission struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:50;not null" json:"name"`
|
||||
Code string `gorm:"size:100;uniqueIndex;not null" json:"code"`
|
||||
Module string `gorm:"size:50;not null" json:"module"`
|
||||
Description string `gorm:"size:255" json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// User 用户
|
||||
type User struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Username string `gorm:"size:50;uniqueIndex;not null" json:"username"`
|
||||
Email string `gorm:"size:100;uniqueIndex;not null" json:"email"`
|
||||
PasswordHash string `gorm:"size:255;not null" json:"-"`
|
||||
RoleID uint `gorm:"default:1" json:"role_id"`
|
||||
Role *Role `gorm:"foreignKey:RoleID" json:"role,omitempty"`
|
||||
Status int8 `gorm:"default:1" json:"status"` // 1:正常 0:禁用
|
||||
StorageUsed int64 `gorm:"default:0" json:"storage_used"`
|
||||
StorageLimit int64 `gorm:"default:10737418240" json:"storage_limit"`
|
||||
LastLoginAt *time.Time `json:"last_login_at"`
|
||||
LastLoginIP string `gorm:"size:50" json:"last_login_ip"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// APIKey API密钥
|
||||
type APIKey struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
AccessKey string `gorm:"size:32;uniqueIndex;not null" json:"access_key"`
|
||||
SecretKey string `gorm:"size:64;not null" json:"-"`
|
||||
Name string `gorm:"size:50" json:"name"`
|
||||
Status int8 `gorm:"default:1" json:"status"`
|
||||
LastUsedAt *time.Time `json:"last_used_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// Project 项目
|
||||
type Project struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
Name string `gorm:"size:100;not null;uniqueIndex:idx_user_project" json:"name"`
|
||||
Description string `json:"description"`
|
||||
StorageUsed int64 `gorm:"default:0" json:"storage_used"`
|
||||
StorageLimit int64 `gorm:"default:5368709120" json:"storage_limit"`
|
||||
Status int8 `gorm:"default:1" json:"status"` // 1:正常 0:禁用
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// File 文件
|
||||
type File struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
ProjectID uint `gorm:"index;not null" json:"project_id"`
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
Filename string `gorm:"size:500;not null" json:"filename"` // 原始文件名(可含虚拟目录)
|
||||
StoredPath string `gorm:"size:500;not null" json:"-"` // 物理存储路径
|
||||
Size int64 `gorm:"not null" json:"size"`
|
||||
MimeType string `gorm:"size:100" json:"mime_type"`
|
||||
MD5 string `gorm:"size:32;index" json:"md5"`
|
||||
StorageType int8 `gorm:"default:1" json:"storage_type"` // 1:本地存储
|
||||
Visibility int8 `gorm:"default:1" json:"visibility"` // 1:私有 2:公开
|
||||
DownloadCount int64 `gorm:"default:0" json:"download_count"`
|
||||
Status int8 `gorm:"default:1;index" json:"status"` // 1:正常 0:已删除(回收站)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `json:"deleted_at"`
|
||||
Project *Project `gorm:"foreignKey:ProjectID" json:"project,omitempty"`
|
||||
}
|
||||
|
||||
// TempLink 临时访问链接
|
||||
type TempLink struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
FileID uint `gorm:"index;not null" json:"file_id"`
|
||||
UserID uint `gorm:"not null" json:"user_id"`
|
||||
Token string `gorm:"size:64;uniqueIndex;not null" json:"token"`
|
||||
Password string `gorm:"size:50" json:"-"`
|
||||
HasPwd bool `gorm:"-" json:"has_password"`
|
||||
MaxCount int `gorm:"default:0" json:"max_count"` // 0为不限
|
||||
UsedCount int `gorm:"default:0" json:"used_count"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// TrafficLog 流量日志
|
||||
type TrafficLog struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
ProjectID uint `json:"project_id"`
|
||||
FileID uint `json:"file_id"`
|
||||
Type int8 `gorm:"not null" json:"type"` // 1:上传 2:下载
|
||||
Size int64 `gorm:"not null" json:"size"`
|
||||
IP string `gorm:"size:50" json:"ip"`
|
||||
CreatedAt time.Time `gorm:"index" json:"created_at"`
|
||||
}
|
||||
|
||||
// Webhook Webhook回调配置
|
||||
type Webhook struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index;not null" json:"user_id"`
|
||||
ProjectID *uint `json:"project_id"` // 为空则为用户级别
|
||||
URL string `gorm:"size:500;not null" json:"url"`
|
||||
Secret string `gorm:"size:64" json:"-"`
|
||||
Events string `gorm:"size:255;not null" json:"events"` // 逗号分隔: file.upload,file.delete
|
||||
Status int8 `gorm:"default:1" json:"status"`
|
||||
LastTriggeredAt *time.Time `json:"last_triggered_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// SystemSetting 系统设置
|
||||
type SystemSetting struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Key string `gorm:"column:key;size:100;uniqueIndex;not null" json:"key"`
|
||||
Value string `json:"value"`
|
||||
Description string `gorm:"size:255" json:"description"`
|
||||
GroupName string `gorm:"size:50;default:general" json:"group_name"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// OperationLog 操作日志
|
||||
type OperationLog struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID *uint `gorm:"index" json:"user_id"`
|
||||
Username string `gorm:"size:50" json:"username"`
|
||||
Action string `gorm:"size:50;index;not null" json:"action"` // login/logout/upload/download/delete/create/update
|
||||
ResourceType string `gorm:"size:50" json:"resource_type"`
|
||||
ResourceID uint `json:"resource_id"`
|
||||
ResourceName string `gorm:"size:255" json:"resource_name"`
|
||||
IP string `gorm:"size:50" json:"ip"`
|
||||
UserAgent string `gorm:"size:500" json:"user_agent"`
|
||||
RequestPath string `gorm:"size:500" json:"request_path"`
|
||||
RequestMethod string `gorm:"size:10" json:"request_method"`
|
||||
Status int8 `gorm:"default:1" json:"status"` // 1:成功 0:失败
|
||||
ErrorMessage string `json:"error_message"`
|
||||
ExtraData string `json:"extra_data"`
|
||||
CreatedAt time.Time `gorm:"index" json:"created_at"`
|
||||
}
|
||||
|
||||
// SystemLog 系统日志
|
||||
type SystemLog struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Level string `gorm:"size:10;index;not null" json:"level"` // debug/info/warn/error/fatal
|
||||
Module string `gorm:"size:50;index" json:"module"`
|
||||
Message string `gorm:"not null" json:"message"`
|
||||
StackTrace string `json:"stack_trace"`
|
||||
RequestID string `gorm:"size:50" json:"request_id"`
|
||||
IP string `gorm:"size:50" json:"ip"`
|
||||
ExtraData string `json:"extra_data"`
|
||||
CreatedAt time.Time `gorm:"index" json:"created_at"`
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
// AutoMigrate 自动迁移所有表
|
||||
func AutoMigrate(db *gorm.DB) error {
|
||||
return db.AutoMigrate(
|
||||
&Role{},
|
||||
&Permission{},
|
||||
&User{},
|
||||
&APIKey{},
|
||||
&Project{},
|
||||
&File{},
|
||||
&TempLink{},
|
||||
&TrafficLog{},
|
||||
&Webhook{},
|
||||
&SystemSetting{},
|
||||
&OperationLog{},
|
||||
&SystemLog{},
|
||||
)
|
||||
}
|
||||
|
||||
var defaultRoles = []Role{
|
||||
{Name: "超级管理员", Code: "super_admin", Description: "系统超级管理员,拥有所有权限", IsSystem: true},
|
||||
{Name: "管理员", Code: "admin", Description: "系统管理员,可管理用户和内容", IsSystem: true},
|
||||
{Name: "普通用户", Code: "user", Description: "普通用户,管理自己的项目和文件", IsSystem: true},
|
||||
}
|
||||
|
||||
var defaultPermissions = []Permission{
|
||||
// 用户管理
|
||||
{Name: "查看用户列表", Code: "user:list", Module: "user", Description: "查看所有用户列表"},
|
||||
{Name: "查看用户详情", Code: "user:detail", Module: "user", Description: "查看用户详细信息"},
|
||||
{Name: "创建用户", Code: "user:create", Module: "user", Description: "创建新用户"},
|
||||
{Name: "编辑用户", Code: "user:edit", Module: "user", Description: "编辑用户信息"},
|
||||
{Name: "删除用户", Code: "user:delete", Module: "user", Description: "删除用户"},
|
||||
{Name: "禁用用户", Code: "user:disable", Module: "user", Description: "禁用/启用用户"},
|
||||
{Name: "分配角色", Code: "user:assign_role", Module: "user", Description: "修改用户角色"},
|
||||
{Name: "重置密码", Code: "user:reset_password", Module: "user", Description: "重置用户密码"},
|
||||
// 项目管理
|
||||
{Name: "查看项目列表", Code: "project:list", Module: "project", Description: "查看项目列表"},
|
||||
{Name: "创建项目", Code: "project:create", Module: "project", Description: "创建新项目"},
|
||||
{Name: "编辑项目", Code: "project:edit", Module: "project", Description: "编辑项目信息"},
|
||||
{Name: "删除项目", Code: "project:delete", Module: "project", Description: "删除项目"},
|
||||
// 文件管理
|
||||
{Name: "上传文件", Code: "file:upload", Module: "file", Description: "上传文件"},
|
||||
{Name: "下载文件", Code: "file:download", Module: "file", Description: "下载文件"},
|
||||
{Name: "删除文件", Code: "file:delete", Module: "file", Description: "删除文件"},
|
||||
{Name: "查看文件列表", Code: "file:list", Module: "file", Description: "查看文件列表"},
|
||||
// 系统管理
|
||||
{Name: "查看系统设置", Code: "system:settings:view", Module: "system", Description: "查看系统设置"},
|
||||
{Name: "修改系统设置", Code: "system:settings:edit", Module: "system", Description: "修改系统设置"},
|
||||
{Name: "查看操作日志", Code: "system:logs:operation", Module: "system", Description: "查看操作日志"},
|
||||
{Name: "查看系统日志", Code: "system:logs:system", Module: "system", Description: "查看系统日志"},
|
||||
{Name: "清理日志", Code: "system:logs:cleanup", Module: "system", Description: "清理历史日志"},
|
||||
}
|
||||
|
||||
// admin角色不拥有的权限
|
||||
var adminExcluded = map[string]bool{
|
||||
"user:delete": true,
|
||||
"user:assign_role": true,
|
||||
"system:settings:edit": true,
|
||||
}
|
||||
|
||||
// 普通用户拥有的权限
|
||||
var userPerms = map[string]bool{
|
||||
"project:list": true, "project:create": true, "project:edit": true, "project:delete": true,
|
||||
"file:upload": true, "file:download": true, "file:delete": true, "file:list": true,
|
||||
}
|
||||
|
||||
var defaultSettings = []SystemSetting{
|
||||
{Key: "site_name", Value: "云泽文件存储云平台", Description: "站点名称", GroupName: "site"},
|
||||
{Key: "site_description", Value: "高效、安全的文件存储服务", Description: "站点描述", GroupName: "site"},
|
||||
{Key: "site_logo", Value: "/assets/logo.png", Description: "站点Logo路径", GroupName: "site"},
|
||||
{Key: "site_icp", Value: "", Description: "ICP备案号", GroupName: "site"},
|
||||
{Key: "site_copyright", Value: "© 2024 FileStorageSystem", Description: "版权信息", GroupName: "site"},
|
||||
{Key: "register_enabled", Value: "true", Description: "是否开放注册", GroupName: "feature"},
|
||||
{Key: "site_enabled", Value: "true", Description: "站点是否启用", GroupName: "feature"},
|
||||
{Key: "site_maintenance_msg", Value: "系统维护中,请稍后再访问", Description: "维护提示信息", GroupName: "feature"},
|
||||
{Key: "default_storage_limit", Value: "10737418240", Description: "默认用户存储配额(字节)", GroupName: "storage"},
|
||||
{Key: "default_project_limit", Value: "5368709120", Description: "默认项目存储配额(字节)", GroupName: "storage"},
|
||||
{Key: "max_file_size", Value: "104857600", Description: "单文件最大限制(字节)", GroupName: "storage"},
|
||||
{Key: "allowed_file_types", Value: "*", Description: "允许的文件类型(*表示所有)", GroupName: "storage"},
|
||||
{Key: "api_rate_limit", Value: "100", Description: "API请求频率限制(次/分钟)", GroupName: "api"},
|
||||
{Key: "temp_link_max_age", Value: "3600", Description: "临时链接默认有效期(秒)", GroupName: "api"},
|
||||
{Key: "webhook_enabled", Value: "true", Description: "是否启用Webhook回调", GroupName: "api"},
|
||||
}
|
||||
|
||||
// SeedData 初始化种子数据(幂等)
|
||||
func SeedData(db *gorm.DB) error {
|
||||
db.Logger = db.Logger.LogMode(logger.Warn)
|
||||
|
||||
// 1. 角色
|
||||
for i := range defaultRoles {
|
||||
var r Role
|
||||
if err := db.Where("code = ?", defaultRoles[i].Code).First(&r).Error; err != nil {
|
||||
if err := db.Create(&defaultRoles[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 权限
|
||||
for i := range defaultPermissions {
|
||||
var p Permission
|
||||
if err := db.Where("code = ?", defaultPermissions[i].Code).First(&p).Error; err != nil {
|
||||
if err := db.Create(&defaultPermissions[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 角色权限关联
|
||||
var perms []Permission
|
||||
if err := db.Find(&perms).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
rolePerms := map[string]func(code string) bool{
|
||||
"super_admin": func(string) bool { return true },
|
||||
"admin": func(code string) bool { return !adminExcluded[code] },
|
||||
"user": func(code string) bool { return userPerms[code] },
|
||||
}
|
||||
for roleCode, match := range rolePerms {
|
||||
var role Role
|
||||
if err := db.Where("code = ?", roleCode).First(&role).Error; err != nil {
|
||||
continue
|
||||
}
|
||||
for _, p := range perms {
|
||||
if !match(p.Code) {
|
||||
continue
|
||||
}
|
||||
var count int64
|
||||
db.Table("role_permissions").
|
||||
Where("role_id = ? AND permission_id = ?", role.ID, p.ID).
|
||||
Count(&count)
|
||||
if count == 0 {
|
||||
if err := db.Exec("INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)", role.ID, p.ID).Error; err != nil {
|
||||
log.Printf("插入角色权限失败: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 系统设置
|
||||
for i := range defaultSettings {
|
||||
var s SystemSetting
|
||||
if err := db.Where("`key` = ?", defaultSettings[i].Key).First(&s).Error; err != nil {
|
||||
if err := db.Create(&defaultSettings[i]).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user