[web2py-devs] auth.update_membership()

109 views
Skip to first unread message

Richard

unread,
Jul 26, 2017, 9:53:38 AM7/26/17
to web2py-developers
Hello,

Is there any particular reason to not have an Auth method for updating membership instead of delete and add??

Thanks

Richard

Anthony

unread,
Jul 26, 2017, 10:38:39 AM7/26/17
to web2py-developers
Why would you update an auth_membership record? Are you saying when you want to simultaneously drop membership in one group and add membership to a different group, you would rather do that by changing the group in an existing record instead of deleting one membership and adding another? I don't think it is worth adding a new method for that use case, and it would probably be more clear to keep the delete and add operations separate and explicit anyway. In other words, conceptually, the only update you can really make to an existing membership is to delete it.

Anthony

Anthony

unread,
Jul 26, 2017, 10:40:18 AM7/26/17
to web2py-developers
And of course, if you really want to do something like that, nothing stops you from writing your own function that updates an existing record in the auth_membership table.

Anthony

Richard Vézina

unread,
Jul 26, 2017, 11:04:32 AM7/26/17
to web2py-d...@googlegroups.com
Hello Anthony,

Thanks for answering... I have use case where user need to change role, for record input/review and approval... In a perfect world they wouldn't do that, but in real world we lack staff to do these differents activities...

So, deleting and adding records burns ID over time, it not a big deal, but it would be more logic to just update the actual role of the person... I can't use your first option as all the differents groups needs to exist at the same time obviously... 

update_membership would also be performed in a signle operation instead of 2...

I can surely create my own method or function, but it would make more sens to include a update method in web2py from my stand point instead of subclassing auth in case I go with a method...

I will have a look at Auth code to see how I could mimic add_ and del_membership in a function, particularly how they update auth.user_groups, which is important to be up to date in the context as the UI change base on user role membership...

Previously, I was just using dal straigh db().update(), but auth.user_groups didn't get updated, I then clear auth.user_groups = {}... But it appears to not work properly sometimes, but I am not sure of that because I was having other issue yeasterday that I may had confuse with auth.user_groups not been updated... But with add_ and del_membership it work just fine now so far...

Richard





--
-- mail from:GoogleGroups "web2py-developers" mailing list
make speech: web2py-developers@googlegroups.com
unsubscribe: web2py-developers+unsubscribe@googlegroups.com
details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Anthony

unread,
Jul 26, 2017, 11:50:11 AM7/26/17
to web2py-developers
On Wednesday, July 26, 2017 at 11:04:32 AM UTC-4, Richard wrote:
Hello Anthony,

Thanks for answering... I have use case where user need to change role, for record input/review and approval... In a perfect world they wouldn't do that, but in real world we lack staff to do these differents activities...

Are you saying the same user must constantly rotate among multiple different roles? That seems like a rare enough use case that we don't need to support it with a special method in the framework.

Instead of using auth_membership, have you considered just adding a "role" field to the auth_user table?
 
So, deleting and adding records burns ID over time, it not a big deal, but it would be more logic to just update the actual role of the person... I can't use your first option as all the differents groups needs to exist at the same time obviously... 

I'm not sure what you mean by my "first option." My two suggestions are just use the delete and add methods, or write a custom function to update the existing record. I don't see how either approach creates a problem with different groups existing at the same time.
 
update_membership would also be performed in a signle operation instead of 2...

Sure, but both operations should be fairly fast. Is there a performance issue -- do you have a high load of role changes specifically?
 
I can surely create my own method or function, but it would make more sens to include a update method in web2py from my stand point instead of subclassing auth in case I go with a method...

Just write a function -- no need to go subclassing Auth just to be able to write auth.update_membership(...) instead of auth_update_membership(...).
 
I will have a look at Auth code to see how I could mimic add_ and del_membership in a function, particularly how they update auth.user_groups, which is important to be up to date in the context as the UI change base on user role membership...

Those functions include a lot of logic allowing you to alternatively specify the group_id or role name and to handle is_active when present. You could simplify the logic by constraining how you specify the arguments. auth.user_groups is just a dictionary, so very simple to update -- you can even just call auth.update_groups(), which will create the dictionary from scratch.

