auth_hasmembership(["admin","supervisor","auditor"]) ?

141 views
Skip to first unread message

António Ramos

unread,
Nov 10, 2016, 11:50:02 AM11/10/16
to web...@googlegroups.com
i have a row in a table that want to protect from users
i have the field  as list:string like this ->["admin","supervisor","auditor"]

with auth_requiresmembership(role) i need role to be  string , not a list.

what is the best solution here?

regards
António
Message has been deleted

Marlysson Silva

unread,
Nov 11, 2016, 7:42:51 AM11/11/16
to web2py-users
To use a conditions based in values use:

@auth.require(conditions)


And to use many values in conditions I guess that this solve your problem:

role_names = ["admin","supervisor","auditor"]
@auth_requires(any( auth.has_membership(role) for role in role_names) ) ]

This statement above means that current logged user be admin OR supervisor OR autidor.

To satisfy all roles replace ANY by ALL


ps. I don't tested.

黄祥

unread,
Nov 11, 2016, 7:55:25 AM11/11/16
to web2py-users
i'm interested in ANY and ALL in your code, but can't find anything that contain ANY or ALL on the link you provide, is it DAL, web2py or python syntax?

best regards,
stifan
Message has been deleted

Niphlod

unread,
Nov 11, 2016, 8:16:25 AM11/11/16
to web2py-users
any and all are definitely python syntax.

I do this using the cached groups, so I don't reach the db for every check


ALLOWED = set(('admin', 'contributor'))
@auth.requires(lambda: auth.user_id and ALLOWED & set(auth.user_groups.values()))

Marlysson Silva

unread,
Nov 11, 2016, 8:16:54 AM11/11/16
to web2py-users
It's a python code .Built-in functions.
The link that I provided it to combine requirements in web2py permission level.

References:
ALL

ANY

The ANY and ALL using a iterable to verify your values ( returning true or false) , then I use a web2py code ( has_permission ) that return a boolean value ( True or False ) and ANY and ALL verify your values.

Remember of concept's boolean to variables that don't contains boolean content.
Empty string , zero value.

returned_value_one = [True , True , True]
returned_value_two = [True, False, False]

>> any(returned_value_one)
True
>> any(returned_value_two)
True
>>all(returned_value_one)
True
>>all(returned_value_two)
False

黄祥

unread,
Nov 11, 2016, 9:22:12 AM11/11/16
to web2py-users
thanks all for the detail explanation, learn a lot new things today
{{=DIV(auth.user_groups) }}
result :
{1L: 'Admin', 2L: 'User'}

{{=DIV(auth.user_groups.values() ) }}
result :
AdminUser

{{=set(auth.user_groups.values() ) }}
result :
set(['Admin', 'User'])

now about hitting database, just want to clarify in web2py there is auth.has_membership()
e.g.
controllers/default.py
"""
# 1 usually used
has_membership_admin = auth.has_membership(role = 'Admin')
"""

# 2 learn today
has_membership_admin = 'Admin' in auth.user_groups.values()

def test():
table = db.test
grid = SQLFORM.grid(table, deletable = has_membership_admin)
return locals()

did the #2 is faster than #1 because #2 didn't hit database?

thanks and best regards,
stifan

Marlysson Silva

unread,
Nov 11, 2016, 9:45:07 AM11/11/16
to web2py-users
Likely because when user log in system , is created a object AUTH that contains all informations about current user logged , at login action happen all operations necessary to get user data of database ( including groups informations related ) 

Then with all this data in "session" don't need verify in database level , because exists a object in "session" with this data.

I guess :D , I tried analyse the code's web2py , and the Auth object create a this.user_groups attribute

request = current.request
session
= current.session
auth
= session.auth

self.user_groups = auth and auth.user_groups or {}

Then all data about auth.* using "session data"

Reference:
https://github.com/web2py/web2py/blob/master/gluon/tools.py#L1805

Richard Vézina

unread,
Nov 11, 2016, 10:11:46 AM11/11/16
to web2py-users
Simone,

I don't understand why you say you cached groups, from what you showed you only prevent accessing db until the very end with the lambda no?

Richard

--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Niphlod

unread,
Nov 11, 2016, 11:00:12 AM11/11/16
to web2py-users
every time you invoke has_membership you ask web2py to verify if in that instance the user belongs to a particular group. It translates to 1 or more queries to the backend.
"my" method instead looks into the groups stored in the session (fetched only once at login), so it doesn't need the roundtrip to check the membership.

