LiYongHui
yonghui li
commited on
Commit
·
574bc66
1
Parent(s):
09e1055
feat: add feishu oauth (#815)
Browse files### What problem does this PR solve?
The back-end code adds Feishu oauth
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
Co-authored-by: yonghui li <[email protected]>
- api/apps/user_app.py +73 -0
- api/settings.py +1 -0
- conf/service_conf.yaml +7 -1
api/apps/user_app.py
CHANGED
|
@@ -122,6 +122,79 @@ def github_callback():
|
|
| 122 |
return redirect("/?auth=%s" % user.get_id())
|
| 123 |
|
| 124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
def user_info_from_github(access_token):
|
| 126 |
import requests
|
| 127 |
headers = {"Accept": "application/json",
|
|
|
|
| 122 |
return redirect("/?auth=%s" % user.get_id())
|
| 123 |
|
| 124 |
|
| 125 |
+
@manager.route('/feishu_callback', methods=['GET'])
|
| 126 |
+
def feishu_callback():
|
| 127 |
+
import requests
|
| 128 |
+
app_access_token_res = requests.post(FEISHU_OAUTH.get("app_access_token_url"), data=json.dumps({
|
| 129 |
+
"app_id": FEISHU_OAUTH.get("app_id"),
|
| 130 |
+
"app_secret": FEISHU_OAUTH.get("app_secret")
|
| 131 |
+
}), headers={"Content-Type": "application/json; charset=utf-8"})
|
| 132 |
+
app_access_token_res = app_access_token_res.json()
|
| 133 |
+
if app_access_token_res['code'] != 0:
|
| 134 |
+
return redirect("/?error=%s" % app_access_token_res)
|
| 135 |
+
|
| 136 |
+
res = requests.post(FEISHU_OAUTH.get("user_access_token_url"), data=json.dumps({
|
| 137 |
+
"grant_type": FEISHU_OAUTH.get("grant_type"),
|
| 138 |
+
"code": request.args.get('code')
|
| 139 |
+
}), headers={"Content-Type": "application/json; charset=utf-8",
|
| 140 |
+
'Authorization': f"Bearer {app_access_token_res['app_access_token']}"})
|
| 141 |
+
res = res.json()
|
| 142 |
+
if res['code'] != 0:
|
| 143 |
+
return redirect("/?error=%s" % res["message"])
|
| 144 |
+
|
| 145 |
+
if "contact:user.email:readonly" not in res["data"]["scope"].split(" "):
|
| 146 |
+
return redirect("/?error=contact:user.email:readonly not in scope")
|
| 147 |
+
session["access_token"] = res["data"]["access_token"]
|
| 148 |
+
session["access_token_from"] = "feishu"
|
| 149 |
+
userinfo = user_info_from_feishu(session["access_token"])
|
| 150 |
+
users = UserService.query(email=userinfo["email"])
|
| 151 |
+
user_id = get_uuid()
|
| 152 |
+
if not users:
|
| 153 |
+
try:
|
| 154 |
+
try:
|
| 155 |
+
avatar = download_img(userinfo["avatar_url"])
|
| 156 |
+
except Exception as e:
|
| 157 |
+
stat_logger.exception(e)
|
| 158 |
+
avatar = ""
|
| 159 |
+
users = user_register(user_id, {
|
| 160 |
+
"access_token": session["access_token"],
|
| 161 |
+
"email": userinfo["email"],
|
| 162 |
+
"avatar": avatar,
|
| 163 |
+
"nickname": userinfo["en_name"],
|
| 164 |
+
"login_channel": "feishu",
|
| 165 |
+
"last_login_time": get_format_time(),
|
| 166 |
+
"is_superuser": False,
|
| 167 |
+
})
|
| 168 |
+
if not users:
|
| 169 |
+
raise Exception('Register user failure.')
|
| 170 |
+
if len(users) > 1:
|
| 171 |
+
raise Exception('Same E-mail exist!')
|
| 172 |
+
user = users[0]
|
| 173 |
+
login_user(user)
|
| 174 |
+
return redirect("/?auth=%s" % user.get_id())
|
| 175 |
+
except Exception as e:
|
| 176 |
+
rollback_user_registration(user_id)
|
| 177 |
+
stat_logger.exception(e)
|
| 178 |
+
return redirect("/?error=%s" % str(e))
|
| 179 |
+
user = users[0]
|
| 180 |
+
user.access_token = get_uuid()
|
| 181 |
+
login_user(user)
|
| 182 |
+
user.save()
|
| 183 |
+
return redirect("/?auth=%s" % user.get_id())
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def user_info_from_feishu(access_token):
|
| 187 |
+
import requests
|
| 188 |
+
headers = {"Content-Type": "application/json; charset=utf-8",
|
| 189 |
+
'Authorization': f"Bearer {access_token}"}
|
| 190 |
+
res = requests.get(
|
| 191 |
+
f"https://open.feishu.cn/open-apis/authen/v1/user_info",
|
| 192 |
+
headers=headers)
|
| 193 |
+
user_info = res.json()["data"]
|
| 194 |
+
user_info["email"] = None if user_info.get("email") == "" else user_info["email"]
|
| 195 |
+
return user_info
|
| 196 |
+
|
| 197 |
+
|
| 198 |
def user_info_from_github(access_token):
|
| 199 |
import requests
|
| 200 |
headers = {"Accept": "application/json",
|
api/settings.py
CHANGED
|
@@ -158,6 +158,7 @@ CLIENT_AUTHENTICATION = AUTHENTICATION_CONF.get(
|
|
| 158 |
"switch", False)
|
| 159 |
HTTP_APP_KEY = AUTHENTICATION_CONF.get("client", {}).get("http_app_key")
|
| 160 |
GITHUB_OAUTH = get_base_config("oauth", {}).get("github")
|
|
|
|
| 161 |
WECHAT_OAUTH = get_base_config("oauth", {}).get("wechat")
|
| 162 |
|
| 163 |
# site
|
|
|
|
| 158 |
"switch", False)
|
| 159 |
HTTP_APP_KEY = AUTHENTICATION_CONF.get("client", {}).get("http_app_key")
|
| 160 |
GITHUB_OAUTH = get_base_config("oauth", {}).get("github")
|
| 161 |
+
FEISHU_OAUTH = get_base_config("oauth", {}).get("feishu")
|
| 162 |
WECHAT_OAUTH = get_base_config("oauth", {}).get("wechat")
|
| 163 |
|
| 164 |
# site
|
conf/service_conf.yaml
CHANGED
|
@@ -28,6 +28,12 @@ oauth:
|
|
| 28 |
client_id: xxxxxxxxxxxxxxxxxxxxxxxxx
|
| 29 |
secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 30 |
url: https://github.com/login/oauth/access_token
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
authentication:
|
| 32 |
client:
|
| 33 |
switch: false
|
|
@@ -38,4 +44,4 @@ authentication:
|
|
| 38 |
permission:
|
| 39 |
switch: false
|
| 40 |
component: false
|
| 41 |
-
dataset: false
|
|
|
|
| 28 |
client_id: xxxxxxxxxxxxxxxxxxxxxxxxx
|
| 29 |
secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 30 |
url: https://github.com/login/oauth/access_token
|
| 31 |
+
feishu:
|
| 32 |
+
app_id: cli_xxxxxxxxxxxxxxxxxxx
|
| 33 |
+
app_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 34 |
+
app_access_token_url: https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal
|
| 35 |
+
user_access_token_url: https://open.feishu.cn/open-apis/authen/v1/oidc/access_token
|
| 36 |
+
grant_type: 'authorization_code'
|
| 37 |
authentication:
|
| 38 |
client:
|
| 39 |
switch: false
|
|
|
|
| 44 |
permission:
|
| 45 |
switch: false
|
| 46 |
component: false
|
| 47 |
+
dataset: false
|