"""
admin apis
~~~~~~~~~
:copyright: © 2020 by the Lin team.
:license: MIT, see LICENSE for more details.
"""
import math
from flask import Blueprint, g
from lin import (
DocResponse,
Forbidden,
GroupLevelEnum,
Logger,
NotFound,
ParameterError,
Success,
admin_required,
db,
manager,
permission_meta,
)
from sqlalchemy import func
from app.api import AuthorizationBearerSecurity, api
from app.api.cms.schema import ResetPasswordSchema
from app.api.cms.schema.admin import (
AdminGroupListSchema,
AdminGroupPermissionSchema,
AdminUserPageSchema,
AdminUserSchema,
CreateGroupSchema,
GroupBaseSchema,
GroupIdWithPermissionIdListSchema,
QueryPageWithGroupIdSchema,
UpdateUserInfoSchema,
)
admin_api = Blueprint("admin", __name__)
@admin_api.route("/permission")
@permission_meta(name="查询所有可分配的权限", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
)
def permissions():
"""
查询所有可分配的权限
"""
return manager.get_ep_infos()
@admin_api.route("/users")
@permission_meta(name="查询所有用户", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(r=AdminUserPageSchema),
before=QueryPageWithGroupIdSchema.offset_handler,
)
def get_admin_users(query: QueryPageWithGroupIdSchema):
"""
查询所有用户及其所属组信息
"""
query_group_id = db.session.query(manager.group_model.id).filter(
manager.group_model.level != GroupLevelEnum.ROOT.value
)
if g.group_id:
query_group_id = query_group_id.filter(manager.group_model.id == g.group_id)
total = (
db.session.query(func.count(func.distinct(manager.user_group_model.user_id)))
.filter(manager.user_group_model.group_id.in_(query_group_id))
.scalar()
)
query_current_page_user_ids = (
db.session.query(manager.user_group_model.user_id)
.filter(manager.user_group_model.group_id.in_(query_group_id))
.group_by(manager.user_group_model.user_id)
.offset(g.offset)
.limit(g.count)
)
current_page_user_ids = [user_id[0] for user_id in query_current_page_user_ids.all()]
current_page_users = manager.user_model.query.filter(manager.user_model.id.in_(current_page_user_ids)).all()
current_groups = manager.group_model.query.filter(
manager.group_model.id.in_(
db.session.query(manager.user_group_model.group_id)
.filter(manager.user_group_model.user_id.in_(current_page_user_ids))
.group_by(manager.user_group_model.group_id)
)
).all()
user_group_relations = (
db.session.query(manager.user_group_model)
.filter(manager.user_group_model.user_id.in_(current_page_user_ids))
.all()
)
items = [
AdminUserSchema(email=user.email, groups=list(), id=user.id, username=user.username)
for user in current_page_users
]
for item in items:
for ug in user_group_relations:
if ug.user_id == item.id:
for group in current_groups:
if ug.group_id == group.id:
item.groups.append(group)
return {
"items": items,
"count": g.count,
"page": g.page,
"total": total,
"total_page": math.ceil(total / g.count),
}
@admin_api.route("/user/<int:uid>/password", methods=["PUT"])
@permission_meta(name="修改用户密码", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
resp=DocResponse(NotFound("用户不存在"), Success("密码修改成功")),
security=[AuthorizationBearerSecurity],
)
def change_user_password(uid: int, json: ResetPasswordSchema):
"""
修改用户密码
"""
user = manager.find_user(id=uid)
if not user:
raise NotFound("用户不存在")
with db.auto_commit():
user.reset_password(g.new_password)
return Success("密码修改成功")
@admin_api.route("/user/<int:uid>", methods=["DELETE"])
@permission_meta(name="删除用户", module="管理员", mount=False)
@Logger(template="管理员删除了一个用户")
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(NotFound("用户不存在"), Success("删除成功"), Forbidden("用户不能删除")),
)
def delete_user(uid):
"""
删除用户
"""
user = manager.user_model.get(id=uid)
if user is None:
raise NotFound("用户不存在")
groups = manager.group_model.select_by_user_id(uid)
if groups[0].level == GroupLevelEnum.ROOT.value:
raise Forbidden("无法删除此用户")
with db.auto_commit():
manager.user_group_model.query.filter_by(user_id=uid).delete(synchronize_session=False)
user.hard_delete()
return Success("操作成功")
@admin_api.route("/user/<int:uid>", methods=["PUT"])
@permission_meta(name="管理员更新用户信息", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(
NotFound("用户不存在"),
Success("更新成功"),
ParameterError("邮箱已被注册,请重新输入邮箱"),
),
)
def update_user(uid: int, json: UpdateUserInfoSchema):
"""
更新用户信息
"""
user = manager.user_model.get(id=uid)
if user is None:
raise NotFound("用户不存在")
if user.email != g.email:
exists = manager.user_model.get(email=g.email)
if exists:
raise ParameterError("邮箱已被注册,请重新输入邮箱")
with db.auto_commit():
user.email = g.email
group_ids = g.group_ids
manager.user_group_model.query.filter_by(user_id=user.id).delete(synchronize_session=False)
user_group_list = list()
if not group_ids:
group_ids = [manager.group_model.get(level=GroupLevelEnum.GUEST.value).id]
for group_id in group_ids:
user_group = manager.user_group_model()
user_group.user_id = user.id
user_group.group_id = group_id
user_group_list.append(user_group)
db.session.add_all(user_group_list)
return Success("操作成功")
@admin_api.route("/group/all")
@permission_meta(name="查询所有分组", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(NotFound("不存在任何分组"), r=AdminGroupListSchema),
)
def get_all_group():
"""
获取所有分组
"""
groups = manager.group_model.query.filter(
manager.group_model.is_deleted is False,
manager.group_model.level != GroupLevelEnum.ROOT.value,
).all()
if groups is None:
raise NotFound("不存在任何分组")
return groups
@admin_api.route("/group/<int:gid>")
@permission_meta(name="查询一个分组及其权限", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(NotFound("分组不存在"), r=AdminGroupPermissionSchema),
)
def get_group(gid):
"""
获取一个分组及其权限
"""
group = manager.group_model.get(id=gid, one=True, soft=False)
if group is None:
raise NotFound("分组不存在")
group_permissions = manager.permission_model.select_by_group_id(gid)
setattr(group, "permissions", group_permissions)
group._fields.append("permissions")
return group
@admin_api.route("/group", methods=["POST"])
@permission_meta(name="新建分组", module="管理员", mount=False)
@Logger(template="管理员新建了一个分组")
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(
ParameterError("用户组已存在, 不可创建同名分组"),
Success("新建用户组成功"),
),
)
def create_group(json: CreateGroupSchema):
"""
新建分组
"""
exists = manager.group_model.get(name=g.name)
if exists:
raise Forbidden("分组已存在,不可创建同名分组")
with db.auto_commit():
group = manager.group_model.create(
name=g.name,
info=g.info,
)
db.session.flush()
group_permission_list = list()
for permission_id in g.permission_ids:
gp = manager.group_permission_model()
gp.group_id = group.id
gp.permission_id = permission_id
group_permission_list.append(gp)
db.session.add_all(group_permission_list)
return Success("新建分组成功")
@admin_api.route("/group/<int:gid>", methods=["PUT"])
@permission_meta(name="更新一个分组", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(
ParameterError("分组不存在,更新失败"),
Success("更新分组成功"),
),
)
def update_group(gid, json: GroupBaseSchema):
"""
更新一个分组基本信息
"""
exists = manager.group_model.get(id=gid)
if not exists:
raise NotFound("分组不存在,更新失败")
exists.update(name=g.name, info=g.info, commit=True)
return Success("更新成功")
@admin_api.route("/group/<int:gid>", methods=["DELETE"])
@permission_meta(name="删除一个分组", module="管理员", mount=False)
@Logger(template="管理员删除一个分组")
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(NotFound("分组不存在,删除失败"), Forbidden("分组不可删除"), Success("删除分组成功")),
)
def delete_group(gid):
"""
删除一个分组
"""
exist = manager.group_model.get(id=gid)
if not exist:
raise NotFound("分组不存在,删除失败")
guest_group = manager.group_model.get(level=GroupLevelEnum.GUEST.value)
root_group = manager.group_model.get(level=GroupLevelEnum.ROOT.value)
if gid in (guest_group.id, root_group.id):
raise Forbidden("不可删除此分组")
if manager.user_model.select_page_by_group_id(gid, root_group.id):
raise Forbidden("分组下存在用户,不可删除")
with db.auto_commit():
manager.group_permission_model.query.filter_by(group_id=gid).delete(synchronize_session=False)
exist.delete()
return Success("删除分组成功")
@admin_api.route("/permission/dispatch/batch", methods=["POST"])
@permission_meta(name="分配多个权限", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
security=[AuthorizationBearerSecurity],
resp=DocResponse(
Success("添加权限成功"),
),
)
def dispatch_auths(json: GroupIdWithPermissionIdListSchema):
"""
分配多个权限
"""
with db.auto_commit():
for permission_id in g.permission_ids:
one = manager.group_permission_model.get(group_id=g.group_id, permission_id=permission_id)
if not one:
manager.group_permission_model.create(
group_id=g.group_id,
permission_id=permission_id,
)
return Success("添加权限成功")
@admin_api.route("/permission/remove", methods=["POST"])
@permission_meta(name="删除多个权限", module="管理员", mount=False)
@admin_required
@api.validate(
tags=["管理员"],
resp=DocResponse(Success("删除权限成功")),
security=[AuthorizationBearerSecurity],
)
def remove_auths(json: GroupIdWithPermissionIdListSchema):
"""
删除多个权限
"""
with db.auto_commit():
db.session.query(manager.group_permission_model).filter(
manager.group_permission_model.permission_id.in_(g.permission_ids),
manager.group_permission_model.group_id == g.group_id,
).delete(synchronize_session=False)
return Success("删除权限成功")