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

New permissions framework #1705

Merged
merged 106 commits into from Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
c8c201a
Data model for new permissions
rafalp Dec 21, 2023
f84cfdd
Test permissions id function
rafalp Dec 21, 2023
944a1d9
Small model updates
rafalp Dec 21, 2023
24fbd81
Add some fields to users group
rafalp Dec 21, 2023
1f639c8
Improve default data fixtures
rafalp Dec 21, 2023
31a7eb7
First category perms, fix tests exploding
rafalp Dec 21, 2023
63bf5cc
Tweak category permissions enum
rafalp Dec 21, 2023
870d611
Create user with group and secondary groups, group model tweaks
rafalp Dec 22, 2023
bc520d0
WIP groups in user admin, new admin permission
rafalp Dec 22, 2023
0117c53
is root admin -> is misago root
rafalp Dec 22, 2023
5f5b677
More tweaks to data model
rafalp Dec 22, 2023
f586561
WIP new user admin perms
rafalp Dec 22, 2023
6aab883
WIP user admin update
rafalp Dec 25, 2023
ac4fd82
More work on new/edit user form
rafalp Dec 25, 2023
cbe66c1
Add tests for admin changing other admins emails
rafalp Dec 25, 2023
b929963
User edit admin form
rafalp Dec 26, 2023
f02087a
Search users in admin
rafalp Dec 26, 2023
423329f
Add mass delete users test for admins and root admins
rafalp Dec 26, 2023
02279f9
Split users admin forms.py file
rafalp Dec 26, 2023
1e1b5f2
Fix admin context processor and admin form rendering
rafalp Dec 26, 2023
168bb7c
Fix legal agreements tests
rafalp Dec 26, 2023
1035e27
Fix custom profile field tests
rafalp Dec 27, 2023
a26c5ae
Add a help text to group fields
rafalp Dec 27, 2023
9ed7d4b
Fix some permission checks
rafalp Dec 27, 2023
039dba3
Fix tests
rafalp Dec 27, 2023
8a8cb77
WIP admin users groups
rafalp Dec 27, 2023
5898e52
Add tests for count groups members
rafalp Dec 27, 2023
1982475
Add group model tests
rafalp Dec 27, 2023
f20d075
Rename def groups ids to custom groups ids start
rafalp Dec 27, 2023
569e0f6
Fix admin multi-checkbox lists, tweat group model
rafalp Dec 27, 2023
52eda47
Add tests for reorder
rafalp Dec 27, 2023
ad1fcc4
Reorder -> Ordering
rafalp Dec 27, 2023
6334de1
Rename views
rafalp Dec 27, 2023
a5c3cc8
Groups admin tests: list and ordering
rafalp Dec 28, 2023
9921620
Add postgresql utils for deleting models from DB bypassing Django ORM
rafalp Dec 28, 2023
d7fb6af
Format docstrings
rafalp Dec 28, 2023
ed56dc0
Delete group admin action
rafalp Dec 28, 2023
3f1917d
Group delete util
rafalp Dec 28, 2023
76b78fe
Fix tests
rafalp Dec 28, 2023
7cc76b6
More work on groups admin
rafalp Dec 28, 2023
1013754
Make group a default admin action
rafalp Dec 28, 2023
96df026
Small style tweak
rafalp Dec 28, 2023
9f062b8
WIP create new group
rafalp Dec 28, 2023
a623898
Small setup for copy permissions util
rafalp Dec 28, 2023
8bbe5cf
Format code with black
rafalp Dec 28, 2023
e8571b1
Test create_group util
rafalp Dec 29, 2023
cc6238e
Add copy_group_permissions hook
rafalp Dec 29, 2023
d943b74
Copy permissions utils
rafalp Dec 29, 2023
62a9d6f
Add tests for copy category permissions
rafalp Dec 29, 2023
d6a675f
Add tests for new group form
rafalp Dec 29, 2023
b55eaf4
Add tests for new group view
rafalp Dec 29, 2023
81c09ba
update_group utility function
rafalp Dec 29, 2023
9931750
Basic edit group form
rafalp Dec 29, 2023
5dd8f11
Validate group's slug
rafalp Dec 29, 2023
4b2c828
Fix tests
rafalp Dec 29, 2023
eb5a837
Misc tweaks and polish to group edit
rafalp Dec 29, 2023
b678bac
WIP permissions table
rafalp Dec 29, 2023
c0e3939
WIP change perms table to give more space to item names
rafalp Dec 29, 2023
60b4913
Improve permissions table design and markup
rafalp Dec 30, 2023
7c1f9f9
Perms table final look
rafalp Dec 30, 2023
20b800e
Redirect away from perms table if its empty
rafalp Dec 30, 2023
b7d4c0d
Format code with black
rafalp Dec 30, 2023
a69758c
More work on category permissions tables
rafalp Dec 30, 2023
1470dbb
WIP category perms forms
rafalp Dec 31, 2023
7babea1
Group category permissions form
rafalp Dec 31, 2023
a9e3f56
Update docs
rafalp Dec 31, 2023
df4f1e4
Category groups permissions table
rafalp Dec 31, 2023
d0f623f
Begin moderators admin
rafalp Dec 31, 2023
23b8604
WIP user select input
rafalp Jan 2, 2024
9f16072
Hide user select by default
rafalp Jan 2, 2024
5665c0e
WIP moderator forms
rafalp Jan 2, 2024
b581741
Add tests for select user api
rafalp Jan 2, 2024
736158f
WIP moderators admin
rafalp Jan 2, 2024
5dc3455
Move groups admin to misago.admin, prevent default group with mod perms
rafalp Jan 3, 2024
874d501
More work on moderators admin
rafalp Jan 3, 2024
4ccf65e
Small tweaks to admin lists, more work on mods admin
rafalp Jan 3, 2024
4fcc746
Delete moderator admin action
rafalp Jan 3, 2024
57c4859
Tweak admin messages
rafalp Jan 3, 2024
c1d03b5
New moderator form submit button, remove debug print
rafalp Jan 3, 2024
9a8a690
Add tests for moderators list
rafalp Jan 3, 2024
80f8694
New moderator tests
rafalp Jan 3, 2024
809d3dc
Moderator admin
rafalp Jan 3, 2024
5b81bc3
Hide fields from moderator form if global moderator is set
rafalp Jan 3, 2024
ca8f7ab
Add deprecation warnings to ranks and roles
rafalp Jan 3, 2024
467cf63
WIP user permissions
rafalp Jan 3, 2024
4b69890
WIP build permissions
rafalp Jan 3, 2024
12be95d
WIP user perms
rafalp Jan 3, 2024
b63bf62
Category permissions
rafalp Jan 3, 2024
6b66ef3
Get user/anonymous user permissions
rafalp Jan 3, 2024
e6ecc68
Update docs
rafalp Jan 3, 2024
9ab7a7a
Fix default permissions, add build user perms tests
rafalp Jan 3, 2024
5bd6ad3
Categories permissions
rafalp Jan 3, 2024
282b02e
WIP permissions proxy, debug toolbar
rafalp Jan 3, 2024
8d1ec74
Perms proxy
rafalp Jan 3, 2024
8357a5d
permissions.category -> permissions.categories, move template, add pr…
rafalp Jan 3, 2024
940b56c
Fix permission name, remove debug code
rafalp Jan 3, 2024
fe6ec0b
Fix admin check in admin login form
rafalp Jan 3, 2024
04db484
Review and update is_staff checks
rafalp Jan 4, 2024
12a5a87
Small tests tweaks
rafalp Jan 4, 2024
b2c4c6c
Copy faked categories new permissions
rafalp Jan 4, 2024
8c0c8e9
Tweak docs
rafalp Jan 4, 2024
c7fc633
Fix generated docs
rafalp Jan 4, 2024
b7ca11e
Fix tests
rafalp Jan 4, 2024
c39d8af
Fix warnings
rafalp Jan 4, 2024
331c3d6
Fix regex patterns
rafalp Jan 4, 2024
91ce26b
Fix more regex patterns
rafalp Jan 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions dev-docs/plugins/extending-misago.md
Expand Up @@ -105,6 +105,7 @@ The following models currently define this field:
- `misago.threads.models.Poll`
- `misago.threads.models.Post`
- `misago.threads.models.Thread`
- `misago.users.models.Group`
- `misago.users.models.User`

