diff --git a/pkg/email/template.go b/pkg/email/template.go index 451e27d..7b25ce3 100644 --- a/pkg/email/template.go +++ b/pkg/email/template.go @@ -6,20 +6,6 @@ import ( "github.com/HFO4/cloudreve/pkg/util" ) -// NewOveruseNotification 新建超额提醒邮件 -func NewOveruseNotification(userName, reason string) (string, string) { - options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "over_used_template") - replace := map[string]string{ - "{siteTitle}": options["siteName"], - "{userName}": userName, - "{notifyReason}": reason, - "{siteUrl}": options["siteURL"], - "{siteSecTitle}": options["siteTitle"], - } - return fmt.Sprintf("【%s】空间容量超额提醒", options["siteName"]), - util.Replace(replace, options["over_used_template"]) -} - // NewActivationEmail 新建激活邮件 func NewActivationEmail(userName, activateURL string) (string, string) { options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "mail_activation_template") diff --git a/pkg/payment/alipay.go b/pkg/payment/alipay.go deleted file mode 100644 index a1fbf2c..0000000 --- a/pkg/payment/alipay.go +++ /dev/null @@ -1,42 +0,0 @@ -package payment - -import ( - "fmt" - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - alipay "github.com/smartwalle/alipay/v3" - "net/url" -) - -// Alipay 支付宝当面付支付处理 -type Alipay struct { - Client *alipay.Client -} - -// Create 创建订单 -func (pay *Alipay) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) { - gateway, _ := url.Parse("/api/v3/callback/alipay") - var p = alipay.TradePreCreate{ - Trade: alipay.Trade{ - NotifyURL: model.GetSiteURL().ResolveReference(gateway).String(), - Subject: order.Name, - OutTradeNo: order.OrderNo, - TotalAmount: fmt.Sprintf("%.2f", float64(order.Price*order.Num)/100), - }, - } - - if _, err := order.Create(); err != nil { - return nil, ErrInsertOrder.WithError(err) - } - - res, err := pay.Client.TradePreCreate(p) - if err != nil { - return nil, ErrIssueOrder.WithError(err) - } - - return &OrderCreateRes{ - Payment: true, - QRCode: res.Content.QRCode, - ID: order.OrderNo, - }, nil -} diff --git a/pkg/payment/order.go b/pkg/payment/order.go deleted file mode 100644 index 37daff2..0000000 --- a/pkg/payment/order.go +++ /dev/null @@ -1,147 +0,0 @@ -package payment - -import ( - "fmt" - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/qingwg/payjs" - "github.com/smartwalle/alipay/v3" - "math/rand" - "net/url" - "time" -) - -var ( - // ErrUnknownPaymentMethod 未知支付方式 - ErrUnknownPaymentMethod = serializer.NewError(serializer.CodeNotFound, "未知支付方式", nil) - // ErrUnsupportedPaymentMethod 未知支付方式 - ErrUnsupportedPaymentMethod = serializer.NewError(serializer.CodeNotFound, "此订单不支持此支付方式", nil) - // ErrInsertOrder 无法插入订单记录 - ErrInsertOrder = serializer.NewError(serializer.CodeDBError, "无法插入订单记录", nil) - // ErrScoreNotEnough 积分不足 - ErrScoreNotEnough = serializer.NewError(serializer.CodeNoPermissionErr, "积分不足", nil) - // ErrCreateStoragePack 无法创建容量包 - ErrCreateStoragePack = serializer.NewError(serializer.CodeNoPermissionErr, "无法创建容量包", nil) - // ErrGroupConflict 用户组冲突 - ErrGroupConflict = serializer.NewError(serializer.CodeNoPermissionErr, "当前用户组仍未过期,请前往个人设置手动解约后继续", nil) - // ErrGroupInvalid 用户组冲突 - ErrGroupInvalid = serializer.NewError(serializer.CodeNoPermissionErr, "用户组不可用", nil) - // ErrUpgradeGroup 用户组冲突 - ErrUpgradeGroup = serializer.NewError(serializer.CodeDBError, "无法升级用户组", nil) - // ErrUInitPayment 无法初始化支付实例 - ErrUInitPayment = serializer.NewError(serializer.CodeInternalSetting, "无法初始化支付实例", nil) - // ErrIssueOrder 订单接口请求失败 - ErrIssueOrder = serializer.NewError(serializer.CodeInternalSetting, "无法创建订单", nil) - // ErrOrderNotFound 订单不存在 - ErrOrderNotFound = serializer.NewError(serializer.CodeNotFound, "订单不存在", nil) -) - -// Pay 支付处理接口 -type Pay interface { - Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) -} - -// OrderCreateRes 订单创建结果 -type OrderCreateRes struct { - Payment bool `json:"payment"` // 是否需要支付 - ID string `json:"id,omitempty"` // 订单号 - QRCode string `json:"qr_code,omitempty"` // 支付二维码指向的地址 -} - -// NewPaymentInstance 获取新的支付实例 -func NewPaymentInstance(method string) (Pay, error) { - switch method { - case "score": - return &ScorePayment{}, nil - case "alipay": - options := model.GetSettingByNames("alipay_enabled", "appid", "appkey", "shopid") - if options["alipay_enabled"] != "1" { - return nil, ErrUnknownPaymentMethod - } - - // 初始化支付宝客户端 - var client, err = alipay.New(options["appid"], options["appkey"], true) - if err != nil { - return nil, ErrUInitPayment.WithError(err) - } - - // 加载支付宝公钥 - err = client.LoadAliPayPublicKey(options["shopid"]) - if err != nil { - return nil, ErrUInitPayment.WithError(err) - } - - return &Alipay{Client: client}, nil - case "payjs": - options := model.GetSettingByNames("payjs_enabled", "payjs_secret", "payjs_id") - if options["payjs_enabled"] != "1" { - return nil, ErrUnknownPaymentMethod - } - - callback, _ := url.Parse("/api/v3/callback/payjs") - payjsConfig := &payjs.Config{ - Key: options["payjs_secret"], - MchID: options["payjs_id"], - NotifyUrl: model.GetSiteURL().ResolveReference(callback).String(), - } - - return &PayJSClient{Client: payjs.New(payjsConfig)}, nil - - default: - return nil, ErrUnknownPaymentMethod - } -} - -// NewOrder 创建新订单 -func NewOrder(pack *serializer.PackProduct, group *serializer.GroupProducts, num int, method string, user *model.User) (*OrderCreateRes, error) { - // 获取支付实例 - pay, err := NewPaymentInstance(method) - if err != nil { - return nil, err - } - - var ( - orderType int - productID int64 - title string - price int - ) - if pack != nil { - orderType = model.PackOrderType - productID = pack.ID - title = pack.Name - price = pack.Price - } else if group != nil { - orderType = model.GroupOrderType - productID = group.ID - title = group.Name - price = group.Price - } else { - orderType = model.ScoreOrderType - productID = 0 - title = fmt.Sprintf("%d 积分", num) - price = model.GetIntSetting("score_price", 1) - } - - // 创建订单记录 - order := &model.Order{ - UserID: user.ID, - OrderNo: orderID(), - Type: orderType, - Method: method, - ProductID: productID, - Num: num, - Name: fmt.Sprintf("%s - %s", model.GetSettingByName("siteName"), title), - Price: price, - Status: model.OrderUnpaid, - } - - return pay.Create(order, pack, group, user) -} - -func orderID() string { - return fmt.Sprintf("%s%d", - time.Now().Format("20060102150405"), - 100000+rand.Intn(900000), - ) -} diff --git a/pkg/payment/payjs.go b/pkg/payment/payjs.go deleted file mode 100644 index ae77764..0000000 --- a/pkg/payment/payjs.go +++ /dev/null @@ -1,31 +0,0 @@ -package payment - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/qingwg/payjs" -) - -// PayJSClient PayJS支付处理 -type PayJSClient struct { - Client *payjs.PayJS -} - -// Create 创建订单 -func (pay *PayJSClient) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) { - if _, err := order.Create(); err != nil { - return nil, ErrInsertOrder.WithError(err) - } - - PayNative := pay.Client.GetNative() - res, err := PayNative.Create(int64(order.Price*order.Num), order.Name, order.OrderNo, "", "") - if err != nil { - return nil, ErrIssueOrder.WithError(err) - } - - return &OrderCreateRes{ - Payment: true, - QRCode: res.CodeUrl, - ID: order.OrderNo, - }, nil -} diff --git a/pkg/payment/purchase.go b/pkg/payment/purchase.go deleted file mode 100644 index 9aa804b..0000000 --- a/pkg/payment/purchase.go +++ /dev/null @@ -1,127 +0,0 @@ -package payment - -import ( - "encoding/json" - "errors" - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "time" -) - -// GivePack 创建容量包 -func GivePack(user *model.User, packInfo *serializer.PackProduct, num int) error { - timeNow := time.Now() - expires := timeNow.Add(time.Duration(packInfo.Time*int64(num)) * time.Second) - pack := model.StoragePack{ - Name: packInfo.Name, - UserID: user.ID, - ActiveTime: &timeNow, - ExpiredTime: &expires, - Size: packInfo.Size, - } - if _, err := pack.Create(); err != nil { - return ErrCreateStoragePack.WithError(err) - } - return nil -} - -func checkGroupUpgrade(user *model.User, groupInfo *serializer.GroupProducts) error { - // 检查用户是否已有未过期用户 - if user.PreviousGroupID != 0 { - return ErrGroupConflict - } - - // 用户组不能相同 - if user.GroupID == groupInfo.GroupID { - return ErrGroupInvalid - } - - return nil -} - -// GiveGroup 升级用户组 -func GiveGroup(user *model.User, groupInfo *serializer.GroupProducts, num int) error { - if err := checkGroupUpgrade(user, groupInfo); err != nil { - return err - } - - timeNow := time.Now() - expires := timeNow.Add(time.Duration(groupInfo.Time*int64(num)) * time.Second) - - if err := user.UpgradeGroup(groupInfo.GroupID, &expires); err != nil { - return ErrUpgradeGroup.WithError(err) - } - - return nil -} - -// GiveScore 积分充值 -func GiveScore(user *model.User, num int) error { - return nil -} - -// GiveProduct “发货” -func GiveProduct(user *model.User, pack *serializer.PackProduct, group *serializer.GroupProducts, num int) error { - if pack != nil { - return GivePack(user, pack, num) - } else if group != nil { - return GiveGroup(user, group, num) - } else { - return GiveScore(user, num) - } -} - -// OrderPaid 订单已支付处理 -func OrderPaid(orderNo string) error { - order, err := model.GetOrderByNo(orderNo) - if err != nil { - return ErrOrderNotFound.WithError(err) - } - - // 更新订单状态为 已支付 - order.UpdateStatus(model.OrderPaid) - - user, err := model.GetActiveUserByID(order.UserID) - if err != nil { - return errors.New("用户不存在") - } - - // 查询商品 - options := model.GetSettingByNames("pack_data", "group_sell_data") - - var ( - packs []serializer.PackProduct - groups []serializer.GroupProducts - ) - if err := json.Unmarshal([]byte(options["pack_data"]), &packs); err != nil { - return err - } - if err := json.Unmarshal([]byte(options["group_sell_data"]), &groups); err != nil { - return err - } - - // 查找要购买的商品 - var ( - pack *serializer.PackProduct - group *serializer.GroupProducts - ) - if order.Type == model.GroupOrderType { - for _, v := range groups { - if v.ID == order.ProductID { - group = &v - break - } - } - } else if order.Type == model.PackOrderType { - for _, v := range packs { - if v.ID == order.ProductID { - pack = &v - break - } - } - } - - // "发货" - return GiveProduct(&user, pack, group, order.Num) - -} diff --git a/pkg/payment/score.go b/pkg/payment/score.go deleted file mode 100644 index b123ff7..0000000 --- a/pkg/payment/score.go +++ /dev/null @@ -1,34 +0,0 @@ -package payment - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" -) - -// ScorePayment 积分支付处理 -type ScorePayment struct { -} - -// Create 创建新订单 -func (pay *ScorePayment) Create(order *model.Order, pack *serializer.PackProduct, group *serializer.GroupProducts, user *model.User) (*OrderCreateRes, error) { - if pack != nil { - order.Price = pack.Score - } else { - order.Price = group.Score - } - - // 检查此订单是否可用积分支付 - if order.Price == 0 { - return nil, ErrUnsupportedPaymentMethod - } - - // 创建订单记录 - order.Status = model.OrderPaid - if _, err := order.Create(); err != nil { - return nil, ErrInsertOrder.WithError(err) - } - - return &OrderCreateRes{ - Payment: false, - }, nil -} diff --git a/pkg/qq/connect.go b/pkg/qq/connect.go deleted file mode 100644 index 3c34295..0000000 --- a/pkg/qq/connect.go +++ /dev/null @@ -1,211 +0,0 @@ -package qq - -import ( - "crypto/md5" - "encoding/json" - "errors" - "fmt" - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/request" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/gofrs/uuid" - "net/url" - "strings" -) - -// LoginPage 登陆页面描述 -type LoginPage struct { - URL string - SecretKey string -} - -// UserCredentials 登陆成功后的凭证 -type UserCredentials struct { - OpenID string - AccessToken string -} - -// UserInfo 用户信息 -type UserInfo struct { - Nick string - Avatar string -} - -var ( - // ErrNotEnabled 未开启登录功能 - ErrNotEnabled = serializer.NewError(serializer.CodeNoPermissionErr, "QQ登录功能未开启", nil) - // ErrObtainAccessToken 无法获取AccessToken - ErrObtainAccessToken = serializer.NewError(serializer.CodeParamErr, "无法获取AccessToken", nil) - // ErrObtainOpenID 无法获取OpenID - ErrObtainOpenID = serializer.NewError(serializer.CodeParamErr, "无法获取OpenID", nil) - //ErrDecodeResponse 无法解析服务端响应 - ErrDecodeResponse = serializer.NewError(serializer.CodeInternalSetting, "无法解析服务端响应", nil) -) - -// NewLoginRequest 新建登录会话 -func NewLoginRequest() (*LoginPage, error) { - // 获取相关设定 - options := model.GetSettingByNames("qq_login", "qq_login_id") - if options["qq_login"] == "0" { - return nil, ErrNotEnabled - } - - // 生成唯一ID - u2, err := uuid.NewV4() - if err != nil { - return nil, err - } - secret := fmt.Sprintf("%x", md5.Sum(u2.Bytes())) - - // 生成登录地址 - loginURL, _ := url.Parse("https://graph.qq.com/oauth2.0/authorize?response_type=code") - queries := loginURL.Query() - queries.Add("client_id", options["qq_login_id"]) - queries.Add("redirect_uri", getCallbackURL()) - queries.Add("state", secret) - loginURL.RawQuery = queries.Encode() - - return &LoginPage{ - URL: loginURL.String(), - SecretKey: secret, - }, nil -} - -func getCallbackURL() string { - //return "https://drive.aoaoao.me/Callback/QQ" - // 生成回调地址 - gateway, _ := url.Parse("/#/login/qq") - callback := model.GetSiteURL().ResolveReference(gateway).String() - - return callback -} - -func getAccessTokenURL(code string) string { - // 获取相关设定 - options := model.GetSettingByNames("qq_login_id", "qq_login_key") - - api, _ := url.Parse("https://graph.qq.com/oauth2.0/token?grant_type=authorization_code") - queries := api.Query() - queries.Add("client_id", options["qq_login_id"]) - queries.Add("redirect_uri", getCallbackURL()) - queries.Add("client_secret", options["qq_login_key"]) - queries.Add("code", code) - api.RawQuery = queries.Encode() - - return api.String() -} - -func getUserInfoURL(openid, ak string) string { - // 获取相关设定 - options := model.GetSettingByNames("qq_login_id", "qq_login_key") - - api, _ := url.Parse("https://graph.qq.com/user/get_user_info") - queries := api.Query() - queries.Add("oauth_consumer_key", options["qq_login_id"]) - queries.Add("openid", openid) - queries.Add("access_token", ak) - api.RawQuery = queries.Encode() - - return api.String() -} - -func getResponse(body string) (map[string]interface{}, error) { - var res map[string]interface{} - - if !strings.Contains(body, "callback") { - return res, nil - } - - body = strings.TrimPrefix(body, "callback(") - body = strings.TrimSuffix(body, ");\n") - - err := json.Unmarshal([]byte(body), &res) - - return res, err -} - -// Callback 处理回调,返回openid和access key -func Callback(code string) (*UserCredentials, error) { - // 获取相关设定 - options := model.GetSettingByNames("qq_login") - if options["qq_login"] == "0" { - return nil, ErrNotEnabled - } - - api := getAccessTokenURL(code) - - // 获取AccessToken - client := request.HTTPClient{} - res := client.Request("GET", api, nil) - resp, err := res.GetResponse() - if err != nil { - return nil, ErrObtainAccessToken.WithError(err) - } - - // 如果服务端返回错误 - errResp, err := getResponse(resp) - if msg, ok := errResp["error_description"]; err == nil && ok { - return nil, ErrObtainAccessToken.WithError(errors.New(msg.(string))) - } - - // 获取AccessToken - vals, err := url.ParseQuery(resp) - if err != nil { - return nil, ErrDecodeResponse.WithError(err) - } - accessToken := vals.Get("access_token") - - // 用 AccessToken 换取OpenID - res = client.Request("GET", "https://graph.qq.com/oauth2.0/me?access_token="+accessToken, nil) - resp, err = res.GetResponse() - if err != nil { - return nil, ErrObtainOpenID.WithError(err) - } - - // 解析服务端响应 - errResp, err = getResponse(resp) - if msg, ok := errResp["error_description"]; err == nil && ok { - return nil, ErrObtainOpenID.WithError(errors.New(msg.(string))) - } - - if openid, ok := errResp["openid"]; ok { - return &UserCredentials{ - OpenID: openid.(string), - AccessToken: accessToken, - }, nil - } - - return nil, ErrDecodeResponse -} - -// GetUserInfo 使用凭证获取用户信息 -func GetUserInfo(credential *UserCredentials) (*UserInfo, error) { - api := getUserInfoURL(credential.OpenID, credential.AccessToken) - - // 获取用户信息 - client := request.HTTPClient{} - res := client.Request("GET", api, nil) - resp, err := res.GetResponse() - if err != nil { - return nil, ErrObtainAccessToken.WithError(err) - } - - var resSerialized map[string]interface{} - if err := json.Unmarshal([]byte(resp), &resSerialized); err != nil { - return nil, ErrDecodeResponse.WithError(err) - } - - // 如果服务端返回错误 - if msg, ok := resSerialized["msg"]; ok && msg.(string) != "" { - return nil, ErrObtainAccessToken.WithError(errors.New(msg.(string))) - } - - if avatar, ok := resSerialized["figureurl_qq_2"]; ok { - return &UserInfo{ - Nick: resSerialized["nickname"].(string), - Avatar: avatar.(string), - }, nil - } - - return nil, ErrDecodeResponse -} diff --git a/pkg/serializer/setting.go b/pkg/serializer/setting.go index 35f210b..8db0827 100644 --- a/pkg/serializer/setting.go +++ b/pkg/serializer/setting.go @@ -9,7 +9,6 @@ type SiteConfig struct { RegCaptcha bool `json:"regCaptcha"` ForgetCaptcha bool `json:"forgetCaptcha"` EmailActive bool `json:"emailActive"` - QQLogin bool `json:"QQLogin"` Themes string `json:"themes"` DefaultTheme string `json:"defaultTheme"` HomepageViewMethod string `json:"home_view_method"` @@ -67,7 +66,6 @@ func BuildSiteConfig(settings map[string]string, user *model.User) Response { RegCaptcha: model.IsTrueVal(checkSettingValue(settings, "reg_captcha")), ForgetCaptcha: model.IsTrueVal(checkSettingValue(settings, "forget_captcha")), EmailActive: model.IsTrueVal(checkSettingValue(settings, "email_active")), - QQLogin: model.IsTrueVal(checkSettingValue(settings, "qq_login")), Themes: checkSettingValue(settings, "themes"), DefaultTheme: checkSettingValue(settings, "defaultTheme"), HomepageViewMethod: checkSettingValue(settings, "home_view_method"), diff --git a/pkg/serializer/user.go b/pkg/serializer/user.go index bc78a3a..688ba23 100644 --- a/pkg/serializer/user.go +++ b/pkg/serializer/user.go @@ -44,7 +44,6 @@ type group struct { AllowShare bool `json:"allowShare"` AllowRemoteDownload bool `json:"allowRemoteDownload"` AllowArchiveDownload bool `json:"allowArchiveDownload"` - ShareFreeEnabled bool `json:"shareFree"` ShareDownload bool `json:"shareDownload"` CompressEnabled bool `json:"compress"` WebDAVEnabled bool `json:"webdav"` @@ -127,7 +126,7 @@ func BuildUserResponse(user model.User) Response { // BuildUserStorageResponse 序列化用户存储概况响应 func BuildUserStorageResponse(user model.User) Response { - total := user.Group.MaxStorage + user.GetAvailablePackSize() + total := user.Group.MaxStorage storageResp := storage{ Used: user.Storage, Free: total - user.Storage, diff --git a/pkg/serializer/vas.go b/pkg/serializer/vas.go deleted file mode 100644 index c20dc88..0000000 --- a/pkg/serializer/vas.go +++ /dev/null @@ -1,120 +0,0 @@ -package serializer - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/hashid" - "github.com/HFO4/cloudreve/pkg/util" -) - -type quota struct { - Base uint64 `json:"base"` - Pack uint64 `json:"pack"` - Used uint64 `json:"used"` - Total uint64 `json:"total"` - Packs []storagePacks `json:"packs"` -} - -type storagePacks struct { - Name string `json:"name"` - Size uint64 `json:"size"` - ActivateDate string `json:"activate_date"` - Expiration int `json:"expiration"` - ExpirationDate string `json:"expiration_date"` -} - -// MountedFolders 已挂载的目录 -type MountedFolders struct { - ID string `json:"id"` - Name string `json:"name"` - PolicyName string `json:"policy_name"` -} - -type policyOptions struct { - Name string `json:"name"` - ID string `json:"id"` -} - -// BuildPolicySettingRes 构建存储策略选项选择 -func BuildPolicySettingRes(policies []model.Policy, current *model.Policy) Response { - options := make([]policyOptions, 0, len(policies)) - for _, policy := range policies { - options = append(options, policyOptions{ - Name: policy.Name, - ID: hashid.HashID(policy.ID, hashid.PolicyID), - }) - } - - return Response{ - Data: map[string]interface{}{ - "options": options, - "current": policyOptions{ - Name: current.Name, - ID: hashid.HashID(current.ID, hashid.PolicyID), - }, - }, - } -} - -// BuildUserQuotaResponse 序列化用户存储配额概况响应 -func BuildUserQuotaResponse(user *model.User, packs []model.StoragePack) Response { - packSize := user.GetAvailablePackSize() - res := quota{ - Base: user.Group.MaxStorage, - Pack: packSize, - Used: user.Storage, - Total: packSize + user.Group.MaxStorage, - Packs: make([]storagePacks, 0, len(packs)), - } - for _, pack := range packs { - res.Packs = append(res.Packs, storagePacks{ - Name: pack.Name, - Size: pack.Size, - ActivateDate: pack.ActiveTime.Format("2006-01-02 15:04:05"), - Expiration: int(pack.ExpiredTime.Sub(*pack.ActiveTime).Seconds()), - ExpirationDate: pack.ExpiredTime.Format("2006-01-02 15:04:05"), - }) - } - - return Response{ - Data: res, - } -} - -// PackProduct 容量包商品 -type PackProduct struct { - ID int64 `json:"id"` - Name string `json:"name"` - Size uint64 `json:"size"` - Time int64 `json:"time"` - Price int `json:"price"` - Score int `json:"score"` -} - -// GroupProducts 用户组商品 -type GroupProducts struct { - ID int64 `json:"id"` - Name string `json:"name"` - GroupID uint `json:"group_id"` - Time int64 `json:"time"` - Price int `json:"price"` - Score int `json:"score"` - Des []string `json:"des"` - Highlight bool `json:"highlight"` -} - -// BuildProductResponse 构建增值服务商品响应 -func BuildProductResponse(groups []GroupProducts, packs []PackProduct, alipay, payjs bool, scorePrice int) Response { - // 隐藏响应中的用户组ID - for i := 0; i < len(groups); i++ { - groups[i].GroupID = 0 - } - return Response{ - Data: map[string]interface{}{ - "packs": packs, - "groups": groups, - "alipay": alipay, - "payjs": payjs, - "score_price": scorePrice, - }, - } -} diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index 1b89a7b..2b02e80 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -87,39 +87,6 @@ func AdminSendTestMail(c *gin.Context) { } } -// AdminListRedeems 列出激活码 -func AdminListRedeems(c *gin.Context) { - var service admin.AdminListService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Redeems() - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// AdminGenerateRedeems 生成激活码 -func AdminGenerateRedeems(c *gin.Context) { - var service admin.GenerateRedeemsService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Generate() - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// AdminDeleteRedeem 删除激活码 -func AdminDeleteRedeem(c *gin.Context) { - var service admin.SingleIDService - if err := c.ShouldBindUri(&service); err == nil { - res := service.DeleteRedeem() - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - // AdminTestAria2 测试aria2连接 func AdminTestAria2(c *gin.Context) { var service admin.Aria2TestService @@ -392,28 +359,6 @@ func AdminDeleteShare(c *gin.Context) { } } -// AdminListOrder 列出订单 -func AdminListOrder(c *gin.Context) { - var service admin.AdminListService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Orders() - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// AdminDeleteOrder 批量删除订单 -func AdminDeleteOrder(c *gin.Context) { - var service admin.OrderBatchService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Delete(c) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - // AdminListDownload 列出离线下载任务 func AdminListDownload(c *gin.Context) { var service admin.AdminListService diff --git a/routers/controllers/share.go b/routers/controllers/share.go index a264f13..bdc7d1e 100644 --- a/routers/controllers/share.go +++ b/routers/controllers/share.go @@ -172,17 +172,6 @@ func GetShareDocPreview(c *gin.Context) { } } -// SaveShare 转存他人分享 -func SaveShare(c *gin.Context) { - var service share.Service - if err := c.ShouldBindJSON(&service); err == nil { - res := service.SaveToMyFile(c) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - // ListSharedFolder 列出分享的目录下的对象 func ListSharedFolder(c *gin.Context) { var service share.Service diff --git a/routers/controllers/site.go b/routers/controllers/site.go index d3d8e4e..4793eb4 100644 --- a/routers/controllers/site.go +++ b/routers/controllers/site.go @@ -14,7 +14,6 @@ func SiteConfig(c *gin.Context) { siteConfig := model.GetSettingByNames( "siteName", "login_captcha", - "qq_login", "reg_captcha", "email_active", "forget_captcha", diff --git a/routers/controllers/user.go b/routers/controllers/user.go index c91ce80..818dff5 100644 --- a/routers/controllers/user.go +++ b/routers/controllers/user.go @@ -5,7 +5,6 @@ import ( "fmt" model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/authn" - "github.com/HFO4/cloudreve/pkg/qq" "github.com/HFO4/cloudreve/pkg/request" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/thumb" @@ -213,24 +212,6 @@ func UserActivate(c *gin.Context) { } } -// UserQQLogin 初始化QQ登录 -func UserQQLogin(c *gin.Context) { - // 新建绑定 - res, err := qq.NewLoginRequest() - if err != nil { - c.JSON(200, serializer.Err(serializer.CodeNotSet, "无法使用QQ登录", err)) - return - } - - // 设定QQ登录会话Secret - util.SetSession(c, map[string]interface{}{"qq_login_secret": res.SecretKey}) - - c.JSON(200, serializer.Response{ - Data: res.URL, - }) - -} - // UserSignOut 用户退出登录 func UserSignOut(c *gin.Context) { util.DeleteSession(c, "user_id") @@ -251,17 +232,6 @@ func UserStorage(c *gin.Context) { c.JSON(200, res) } -// UserAvailablePolicies 用户存储策略设置 -func UserAvailablePolicies(c *gin.Context) { - var service user.SettingService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Policy(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - // UserTasks 获取任务队列 func UserTasks(c *gin.Context) { var service user.SettingListService @@ -368,12 +338,6 @@ func UpdateOption(c *gin.Context) { switch service.Option { case "nick": subService = &user.ChangerNick{} - case "vip": - subService = &user.VIPUnsubscribe{} - case "qq": - subService = &user.QQBind{} - case "policy": - subService = &user.PolicyChange{} case "homepage": subService = &user.HomePage{} case "password": diff --git a/routers/controllers/vas.go b/routers/controllers/vas.go deleted file mode 100644 index 6a77f80..0000000 --- a/routers/controllers/vas.go +++ /dev/null @@ -1,144 +0,0 @@ -package controllers - -import ( - "github.com/HFO4/cloudreve/pkg/payment" - "github.com/HFO4/cloudreve/pkg/util" - "github.com/HFO4/cloudreve/service/vas" - "github.com/gin-gonic/gin" - "github.com/qingwg/payjs/notify" - "github.com/smartwalle/alipay/v3" -) - -// GetQuota 获取容量配额信息 -func GetQuota(c *gin.Context) { - var service vas.GeneralVASService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Quota(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// GetProduct 获取商品信息 -func GetProduct(c *gin.Context) { - var service vas.GeneralVASService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Products(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// NewOrder 新建支付订单 -func NewOrder(c *gin.Context) { - var service vas.CreateOrderService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Create(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// OrderStatus 查询订单状态 -func OrderStatus(c *gin.Context) { - var service vas.OrderService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Status(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// GetRedeemInfo 获取兑换码信息 -func GetRedeemInfo(c *gin.Context) { - var service vas.RedeemService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Query(c) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// DoRedeem 获取兑换码信息 -func DoRedeem(c *gin.Context) { - var service vas.RedeemService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Redeem(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - -// AlipayCallback 支付宝回调 -func AlipayCallback(c *gin.Context) { - pay, err := payment.NewPaymentInstance("alipay") - if err != nil { - util.Log().Debug("[支付宝回调] 无法创建支付宝客户端, %s", err) - c.Status(400) - return - } - - res, err := pay.(*payment.Alipay).Client.GetTradeNotification(c.Request) - if err != nil { - util.Log().Debug("[支付宝回调] 回调验证失败, %s", err) - c.Status(403) - return - } - - if res != nil && res.TradeStatus == "TRADE_SUCCESS" { - // 支付成功 - if err := payment.OrderPaid(res.OutTradeNo); err != nil { - util.Log().Debug("[支付宝回调] 支付处理失败, %s", err) - } - } - - // 确认收到通知消息 - alipay.AckNotification(c.Writer) -} - -// PayJSCallback PayJS回调 -func PayJSCallback(c *gin.Context) { - pay, err := payment.NewPaymentInstance("payjs") - if err != nil { - util.Log().Debug("[PayJS回调] 无法创建支付宝客户端, %s", err) - c.Status(400) - return - } - - payNotify := pay.(*payment.PayJSClient).Client.GetNotify(c.Request, c.Writer) - - //设置接收消息的处理方法 - payNotify.SetMessageHandler(func(msg notify.Message) { - if err := payment.OrderPaid(msg.OutTradeNo); err != nil { - util.Log().Debug("[PayJS回调] 支付处理失败, %s", err) - } - }) - - //处理消息接收以及回复 - err = payNotify.Serve() - if err != nil { - util.Log().Debug("[PayJS回调] 回调处理失败, %s", err) - return - } - - //发送回复的消息 - payNotify.SendResponseMsg() - -} - -// QQCallback QQ互联回调 -func QQCallback(c *gin.Context) { - var service vas.QQCallbackService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Callback(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} diff --git a/routers/controllers/webdav.go b/routers/controllers/webdav.go index 51a058b..48e91c3 100644 --- a/routers/controllers/webdav.go +++ b/routers/controllers/webdav.go @@ -64,17 +64,6 @@ func DeleteWebDAVAccounts(c *gin.Context) { } } -// DeleteWebDAVMounts 删除WebDAV挂载 -func DeleteWebDAVMounts(c *gin.Context) { - var service setting.WebDAVListService - if err := c.ShouldBindUri(&service); err == nil { - res := service.Unmount(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} - // CreateWebDAVAccounts 创建WebDAV账户 func CreateWebDAVAccounts(c *gin.Context) { var service setting.WebDAVAccountCreateService @@ -85,14 +74,3 @@ func CreateWebDAVAccounts(c *gin.Context) { c.JSON(200, ErrorResponse(err)) } } - -// CreateWebDAVMounts 创建WebDAV目录挂载 -func CreateWebDAVMounts(c *gin.Context) { - var service setting.WebDAVMountCreateService - if err := c.ShouldBindJSON(&service); err == nil { - res := service.Create(c, CurrentUser(c)) - c.JSON(200, res) - } else { - c.JSON(200, ErrorResponse(err)) - } -} diff --git a/routers/router.go b/routers/router.go index 2d67e86..bb43135 100644 --- a/routers/router.go +++ b/routers/router.go @@ -132,8 +132,6 @@ func InitMasterRouter() *gin.Engine { middleware.HashID(hashid.UserID), controllers.UserActivate, ) - // 初始化QQ登录 - user.POST("qq", controllers.UserQQLogin) // WebAuthn登陆初始化 user.GET("authn/:username", middleware.IsFunctionEnabled("authn_enabled"), @@ -174,21 +172,6 @@ func InitMasterRouter() *gin.Engine { // 回调接口 callback := v3.Group("callback") { - // QQ互联回调 - callback.POST( - "qq", - controllers.QQCallback, - ) - // PAYJS回调 - callback.POST( - "payjs", - controllers.PayJSCallback, - ) - // 支付宝回调 - callback.POST( - "alipay", - controllers.AlipayCallback, - ) // 远程策略上传回调 callback.POST( "remote/:key", @@ -312,17 +295,6 @@ func InitMasterRouter() *gin.Engine { // 重新加载子服务 admin.POST("mailTest", controllers.AdminSendTestMail) - // 兑换码相关 - redeem := admin.Group("redeem") - { - // 列出激活码 - redeem.POST("list", controllers.AdminListRedeems) - // 生成激活码 - redeem.POST("", controllers.AdminGenerateRedeems) - // 删除激活码 - redeem.DELETE(":id", controllers.AdminDeleteRedeem) - } - // 离线下载相关 aria2 := admin.Group("aria2") { @@ -398,14 +370,6 @@ func InitMasterRouter() *gin.Engine { share.POST("delete", controllers.AdminDeleteShare) } - order := admin.Group("order") - { - // 列出订单 - order.POST("list", controllers.AdminListOrder) - // 删除 - order.POST("delete", controllers.AdminDeleteOrder) - } - download := admin.Group("download") { // 列出任务 @@ -445,8 +409,6 @@ func InitMasterRouter() *gin.Engine { // 用户设置 setting := user.Group("setting") { - // 获取用户可选存储策略 - setting.GET("policies", controllers.UserAvailablePolicies) // 任务队列 setting.GET("tasks", controllers.UserTasks) // 获取当前用户设定 @@ -541,13 +503,6 @@ func InitMasterRouter() *gin.Engine { share.GET("", controllers.ListShare) // 搜索公共分享 share.GET("search", controllers.SearchShare) - // 转存他人分享 - share.POST("save/:id", - middleware.ShareAvailable(), - middleware.CheckShareUnlocked(), - middleware.BeforeShareDownload(), - controllers.SaveShare, - ) // 更新分享属性 share.PATCH(":id", middleware.ShareAvailable(), @@ -571,23 +526,6 @@ func InitMasterRouter() *gin.Engine { tag.DELETE(":id", middleware.HashID(hashid.TagID), controllers.DeleteTag) } - // 增值服务相关 - vas := auth.Group("vas") - { - // 获取容量包及配额信息 - vas.GET("pack", controllers.GetQuota) - // 获取商品信息,同时返回支付信息 - vas.GET("product", controllers.GetProduct) - // 新建支付订单 - vas.POST("order", controllers.NewOrder) - // 查询订单状态 - vas.GET("order/:id", controllers.OrderStatus) - // 获取兑换码信息 - vas.GET("redeem/:code", controllers.GetRedeemInfo) - // 执行兑换 - vas.POST("redeem/:code", controllers.DoRedeem) - } - // WebDAV管理相关 webdav := auth.Group("webdav") { @@ -597,13 +535,6 @@ func InitMasterRouter() *gin.Engine { webdav.POST("accounts", controllers.CreateWebDAVAccounts) // 删除账号 webdav.DELETE("accounts/:id", controllers.DeleteWebDAVAccounts) - // 删除目录挂载 - webdav.DELETE("mount/:id", - middleware.HashID(hashid.FolderID), - controllers.DeleteWebDAVMounts, - ) - // 创建目录挂载 - webdav.POST("mount", controllers.CreateWebDAVMounts) } } diff --git a/service/admin/order.go b/service/admin/order.go deleted file mode 100644 index f5d559f..0000000 --- a/service/admin/order.go +++ /dev/null @@ -1,75 +0,0 @@ -package admin - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/gin-gonic/gin" - "strings" -) - -// OrderBatchService 订单批量操作服务 -type OrderBatchService struct { - ID []uint `json:"id" binding:"min=1"` -} - -// Delete 删除订单 -func (service *OrderBatchService) Delete(c *gin.Context) serializer.Response { - if err := model.DB.Where("id in (?)", service.ID).Delete(&model.Order{}).Error; err != nil { - return serializer.DBErr("无法删除订单", err) - } - return serializer.Response{} -} - -// Orders 列出订单 -func (service *AdminListService) Orders() serializer.Response { - var res []model.Order - total := 0 - - tx := model.DB.Model(&model.Order{}) - if service.OrderBy != "" { - tx = tx.Order(service.OrderBy) - } - - for k, v := range service.Conditions { - tx = tx.Where(k+" = ?", v) - } - - if len(service.Searches) > 0 { - search := "" - for k, v := range service.Searches { - search += k + " like '%" + v + "%' OR " - } - search = strings.TrimSuffix(search, " OR ") - tx = tx.Where(search) - } - - // 计算总数用于分页 - tx.Count(&total) - - // 查询记录 - tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res) - - // 查询对应用户,同时计算HashID - users := make(map[uint]model.User) - for _, file := range res { - users[file.UserID] = model.User{} - } - - userIDs := make([]uint, 0, len(users)) - for k := range users { - userIDs = append(userIDs, k) - } - - var userList []model.User - model.DB.Where("id in (?)", userIDs).Find(&userList) - - for _, v := range userList { - users[v.ID] = v - } - - return serializer.Response{Data: map[string]interface{}{ - "total": total, - "items": res, - "users": users, - }} -} diff --git a/service/admin/policy.go b/service/admin/policy.go index af8bd42..4c293bc 100644 --- a/service/admin/policy.go +++ b/service/admin/policy.go @@ -71,10 +71,7 @@ func (service *PolicyService) Delete() serializer.Response { // 检查用户组使用 var groups []model.Group model.DB.Model(&model.Group{}).Where( - "policies like ? OR policies like ? OR policies like ? OR policies like ?", - fmt.Sprintf("[%d,%%", service.ID), - fmt.Sprintf("%%,%d]", service.ID), - fmt.Sprintf("%%,%d,%%", service.ID), + "policies like ?", fmt.Sprintf("%%[%d]%%", service.ID), ).Find(&groups) diff --git a/service/admin/user.go b/service/admin/user.go index 01120c7..ac753e1 100644 --- a/service/admin/user.go +++ b/service/admin/user.go @@ -71,12 +71,6 @@ func (service *UserBatchService) Delete() serializer.Response { model.DB.Where("user_id = ?", uid).Delete(&model.Download{}) model.DB.Where("user_id = ?", uid).Delete(&model.Task{}) - // 删除订单记录 - model.DB.Where("user_id = ?", uid).Delete(&model.Order{}) - - // 删除容量包 - model.DB.Where("user_id = ?", uid).Delete(&model.StoragePack{}) - // 删除标签 model.DB.Where("user_id = ?", uid).Delete(&model.Tag{}) diff --git a/service/admin/vas.go b/service/admin/vas.go deleted file mode 100644 index 612672e..0000000 --- a/service/admin/vas.go +++ /dev/null @@ -1,98 +0,0 @@ -package admin - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/gofrs/uuid" -) - -// GenerateRedeemsService 兑换码生成服务 -type GenerateRedeemsService struct { - Num int `json:"num" binding:"required,min=1,max=100"` - ID int64 `json:"id"` - Time int `json:"time" binding:"required,min=1"` - Type int `json:"type" binding:"min=0,max=2"` -} - -// SingleIDService 单ID服务 -type SingleIDService struct { - ID uint `uri:"id" binding:"required"` -} - -// DeleteRedeem 删除兑换码 -func (service *SingleIDService) DeleteRedeem() serializer.Response { - if err := model.DB.Where("id = ?", service.ID).Delete(&model.Redeem{}).Error; err != nil { - return serializer.DBErr("无法删除兑换码", err) - } - - return serializer.Response{} -} - -// Generate 生成兑换码 -func (service *GenerateRedeemsService) Generate() serializer.Response { - res := make([]string, service.Num) - redeem := model.Redeem{} - - // 开始事务 - tx := model.DB.Begin() - if err := tx.Error; err != nil { - return serializer.DBErr("无法开启事务", err) - } - - // 创建每个兑换码 - for i := 0; i < service.Num; i++ { - redeem.Model.ID = 0 - redeem.Num = service.Time - redeem.Type = service.Type - redeem.ProductID = service.ID - redeem.Used = false - - // 生成唯一兑换码 - u2, err := uuid.NewV4() - if err != nil { - tx.Rollback() - return serializer.Err(serializer.CodeInternalSetting, "无法生成兑换码", err) - } - - redeem.Code = u2.String() - if err := tx.Create(&redeem).Error; err != nil { - tx.Rollback() - return serializer.DBErr("无法创建兑换码记录", err) - } - - res[i] = redeem.Code - } - - if err := tx.Commit().Error; err != nil { - return serializer.DBErr("无法创建兑换码记录", err) - } - - return serializer.Response{Data: res} - -} - -// Redeems 列出激活码 -func (service *AdminListService) Redeems() serializer.Response { - var res []model.Redeem - total := 0 - - tx := model.DB.Model(&model.Redeem{}) - if service.OrderBy != "" { - tx = tx.Order(service.OrderBy) - } - - for k, v := range service.Conditions { - tx = tx.Where("? = ?", k, v) - } - - // 计算总数用于分页 - tx.Count(&total) - - // 查询记录 - tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res) - - return serializer.Response{Data: map[string]interface{}{ - "total": total, - "items": res, - }} -} diff --git a/service/setting/webdav.go b/service/setting/webdav.go index 0b419a0..7e1931c 100644 --- a/service/setting/webdav.go +++ b/service/setting/webdav.go @@ -2,8 +2,6 @@ package setting import ( model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/filesystem" - "github.com/HFO4/cloudreve/pkg/hashid" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" "github.com/gin-gonic/gin" @@ -30,59 +28,6 @@ type WebDAVMountCreateService struct { Policy string `json:"policy" binding:"required,min=1"` } -// Create 创建目录挂载 -func (service *WebDAVMountCreateService) Create(c *gin.Context, user *model.User) serializer.Response { - // 创建文件系统 - fs, err := filesystem.NewFileSystem(user) - if err != nil { - return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) - } - defer fs.Recycle() - - // 检索要挂载的目录 - exist, folder := fs.IsPathExist(service.Path) - if !exist { - return serializer.Err(serializer.CodeNotFound, "路径不存在", err) - } - - // 检索要挂载的存储策略 - policyID, err := hashid.DecodeHashID(service.Policy, hashid.PolicyID) - if err != nil { - return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err) - } - - // 检查存储策略是否可用 - if policy, err := model.GetPolicyByID(policyID); err != nil || !util.ContainsUint(user.Group.PolicyList, policy.ID) { - return serializer.Err(serializer.CodeNotFound, "存储策略不可用", err) - } - - // 挂载 - if err := folder.Mount(policyID); err != nil { - return serializer.Err(serializer.CodeDBError, "挂载失败", err) - } - - return serializer.Response{ - Data: map[string]interface{}{ - "id": hashid.HashID(folder.ID, hashid.FolderID), - }, - } -} - -// Unmount 取消目录挂载 -func (service *WebDAVListService) Unmount(c *gin.Context, user *model.User) serializer.Response { - folderID, _ := c.Get("object_id") - folder, err := model.GetFoldersByIDs([]uint{folderID.(uint)}, user.ID) - if err != nil || len(folder) == 0 { - return serializer.Err(serializer.CodeNotFound, "目录不存在", err) - } - - if err := folder[0].Mount(0); err != nil { - return serializer.Err(serializer.CodeDBError, "取消挂载失败", err) - } - - return serializer.Response{} -} - // Create 创建WebDAV账户 func (service *WebDAVAccountCreateService) Create(c *gin.Context, user *model.User) serializer.Response { account := model.Webdav{ diff --git a/service/share/visit.go b/service/share/visit.go index a2250fe..03c64a3 100644 --- a/service/share/visit.go +++ b/service/share/visit.go @@ -223,39 +223,6 @@ func (service *Service) CreateDocPreviewSession(c *gin.Context) serializer.Respo return subService.CreateDocPreviewSession(ctx, c) } -// SaveToMyFile 将此分享转存到自己的网盘 -func (service *Service) SaveToMyFile(c *gin.Context) serializer.Response { - shareCtx, _ := c.Get("share") - share := shareCtx.(*model.Share) - userCtx, _ := c.Get("user") - user := userCtx.(*model.User) - - // 不能转存自己的文件 - if share.UserID == user.ID { - return serializer.Err(serializer.CodePolicyNotAllowed, "不能转存自己的分享", nil) - } - - // 创建文件系统 - fs, err := filesystem.NewFileSystem(user) - if err != nil { - return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err) - } - defer fs.Recycle() - - // 重设文件系统处理目标为源文件 - err = fs.SetTargetByInterface(share.Source()) - if err != nil { - return serializer.Err(serializer.CodePolicyNotAllowed, "源文件不存在", err) - } - - err = fs.SaveTo(context.Background(), service.Path) - if err != nil { - return serializer.Err(serializer.CodeNotSet, err.Error(), err) - } - - return serializer.Response{} -} - // List 列出分享的目录下的对象 func (service *Service) List(c *gin.Context) serializer.Response { shareCtx, _ := c.Get("share") diff --git a/service/user/login.go b/service/user/login.go index f3c38b5..3578f92 100644 --- a/service/user/login.go +++ b/service/user/login.go @@ -135,7 +135,6 @@ func (service *UserLoginService) Login(c *gin.Context) serializer.Response { expectedUser, err := model.GetUserByEmail(service.UserName) if model.IsTrueVal(isCaptchaRequired) { - // TODO 验证码校验 captchaID := util.GetSession(c, "captchaID") util.DeleteSession(c, "captchaID") if captchaID == nil || !base64Captcha.VerifyCaptcha(captchaID.(string), service.CaptchaCode) { diff --git a/service/user/setting.go b/service/user/setting.go index 59cb399..4e1a02a 100644 --- a/service/user/setting.go +++ b/service/user/setting.go @@ -4,8 +4,6 @@ import ( "crypto/md5" "fmt" model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/hashid" - "github.com/HFO4/cloudreve/pkg/qq" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" "github.com/gin-gonic/gin" @@ -14,8 +12,6 @@ import ( "net/url" "os" "path/filepath" - "strings" - "time" ) // SettingService 通用设置服务 @@ -47,14 +43,6 @@ type ChangerNick struct { Nick string `json:"nick" binding:"required,min=1,max=255"` } -// VIPUnsubscribe 用户组解约服务 -type VIPUnsubscribe struct { -} - -// QQBind QQ互联服务 -type QQBind struct { -} - // PolicyChange 更改存储策略 type PolicyChange struct { ID string `json:"id" binding:"required"` @@ -173,77 +161,6 @@ func (service *HomePage) Update(c *gin.Context, user *model.User) serializer.Res return serializer.Response{} } -// Update 更改用户偏好的存储策略 -func (service *PolicyChange) Update(c *gin.Context, user *model.User) serializer.Response { - // 取得存储策略的ID - rawID, err := hashid.DecodeHashID(service.ID, hashid.PolicyID) - if err != nil { - return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err) - } - - // 用户是否可以切换到此存储策略 - if !util.ContainsUint(user.Group.PolicyList, rawID) { - return serializer.Err(serializer.CodeNoPermissionErr, "存储策略不可用", nil) - } - - // 查找存储策略 - if _, err := model.GetPolicyByID(rawID); err != nil { - return serializer.Err(serializer.CodeNoPermissionErr, "存储策略不可用", nil) - } - - // 切换存储策略 - user.OptionsSerialized.PreferredPolicy = rawID - if err := user.UpdateOptions(); err != nil { - return serializer.DBErr("存储策略切换失败", err) - } - - return serializer.Response{} -} - -// Update 绑定或解绑QQ -func (service *QQBind) Update(c *gin.Context, user *model.User) serializer.Response { - // 解除绑定 - if user.OpenID != "" { - // 只通过QQ登录的用户无法解除绑定 - if strings.HasSuffix(user.Email, "@login.qq.com") { - return serializer.Err(serializer.CodeNoPermissionErr, "无法解绑此账号", nil) - } - - if err := user.Update(map[string]interface{}{"open_id": ""}); err != nil { - return serializer.DBErr("接除绑定失败", err) - } - return serializer.Response{ - Data: "", - } - } - - // 新建绑定 - res, err := qq.NewLoginRequest() - if err != nil { - return serializer.Err(serializer.CodeNotSet, "无法使用QQ登录", err) - } - - // 设定QQ登录会话Secret - util.SetSession(c, map[string]interface{}{"qq_login_secret": res.SecretKey}) - - return serializer.Response{ - Data: res.URL, - } -} - -// Update 用户组解约 -func (service *VIPUnsubscribe) Update(c *gin.Context, user *model.User) serializer.Response { - if user.GroupExpires != nil { - timeNow := time.Now() - if time.Now().Before(*user.GroupExpires) { - if err := user.Update(map[string]interface{}{"group_expires": &timeNow}); err != nil { - return serializer.DBErr("解约失败", err) - } - } - } - return serializer.Response{} -} - // Update 更改昵称 func (service *ChangerNick) Update(c *gin.Context, user *model.User) serializer.Response { if err := user.Update(map[string]interface{}{"nick": service.Nick}); err != nil { @@ -322,46 +239,16 @@ func (service *SettingListService) ListTasks(c *gin.Context, user *model.User) s return serializer.BuildTaskList(tasks, total) } -// Policy 获取用户存储策略设置 -func (service *SettingService) Policy(c *gin.Context, user *model.User) serializer.Response { - // 取得用户可用存储策略 - available := make([]model.Policy, 0, len(user.Group.PolicyList)) - for _, id := range user.Group.PolicyList { - if policy, err := model.GetPolicyByID(id); err == nil { - available = append(available, policy) - } - } - - // 取得用户当前策略 - current := user.Policy - - return serializer.BuildPolicySettingRes(available, ¤t) -} - // Settings 获取用户设定 func (service *SettingService) Settings(c *gin.Context, user *model.User) serializer.Response { - // 取得存储策略设定 - policy := service.Policy(c, user) - - // 用户组有效期 - var groupExpires int64 - if user.GroupExpires != nil { - if expires := user.GroupExpires.Unix() - time.Now().Unix(); expires > 0 { - groupExpires = user.GroupExpires.Unix() - } - } - return serializer.Response{ Data: map[string]interface{}{ - "policy": policy.Data.(map[string]interface{}), - "uid": user.ID, - "qq": user.OpenID != "", - "homepage": !user.OptionsSerialized.ProfileOff, - "two_factor": user.TwoFactor != "", - "prefer_theme": user.OptionsSerialized.PreferredTheme, - "themes": model.GetSettingByName("themes"), - "group_expires": groupExpires, - "authn": serializer.BuildWebAuthnList(user.WebAuthnCredentials()), + "uid": user.ID, + "homepage": !user.OptionsSerialized.ProfileOff, + "two_factor": user.TwoFactor != "", + "prefer_theme": user.OptionsSerialized.PreferredTheme, + "themes": model.GetSettingByName("themes"), + "authn": serializer.BuildWebAuthnList(user.WebAuthnCredentials()), }, } } diff --git a/service/vas/purchase.go b/service/vas/purchase.go deleted file mode 100644 index a1b3864..0000000 --- a/service/vas/purchase.go +++ /dev/null @@ -1,219 +0,0 @@ -package vas - -import ( - "encoding/json" - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/payment" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/gin-gonic/gin" -) - -// CreateOrderService 创建订单服务 -type CreateOrderService struct { - Action string `json:"action" binding:"required,eq=group|eq=pack|eq=score"` - Method string `json:"method" binding:"required,eq=alipay|eq=score|eq=payjs"` - ID int64 `json:"id" binding:"required"` - Num int `json:"num" binding:"required,min=1"` -} - -// RedeemService 兑换服务 -type RedeemService struct { - Code string `uri:"code" binding:"required,max=64"` -} - -// OrderService 订单查询 -type OrderService struct { - ID string `uri:"id" binding:"required"` -} - -// Status 查询订单状态 -func (service *OrderService) Status(c *gin.Context, user *model.User) serializer.Response { - order, _ := model.GetOrderByNo(service.ID) - if order == nil || order.UserID != user.ID { - return serializer.Err(serializer.CodeNotFound, "订单不存在", nil) - } - - return serializer.Response{Data: order.Status} -} - -// Redeem 开始兑换 -func (service *RedeemService) Redeem(c *gin.Context, user *model.User) serializer.Response { - redeem, err := model.GetAvailableRedeem(service.Code) - if err != nil { - return serializer.Err(serializer.CodeDBError, "兑换码无效", err) - } - - // 取得当前商品信息 - packs, groups, err := decodeProductInfo() - if err != nil { - return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err) - } - - // 查找要购买的商品 - var ( - pack *serializer.PackProduct - group *serializer.GroupProducts - ) - if redeem.Type == model.GroupOrderType { - for _, v := range groups { - if v.ID == redeem.ProductID { - group = &v - break - } - } - - if group == nil { - return serializer.Err(serializer.CodeNotFound, "商品已失效", err) - } - - } else if redeem.Type == model.PackOrderType { - for _, v := range packs { - if v.ID == redeem.ProductID { - pack = &v - break - } - } - - if pack == nil { - return serializer.Err(serializer.CodeNotFound, "商品已失效", err) - } - - } - - err = payment.GiveProduct(user, pack, group, redeem.Num) - if err != nil { - return serializer.Err(serializer.CodeNotSet, "兑换失败", err) - } - - redeem.Use() - - return serializer.Response{} - -} - -// Query 检查兑换码信息 -func (service *RedeemService) Query(c *gin.Context) serializer.Response { - redeem, err := model.GetAvailableRedeem(service.Code) - if err != nil { - return serializer.Err(serializer.CodeDBError, "兑换码无效", err) - } - - var ( - name = "积分" - productTime int64 - ) - if redeem.Type != model.ScoreOrderType { - packs, groups, err := decodeProductInfo() - if err != nil { - return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err) - } - if redeem.Type == model.GroupOrderType { - for _, v := range groups { - if v.ID == redeem.ProductID { - name = v.Name - productTime = v.Time - break - } - } - } else { - for _, v := range packs { - if v.ID == redeem.ProductID { - name = v.Name - productTime = v.Time - break - } - } - } - - if name == "积分" { - return serializer.Err(serializer.CodeNotFound, "商品已失效", err) - } - - } - - return serializer.Response{ - Data: struct { - Name string `json:"name"` - Type int `json:"type"` - Num int `json:"num"` - Time int64 `json:"time"` - }{ - name, redeem.Type, redeem.Num, productTime, - }, - } -} - -// Create 创建新订单 -func (service *CreateOrderService) Create(c *gin.Context, user *model.User) serializer.Response { - // 取得当前商品信息 - packs, groups, err := decodeProductInfo() - if err != nil { - return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err) - } - - // 查找要购买的商品 - var ( - pack *serializer.PackProduct - group *serializer.GroupProducts - ) - if service.Action == "group" { - for _, v := range groups { - if v.ID == service.ID { - group = &v - break - } - } - } else if service.Action == "pack" { - for _, v := range packs { - if v.ID == service.ID { - pack = &v - break - } - } - } - - // 购买积分 - if pack == nil && group == nil { - if service.Method == "score" { - return serializer.Err(serializer.CodeNotFound, "不支持此支付方式", nil) - } - } - - // 创建订单 - res, err := payment.NewOrder(pack, group, service.Num, service.Method, user) - if err != nil { - return serializer.Err(serializer.CodeNotSet, err.Error(), err) - } - - return serializer.Response{Data: res} - -} - -// Products 获取商品信息 -func (service *GeneralVASService) Products(c *gin.Context, user *model.User) serializer.Response { - options := model.GetSettingByNames("alipay_enabled", "payjs_enabled", "score_price") - scorePrice := model.GetIntSetting("score_price", 0) - packs, groups, err := decodeProductInfo() - if err != nil { - return serializer.Err(serializer.CodeInternalSetting, "无法解析商品设置", err) - } - - return serializer.BuildProductResponse(groups, packs, options["alipay_enabled"] == "1", options["payjs_enabled"] == "1", scorePrice) -} - -func decodeProductInfo() ([]serializer.PackProduct, []serializer.GroupProducts, error) { - options := model.GetSettingByNames("pack_data", "group_sell_data", "alipay_enabled", "payjs_enabled") - - var ( - packs []serializer.PackProduct - groups []serializer.GroupProducts - ) - if err := json.Unmarshal([]byte(options["pack_data"]), &packs); err != nil { - return nil, nil, err - } - if err := json.Unmarshal([]byte(options["group_sell_data"]), &groups); err != nil { - return nil, nil, err - } - - return packs, groups, nil -} diff --git a/service/vas/qq.go b/service/vas/qq.go deleted file mode 100644 index c290e33..0000000 --- a/service/vas/qq.go +++ /dev/null @@ -1,107 +0,0 @@ -package vas - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/qq" - "github.com/HFO4/cloudreve/pkg/request" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/HFO4/cloudreve/pkg/thumb" - "github.com/HFO4/cloudreve/pkg/util" - "github.com/gin-gonic/gin" -) - -// QQCallbackService QQ互联回调处理服务 -type QQCallbackService struct { - Code string `json:"code" binding:"required"` - State string `json:"state" binding:"required"` -} - -// Callback 处理QQ互联回调 -func (service *QQCallbackService) Callback(c *gin.Context, user *model.User) serializer.Response { - - state := util.GetSession(c, "qq_login_secret") - if stateStr, ok := state.(string); !ok || stateStr != service.State { - return serializer.Err(serializer.CodeSignExpired, "请求过期,请重试", nil) - } - util.DeleteSession(c, "qq_login_secret") - - // 获取OpenID - credential, err := qq.Callback(service.Code) - if err != nil { - return serializer.Err(serializer.CodeNotSet, "无法获取登录状态", err) - } - - // 如果已登录,则绑定已有用户 - if user != nil { - - if user.OpenID != "" { - return serializer.Err(serializer.CodeCallbackError, "您已绑定了QQ账号,请先解除绑定", nil) - } - if err := user.Update(map[string]interface{}{"open_id": credential.OpenID}); err != nil { - return serializer.DBErr("绑定失败", err) - } - return serializer.Response{ - Data: "/setting", - } - - } - - // 未登录,尝试查找用户 - if expectedUser, err := model.GetActiveUserByOpenID(credential.OpenID); err == nil { - // 用户绑定了此QQ,设定为登录状态 - util.SetSession(c, map[string]interface{}{ - "user_id": expectedUser.ID, - }) - res := serializer.BuildUserResponse(expectedUser) - res.Code = 203 - return res - - } - - // 无匹配用户,创建新用户 - if !model.IsTrueVal(model.GetSettingByName("qq_direct_login")) { - return serializer.Err(serializer.CodeNoPermissionErr, "此QQ号未绑定任何账号", nil) - } - - // 获取用户信息 - userInfo, err := qq.GetUserInfo(credential) - if err != nil { - return serializer.Err(serializer.CodeNotSet, "无法获取用户信息", err) - } - - // 生成邮箱地址 - fakeEmail := util.RandStringRunes(16) + "@login.qq.com" - - // 创建用户 - defaultGroup := model.GetIntSetting("default_group", 2) - - newUser := model.NewUser() - newUser.Email = fakeEmail - newUser.Nick = userInfo.Nick - newUser.SetPassword("") - newUser.Status = model.Active - newUser.GroupID = uint(defaultGroup) - newUser.OpenID = credential.OpenID - newUser.Avatar = "file" - - // 创建用户 - if err := model.DB.Create(&newUser).Error; err != nil { - return serializer.DBErr("此邮箱已被使用", err) - } - - // 下载头像 - r := request.HTTPClient{} - rawAvatar := r.Request("GET", userInfo.Avatar, nil) - if avatar, err := thumb.NewThumbFromFile(rawAvatar.Response.Body, "avatar.jpg"); err == nil { - avatar.CreateAvatar(newUser.ID) - } - - // 登录 - util.SetSession(c, map[string]interface{}{"user_id": newUser.ID}) - - newUser, _ = model.GetActiveUserByID(newUser.ID) - - res := serializer.BuildUserResponse(newUser) - res.Code = 203 - return res -} diff --git a/service/vas/quota.go b/service/vas/quota.go deleted file mode 100644 index 294c0df..0000000 --- a/service/vas/quota.go +++ /dev/null @@ -1,17 +0,0 @@ -package vas - -import ( - model "github.com/HFO4/cloudreve/models" - "github.com/HFO4/cloudreve/pkg/serializer" - "github.com/gin-gonic/gin" -) - -// GeneralVASService 通用增值服务 -type GeneralVASService struct { -} - -// Quota 获取容量配额信息 -func (service *GeneralVASService) Quota(c *gin.Context, user *model.User) serializer.Response { - packs := user.GetAvailableStoragePacks() - return serializer.BuildUserQuotaResponse(user, packs) -}