Auth question

326 views
Skip to first unread message

Rahul

unread,
Oct 16, 2018, 8:35:04 AM10/16/18
to web2py-users
Hey Everyone,
       Greetings! I have a question. I went through Auth documentation and understood that we can add extra fields to the Auth tables. However, I still want to be a little more clear to achieve below - I am currently using three fields for a multi-tenant system like workspace, username and password. Here workspace depicts where the user belongs to (see explanation in Q1 below) I am currently using my own code to manage this stuff manually (almost everything that auth does), now though I want to give Auth a try and tailor it to fit my needs. I dont want to maintain that amount of code and use the existing API. Can I get help on achieving that in the simplest way. If it works, I would switch to using Auth 

 Q1] How can we use Auth to add one more extra field for authentication when I want a system to validate login based on three parameters like - Validation needs to be done based on all three parameters specified. For each application I can use 'n' number of unique workspaces and 'n' number of users would belong to these workspaces. How to do this ?
  1. workspace - An alpha numeric field that would store a unique name denoting users belonging to a particular set   (For example users working in a specific  location like los-angeles or washington)  or an office location like michigan, nevada or Zones like north, south  .. sort-of etc. )
  2. username - Its available already 
  3. password - Its available already

Q2] Which all tables need to be modified ? 

Q3] Any changes in any other code in any files ? 

I know I can clone my app multiple times and support multi-tenancy however, if this can be achieved with Auth - that would be great. 

Regards,

Rahul 

Jim S

unread,
Oct 16, 2018, 10:19:49 AM10/16/18
to web2py-users

Rahul

unread,
Oct 17, 2018, 3:06:44 AM10/17/18
to web2py-users
Hi Jim,
          I am afraid no I didn't check that section but I just finished reading it. Thanks! for directing me to it. Looks like a new addition to DAL (might be a couple of versions back) & looks promising. So now, we can specify something like request_tenant using db._common_fields  field parameter. 

I would need it for all tables so is there a specific syntax like below that I am required to specify in each table I create ?
db._common_fields.append(Field('request_tenant',
                               default=request.env.http_host,
                               writable=False))

Also, can we set the default value to a field value that we can query or pass as a session variable like session.workspace == 'some workspace name'  while the user logs in ? 
default=session.workspace,

If yes - what do I need to modify to add this additional field in Auth so it will be an input field for the user to key in the workspace name. Then I can store this workspace in session variable and use it. The reason is I want a group of users (accessing the same app and database from different locations) belonging to same workspace.  This is how they are grouped. please see the screenshot posted from my actual application login. In it I use workspace name as well to validate but after reading the book seems like we would not require workspace for validation if we can have the user provide the field for redirection and for us to grab the session variable. 

Or is this not needed at all after we use common fields ?  

I hope I am clear and make sense  :-) 

Regards,

Rahul
login.jpg

Jim Steil

unread,
Oct 17, 2018, 10:27:32 AM10/17/18
to web...@googlegroups.com
Rahul

First, what I was referring to was common_filters, not common fields.  Here is the scenario as I see it.

In you auth_user table you have a workspace field.  Then in other tables that are workspace-specific you also have a workspace field to show which workspace they relate to

Here is how I think I would handle it, assuming I am understanding your need.  And, assuming that the workspace identifier is stored on the user record.  You wouldn't gather it on the login page.

In db.py I'd have code that would check to see if the user is logged in.  If so, then set the common filters for the workspace-specific tables

if auth.is_logged_in:
    db.related_table_1._common_filter = lambda query: db.related_table_1.workspace = auth.user.workspace
    db.related_table_2._common_filter = lambda query: db.related_table_2.workspace = auth.user.workspace
    db.related_table_3._common_filter = lambda query: db.related_table_3.workspace = auth.user.workspace
    db.related_table_4._common_filter = lambda query: db.related_table_4.workspace = auth.user.workspace
    ...etc...

Make sense?

Anyone else out there that's done this and can show a better way?  

-Jim


NOTE - you might also skip the common filters if you're logging in as an admin.  Then you might want to see data for all workspaces

