Skip to content

Commit 18f368b

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents 6169786 + e1f60a8 commit 18f368b

10 files changed

Lines changed: 66 additions & 78 deletions

File tree

.development.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
SQLALCHEMY_DATABASE_URI = 'sqlite:///../lincmsdev.db'
22
# SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@localhost:3306/lincmsdev'
3+
# SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:123456@localhost:5432/lincmsdev'
34
SECRET_KEY = '\x88W\xf09\x91\x07\x98\x89\x87\x96\xa0A\xc68\xf9\xecJJU\x17\xc5V\xbe\x8b\xef\xd7\xd8\xd3\xe6\x95*4'

.production.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
SQLALCHEMY_DATABASE_URI = 'sqlite:///../lincmsprod.db'
22
# SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@localhost:3306/lincmsprod'
3+
# SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:123456@localhost:5432/lincmsprod'
34
DEVELOPMENT_SECRET_KEY = '\x88W\xf09\x91\x07\x98\x89\x87\x96\xa0A\xc68\xf9\xecJJU\x17\xc5V\xbe\x8b\xef\xd7\xd8\xd3\xe6\x95*4'

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<p align="center">
1313
<a href="http://Flask.pocoo.org/docs/1.0/" rel="nofollow">
14-
<img src="https://img.shields.io/badge/Flask-2.0.2-green.svg" alt="Flask version" data-canonical-src="https://img.shields.io/badge/Flask-2.0.2-green.svg" style="max-width:100%;"></a>
14+
<img src="https://img.shields.io/badge/Flask-2.0.3-green.svg" alt="Flask version" data-canonical-src="https://img.shields.io/badge/Flask-2.0.3-green.svg" style="max-width:100%;"></a>
1515
<a href="https://doc.cms.talelin.com/" rel="nofollow"><img src="https://img.shields.io/badge/license-MIT-skyblue.svg" alt="LISENCE" data-canonical-src="https://img.shields.io/badge/license-MIT-skyblue.svg" style="max-width:100%;"></a>
1616
</p>
1717

app/api/cms/admin.py

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@
2828
AdminGroupListSchema,
2929
AdminGroupPermissionSchema,
3030
AdminUserPageSchema,
31+
AdminUserSchema,
3132
CreateGroupSchema,
3233
GroupBaseSchema,
3334
GroupIdWithPermissionIdListSchema,
34-
GroupQuerySearchSchema,
3535
UpdateUserInfoSchema,
3636
)
37-
from app.util.page import get_page_from_query
37+
from app.schema import QueryPageSchema
3838

3939
admin_api = Blueprint("admin", __name__)
4040