Anthony

Richard Vézina

unread,
Jul 26, 2017, 12:15:48 PM7/26/17
to web2py-d...@googlegroups.com
On Wed, Jul 26, 2017 at 11:50 AM, Anthony <abas...@gmail.com> wrote:
On Wednesday, July 26, 2017 at 11:04:32 AM UTC-4, Richard wrote:
Hello Anthony,

Thanks for answering... I have use case where user need to change role, for record input/review and approval... In a perfect world they wouldn't do that, but in real world we lack staff to do these differents activities...

Are you saying the same user must constantly rotate among multiple different roles?

Yes
 
That seems like a rare enough use case that we don't need to support it with a special method in the framework.

Instead of using auth_membership, have you considered just adding a "role" field to the auth_user table?

Could, but it already implemented a long time ago... And it would prevent the usage of auth.has_membership...
 
 
So, deleting and adding records burns ID over time, it not a big deal, but it would be more logic to just update the actual role of the person... I can't use your first option as all the differents groups needs to exist at the same time obviously... 

I'm not sure what you mean by my "first option." My two suggestions are just use the delete and add methods, or write a custom function to update the existing record. I don't see how either approach creates a problem with different groups existing at the same time.

I thougth you mention to just change group name...
 
 
update_membership would also be performed in a signle operation instead of 2...

Sure, but both operations should be fairly fast. Is there a performance issue -- do you have a high load of role changes specifically?

No, performance is not much a concern about that it more of having less possible queries and clarity of code...
 
 
I can surely create my own method or function, but it would make more sens to include a update method in web2py from my stand point instead of subclassing auth in case I go with a method...

Just write a function -- no need to go subclassing Auth just to be able to write auth.update_membership(...) instead of auth_update_membership(...).

Yes
 
 
I will have a look at Auth code to see how I could mimic add_ and del_membership in a function, particularly how they update auth.user_groups, which is important to be up to date in the context as the UI change base on user role membership...

Those functions include a lot of logic allowing you to alternatively specify the group_id or role name and to handle is_active when present. You could simplify the logic by constraining how you specify the arguments. auth.user_groups is just a dictionary, so very simple to update -- you can even just call auth.update_groups(), which will create the dictionary from scratch.

I guess I can revert using db().update() and just add auth.update_groups() after and it should solve my problem...
 


Anthony

Anthony

unread,
Jul 26, 2017, 2:55:12 PM7/26/17
to web2py-d...@googlegroups.com

Instead of using auth_membership, have you considered just adding a "role" field to the auth_user table?

Could, but it already implemented a long time ago... And it would prevent the usage of auth.has_membership...

First, you are concerned about needing to update auth.user_groups, yet if you are using auth.has_membership, note that it does not look at auth.user_groups and instead always does a database lookup to check for group membership. In that case, you might as well just do db.auth_membership.update(...) to update the memberships, as that will be sufficient for auth.has_membership to work properly.

Second, losing auth.has_membership() is not a big deal, as you can simply do:

@auth.requires(auth.user.role == 'myrole')

You could also define constants in a model, such as:

IS_MYROLE = auth.user.role == 'myrole'

I'm not sure what you mean by my "first option." My two suggestions are just use the delete and add methods, or write a custom function to update the existing record. I don't see how either approach creates a problem with different groups existing at the same time.

I thougth you mention to just change group name...

I was just asking if your goal was to change the group field in the auth_membership table (not the group name in the auth_group table).

Can you explain why your users must rotate among different memberships rather than simply having multiple simultaneous memberships? If a user can insert a record at one time and approve a record at another time, why not just give them insert and approve roles all the time rather than switch between the roles?

Anthony

Richard Vézina

unread,
Jul 26, 2017, 3:26:53 PM7/26/17
to web2py-d...@googlegroups.com
I use my own has_membership() now :

def has_membership(id_role):
    return True if (auth.user_id and id_role in auth.user_groups.values()) or \
                   (auth.user_id and id_role in auth.user_groups) else False

