requires_verification = False not working with custom auth table

79 views
Skip to first unread message

b.l. masters

unread,
Jun 5, 2018, 3:13:11 PM6/5/18
to web2py-users
Hi

I've created a custom auth table to hide unwanted fields, and add validators in the db.py file to better manage the registration process. As part of this, within the db.py, I also include lines to *not* require verification or approval. When I use  .../default/user/register this feature works just as expected.

However, when I call the form, in default.py using:

  form=auth.register()

It appears as I need to when embed {{=form}} into the view. However, once the registration is complete it is still requiring verification. How can I get requires_verification = False to apply to my embedded form as well?

Below, I pasted the table definition and related settings, in db.py
(note, I also tried changing the settings with the custom table name, and this did not work).

On a related note, I did try to avoid creating a custom auth table, and just add some extra fields to the existing one. But I could not get any validators to work to be ale to "hide" the required fields that I don't want that are part of auth, nor to be able to modify the other features I wanted.

Thanks for any help

---

db.define_table(
    auth.settings.table_user_name,
    Field('first_name', length=128, default='', writable=False, readable=False),
    Field('last_name', length=128, default='', writable=False, readable=False, ),
    Field('username', label=T('Username'), length=128, default='', unique=True),
    Field('email', length=128, writable=False, readable=False), # required
    Field('password', 'password', length=512,            # required
          readable=False, label=T('Password')),
    Field('token', label=T('Invite Code'), length=128, default=''),
    Field('new_status', type='boolean', writable=False, readable=False),
    Field('registration_key', length=512,                # required
          writable=False, readable=False, default=''),
    Field('reset_password_key', length=512,              # required
         writable=False, readable=False, default=''),
    Field('registration_id', length=512,                 # required
          writable=False, readable=False, default=''))

custom_auth_table = db[auth.settings.table_user_name] # get the custom_auth_table

auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = False
auth.settings.login_after_registration = True
auth.settings.login_next = URL('appname', 'accounts', 'index')
auth.settings.register_next = URL('appname', 'accounts', 'index')

Anthony

unread,
Jun 6, 2018, 10:12:04 AM6/6/18
to web2py-users
The Auth settings should work the same in either case. Please show your exact code (model, controller, view) and describe the exact workflow (i.e., exactly what you do and see in the UI) in both cases.

Also, note that if you just want to change the visibility and/or validators of particular fields, you can do so without a custom table definition. Just apply the changes after defining the table. For example:

def hide_fields(table, fieldnames):
   
for fieldname in fieldnames:
        table
[fieldname].readable = table[fieldname].writeable = False

hide_fields
(db.auth_user, ['first_name', 'last_name', 'email'])

Anthony

b.l. masters

unread,
Jun 6, 2018, 1:01:59 PM6/6/18
to web2py-users
In terms of UI, at the [home]/index.html and the .../default/user/register are both displaying the form correctly. It includes:
- username
- password
- confirm password
- Invite Code

The workflow for both should be:
- load form in view
- user enters info and hits return
- user is automatically logged in and sent to .../accounts/index; with no registration required

For
../default/user/register this workflow is occurring as it should.
For [home]/index.html with the embedded form, it is sending user to the .../default/user/login page. It does create the account.  But when attempting to login that user in, it is requiring registration. And it is entering a registration key into the auth_user table.

If I make it a custom form for the [home]/index.html  then the automatic password hashing is not be applied in the DB, and I don't get the password verification. And to make all of that work I am managing an extra form and all of its related actions, that since it is the auth can have impact across alot of funtions in the app. So it would be ideal to just have this work without having to create a custom form.

I've pasted the code below. Thanks for the help.

-b

--

