From 2471dacec18958a71777a8cc4781629cdb7b3667 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Sun, 1 Mar 2020 17:57:18 +0800 Subject: [PATCH] Feat: OneDrive OAuth --- routers/controllers/admin.go | 13 ++++++++++- routers/controllers/callback.go | 11 +++++++++ routers/router.go | 7 ++++++ service/admin/policy.go | 30 +++++++++++++++++++++++- service/callback/oauth.go | 41 +++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 service/callback/oauth.go diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index 445497d..bfd28b8 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -184,7 +184,7 @@ func AdminAddCORS(c *gin.Context) { } } -// AdminAddCORS 创建跨域策略 +// AdminAddSCF 创建回调函数 func AdminAddSCF(c *gin.Context) { var service admin.PolicyService if err := c.ShouldBindJSON(&service); err == nil { @@ -194,3 +194,14 @@ func AdminAddSCF(c *gin.Context) { c.JSON(200, ErrorResponse(err)) } } + +// AdminOneDriveOAuth 获取 OneDrive OAuth URL +func AdminOneDriveOAuth(c *gin.Context) { + var service admin.PolicyService + if err := c.ShouldBindUri(&service); err == nil { + res := service.GetOAuth(c) + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} diff --git a/routers/controllers/callback.go b/routers/controllers/callback.go index c74796e..47afad1 100644 --- a/routers/controllers/callback.go +++ b/routers/controllers/callback.go @@ -77,6 +77,17 @@ func OneDriveCallback(c *gin.Context) { } } +// OneDriveOAuth OneDrive 授权回调 +func OneDriveOAuth(c *gin.Context) { + var callbackBody callback.OneDriveOauthService + if err := c.ShouldBindQuery(&callbackBody); err == nil { + res := callbackBody.Auth(c) + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + // COSCallback COS上传完成客户端回调 func COSCallback(c *gin.Context) { var callbackBody callback.COSCallback diff --git a/routers/router.go b/routers/router.go index 1abe503..0259ef2 100644 --- a/routers/router.go +++ b/routers/router.go @@ -220,6 +220,11 @@ func InitMasterRouter() *gin.Engine { middleware.OneDriveCallbackAuth(), controllers.OneDriveCallback, ) + // 文件上传完成 + onedrive.GET( + "auth", + controllers.OneDriveOAuth, + ) } // 腾讯云COS策略上传回调 callback.GET( @@ -338,6 +343,8 @@ func InitMasterRouter() *gin.Engine { policy.POST("cors", controllers.AdminAddCORS) // 创建COS回调函数 policy.POST("scf", controllers.AdminAddSCF) + // 获取 OneDrive OAuth URL + policy.GET(":id/oauth", controllers.AdminOneDriveOAuth) } } diff --git a/service/admin/policy.go b/service/admin/policy.go index bc7187c..2708f46 100644 --- a/service/admin/policy.go +++ b/service/admin/policy.go @@ -2,16 +2,20 @@ package admin import ( "bytes" + "context" "encoding/json" "fmt" model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/auth" + "github.com/HFO4/cloudreve/pkg/cache" "github.com/HFO4/cloudreve/pkg/conf" "github.com/HFO4/cloudreve/pkg/filesystem/driver/cos" + "github.com/HFO4/cloudreve/pkg/filesystem/driver/onedrive" "github.com/HFO4/cloudreve/pkg/filesystem/driver/oss" "github.com/HFO4/cloudreve/pkg/request" "github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/util" + "github.com/gin-gonic/gin" cossdk "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" @@ -43,10 +47,34 @@ type AddPolicyService struct { // PolicyService 存储策略ID服务 type PolicyService struct { - ID uint `json:"id" binding:"required"` + ID uint `uri:"id" json:"id" binding:"required"` Region string `json:"region"` } +// GetOAuth 获取 OneDrive OAuth 地址 +func (service *PolicyService) GetOAuth(c *gin.Context) serializer.Response { + policy, err := model.GetPolicyByID(service.ID) + if err != nil || policy.Type != "onedrive" { + return serializer.Err(serializer.CodeNotFound, "存储策略不存在", nil) + } + + client, err := onedrive.NewClient(&policy) + if err != nil { + return serializer.Err(serializer.CodeInternalSetting, "无法初始化 OneDrive 客户端", err) + } + + util.SetSession(c, map[string]interface{}{ + "onedrive_oauth_policy": policy.ID, + }) + + cache.Deletes([]string{policy.BucketName}, "onedrive_") + + return serializer.Response{Data: client.OAuthURL(context.Background(), []string{ + "offline_access", + "files.readwrite.all", + })} +} + // AddSCF 创建回调云函数 func (service *PolicyService) AddSCF() serializer.Response { policy, err := model.GetPolicyByID(service.ID) diff --git a/service/callback/oauth.go b/service/callback/oauth.go new file mode 100644 index 0000000..aa0c626 --- /dev/null +++ b/service/callback/oauth.go @@ -0,0 +1,41 @@ +package callback + +import ( + "context" + model "github.com/HFO4/cloudreve/models" + "github.com/HFO4/cloudreve/pkg/filesystem/driver/onedrive" + "github.com/HFO4/cloudreve/pkg/serializer" + "github.com/HFO4/cloudreve/pkg/util" + "github.com/gin-gonic/gin" +) + +// OneDriveOauthService OneDrive 授权回调服务 +type OneDriveOauthService struct { + Code string `form:"code" binding:"required"` +} + +// Auth 更新认证信息 +func (service *OneDriveOauthService) Auth(c *gin.Context) serializer.Response { + policyId := util.GetSession(c, "onedrive_oauth_policy").(uint) + policy, err := model.GetPolicyByID(policyId) + if err != nil { + return serializer.Err(serializer.CodeNotFound, "存储策略不存在", nil) + } + + client, err := onedrive.NewClient(&policy) + if err != nil { + return serializer.Err(serializer.CodeInternalSetting, "无法初始化 OneDrive 客户端", err) + } + + credential, err := client.ObtainToken(context.Background(), onedrive.WithCode(service.Code)) + if err != nil { + return serializer.Err(serializer.CodeInternalSetting, "AccessToken 获取失败", err) + } + + // 更新存储策略的 RefreshToken + if err := client.Policy.UpdateAccessKey(credential.RefreshToken); err != nil { + return serializer.DBErr("无法更新 RefreshToken", err) + } + + return serializer.Response{} +}