Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/permission NEW permission system #440

Open
wants to merge 36 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8f189dd
feat(permission): Add new models
DoyunShin Jan 9, 2024
9344b54
refactor(calendar): move meta to top
DoyunShin Jan 9, 2024
9ed4cb9
feat(permission): Fix all permission function request to new one.
DoyunShin Jan 9, 2024
b5be2b0
feat(permission): remove related name from models
DoyunShin Jan 9, 2024
0038fed
feat(permission): move org_type to groups
DoyunShin Jan 9, 2024
62eca9f
feat(permission): add permission admin page
DoyunShin Jan 9, 2024
6dc93d7
refactor(permission): clear all imports and type hints
DoyunShin Jan 9, 2024
e9e2cb9
fix(permission): Remove deleted column
DoyunShin Jan 9, 2024
3ae56e4
fix(permission): Fix unique_together column name
DoyunShin Jan 9, 2024
d7f119a
refactor(permission): remove _id names and fix some of type hints
DoyunShin Jan 9, 2024
4632984
refactor(permission): Fix type hinting
DoyunShin Jan 9, 2024
706cf12
refactor(permission): add annotation
DoyunShin Jan 9, 2024
e4b7544
feat(permission): Remove all bitmasks
DoyunShin Jan 9, 2024
7d0861c
fix(permission): Fix UserGroup PK
DoyunShin Jan 10, 2024
49fb8f6
fix(permission): Resotre org_type on manual
DoyunShin Jan 10, 2024
33546bb
fix(permission): Remove every OldUserGroup
DoyunShin Jan 10, 2024
226d1d8
fix(permission): Fix BoardPermission legacy codes
DoyunShin Jan 10, 2024
cdc2eff
fix(permission): Add default groups on test
DoyunShin Jan 10, 2024
5708cff
feat(permission): Migration file
DoyunShin Jan 10, 2024
6c39c24
fix(permission): Fix UserProfile to User
DoyunShin Jan 11, 2024
234f023
fix(permission): Add all board permissions
DoyunShin Jan 11, 2024
2bea426
refactor(permission): remove unnecessery prints
DoyunShin Jan 11, 2024
e4ad24a
refactor(permission): Remove Old Structures
DoyunShin Jan 11, 2024
0d53fe8
refactor(permission): move meta to down
DoyunShin Jan 11, 2024
2e80713
refactor(permission): Remove Old Structures
DoyunShin Jan 11, 2024
193a912
fix(permission): Restore manualuser org_type
DoyunShin Jan 11, 2024
4df23e8
refactor(permission): Remove commit in migration
DoyunShin Jan 16, 2024
be94d66
fix(permission): Revert org_type null=False
DoyunShin Jan 16, 2024
529c709
fix(permission): Check is_school_admin not has_group_by_id
DoyunShin Jan 16, 2024
c1a6d80
fix(permission): groups cached property, argument names, any() function
DoyunShin Jan 16, 2024
1f43ed0
fix(permission): Fix default official groups
DoyunShin Jan 16, 2024
283468e
fix(permission): Remove by_name functions
DoyunShin Jan 16, 2024
32ef449
fix(permission): Use Group join
DoyunShin Jan 16, 2024
3e12f68
refactor(permission): use annotations for self typing
injoonH Jan 23, 2024
c71e9f2
chore(permission): remove unused imports
injoonH Jan 23, 2024
3a22da3
fix(permission): fix admin page for `UserGroup`
injoonH Jan 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Generated by Django 4.2.3 on 2024-01-10 17:16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ 파일명 0059_remove_board_comment_access_mask_and_more.py로 수정해야 합니다.


import django.db.models.deletion
from django.db import migrations, models

from apps.core.models import BoardAccessPermissionType


def move_board_permissions(apps, schema_editor):
Board = apps.get_model("core", "Board")
BoardPermission = apps.get_model("core", "BoardPermission")
Group = apps.get_model("user", "Group")
for board in Board.objects.all():
read_access_mask = board.read_access_mask
write_access_mask = board.write_access_mask
comment_access_mask = board.comment_access_mask

for group in Group.objects.all():
read = bool((read_access_mask & (1 << (group.group_id - 1))) > 0)
write = bool((write_access_mask & (1 << (group.group_id - 1))) > 0)
comment = bool((comment_access_mask & (1 << (group.group_id - 1))) > 0)

if read:
BoardPermission.objects.create(
board=board,
group=group,
permission=BoardAccessPermissionType.READ,
)
if write:
BoardPermission.objects.create(
board=board,
group=group,
permission=BoardAccessPermissionType.WRITE,
)
if comment:
BoardPermission.objects.create(
board=board,
group=group,
permission=BoardAccessPermissionType.COMMENT,
)


class Migration(migrations.Migration):
dependencies = [
("user", "0022_group_remove_userprofile_group_and_more"),
("core", "0057_alter_article_name_type_and_more"),
]