```python
from gluon.tools import Auth, Service, PluginManager

auth = Auth(db)
service = Service()
plugins = PluginManager()


## after auth = Auth(db)

db.define_table(
    auth.settings.table_user_name,
    Field('first_name', length=128, default='', writable=False, readable=False),
    Field('last_name', length=128, default='', writable=False, readable=False, ),
    Field('username', label=T('Username'), length=128, default='', unique=True),
    Field('email', length=128, writable=False, readable=False), # required
    Field('password', 'password', length=512,            # required
          readable=False, label=T('Password')),
    Field('token', label=T('Invite Code'), length=128, default=''),
    Field('new_status', type='boolean', writable=False, readable=False),
    Field('registration_key', length=512,                # required
          writable=False, readable=False, default=''),
    Field('reset_password_key', length=512,              # required
         writable=False, readable=False, default=''),
    Field('registration_id', length=512,                 # required
          writable=False, readable=False, default=''))

## do not forget validators


custom_auth_table = db[auth.settings.table_user_name] # get the custom_auth_table
custom_auth_table.username.requires = IS_NOT_IN_DB(db, custom_auth_table.username)
custom_auth_table.token.requires = [IS_IN_DB(db, 'tokens.token', '%(name)s', error_message=T('This is not a valid token or it has expired. Please obtain a new token and try again'))]
custom_auth_table.password.requires=IS_LENGTH(minsize=15, maxsize=60, error_message=T('Your password must be at least 15 character long'))
custom_auth_table.email.requires = [IS_EMAIL(error_message=auth.messages.invalid_email)]
custom_auth_table.registration_requires_verification = False
custom_auth_table.password_min_length = 15

auth.settings.table_user = custom_auth_table # tell auth to use custom_auth_table

#db.custom_auth_table._after_insert.append(lambda f, id: assign_group(f, id))

# custom fields used to manage Services group management
auth.settings.extra_fields['auth_group']= [
    Field('member_count', type='integer', default=1),
    Field('group_type', length=128)]


auth.settings.remember_me_form=False
# hide retrieve username since we won't collect emails from users
auth.settings.login_after_registration = True
auth.settings.login_next = URL('xx', 'accounts', 'index')
auth.settings.register_next = URL('xx', 'accounts', 'index')

## before auth.define_tables()

auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = False
auth.settings.login_after_registration = True

auth.define_tables(username=True, signature=False)
```

Here is the relevant portion from the controller (default.py)
```python
def index():
    #T.set_current_languages('zh-cn')
    form=auth.register()
    if form.process().accepted:
        userID= form.vars.id
        # assign user to group and appropriate services
        user_group_assignment(userID)
        # log user in and redirect to accounts main page
        auth.login_bare(request.vars.username, request.vars.password)
        redirect(URL('accounts', 'index'))
    elif form.errors:
        response.flash = 'An error has occurred when attempting to make your new account. Please try again, and if the problem persists please contact xx support'
    return dict(form=form)
```

Here is the relevant portion of the view (default/index.html):

```html
 <div style="background-color: rgb(133, 24, 152);" class="container row featurette quote-row" id="signup">
      <div class="col-md-7">
        <h1>{{=T("Sign Up")}}</h1>
         <p class="lead">{{=T("Complete the form below to receive a password, and access to all of our computer services.")}}</p>
      </div>
  </div>

  <div class="container marketing">
   
    {{=form}}

  </div><!-- /.container -->
```

 


Anthony

unread,
Jun 6, 2018, 2:28:42 PM6/6/18
to web2py-users
def index():
    #T.set_current_languages('zh-cn')
    form=auth.register()
    if form.process().accepted:
        userID= form.vars.id
        # assign user to group and appropriate services
        user_group_assignment(userID)
        # log user in and redirect to accounts main page
        auth.login_bare(request.vars.username, request.vars.password)
        redirect(URL('accounts', 'index'))

auth.register() itself handles the form processing, automatic login, and redirect. Also, you cannot call .process() on a form that has already been processed.

Anthony

b.l. masters

unread,
Jun 6, 2018, 4:48:48 PM6/6/18
to web2py-users
So by "auth.register() itself handles the form processing, automatic login, and redirect": Do you mean, that these functions are applied in the pre-processing (as you also mention), so I can't alter them??  Or can the:

auth.settings.login_after_registration, auth.settings.registration_requires_verification, etc.

