Feat: model/policy

pull/247/head
HFO4 5 years ago
parent 41e0dec74c
commit 4309653160

@ -11,15 +11,13 @@ type Group struct {
Name string Name string
Policies string Policies string
MaxStorage uint64 MaxStorage uint64
SpeedLimit int
ShareEnabled bool ShareEnabled bool
RangeTransferEnabled bool
WebDAVEnabled bool WebDAVEnabled bool
Aria2Option string Aria2Option string
Color string Color string
// 数据库忽略字段 // 数据库忽略字段
PolicyList []int `gorm:"-"` PolicyList []uint `gorm:"-"`
} }
// GetGroupByID 用ID获取用户组 // GetGroupByID 用ID获取用户组
@ -35,3 +33,16 @@ func (group *Group) AfterFind() (err error) {
err = json.Unmarshal([]byte(group.Policies), &group.PolicyList) err = json.Unmarshal([]byte(group.Policies), &group.PolicyList)
return err return err
} }
// BeforeSave Save用户前的钩子
func (group *Group) BeforeSave() (err error) {
err = group.SerializePolicyList()
return err
}
//SerializePolicyList 将序列后的可选策略列表写入数据库字段
func (group *Group) SerializePolicyList() (err error) {
optionsValue, err := json.Marshal(&group.PolicyList)
group.Policies = string(optionsValue)
return err
}

@ -24,7 +24,7 @@ func TestGetGroupByID(t *testing.T) {
}, },
Name: "管理员", Name: "管理员",
Policies: "[1]", Policies: "[1]",
PolicyList: []int{1}, PolicyList: []uint{1},
}, group) }, group)
//未找到用户时 //未找到用户时

