mirror of
https://github.com/logos-co/open-law.git
synced 2025-02-10 13:57:17 +00:00
local access groups
This commit is contained in:
parent
039d9b8fea
commit
ba467e9f73
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -14,10 +14,11 @@
|
|||||||
"backref",
|
"backref",
|
||||||
"bookname",
|
"bookname",
|
||||||
"Btns",
|
"Btns",
|
||||||
"CUDA",
|
|
||||||
"CLEANR",
|
"CLEANR",
|
||||||
|
"CUDA",
|
||||||
"Divs",
|
"Divs",
|
||||||
"flowbite",
|
"flowbite",
|
||||||
|
"indeterminated",
|
||||||
"jsonify",
|
"jsonify",
|
||||||
"pydantic",
|
"pydantic",
|
||||||
"pytest",
|
"pytest",
|
||||||
|
@ -69,5 +69,4 @@ def create_editor_group(book_id: int):
|
|||||||
m.PermissionAccessGroups(
|
m.PermissionAccessGroups(
|
||||||
permission_id=permission.id, access_group_id=group.id
|
permission_id=permission.id, access_group_id=group.id
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
return group
|
return group
|
||||||
|
File diff suppressed because one or more lines are too long
145086
app/static/js/main.js
145086
app/static/js/main.js
File diff suppressed because one or more lines are too long
@ -59,8 +59,8 @@
|
|||||||
<button name="submit" type="submit"></button>
|
<button name="submit" type="submit"></button>
|
||||||
</form>
|
</form>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<svg id="dropdownCollectionContextButton{{collection.id}}" data-dropdown-toggle="dropdown" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 0 0" stroke-width="1.5" stroke="none" class="w-0 h-0"></svg>
|
<svg id="dropdownCollectionContextButton{{collection.id}}" data-dropdown-toggle="dropdown" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 0 0" stroke-width="1.5" stroke="none" class="w-0 h-0"></svg>
|
||||||
</div>
|
</div>
|
||||||
<div data="collection-context-menu-{{collection.id}}" id="dropdown" class="z-10 hidden bg-white divide-y divide-gray-800 border border-gray-800 dark:border-none dark:divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
|
<div data="collection-context-menu-{{collection.id}}" id="dropdown" class="z-10 hidden bg-white divide-y divide-gray-800 border border-gray-800 dark:border-none dark:divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
|
@ -83,10 +83,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<input data-tooltip-target="a-tooltip-collection-{{collection.id}}" type="checkbox" data-permission="A" data-access-to="collection" data-access-to-id="{{ collection.id }}" class="w-4 h-4 text-green-600 bg-green-100 border-green-400 rounded focus:ring-green-500 dark:focus:ring-green-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-green-300 dark:border-green-500" />
|
<input data-tooltip-target="a-tooltip-collection-{{collection.id}}" type="checkbox" data-permission="A" data-access-to="collection" data-access-to-id="{{ collection.id }}" class="w-4 h-4 text-green-600 bg-green-100 border-green-400 rounded focus:ring-green-500 dark:focus:ring-green-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-green-300 dark:border-green-500" />
|
||||||
|
|
||||||
|
|
||||||
{#
|
|
||||||
<input type="checkbox" data-access-to="collection" data-access-to-id="{{ collection.id }}" class="w-4 h-4 text-blue-600 bg-gray-300 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-400 dark:border-gray-600" />
|
|
||||||
#}
|
|
||||||
<span class="text-center dark:text-gray-300">{{ collection.label }}</span>
|
<span class="text-center dark:text-gray-300">{{ collection.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -148,12 +144,6 @@
|
|||||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||||
</div>
|
</div>
|
||||||
<input data-tooltip-target="a-tooltip-section-{{section.id}}" type="checkbox" data-permission="A" data-access-to="section" data-access-to-id="{{ section.id }}" class="w-4 h-4 text-green-600 bg-green-100 border-green-400 rounded focus:ring-green-500 dark:focus:ring-green-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-green-300 dark:border-green-500" />
|
<input data-tooltip-target="a-tooltip-section-{{section.id}}" type="checkbox" data-permission="A" data-access-to="section" data-access-to-id="{{ section.id }}" class="w-4 h-4 text-green-600 bg-green-100 border-green-400 rounded focus:ring-green-500 dark:focus:ring-green-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-green-300 dark:border-green-500" />
|
||||||
|
|
||||||
|
|
||||||
{#
|
|
||||||
<input type="checkbox" data-permission="A" data-access-to="section" data-access-to-id="{{ section.id }}" class="w-4 h-4 text-blue-600 bg-gray-300 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-400 dark:border-gray-600" />
|
|
||||||
#}
|
|
||||||
|
|
||||||
<span class="text-center dark:text-gray-300">{{ section.label }}</span>
|
<span class="text-center dark:text-gray-300">{{ section.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
from flask import redirect, url_for, Blueprint, flash, request
|
from flask import redirect, url_for, Blueprint, flash, request
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from sqlalchemy import or_
|
|
||||||
|
|
||||||
from app import forms as f, models as m, db
|
from app import forms as f, models as m, db
|
||||||
from app.logger import log
|
from app.logger import log
|
||||||
|
from app.controllers.create_access_groups import (
|
||||||
|
create_editor_group,
|
||||||
|
create_moderator_group,
|
||||||
|
)
|
||||||
|
|
||||||
bp = Blueprint("permission", __name__, url_prefix="/permission")
|
bp = Blueprint("permission", __name__, url_prefix="/permission")
|
||||||
|
|
||||||
@ -34,10 +39,70 @@ def set_permissions():
|
|||||||
flash("User are not contributor of this book!", "danger")
|
flash("User are not contributor of this book!", "danger")
|
||||||
return redirect(url_for("book.my_library"))
|
return redirect(url_for("book.my_library"))
|
||||||
|
|
||||||
# TODO process data from checkbox tree
|
user: m.User = contributor.user
|
||||||
# permissions = json.loads(form.permissions.data)
|
users_access_groups: list[m.AccessGroup] = list(
|
||||||
|
set(book.list_access_groups).intersection(user.access_groups)
|
||||||
|
)
|
||||||
|
if len(users_access_groups) > 1:
|
||||||
|
log(
|
||||||
|
log.WARNING,
|
||||||
|
"User: [%s] has more than 1 access group in book [%s]",
|
||||||
|
user,
|
||||||
|
book,
|
||||||
|
)
|
||||||
|
|
||||||
return {"status": "ok"}
|
for users_access in users_access_groups:
|
||||||
|
users_access: m.AccessGroup
|
||||||
|
users_access.users.remove(user)
|
||||||
|
|
||||||
|
new_access_group = None
|
||||||
|
match contributor.role:
|
||||||
|
case m.BookContributor.Roles.EDITOR:
|
||||||
|
new_access_group = create_editor_group(book.id)
|
||||||
|
case m.BookContributor.Roles.MODERATOR:
|
||||||
|
new_access_group = create_moderator_group(book.id)
|
||||||
|
case _:
|
||||||
|
log(
|
||||||
|
log.CRITICAL,
|
||||||
|
"Unknown contributor's [%s] role: [%s]",
|
||||||
|
contributor,
|
||||||
|
contributor.role,
|
||||||
|
)
|
||||||
|
flash("Unknown contributor's role", "danger")
|
||||||
|
return redirect(url_for("book.settings", book_id=book_id))
|
||||||
|
m.UserAccessGroups(user_id=user.id, access_group_id=new_access_group.id).save(
|
||||||
|
False
|
||||||
|
)
|
||||||
|
|
||||||
|
permissions_json = json.loads(form.permissions.data)
|
||||||
|
book_ids = permissions_json.get("book", [])
|
||||||
|
for book_id in book_ids:
|
||||||
|
m.BookAccessGroups(
|
||||||
|
book_id=book_id, access_group_id=new_access_group.id
|
||||||
|
).save(False)
|
||||||
|
|
||||||
|
collection_ids = permissions_json.get("collection", [])
|
||||||
|
for collection_id in collection_ids:
|
||||||
|
m.CollectionAccessGroups(
|
||||||
|
collection_id=collection_id, access_group_id=new_access_group.id
|
||||||
|
).save(False)
|
||||||
|
|
||||||
|
section_ids = permissions_json.get("section", [])
|
||||||
|
for section_id in section_ids:
|
||||||
|
m.SectionAccessGroups(
|
||||||
|
section_id=section_id, access_group_id=new_access_group.id
|
||||||
|
).save(False)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
flash("Success!", "success")
|
||||||
|
return redirect(url_for("book.settings", book_id=book_id))
|
||||||
|
|
||||||
|
log(log.ERROR, "Errors edit contributor access level: [%s]", form.errors)
|
||||||
|
for field, errors in form.errors.items():
|
||||||
|
field_label = form._fields[field].label.text
|
||||||
|
for error in errors:
|
||||||
|
flash(error.replace("Field", field_label), "danger")
|
||||||
|
return redirect(url_for("book.settings", book_id=book_id))
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/access_tree", methods=["GET"])
|
@bp.route("/access_tree", methods=["GET"])
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
from flask import current_app as Response
|
from flask import current_app as Response
|
||||||
|
|
||||||
from app import models as m
|
from app import models as m
|
||||||
@ -287,3 +289,44 @@ def test_editor_access_tree_entire_book(client):
|
|||||||
assert collections_ids
|
assert collections_ids
|
||||||
assert collection_1.id in collections_ids
|
assert collection_1.id in collections_ids
|
||||||
assert collection_2.id in collections_ids
|
assert collection_2.id in collections_ids
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_access_level(client):
|
||||||
|
login(client)
|
||||||
|
book = create_book(client)
|
||||||
|
collection_1, _ = create_collection(client, book.id)
|
||||||
|
collection_2, _ = create_collection(client, book.id)
|
||||||
|
|
||||||
|
editor = m.User(username="editor", password="editor").save()
|
||||||
|
response: Response = client.post(
|
||||||
|
f"/book/{book.id}/add_contributor",
|
||||||
|
data=dict(user_id=editor.id, role=m.BookContributor.Roles.EDITOR),
|
||||||
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert b"Contributor was added!" in response.data
|
||||||
|
assert len(book.list_access_groups) == 2
|
||||||
|
|
||||||
|
json_string = json.dumps({"collection": [collection_1.id]})
|
||||||
|
response: Response = client.post(
|
||||||
|
"/permission/set",
|
||||||
|
data=dict(
|
||||||
|
book_id=book.id,
|
||||||
|
user_id=editor.id,
|
||||||
|
permissions=json_string,
|
||||||
|
),
|
||||||
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(book.list_access_groups) == 3
|
||||||
|
|
||||||
|
response: Response = client.post(
|
||||||
|
"/permission/set",
|
||||||
|
data=dict(
|
||||||
|
book_id=book.id,
|
||||||
|
user_id=editor.id,
|
||||||
|
),
|
||||||
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert b"Success!" not in response.data
|
||||||
|
Loading…
x
Reference in New Issue
Block a user