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

fix: optimize and debug has_role and can_manage_some_groups #7949

Merged
merged 5 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 14 additions & 7 deletions ietf/group/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
import datetime

from itertools import chain
from pathlib import Path

from django.db.models import Q
Expand Down Expand Up @@ -153,17 +154,23 @@ def can_manage_materials(user, group):
def can_manage_session_materials(user, group, session):
return has_role(user, 'Secretariat') or (group.has_role(user, group.features.matman_roles) and not session.is_material_submission_cutoff())

# Maybe this should be cached...
def can_manage_some_groups(user):
if not user.is_authenticated:
return False
authroles = set(
chain.from_iterable(
GroupFeatures.objects.values_list("groupman_authroles", flat=True)
)
)
extra_role_qs = dict()
for gf in GroupFeatures.objects.all():
for authrole in gf.groupman_authroles:
if has_role(user, authrole):
return True
if Role.objects.filter(name__in=gf.groupman_roles, group__type_id=gf.type_id, person__user=user).exists():
return True
return False
extra_role_qs[f"{gf.type_id} groupman roles"] = Q(
name__in=gf.groupman_roles,
group__type_id=gf.type_id,
group__state__in=["active", "bof", "proposed"],
)
return has_role(user, authroles, extra_role_qs=extra_role_qs)


def can_provide_status_update(user, group):
if not group.features.acts_like_wg:
Expand Down
162 changes: 117 additions & 45 deletions ietf/ietfauth/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,72 +38,144 @@ def has_role(user, role_names, *args, **kwargs):
"""Determines whether user has any of the given standard roles
given. Role names must be a list or, in case of a single value, a
string."""
if not isinstance(role_names, (list, tuple)):
role_names = [ role_names ]

extra_role_qs = kwargs.get("extra_role_qs", None)
if not isinstance(role_names, (list, tuple, set)):
role_names = [role_names]

if not user or not user.is_authenticated:
return False

# use cache to avoid checking the same permissions again and again
if not hasattr(user, "roles_check_cache"):
user.roles_check_cache = {}

key = frozenset(role_names)
keynames = set(role_names)
if extra_role_qs:
keynames.update(set(extra_role_qs.keys()))
year = kwargs.get("year", None)
if year is not None:
keynames.add(f"nomcomyear{year}")
key = frozenset(keynames)
if key not in user.roles_check_cache:
try:
person = user.person
except Person.DoesNotExist:
return False

