forked from Github-Mirrors/canaille
refactor: store user profile in g.user
This commit is contained in:
parent
1f9d148c0d
commit
c895366684
10 changed files with 45 additions and 8 deletions
|
@ -6,6 +6,7 @@ from urllib.parse import urlunsplit
|
|||
from canaille.app import models
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import render_template
|
||||
from flask import request
|
||||
from flask import session
|
||||
|
@ -14,12 +15,16 @@ from werkzeug.routing import BaseConverter
|
|||
|
||||
|
||||
def current_user():
|
||||
if "user" in g:
|
||||
return g.user
|
||||
|
||||
for user_id in session.get("user_id", [])[::-1]:
|
||||
user = models.User.get(id=user_id)
|
||||
if user and (
|
||||
not current_app.backend.has_account_lockability() or not user.locked
|
||||
):
|
||||
return user
|
||||
g.user = user
|
||||
return g.user
|
||||
|
||||
session["user_id"].remove(user_id)
|
||||
|
||||
|
|
|
@ -174,6 +174,9 @@ class User(canaille.core.models.User, LDAPObject):
|
|||
|
||||
def load_permissions(self):
|
||||
conn = Backend.get().connection
|
||||
self.permissions = set()
|
||||
self.read = set()
|
||||
self.write = set()
|
||||
|
||||
for access_group_name, details in current_app.config["ACL"].items():
|
||||
filter_ = self.acl_filter_to_ldap_filter(details.get("FILTER"))
|
||||
|
|
|
@ -26,6 +26,7 @@ from flask import abort
|
|||
from flask import Blueprint
|
||||
from flask import current_app
|
||||
from flask import flash
|
||||
from flask import g
|
||||
from flask import redirect
|
||||
from flask import request
|
||||
from flask import send_file
|
||||
|
@ -494,6 +495,8 @@ def profile_create(current_app, form):
|
|||
user.set_password(form["password1"].data)
|
||||
user.save()
|
||||
|
||||
user.load_permissions()
|
||||
|
||||
flash(_("User account creation succeed."), "success")
|
||||
|
||||
return user
|
||||
|
@ -568,6 +571,7 @@ def profile_edition_main_form_validation(user, edited_user, profile_form):
|
|||
edited_user.preferred_language = None
|
||||
|
||||
edited_user.save()
|
||||
g.user.reload()
|
||||
|
||||
|
||||
def profile_edition_emails_form(user, edited_user, has_smtp):
|
||||
|
@ -611,10 +615,12 @@ def profile_edition_remove_email(user, edited_user, email):
|
|||
@bp.route("/profile/<user:edited_user>", methods=("GET", "POST"))
|
||||
@user_needed()
|
||||
def profile_edition(user, edited_user):
|
||||
if not user.can_manage_users and not (user.can_edit_self and edited_user == user):
|
||||
if not user.can_manage_users and not (
|
||||
user.can_edit_self and edited_user.id == user.id
|
||||
):
|
||||
abort(404)
|
||||
|
||||
menuitem = "profile" if edited_user == user else "users"
|
||||
menuitem = "profile" if edited_user.id == user.id else "users"
|
||||
has_smtp = "SMTP" in current_app.config
|
||||
has_email_confirmation = current_app.config.get("EMAIL_CONFIRMATION") is True or (
|
||||
current_app.config.get("EMAIL_CONFIRMATION") is None and has_smtp
|
||||
|
@ -681,7 +687,9 @@ def profile_edition(user, edited_user):
|
|||
@bp.route("/profile/<user:edited_user>/settings", methods=("GET", "POST"))
|
||||
@user_needed()
|
||||
def profile_settings(user, edited_user):
|
||||
if not user.can_manage_users and not (user.can_edit_self and edited_user == user):
|
||||
if not user.can_manage_users and not (
|
||||
user.can_edit_self and edited_user.id == user.id
|
||||
):
|
||||
abort(404)
|
||||
|
||||
if (
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
|
||||
from flask import g
|
||||
from flask import session
|
||||
|
||||
|
||||
|
@ -15,6 +16,7 @@ class User:
|
|||
raise NotImplementedError()
|
||||
|
||||
def login(self):
|
||||
g.user = self
|
||||
try:
|
||||
previous = (
|
||||
session["user_id"]
|
||||
|
@ -29,6 +31,7 @@ class User:
|
|||
def logout(self):
|
||||
try:
|
||||
session["user_id"].pop()
|
||||
del g.user
|
||||
if not session["user_id"]:
|
||||
del session["user_id"]
|
||||
except (IndexError, KeyError):
|
||||
|
|
|
@ -150,6 +150,7 @@ def user(app, backend):
|
|||
formatted_address="1235, somewhere",
|
||||
)
|
||||
u.save()
|
||||
u.load_permissions()
|
||||
yield u
|
||||
u.delete()
|
||||
|
||||
|
@ -164,6 +165,7 @@ def admin(app, backend):
|
|||
password="admin",
|
||||
)
|
||||
u.save()
|
||||
u.load_permissions()
|
||||
yield u
|
||||
u.delete()
|
||||
|
||||
|
@ -178,6 +180,7 @@ def moderator(app, backend):
|
|||
password="moderator",
|
||||
)
|
||||
u.save()
|
||||
u.load_permissions()
|
||||
yield u
|
||||
u.delete()
|
||||
|
||||
|
|
|
@ -2,22 +2,24 @@ import datetime
|
|||
from unittest import mock
|
||||
|
||||
from canaille.app import models
|
||||
from flask import g
|
||||
|
||||
|
||||
def test_index(testclient, user):
|
||||
res = testclient.get("/", status=302)
|
||||
assert res.location == "/login"
|
||||
|
||||
with testclient.session_transaction() as sess:
|
||||
sess["user_id"] = [user.id]
|
||||
g.user = user
|
||||
res = testclient.get("/", status=302)
|
||||
assert res.location == "/profile/user"
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["use_oidc"]
|
||||
g.user.reload()
|
||||
res = testclient.get("/", status=302)
|
||||
assert res.location == "/consent/"
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = []
|
||||
g.user.reload()
|
||||
res = testclient.get("/", status=302)
|
||||
assert res.location == "/about"
|
||||
|
||||
|
@ -243,7 +245,6 @@ def test_user_deleted_in_session(testclient, backend):
|
|||
with testclient.session_transaction() as session:
|
||||
session["user_id"] = [u.id]
|
||||
|
||||
testclient.get("/profile/jake", status=200)
|
||||
u.delete()
|
||||
|
||||
testclient.get("/profile/jake", status=404)
|
||||
|
@ -425,7 +426,6 @@ def test_signin_locked_account(testclient, user):
|
|||
|
||||
|
||||
def test_account_locked_during_session(testclient, logged_user):
|
||||
testclient.get("/profile/user/settings", status=200)
|
||||
logged_user.lock_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
logged_user.save()
|
||||
testclient.get("/profile/user/settings", status=403)
|
||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
|||
|
||||
from canaille.app import models
|
||||
from canaille.core.account import Invitation
|
||||
from flask import g
|
||||
|
||||
|
||||
def test_invitation(testclient, logged_admin, foo_group, smtpd):
|
||||
|
@ -19,9 +20,11 @@ def test_invitation(testclient, logged_admin, foo_group, smtpd):
|
|||
url = res.pyquery(".copy-text")[0].value
|
||||
|
||||
# logout
|
||||
g.user = None
|
||||
with testclient.session_transaction() as sess:
|
||||
del sess["user_id"]
|
||||
|
||||
testclient.get("/logout")
|
||||
res = testclient.get(url, status=200)
|
||||
|
||||
assert res.form["user_name"].value == "someone"
|
||||
|
@ -68,6 +71,7 @@ def test_invitation_editable_user_name(testclient, logged_admin, foo_group, smtp
|
|||
url = res.pyquery(".copy-text")[0].value
|
||||
|
||||
# logout
|
||||
g.user = None
|
||||
with testclient.session_transaction() as sess:
|
||||
del sess["user_id"]
|
||||
|
||||
|
@ -114,6 +118,7 @@ def test_generate_link(testclient, logged_admin, foo_group, smtpd):
|
|||
url = res.pyquery(".copy-text")[0].value
|
||||
|
||||
# logout
|
||||
g.user = None
|
||||
with testclient.session_transaction() as sess:
|
||||
del sess["user_id"]
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
from canaille.core.populate import fake_users
|
||||
from flask import g
|
||||
from webtest import Upload
|
||||
|
||||
|
||||
|
@ -86,6 +87,7 @@ def test_user_list_search_only_allowed_fields(
|
|||
res.mustcontain(no=moderator.formatted_name[0])
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["READ"].remove("user_name")
|
||||
g.user.reload()
|
||||
|
||||
form = res.forms["search"]
|
||||
form["query"] = "user"
|
||||
|
@ -105,6 +107,7 @@ def test_edition_permission(
|
|||
testclient.get("/profile/user", status=404)
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["edit_self"]
|
||||
g.user.reload()
|
||||
testclient.get("/profile/user", status=200)
|
||||
|
||||
|
||||
|
@ -204,6 +207,7 @@ def test_field_permissions_none(testclient, logged_user):
|
|||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
|
||||
g.user.reload()
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
form = res.forms["baseform"]
|
||||
assert "phone_numbers-0" not in form.fields
|
||||
|
@ -230,6 +234,7 @@ def test_field_permissions_read(testclient, logged_user):
|
|||
"WRITE": [],
|
||||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
g.user.reload()
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
form = res.forms["baseform"]
|
||||
assert "phone_numbers-0" in form.fields
|
||||
|
@ -256,6 +261,7 @@ def test_field_permissions_write(testclient, logged_user):
|
|||
"WRITE": ["phone_numbers"],
|
||||
"PERMISSIONS": ["edit_self"],
|
||||
}
|
||||
g.user.reload()
|
||||
res = testclient.get("/profile/user", status=200)
|
||||
form = res.forms["baseform"]
|
||||
assert "phone_numbers-0" in form.fields
|
||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
|||
from unittest import mock
|
||||
|
||||
from canaille.app import models
|
||||
from flask import g
|
||||
|
||||
|
||||
def test_edition(
|
||||
|
@ -300,6 +301,7 @@ def test_edition_permission(
|
|||
testclient.get("/profile/user/settings", status=404)
|
||||
|
||||
testclient.app.config["ACL"]["DEFAULT"]["PERMISSIONS"] = ["edit_self"]
|
||||
g.user.reload()
|
||||
testclient.get("/profile/user/settings", status=200)
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from authlib.jose import jwt
|
|||
from authlib.oauth2.rfc7636 import create_s256_code_challenge
|
||||
from canaille.app import models
|
||||
from canaille.oidc.oauth import setup_oauth
|
||||
from flask import g
|
||||
from werkzeug.security import gen_salt
|
||||
|
||||
from . import client_credentials
|
||||
|
@ -234,6 +235,7 @@ def test_logout_login(testclient, logged_user, client):
|
|||
)
|
||||
|
||||
res = res.form.submit(name="answer", value="logout", status=302)
|
||||
g.user = None
|
||||
res = res.follow(status=200)
|
||||
|
||||
res.form["login"] = logged_user.user_name[0]
|
||||
|
|
Loading…
Reference in a new issue