提交 978f7fa2a3737508c283610453f1d682becb358a
Merge branch 'master' of http://gitlab.ctune.cn/weijunh/DMapManager
正在显示
12 个修改的文件
包含
402 行增加
和
110 行删除
1 | +from datetime import datetime | |
1 | 2 | from logging import error |
2 | 3 | from flasgger import swag_from |
3 | 4 | from app.util import BlueprintApi |
... | ... | @@ -6,7 +7,7 @@ from .models import * |
6 | 7 | from .oauth2 import authorization, generate_user_info, require_oauth |
7 | 8 | from authlib.oauth2 import OAuth2Error |
8 | 9 | from authlib.integrations.flask_oauth2 import current_token |
9 | -from . import user_create, client_create, client_query, user_query, user_update, user_delete | |
10 | +from . import user_create, client_create, client_query, user_query, user_update, user_delete, auth_log_query | |
10 | 11 | import configure |
11 | 12 | from app.decorators.auth_decorator import auth_decorator |
12 | 13 | import time |
... | ... | @@ -15,7 +16,8 @@ from app.util.component.StructurePrint import StructurePrint |
15 | 16 | import traceback |
16 | 17 | # from oauthlib import oauth2 |
17 | 18 | import requests |
18 | -from app.modules.auth.models import OAuth2Token, User, db | |
19 | +from app.modules.auth.models import OAuth2Token, User, db, OAuthLog | |
20 | +from app.util.enum.AuthEnum import AuthEnum, OriginEnum, OperateEnum | |
19 | 21 | |
20 | 22 | |
21 | 23 | def current_user(): |
... | ... | @@ -35,6 +37,16 @@ def split_by_crlf(s): |
35 | 37 | return [v for v in s.splitlines() if v] |
36 | 38 | |
37 | 39 | |
40 | +def getRedirectUrl(request): # 获取重定向地址 | |
41 | + # 获取头部信息 | |
42 | + X_Forwarded_Proto = request.headers.get("X-Forwarded-Proto") # 协议 | |
43 | + X_Forwarded_Host = request.headers.get("X-Forwarded-Host") # host | |
44 | + if not X_Forwarded_Proto == None and not X_Forwarded_Host == None: | |
45 | + return X_Forwarded_Proto+"://"+X_Forwarded_Host | |
46 | + else: | |
47 | + return request.host_url.rstrip("/") | |
48 | + | |
49 | + | |
38 | 50 | class DataManager(BlueprintApi): |
39 | 51 | bp = Blueprint("Auth", __name__, url_prefix="/auth") |
40 | 52 | |
... | ... | @@ -45,7 +57,7 @@ class DataManager(BlueprintApi): |
45 | 57 | request2 = authorization.create_oauth2_request(request) |
46 | 58 | grant2 = authorization.get_authorization_grant(request=request2) |
47 | 59 | redirect_uri = grant2.validate_authorization_request() |
48 | - session["redirect_uri"] = redirect_uri | |
60 | + session["redirect_uri"] = redirect_uri # 记录跳转重定向地址 | |
49 | 61 | if request.method == "GET": |
50 | 62 | # 没有登录,跳转到登录界面 |
51 | 63 | try: |
... | ... | @@ -71,8 +83,11 @@ class DataManager(BlueprintApi): |
71 | 83 | crypt_pwd = request.form.get("password") |
72 | 84 | # password = SM3.encode(crypt_pwd) |
73 | 85 | password = SM3.encode(AESHelper.decode(crypt_pwd)) |
86 | + | |
87 | + # 仅支持dmap平台保留用户登录 | |
88 | + origin_type = OriginEnum.Dmap.name.lower() | |
74 | 89 | user = User.query.filter_by( |
75 | - username=username, password=password).first() | |
90 | + username=username, password=password, origin=origin_type).first() | |
76 | 91 | if not user: |
77 | 92 | error = "账号或密码不正确" |
78 | 93 | flash(error) |
... | ... | @@ -83,6 +98,17 @@ class DataManager(BlueprintApi): |
83 | 98 | if user: |
84 | 99 | session["id"] = user.id |
85 | 100 | grant_user = user |
101 | + | |
102 | + # 日志 | |
103 | + log = OAuthLog(user_id=user.id, username=user.username, | |
104 | + auth_type=AuthEnum.Other.name.lower(), | |
105 | + message="认证成功", create_time=datetime.now(), | |
106 | + operate_type=OperateEnum.Login, | |
107 | + displayname=user.displayname, ip=request.remote_addr | |
108 | + ) | |
109 | + db.session.add(log) | |
110 | + db.session.commit() | |
111 | + | |
86 | 112 | return authorization.create_authorization_response(request=request, grant_user=grant_user) |
87 | 113 | |
88 | 114 | # try: |
... | ... | @@ -116,16 +142,34 @@ class DataManager(BlueprintApi): |
116 | 142 | def logout(): |
117 | 143 | try: |
118 | 144 | request2 = authorization.create_oauth2_request(request) |
119 | - grant1 = authorization.get_authorization_grant(request=request2) | |
145 | + grant1 = authorization.get_authorization_grant( | |
146 | + request=request2) | |
120 | 147 | redirect_uri = grant1.validate_authorization_request() |
121 | 148 | access_token = request.args.get("accesstoken") |
122 | - accesstoken = OAuth2Token.query.filter_by( | |
123 | - access_token=access_token).first() | |
124 | - accesstoken.revoked = True | |
125 | - db.session.commit() | |
126 | - remove_user() | |
149 | + | |
150 | + if not access_token == None: | |
151 | + accesstoken = OAuth2Token.query.filter_by( | |
152 | + access_token=access_token).one_or_none() | |
153 | + if not accesstoken == None: | |
154 | + accesstoken.revoked = True | |
155 | + db.session.commit() | |
156 | + if current_user() != None: | |
157 | + remove_user() | |
158 | + | |
159 | + user = User.query.get(accesstoken.user_id) | |
160 | + # 日志 | |
161 | + if user != None: | |
162 | + log = OAuthLog(user_id=user.id, username=user.username, | |
163 | + auth_type=AuthEnum.Other.name.lower(), | |
164 | + message="注销成功", create_time=datetime.now(), | |
165 | + operate_type=OperateEnum.Logout, token=access_token, | |
166 | + displayname=user.displayname, ip=request.remote_addr | |
167 | + ) | |
168 | + db.session.add(log) | |
169 | + db.session.commit() | |
170 | + | |
127 | 171 | except OAuth2Error as error: |
128 | - return jsonify(dict(error.get_body())) | |
172 | + StructurePrint().print(error.__str__()+":" + traceback.format_exc(), "error") | |
129 | 173 | return redirect(redirect_uri) |
130 | 174 | |
131 | 175 | """接口""" |
... | ... | @@ -207,15 +251,15 @@ class DataManager(BlueprintApi): |
207 | 251 | except Exception as e: |
208 | 252 | StructurePrint().print(e.__str__()+":" + traceback.format_exc(), "error") |
209 | 253 | |
210 | - @staticmethod | |
211 | - @bp.route("/translate", methods=["GET"]) | |
212 | - def translate(): | |
213 | - password = ['esri@123', 'admin', 'DMap@123', 'passwd'] | |
214 | - result = {} | |
215 | - for p in password: | |
216 | - new_pwd = SM3.encode(p) | |
217 | - result[p] = new_pwd | |
218 | - return result | |
254 | + # @staticmethod | |
255 | + # @bp.route("/translate", methods=["GET"]) | |
256 | + # def translate(): | |
257 | + # password = ['esri@123', 'admin', 'DMap@123', 'passwd','dci112..'] | |
258 | + # result = {} | |
259 | + # for p in password: | |
260 | + # new_pwd = SM3.encode(p) | |
261 | + # result[p] = new_pwd | |
262 | + # return result | |
219 | 263 | |
220 | 264 | ''' |
221 | 265 | 三方登录:OA |
... | ... | @@ -226,8 +270,9 @@ class DataManager(BlueprintApi): |
226 | 270 | client = oauth2.WebApplicationClient( |
227 | 271 | configure.OA["client_id"]) |
228 | 272 | state = client.state_generator() |
273 | + StructurePrint().print(request.headers, "info") | |
229 | 274 | auth_uri = client.prepare_request_uri( |
230 | - configure.OA["authorization_endpoint"], configure.OA["redirect_uri"], configure.OA["scope"], state) | |
275 | + configure.OA["authorization_endpoint"], getRedirectUrl(request) + configure.OA["redirect_uri"], configure.OA["scope"], state) | |
231 | 276 | session["oauth_state"] = state |
232 | 277 | return redirect(auth_uri) |
233 | 278 | |
... | ... | @@ -237,78 +282,111 @@ class DataManager(BlueprintApi): |
237 | 282 | @staticmethod |
238 | 283 | @bp.route("/oa/callback", methods=["GET"]) |
239 | 284 | def oa_callback(): |
285 | + try: | |
286 | + auth_default_redirect_uri = configure.auth_default_redirect_uri | |
287 | + client = oauth2.WebApplicationClient( | |
288 | + configure.OA["client_id"]) | |
289 | + | |
290 | + # 获取code | |
291 | + code = client.parse_request_uri_response( | |
292 | + request.url, session["oauth_state"]).get("code") | |
293 | + | |
294 | + if code == None: | |
295 | + return "登录失败" | |
296 | + | |
297 | + # 获取token | |
298 | + body = client.prepare_request_body( | |
299 | + code, redirect_uri=getRedirectUrl(request) + configure.OA["redirect_uri"], client_secret=configure.OA["client_secret"]) | |
300 | + | |
301 | + r = requests.post(configure.OA["token_endpoint"], body, headers={ | |
302 | + "Content-Type": "application/x-www-form-urlencoded"}) | |
303 | + | |
304 | + tokeninfo = r.json() | |
305 | + access_token = tokeninfo.get("access_token") | |
306 | + id_token = tokeninfo.get("id_token") | |
307 | + | |
308 | + origin_type = "dci_oa" # 三方登录标识 | |
309 | + if access_token: | |
310 | + # 获取用户信息 | |
311 | + userinfo_url = configure.OA["userinfo_endpoint"] | |
312 | + user_request = requests.get(userinfo_url, headers={ | |
313 | + "Authorization": "Bearer %s" % access_token}) | |
314 | + userinfo = user_request.json() | |
315 | + user_name = userinfo.get("user_name") | |
316 | + display_name = userinfo.get("displayname") | |
317 | + display_name = display_name.split( | |
318 | + )[-1] if display_name != None else user_name | |
319 | + | |
320 | + # 默认关联dmap用户 | |
321 | + try: | |
322 | + user = User.query.filter_by( | |
323 | + username=user_name, origin=origin_type).first() | |
324 | + except error as e: | |
325 | + user = None | |
326 | + | |
327 | + # 用户不存在,创建用户 | |
240 | 328 | |
241 | - client = oauth2.WebApplicationClient( | |
242 | - configure.OA["client_id"]) | |
243 | - | |
244 | - # 获取code | |
245 | - code = client.parse_request_uri_response( | |
246 | - request.url, session["oauth_state"]).get("code") | |
247 | - | |
248 | - if code == None: | |
249 | - return "登录失败" | |
250 | - | |
251 | - # 获取token | |
252 | - body = client.prepare_request_body( | |
253 | - code, redirect_uri=configure.OA["redirect_uri"], client_secret=configure.OA["client_secret"]) | |
254 | - | |
255 | - r = requests.post(configure.OA["token_endpoint"], body, headers={ | |
256 | - "Content-Type": "application/x-www-form-urlencoded"}) | |
257 | - | |
258 | - tokeninfo = r.json() | |
259 | - access_token = tokeninfo.get("access_token") | |
260 | - | |
261 | - if access_token: | |
262 | - # 获取用户信息 | |
263 | - userinfo_url = configure.OA["userinfo_endpoint"] | |
264 | - user_request = requests.get(userinfo_url, headers={ | |
265 | - "Authorization": "Bearer %s" % access_token}) | |
266 | - userinfo = user_request.json() | |
267 | - user_name = userinfo.get("user_name") | |
268 | - display_name = userinfo.get("displayname") | |
269 | - | |
270 | - # 默认关联dmap用户 | |
271 | - try: | |
272 | - user = User.query.filter_by( | |
273 | - username=user_name).first() | |
274 | - except error as e: | |
275 | - user = None | |
329 | + if not user: | |
330 | + user = User(username=user_name, password=SM3.encode('DMap@123'), role='dataman', | |
331 | + phone='', company='', position='', email='', displayname=display_name, | |
332 | + origin=origin_type, | |
333 | + create_time=time.strftime( | |
334 | + "%Y-%m-%d %H:%M:%S", time.localtime()), | |
335 | + update_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) | |
336 | + db.session.add(user) | |
337 | + db.session.commit() | |
338 | + | |
339 | + session["id"] = user.id | |
340 | + | |
341 | + # dmap token授权 | |
342 | + # 存入数据库 | |
343 | + token = OAuth2Token( | |
344 | + client_id=configure.OA["client_id"], | |
345 | + token_type=tokeninfo.get("token_type"), | |
346 | + access_token=access_token, | |
347 | + scope=tokeninfo.get("scope"), | |
348 | + expires_in=tokeninfo.get("expires_in"), | |
349 | + user_id=user.id | |
350 | + ) | |
351 | + | |
352 | + db.session.add(token) | |
353 | + db.session.commit() | |
276 | 354 | |
277 | - # 用户不存在,创建用户 | |
278 | - if not user: | |
279 | - user = User(username=user_name, password=SM3.encode('DMap@123'), role='dataman', | |
280 | - phone='', company='', position='', email='', | |
281 | - create_time=time.strftime( | |
282 | - "%Y-%m-%d %H:%M:%S", time.localtime()), | |
283 | - update_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) | |
284 | - db.session.add(user) | |
355 | + redirect_uri = session["redirect_uri"] if "redirect_uri" in session else auth_default_redirect_uri | |
356 | + | |
357 | + #session["id_token"] = id_token | |
358 | + response = make_response(redirect(redirect_uri)) | |
359 | + response.set_cookie('accessToken', access_token, | |
360 | + max_age=configure.expiretime) | |
361 | + response.set_cookie('id_token', id_token, | |
362 | + max_age=configure.expiretime) | |
363 | + | |
364 | + log = OAuthLog(user_id=user.id, username=user_name, | |
365 | + auth_type=AuthEnum.Other.name.lower(), | |
366 | + message="三方认证成功", create_time=datetime.now(), | |
367 | + operate_type=OperateEnum.Login, token=access_token, | |
368 | + displayname=display_name, ip=request.remote_addr) | |
369 | + db.session.add(log) | |
285 | 370 | db.session.commit() |
286 | 371 | |
287 | - # dmap token授权 | |
288 | - session["id"] = user.id | |
372 | + return response | |
373 | + else: | |
374 | + raise Exception("缺少access_token") | |
289 | 375 | |
290 | - # 存入数据库 | |
291 | - token = OAuth2Token( | |
292 | - client_id=configure.OA["client_id"], | |
293 | - token_type=tokeninfo.get("token_type"), | |
294 | - access_token=access_token, | |
295 | - scope=tokeninfo.get("scope"), | |
296 | - expires_in=tokeninfo.get("expires_in"), | |
297 | - user_id=user.id | |
298 | - ) | |
299 | - db.session.add(token) | |
300 | - db.session.commit() | |
301 | - redirect_uri = "" | |
302 | - try: | |
303 | - redirect_uri = session["redirect_uri"] | |
304 | - if not redirect_uri: | |
305 | - redirect_uri = '/' | |
306 | - except: | |
307 | - redirect_uri = "/" | |
308 | - | |
309 | - response = make_response(redirect(redirect_uri)) | |
310 | - response.set_cookie('accessToken', access_token, max_age=604_800) | |
311 | - | |
312 | - return response | |
313 | - else: | |
314 | - return redirect('/') | |
376 | + except Exception as e: | |
377 | + StructurePrint().print(e.__str__()+":" + traceback.format_exc(), "error") | |
378 | + pop_list = ["id", "redirect_uri"] | |
379 | + for p in pop_list: | |
380 | + if p in session: | |
381 | + session.pop(p) | |
382 | + return redirect(auth_default_redirect_uri) | |
383 | + | |
384 | + @staticmethod | |
385 | + @bp.route("/logs", methods=["GET"]) | |
386 | + @swag_from(auth_log_query.Api.api_doc) | |
387 | + @auth_decorator(configure.UserPermission) | |
388 | + def authLog(): | |
389 | + ''' | |
390 | + 登录日志 | |
391 | + ''' | |
392 | + return auth_log_query.Api().result | ... | ... |
app/modules/auth/auth_log_query.py
0 → 100644
1 | +# coding=utf-8 | |
2 | +# author: qianyingz | |
3 | +# createtime: 2022/03/09 | |
4 | +# email: qianyingz@chinadci.com | |
5 | +from tokenize import String | |
6 | +from numpy import number | |
7 | +from sqlalchemy import or_ | |
8 | +from .models import * | |
9 | +from app.util.component.ApiTemplate import ApiTemplate | |
10 | +import json | |
11 | + | |
12 | + | |
13 | +class Api(ApiTemplate): | |
14 | + api_name = "登录日志" | |
15 | + | |
16 | + def para_check(self): | |
17 | + pass | |
18 | + | |
19 | + def process(self): | |
20 | + # 返回结果 | |
21 | + res = {} | |
22 | + res["result"] = False | |
23 | + try: | |
24 | + # 业务逻辑 | |
25 | + page_index = int(self.para.get("page_index", "0")) | |
26 | + page_size = int(self.para.get("page_size", "1000")) | |
27 | + # name = self.para.get("name") | |
28 | + order_by = self.para.get("order_by") | |
29 | + filter_param = self.para.get("filter_param", "") | |
30 | + filter_param_json = {} if filter_param == "" else json.loads( | |
31 | + filter_param) | |
32 | + kw = filter_param_json["kw"] if "kw" in filter_param_json else None | |
33 | + type = filter_param_json["type"] if "type" in filter_param_json else None | |
34 | + | |
35 | + log_query = OAuthLog.query | |
36 | + | |
37 | + if kw != None: | |
38 | + if isinstance(kw, str): | |
39 | + filter_username_query = log_query.filter(OAuthLog.username.like( | |
40 | + "%" + kw + "%")) | |
41 | + filter_display_query = log_query.filter( | |
42 | + OAuthLog.displayname.like("%" + kw + "%")) | |
43 | + log_query = filter_username_query.union( | |
44 | + filter_display_query) | |
45 | + | |
46 | + if type != None: | |
47 | + if isinstance(type, (str,int)): | |
48 | + log_query = log_query.filter(OAuthLog.operate_type == type) | |
49 | + elif isinstance(type, list): | |
50 | + log_query = log_query.filter(OAuthLog.operate_type.in_(type)) | |
51 | + | |
52 | + log_query = log_query.order_by(OAuthLog.create_time.desc()) | |
53 | + | |
54 | + count = log_query.count() | |
55 | + logs = log_query.limit(page_size).offset( | |
56 | + page_index*page_size).all() | |
57 | + | |
58 | + res["data"] = {"count": count, | |
59 | + "list": list(map(lambda t: | |
60 | + {"id": t.id, "username": t.username, "ip": t.ip, | |
61 | + "message": t.message, "create_time": t.create_time.strftime("%Y-%m-%d %H:%M:%S"), | |
62 | + "operate_type": t.operate_type, | |
63 | + "auth_type": t.auth_type, | |
64 | + "displayname": t.displayname}, logs))} | |
65 | + | |
66 | + # # 获取集合 | |
67 | + # userLinq = User.query.order_by(User.id.desc()) | |
68 | + # if name: | |
69 | + # userLinq = userLinq.filter( | |
70 | + # User.username.like("%" + name + "%")) | |
71 | + # tmp_count = userLinq.count() | |
72 | + # tmp_list = userLinq.limit(page_size).offset( | |
73 | + # page_index * page_size).all() | |
74 | + # res["data"] = { | |
75 | + # "count": tmp_count, | |
76 | + # "list": list(map(lambda t: | |
77 | + # {"guid": t.id, "username": t.username, | |
78 | + # "role": t.role, "display_name": t.display_name, | |
79 | + # "status": t.status}, | |
80 | + # tmp_list))} | |
81 | + | |
82 | + res["result"] = True | |
83 | + | |
84 | + except Exception as e: | |
85 | + raise e | |
86 | + return res | |
87 | + | |
88 | + api_doc = { | |
89 | + "tags": ["登录日志"], | |
90 | + "parameters": [ | |
91 | + {"name": "page_index", | |
92 | + "in": "query", | |
93 | + "type": "int", | |
94 | + "description": "当前页", | |
95 | + "default": 0}, | |
96 | + {"name": "page_size", | |
97 | + "in": "query", | |
98 | + "type": "int", | |
99 | + "description": "条数", | |
100 | + "default": 1000}, | |
101 | + {"name": "order_by", | |
102 | + "in": "query", | |
103 | + "type": "string", | |
104 | + "description": "排序"}, | |
105 | + {"name": "filter_param", | |
106 | + "in": "query", | |
107 | + "type": "json", | |
108 | + "description": "过滤"} | |
109 | + ], | |
110 | + "responses": { | |
111 | + 200: { | |
112 | + "schema": { | |
113 | + "properties": { | |
114 | + } | |
115 | + } | |
116 | + } | |
117 | + } | |
118 | + } | ... | ... |
1 | -from flask_sqlalchemy import sqlalchemy | |
2 | -from sqlalchemy import Column, Integer, Text, Time, ForeignKey | |
1 | +from sqlalchemy import Column, Integer, Text, Time, ForeignKey, DateTime | |
3 | 2 | from app.models import db |
4 | 3 | from authlib.integrations.sqla_oauth2 import ( |
5 | 4 | OAuth2ClientMixin, |
... | ... | @@ -7,6 +6,7 @@ from authlib.integrations.sqla_oauth2 import ( |
7 | 6 | OAuth2AuthorizationCodeMixin |
8 | 7 | ) |
9 | 8 | from sqlalchemy.orm import relationship |
9 | +from app.util.enum.AuthEnum import OriginEnum,UserStatusEnum | |
10 | 10 | |
11 | 11 | |
12 | 12 | class User (db.Model): |
... | ... | @@ -16,17 +16,18 @@ class User (db.Model): |
16 | 16 | __tablename__ = "dmap_user" |
17 | 17 | id = Column(Integer, primary_key=True) |
18 | 18 | username = Column(Text) |
19 | - | |
20 | 19 | password = Column(Text) |
21 | 20 | company = Column(Text) |
22 | 21 | position = Column(Text) |
23 | 22 | phone = Column(Text) |
24 | 23 | email = Column(Text) |
25 | - create_time = Column(Time) | |
26 | - update_time = Column(Time) | |
24 | + create_time = Column(DateTime) | |
25 | + update_time = Column(DateTime) | |
27 | 26 | role = Column(Text) |
28 | - #display_name = Column(Text, nullable=True) # 昵称 | |
29 | - #origin = Column(Text, default="dmap") # 用户来源,默认dmap平台用户 | |
27 | + displayname = Column(Text, nullable=True) # 昵称 | |
28 | + # 用户来源,默认dmap平台用户 | |
29 | + origin = Column(Text, default=OriginEnum.Dmap.name.lower()) | |
30 | + status = Column(Integer, default=UserStatusEnum.Active) # 1:激活,2:冻结,0:注销 | |
30 | 31 | |
31 | 32 | def __str__(self): |
32 | 33 | return self.username |
... | ... | @@ -68,3 +69,26 @@ class OAuth2Token(db.Model, OAuth2TokenMixin): |
68 | 69 | Integer, ForeignKey('dmap_user.id', ondelete='CASCADE')) |
69 | 70 | # name = Column(Text) |
70 | 71 | user = relationship('User') |
72 | + | |
73 | + | |
74 | +''' | |
75 | +认证日志 | |
76 | +''' | |
77 | + | |
78 | +# 认证日志 | |
79 | + | |
80 | + | |
81 | +class OAuthLog(db.Model): | |
82 | + __tablename__ = "dmap_oauth_log" | |
83 | + | |
84 | + id = Column(Integer, primary_key=True) | |
85 | + user_id = Column(Text, nullable=False) | |
86 | + username = Column(Text) # 用户输入账号 | |
87 | + displayname=Column(Text) # 昵称 | |
88 | + ip = Column(Text) | |
89 | + # 登录方式:password,三方登录 | |
90 | + auth_type = Column(Text) | |
91 | + message = Column(Text) # 登录返回提示 | |
92 | + create_time = Column(DateTime) # 记录创建时间 | |
93 | + operate_type = Column(Integer, nullable=False) # 操作类型,登录,注销 | |
94 | + token = Column(Text) | ... | ... |
... | ... | @@ -51,7 +51,7 @@ def exists_nonce(nonce, req): |
51 | 51 | |
52 | 52 | |
53 | 53 | def generate_user_info(user, scope): |
54 | - return UserInfo(sub=str(user.id), name=user.username, role=user.role, company=user.company) | |
54 | + return UserInfo(sub=str(user.id), name=user.username, role=user.role, company=user.company, display_name=user.displayname, status=user.status) | |
55 | 55 | |
56 | 56 | |
57 | 57 | def create_authorization_code(client, grant_user, request): | ... | ... |
... | ... | @@ -27,18 +27,19 @@ class Api(ApiTemplate): |
27 | 27 | res["result"] = False |
28 | 28 | try: |
29 | 29 | # 业务逻辑 |
30 | - username = AESHelper.decode( self.para.get("username", '')) | |
30 | + username = AESHelper.decode(self.para.get("username", '')) | |
31 | 31 | password = SM3.encode(AESHelper.decode(self.para.get("pwd", ''))) |
32 | 32 | role = AESHelper.decode(self.para.get("role", '')) |
33 | 33 | company = AESHelper.decode(self.para.get("company", '')) |
34 | 34 | position = AESHelper.decode(self.para.get("position", '')) |
35 | 35 | email = AESHelper.decode(self.para.get("email", '')) |
36 | 36 | phone = AESHelper.decode(self.para.get("phone", '')) |
37 | + displayname = username | |
37 | 38 | # 是否重名 |
38 | 39 | if(User.query.filter_by(username=username).one_or_none()): |
39 | 40 | res["msg"] = "username 已存在" |
40 | 41 | else: |
41 | - user = User(username=username, password=password, role=role, | |
42 | + user = User(username=username, displayname=displayname, password=password, role=role, | |
42 | 43 | phone=phone, company=company, position=position, email=email, |
43 | 44 | create_time=time.strftime( |
44 | 45 | "%Y-%m-%d %H:%M:%S", time.localtime()), | ... | ... |
... | ... | @@ -20,7 +20,6 @@ class Api(ApiTemplate): |
20 | 20 | res["result"] = False |
21 | 21 | try: |
22 | 22 | # 业务逻辑 |
23 | - pass | |
24 | 23 | page_index = int(self.para.get("page_index", "0")) |
25 | 24 | page_size = int(self.para.get("page_size", "1000")) |
26 | 25 | name = self.para.get("name") |
... | ... | @@ -31,7 +30,8 @@ class Api(ApiTemplate): |
31 | 30 | res["data"] = {"guid": tmp_user.id, "username": tmp_user.username, |
32 | 31 | "role": tmp_user.role, "company": tmp_user.company, |
33 | 32 | "position": tmp_user.position, "email": tmp_user.email, |
34 | - "phone": tmp_user.phone} | |
33 | + "phone": tmp_user.phone, "display_name": tmp_user.displayname, | |
34 | + "status": tmp_user.status} | |
35 | 35 | else: |
36 | 36 | # 获取集合 |
37 | 37 | userLinq = User.query.order_by(User.id.desc()) |
... | ... | @@ -45,7 +45,8 @@ class Api(ApiTemplate): |
45 | 45 | "count": tmp_count, |
46 | 46 | "list": list(map(lambda t: |
47 | 47 | {"guid": t.id, "username": t.username, |
48 | - "role": t.role}, | |
48 | + "role": t.role, "display_name": t.displayname, | |
49 | + "status": t.status}, | |
49 | 50 | tmp_list))} |
50 | 51 | res["result"] = True |
51 | 52 | ... | ... |
... | ... | @@ -238,4 +238,28 @@ button { |
238 | 238 | -webkit-box-sizing: border-box; |
239 | 239 | -moz-box-sizing: border-box; |
240 | 240 | box-sizing: border-box; |
241 | +} | |
242 | + | |
243 | +.other-mod { | |
244 | + margin-top: 35px; | |
245 | +} | |
246 | + | |
247 | +.other-mod .other-tit { | |
248 | + color: #999; | |
249 | + display: inline-block; | |
250 | + margin-right: 20px; | |
251 | +} | |
252 | + | |
253 | +.other-mod .other-link { | |
254 | + text-align: right; | |
255 | + margin-left: 20px; | |
256 | + float: right; | |
257 | +} | |
258 | + | |
259 | +.other-mod .other-link a { | |
260 | + color: #545454; | |
261 | +} | |
262 | + | |
263 | +.other-mod .other-link:hover a { | |
264 | + color: #3081c3; | |
241 | 265 | } |
\ No newline at end of file | ... | ... |
... | ... | @@ -76,8 +76,13 @@ |
76 | 76 | 立即登录 |
77 | 77 | </button> |
78 | 78 | </div> |
79 | - <div>——或者——</div> | |
80 | - <a href="/auth/oa"> 城信所统一用户认证 </a> | |
79 | + | |
80 | + <div class="form-group other-mod"> | |
81 | + <div class="other-tit"><span>其他登录方式</span></div> | |
82 | + <div class="other-link"> | |
83 | + <a href="/auth/oa">城信所统一用户认证</a> | |
84 | + </div> | |
85 | + </div> | |
81 | 86 | </form> |
82 | 87 | </div> |
83 | 88 | <div class="clear"></div> | ... | ... |
app/util/enum/AuthEnum.py
0 → 100644
1 | +from enum import Enum,IntEnum | |
2 | + | |
3 | +''' | |
4 | +认证方式 | |
5 | +''' | |
6 | + | |
7 | + | |
8 | +class AuthEnum(IntEnum): | |
9 | + Password = 1 # 账号密码登录,包括三方的账号密码登录 | |
10 | + Other = 3 # 三方登录 | |
11 | + | |
12 | + | |
13 | +''' | |
14 | +用户来源 | |
15 | +''' | |
16 | + | |
17 | + | |
18 | +class OriginEnum(IntEnum): | |
19 | + Dmap = 1 | |
20 | + | |
21 | + | |
22 | +'''用户状态''' | |
23 | + | |
24 | + | |
25 | +class UserStatusEnum(IntEnum): | |
26 | + Cancellation = 0, # 注销 | |
27 | + Active = 1, # 活跃 | |
28 | + Freeze = 2 # 冻结 | |
29 | + | |
30 | + | |
31 | +class OperateEnum(IntEnum): | |
32 | + Login = 1, # 登录 | |
33 | + Logout = 2 # 注销 | ... | ... |
... | ... | @@ -27,13 +27,17 @@ ServicePermission = ['admin', 'dataman', 'publisher'] |
27 | 27 | |
28 | 28 | log_level = logging.INFO |
29 | 29 | |
30 | +expiretime = 604_800 # 7天 | |
30 | 31 | |
31 | 32 | OA = { |
32 | 33 | "client_id": "dmap", |
33 | 34 | "client_secret": "secret", |
34 | 35 | "scope": "openid profile", |
35 | - "redirect_uri": "http://localhost:8841/auth/oa/callback", | |
36 | + "redirect_uri": "/auth/oa/callback", | |
36 | 37 | "authorization_endpoint": "https://login.chinadci.com/netsso/connect/authorize", |
37 | 38 | "token_endpoint": "https://login.chinadci.com/netsso/connect/token", |
38 | - "userinfo_endpoint": "https://login.chinadci.com/netsso/connect/userinfo" | |
39 | + "userinfo_endpoint": "https://login.chinadci.com/netsso/connect/userinfo", | |
40 | + "end_session_endpoint": "https://login.chinadci.com/netsso/connect/endsession" | |
39 | 41 | } |
42 | + | |
43 | +auth_default_redirect_uri="http://localhost:9999" | |
\ No newline at end of file | ... | ... |
... | ... | @@ -77,4 +77,8 @@ result=AESHelper.decode(encryption) |
77 | 77 | |
78 | 78 | [验证码基础知识](https://baike.baidu.com/item/%E9%AA%8C%E8%AF%81%E7%A0%81/31701) |
79 | 79 | [使用python图像处理标准库](https://www.liaoxuefeng.com/wiki/1016959663602400/1017785454949568) |
80 | -[pillow](https://pillow.readthedocs.io/en/stable/index.html) | |
\ No newline at end of file | ||
80 | +[pillow](https://pillow.readthedocs.io/en/stable/index.html) | |
81 | + | |
82 | + | |
83 | +## 5 使用编译文件的方法 | |
84 | +cmd下运行./compile.py | ... | ... |
请
注册
或
登录
后发表评论