work on the auth.register()? If yes, where/how? I tried placing these settings in the def index() at one point, and in the def user() and  neither seemed to have any effect. Is there an example in the manual that illustrates how this would be done? I have looked and haven't found this.

Thanks much
-barbra

Dave S

unread,
Jun 6, 2018, 5:01:30 PM6/6/18
to web2py-users


On Wednesday, June 6, 2018 at 1:48:48 PM UTC-7, b.l. masters wrote:
So by "auth.register() itself handles the form processing, automatic login, and redirect": Do you mean, that these functions are applied in the pre-processing (as you also mention), so I can't alter them??  Or can the:

auth.settings.login_after_registration, auth.settings.registration_requires_verification, etc.

work on the auth.register()? If yes, where/how? I tried placing these settings in the def index() at one point, and in the def user() and  neither seemed to have any effect. Is there an example in the manual that illustrates how this would be done? I have looked and haven't found this.

Thanks much

I would expect to do this in db.py, right after instantiating the auth tables.  See the comments in
<URL:http://web2py.com/books/default/chapter/29/09/access-control#Renaming-Auth-tables>
and note that
<URL:http://web2py.com/books/default/chapter/29/09/access-control#Customizing-Auth>
describes doing things right after

auth = Auth()
which is typically in models/db.py.  Model files are evaluated for every request.

/dps

You've probably seen the list of settings at
<URL:http://web2py.com/books/default/chapter/29/09/access-control#Auth-Settings-and-messages>


/dps

Anthony

unread,
Jun 6, 2018, 5:28:55 PM6/6/18
to web2py-users
On Wednesday, June 6, 2018 at 4:48:48 PM UTC-4, b.l. masters wrote:
So by "auth.register() itself handles the form processing, automatic login, and redirect": Do you mean, that these functions are applied in the pre-processing (as you also mention), so I can't alter them??  Or can the:

auth.settings.login_after_registration, auth.settings.registration_requires_verification, etc.

work on the auth.register()?

The /default/user action calls auth(), which itself ultimately calls auth.register(). So, using auth.register() directly is the same as going to the /default/user action. Any settings applied (such as the two above) will be in effect in either case.

auth.register() creates a SQLFORM and calls .process() on that form. So you cannot then also call .process() on that same form. You need to remove that from your code. Also, auth.register() automatically creates the user group and does the redirect.

Anthony

b.l. masters

unread,
Jun 6, 2018, 5:30:20 PM6/6/18
to web2py-users
That is what I have done, is place them in db.py. And that is what is not working. These are what I already have in my db.py:

auth.settings.remember_me_form=False

auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = False
auth.settings.login_after_registration = True
auth.settings.login_next = URL('site, 'accounts', 'index')
auth.settings.register_next = URL('site', 'accounts', 'index')

Its works for the ..default/user/register but not if I call the auth.register() form in a different location.

So, that is what I am needing: to get these same settings to also work when I call the auth.register()

Thanks
-b

b.l. masters

unread,
Jun 6, 2018, 5:40:48 PM6/6/18
to web...@googlegroups.com
I feel like I must be missing some basic step here. So would I put these settings  like this, in default.py?:

def user():

    auth.settings.registration_requires_verification = False
    auth.settings.registration_requires_approval = False
    auth.settings.login_after_registration = True
    auth.settings.login_next = URL('site', 'accounts', 'index')
    auth.settings.register_next = URL('site', 'accounts', 'index')
    return dict(form=auth())

Because, I tried this, and its not applying the settings when I use auth.register() either. Sorry, but an example of exactly where these settings should go so that these settings will work when I use auth.register() would be super helpful. As they don't seem to work in all of the places I would have tried.

Thanks

Anthony

unread,
Jun 6, 2018, 8:02:45 PM6/6/18
to web2py-users
Please show the new version of index().

Massimo Di Pierro

unread,
Jun 14, 2018, 10:09:10 PM6/14/18
to web2py-users
I think it is best to set the settings in the model where you define_tables() but your code should work. Anthony, is right, show us the full index()
Reply all
Reply to author
Forward
0 new messages