lesscode-flask 0.0.65__tar.gz → 0.0.67__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/PKG-INFO +1 -12
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/__init__.py +1 -1
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/app.py +14 -6
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/db/__init__.py +7 -2
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/log/access_log_handler.py +15 -9
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/parameterized_query.py +25 -7
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/user.py +7 -2
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/base_service.py +15 -11
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/setup/__init__.py +22 -12
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/decorator/cache.py +1 -1
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/wsgi.py +23 -8
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask.egg-info/PKG-INFO +1 -12
- lesscode-flask-0.0.67/lesscode_flask.egg-info/requires.txt +1 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/__init__.py +14 -2
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/clickhouse.py +8 -3
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/elasticsearch.py +5 -1
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/settings/__init__.py +11 -5
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/utils/requests_session.py +8 -1
- lesscode-flask-0.0.65/lesscode_flask.egg-info/requires.txt +0 -12
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/README.md +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/db/datasource.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/db/executor.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/access_log.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/auth_client.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/auth_permission.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/base_model.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/model/response_result.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/access_log_service.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/auth_client_service.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/auth_permission_service.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/authentication_service.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/setting/__init__.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/__init__.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/decorator/__init__.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/decorator/swagger.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/file/file_exporter.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/helpers.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/json/NotSortJSONProvider.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/oss/__init__.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/oss/ks3_oss.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/redis/redis_helper.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/request/request.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/swagger/swagger_template.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/swagger/swagger_util.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/thread/thread_utils.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask.egg-info/SOURCES.txt +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask.egg-info/dependency_links.txt +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask.egg-info/top_level.txt +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/kingbase.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/mysql.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/query_runner/pg.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/settings/helpers.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/redash/utils/__init__.py +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/setup.cfg +0 -0
- {lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lesscode-flask
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.67
|
|
4
4
|
Summary: lesscode-flask 是基于flask的web开发脚手架项目,该项目初衷为简化开发过程,让研发人员更加关注业务。
|
|
5
5
|
Home-page: https://lesscode-flask
|
|
6
6
|
Author: Chao.yy
|
|
@@ -11,17 +11,6 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Requires-Dist: Flask==3.0.3
|
|
14
|
-
Requires-Dist: Flask-Login==0.6.3
|
|
15
|
-
Requires-Dist: redis==5.1.1
|
|
16
|
-
Requires-Dist: flask-swagger-ui==4.11.1
|
|
17
|
-
Requires-Dist: pystache==0.6.5
|
|
18
|
-
Requires-Dist: python-dateutil==2.9.0.post0
|
|
19
|
-
Requires-Dist: funcy==2.0
|
|
20
|
-
Requires-Dist: Flask-SQLAlchemy==3.1.1
|
|
21
|
-
Requires-Dist: sqlparse==0.5.1
|
|
22
|
-
Requires-Dist: requests==2.32.3
|
|
23
|
-
Requires-Dist: gunicorn==23.0.0
|
|
24
|
-
Requires-Dist: gevent==24.10.2
|
|
25
14
|
|
|
26
15
|
# lesscode-flask
|
|
27
16
|
|
|
@@ -6,9 +6,11 @@ import sys
|
|
|
6
6
|
import time
|
|
7
7
|
import traceback
|
|
8
8
|
import typing as t
|
|
9
|
-
from
|
|
9
|
+
from importlib import import_module
|
|
10
|
+
|
|
11
|
+
# from flask import Flask, typing as ft, Response
|
|
10
12
|
from flask.globals import request_ctx, request
|
|
11
|
-
from flask_login import current_user
|
|
13
|
+
# from flask_login import current_user
|
|
12
14
|
from lesscode_utils.json_utils import JSONEncoder
|
|
13
15
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
14
16
|
|
|
@@ -52,6 +54,10 @@ class Lesscoder(Flask):
|
|
|
52
54
|
|
|
53
55
|
def preprocess_request(self) -> ft.ResponseReturnValue | None:
|
|
54
56
|
if self.config.get("AUTHORIZATION_ENABLE"): # 启动 AUTHORIZATION_ENABLE 才进行权限验证
|
|
57
|
+
try:
|
|
58
|
+
flask_login = import_module("flask_login")
|
|
59
|
+
except ImportError as e:
|
|
60
|
+
raise Exception(f"flask_login is not exist,run:pip install Flask-Login==0.6.3")
|
|
55
61
|
# 获取当前请求的url
|
|
56
62
|
url = request.path
|
|
57
63
|
# 获取URL 对应的id 与访问权限
|
|
@@ -62,13 +68,13 @@ class Lesscoder(Flask):
|
|
|
62
68
|
access = app_config.get("AUTH_DEFAULT_ACCESS", "0")
|
|
63
69
|
# '访问权限2:需要权限 1:需要登录 0:游客',
|
|
64
70
|
if str(access) == "1": # 需要登录
|
|
65
|
-
if current_user.is_anonymous_user:
|
|
71
|
+
if flask_login.current_user.is_anonymous_user:
|
|
66
72
|
# abort(403, "需要登录")
|
|
67
73
|
ResponseResult.fail("请登录后访问", status_code="403")
|
|
68
74
|
elif str(access) == "2": # 需要权限
|
|
69
|
-
if current_user.is_anonymous_user:
|
|
75
|
+
if flask_login.current_user.is_anonymous_user:
|
|
70
76
|
ResponseResult.fail("请登录后访问", status_code="403")
|
|
71
|
-
if not current_user.has_permission(id):
|
|
77
|
+
if not flask_login.current_user.has_permission(id):
|
|
72
78
|
ResponseResult.fail("请获取授权后访问", status_code="403")
|
|
73
79
|
return super(Lesscoder, self).preprocess_request()
|
|
74
80
|
|
|
@@ -86,7 +92,8 @@ class Lesscoder(Flask):
|
|
|
86
92
|
# # 计算请求耗时
|
|
87
93
|
# duration = time.time() - start_time
|
|
88
94
|
# 100 为自定义 'ACCESS' 的日志级别标识
|
|
89
|
-
logging.log(100,"访问日志", {"request_id": request_id,"start_time":start_time, "end_time": time.time(),
|
|
95
|
+
logging.log(100, "访问日志", {"request_id": request_id, "start_time": start_time, "end_time": time.time(),
|
|
96
|
+
"status_code": response.status_code})
|
|
90
97
|
return response
|
|
91
98
|
|
|
92
99
|
def dispatch_request(self) -> ft.ResponseReturnValue:
|
|
@@ -140,6 +147,7 @@ class Lesscoder(Flask):
|
|
|
140
147
|
setup_resource_register(self)
|
|
141
148
|
for blueprint_name, blueprint in blueprint_map.items():
|
|
142
149
|
self.register_blueprint(blueprint)
|
|
150
|
+
|
|
143
151
|
@staticmethod
|
|
144
152
|
def handle_exception(e):
|
|
145
153
|
traceback.print_exc() # 打印堆栈信息
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from importlib import import_module
|
|
2
3
|
|
|
3
4
|
from lesscode_flask.db.executor import QueryExecutor, QueryExecutionError
|
|
4
5
|
from lesscode_flask.model.parameterized_query import ParameterizedQuery
|
|
@@ -33,10 +34,14 @@ def execute_query(
|
|
|
33
34
|
return e
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
from flask_sqlalchemy import SQLAlchemy
|
|
37
|
+
# from flask_sqlalchemy import SQLAlchemy
|
|
38
|
+
try:
|
|
39
|
+
flask_sqlalchemy = import_module("flask_sqlalchemy")
|
|
40
|
+
except ImportError as e:
|
|
41
|
+
raise Exception(f"flask_sqlalchemy is not exist,run:pip install Flask-SQLAlchemy==3.1.1")
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
class LessCodeSQLAlchemy(SQLAlchemy):
|
|
44
|
+
class LessCodeSQLAlchemy(flask_sqlalchemy.SQLAlchemy):
|
|
40
45
|
pass
|
|
41
46
|
# def apply_driver_hacks(self, app, info, options):
|
|
42
47
|
# options.update(json_serializer=json_dumps)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
# from flask_login import current_user
|
|
2
|
+
import threading
|
|
3
|
+
from importlib import import_module
|
|
1
4
|
from logging import Handler
|
|
2
5
|
|
|
3
6
|
from flask import request, copy_current_request_context
|
|
4
|
-
from flask_login import current_user
|
|
5
|
-
import threading
|
|
6
|
-
from lesscode_flask.model.access_log import AccessLog
|
|
7
|
-
from lesscode_flask.model.user import AnonymousUser, ApiUser, User
|
|
8
7
|
|
|
8
|
+
from lesscode_flask.model.access_log import AccessLog
|
|
9
|
+
from lesscode_flask.model.user import AnonymousUser, ApiUser
|
|
9
10
|
from lesscode_flask.service.access_log_service import AccessLogService
|
|
10
11
|
from lesscode_flask.utils.helpers import app_config
|
|
11
12
|
from lesscode_flask.utils.redis.redis_helper import RedisHelper
|
|
@@ -50,19 +51,24 @@ class AccessLogHandler(Handler):
|
|
|
50
51
|
resource_label = url_info.get("label", "-")
|
|
51
52
|
except Exception as e:
|
|
52
53
|
pass
|
|
54
|
+
try:
|
|
55
|
+
flask_login = import_module("flask_login")
|
|
56
|
+
except ImportError as e:
|
|
57
|
+
raise Exception(f"flask_login is not exist,run:pip install Flask-Login==0.6.3")
|
|
53
58
|
'请求类型0:用户请求,1:API用户,2:匿名用户',
|
|
54
|
-
if isinstance(current_user, AnonymousUser):
|
|
59
|
+
if isinstance(flask_login.current_user, AnonymousUser):
|
|
55
60
|
type = 2
|
|
56
|
-
elif isinstance(current_user, ApiUser):
|
|
61
|
+
elif isinstance(flask_login.current_user, ApiUser):
|
|
57
62
|
type = 1
|
|
58
63
|
else:
|
|
59
64
|
type = 0
|
|
60
65
|
|
|
61
|
-
access_log = AccessLog(request_id=request_id, display_name=current_user.display_name,
|
|
62
|
-
obj_id=current_user.id, type=type,
|
|
66
|
+
access_log = AccessLog(request_id=request_id, display_name=flask_login.current_user.display_name,
|
|
67
|
+
obj_id=flask_login.current_user.id, type=type,
|
|
63
68
|
resource_id=resource_id,
|
|
64
69
|
resource_label=resource_label, url=url, referrer=referrer, client_ip=client_ip,
|
|
65
|
-
user_agent=user_agent_string,start_time=start_time, end_time=end_time,
|
|
70
|
+
user_agent=user_agent_string, start_time=start_time, end_time=end_time,
|
|
71
|
+
duration=end_time - start_time, status_code=status_code,
|
|
66
72
|
params=params)
|
|
67
73
|
|
|
68
74
|
@copy_current_request_context
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from functools import partial
|
|
3
|
+
from importlib import import_module
|
|
3
4
|
from numbers import Number
|
|
4
5
|
|
|
5
|
-
import pystache
|
|
6
|
-
from dateutil.parser import parse
|
|
7
|
-
from funcy import distinct
|
|
8
|
-
|
|
9
6
|
from lesscode_flask.utils.helpers import mustache_render
|
|
10
7
|
|
|
11
8
|
|
|
9
|
+
# import pystache
|
|
10
|
+
# from dateutil.parser import parse
|
|
11
|
+
# from funcy import distinct
|
|
12
|
+
|
|
13
|
+
|
|
12
14
|
def _pluck_name_and_value(default_column, row):
|
|
13
15
|
row = {k.lower(): v for k, v in row.items()}
|
|
14
16
|
name_column = "name" if "name" in row.keys() else default_column.lower()
|
|
@@ -30,7 +32,7 @@ def _pluck_name_and_value(default_column, row):
|
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
def dropdown_values(query_id, org):
|
|
33
|
-
data = []
|
|
35
|
+
data = [] # load_result(query_id, org)
|
|
34
36
|
first_column = data["columns"][0]["name"]
|
|
35
37
|
pluck = partial(_pluck_name_and_value, first_column)
|
|
36
38
|
return list(map(pluck, data["rows"]))
|
|
@@ -53,6 +55,14 @@ def join_parameter_list_values(parameters, schema):
|
|
|
53
55
|
|
|
54
56
|
def _collect_key_names(nodes):
|
|
55
57
|
keys = []
|
|
58
|
+
try:
|
|
59
|
+
pystache = import_module("pystache")
|
|
60
|
+
except ImportError:
|
|
61
|
+
raise Exception(f"pystache is not exist,run:pip install pystache==0.6.5")
|
|
62
|
+
try:
|
|
63
|
+
funcy = import_module("funcy")
|
|
64
|
+
except ImportError:
|
|
65
|
+
raise Exception(f"pystache is not exist,run:pip install pystache==0.6.5")
|
|
56
66
|
for node in nodes._parse_tree:
|
|
57
67
|
if isinstance(node, pystache.parser._EscapeNode):
|
|
58
68
|
keys.append(node.key)
|
|
@@ -60,10 +70,14 @@ def _collect_key_names(nodes):
|
|
|
60
70
|
keys.append(node.key)
|
|
61
71
|
keys.extend(_collect_key_names(node.parsed))
|
|
62
72
|
|
|
63
|
-
return distinct(keys)
|
|
73
|
+
return funcy.distinct(keys)
|
|
64
74
|
|
|
65
75
|
|
|
66
76
|
def _collect_query_parameters(query):
|
|
77
|
+
try:
|
|
78
|
+
pystache = import_module("pystache")
|
|
79
|
+
except ImportError:
|
|
80
|
+
raise Exception(f"pystache is not exist,run:pip install pystache==0.6.5")
|
|
67
81
|
nodes = pystache.parse(query)
|
|
68
82
|
keys = _collect_key_names(nodes)
|
|
69
83
|
return keys
|
|
@@ -100,7 +114,11 @@ def _is_regex_pattern(value, regex):
|
|
|
100
114
|
|
|
101
115
|
|
|
102
116
|
def _is_date(string):
|
|
103
|
-
|
|
117
|
+
try:
|
|
118
|
+
dateutil_parser = import_module("dateutil.parser")
|
|
119
|
+
except ImportError:
|
|
120
|
+
raise Exception(f"python-dateutil is not exist,run:pip install python-dateutil==2.9.0.post0")
|
|
121
|
+
dateutil_parser.parse(string)
|
|
104
122
|
return True
|
|
105
123
|
|
|
106
124
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
from functools import reduce
|
|
2
|
+
from importlib import import_module
|
|
2
3
|
|
|
3
|
-
from flask_login import AnonymousUserMixin, UserMixin
|
|
4
|
+
# from flask_login import AnonymousUserMixin, UserMixin
|
|
5
|
+
try:
|
|
6
|
+
flask_login = import_module("flask_login")
|
|
7
|
+
except ImportError as e:
|
|
8
|
+
raise Exception(f"flask_login is not exist,run:pip install Flask-Login==0.6.3")
|
|
4
9
|
|
|
5
10
|
|
|
6
11
|
class PermissionsCheckMixin:
|
|
@@ -17,7 +22,7 @@ class PermissionsCheckMixin:
|
|
|
17
22
|
return has_permissions
|
|
18
23
|
|
|
19
24
|
|
|
20
|
-
class User(UserMixin, PermissionsCheckMixin):
|
|
25
|
+
class User(flask_login.UserMixin, PermissionsCheckMixin):
|
|
21
26
|
"""
|
|
22
27
|
在线用户对象类
|
|
23
28
|
"""
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from importlib import import_module
|
|
2
3
|
|
|
3
|
-
from flask_login import current_user
|
|
4
|
-
|
|
4
|
+
# from flask_login import current_user
|
|
5
|
+
try:
|
|
6
|
+
flask_login = import_module("flask_login")
|
|
7
|
+
except ImportError as e:
|
|
8
|
+
raise Exception(f"flask_login is not exist,run:pip install Flask-Login==0.6.3")
|
|
5
9
|
from lesscode_flask.db import db
|
|
6
10
|
from lesscode_flask.model.base_model import BaseModel
|
|
7
11
|
from lesscode_flask.utils.helpers import result_to_dict, parameter_validation, format_page_index
|
|
@@ -28,9 +32,9 @@ class BaseService:
|
|
|
28
32
|
# current_user = None
|
|
29
33
|
try:
|
|
30
34
|
if hasattr(item, "create_user_id"):
|
|
31
|
-
item.create_user_id = current_user.id
|
|
35
|
+
item.create_user_id = flask_login.current_user.id
|
|
32
36
|
if hasattr(item, "create_user_name"):
|
|
33
|
-
item.create_user_name = current_user.display_name
|
|
37
|
+
item.create_user_name = flask_login.current_user.display_name
|
|
34
38
|
except Exception as e:
|
|
35
39
|
if hasattr(item, "create_user_id"):
|
|
36
40
|
item.create_user_id = "AnonymousUserId"
|
|
@@ -49,9 +53,9 @@ class BaseService:
|
|
|
49
53
|
for item in items:
|
|
50
54
|
try:
|
|
51
55
|
if hasattr(item, "create_user_id"):
|
|
52
|
-
item.create_user_id = current_user.id
|
|
56
|
+
item.create_user_id = flask_login.current_user.id
|
|
53
57
|
if hasattr(item, "create_user_name"):
|
|
54
|
-
item.create_user_name = current_user.display_name
|
|
58
|
+
item.create_user_name = flask_login.current_user.display_name
|
|
55
59
|
except Exception as e:
|
|
56
60
|
if hasattr(item, "create_user_id"):
|
|
57
61
|
item.create_user_id = "AnonymousUserId"
|
|
@@ -69,9 +73,9 @@ class BaseService:
|
|
|
69
73
|
|
|
70
74
|
try:
|
|
71
75
|
if hasattr(self.model, "modify_user_id"):
|
|
72
|
-
item["modify_user_id"] = current_user.id
|
|
76
|
+
item["modify_user_id"] = flask_login.current_user.id
|
|
73
77
|
if hasattr(self.model, "modify_user_name"):
|
|
74
|
-
item["modify_user_name"] = current_user.display_name
|
|
78
|
+
item["modify_user_name"] = flask_login.current_user.display_name
|
|
75
79
|
except Exception as e:
|
|
76
80
|
if hasattr(item, "modify_user_id"):
|
|
77
81
|
item.create_user_id = "AnonymousUserId"
|
|
@@ -81,13 +85,13 @@ class BaseService:
|
|
|
81
85
|
db.session.commit()
|
|
82
86
|
return id
|
|
83
87
|
|
|
84
|
-
def update_items(self, filters: list
|
|
88
|
+
def update_items(self, filters: list, item: dict):
|
|
85
89
|
|
|
86
90
|
try:
|
|
87
91
|
if hasattr(self.model, "modify_user_id"):
|
|
88
|
-
item["modify_user_id"] = current_user.id
|
|
92
|
+
item["modify_user_id"] = flask_login.current_user.id
|
|
89
93
|
if hasattr(self.model, "modify_user_name"):
|
|
90
|
-
item["modify_user_name"] = current_user.display_name
|
|
94
|
+
item["modify_user_name"] = flask_login.current_user.display_name
|
|
91
95
|
except Exception as e:
|
|
92
96
|
if hasattr(item, "modify_user_id"):
|
|
93
97
|
item.create_user_id = "AnonymousUserId"
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import importlib
|
|
2
1
|
import inspect
|
|
3
|
-
|
|
4
2
|
import uuid
|
|
5
|
-
|
|
6
3
|
from datetime import datetime
|
|
7
|
-
|
|
4
|
+
from importlib import import_module
|
|
8
5
|
from logging.handlers import TimedRotatingFileHandler
|
|
9
6
|
|
|
10
|
-
import redis
|
|
11
7
|
from flask import current_app
|
|
12
|
-
from flask_login import LoginManager
|
|
13
|
-
from flask_swagger_ui import get_swaggerui_blueprint
|
|
14
8
|
|
|
15
9
|
from lesscode_flask.db import db
|
|
16
10
|
from lesscode_flask.log.access_log_handler import AccessLogHandler
|
|
17
|
-
from lesscode_flask.model.user import AnonymousUser
|
|
11
|
+
from lesscode_flask.model.user import AnonymousUser
|
|
18
12
|
from lesscode_flask.service.authentication_service import get_token_user, get_api_user, get_gateway_user
|
|
19
13
|
from lesscode_flask.utils.swagger.swagger_template import split_doc
|
|
20
14
|
from lesscode_flask.utils.swagger.swagger_util import generate_openapi_spec, replace_symbol, get_params_type, \
|
|
21
15
|
get_sample_data
|
|
22
16
|
|
|
23
17
|
|
|
18
|
+
# from flask_login import LoginManager
|
|
19
|
+
# from flask_swagger_ui import get_swaggerui_blueprint
|
|
20
|
+
|
|
21
|
+
|
|
24
22
|
def setup_logging(app):
|
|
25
23
|
"""
|
|
26
24
|
初始化日志配置
|
|
@@ -93,7 +91,7 @@ def setup_blueprint(app, path=None, pkg_name="handlers", blueprint_map={}):
|
|
|
93
91
|
elif os.path.isfile(full_file) and handler_name.lower().endswith("handler.py"):
|
|
94
92
|
# 文件,并且为handler结尾,认为是请求处理器,完成动态装载
|
|
95
93
|
module_path = "{}.{}".format(pkg_name, handler_name.replace(".py", ""))
|
|
96
|
-
module =
|
|
94
|
+
module = import_module(module_path) # __import__(module_path)
|
|
97
95
|
for name, obj in inspect.getmembers(module):
|
|
98
96
|
# 找到Blueprint 的属性进行注册
|
|
99
97
|
if isinstance(obj, Blueprint):
|
|
@@ -129,7 +127,11 @@ def setup_sql_alchemy(app):
|
|
|
129
127
|
|
|
130
128
|
|
|
131
129
|
def setup_login_manager(app):
|
|
132
|
-
|
|
130
|
+
try:
|
|
131
|
+
flask_login = import_module("flask_login")
|
|
132
|
+
except ImportError as e:
|
|
133
|
+
raise Exception(f"flask_login is not exist,run:pip install Flask-Login==0.6.3")
|
|
134
|
+
login_manager = flask_login.LoginManager(app)
|
|
133
135
|
setattr(app, "login_manager", login_manager)
|
|
134
136
|
|
|
135
137
|
@login_manager.request_loader
|
|
@@ -163,7 +165,11 @@ def setup_swagger(app):
|
|
|
163
165
|
# API_URL = 'http://127.0.0.1:5001/static/swagger.json' # Swagger 规范的路径(本地 JSON 文件)
|
|
164
166
|
API_URL = app.config.get("SWAGGER_API_URL", "") # 接口
|
|
165
167
|
# 创建 Swagger UI 蓝图
|
|
166
|
-
|
|
168
|
+
try:
|
|
169
|
+
flask_swagger_ui = import_module("flask_swagger_ui")
|
|
170
|
+
except ImportError as e:
|
|
171
|
+
raise Exception(f"flask_swagger_ui is not exist,run:pip install flask-swagger-ui==4.11.1")
|
|
172
|
+
swagger_ui_blueprint = flask_swagger_ui.get_swaggerui_blueprint(
|
|
167
173
|
SWAGGER_URL, # Swagger UI 访问路径
|
|
168
174
|
app.config.get("OUTSIDE_SCREEN_IP") + API_URL, # Swagger 文件路径
|
|
169
175
|
config={ # Swagger UI 配置参数
|
|
@@ -187,6 +193,10 @@ def setup_redis(app):
|
|
|
187
193
|
|
|
188
194
|
for r in redis_conn_list:
|
|
189
195
|
if r.get("type") == "redis":
|
|
196
|
+
try:
|
|
197
|
+
redis = import_module("redis")
|
|
198
|
+
except ImportError:
|
|
199
|
+
raise Exception(f"redis is not exist,run:pip install redis==5.1.1")
|
|
190
200
|
conn = redis.Redis(host=r.get("host"), port=r.get("port"), db=r.get("db"), password=r.get("password"),
|
|
191
201
|
decode_responses=True)
|
|
192
202
|
if not hasattr(current_app, "redis_conn_dict"):
|
|
@@ -361,7 +371,7 @@ def setup_resource_register(app):
|
|
|
361
371
|
description=inter_desc, param_list=param_list))
|
|
362
372
|
resource_list.append(resource)
|
|
363
373
|
try:
|
|
364
|
-
httpx =
|
|
374
|
+
httpx = import_module("httpx")
|
|
365
375
|
except ImportError as e:
|
|
366
376
|
raise Exception(f"httpx is not exist,run:pip install httpx==0.24.1")
|
|
367
377
|
with httpx.Client(**{"timeout": None}) as session:
|
|
@@ -125,7 +125,7 @@ def insert_cache(data, ex, cache_key, conn_name=None):
|
|
|
125
125
|
try:
|
|
126
126
|
json_utils = import_module("lesscode_utils.json_utils")
|
|
127
127
|
except ImportError:
|
|
128
|
-
raise Exception(f"
|
|
128
|
+
raise Exception(f"lesscode_utils is not exist,run:pip install lesscode_utils==0.0.61")
|
|
129
129
|
RedisHelper(conn_name).sync_set(cache_key, json_utils.JSONEncoder().encode(data), ex=ex)
|
|
130
130
|
except:
|
|
131
131
|
logging.error(traceback.format_exc())
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# 解决MonkeyPatchWarning
|
|
3
3
|
import os
|
|
4
|
+
from importlib import import_module
|
|
4
5
|
|
|
5
|
-
from gevent import monkey # 导入补丁模块
|
|
6
|
+
# from gevent import monkey # 导入补丁模块
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
from funcy import iteritems
|
|
9
|
-
|
|
8
|
+
# 创建补丁
|
|
9
|
+
# from funcy import iteritems
|
|
10
|
+
try:
|
|
11
|
+
gunicorn_app_base = import_module("gunicorn.app.base")
|
|
12
|
+
except ImportError as e:
|
|
13
|
+
raise Exception(f"gunicorn is not exist,run:pip install gunicorn==23.0.0")
|
|
10
14
|
|
|
15
|
+
try:
|
|
16
|
+
gevent = import_module("gevent")
|
|
17
|
+
except ImportError as e:
|
|
18
|
+
raise Exception(f"gevent is not exist,run:pip install gevent==24.10.2")
|
|
11
19
|
|
|
12
|
-
|
|
20
|
+
gevent.monkey.patch_all()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Application(gunicorn_app_base.BaseApplication):
|
|
13
24
|
def __init__(self, app):
|
|
14
25
|
self.app = app
|
|
15
26
|
cpu_count = os.cpu_count()
|
|
@@ -17,7 +28,7 @@ class Application(BaseApplication):
|
|
|
17
28
|
cpu_count = 5
|
|
18
29
|
options = {
|
|
19
30
|
'bind': f"0.0.0.0:{app.config.get('PORT', 5002)}", # 绑定地址和端口
|
|
20
|
-
'workers': cpu_count*2+1, # 指定 workers 数量
|
|
31
|
+
'workers': cpu_count * 2 + 1, # 指定 workers 数量
|
|
21
32
|
'accesslog': "-", # 输出到标准输出,取消gunicorn接管日志输出
|
|
22
33
|
'worker_class': 'gevent', # worker 运行方式
|
|
23
34
|
'timeout': 300
|
|
@@ -28,9 +39,13 @@ class Application(BaseApplication):
|
|
|
28
39
|
# self.logger = logging # 自定义一直输出,如果项目中已经使用了其他的日志框架,而不想让gunicorn接管日志输出,需要将日志框架的对象指定给这里
|
|
29
40
|
|
|
30
41
|
def load_config(self):
|
|
31
|
-
|
|
42
|
+
try:
|
|
43
|
+
funcy = import_module("funcy")
|
|
44
|
+
except ImportError:
|
|
45
|
+
raise Exception(f"pystache is not exist,run:pip install pystache==0.6.5")
|
|
46
|
+
config = {key: value for key, value in funcy.iteritems(self.options)
|
|
32
47
|
if key in self.cfg.settings and value is not None}
|
|
33
|
-
for key, value in iteritems(config):
|
|
48
|
+
for key, value in funcy.iteritems(config):
|
|
34
49
|
self.cfg.set(key.lower(), value)
|
|
35
50
|
|
|
36
51
|
def load(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lesscode-flask
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.67
|
|
4
4
|
Summary: lesscode-flask 是基于flask的web开发脚手架项目,该项目初衷为简化开发过程,让研发人员更加关注业务。
|
|
5
5
|
Home-page: https://lesscode-flask
|
|
6
6
|
Author: Chao.yy
|
|
@@ -11,17 +11,6 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Requires-Python: >=3.9
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Requires-Dist: Flask==3.0.3
|
|
14
|
-
Requires-Dist: Flask-Login==0.6.3
|
|
15
|
-
Requires-Dist: redis==5.1.1
|
|
16
|
-
Requires-Dist: flask-swagger-ui==4.11.1
|
|
17
|
-
Requires-Dist: pystache==0.6.5
|
|
18
|
-
Requires-Dist: python-dateutil==2.9.0.post0
|
|
19
|
-
Requires-Dist: funcy==2.0
|
|
20
|
-
Requires-Dist: Flask-SQLAlchemy==3.1.1
|
|
21
|
-
Requires-Dist: sqlparse==0.5.1
|
|
22
|
-
Requires-Dist: requests==2.32.3
|
|
23
|
-
Requires-Dist: gunicorn==23.0.0
|
|
24
|
-
Requires-Dist: gevent==24.10.2
|
|
25
14
|
|
|
26
15
|
# lesscode-flask
|
|
27
16
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Flask==3.0.3
|
|
@@ -2,12 +2,24 @@ import logging
|
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from contextlib import ExitStack
|
|
4
4
|
from functools import wraps
|
|
5
|
+
from importlib import import_module
|
|
5
6
|
|
|
6
|
-
import sqlparse
|
|
7
|
+
# import sqlparse
|
|
7
8
|
from dateutil import parser
|
|
9
|
+
|
|
8
10
|
# from rq.timeouts import JobTimeoutException
|
|
9
11
|
# from sshtunnel import open_tunnel
|
|
10
12
|
|
|
13
|
+
try:
|
|
14
|
+
sqlparse = import_module("sqlparse")
|
|
15
|
+
except ImportError as e:
|
|
16
|
+
raise Exception(f"sqlparse is not exist,run:pip install sqlparse==0.5.1")
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
sshtunnel = import_module("sshtunnel")
|
|
20
|
+
except ImportError as e:
|
|
21
|
+
raise Exception(f"sshtunnel is not exist,run:pip install sshtunnel==0.4.0")
|
|
22
|
+
|
|
11
23
|
from redash import settings, utils
|
|
12
24
|
from redash.utils.requests_session import (
|
|
13
25
|
# UnacceptableAddressException,
|
|
@@ -503,7 +515,7 @@ def with_ssh_tunnel(query_runner, details):
|
|
|
503
515
|
"ssh_username": details["ssh_username"],
|
|
504
516
|
**settings.dynamic_settings.ssh_tunnel_auth(),
|
|
505
517
|
}
|
|
506
|
-
server = stack.enter_context(open_tunnel(bastion_address, remote_bind_address=remote_address, **auth))
|
|
518
|
+
server = stack.enter_context(sshtunnel.open_tunnel(bastion_address, remote_bind_address=remote_address, **auth))
|
|
507
519
|
except Exception as error:
|
|
508
520
|
raise type(error)("SSH tunnel: {}".format(str(error)))
|
|
509
521
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
|
+
from importlib import import_module
|
|
3
4
|
from urllib.parse import urlparse
|
|
4
5
|
|
|
5
|
-
import requests
|
|
6
|
-
|
|
7
6
|
from redash.query_runner import *
|
|
8
|
-
from redash.utils import
|
|
7
|
+
from redash.utils import json_loads
|
|
8
|
+
|
|
9
|
+
# import requests
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
@@ -89,6 +90,10 @@ class ClickHouse(BaseSQLQueryRunner):
|
|
|
89
90
|
|
|
90
91
|
def _send_query(self, data, stream=False):
|
|
91
92
|
url = self.configuration.get("url", "http://127.0.0.1:8123")
|
|
93
|
+
try:
|
|
94
|
+
requests = import_module("requests")
|
|
95
|
+
except ImportError as e:
|
|
96
|
+
raise Exception(f"requests is not exist,run:pip install requests==2.32.3")
|
|
92
97
|
try:
|
|
93
98
|
verify = self.configuration.get("verify", True)
|
|
94
99
|
r = requests.post(
|
|
@@ -3,8 +3,12 @@ import sys
|
|
|
3
3
|
import urllib.request
|
|
4
4
|
import urllib.parse
|
|
5
5
|
import urllib.error
|
|
6
|
+
from importlib import import_module
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
try:
|
|
9
|
+
requests = import_module("requests")
|
|
10
|
+
except ImportError as e:
|
|
11
|
+
raise Exception(f"requests is not exist,run:pip install requests==2.32.3")
|
|
8
12
|
from requests.auth import HTTPBasicAuth
|
|
9
13
|
|
|
10
14
|
from redash.query_runner import *
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from importlib import import_module
|
|
2
3
|
|
|
3
4
|
from redash.settings.helpers import parse_boolean, array_from_string
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
# from funcy import distinct, remove
|
|
5
7
|
|
|
6
8
|
# Whether api calls using the json query runner will block private addresses
|
|
7
9
|
ENFORCE_PRIVATE_ADDRESS_BLOCK = parse_boolean(os.environ.get("REDASH_ENFORCE_PRIVATE_IP_BLOCK", "true"))
|
|
8
10
|
# requests
|
|
9
11
|
REQUESTS_ALLOW_REDIRECTS = parse_boolean(os.environ.get("REDASH_REQUESTS_ALLOW_REDIRECTS", "false"))
|
|
10
12
|
|
|
11
|
-
|
|
12
13
|
# Query Runners
|
|
13
14
|
default_query_runners = [
|
|
14
15
|
# "redash.query_runner.athena",
|
|
@@ -84,7 +85,12 @@ enabled_query_runners = array_from_string(
|
|
|
84
85
|
additional_query_runners = array_from_string(os.environ.get("REDASH_ADDITIONAL_QUERY_RUNNERS", ""))
|
|
85
86
|
disabled_query_runners = array_from_string(os.environ.get("REDASH_DISABLED_QUERY_RUNNERS", ""))
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
try:
|
|
89
|
+
funcy = import_module("funcy")
|
|
90
|
+
except ImportError as e:
|
|
91
|
+
raise Exception(f"funcy is not exist,run:pip install funcy==2.0")
|
|
92
|
+
|
|
93
|
+
QUERY_RUNNERS = funcy.remove(
|
|
88
94
|
set(disabled_query_runners),
|
|
89
|
-
distinct(enabled_query_runners + additional_query_runners),
|
|
90
|
-
)
|
|
95
|
+
funcy.distinct(enabled_query_runners + additional_query_runners),
|
|
96
|
+
)
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
# from advocate.exceptions import UnacceptableAddressException # noqa: F401
|
|
2
|
+
from importlib import import_module
|
|
2
3
|
|
|
3
4
|
from redash import settings
|
|
4
5
|
|
|
5
6
|
# if settings.ENFORCE_PRIVATE_ADDRESS_BLOCK:
|
|
6
7
|
# import advocate as requests_or_advocate
|
|
7
8
|
# else:
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
# import requests as requests_or_advocate
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
requests_or_advocate = import_module("requests")
|
|
14
|
+
except ImportError as e:
|
|
15
|
+
raise Exception(f"requests is not exist,run:pip install requests==2.32.3")
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
class ConfiguredSession(requests_or_advocate.Session):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/access_log_service.py
RENAMED
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/auth_client_service.py
RENAMED
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/auth_permission_service.py
RENAMED
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/service/authentication_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/json/NotSortJSONProvider.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/swagger/swagger_template.py
RENAMED
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask/utils/swagger/swagger_util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lesscode-flask-0.0.65 → lesscode-flask-0.0.67}/lesscode_flask.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|