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 <yonghui.li@bondex.com.cn>
- 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
|