Skip to content

Commit

Permalink
feat: BaseAuthFieldModelAdmin add the perm_fields attribute and add t…
Browse files Browse the repository at this point in the history
…he test file
  • Loading branch information
amisadmin committed Sep 19, 2023
1 parent 120ddbc commit 44ee8a7
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 8 deletions.
18 changes: 12 additions & 6 deletions fastapi_amis_admin/admin/extensions/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ class BaseAuthFieldModelAdmin(ModelAdmin):
#todo 优化
"""

perm_fields: Dict[Union[FieldPermEnum, int], Sequence[str]] = None
"""指定的字段,进行权限验证."""
perm_fields_exclude: Dict[Union[FieldPermEnum, int], Sequence[str]] = None
"""exclude指定的字段,不进行权限验证."""

Expand All @@ -120,8 +122,6 @@ def __init__(self, app: "AdminApp"):

def get_permission_fields(self, action: str) -> Dict[str, str]:
"""获取权限字段"""
if not self.perm_fields_exclude:
return {}
info = {
"list": (self.schema_list, "列表展示-", FieldPermEnum.LIST),
"filter": (self.schema_filter, "列表筛选-", FieldPermEnum.FILTER),
Expand All @@ -132,11 +132,17 @@ def get_permission_fields(self, action: str) -> Dict[str, str]:
if action not in info:
return {}
schema, prefix, perm = info[action]
exlude = set()
for k, fileds in self.perm_fields_exclude.items():
perm_fields_exclude = self.perm_fields_exclude or {}
perm_fields = self.perm_fields or {}
exclude = set()
for k, fields in perm_fields_exclude.items():
if (k & perm) == perm:
exclude.update(set(fields))
include = set()
for k, fields in perm_fields.items():
if (k & perm) == perm:
exlude.update(set(fileds))
return get_schema_fields_name_label(schema, prefix=prefix, exclude_required=True, exclude=exlude)
include.update(set(fields))
return get_schema_fields_name_label(schema, prefix=prefix, exclude_required=True, exclude=exclude, include=include)

@cached_property
def create_permission_fields(self) -> Dict[str, str]:
Expand Down
1 change: 1 addition & 0 deletions fastapi_amis_admin/admin/extensions/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class RecentTimeSelectPerm(SelectPerm):
time_column: str = "create_time"

def __post_init__(self):
super().__post_init__()
# 如果td为int,则表示秒数
self.td = timedelta(seconds=self.td) if isinstance(self.td, int) else self.td

Expand Down
7 changes: 5 additions & 2 deletions fastapi_amis_admin/admin/extensions/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@ def get_schema_fields_name_label(
prefix: str = "",
exclude_required: bool = False,
exclude: Iterable[str] = None,
include: Iterable[str] = None,
) -> Dict[str, str]:
"""获取schema字段名和标签.如果exclude中包含__all__,则返回空字典."""
if not schema:
return {}
if exclude and "__all__" in exclude:
exclude = set(exclude or [])
if "__all__" in exclude:
return {}
include = set(include or ["__all__"])
fields = {}
for field in model_fields(schema).values():
if exclude_required and field.required:
continue
name = field.alias or field.name
if exclude and name in exclude:
if name in exclude or (name not in include and "__all__" not in include):
continue
label = field.field_info.title or field.name
fields[name] = prefix + label
Expand Down
Empty file.
143 changes: 143 additions & 0 deletions tests/test_admin/test_extensions/test_BaseAuthFieldModelAdmin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
from fastapi_amis_admin import admin
from fastapi_amis_admin.admin import AdminSite, FieldPermEnum


async def test_perm_fields(site: AdminSite, models):
@site.register_admin
class ArticleAdmin(admin.BaseAuthFieldModelAdmin):
model = models.Article
read_fields = [
models.Article.id,
models.Article.title,
models.Article.description,
models.Article.status,
models.Article.category_id,
]
perm_fields = {
FieldPermEnum.VIEW: ["id", "title"],
FieldPermEnum.UPDATE: ["status"],
FieldPermEnum.CREATE: ["description", "status"],
}

site.register_router()
ins = site.get_admin_or_create(ArticleAdmin)
# create_permission_fields
assert "description" in ins.create_permission_fields
assert "status" in ins.create_permission_fields
assert "category_id" not in ins.create_permission_fields

# update_permission_fields
assert "status" in ins.update_permission_fields
assert "category_id" not in ins.update_permission_fields

# read_permission_fields
assert "id" in ins.read_permission_fields
# title not in read_permission_fields, because title is required in schema_read
assert "title" not in ins.read_permission_fields
assert "category_id" not in ins.read_permission_fields

# list_permission_fields
assert "id" in ins.list_permission_fields
assert "title" in ins.list_permission_fields
assert "category_id" not in ins.create_permission_fields

# filter_permission_fields
assert "id" in ins.filter_permission_fields
assert "title" in ins.filter_permission_fields
assert "category_id" not in ins.create_permission_fields


async def test_perm_fields_exclude(site: AdminSite, models):
@site.register_admin
class ArticleAdmin(admin.BaseAuthFieldModelAdmin):
model = models.Article
read_fields = [
models.Article.id,
models.Article.title,
models.Article.description,
models.Article.status,
models.Article.category_id,
]
perm_fields_exclude = {
FieldPermEnum.VIEW: ["id", "title"],
FieldPermEnum.UPDATE: ["status"],
FieldPermEnum.CREATE: ["description", "status"],
}

site.register_router()
ins = site.get_admin_or_create(ArticleAdmin)
# create_permission_fields
assert "description" not in ins.create_permission_fields
assert "status" not in ins.create_permission_fields
assert "category_id" in ins.create_permission_fields

# update_permission_fields
assert "status" not in ins.update_permission_fields
assert "category_id" in ins.update_permission_fields

# read_permission_fields
assert "id" not in ins.read_permission_fields
# title not in read_permission_fields, because title is required in schema_read
assert "title" not in ins.read_permission_fields
assert "category_id" in ins.read_permission_fields

# list_permission_fields
assert "id" not in ins.list_permission_fields
assert "title" not in ins.list_permission_fields
assert "category_id" in ins.create_permission_fields

# filter_permission_fields
assert "id" not in ins.filter_permission_fields
assert "title" not in ins.filter_permission_fields
assert "category_id" in ins.create_permission_fields


async def test_perm_fields_and_exclude(site: AdminSite, models):
@site.register_admin
class ArticleAdmin(admin.BaseAuthFieldModelAdmin):
model = models.Article
read_fields = [
models.Article.id,
models.Article.title,
models.Article.description,
models.Article.status,
models.Article.category_id,
]
perm_fields = {
FieldPermEnum.VIEW: ["id", "title"],
FieldPermEnum.UPDATE: ["status", "title"],
FieldPermEnum.CREATE: ["description", "status"],
}
perm_fields_exclude = {
FieldPermEnum.VIEW: ["title"],
FieldPermEnum.UPDATE: ["status"],
FieldPermEnum.CREATE: ["description"],
}

site.register_router()
ins = site.get_admin_or_create(ArticleAdmin)
# create_permission_fields
assert "description" not in ins.create_permission_fields
assert "status" in ins.create_permission_fields
assert "category_id" not in ins.create_permission_fields

# update_permission_fields
assert "title" in ins.update_permission_fields
assert "status" not in ins.update_permission_fields
assert "category_id" not in ins.update_permission_fields

# read_permission_fields
assert "id" in ins.read_permission_fields
# title not in read_permission_fields, because title is required in schema_read
assert "title" not in ins.read_permission_fields
assert "category_id" not in ins.read_permission_fields

# list_permission_fields
assert "id" in ins.list_permission_fields
assert "title" not in ins.list_permission_fields
assert "category_id" not in ins.create_permission_fields

# filter_permission_fields
assert "id" in ins.filter_permission_fields
assert "title" not in ins.filter_permission_fields
assert "category_id" not in ins.create_permission_fields

0 comments on commit 44ee8a7

Please sign in to comment.