Skip to content

Commit

Permalink
Commit WIP post reply code and new permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalp committed Sep 24, 2024
1 parent e122d95 commit de12440
Show file tree
Hide file tree
Showing 9 changed files with 505 additions and 29 deletions.
2 changes: 2 additions & 0 deletions misago/permissions/hooks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
check_post_in_closed_thread_permission_hook,
)
from .check_private_threads_permission import check_private_threads_permission_hook
from .check_reply_thread_permission import check_reply_thread_permission_hook
from .check_see_category_permission import check_see_category_permission_hook
from .check_see_private_thread_permission import (
check_see_private_thread_permission_hook,
Expand Down Expand Up @@ -46,6 +47,7 @@
"check_post_in_closed_category_permission_hook",
"check_post_in_closed_thread_permission_hook",
"check_private_threads_permission_hook",
"check_reply_thread_permission_hook",
"check_see_category_permission_hook",
"check_see_private_thread_permission_hook",
"check_see_thread_permission_hook",
Expand Down
119 changes: 119 additions & 0 deletions misago/permissions/hooks/check_post_in_closed_thread_permission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from typing import TYPE_CHECKING, Protocol

from ...plugins.hooks import FilterHook
from ...threads.models import Thread

if TYPE_CHECKING:
from ..proxy import UserPermissionsProxy


class CheckPostInClosedThreadPermissionHookAction(Protocol):
"""
A standard Misago function used to check if the user has permission to
post in a closed thread. It raises Django's `PermissionDenied` with an
error message if thread is closed and they can't post in it.
# Arguments
## `user_permissions: UserPermissionsProxy`
A proxy object with the current user's permissions.
## `thread: Thread`
A thread to check permissions for.
"""

def __call__(
self,
permissions: "UserPermissionsProxy",
thread: Thread,
) -> None: ...


class CheckPostInClosedThreadPermissionHookFilter(Protocol):
"""
A function implemented by a plugin that can be registered in this hook.
# Arguments
## `action: CheckPostInClosedThreadPermissionHookAction`
A standard Misago function used to check if the user has permission to
post in a closed thread. It raises Django's `PermissionDenied` with an
error message if thread is closed and they can't post in it.
See the [action](#action) section for details.
## `user_permissions: UserPermissionsProxy`
A proxy object with the current user's permissions.
## `thread: Thread`
A thread to check permissions for.
"""

def __call__(
self,
action: CheckPostInClosedThreadPermissionHookAction,
permissions: "UserPermissionsProxy",
thread: Thread,
) -> None: ...


class CheckPostInClosedThreadPermissionHook(
FilterHook[
CheckPostInClosedThreadPermissionHookAction,
CheckPostInClosedThreadPermissionHookFilter,
]
):
"""
This hook wraps the standard function that Misago uses to check if the user
has permission to post in a closed thread. It raises Django's `PermissionDenied`
with an error message if thread is closed and they can't post in it.
# Example
The code below implements a custom filter function that permits a user to
post in the specific thread if they have a custom flag set on their account.
```python
from misago.permissions.hooks import check_post_in_closed_thread_permission_hook
from misago.permissions.proxy import UserPermissionsProxy
from misago.threads.models import Thread
@check_post_in_closed_thread_permission_hook.append_filter
def check_user_can_post_in_closed_thread(
action,
permissions: UserPermissionsProxy,
thread: Thread,
) -> None:
user = permissions.user
if user.is_authenticated:
post_in_closed_categories = (
user.plugin_data.get("post_in_closed_threads") or []
)
else:
post_in_closed_categories = None
if (
not post_in_closed_categories
or thread.id not in post_in_closed_categories
):
action(permissions, thread)
```
"""

__slots__ = FilterHook.__slots__

def __call__(
self,
action: CheckPostInClosedThreadPermissionHookAction,
permissions: "UserPermissionsProxy",
thread: Thread,
) -> None:
return super().__call__(action, permissions, thread)


check_post_in_closed_thread_permission_hook = CheckPostInClosedThreadPermissionHook()
130 changes: 130 additions & 0 deletions misago/permissions/hooks/check_reply_thread_permission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from typing import TYPE_CHECKING, Protocol

from ...categories.models import Category
from ...plugins.hooks import FilterHook
from ...threads.models import Thread

if TYPE_CHECKING:
from ..proxy import UserPermissionsProxy


class CheckReplyThreadPermissionHookAction(Protocol):
"""
A standard Misago function used to check if the user has permission to
reply to a thread. It raises Django's `PermissionDenied` with an
error message if they can't reply to it.
# Arguments
## `user_permissions: UserPermissionsProxy`
A proxy object with the current user's permissions.
## `category: Category`
A category to check permissions for.
## `thread: Thread`
A thread to check permissions for.
"""

def __call__(
self,
permissions: "UserPermissionsProxy",
category: Category,
thread: Thread,
) -> None: ...


class CheckReplyThreadPermissionHookFilter(Protocol):
"""
A function implemented by a plugin that can be registered in this hook.
# Arguments
## `action: CheckReplyThreadPermissionHookAction`
A standard Misago function used to check if the user has permission to
reply to a thread. It raises Django's `PermissionDenied` with an
error message if they can't reply to it.
See the [action](#action) section for details.
## `user_permissions: UserPermissionsProxy`
A proxy object with the current user's permissions.
## `category: Category`
A category to check permissions for.
## `thread: Thread`
A thread to check permissions for.
"""

def __call__(
self,
action: CheckReplyThreadPermissionHookAction,
permissions: "UserPermissionsProxy",
category: Category,
thread: Thread,
) -> None: ...


class CheckReplyThreadPermissionHook(
FilterHook[
CheckReplyThreadPermissionHookAction,
CheckReplyThreadPermissionHookFilter,
]
):
"""
This hook wraps the standard function that Misago uses to check if the user
has permission to reply to a thread. It raises Django's `PermissionDenied`
with an error message if they can't post in it.
# Example
The code below implements a custom filter function that prevents a user from
replying to a thread if they are thread's starter, but only in categories
with a plugin flag.
```python
from django.core.exceptions import PermissionDenied
from misago.categories.models import Category
from misago.permissions.hooks import check_reply_thread_permission_hook
from misago.permissions.proxy import UserPermissionsProxy
from misago.threads.models import Thread
@check_reply_thread_permission_hook.append_filter
def check_user_can_post_in_closed_thread(
action,
permissions: UserPermissionsProxy,
category: Category,
thread: Thread,
) -> None:
user = permissions.user
if (
category.plugin_data.get("block_starters")
and user.is_authenticated and user.id == thread.starter_id
):
raise PermissionDenied("You can't reply to threads you've started.")
action(permissions, category, thread)
```
"""

__slots__ = FilterHook.__slots__

def __call__(
self,
action: CheckReplyThreadPermissionHookAction,
permissions: "UserPermissionsProxy",
category: Category,
thread: Thread,
) -> None:
return super().__call__(action, permissions, category, thread)


check_reply_thread_permission_hook = CheckReplyThreadPermissionHook()
Loading

0 comments on commit de12440

Please sign in to comment.