`plugin_data` is not a replacement for models. Use it for [denormalization](https://en.wikipedia.org/wiki/Denormalization), storing small bits of data that are frequently accessed or used in queries.
Expand Down
151 changes: 151 additions & 0 deletions dev-docs/plugins/hooks/build-user-category-permissions-hook.md
@@ -0,0 +1,151 @@
# `build_user_category_permissions_hook`

This hook wraps the standard function that Misago uses to build user category permissions.

Category permissions are stored as a Python `dict` with permission names as keys and values being category IDs with the associated permission:

```python
category_permissions = {
"see": [1, 2, 3],
"browse": [1, 2, 3],
"start": [1, 2],
"reply": [1, 2, 3],
"attachments": [1, 2, 3],
}
```

Plugins can add custom permissions to this dict.


## Location

This hook can be imported from `misago.permissions.hooks`:

```python
from misago.permissions.hooks import build_user_category_permissions_hook
```


## Filter

```python
def custom_build_user_category_permissions_filter(
action: BuildUserCategoryPermissionsHookAction,
groups: list[Group],
categories: dict[int, Category],
category_permissions: dict[int, list[str]],
user_permissions: dict,
) -> dict:
...
```

A function implemented by a plugin that can be registered in this hook.


### Arguments

#### `action: BuildUserCategoryPermissionsHookAction`

A standard Misago function used to build user category permissions or the next filter function from another plugin.

See the [action](#action) section for details.


#### `groups: list[Group]`

A list of groups user belongs to.


#### `categories: dict[int, Category]`

A `dict` of categories.


#### `category_permissions: dict[int, list[str]]`

A Python `dict` containing lists of category permissions read from the database, indexed by category IDs.


#### `user_permissions: dict`

A Python `dict` with user permissions build so far.


### Return value

A Python `dict` with category permissions.


## Action

```python
def build_user_category_permissions_action(
groups: list[Group],
categories: dict[int, Category],
category_permissions: dict[int, list[str]],
user_permissions: dict,
) -> dict:
...
```

A standard Misago function used to get user category permissions.


### Arguments

#### `groups: list[Group]`

A list of groups user belongs to.


#### `categories: dict[int, Category]`

A `dict` of categories.


#### `category_permissions: dict[int, list[str]]`

A Python `dict` containing lists of category permissions read from the database, indexed by category IDs.


#### `user_permissions: dict`

A Python `dict` with user permissions build so far.


### Return value

A Python `dict` with category permissions.


## Example

The code below implements a custom filter function that includes a custom permission in user's category permissions, if they can browse it:

```python
from misago.categories.models import Category
from misago.permissions.enums import CategoryPermission
from misago.permissions.hooks import build_user_category_permissions_hook
from misago.users.models import Group


@build_user_category_permissions_hook.append_filter
def include_plugin_permission(
action,
groups: list[Group],
categories: dict[int, Category],
category_permissions: dict[int, list[str]],
user_permissions: dict,
) -> dict:
permissions = action(group, categories, category_permissions, user_permissions)
permissions["plugin"] = []

for category_id in categories:
if (
category_id in permissions[CategoryPermission.BROWSE]
and "plugin" in category_permissions.get(category_id, [])
):
permissions["plugin"].append(category_id)

return permissions
```
89 changes: 89 additions & 0 deletions dev-docs/plugins/hooks/build-user-permissions-hook.md
@@ -0,0 +1,89 @@
# `build_user_permissions_hook`

This hook wraps the standard function that Misago uses to build user permissions from their groups.


## Location

This hook can be imported from `misago.permissions.hooks`:

```python
from misago.permissions.hooks import build_user_permissions_hook
```


## Filter

```python
def custom_build_user_permissions_filter(
action: BuildUserPermissionsHookAction, groups: list[Group]
) -> dict:
...
```

A function implemented by a plugin that can be registered in this hook.


### Arguments

#### `action: BuildUserPermissionsHookAction`

A standard Misago function used to build user permissions from their groups or the next filter function from another plugin.

See the [action](#action) section for details.


#### `groups: list[Group]`

A list of groups user belongs to.


### Return value

A Python `dict` with user permissions build from their groups.


## Action

```python
def build_user_permissions_action(groups: list[Group]) -> dict:
...
```

A standard Misago function used to build user permissions from their groups.


### Arguments

#### `groups: list[Group]`

A list of groups user belongs to.


### Return value

A Python `dict` with user permissions build from their groups.


## Example

The code below implements a custom filter function that includes a custom permission in user permissions:

```python
from misago.permissions.hooks import build_user_permissions_hook
from misago.users.models import Group


@build_user_permissions_hook.append_filter
def include_plugin_permission(
action, groups: list[Group]
) -> dict:
permissions = action(groups)
permissions["plugin_permission"] = False

for group in groups:
if group.plugin_data.get("plugin_permission"):
permissions["plugin_permission"] = True

return permissions
```
112 changes: 112 additions & 0 deletions dev-docs/plugins/hooks/copy-category-permissions-hook.md
@@ -0,0 +1,112 @@
# `copy_category_permissions_hook`

This hook wraps the standard function that Misago uses to copy category permissions.


## Location

This hook can be imported from `misago.permissions.hooks`:

```python
from misago.permissions.hooks import copy_category_permissions_hook
```


## Filter

```python
def custom_copy_category_permissions_filter(
action: CopyCategoryPermissionsHookAction,
src: Category,
dst: Category,
request: HttpRequest | None=None,
) -> None:
...
```

A function implemented by a plugin that can be registered in this hook.


### Arguments

#### `action: CopyCategoryPermissionsHookAction`

A standard Misago function used to copy permissions from one category to another or the next filter function from another plugin.

See the [action](#action) section for details.


#### `src: Category`

A category to copy permissions from.


#### `dst: Category`

A category to copy permissions to.


#### `request: Optional[HttpRequest]`

The request object or `None` if it was not provided.


## Action

```python
def copy_category_permissions_action(
src: Category, dst: Category, request: HttpRequest | None=None
) -> None:
...
```

A standard Misago function used to copy permissions from one category to another or the next filter function from another plugin.


### Arguments

#### `src: Category`

A category to copy permissions from.


#### `dst: Category`

A category to copy permissions to.


#### `request: Optional[HttpRequest]`

The request object or `None` if it was not provided.


## Example

The code below implements a custom filter function that copies additional models with the plugin's category permissions:

```python
from django.http import HttpRequest
from misago.permissions.hooks import copy_category_permissions_hook
from misago.users.models import Category

from .models PluginCategoryPermissions


@copy_category_permissions_hook.append_filter
def copy_group_plugin_perms(
action, src: Category, dst: Category, request: HttpRequest | None = None,
) -> None:
# Delete old permissions
PluginCategoryPermissions.objects.filter(category=dst).delete()

# Copy permissions
for permission in PluginCategoryPermissions.objects.filter(category=src):
PluginCategoryPermissions.objects.create(
category=dst,
group_id=permission.group_id,
can_do_something=permission.can_do_something,
)

# Call the next function in chain
return action(group, **kwargs)
```