NOTE 2 - If you really want people to specify their workspace when they login (meaning they have access to all of them but they choose which one on login) then you'd have to override the default login code to gather that extra variable and store it in your session somewhere.  Then use that instead of auth.user.workspace when building your filters.



--
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 a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/6SscBvMorU0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rahul

unread,
Oct 19, 2018, 2:54:19 AM10/19/18
to web2py-users
Hi Jim,
        That makes sense. I will check it out on which option to go. Thanks! for all the guidance. 

Thank you,

Rahul Dhakate

Rahul

unread,
Oct 23, 2018, 8:59:21 AM10/23/18
to web2py-users
Hi Jim, All,
         Okay I tried this - And I also decorated index() function in controller like below as I want to redirect the user to login page rather than directly jumping to index.html 

# ---- example index page ----
@auth.requires_login()
def index():
    response
.flash= T("Hello World")
   
return dict(message=T('Welcome to web2py!'))

However, now when I put the credentials username and password, it doesnt log me in - I generates the below URL like below and appends it to url box. What might I be missing because it was logging me in fine sometime ago but now it doesnt allow. Note I did cleanup a lot of HTML code from my login page. There sure is something going on here that I am not catching - 




 

Sincerely, Rahul D. 

Jim S

unread,
Oct 23, 2018, 10:19:48 AM10/23/18
to web2py-users
Did you modify the user() function in default.py?  Or, are you using your own custom login functions?

-Jim

Rahul

unread,
Oct 24, 2018, 12:26:45 AM10/24/18
to web2py-users
The user function remains as-is - No modifications done. 

def user():
   
"""
    exposes:
    http://..../[app]/default/user/login
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    http://..../[app]/default/user/bulk_register
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    also notice there is http://..../[app]/appadmin/manage/auth to allow administrator to manage users
    """

   
return dict(form=auth())

I am using the specified functions to expose methods as below - 
# ---- User functions ---
def login(): return dict(form=auth.login())
def register(): return dict(form=auth.register())
def retrieve_password(): return dict(form=auth.reset_password())
def logout(): return dict(form=auth.logout())
def profile(): return dict(form=auth.profile())



and the corresponding files reside in \views\  not in \views\default - I am not sure if the application is even picking up these files. 

Note - I have extended the Auth (auth_user) table and added workspace and other fields - This will be specified everytime I add a new user. I would filter out the results as you mentioned but only after all the login stuff works properly.