@@ -60,78 +60,70 @@ def permissions():
6060
tags=["管理员"],
6161
security=[AuthorizationBearerSecurity],
6262
resp=DocResponse(r=AdminUserPageSchema),
63-
before=GroupQuerySearchSchema.offset_handler,
63+
before=QueryPageSchema.offset_handler,
6464
)
65-
def get_admin_users(query: GroupQuerySearchSchema):
65+
def get_admin_users(query: QueryPageSchema):
6666
"""
67-
查询所有用户
67+
查询所有用户及其所属组信息
6868
"""
69-
# 根据筛选条件和分页,获取 用户id 与 用户组id 的一对多 数据
70-
# 过滤root 分组
69+
# 获取 符合条件的 用户id 数量 ,过滤root 分组
7170
query_root_group_id = db.session.query(manager.group_model.id).filter(
7271
manager.group_model.level == GroupLevelEnum.ROOT.value
7372
)
74-
_user_groups_list = db.session.query(
75-
manager.user_group_model.user_id.label("user_id"),
76-
func.group_concat(manager.user_group_model.group_id).label("group_ids"),
77-
).filter(~manager.user_group_model.group_id.in_(query_root_group_id))
78-
if g.group_id:
79-
_user_groups_list = _user_groups_list.filter(
80-
manager.user_group_model.group_id == g.group_id
81-
)
82-
user_groups_list = (
83-
_user_groups_list.group_by(manager.user_group_model.user_id)
73+
# 获取符合条件的用户总量
74+
total = (
75+
db.session.query(func.count(func.distinct(manager.user_group_model.user_id)))
76+
.filter(~manager.user_group_model.group_id.in_(query_root_group_id))
77+
.scalar()
78+
)
79+
# 获取当前分页条件下查询到的非Root组的用户id
80+
current_page_user_ids = (
81+
db.session.query(manager.user_group_model.user_id)
82+
.filter(~manager.user_group_model.group_id.in_(query_root_group_id))
83+
.group_by(manager.user_group_model.user_id)
8484
.offset(g.offset)
8585
.limit(g.count)
86-
.all()
8786
)
88-
89-
# 获取 符合条件的 用户id 数量
90-
# 过滤root 分组
91-
_total = db.session.query(
92-
func.count(func.distinct(manager.user_group_model.user_id))
93-
).filter(~manager.user_group_model.group_id.in_(query_root_group_id))
94-
if g.group_id:
95-
_total = _total.filter(manager.user_group_model.group_id == g.group_id)
96-
total = _total.scalar()
97-
98-
# 获取本次需要返回的用户的数据
99-
user_ids = [x.user_id for x in user_groups_list]
100-
users = manager.user_model.query.filter(manager.user_model.id.in_(user_ids)).all()
101-
user_dict = dict()
102-
for user in users:
103-
user.groups = list()
104-
user._fields.append("groups")
105-
user_dict[user.id] = user
106-
107-
# 使用用户组来过滤,则不需要补全用户组信息
108-
if not g.group_id:
109-
# 拿到本次请求返回用户的所有 用户组 id List
110-
group_ids = [
111-
int(i)
112-
for i in set().union(*(x.group_ids.split(",") for x in user_groups_list))
113-
]
114-
# 获取本次需要返回的用户组的数据
115-
groups = manager.group_model.query.filter(
116-
manager.group_model.id.in_(group_ids)
117-
).all()
118-
group_dict = dict()
119-
for group in groups:
120-
group_dict[group.id] = group
121-
items = []
122-
123-
# 根据 用户与用户组 一对多的关系, 补全用户的用户组详细信息
124-
for user_id, group_ids in user_groups_list:
125-
group_id_list = [int(gid) for gid in group_ids.split(",")]
126-
groups = [group_dict[group_id] for group_id in group_id_list]
127-
user_dict[user_id].groups = groups
128-
items.append(user_dict[user_id])
129-
130-
total_page = math.ceil(total / g.count)
131-
page = get_page_from_query()
132-
return AdminUserPageSchema(
133-
count=g.count, total=total, total_page=total_page, page=page, items=users
87+
# 获取用户的基本信息
88+
current_page_users = manager.user_model.query.filter(
89+
manager.user_model.id.in_(current_page_user_ids)
90+
).all()
91+
# 获取需要填充分组的基本信息
92+
current_groups = manager.group_model.query.filter(
93+
manager.group_model.id.in_(
94+
db.session.query(manager.user_group_model.group_id)
95+
.filter(manager.user_group_model.user_id.in_(current_page_user_ids))
96+
.group_by(manager.user_group_model.group_id)
97+
)
98+
).all()
99+
# 获取这些用户和分组的多对多关联关系
100+
user_group_relations = (
101+
db.session.query(manager.user_group_model)
102+
.filter(manager.user_group_model.user_id.in_(current_page_user_ids))
103+
.all()
134104
)
105+
# 根据关联关系拼装的items数据结构
106+
items = [
107+
AdminUserSchema(
108+
email=user.email, groups=list(), id=user.id, username=user.username
109+
)
110+
for user in current_page_users
111+
]
112+
# 填充分组信息
113+
for item in items:
114+
for ug in user_group_relations:
115+
if ug.user_id == item.id:
116+
for group in current_groups:
117+
if ug.group_id == group.id:
118+
item.groups.append(group)
119+
120+
return {
121+
"items": items,
122+
"count": g.count,
123+
"page": g.page,
124+
"total": total,
125+
"total_page": math.ceil(total / g.count),
126+
}
135127

136128

137129
@admin_api.route("/user/<int:uid>/password", methods=["PUT"])

app/api/cms/schema/admin.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ class AdminUserPageSchema(BasePageSchema):
2828
items: List[AdminUserSchema]
2929

3030

31-
class GroupQuerySearchSchema(QueryPageSchema):
32-
group_id: Optional[int] = Field(gt=0, description="用户组ID")
33-
34-
3531
class UpdateUserInfoSchema(GroupIdListSchema, EmailSchema):
3632
pass
3733

app/api/cms/schema/user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class PermissionModuleSchema(BaseModel):
3333

3434
class UserBaseInfoSchema(EmailSchema):
3535
nickname: Optional[str] = Field(description="用户昵称", min_length=2, max_length=10)
36-
avatar: Optional[AnyHttpUrl] = Field(description="头像url")
36+
avatar: Optional[str] = Field(description="头像url")
3737

3838

3939
class UserSchema(UserBaseInfoSchema):

app/api/cms/user.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
:copyright: © 2020 by the Lin team.
55
:license: MIT, see LICENSE for more details.
66
"""
7+
import jwt
78
from flask import Blueprint, current_app, g, request
89
from flask_jwt_extended import (
910
create_access_token,
@@ -12,7 +13,6 @@
1213
get_jwt_identity,
1314
verify_jwt_in_request,
1415
)
15-
from itsdangerous import JSONWebSignatureSerializer as JWSSerializer
1616
from lin import (
1717
DocResponse,
1818
Duplicated,
@@ -100,8 +100,7 @@ def login(json: LoginSchema):
100100
if current_app.config.get("LOGIN_CAPTCHA"):
101101
tag = request.headers.get("tag")
102102
secret_key = current_app.config.get("SECRET_KEY")
103-
serializer = JWSSerializer(secret_key)
104-
if g.captcha != serializer.loads(tag):
103+
if g.captcha != jwt.decode(tag, secret_key, algorithms=["HS256"]).get("code"):
105104
raise Failed("验证码校验失败") # type: ignore
106105

107106
user = manager.user_model.verify(g.username, g.password)
@@ -251,6 +250,5 @@ def get_captcha():
251250
return CaptchaSchema() # type: ignore
252251
image, code = CaptchaTool().get_verify_code()
253252
secret_key = current_app.config.get("SECRET_KEY")
254-
serializer = JWSSerializer(secret_key)
255-
tag = serializer.dumps(code)
253+
tag = jwt.encode({"code": code}, secret_key, algorithm="HS256")
256254
return {"tag": tag, "image": image}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ default = true
1111

1212
[tool.poetry.dependencies]
1313
python = "^3.8"
14-
Lin-CMS = "^0.4.5"
14+
Lin-CMS = "^0.4.7"
1515
pillow = "^9.0.0"
1616
flask-cors = "^3.0.10"
1717
gunicorn = "^20.1.0"

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Lin-CMS==0.4.5
1+
Lin-CMS==0.4.7
22
pillow==9.0.0
33
flask-cors==3.0.10
44
gunicorn==20.1.0

requirements-prod.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Lin-CMS==0.4.5
1+
Lin-CMS==0.4.7
22
pillow==9.0.0
33
flask-cors==3.0.10
44
gunicorn==20.1.0

0 commit comments

Comments
 (0)