Ok, so something like
auth.default_settings.user_id_need_user_groups_update = cache.ram('user_id_need_user_groups_update', lambda: []) in models.. That would make more sens then create form authapi.py as I couldn't reinit without losing the list at each request from my understanding...
It would requires either way that AuthAPI to be alter or subclassed from the user app to modify add/del_membership()
And I still have to figure out how to make the check each time to force the reinitialization of auth.user_groups, I am not sure if there is anything that is trigger at each, is authapi init perform at each request?? I had put this in the begining of __init__ (in blue) :
def __init__(self, db=None, hmac_key=None, signature=True):
self.db = db
session = current.session
auth = session.auth
if user_id_need_user_groups_update:
if auth.user_id in user_id_need_user_groups_update:
self.user_groups = auth.update_groups()
else:
self.user_groups = auth and auth.user_groups or {}
now = current.request.now
And modify add/del_membership() in blue :
def add_membership(self, group_id=None, user_id=None, role=None):
"""
Gives user_id membership of group_id or role
if user is None than user_id is that of current logged in user
"""
group_id = group_id or self.id_group(role)
try:
group_id = int(group_id)
except:
group_id = self.id_group(group_id) # interpret group_id as a role
if not user_id and self.user:
if not group_id:
raise ValueError('group_id not provided or invalid')
if not user_id:
raise ValueError('user_id not provided or invalid')
membership = self.table_membership()
db = membership._db
record = db((membership.user_id == user_id) &
(membership.group_id == group_id),
ignore_common_filters=True).select().first()
if record:
if hasattr(record, 'is_active') and not record.is_active:
record.update_record(is_active=True)
else:
id = membership.insert(group_id=group_id, user_id=user_id)
if role and user_id == self.user_id:
self.user_groups[group_id] = role
else:
self.update_groups()
self.default_settings.user_id_need_user_groups_update.append(user_id)
self.log_event(self.messages['add_membership_log'],
dict(user_id=user_id, group_id=group_id))
return id
def del_membership(self, group_id=None, user_id=None, role=None):
"""
Revokes membership from group_id to user_id
if user_id is None than user_id is that of current logged in user
"""
group_id = group_id or self.id_group(role)
try:
group_id = int(group_id)
except:
group_id = self.id_group(group_id) # interpret group_id as a role
if not user_id and self.user:
membership = self.table_membership()
self.log_event(self.messages['del_membership_log'],
dict(user_id=user_id, group_id=group_id))
ret = self.db(membership.user_id == user_id)(membership.group_id == group_id).delete()
if group_id in self.user_groups:
del self.user_groups[group_id]
else:
self.default_settings.user_id_need_user_groups_update.append(user_id)
return ret
I have not test anything yet...
I understand your concern, but it improve app speed a lot avoiding to hit the db with auth.has_membership(), we could even and replace the actual has_membership by the one that don't hit database once the user as set user_id_need_user_groups_update, I guess it would allow user traction to the feature and we could add this proposal in the book as a mean (a step) to speed up app???
Richard