Modify: clean modals
This commit is contained in:
parent
4d70f9fa3e
commit
4ba24e0cf1
30 changed files with 22 additions and 598 deletions
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit d46074216363ac62a66a02284f2a791b79a392cd
|
||||
Subproject commit 186f0aac0964c95ed4826894ddf888e32e00d46b
|
|
@ -1,23 +1,10 @@
|
|||
package bootstrap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"github.com/HFO4/cloudreve/bootstrap/constant"
|
||||
"github.com/HFO4/cloudreve/pkg/conf"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var matrix []byte
|
||||
var APPID string
|
||||
|
||||
// InitApplication 初始化应用常量
|
||||
func InitApplication() {
|
||||
fmt.Print(`
|
||||
|
@ -31,65 +18,4 @@ V` + conf.BackendVersion + ` Commit #` + conf.LastCommit + ` Pro=` + conf.IsPr
|
|||
================================================
|
||||
|
||||
`)
|
||||
data, err := ioutil.ReadFile(util.RelativePath(string([]byte{107, 101, 121, 46, 98, 105, 110})))
|
||||
if err != nil {
|
||||
util.Log().Panic("%s", err)
|
||||
}
|
||||
|
||||
table := deSign(data)
|
||||
constant.HashIDTable = table["table"].([]int)
|
||||
APPID = table["id"].(string)
|
||||
matrix = table["pic"].([]byte)
|
||||
}
|
||||
|
||||
// InitCustomRoute 初始化自定义路由
|
||||
func InitCustomRoute(group *gin.RouterGroup) {
|
||||
group.GET(string([]byte{98, 103}), func(c *gin.Context) {
|
||||
c.Header("content-type", "image/png")
|
||||
c.Writer.Write(matrix)
|
||||
})
|
||||
group.GET("id", func(c *gin.Context) {
|
||||
c.String(200, APPID)
|
||||
})
|
||||
}
|
||||
|
||||
func deSign(data []byte) map[string]interface{} {
|
||||
res := decode(data, seed())
|
||||
dec := gob.NewDecoder(bytes.NewReader(res))
|
||||
obj := map[string]interface{}{}
|
||||
err := dec.Decode(&obj)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func seed() []byte {
|
||||
res := []int{10}
|
||||
s := "2020"
|
||||
m := 1 << 20
|
||||
a := 9
|
||||
b := 7
|
||||
for i := 1; i < 23; i++ {
|
||||
res = append(res, (a*res[i-1]+b)%m)
|
||||
s += strconv.Itoa(res[i])
|
||||
}
|
||||
return []byte(s)
|
||||
}
|
||||
|
||||
func decode(cryted []byte, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key[:32])
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
orig := make([]byte, len(cryted))
|
||||
blockMode.CryptBlocks(orig, cryted)
|
||||
orig = pKCS7UnPadding(orig)
|
||||
return orig
|
||||
}
|
||||
|
||||
func pKCS7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
package constant
|
||||
|
||||
var HashIDTable = []int{}
|
|
@ -1,7 +1,6 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/HFO4/cloudreve/bootstrap/constant"
|
||||
"github.com/HFO4/cloudreve/pkg/cache"
|
||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -15,7 +14,6 @@ func TestHashID(t *testing.T) {
|
|||
asserts := assert.New(t)
|
||||
rec := httptest.NewRecorder()
|
||||
TestFunc := HashID(hashid.FolderID)
|
||||
constant.HashIDTable = []int{0, 1, 2, 3, 4, 5, 6}
|
||||
|
||||
// 未给定ID对象,跳过
|
||||
{
|
||||
|
|
|
@ -15,7 +15,6 @@ type Folder struct {
|
|||
Name string `gorm:"unique_index:idx_only_one_name"`
|
||||
ParentID *uint `gorm:"index:parent_id;unique_index:idx_only_one_name"`
|
||||
OwnerID uint `gorm:"index:owner_id"`
|
||||
PolicyID uint // Webdav下挂载的存储策略ID
|
||||
|
||||
// 数据库忽略字段
|
||||
Position string `gorm:"-"`
|
||||
|
@ -30,13 +29,6 @@ func (folder *Folder) Create() (uint, error) {
|
|||
return folder.ID, nil
|
||||
}
|
||||
|
||||
// GetMountedFolders 列出已挂载存储策略的目录
|
||||
func GetMountedFolders(uid uint) []Folder {
|
||||
var folders []Folder
|
||||
DB.Where("owner_id = ? and policy_id <> ?", uid, 0).Find(&folders)
|
||||
return folders
|
||||
}
|
||||
|
||||
// GetChild 返回folder下名为name的子目录,不存在则返回错误
|
||||
func (folder *Folder) GetChild(name string) (*Folder, error) {
|
||||
var resFolder Folder
|
||||
|
@ -272,11 +264,6 @@ func (folder *Folder) Rename(new string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Mount 目录挂载
|
||||
func (folder *Folder) Mount(new uint) error {
|
||||
return DB.Model(&folder).Update("policy_id", new).Error
|
||||
}
|
||||
|
||||
/*
|
||||
实现 FileInfo.FileInfo 接口
|
||||
TODO 测试
|
||||
|
|
|
@ -29,7 +29,6 @@ type GroupOption struct {
|
|||
DecompressSize uint64 `json:"decompress_size,omitempty"`
|
||||
OneTimeDownload bool `json:"one_time_download,omitempty"`
|
||||
ShareDownload bool `json:"share_download,omitempty"`
|
||||
ShareFree bool `json:"share_free,omitempty"`
|
||||
Aria2 bool `json:"aria2,omitempty"` // 离线下载
|
||||
Aria2Options map[string]interface{} `json:"aria2_options,omitempty"` // 离线下载用户组配置
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestGetGroupByID(t *testing.T) {
|
|||
ID: 1,
|
||||
},
|
||||
Name: "管理员",
|
||||
Policies: "[1]",
|
||||
PolicyID: 1,
|
||||
PolicyList: []uint{1},
|
||||
}, group)
|
||||
|
||||
|
@ -42,7 +42,7 @@ func TestGroup_AfterFind(t *testing.T) {
|
|||
ID: 1,
|
||||
},
|
||||
Name: "管理员",
|
||||
Policies: "[1]",
|
||||
PolicyID: 1,
|
||||
}
|
||||
err := testCase.AfterFind()
|
||||
asserts.NoError(err)
|
||||
|
|
|
@ -35,8 +35,8 @@ func migration() {
|
|||
if conf.DatabaseConfig.Type == "mysql" {
|
||||
DB = DB.Set("gorm:table_options", "ENGINE=InnoDB")
|
||||
}
|
||||
DB.AutoMigrate(&User{}, &Setting{}, &Group{}, &Policy{}, &Folder{}, &File{}, &StoragePack{}, &Share{},
|
||||
&Task{}, &Download{}, &Tag{}, &Webdav{}, &Order{}, &Redeem{})
|
||||
DB.AutoMigrate(&User{}, &Setting{}, &Group{}, &Policy{}, &Folder{}, &File{}, &Share{},
|
||||
&Task{}, &Download{}, &Tag{}, &Webdav{})
|
||||
|
||||
// 创建初始存储策略
|
||||
addDefaultPolicy()
|
||||
|
@ -90,9 +90,6 @@ func addDefaultSettings() {
|
|||
{Name: "replyTo", Value: `abslant@126.com`, Type: "mail"},
|
||||
{Name: "smtpUser", Value: `no-reply@acg.blue`, Type: "mail"},
|
||||
{Name: "smtpPass", Value: ``, Type: "mail"},
|
||||
{Name: "over_used_template", Value: `<meta name="viewport"content="width=device-width"><meta http-equiv="Content-Type"content="text/html; charset=UTF-8"><title>容量超额提醒</title><style type="text/css">img{max-width:100%}body{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:none;width:100%!important;height:100%;line-height:1.6em}body{background-color:#f6f6f6}@media only screen and(max-width:640px){body{padding:0!important}h1{font-weight:800!important;margin:20px 0 5px!important}h2{font-weight:800!important;margin:20px 0 5px!important}h3{font-weight:800!important;margin:20px 0 5px!important}h4{font-weight:800!important;margin:20px 0 5px!important}h1{font-size:22px!important}h2{font-size:18px!important}h3{font-size:16px!important}.container{padding:0!important;width:100%!important}.content{padding:0!important}.content-wrap{padding:10px!important}.invoice{width:100%!important}}</style><table class="body-wrap"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;"bgcolor="#f6f6f6"><tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;"valign="top"></td><td class="container"width="600"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; margin: 0 auto;"valign="top"><div class="content"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 20px;"><table class="main"width="100%"cellpadding="0"cellspacing="0"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px
|
||||
solid #e9e9e9;"bgcolor="#fff"><tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="alert alert-warning"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #FF9F00; margin: 0; padding: 20px;"align="center"bgcolor="#FF9F00"valign="top">容量超额警告</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-wrap"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;"valign="top"><table width="100%"cellpadding="0"cellspacing="0"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">亲爱的<strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{userName}</strong>:</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">由于{notifyReason},您在{siteTitle}的账户的容量使用超出配额,您将无法继续上传新文件,请尽快清理文件,否则我们将会禁用您的账户。</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top"><a href="{siteUrl}Login"class="btn-primary"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">登录{siteTitle}</a></td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">感谢您选择{siteTitle}。</td></tr></tbody></table></td></tr></tbody></table><div class="footer"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"><table width="100%"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="aligncenter content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;"align="center"valign="top">此邮件由系统自动发送,请不要直接回复。</td></tr></tbody></table></div></div></td><td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;"valign="top"></td></tr></tbody></table>`, Type: "mail_template"},
|
||||
{Name: "ban_time", Value: `604800`, Type: "storage_policy"},
|
||||
{Name: "maxEditSize", Value: `4194304`, Type: "file_edit"},
|
||||
{Name: "archive_timeout", Value: `60`, Type: "timeout"},
|
||||
{Name: "download_timeout", Value: `60`, Type: "timeout"},
|
||||
|
@ -108,10 +105,6 @@ solid #e9e9e9;"bgcolor="#fff"><tbody><tr style="font-family: 'Helvetica Neue',He
|
|||
{Name: "onedrive_chunk_retries", Value: `1`, Type: "retry"},
|
||||
{Name: "reset_after_upload_failed", Value: `0`, Type: "upload"},
|
||||
{Name: "login_captcha", Value: `0`, Type: "login"},
|
||||
{Name: "qq_login", Value: `0`, Type: "login"},
|
||||
{Name: "qq_direct_login", Value: `0`, Type: "login"},
|
||||
{Name: "qq_login_id", Value: ``, Type: "login"},
|
||||
{Name: "qq_login_key", Value: ``, Type: "login"},
|
||||
{Name: "reg_captcha", Value: `0`, Type: "login"},
|
||||
{Name: "email_active", Value: `0`, Type: "register"},
|
||||
{Name: "mail_activation_template", Value: `<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box;
|
||||
|
@ -129,17 +122,8 @@ box-sizing: border-box; font-size: 14px; margin: 0;"><td style="font-family: 'He
|
|||
solid #e9e9e9;"bgcolor="#fff"><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size:
|
||||
14px; margin: 0;"><td class="alert alert-warning"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #2196F3; margin: 0; padding: 20px;"align="center"bgcolor="#FF9F00"valign="top">重设{siteTitle}密码</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-wrap"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;"valign="top"><table width="100%"cellpadding="0"cellspacing="0"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica
|
||||
Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">亲爱的<strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{userName}</strong>:</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">请点击下方按钮完成密码重设。如果非你本人操作,请忽略此邮件。</td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top"><a href="{resetUrl}"class="btn-primary"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #2196F3; margin: 0; border-color: #2196F3; border-style: solid; border-width: 10px 20px;">重设密码</a></td></tr><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;"valign="top">感谢您选择{siteTitle}。</td></tr></table></td></tr></table><div class="footer"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;"><table width="100%"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"><td class="aligncenter content-block"style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;"align="center"valign="top">此邮件由系统自动发送,请不要直接回复。</td></tr></table></div></div></td><td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;"valign="top"></td></tr></table></body></html>`, Type: "mail_template"},
|
||||
{Name: "pack_data", Value: `[]`, Type: "pack"},
|
||||
{Name: "database_version", Value: `3.0.0-alpha1`, Type: "version"},
|
||||
{Name: "alipay_enabled", Value: `0`, Type: "payment"},
|
||||
{Name: "payjs_enabled", Value: `0`, Type: "payment"},
|
||||
{Name: "payjs_id", Value: ``, Type: "payment"},
|
||||
{Name: "payjs_secret", Value: ``, Type: "payment"},
|
||||
{Name: "appid", Value: ``, Type: "payment"},
|
||||
{Name: "appkey", Value: ``, Type: "payment"},
|
||||
{Name: "shopid", Value: ``, Type: "payment"},
|
||||
{Name: "hot_share_num", Value: `10`, Type: "share"},
|
||||
{Name: "group_sell_data", Value: `[]`, Type: "group_sell"},
|
||||
{Name: "gravatar_server", Value: `https://www.gravatar.com/`, Type: "avatar"},
|
||||
{Name: "defaultTheme", Value: `#3f51b5`, Type: "basic"},
|
||||
{Name: "themes", Value: `{"#3f51b5":{"palette":{"primary":{"main":"#3f51b5"},"secondary":{"main":"#f50057"}}},"#2196f3":{"palette":{"primary":{"main":"#2196f3"},"secondary":{"main":"#FFC107"}}},"#673AB7":{"palette":{"primary":{"main":"#673AB7"},"secondary":{"main":"#2196F3"}}},"#E91E63":{"palette":{"primary":{"main":"#E91E63"},"secondary":{"main":"#42A5F5","contrastText":"#fff"}}},"#FF5722":{"palette":{"primary":{"main":"#FF5722"},"secondary":{"main":"#3F51B5"}}},"#FFC107":{"palette":{"primary":{"main":"#FFC107"},"secondary":{"main":"#26C6DA"}}},"#8BC34A":{"palette":{"primary":{"main":"#8BC34A","contrastText":"#fff"},"secondary":{"main":"#FF8A65","contrastText":"#fff"}}},"#009688":{"palette":{"primary":{"main":"#009688"},"secondary":{"main":"#4DD0E1","contrastText":"#fff"}}},"#607D8B":{"palette":{"primary":{"main":"#607D8B"},"secondary":{"main":"#F06292"}}},"#795548":{"palette":{"primary":{"main":"#795548"},"secondary":{"main":"#4CAF50","contrastText":"#fff"}}}}`, Type: "basic"},
|
||||
|
@ -157,9 +141,6 @@ Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; verti
|
|||
{Name: "avatar_size_l", Value: "200", Type: "avatar"},
|
||||
{Name: "avatar_size_m", Value: "130", Type: "avatar"},
|
||||
{Name: "avatar_size_s", Value: "50", Type: "avatar"},
|
||||
{Name: "score_enabled", Value: "1", Type: "score"},
|
||||
{Name: "share_score_rate", Value: "80", Type: "score"},
|
||||
{Name: "score_price", Value: "1", Type: "score"},
|
||||
{Name: "home_view_method", Value: "icon", Type: "view"},
|
||||
{Name: "share_view_method", Value: "list", Type: "view"},
|
||||
{Name: "cron_garbage_collect", Value: "@hourly", Type: "cron"},
|
||||
|
@ -206,7 +187,6 @@ func addDefaultGroups() {
|
|||
ArchiveDownload: true,
|
||||
ArchiveTask: true,
|
||||
ShareDownload: true,
|
||||
ShareFree: true,
|
||||
Aria2: true,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
// PackOrderType 容量包订单
|
||||
PackOrderType = iota
|
||||
// GroupOrderType 用户组订单
|
||||
GroupOrderType
|
||||
// ScoreOrderType 积分充值订单
|
||||
ScoreOrderType
|
||||
)
|
||||
|
||||
const (
|
||||
// OrderUnpaid 未支付
|
||||
OrderUnpaid = iota
|
||||
// OrderPaid 已支付
|
||||
OrderPaid
|
||||
// OrderCanceled 已取消
|
||||
OrderCanceled
|
||||
)
|
||||
|
||||
// Order 交易订单
|
||||
type Order struct {
|
||||
gorm.Model
|
||||
UserID uint // 创建者ID
|
||||
OrderNo string `gorm:"index:order_number"` // 商户自定义订单编号
|
||||
Type int // 订单类型
|
||||
Method string // 支付类型
|
||||
ProductID int64 // 商品ID
|
||||
Num int // 商品数量
|
||||
Name string // 订单标题
|
||||
Price int // 商品单价
|
||||
Status int // 订单状态
|
||||
}
|
||||
|
||||
// Create 创建订单记录
|
||||
func (order *Order) Create() (uint, error) {
|
||||
if err := DB.Create(order).Error; err != nil {
|
||||
util.Log().Warning("无法插入离线下载记录, %s", err)
|
||||
return 0, err
|
||||
}
|
||||
return order.ID, nil
|
||||
}
|
||||
|
||||
// UpdateStatus 更新订单状态
|
||||
func (order *Order) UpdateStatus(status int) {
|
||||
DB.Model(order).Update("status", status)
|
||||
}
|
||||
|
||||
// GetOrderByNo 根据商户订单号查询订单
|
||||
func GetOrderByNo(id string) (*Order, error) {
|
||||
var order Order
|
||||
err := DB.Where("order_no = ?", id).First(&order).Error
|
||||
return &order, err
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package model
|
||||
|
||||
import "github.com/jinzhu/gorm"
|
||||
|
||||
// Redeem 兑换码
|
||||
type Redeem struct {
|
||||
gorm.Model
|
||||
Type int // 订单类型
|
||||
ProductID int64 // 商品ID
|
||||
Num int // 商品数量
|
||||
Code string `gorm:"size:64,index:redeem_code"` // 兑换码
|
||||
Used bool // 是否已被使用
|
||||
}
|
||||
|
||||
// GetAvailableRedeem 根据code查找可用兑换码
|
||||
func GetAvailableRedeem(code string) (*Redeem, error) {
|
||||
redeem := &Redeem{}
|
||||
result := DB.Where("code = ? and used = ?", code, false).First(redeem)
|
||||
return redeem, result.Error
|
||||
}
|
||||
|
||||
// Use 设定为已使用状态
|
||||
func (redeem *Redeem) Use() {
|
||||
DB.Model(redeem).Updates(map[string]interface{}{
|
||||
"used": true,
|
||||
})
|
||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/gorm"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -24,7 +23,6 @@ type Share struct {
|
|||
Downloads int // 下载数
|
||||
RemainDownloads int // 剩余下载配额,负值标识无限制
|
||||
Expires *time.Time // 过期时间,空值表示无过期时间
|
||||
Score int // 每人次下载扣除积分
|
||||
PreviewEnabled bool // 是否允许直接预览
|
||||
SourceName string `gorm:"index:source"` // 用于搜索的字段
|
||||
|
||||
|
@ -136,12 +134,6 @@ func (share *Share) CanBeDownloadBy(user *User) error {
|
|||
}
|
||||
return errors.New("您当前的用户组无权下载")
|
||||
}
|
||||
|
||||
// 需要积分但未登录
|
||||
if share.Score > 0 && user.IsAnonymous() {
|
||||
return errors.New("未登录用户无法下载")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -156,12 +148,9 @@ func (share *Share) WasDownloadedBy(user *User, c *gin.Context) (exist bool) {
|
|||
return exist
|
||||
}
|
||||
|
||||
// DownloadBy 增加下载次数、检查积分等,匿名用户不会缓存
|
||||
// DownloadBy 增加下载次数,匿名用户不会缓存
|
||||
func (share *Share) DownloadBy(user *User, c *gin.Context) error {
|
||||
if !share.WasDownloadedBy(user, c) {
|
||||
if err := share.Purchase(user); err != nil {
|
||||
return err
|
||||
}
|
||||
share.Downloaded()
|
||||
if !user.IsAnonymous() {
|
||||
cache.Set(fmt.Sprintf("share_%d_%d", share.ID, user.ID), true,
|
||||
|
@ -173,25 +162,6 @@ func (share *Share) DownloadBy(user *User, c *gin.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Purchase 使用积分购买分享
|
||||
func (share *Share) Purchase(user *User) error {
|
||||
// 不需要付积分
|
||||
if share.Score == 0 || user.Group.OptionsSerialized.ShareFree || user.ID == share.UserID {
|
||||
return nil
|
||||
}
|
||||
|
||||
ok := user.PayScore(share.Score)
|
||||
if !ok {
|
||||
return errors.New("积分不足")
|
||||
}
|
||||
|
||||
scoreRate := GetIntSetting("share_score_rate", 100)
|
||||
gainedScore := int(math.Ceil(float64(share.Score*scoreRate) / 100))
|
||||
share.Creator().AddScore(gainedScore)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Viewed 增加访问次数
|
||||
func (share *Share) Viewed() {
|
||||
share.Views++
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/HFO4/cloudreve/pkg/cache"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/jinzhu/gorm"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// StoragePack 容量包模型
|
||||
type StoragePack struct {
|
||||
// 表字段
|
||||
gorm.Model
|
||||
Name string
|
||||
UserID uint
|
||||
ActiveTime *time.Time
|
||||
ExpiredTime *time.Time `gorm:"index:expired"`
|
||||
Size uint64
|
||||
}
|
||||
|
||||
// Create 创建容量包
|
||||
func (pack *StoragePack) Create() (uint, error) {
|
||||
if err := DB.Create(pack).Error; err != nil {
|
||||
util.Log().Warning("无法插入离线下载记录, %s", err)
|
||||
return 0, err
|
||||
}
|
||||
return pack.ID, nil
|
||||
}
|
||||
|
||||
// GetAvailablePackSize 返回给定用户当前可用的容量包总容量
|
||||
func (user *User) GetAvailablePackSize() uint64 {
|
||||
var (
|
||||
total uint64
|
||||
firstExpire *time.Time
|
||||
timeNow = time.Now()
|
||||
ttl int64
|
||||
)
|
||||
|
||||
// 尝试从缓存中读取
|
||||
cacheKey := "pack_size_" + strconv.FormatUint(uint64(user.ID), 10)
|
||||
if total, ok := cache.Get(cacheKey); ok {
|
||||
return total.(uint64)
|
||||
}
|
||||
|
||||
// 查找所有有效容量包
|
||||
packs := user.GetAvailableStoragePacks()
|
||||
|
||||
// 计算总容量, 并找到其中最早的过期时间
|
||||
for _, v := range packs {
|
||||
total += v.Size
|
||||
if firstExpire == nil {
|
||||
firstExpire = v.ExpiredTime
|
||||
continue
|
||||
}
|
||||
if v.ExpiredTime != nil && firstExpire.After(*v.ExpiredTime) {
|
||||
firstExpire = v.ExpiredTime
|
||||
}
|
||||
}
|
||||
|
||||
// 用最早的过期时间计算缓存TTL,并写入缓存
|
||||
if firstExpire != nil {
|
||||
ttl = firstExpire.Unix() - timeNow.Unix()
|
||||
if ttl > 0 {
|
||||
_ = cache.Set(cacheKey, total, int(ttl))
|
||||
}
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// GetAvailableStoragePacks 返回用户可用的容量包
|
||||
func (user *User) GetAvailableStoragePacks() []StoragePack {
|
||||
var packs []StoragePack
|
||||
timeNow := time.Now()
|
||||
// 查找所有有效容量包
|
||||
DB.Where("expired_time > ? AND user_id = ?", timeNow, user.ID).Find(&packs)
|
||||
return packs
|
||||
}
|
||||
|
||||
// GetExpiredStoragePack 获取已过期的容量包
|
||||
func GetExpiredStoragePack() []StoragePack {
|
||||
var packs []StoragePack
|
||||
DB.Where("expired_time < ?", time.Now()).Find(&packs)
|
||||
return packs
|
||||
}
|
||||
|
||||
// Delete 删除容量包
|
||||
func (pack *StoragePack) Delete() error {
|
||||
return DB.Delete(&pack).Error
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUser_GetAvailablePackSize(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
user := User{
|
||||
Model: gorm.Model{ID: 1},
|
||||
}
|
||||
|
||||
// 未命中缓存
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WithArgs(sqlmock.AnyArg(), 1).
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"id", "size", "expired_time"}).
|
||||
AddRow(1, 10, time.Now().Add(time.Second*time.Duration(20))).
|
||||
AddRow(3, 0, nil).
|
||||
AddRow(2, 20, time.Now().Add(time.Second*time.Duration(10))),
|
||||
)
|
||||
total := user.GetAvailablePackSize()
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.EqualValues(30, total)
|
||||
}
|
||||
|
||||
// 命中缓存
|
||||
{
|
||||
total := user.GetAvailablePackSize()
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.EqualValues(30, total)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStoragePack_Create(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
pack := &StoragePack{}
|
||||
|
||||
// 成功
|
||||
{
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("INSERT(.+)").WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
id, err := pack.Create()
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Equal(uint(1), id)
|
||||
asserts.NoError(err)
|
||||
}
|
||||
|
||||
// 失败
|
||||
{
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("INSERT(.+)").WillReturnError(errors.New("error"))
|
||||
mock.ExpectRollback()
|
||||
id, err := pack.Create()
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Equal(uint(0), id)
|
||||
asserts.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExpiredStoragePack(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id"}))
|
||||
res := GetExpiredStoragePack()
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Len(res, 0)
|
||||
}
|
||||
|
||||
func TestStoragePack_Delete(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
pack := &StoragePack{}
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)").WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
asserts.NoError(pack.Delete())
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
|
||||
}
|
125
models/user.go
125
models/user.go
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -26,21 +25,16 @@ const (
|
|||
type User struct {
|
||||
// 表字段
|
||||
gorm.Model
|
||||
Email string `gorm:"type:varchar(100);unique_index"`
|
||||
Nick string `gorm:"size:50"`
|
||||
Password string `json:"-"`
|
||||
Status int
|
||||
GroupID uint
|
||||
Storage uint64
|
||||
OpenID string
|
||||
TwoFactor string
|
||||
Avatar string
|
||||
Options string `json:"-",gorm:"type:text"`
|
||||
Authn string `gorm:"type:text"`
|
||||
Score int
|
||||
PreviousGroupID uint // 初始用户组
|
||||
GroupExpires *time.Time // 用户组过期日期
|
||||
NotifyDate *time.Time // 通知超出配额时的日期
|
||||
Email string `gorm:"type:varchar(100);unique_index"`
|
||||
Nick string `gorm:"size:50"`
|
||||
Password string `json:"-"`
|
||||
Status int
|
||||
GroupID uint
|
||||
Storage uint64
|
||||
TwoFactor string
|
||||
Avatar string
|
||||
Options string `json:"-",gorm:"type:text"`
|
||||
Authn string `gorm:"type:text"`
|
||||
|
||||
// 关联模型
|
||||
Group Group `gorm:"save_associations:false:false"`
|
||||
|
@ -52,9 +46,8 @@ type User struct {
|
|||
|
||||
// UserOption 用户个性化配置字段
|
||||
type UserOption struct {
|
||||
ProfileOff bool `json:"profile_off,omitempty"`
|
||||
PreferredPolicy uint `json:"preferred_policy,omitempty"`
|
||||
PreferredTheme string `json:"preferred_theme,omitempty"`
|
||||
ProfileOff bool `json:"profile_off,omitempty"`
|
||||
PreferredTheme string `json:"preferred_theme,omitempty"`
|
||||
}
|
||||
|
||||
// Root 获取用户的根目录
|
||||
|
@ -94,25 +87,6 @@ func (user *User) IncreaseStorage(size uint64) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// PayScore 扣除积分,返回是否成功
|
||||
func (user *User) PayScore(score int) bool {
|
||||
if score == 0 {
|
||||
return true
|
||||
}
|
||||
if score <= user.Score {
|
||||
user.Score -= score
|
||||
DB.Model(user).Update("score", gorm.Expr("score - ?", score))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddScore 增加积分
|
||||
func (user *User) AddScore(score int) {
|
||||
user.Score += score
|
||||
DB.Model(user).Update("score", gorm.Expr("score + ?", score))
|
||||
}
|
||||
|
||||
// IncreaseStorageWithoutCheck 忽略可用容量,增加用户已用容量
|
||||
func (user *User) IncreaseStorageWithoutCheck(size uint64) {
|
||||
if size == 0 {
|
||||
|
@ -125,7 +99,7 @@ func (user *User) IncreaseStorageWithoutCheck(size uint64) {
|
|||
|
||||
// GetRemainingCapacity 获取剩余配额
|
||||
func (user *User) GetRemainingCapacity() uint64 {
|
||||
total := user.Group.MaxStorage + user.GetAvailablePackSize()
|
||||
total := user.Group.MaxStorage
|
||||
if total <= user.Storage {
|
||||
return 0
|
||||
}
|
||||
|
@ -134,26 +108,7 @@ func (user *User) GetRemainingCapacity() uint64 {
|
|||
|
||||
// GetPolicyID 获取用户当前的存储策略ID
|
||||
func (user *User) GetPolicyID(prefer uint) uint {
|
||||
if prefer == 0 {
|
||||
prefer = user.OptionsSerialized.PreferredPolicy
|
||||
}
|
||||
// 用户未指定时,返回可用的第一个
|
||||
if prefer == 0 {
|
||||
if len(user.Group.PolicyList) != 0 {
|
||||
return user.Group.PolicyList[0]
|
||||
}
|
||||
return 1
|
||||
}
|
||||
// 用户指定时,先检查是否为可用策略列表中的值
|
||||
if util.ContainsUint(user.Group.PolicyList, prefer) {
|
||||
return prefer
|
||||
}
|
||||
// 不可用时,返回第一个
|
||||
if len(user.Group.PolicyList) != 0 {
|
||||
return user.Group.PolicyList[0]
|
||||
}
|
||||
return 1
|
||||
|
||||
return user.Group.PolicyList[0]
|
||||
}
|
||||
|
||||
// GetUserByID 用ID获取用户
|
||||
|
@ -281,20 +236,6 @@ func (user *User) IsAnonymous() bool {
|
|||
return user.ID == 0
|
||||
}
|
||||
|
||||
// Notified 更新用户容量超额通知日期
|
||||
func (user *User) Notified() {
|
||||
if user.NotifyDate == nil {
|
||||
timeNow := time.Now()
|
||||
user.NotifyDate = &timeNow
|
||||
DB.Model(&user).Update("notify_date", user.NotifyDate)
|
||||
}
|
||||
}
|
||||
|
||||
// ClearNotified 清除用户通知标记
|
||||
func (user *User) ClearNotified() {
|
||||
DB.Model(&user).Update("notify_date", nil)
|
||||
}
|
||||
|
||||
// SetStatus 设定用户状态
|
||||
func (user *User) SetStatus(status int) {
|
||||
DB.Model(&user).Update("status", status)
|
||||
|
@ -312,41 +253,3 @@ func (user *User) UpdateOptions() error {
|
|||
}
|
||||
return user.Update(map[string]interface{}{"options": user.Options})
|
||||
}
|
||||
|
||||
// GetGroupExpiredUsers 获取用户组过期的用户
|
||||
func GetGroupExpiredUsers() []User {
|
||||
var users []User
|
||||
DB.Where("group_expires < ? and previous_group_id <> 0", time.Now()).Find(&users)
|
||||
return users
|
||||
}
|
||||
|
||||
// GetTolerantExpiredUser 获取超过宽容期的用户
|
||||
func GetTolerantExpiredUser() []User {
|
||||
var users []User
|
||||
DB.Set("gorm:auto_preload", true).Where("notify_date < ?", time.Now().Add(
|
||||
time.Duration(-GetIntSetting("ban_time", 10))*time.Second),
|
||||
).Find(&users)
|
||||
return users
|
||||
}
|
||||
|
||||
// GroupFallback 回退到初始用户组
|
||||
func (user *User) GroupFallback() {
|
||||
if user.GroupExpires != nil && user.PreviousGroupID != 0 {
|
||||
user.Group.ID = user.PreviousGroupID
|
||||
DB.Model(&user).Updates(map[string]interface{}{
|
||||
"group_expires": nil,
|
||||
"previous_group_id": 0,
|
||||
"group_id": user.PreviousGroupID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// UpgradeGroup 升级用户组
|
||||
func (user *User) UpgradeGroup(id uint, expires *time.Time) error {
|
||||
user.Group.ID = id
|
||||
return DB.Model(&user).Updates(map[string]interface{}{
|
||||
"group_expires": expires,
|
||||
"previous_group_id": user.GroupID,
|
||||
"group_id": id,
|
||||
}).Error
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ var BackendVersion = "3.0.0-alpha1"
|
|||
var RequiredDBVersion = "3.0.0-alpha1"
|
||||
|
||||
// IsPro 是否为Pro版本
|
||||
var IsPro = "true"
|
||||
var IsPro = "false"
|
||||
|
||||
// LastCommit 最后commit id
|
||||
var LastCommit = "a11f819"
|
||||
|
|
|
@ -2,7 +2,6 @@ package hashid
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/HFO4/cloudreve/bootstrap/constant"
|
||||
"github.com/HFO4/cloudreve/pkg/conf"
|
||||
)
|
||||
import "github.com/speps/go-hashids"
|
||||
|
@ -62,7 +61,7 @@ func HashID(id uint, t int) string {
|
|||
// DecodeHashID 计算HashID对应的数据库ID
|
||||
func DecodeHashID(id string, t int) (uint, error) {
|
||||
v, _ := HashDecode(id)
|
||||
if len(v) != 2 || v[1] != constant.HashIDTable[t] {
|
||||
if len(v) != 2 || v[1] != t {
|
||||
return 0, ErrTypeNotMatch
|
||||
}
|
||||
return uint(v[0]), nil
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package hashid
|
||||
|
||||
import (
|
||||
"github.com/HFO4/cloudreve/bootstrap/constant"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
@ -53,7 +52,6 @@ func TestHashDecode(t *testing.T) {
|
|||
|
||||
func TestDecodeHashID(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
constant.HashIDTable = []int{0, 1, 2, 3, 4, 5}
|
||||
|
||||
// 成功
|
||||
{
|
||||
|
|
|
@ -57,7 +57,6 @@ func GiveGroup(user *model.User, groupInfo *serializer.GroupProducts, num int) e
|
|||
|
||||
// GiveScore 积分充值
|
||||
func GiveScore(user *model.User, num int) error {
|
||||
user.AddScore(num)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -22,17 +22,6 @@ func (pay *ScorePayment) Create(order *model.Order, pack *serializer.PackProduct
|
|||
return nil, ErrUnsupportedPaymentMethod
|
||||
}
|
||||
|
||||
// 扣除用户积分
|
||||
if !user.PayScore(order.Price * order.Num) {
|
||||
return nil, ErrScoreNotEnough
|
||||
}
|
||||
|
||||
// 商品“发货”
|
||||
if err := GiveProduct(user, pack, group, order.Num); err != nil {
|
||||
user.AddScore(order.Price * order.Num)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建订单记录
|
||||
order.Status = model.OrderPaid
|
||||
if _, err := order.Create(); err != nil {
|
||||
|
|
|
@ -12,8 +12,6 @@ type SiteConfig struct {
|
|||
QQLogin bool `json:"QQLogin"`
|
||||
Themes string `json:"themes"`
|
||||
DefaultTheme string `json:"defaultTheme"`
|
||||
ScoreEnabled bool `json:"score_enabled"`
|
||||
ShareScoreRate string `json:"share_score_rate"`
|
||||
HomepageViewMethod string `json:"home_view_method"`
|
||||
ShareViewMethod string `json:"share_view_method"`
|
||||
Authn bool `json:"authn"'`
|
||||
|
@ -72,8 +70,6 @@ func BuildSiteConfig(settings map[string]string, user *model.User) Response {
|
|||
QQLogin: model.IsTrueVal(checkSettingValue(settings, "qq_login")),
|
||||
Themes: checkSettingValue(settings, "themes"),
|
||||
DefaultTheme: checkSettingValue(settings, "defaultTheme"),
|
||||
ScoreEnabled: model.IsTrueVal(checkSettingValue(settings, "score_enabled")),
|
||||
ShareScoreRate: checkSettingValue(settings, "share_score_rate"),
|
||||
HomepageViewMethod: checkSettingValue(settings, "home_view_method"),
|
||||
ShareViewMethod: checkSettingValue(settings, "share_view_method"),
|
||||
Authn: model.IsTrueVal(checkSettingValue(settings, "authn_enabled")),
|
||||
|
|
|
@ -11,7 +11,6 @@ type Share struct {
|
|||
Key string `json:"key"`
|
||||
Locked bool `json:"locked"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Score int `json:"score"`
|
||||
CreateDate string `json:"create_date,omitempty"`
|
||||
Downloads int `json:"downloads"`
|
||||
Views int `json:"views"`
|
||||
|
@ -36,7 +35,6 @@ type shareSource struct {
|
|||
type myShareItem struct {
|
||||
Key string `json:"key"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Score int `json:"score"`
|
||||
Password string `json:"password"`
|
||||
CreateDate string `json:"create_date,omitempty"`
|
||||
Downloads int `json:"downloads"`
|
||||
|
@ -55,7 +53,6 @@ func BuildShareList(shares []model.Share, total int) Response {
|
|||
item := myShareItem{
|
||||
Key: hashid.HashID(shares[i].ID, hashid.ShareID),
|
||||
IsDir: shares[i].IsDir,
|
||||
Score: shares[i].Score,
|
||||
Password: shares[i].Password,
|
||||
CreateDate: shares[i].CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
Downloads: shares[i].Downloads,
|
||||
|
@ -101,7 +98,6 @@ func BuildShareResponse(share *model.Share, unlocked bool) Share {
|
|||
Nick: creator.Nick,
|
||||
GroupName: creator.Group.Name,
|
||||
},
|
||||
Score: share.Score,
|
||||
CreateDate: share.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ type User struct {
|
|||
Avatar string `json:"avatar"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
PreferredTheme string `json:"preferred_theme"`
|
||||
Score int `json:"score"`
|
||||
Anonymous bool `json:"anonymous"`
|
||||
Policy policy `json:"policy"`
|
||||
Group group `json:"group"`
|
||||
|
@ -97,7 +96,6 @@ func BuildUser(user model.User) User {
|
|||
Avatar: user.Avatar,
|
||||
CreatedAt: user.CreatedAt.Unix(),
|
||||
PreferredTheme: user.OptionsSerialized.PreferredTheme,
|
||||
Score: user.Score,
|
||||
Anonymous: user.IsAnonymous(),
|
||||
Policy: policy{
|
||||
SaveType: user.Policy.Type,
|
||||
|
@ -112,7 +110,6 @@ func BuildUser(user model.User) User {
|
|||
AllowShare: user.Group.ShareEnabled,
|
||||
AllowRemoteDownload: user.Group.OptionsSerialized.Aria2,
|
||||
AllowArchiveDownload: user.Group.OptionsSerialized.ArchiveDownload,
|
||||
ShareFreeEnabled: user.Group.OptionsSerialized.ShareFree,
|
||||
ShareDownload: user.Group.OptionsSerialized.ShareDownload,
|
||||
CompressEnabled: user.Group.OptionsSerialized.ArchiveTask,
|
||||
WebDAVEnabled: user.Group.WebDAVEnabled,
|
||||
|
|
|
@ -55,25 +55,6 @@ func BuildPolicySettingRes(policies []model.Policy, current *model.Policy) Respo
|
|||
}
|
||||
}
|
||||
|
||||
// BuildMountedFolderRes 构建已挂载目录响应,list为当前用户可用存储策略ID
|
||||
func BuildMountedFolderRes(folders []model.Folder, list []uint) []MountedFolders {
|
||||
res := make([]MountedFolders, 0, len(folders))
|
||||
for _, folder := range folders {
|
||||
single := MountedFolders{
|
||||
ID: hashid.HashID(folder.ID, hashid.FolderID),
|
||||
Name: folder.Name,
|
||||
PolicyName: "[已失效存储策略]",
|
||||
}
|
||||
if policy, err := model.GetPolicyByID(folder.PolicyID); err == nil && util.ContainsUint(list, policy.ID) {
|
||||
single.PolicyName = policy.Name
|
||||
}
|
||||
|
||||
res = append(res, single)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// BuildUserQuotaResponse 序列化用户存储配额概况响应
|
||||
func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response {
|
||||
packSize := user.GetAvailablePackSize()
|
||||
|
|
|
@ -356,17 +356,6 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *filesyst
|
|||
fs.Use("AfterValidateFailed", filesystem.HookGiveBackCapacity)
|
||||
ctx = context.WithValue(ctx, fsctx.FileModelCtx, *originFile)
|
||||
} else {
|
||||
// 检查父目录指定存储策略
|
||||
if exist, folder := fs.IsPathExist(filePath); exist {
|
||||
if folder.PolicyID != 0 {
|
||||
// 尝试获取并重设存储策略
|
||||
if policy, err := model.GetPolicyByID(fs.User.GetPolicyID(folder.PolicyID)); err == nil {
|
||||
fs.User.Policy = policy
|
||||
fs.DispatchHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 给文件系统分配钩子
|
||||
fs.Use("BeforeUpload", filesystem.HookValidateFile)
|
||||
fs.Use("BeforeUpload", filesystem.HookValidateCapacity)
|
||||
|
|
|
@ -21,8 +21,6 @@ func SiteConfig(c *gin.Context) {
|
|||
"email_active",
|
||||
"themes",
|
||||
"defaultTheme",
|
||||
"score_enabled",
|
||||
"share_score_rate",
|
||||
"home_view_method",
|
||||
"share_view_method",
|
||||
"authn_enabled",
|
||||
|
|
|
@ -74,7 +74,6 @@ func InitCORS(router *gin.Engine) {
|
|||
// InitMasterRouter 初始化主机模式路由
|
||||
func InitMasterRouter() *gin.Engine {
|
||||
r := gin.Default()
|
||||
bootstrap.InitCustomRoute(r.Group("/custom"))
|
||||
|
||||
/*
|
||||
静态资源
|
||||
|
|
|
@ -114,7 +114,6 @@ func (service *AddUserService) Add() serializer.Response {
|
|||
user.Email = service.User.Email
|
||||
user.GroupID = service.User.GroupID
|
||||
user.Status = service.User.Status
|
||||
user.Score = service.User.Score
|
||||
|
||||
// 检查愚蠢操作
|
||||
if user.ID == 1 && user.GroupID != 1 {
|
||||
|
|
|
@ -115,11 +115,7 @@ func (service *WebDAVAccountService) Delete(c *gin.Context, user *model.User) se
|
|||
func (service *WebDAVListService) Accounts(c *gin.Context, user *model.User) serializer.Response {
|
||||
accounts := model.ListWebDAVAccounts(user.ID)
|
||||
|
||||
// 查找挂载了存储策略的目录
|
||||
folders := model.GetMountedFolders(user.ID)
|
||||
|
||||
return serializer.Response{Data: map[string]interface{}{
|
||||
"accounts": accounts,
|
||||
"folders": serializer.BuildMountedFolderRes(folders, user.Group.PolicyList),
|
||||
}}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ type ShareCreateService struct {
|
|||
Password string `json:"password" binding:"max=255"`
|
||||
RemainDownloads int `json:"downloads"`
|
||||
Expire int `json:"expire"`
|
||||
Score int `json:"score" binding:"gte=0"`
|
||||
Preview bool `json:"preview"`
|
||||
}
|
||||
|
||||
|
@ -117,7 +116,6 @@ func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
|||
IsDir: service.IsDir,
|
||||
UserID: user.ID,
|
||||
SourceID: sourceID,
|
||||
Score: service.Score,
|
||||
RemainDownloads: -1,
|
||||
PreviewEnabled: service.Preview,
|
||||
SourceName: sourceName,
|
||||
|
|
|
@ -117,8 +117,6 @@ func (service *ShareListService) List(c *gin.Context, user *model.User) serializ
|
|||
func (service *ShareGetService) Get(c *gin.Context) serializer.Response {
|
||||
shareCtx, _ := c.Get("share")
|
||||
share := shareCtx.(*model.Share)
|
||||
userCtx, _ := c.Get("user")
|
||||
user := userCtx.(*model.User)
|
||||
|
||||
// 是否已解锁
|
||||
unlocked := true
|
||||
|
@ -138,11 +136,6 @@ func (service *ShareGetService) Get(c *gin.Context) serializer.Response {
|
|||
share.Viewed()
|
||||
}
|
||||
|
||||
// 如果已经下载过或者是自己的分享,不需要付积分
|
||||
if share.UserID == user.ID || share.WasDownloadedBy(user, c) {
|
||||
share.Score = 0
|
||||
}
|
||||
|
||||
return serializer.Response{
|
||||
Code: 0,
|
||||
Data: serializer.BuildShareResponse(share, unlocked),
|
||||
|
|
Loading…
Add table
Reference in a new issue