operations = [
migrations.CreateModel(
name="BoardPermission",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("permission", models.SmallIntegerField(verbose_name="permission")),
(
"board",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="core.board",
verbose_name="board slug",
),
),
(
"group",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="user.group",
verbose_name="group",
),
),
],
options={
"verbose_name": "BoardPermission",
"verbose_name_plural": "BoardPermissions",
"unique_together": {("group", "board", "permission")},
},
),
migrations.RunPython(move_board_permissions),
migrations.RemoveField(
model_name="board",
name="comment_access_mask",
),
migrations.RemoveField(
model_name="board",
name="read_access_mask",
),
migrations.RemoveField(
model_name="board",
name="write_access_mask",
),
]
1 change: 1 addition & 0 deletions apps/core/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .block import *
from .board import *
from .board_group import *
from .board_permission import *
from .comment import *
from .comment_log import *
from .communication_article import *
Expand Down
8 changes: 3 additions & 5 deletions apps/core/models/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
)

from .block import Block
from .board import BoardAccessPermissionType, NameType
from .board import Board, NameType
from .comment import Comment
from .communication_article import SchoolResponseStatus
from .report import Report
Expand Down Expand Up @@ -111,7 +111,7 @@ class Article(MetaDataModel):
db_index=True,
default=None,
)
parent_board = models.ForeignKey(
parent_board: Board = models.ForeignKey(
verbose_name="게시판",
to="core.Board",
on_delete=models.CASCADE,
Expand Down Expand Up @@ -315,9 +315,7 @@ def hidden_reasons(self, user: User) -> list:
if self.is_content_social and not user.profile.see_social:
reasons.append(ArticleHiddenReason.SOCIAL_CONTENT)
# 혹시 몰라 여기 두기는 하는데 여기 오기전에 Permission에서 막혀야 함
if not self.parent_board.group_has_access_permission(
BoardAccessPermissionType.READ, user.profile.group
):
if not self.parent_board.permission_list_by_user(user).READ:
reasons.append(ArticleHiddenReason.ACCESS_DENIED_CONTENT)

return reasons
54 changes: 15 additions & 39 deletions apps/core/models/board.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from enum import IntEnum, IntFlag, auto
from enum import IntFlag, auto

from django.db import models
from django_extensions.db.fields import AutoSlugField

from apps.user.models import Group
from ara.db.models import MetaDataModel

from .board_group import BoardGroup
from .board_permission import (
DEFAULT_PERMISSIONS,
BoardAccessPermission,
BoardPermission,
)


class NameType(IntFlag):
Expand All @@ -13,12 +20,6 @@ class NameType(IntFlag):
REALNAME = auto()


class BoardAccessPermissionType(IntEnum):
READ = 0
WRITE = 1
COMMENT = 2


class Board(MetaDataModel):
slug = AutoSlugField(
populate_from=["en_name"],
Expand All @@ -32,24 +33,6 @@ class Board(MetaDataModel):
verbose_name="게시판 영문 이름",
max_length=32,
)
# 사용자 그룹에 대해 접근 권한을 제어하는 bit mask 입니다.
# access_mask & (1 << user.group) > 0 일 때 접근이 가능합니다.
# 사용자 그룹의 값들은 `UserGroup`을 참고하세요.
read_access_mask = models.SmallIntegerField(
# UNAUTHORIZED, EXTERNAL_ORG 제외 모든 사용자 읽기 권한 부여
verbose_name="읽기 권한",
default=0b011011110,
)
write_access_mask = models.SmallIntegerField(
# UNAUTHORIZED, STORE_EMPLOYEE, EXTERNAL_ORG 제외 모든 사용자 쓰기 권한 부여
verbose_name="쓰기 권한",
default=0b011011010,
)
comment_access_mask = models.SmallIntegerField(
# UNAUTHORIZED 제외 모든 사용자 댓글 권한 부여
verbose_name="댓글 권한",
default=0b011111110,
)
is_readonly = models.BooleanField(
verbose_name="읽기 전용 게시판",
default=False,
Expand Down Expand Up @@ -113,18 +96,11 @@ class Meta(MetaDataModel.Meta):
def __str__(self) -> str:
return self.ko_name

def group_has_access_permission(
self, access_type: BoardAccessPermissionType, group: int
) -> bool:
mask = None
if access_type == BoardAccessPermissionType.READ:
mask = self.read_access_mask
elif access_type == BoardAccessPermissionType.WRITE:
mask = self.write_access_mask
elif access_type == BoardAccessPermissionType.COMMENT:
mask = self.comment_access_mask
else:
# TODO: Handle error
return False
def permission_list_by_group(self, group: Group) -> BoardAccessPermission:
return BoardPermission.permission_list_by_group(group, self)

def permission_list_by_user(self, user) -> BoardAccessPermission:
return BoardPermission.permission_list_by_user(user, self)

return (mask & (1 << group)) > 0
def set_default_permission(self):
BoardPermission.add_permission_bulk_by_board(self, DEFAULT_PERMISSIONS)
Loading
Loading