To dramatically speed my app, I may do a little to much usage of auth.has_membership(), but I need to make sure of access right.

Explanations 
My app as be following user role UI centered path... So role membership affect display of stuff all around the places... I shouldn't made it that much of user (or should say task) centric UI, but things are as they are... So it turn out that I had need to rely greatly over auth.has_membership and auth.has_permissions to make sure a given user can access what, but also display him what. So reducing queries hitting the database has a big performance impact so far... I have improve from a factor 5 the speed by using auth.user_groups membership and also, using on_define callback in table model definition...

Some users, the one that use the most the app, need to change role because they kind of do differents task that would need to be done by differents roles in the system and semantically... Since more field for given table are shown to a user a given role to allow him to perform his duty, I user role membership to determine which fields to show and which not to show, since I make sure code remain DRY so I reuse the same create() func for instance for differents roles when it make sens...

I would like now to do the same thing with auth.has_permissions, but it seems more work to do as I have to maintain a bunch of permission data and make my own has_permissions() to check them and update the permission data when user change of group...

UI could had been design in a way that would had reduced the number of check required, but the system have been crafted a long time ago and my knowledge have expand a lot since then so...

Richard



Can you explain why your users must rotate among different memberships rather than simply having multiple simultaneous memberships? If a user can insert a record and one time and approve a record at another time, why not just give them insert and approve roles all the time rather than switch between the roles?

Anthony

--

Massimo DiPierro

unread,
Jul 26, 2017, 5:29:23 PM7/26/17
to web2py-d...@googlegroups.com
I agree, your code speeds up has_membership but does so by checking data stored in session at login and not the database. This means that if membership changes (for example is revoked) has_membership continues to return True until the user logs out and logs ins again. 

That can also be achieved with 

@auth.requires(lambda: ‘role’ in auth.user_groups.values())

instead of

@auth.requires_membership(‘role’)

I do not think it is a good idea to  change behavior or add new methods. Perhaps we can add a cached=False attribute that when set to True uses your method.

Massimo


details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.

Richard Vézina

unread,
Jul 27, 2017, 9:47:17 AM7/27/17
to web2py-d...@googlegroups.com
Hello Massimo,

Are you talking about has_membership() snippet above? If yes, I think a built in bypass to auth.has_membership() that trigger db queries would be a good idea, as long as it properly explained in the book. About having auth.user_groups to be up to date... auth.update_groups() does just fine when I use it after updating user membership in my change_membership function.

I do use such thing in my app already : "@auth.requires(lambda: ‘role’ in auth.user_groups.values())"

In fact, I use this : @auth.requires(lambda: has_membership('admin'))

Thanks

Richard

Richard Vézina

unread,
Jul 27, 2017, 9:55:29 AM7/27/17
to web2py-d...@googlegroups.com
Let me know if you want a PR for has_membership check against auth.user_groups instead of queriying the database...

Richard

Massimo DiPierro

unread,
Jul 28, 2017, 1:47:53 PM7/28/17
to web2py-d...@googlegroups.com
I will the a PR if it does not change the current behavior. Somethiing like has_membership(…, cached=True))


details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.

Michele Comitini

unread,
Jul 28, 2017, 2:25:41 PM7/28/17
to web2py-developers
Wouldn't this be affected by transaction isolation  level on the db?  If the transaction level is isolated reading the cached is good as reading from the current transaction?

Massimo DiPierro

unread,
Jul 28, 2017, 2:40:19 PM7/28/17
to web2py-d...@googlegroups.com
Unfortunately no. The user_groups() are only read from DB at login.


details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.

Richard Vézina

unread,
Jul 31, 2017, 12:04:56 PM7/31/17
to web2py-d...@googlegroups.com
Will do, except if Simone wants the commit as it is his snippet...

Richard

Richard Vézina

unread,
Aug 7, 2017, 3:14:06 PM8/7/17
to web2py-d...@googlegroups.com
No news from Simone... Here a tentative : https://github.com/web2py/web2py/pull/1726

Tests pass locally...

I won't see why it would cause issue.

Thanks

Richard
Reply all
Reply to author
Forward
0 new messages