role_qs = {
"Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"),
"Secretariat": Q(person=person, name="secr", group__acronym="secretariat"),
"IAB" : Q(person=person, name="member", group__acronym="iab"),
"IANA": Q(person=person, name="auth", group__acronym="iana"),
"RFC Editor": Q(person=person, name="auth", group__acronym="rpc"),
"ISE" : Q(person=person, name="chair", group__acronym="ise"),
"IAD": Q(person=person, name="admdir", group__acronym="ietf"),
"IETF Chair": Q(person=person, name="chair", group__acronym="ietf"),
"IETF Trust Chair": Q(person=person, name="chair", group__acronym="ietf-trust"),
"IRTF Chair": Q(person=person, name="chair", group__acronym="irtf"),
"RSAB Chair": Q(person=person, name="chair", group__acronym="rsab"),
"IAB Chair": Q(person=person, name="chair", group__acronym="iab"),
"IAB Executive Director": Q(person=person, name="execdir", group__acronym="iab"),
"IAB Group Chair": Q(person=person, name="chair", group__type="iab", group__state="active"),
"IAOC Chair": Q(person=person, name="chair", group__acronym="iaoc"),
"WG Chair": Q(person=person,name="chair", group__type="wg", group__state__in=["active","bof", "proposed"]),
"WG Secretary": Q(person=person,name="secr", group__type="wg", group__state__in=["active","bof", "proposed"]),
"RG Chair": Q(person=person,name="chair", group__type="rg", group__state__in=["active","proposed"]),
"RG Secretary": Q(person=person,name="secr", group__type="rg", group__state__in=["active","proposed"]),
"AG Secretary": Q(person=person,name="secr", group__type="ag", group__state__in=["active"]),
"RAG Secretary": Q(person=person,name="secr", group__type="rag", group__state__in=["active"]),
"Team Chair": Q(person=person,name="chair", group__type="team", group__state="active"),
"Program Lead": Q(person=person,name="lead", group__type="program", group__state="active"),
"Program Secretary": Q(person=person,name="secr", group__type="program", group__state="active"),
"Program Chair": Q(person=person,name="chair", group__type="program", group__state="active"),
"EDWG Chair": Q(person=person, name="chair", group__type="edwg", group__state="active"),
"Nomcom Chair": Q(person=person, name="chair", group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
"Nomcom Advisor": Q(person=person, name="advisor", group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
"Nomcom": Q(person=person, group__type="nomcom", group__acronym__icontains=kwargs.get('year', '0000')),
"Liaison Manager": Q(person=person,name="liaiman",group__type="sdo",group__state="active", ),
"Authorized Individual": Q(person=person,name="auth",group__type="sdo",group__state="active", ),
"Recording Manager": Q(person=person,name="recman",group__type="ietf",group__state="active", ),
"Reviewer": Q(person=person, name="reviewer", group__state="active"),
"Review Team Secretary": Q(person=person, name="secr", group__reviewteamsettings__isnull=False,group__state="active", ),
"IRSG Member": (Q(person=person, name="member", group__acronym="irsg") | Q(person=person, name="chair", group__acronym="irtf") | Q(person=person, name="atlarge", group__acronym="irsg")),
"RSAB Member": Q(person=person, name="member", group__acronym="rsab"),
"Robot": Q(person=person, name="robot", group__acronym="secretariat"),
}

filter_expr = Q(pk__in=[]) # ensure empty set is returned if no other terms are added
"Area Director": Q(
name__in=("pre-ad", "ad"), group__type="area", group__state="active"
),
"Secretariat": Q(name="secr", group__acronym="secretariat"),
"IAB": Q(name="member", group__acronym="iab"),
"IANA": Q(name="auth", group__acronym="iana"),
"RFC Editor": Q(name="auth", group__acronym="rpc"),
"ISE": Q(name="chair", group__acronym="ise"),
"IAD": Q(name="admdir", group__acronym="ietf"),
"IETF Chair": Q(name="chair", group__acronym="ietf"),
"IETF Trust Chair": Q(name="chair", group__acronym="ietf-trust"),
"IRTF Chair": Q(name="chair", group__acronym="irtf"),
"RSAB Chair": Q(name="chair", group__acronym="rsab"),
"IAB Chair": Q(name="chair", group__acronym="iab"),
"IAB Executive Director": Q(name="execdir", group__acronym="iab"),
"IAB Group Chair": Q(
name="chair", group__type="iab", group__state="active"
),
"IAOC Chair": Q(name="chair", group__acronym="iaoc"),
"WG Chair": Q(
name="chair",
group__type="wg",
group__state__in=["active", "bof", "proposed"],
),
"WG Secretary": Q(
name="secr",
group__type="wg",
group__state__in=["active", "bof", "proposed"],
),
"RG Chair": Q(
name="chair", group__type="rg", group__state__in=["active", "proposed"]
),
"RG Secretary": Q(
name="secr", group__type="rg", group__state__in=["active", "proposed"]
),
"AG Secretary": Q(
name="secr", group__type="ag", group__state__in=["active"]
),
"RAG Secretary": Q(
name="secr", group__type="rag", group__state__in=["active"]
),
"Team Chair": Q(name="chair", group__type="team", group__state="active"),
"Program Lead": Q(
name="lead", group__type="program", group__state="active"
),
"Program Secretary": Q(
name="secr", group__type="program", group__state="active"
),
"Program Chair": Q(
name="chair", group__type="program", group__state="active"
),
"EDWG Chair": Q(name="chair", group__type="edwg", group__state="active"),
"Nomcom Chair": Q(
name="chair",
group__type="nomcom",
group__acronym__icontains=kwargs.get("year", "0000"),
),
"Nomcom Advisor": Q(
name="advisor",
group__type="nomcom",
group__acronym__icontains=kwargs.get("year", "0000"),
),
"Nomcom": Q(
group__type="nomcom",
group__acronym__icontains=kwargs.get("year", "0000"),
),
"Liaison Manager": Q(
name="liaiman",
group__type="sdo",
group__state="active",
),
"Authorized Individual": Q(
name="auth",
group__type="sdo",
group__state="active",
),
"Recording Manager": Q(
name="recman",
group__type="ietf",
group__state="active",
),
"Reviewer": Q(name="reviewer", group__state="active"),
"Review Team Secretary": Q(
name="secr",
group__reviewteamsettings__isnull=False,
group__state="active",
),
"IRSG Member": (
Q(name="member", group__acronym="irsg")
| Q(name="chair", group__acronym="irtf")
| Q(name="atlarge", group__acronym="irsg")
),
"RSAB Member": Q(name="member", group__acronym="rsab"),
"Robot": Q(name="robot", group__acronym="secretariat"),
}

filter_expr = Q(
pk__in=[]
) # ensure empty set is returned if no other terms are added
for r in role_names:
filter_expr |= role_qs[r]
if extra_role_qs:
for r in extra_role_qs:
filter_expr |= extra_role_qs[r]

user.roles_check_cache[key] = bool(Role.objects.filter(filter_expr).exists())
user.roles_check_cache[key] = bool(
Role.objects.filter(person=person).filter(filter_expr).exists()
)

return user.roles_check_cache[key]



# convenient decorator

def passes_test_decorator(test_func, message):
Expand Down
Loading