perf: optimize away more privilege requests

[MIGRATION] This commit contains a new version of the schema.
This commit is contained in:
Lephe 2022-05-12 20:00:01 +01:00
parent 7d9e897ae9
commit 38c4f274a0
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
4 changed files with 42 additions and 13 deletions

View File

@ -47,6 +47,9 @@ class Group(db.Model):
members = db.relationship('Member', secondary=lambda: GroupMember,
back_populates='groups')
# Other fields populated automatically through relations:
# <privileges> list of privileges
def __init__(self, name, css, descr):
self.name = name
self.css = css
@ -59,7 +62,7 @@ class Group(db.Model):
* Group privileges
"""
for gp in GroupPrivilege.query.filter_by(gid=self.id).all():
for gp in self.privileges:
db.session.delete(gp)
db.session.commit()
@ -67,8 +70,7 @@ class Group(db.Model):
db.session.commit()
def privs(self):
gps = GroupPrivilege.query.filter_by(gid=self.id).all()
return sorted(gp.priv for gp in gps)
return sorted(gp.priv for gp in self.privileges)
def __repr__(self):
return f'<Group: {self.name}>'
@ -79,15 +81,17 @@ GroupMember = db.Table('group_member', db.Model.metadata,
db.Column('gid', db.Integer, db.ForeignKey('group.id')),
db.Column('uid', db.Integer, db.ForeignKey('member.id')))
# Many-to-many relationship for privileges granted to groups
# GroupPrivilege: A list of privileges for groups, materialized as a table
class GroupPrivilege(db.Model):
__tablename__ = 'group_privilege'
id = db.Column(db.Integer, primary_key=True)
gid = db.Column(db.Integer, db.ForeignKey('group.id'))
group_id = db.Column(db.Integer, db.ForeignKey('group.id'))
group = db.relationship('Group', backref='privileges',
foreign_keys=group_id)
priv = db.Column(db.String(64))
def __init__(self, group, priv):
self.gid = group.id
self.group = group
self.priv = priv

View File

@ -210,10 +210,10 @@ class Member(User):
"""Check whether the member has the specified privilege."""
if priv in self.special_privs:
return True
return db.session.query(Group, GroupPrivilege).filter(
Group.id.in_([g.id for g in self.groups]),
GroupPrivilege.gid==Group.id,
GroupPrivilege.priv==priv).first() is not None
for g in self.groups:
if priv in g.privs():
return True
return False
def special_privileges(self):
"""List member's special privileges."""

View File

@ -78,11 +78,11 @@ def update_groups():
# Update an existing group
if g is not None:
changes = (g.css != css) or (g.description != descr) or \
(set(g.privs()) != set(privs))
(set(g.privs) != set(privs))
g.css = css
g.description = descr
for gpriv in GroupPrivilege.query.filter_by(gid=g.id):
for gpriv in g.privs:
db.session.delete(gpriv)
for priv in privs:
db.session.add(GroupPrivilege(g, priv))

View File

@ -0,0 +1,25 @@
"""relate groups with their privileges through a relationship
Revision ID: fcf53f1a14e3
Revises: 44fbbb1fd537
Create Date: 2022-05-12 19:43:04.436448
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'fcf53f1a14e3'
down_revision = '44fbbb1fd537'
branch_labels = None
depends_on = None
def upgrade():
# Actually modified by hand for once - Lephe'
op.alter_column('group_privilege', 'gid', new_column_name='group_id')
def downgrade():
op.alter_column('group_privilege', 'group_id', new_column_name='gid')