auth.settings.extra_fields['auth_user'] = [
   
Field ('workspace', length=128),

Sincerely,

Rahul 

Jim S

unread,
Oct 24, 2018, 12:15:21 PM10/24/18
to web2py-users
I'm confused.  Is this code in your controller somewhere?

# ---- User functions ---
def login(): return dict(form=auth.login())
def register(): return dict(form=auth.register())
def retrieve_password(): return dict(form=auth.reset_password())
def logout(): return dict(form=auth.logout())
def profile(): return dict(form=auth.profile())

You shouldn't need it.  To override the default login stuff I've just modified the one in default.py.

-Jim

Rahul

unread,
Oct 24, 2018, 11:59:45 PM10/24/18
to web2py-users
Yes this is in default.py. Please excuse me for my bad code as I am still experimenting with Auth and not totally familiar with the implementation. Is this the right way that I am doing it? or only having user() function is enough ? 

Thanks, Rahul

Jim S

unread,
Oct 25, 2018, 8:32:45 AM10/25/18
to web2py-users
Having the default user() functions is all you need.  I'd try commenting out your 'user' functions.

-Jim

Rahul

unread,
Oct 26, 2018, 2:44:18 AM10/26/18
to web2py-users
Nope - doesnt help. I commented out all the user functions defined in the controller and 


# ---- User functions ---
'''def login(): return dict(form=auth.login())
def register(): return dict(form=auth.register())
def retrieve_password(): return dict(form=auth.reset_password())
def logout(): return dict(form=auth.logout())
def profile(): return dict(form=auth.profile())
'''

I even decorated index - It does take me to the login screen but from there nothing happens. It just wont log me in like it did before. Also,  I have two users in database but none work now.  Again, register seems to fail (It did work earlier) but now it doesnt. See screenshot of both screens. Looks like I must be really doing something weird. If this wont work by this Sunday. I may go back to my old style of coding and do it all by myself. I've seriously lost 10 days reading and experimenting with Auth to make it work . Not too much coded. 

@auth.requires_login()
def index():
    response
.flash = T("Hello User")
   
#redirect(URL(r=request, c='default/user', f='login')) # Redirects user to login page

   
return dict(message=T('Welcome to web2py!'))



Thanks,

Rahul
screens.jpg

Dave S

unread,
Oct 26, 2018, 3:34:37 AM10/26/18
to web2py-users


On Thursday, October 25, 2018 at 11:44:18 PM UTC-7, Rahul wrote:
[...]
I even decorated index - It does take me to the login screen but from there nothing happens. It just wont log me in like it did before. Also,  I have two users in database but none work now.  Again, register seems to fail (It did work earlier) but now it doesnt. See screenshot of both screens. Looks like I must be really doing something weird. If this wont work by this Sunday. I may go back to my old style of coding and do it all by myself. I've seriously lost 10 days reading and experimenting with Auth to make it work . Not too much coded. 

 
Perhaps you should show your changes to the Auth tables.  I haven't used 'extra' fields myself, but the discussions I've seen in this group over the years make it seem a much smaller effort than you seem to be going through.  Most people just go from the discussion in the book, from what I've seen.

/dps

Jim Steil

unread,
Oct 26, 2018, 7:41:12 AM10/26/18
to web...@googlegroups.com
Can you show the entire db.py, default py and index.html?

Jim

Rahul

unread,
Oct 27, 2018, 1:52:21 PM10/27/18
to web2py-users
Hi Dave and Jim,
           Please find the files in the zipped archive. I have added default.py, db.py, index.html and also layout file which I am converting to use with web2py. called ace.html. I have also attached the views\login.html file since I am extending this file  specifically for login form as it is different than layout file. Let me know. Thanks!


Regards,

Rahul 
files.zip
login.html

Jim Steil

unread,
Oct 27, 2018, 9:03:25 PM10/27/18
to web...@googlegroups.com
Rahul

Let's try this a different way.

Attached is a simple multi-tenant app with one table.

Does this do what you need?

1.  Create a new project in web2py
2.  Replace db.py in your models dir with this one
3.  Replace default.py in your controllers dir with this one
4.  Replace index.html in views/default with this one
5.  Add notes.html to views/default
6.  Replace storage.sqlite in your databases dir with this one

Depending on your version of web2py this should all work.

I've created 2 logins

elvis - password is password
blueeyes - password is password

Click on the notes link logged in as each of them and you'll see different notes show up based on the common filter.

-Jim
index.html
default.py
db.py
notes.html
storage.sqlite

Rahul

unread,
Oct 29, 2018, 2:16:43 AM10/29/18
to web2py-users
Hi Jim,
         This works like a charm. Thank you for this. It is what I expected and wanted to achieve with Auth. I'll check my new project for what I may be doing wrong, for now it seems that the scaffolding admin interface I want to use for my app is the one that is the culprit. It has lots of custom js and css files. I would need to figure out a way to merge them with it properly.  Again, Thank you! for your patience and wonderful support. And thank you everyone. 

Regards,

Rahul. 

fjbern...@gmail.com

unread,
Oct 30, 2018, 10:41:08 AM10/30/18
to web2py-users
Hi,


 
## after auth = Auth(db)
 
db.define_table('workspaces',
    Field('workspace', 'string', requires=IS_NOT_EMPTY()))
 
auth.settings.extra_fields['auth_user']= [
  Field('workspace', 'reference workspaces', label=T('workspace')]
 
db.auth_user.workspace.requires = IS_IN_DB(db, db.workspaces.id, '%(workspace)s')
 
I din't try, but I would :)
Reply all
Reply to author
Forward
0 new messages