@ -25,7 +25,10 @@ func migration() {
util.Log().Info("开始进行数据库自动迁移...") util.Log().Info("开始进行数据库自动迁移...")
// 自动迁移模式 // 自动迁移模式
DB.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{}, &Setting{}, &Group{}) DB.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{}, &Setting{}, &Group{}, &Policy{})
// 创建初始存储策略
addDefaultPolicy()
// 创建初始用户组 // 创建初始用户组
addDefaultGroups() addDefaultGroups()
@ -44,6 +47,27 @@ func migration() {
} }
func addDefaultPolicy() {
_, err := GetPolicyByID(1)
// 未找到初始存储策略时,则创建
if gorm.IsRecordNotFoundError(err) {
defaultPolicy := Policy{
Name: "默认上传策略",
Type: "local",
Server: "/Api/V3/File/Upload",
BaseURL: "http://cloudreve.org/public/uploads/",
MaxSize: 10 * 1024 * 1024 * 1024,
AutoRename: true,
DirNameRule: "{date}/{uid}",
FileNameRule: "{uid}_{randomkey8}_{originname}",
IsOriginLinkEnable: false,
}
if err := DB.Create(&defaultPolicy).Error; err != nil {
util.Log().Panic("无法创建初始存储策略, ", err)
}
}
}
func addDefaultSettings() { func addDefaultSettings() {
defaultSettings := []Setting{ defaultSettings := []Setting{
{Name: "siteURL", Value: `http://lite.aoaoao.me/`, Type: "basic"}, {Name: "siteURL", Value: `http://lite.aoaoao.me/`, Type: "basic"},
@ -130,11 +154,10 @@ func addDefaultGroups() {
if gorm.IsRecordNotFoundError(err) { if gorm.IsRecordNotFoundError(err) {
defaultAdminGroup := Group{ defaultAdminGroup := Group{
Name: "管理员", Name: "管理员",
Policies: "[1]", PolicyList: []uint{1},
MaxStorage: 1 * 1024 * 1024 * 1024, MaxStorage: 1 * 1024 * 1024 * 1024,
ShareEnabled: true, ShareEnabled: true,
Color: "danger", Color: "danger",
RangeTransferEnabled: true,
WebDAVEnabled: true, WebDAVEnabled: true,
Aria2Option: "0,0,0", Aria2Option: "0,0,0",
} }
@ -149,11 +172,10 @@ func addDefaultGroups() {
if gorm.IsRecordNotFoundError(err) { if gorm.IsRecordNotFoundError(err) {
defaultAdminGroup := Group{ defaultAdminGroup := Group{
Name: "注册会员", Name: "注册会员",
Policies: "[1]", PolicyList: []uint{1},
MaxStorage: 1 * 1024 * 1024 * 1024, MaxStorage: 1 * 1024 * 1024 * 1024,
ShareEnabled: true, ShareEnabled: true,
Color: "danger", Color: "danger",
RangeTransferEnabled: true,
WebDAVEnabled: true, WebDAVEnabled: true,
Aria2Option: "0,0,0", Aria2Option: "0,0,0",
} }

@ -0,0 +1,66 @@
package model
import (
"encoding/json"
"github.com/jinzhu/gorm"
)
// Policy 存储策略
type Policy struct {
// 表字段
gorm.Model
Name string
Type string
Server string
BucketName string
IsPrivate bool
BaseURL string
AccessKey string `gorm:"size:512"`
SecretKey string `gorm:"size:512"`
MaxSize uint64
AutoRename bool
DirNameRule string
FileNameRule string
IsOriginLinkEnable bool
Options string `gorm:"size:4096"`
// 数据库忽略字段
OptionsSerialized PolicyOption `gorm:"-"`
}
// PolicyOption 非公有的存储策略属性
type PolicyOption struct {
OPName string `json:"op_name"`
OPPassword string `json:"op_pwd"`
FileType []string `json:"file_type"`
MimeType string `json:"mimetype"`
SpeedLimit int `json:"speed_limit"`
RangeTransferEnabled bool `json:"range_transfer_enabled"`
}
// GetPolicyByID 用ID获取存储策略
func GetPolicyByID(ID interface{}) (Policy, error) {
var policy Policy
result := DB.First(&policy, ID)
return policy, result.Error
}
// AfterFind 找到上传策略后的钩子
func (policy *Policy) AfterFind() (err error) {
// 解析上传策略设置到OptionsSerialized
err = json.Unmarshal([]byte(policy.Options), &policy.OptionsSerialized)
return err
}
// BeforeSave Save策略前的钩子
func (policy *Policy) BeforeSave() (err error) {
err = policy.SerializeOptions()
return err
}
//SerializeOptions 将序列后的Option写入到数据库字段
func (policy *Policy) SerializeOptions() (err error) {
optionsValue, err := json.Marshal(&policy.OptionsSerialized)
policy.Options = string(optionsValue)
return err
}

@ -41,6 +41,7 @@ type User struct {
// 关联模型 // 关联模型
Group Group Group Group
Policy Policy `gorm:"PRELOAD:false,association_autoupdate:false"`
// 数据库忽略字段 // 数据库忽略字段
OptionsSerialized UserOption `gorm:"-"` OptionsSerialized UserOption `gorm:"-"`
@ -49,9 +50,32 @@ type User struct {
// UserOption 用户个性化配置字段 // UserOption 用户个性化配置字段
type UserOption struct { type UserOption struct {
ProfileOn int `json:"profile_on"` ProfileOn int `json:"profile_on"`
PreferredPolicy uint `json:"preferred_policy"`
WebDAVKey string `json:"webdav_key"` WebDAVKey string `json:"webdav_key"`
} }
// GetPolicyID 获取用户当前的上传策略ID
func (user *User) GetPolicyID() uint {
// 用户未指定时,返回可用的第一个
if user.OptionsSerialized.PreferredPolicy == 0 {
if len(user.Group.PolicyList) != 0 {
return user.Group.PolicyList[0]
}
return 1
} else {
// 用户指定时,先检查是否为可用策略列表中的值
if util.ContainsUint(user.Group.PolicyList, user.OptionsSerialized.PreferredPolicy) {
return user.OptionsSerialized.PreferredPolicy
}
// 不可用时,返回第一个
if len(user.Group.PolicyList) != 0 {
return user.Group.PolicyList[0]
}
return 1
}
}
// GetUserByID 用ID获取用户 // GetUserByID 用ID获取用户
func GetUserByID(ID interface{}) (User, error) { func GetUserByID(ID interface{}) (User, error) {
var user User var user User
@ -71,17 +95,32 @@ func NewUser() User {
options := UserOption{ options := UserOption{
ProfileOn: 1, ProfileOn: 1,
} }
optionsValue, _ := json.Marshal(&options)
return User{ return User{
Avatar: "default", Avatar: "default",
Options: string(optionsValue), OptionsSerialized: options,
} }
} }
// BeforeSave Save用户前的钩子
func (user *User) BeforeSave() (err error) {
err = user.SerializeOptions()
return err
}
//SerializeOptions 将序列后的Option写入到数据库字段
func (user *User) SerializeOptions() (err error) {
optionsValue, err := json.Marshal(&user.OptionsSerialized)
user.Options = string(optionsValue)
return err
}
// AfterFind 找到用户后的钩子 // AfterFind 找到用户后的钩子
func (user *User) AfterFind() (err error) { func (user *User) AfterFind() (err error) {
// 解析用户设置到OptionsSerialized // 解析用户设置到OptionsSerialized
err = json.Unmarshal([]byte(user.Options), &user.OptionsSerialized) err = json.Unmarshal([]byte(user.Options), &user.OptionsSerialized)
// 预加载存储策略
user.Policy, _ = GetPolicyByID(user.GetPolicyID())
return err return err
} }

@ -37,7 +37,7 @@ func TestGetUserByID(t *testing.T) {
}, },
Name: "管理员", Name: "管理员",
Policies: "[1]", Policies: "[1]",
PolicyList: []int{1}, PolicyList: []uint{1},
}, },
}, user) }, user)
@ -85,17 +85,72 @@ func TestNewUser(t *testing.T) {
newUser := NewUser() newUser := NewUser()
asserts.IsType(User{}, newUser) asserts.IsType(User{}, newUser)
asserts.NotEmpty(newUser.Avatar) asserts.NotEmpty(newUser.Avatar)
asserts.NotEmpty(newUser.Options) asserts.NotEmpty(newUser.OptionsSerialized)
} }
func TestUser_AfterFind(t *testing.T) { func TestUser_AfterFind(t *testing.T) {
asserts := assert.New(t) asserts := assert.New(t)
policyRows := sqlmock.NewRows([]string{"id", "name"}).
AddRow(1, "默认上传策略")
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(policyRows)
newUser := NewUser() newUser := NewUser()
err := newUser.AfterFind() err := newUser.AfterFind()
err = newUser.BeforeSave()
expected := UserOption{} expected := UserOption{}
err = json.Unmarshal([]byte(newUser.Options), &expected) err = json.Unmarshal([]byte(newUser.Options), &expected)
asserts.NoError(err) asserts.NoError(err)
asserts.NoError(mock.ExpectationsWereMet())
asserts.Equal(expected, newUser.OptionsSerialized) asserts.Equal(expected, newUser.OptionsSerialized)
asserts.Equal("默认上传策略", newUser.Policy.Name)
}
func TestUser_BeforeSave(t *testing.T) {
asserts := assert.New(t)
newUser := NewUser()
err := newUser.BeforeSave()
expected, err := json.Marshal(newUser.OptionsSerialized)
asserts.NoError(err)
asserts.Equal(string(expected), newUser.Options)
}
func TestUser_GetPolicyID(t *testing.T) {
asserts := assert.New(t)
newUser := NewUser()
testCases := []struct {
preferred uint
available []uint
expected uint
}{
{
available: []uint{1},
expected: 1,
},
{
available: []uint{5, 2, 3},
expected: 5,
},
{
preferred: 1,
available: []uint{5, 1, 3},
expected: 1,
},
{
preferred: 9,
available: []uint{5, 1, 3},
expected: 5,
},
}
for key, testCase := range testCases {
newUser.OptionsSerialized.PreferredPolicy = testCase.preferred
newUser.Group.PolicyList = testCase.available
asserts.Equal(testCase.expected, newUser.GetPolicyID(), "测试用例 #%d 未通过", key)
}
} }

@ -14,3 +14,13 @@ func RandStringRunes(n int) string {
} }
return string(b) return string(b)
} }
// ContainsUint 返回list中是否包含
func ContainsUint(s []uint, e uint) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}

Loading…
Cancel
Save