The only con is that if a user is logged in it retains the membership it had at the time of the login, so removal of membership is not "translated" to the impossibility to access the decorated function until the user logs out and logins again. 

I prefer using relatively short session timeouts and save zillions of db queries rather than using has_membership, even if has_membership is "strictly" correct (instant verification) while mine isn't.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.

Niphlod

unread,
Nov 11, 2016, 11:07:46 AM11/11/16
to web2py-users
and yes, using a lambda makes that piece of code execute only when that decorated function is called rather than every time the controller is hit.

António Ramos

unread,
Nov 11, 2016, 11:32:51 AM11/11/16
to web...@googlegroups.com
Great discussion.
This should be prommoted to a "tips and trick with auth..." somewhere...

2016-11-11 16:07 GMT+00:00 Niphlod <nip...@gmail.com>:
and yes, using a lambda makes that piece of code execute only when that decorated function is called rather than every time the controller is hit.

--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscribe@googlegroups.com.

Richard Vézina

unread,
Nov 11, 2016, 1:38:14 PM11/11/16
to web2py-users
Thanks to clarify I forgot about has_membership() vs auth.user_groups()... And yes I get tricked by auth.user_groups() sometimes ago for that very reason (update only at login)...

Richard

黄祥

unread,
Nov 11, 2016, 4:15:50 PM11/11/16
to web2py-users
i assume the same thing goes to auth.user vs auth.is_logged_in(), auth.user faster than auth.is_logged_in() because auth.user didn't hit the database, isnt it? anything else how to prevent or avoid database access?
e.g.
models/menu.py
if auth.user:
"""
# 1
result:
<Row { ... }> 
"""

"""
# 2
if auth.is_logged_in():
result:
True
"""
    response.menu += [
(T('Index'), False, URL('default', 'index'), [
(T('Test'), False, URL('default', 'test'), [] ),
]), 
    ]

Anthony

unread,
Nov 11, 2016, 7:08:38 PM11/11/16
to web2py-users
On Friday, November 11, 2016 at 4:15:50 PM UTC-5, 黄祥 wrote:
i assume the same thing goes to auth.user vs auth.is_logged_in(), auth.user faster than auth.is_logged_in() because auth.user didn't hit the database, isnt it?

No, login status is maintained in the session -- auth.is_logged_in() does not hit the database. Note, you can always look at the source code to see how something works -- here's the body of that function:

        if self.user:
           
return True
       
return False

As you can see, it's exactly equivalent to simply checking auth.user.

Anthony

António Ramos

unread,
Nov 25, 2016, 11:30:22 AM11/25/16
to web...@googlegroups.com
can i change auth.has_membership(role) to another user?
i need to iterate over all users and find if they belong to some group.

I have a list [4,5,1] with the id of the group i need to check.

Regards
António

--

Marlysson Silva

unread,
Nov 26, 2016, 6:25:22 PM11/26/16
to web2py-users
Try this:

auth.has_membership(group_id, user_id, role)

The doc are here:
http://web2py.com/books/default/chapter/29/09/access-control#Authorization
To unsubscribe from this group and stop receiving emails from it, send an email to web2py+un...@googlegroups.com.

Richard Vézina

unread,
Dec 8, 2016, 9:21:50 PM12/8/16
to web2py-users
Hello,

As far as I can see auth.groups() return up-to-date user group(s) membership... Maybe it would issue of auth.user_groups() which is only updated at login???


I think using it will help me reduce the number of hit to the db for membership check, as in my app I use to use auth.has_membership() a lot inside the same controller as I use to display different things to user depending of their role in the system... I can't afford to use auth.user_groups() as I have a feature (if we can call it that) that allow some user to switch there actual role in the system by them self...

So, I can make a tradeoff between ultimate performance improvement using auth.user_groups() not it ot the database at all, or using auth.groups() once at the top a controller, caching it for the time a form is submit and then release the cache...

The only other solution I see would be to make sure I use auth.update_groups() when chaging user role as it seems to update auth.user_groups() : http://web2py.readthedocs.io/en/latest/_modules/gluon/tools.html#Auth.update_groups

Actually I should do that when I manage user (creationm, membership, etc.) as it seems to be the proper way to handle auth_* table operation anyway which I didn't do back in time because of my lack of knowledge I guess...

But  I am not sure that if someone change other user membership, for instance the admin changing some user membership, that it will be reflected into every user auth.groups()... If I do modify other user membership, does auth.groups() will reflect the new user membership??

Richard

To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages