123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- package onedrive
- import (
- "errors"
- "fmt"
- "net/url"
- "strings"
- "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
- "github.com/IceWhaleTech/CasaOS/drivers/base"
- "go.uber.org/zap"
- )
- var (
- client_id = "private build"
- client_secret = "private build"
- )
- var onedriveHostMap = map[string]Host{
- "global": {
- Oauth: "https://login.microsoftonline.com",
- Api: "https://graph.microsoft.com",
- },
- "cn": {
- Oauth: "https://login.chinacloudapi.cn",
- Api: "https://microsoftgraph.chinacloudapi.cn",
- },
- "us": {
- Oauth: "https://login.microsoftonline.us",
- Api: "https://graph.microsoft.us",
- },
- "de": {
- Oauth: "https://login.microsoftonline.de",
- Api: "https://graph.microsoft.de",
- },
- }
- func EncodePath(path string, all ...bool) string {
- seg := strings.Split(path, "/")
- toReplace := []struct {
- Src string
- Dst string
- }{
- {Src: "%", Dst: "%25"},
- {"%", "%25"},
- {"?", "%3F"},
- {"#", "%23"},
- }
- for i := range seg {
- if len(all) > 0 && all[0] {
- seg[i] = url.PathEscape(seg[i])
- } else {
- for j := range toReplace {
- seg[i] = strings.ReplaceAll(seg[i], toReplace[j].Src, toReplace[j].Dst)
- }
- }
- }
- return strings.Join(seg, "/")
- }
- func (d *Onedrive) GetMetaUrl(auth bool, path string) string {
- host := onedriveHostMap[d.Region]
- path = EncodePath(path, true)
- if auth {
- return host.Oauth
- }
- if d.IsSharepoint {
- if path == "/" || path == "\\" {
- return fmt.Sprintf("%s/v1.0/sites/%s/drive/root", host.Api, d.SiteId)
- } else {
- return fmt.Sprintf("%s/v1.0/sites/%s/drive/root:%s:", host.Api, d.SiteId, path)
- }
- } else {
- if path == "/" || path == "\\" {
- return fmt.Sprintf("%s/v1.0/me/drive/root", host.Api)
- } else {
- return fmt.Sprintf("%s/v1.0/me/drive/root:%s:", host.Api, path)
- }
- }
- }
- func (d *Onedrive) refreshToken() error {
- var err error
- for i := 0; i < 3; i++ {
- err = d._refreshToken()
- if err == nil {
- break
- }
- }
- return err
- }
- func (d *Onedrive) getRefreshToken() error {
- url := d.GetMetaUrl(true, "") + "/common/oauth2/v2.0/token"
- var resp base.TokenResp
- var e TokenErr
- res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
- "grant_type": "authorization_code",
- "client_id": d.ClientID,
- "client_secret": d.ClientSecret,
- "code": d.Code,
- "redirect_uri": d.RedirectUri,
- }).Post(url)
- if err != nil {
- return err
- }
- logger.Info("get refresh token", zap.String("res", res.String()))
- if e.Error != "" {
- return fmt.Errorf("%s", e.ErrorDescription)
- }
- if resp.RefreshToken == "" {
- return errors.New("refresh token is empty")
- }
- d.RefreshToken, d.AccessToken = resp.RefreshToken, resp.AccessToken
- return nil
- }
- func (d *Onedrive) _refreshToken() error {
- url := d.GetMetaUrl(true, "") + "/common/oauth2/v2.0/token"
- var resp base.TokenResp
- var e TokenErr
- res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
- "grant_type": "refresh_token",
- "client_id": d.ClientID,
- "client_secret": d.ClientSecret,
- "redirect_uri": d.RedirectUri,
- "refresh_token": d.RefreshToken,
- }).Post(url)
- if err != nil {
- return err
- }
- logger.Info("get refresh token", zap.String("res", res.String()))
- if e.Error != "" {
- return fmt.Errorf("%s", e.ErrorDescription)
- }
- if resp.RefreshToken == "" {
- return errors.New("refresh token is empty")
- }
- d.RefreshToken, d.AccessToken = resp.RefreshToken, resp.AccessToken
- return nil
- }
- func (d *Onedrive) Request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
- req := base.RestyClient.R()
- req.SetHeader("Authorization", "Bearer "+d.AccessToken)
- if callback != nil {
- callback(req)
- }
- if resp != nil {
- req.SetResult(resp)
- }
- var e RespErr
- req.SetError(&e)
- res, err := req.Execute(method, url)
- if err != nil {
- return nil, err
- }
- if e.Error.Code != "" {
- if e.Error.Code == "InvalidAuthenticationToken" {
- err = d.refreshToken()
- if err != nil {
- return nil, err
- }
- return d.Request(url, method, callback, resp)
- }
- return nil, errors.New(e.Error.Message)
- }
- return res.Body(), nil
- }
- func GetConfig() Onedrive {
- config := Onedrive{}
- config.ClientID = client_id
- config.ClientSecret = client_secret
- config.RootFolderID = "/"
- config.AuthUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=" + client_id + "&response_type=code&redirect_uri=https%3A%2F%2Fcloudoauth.files.casaos.app&scope=offline_access+files.readwrite.all&state=${HOST}%2Fv1%2Frecover%2FOnedrive"
- config.Icon = "./img/driver/OneDrive.svg"
- config.Region = "global"
- config.RedirectUri = "https://cloudoauth.files.casaos.app"
- return config
- }
|