mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 20:50:19 +08:00
feat: Dingtalk provider supports fetching organization email (#1636)
* feat(dingtalk): try to get email from corp app * chore: format codes * chore: format codes (#1) * Delete .fleet directory * fix: fix syntax errors * Update dingtalk.go * style: fmt codes with gofumpt --------- Co-authored-by: aidenlu <aiden_lu@wochacha.com>
This commit is contained in:
@ -15,11 +15,9 @@
|
|||||||
package idp
|
package idp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -170,10 +168,18 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
Email: dtUserInfo.Email,
|
Email: dtUserInfo.Email,
|
||||||
AvatarUrl: dtUserInfo.AvatarUrl,
|
AvatarUrl: dtUserInfo.AvatarUrl,
|
||||||
}
|
}
|
||||||
isUserInOrg, err := idp.isUserInOrg(userInfo.UnionId)
|
|
||||||
if !isUserInOrg {
|
corpAccessToken := idp.getInnerAppAccessToken()
|
||||||
|
userId, err := idp.getUserId(userInfo.UnionId, corpAccessToken)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
corpEmail, err := idp.getUserCorpEmail(userId, corpAccessToken)
|
||||||
|
if err == nil && corpEmail != "" {
|
||||||
|
userInfo.Email = corpEmail
|
||||||
|
}
|
||||||
|
|
||||||
return &userInfo, nil
|
return &userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,23 +208,14 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
||||||
appKey := idp.Config.ClientID
|
|
||||||
appSecret := idp.Config.ClientSecret
|
|
||||||
body := make(map[string]string)
|
body := make(map[string]string)
|
||||||
body["appKey"] = appKey
|
body["appKey"] = idp.Config.ClientID
|
||||||
body["appSecret"] = appSecret
|
body["appSecret"] = idp.Config.ClientSecret
|
||||||
bodyData, err := json.Marshal(body)
|
respBytes, err := idp.postWithBody(body, "https://api.dingtalk.com/v1.0/oauth2/accessToken")
|
||||||
if err != nil {
|
|
||||||
log.Println(err.Error())
|
|
||||||
}
|
|
||||||
reader := bytes.NewReader(bodyData)
|
|
||||||
request, err := http.NewRequest("POST", "https://api.dingtalk.com/v1.0/oauth2/accessToken", reader)
|
|
||||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
|
||||||
resp, err := idp.Client.Do(request)
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
ExpireIn int `json:"expireIn"`
|
ExpireIn int `json:"expireIn"`
|
||||||
AccessToken string `json:"accessToken"`
|
AccessToken string `json:"accessToken"`
|
||||||
@ -230,34 +227,53 @@ func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
|||||||
return data.AccessToken
|
return data.AccessToken
|
||||||
}
|
}
|
||||||
|
|
||||||
func (idp *DingTalkIdProvider) isUserInOrg(unionId string) (bool, error) {
|
func (idp *DingTalkIdProvider) getUserId(unionId string, accessToken string) (string, error) {
|
||||||
body := make(map[string]string)
|
body := make(map[string]string)
|
||||||
body["unionid"] = unionId
|
body["unionid"] = unionId
|
||||||
bodyData, err := json.Marshal(body)
|
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
return "", err
|
||||||
}
|
|
||||||
reader := bytes.NewReader(bodyData)
|
|
||||||
accessToken := idp.getInnerAppAccessToken()
|
|
||||||
request, _ := http.NewRequest("POST", "https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+accessToken, reader)
|
|
||||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
|
||||||
resp, err := idp.Client.Do(request)
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
ErrCode int `json:"errcode"`
|
ErrCode int `json:"errcode"`
|
||||||
ErrMessage string `json:"errmsg"`
|
ErrMessage string `json:"errmsg"`
|
||||||
|
Result struct {
|
||||||
|
UserId string `json:"userid"`
|
||||||
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(respBytes, &data)
|
err = json.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
return "", err
|
||||||
}
|
}
|
||||||
if data.ErrCode == 60121 {
|
if data.ErrCode == 60121 {
|
||||||
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
return "", fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
||||||
} else if data.ErrCode != 0 {
|
} else if data.ErrCode != 0 {
|
||||||
return false, fmt.Errorf(data.ErrMessage)
|
return "", fmt.Errorf(data.ErrMessage)
|
||||||
}
|
}
|
||||||
return true, nil
|
return data.Result.UserId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *DingTalkIdProvider) getUserCorpEmail(userId string, accessToken string) (string, error) {
|
||||||
|
body := make(map[string]string)
|
||||||
|
body["userid"] = userId
|
||||||
|
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+accessToken)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
ErrMessage string `json:"errmsg"`
|
||||||
|
Result struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
} `json:"result"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(respBytes, &data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if data.ErrMessage != "ok" {
|
||||||
|
return "", fmt.Errorf(data.ErrMessage)
|
||||||
|
}
|
||||||
|
return data.Result.Email, nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user