115 lines
3.9 KiB
Go
115 lines
3.9 KiB
Go
package nextcloud
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/data"
|
|
"github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider"
|
|
"github.com/mayswind/ezbookkeeping/pkg/auth/oauth2/provider/common"
|
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
|
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
|
)
|
|
|
|
type nextcloudUserInfoResponse struct {
|
|
OCS *struct {
|
|
Meta *struct {
|
|
Status string `json:"status"`
|
|
StatusCode int `json:"statuscode"`
|
|
} `json:"meta"`
|
|
Data *struct {
|
|
ID string `json:"id"`
|
|
Email string `json:"email"`
|
|
DisplayName string `json:"display-name"`
|
|
} `json:"data"`
|
|
} `json:"ocs"`
|
|
}
|
|
|
|
// NextcloudOAuth2DataSource represents Nextcloud OAuth 2.0 data source
|
|
type NextcloudOAuth2DataSource struct {
|
|
common.CommonOAuth2DataSource
|
|
baseUrl string
|
|
}
|
|
|
|
// GetAuthUrl returns the authentication url of the Nextcloud data source
|
|
func (s *NextcloudOAuth2DataSource) GetAuthUrl() string {
|
|
// Reference: https://docs.nextcloud.com/server/stable/developer_manual/_static/openapi.html#/operations/oauth2-login_redirector-authorize
|
|
return s.baseUrl + "apps/oauth2/authorize"
|
|
}
|
|
|
|
// GetTokenUrl returns the token url of the Nextcloud data source
|
|
func (s *NextcloudOAuth2DataSource) GetTokenUrl() string {
|
|
// Reference: https://docs.nextcloud.com/server/stable/developer_manual/_static/openapi.html#/operations/oauth2-oauth_api-get-token
|
|
return s.baseUrl + "apps/oauth2/api/v1/token"
|
|
}
|
|
|
|
// GetUserInfoRequest returns the user info request of the Nextcloud data source
|
|
func (s *NextcloudOAuth2DataSource) GetUserInfoRequest() (*http.Request, error) {
|
|
// Reference: https://docs.nextcloud.com/server/stable/developer_manual/_static/openapi.html#/operations/provisioning_api-users-get-current-user
|
|
req, err := http.NewRequest("GET", s.baseUrl+"ocs/v2.php/cloud/user", nil)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("OCS-APIRequest", "true")
|
|
return req, nil
|
|
}
|
|
|
|
// GetScopes returns the scopes required by the Nextcloud provider
|
|
func (s *NextcloudOAuth2DataSource) GetScopes() []string {
|
|
return []string{}
|
|
}
|
|
|
|
// ParseUserInfo returns the user info by parsing the response body
|
|
func (s *NextcloudOAuth2DataSource) ParseUserInfo(c core.Context, body []byte, oauth2Client *http.Client) (*data.OAuth2UserInfo, error) {
|
|
userInfoResp := &nextcloudUserInfoResponse{}
|
|
err := json.Unmarshal(body, &userInfoResp)
|
|
|
|
if err != nil {
|
|
log.Warnf(c, "[nextcloud_oauth2_datasource.ParseUserInfo] failed to parse user info response body, because %s", err.Error())
|
|
return nil, errs.ErrCannotRetrieveUserInfo
|
|
}
|
|
|
|
if userInfoResp.OCS == nil || userInfoResp.OCS.Meta == nil || userInfoResp.OCS.Data == nil {
|
|
log.Warnf(c, "[nextcloud_oauth2_datasource.ParseUserInfo] invalid user info response body")
|
|
return nil, errs.ErrCannotRetrieveUserInfo
|
|
}
|
|
|
|
if userInfoResp.OCS.Meta.StatusCode != 200 {
|
|
log.Warnf(c, "[nextcloud_oauth2_datasource.ParseUserInfo] user info response status code is %d", userInfoResp.OCS.Meta.StatusCode)
|
|
return nil, errs.ErrCannotRetrieveUserInfo
|
|
}
|
|
|
|
if userInfoResp.OCS.Data.ID == "" {
|
|
log.Warnf(c, "[nextcloud_oauth2_datasource.ParseUserInfo] user info id is empty")
|
|
return nil, errs.ErrCannotRetrieveUserInfo
|
|
}
|
|
|
|
return &data.OAuth2UserInfo{
|
|
UserName: userInfoResp.OCS.Data.ID,
|
|
Email: userInfoResp.OCS.Data.Email,
|
|
NickName: userInfoResp.OCS.Data.DisplayName,
|
|
}, nil
|
|
}
|
|
|
|
// NewNextcloudOAuth2Provider creates a new Nextcloud OAuth 2.0 provider instance
|
|
func NewNextcloudOAuth2Provider(config *settings.Config, redirectUrl string) (provider.OAuth2Provider, error) {
|
|
if len(config.OAuth2NextcloudBaseUrl) < 1 {
|
|
return nil, errs.ErrInvalidOAuth2Config
|
|
}
|
|
|
|
baseUrl := config.OAuth2NextcloudBaseUrl
|
|
|
|
if baseUrl[len(baseUrl)-1] != '/' {
|
|
baseUrl += "/"
|
|
}
|
|
|
|
return common.NewCommonOAuth2Provider(config, redirectUrl, &NextcloudOAuth2DataSource{
|
|
baseUrl: baseUrl,
|
|
}), nil
|
|
}
|