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

On Sat, Oct 27, 2018 at 12:52 PM Rahul <[email protected]> wrote:

> 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
>
> On Friday, October 26, 2018 at 5:11:12 PM UTC+5:30, Jim S wrote:
>>
>> Can you show the entire db.py, default py and index.html?
>>
>> Jim
>>
>>
>> On Fri, Oct 26, 2018, 1:44 AM Rahul <[email protected]> wrote:
>>
>>> 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
>>>
>>>
>>>
>>> On Thursday, October 25, 2018 at 6:02:45 PM UTC+5:30, Jim S wrote:
>>>>
>>>> Having the default user() functions is all you need.  I'd try
>>>> commenting out your 'user' functions.
>>>>
>>>> -Jim
>>>>
>>>> On Wednesday, October 24, 2018 at 10:59:45 PM UTC-5, Rahul wrote:
>>>>>
>>>>> 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
>>>>>
>>>>> On Wednesday, October 24, 2018 at 9:45:21 PM UTC+5:30, Jim S wrote:
>>>>>>
>>>>>> 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
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tuesday, October 23, 2018 at 11:26:45 PM UTC-5, Rahul wrote:
>>>>>>>
>>>>>>> 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
>>>>>>>
>>>>>>> On Tuesday, October 23, 2018 at 7:49:48 PM UTC+5:30, Jim S wrote:
>>>>>>>>
>>>>>>>> Did you modify the user() function in default.py?  Or, are you
>>>>>>>> using your own custom login functions?
>>>>>>>>
>>>>>>>> -Jim
>>>>>>>>
>>>>>>>> On Tuesday, October 23, 2018 at 7:59:21 AM UTC-5, Rahul wrote:
>>>>>>>>>
>>>>>>>>> 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 -
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> http://
>>>>>>>>> 127.0.0.1:8000/scaffolding_app/default/user/login?username=rahul&password=integer10&_next=%2Fscaffolding_ace_admin%2Fdefault%2Findex&_formkey=0c0c022a-377d-47dd-bd72-a13e8ee6f387&_formname=login
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Sincerely, Rahul D.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Friday, October 19, 2018 at 12:24:19 PM UTC+5:30, Rahul wrote:
>>>>>>>>>>
>>>>>>>>>> Hi Jim,
>>>>>>>>>>         That makes sense. I will check it out on which option to
>>>>>>>>>> go. Thanks! for all the guidance.
>>>>>>>>>>
>>>>>>>>>> Thank you,
>>>>>>>>>>
>>>>>>>>>> *Rahul Dhakate*
>>>>>>>>>>
>>>>>>>>>> On Wednesday, October 17, 2018 at 7:57:32 PM UTC+5:30, Jim S
>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>> 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.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Wed, Oct 17, 2018 at 2:06 AM Rahul <[email protected]>
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> 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
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On Tuesday, October 16, 2018 at 7:49:49 PM UTC+5:30, Jim S
>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> Have you looked at common filters?
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer?search=common+filter#Common-filters
>>>>>>>>>>>>>
>>>>>>>>>>>>> -Jim
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Tuesday, October 16, 2018 at 7:35:04 AM UTC-5, Rahul wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 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 *
>>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>> 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 [email protected].
>>>>>>>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>>>>>>>
>>>>>>>>>>> --
>>> 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
>>> [email protected].
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
> 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
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.
{{extend 'layout.html'}} {{block header}}

Multitenant Test

{{end}} {{=A('Notes', _href=URL('notes'))}}
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------
# This is a sample controller
# this file is released under public domain and you can use without limitations
# -------------------------------------------------------------------------

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

# ---- API (example) -----
@auth.requires_login()
def api_get_user_email():
    if not request.env.request_method == 'GET': raise HTTP(403)
    return response.json({'status':'success', 'email':auth.user.email})

# ---- Smart Grid (example) -----
@auth.requires_membership('admin') # can only be accessed by members of admin groupd
def grid():
    response.view = 'generic.html' # use a generic view
    tablename = request.args(0)
    if not tablename in db.tables: raise HTTP(403)
    grid = SQLFORM.smartgrid(db[tablename], args=[tablename], deletable=False, editable=False)
    return dict(grid=grid)

# ---- Embedded wiki (example) ----
def wiki():
    auth.wikimenu() # add the wiki to the menu
    return auth.wiki() 

# ---- Action for login/register/etc (required for auth) -----
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())

# ---- action to server uploaded static content (required) ---
@cache.action()
def download():
    """
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    """
    return response.download(request, db)


@auth.requires_login()
def notes():
    grid = SQLFORM.grid(db.notemaker)

    return dict(grid=grid)
# -*- coding: utf-8 -*-

# -------------------------------------------------------------------------
# AppConfig configuration made easy. Look inside private/appconfig.ini
# Auth is for authenticaiton and access control
# -------------------------------------------------------------------------
from gluon.contrib.appconfig import AppConfig
from gluon.tools import Auth

# -------------------------------------------------------------------------
# This scaffolding model makes your app work on Google App Engine too
# File is released under public domain and you can use without limitations
# -------------------------------------------------------------------------

if request.global_settings.web2py_version < "2.15.5":
    raise HTTP(500, "Requires web2py 2.15.5 or newer")

# -------------------------------------------------------------------------
# if SSL/HTTPS is properly configured and you want all HTTP requests to
# be redirected to HTTPS, uncomment the line below:
# -------------------------------------------------------------------------
# request.requires_https()

# -------------------------------------------------------------------------
# once in production, remove reload=True to gain full speed
# -------------------------------------------------------------------------
configuration = AppConfig(reload=True)

if not request.env.web2py_runtime_gae:
    # ---------------------------------------------------------------------
    # if NOT running on Google App Engine use SQLite or other DB
    # ---------------------------------------------------------------------
    db = DAL(configuration.get('db.uri'),
             pool_size=configuration.get('db.pool_size'),
             migrate_enabled=configuration.get('db.migrate'),
             check_reserved=['all'])
else:
    # ---------------------------------------------------------------------
    # connect to Google BigTable (optional 'google:datastore://namespace')
    # ---------------------------------------------------------------------
    db = DAL('google:datastore+ndb')
    # ---------------------------------------------------------------------
    # store sessions and tickets there
    # ---------------------------------------------------------------------
    session.connect(request, response, db=db)
    # ---------------------------------------------------------------------
    # or store session in Memcache, Redis, etc.
    # from gluon.contrib.memdb import MEMDB
    # from google.appengine.api.memcache import Client
    # session.connect(request, response, db = MEMDB(Client()))
    # ---------------------------------------------------------------------

# -------------------------------------------------------------------------
# by default give a view/generic.extension to all actions from localhost
# none otherwise. a pattern can be 'controller/function.extension'
# -------------------------------------------------------------------------
response.generic_patterns = [] 
if request.is_local and not configuration.get('app.production'):
    response.generic_patterns.append('*')

# -------------------------------------------------------------------------
# choose a style for forms
# -------------------------------------------------------------------------
response.formstyle = 'bootstrap4_inline'
response.form_label_separator = ''

# -------------------------------------------------------------------------
# (optional) optimize handling of static files
# -------------------------------------------------------------------------
# response.optimize_css = 'concat,minify,inline'
# response.optimize_js = 'concat,minify,inline'

# -------------------------------------------------------------------------
# (optional) static assets folder versioning
# -------------------------------------------------------------------------
# response.static_version = '0.0.0'

# -------------------------------------------------------------------------
# Here is sample code if you need for
# - email capabilities
# - authentication (registration, login, logout, ... )
# - authorization (role based authorization)
# - services (xml, csv, json, xmlrpc, jsonrpc, amf, rss)
# - old style crud actions
# (more options discussed in gluon/tools.py)
# -------------------------------------------------------------------------

# host names must be a list of allowed host names (glob syntax allowed)
auth = Auth(db, host_names=configuration.get('host.names'))

auth.settings.extra_fields['auth_user'] = [
    Field ('workspace', length=128),
    Field ('created_on', 'date', default=request.now),
    ]
auth.define_tables(username=True, signature=False)  ## Default username=False for using emails

# -------------------------------------------------------------------------
# create all tables needed by auth, maybe add a list of extra fields
# -------------------------------------------------------------------------
auth.settings.extra_fields['auth_user'] = []
auth.define_tables(username=False, signature=False)

# -------------------------------------------------------------------------
# configure email
# -------------------------------------------------------------------------
mail = auth.settings.mailer
mail.settings.server = 'logging' if request.is_local else configuration.get('smtp.server')
mail.settings.sender = configuration.get('smtp.sender')
mail.settings.login = configuration.get('smtp.login')
mail.settings.tls = configuration.get('smtp.tls') or False
mail.settings.ssl = configuration.get('smtp.ssl') or False

# -------------------------------------------------------------------------
# configure auth policy
# -------------------------------------------------------------------------
auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = False
auth.settings.reset_password_requires_verification = True

# -------------------------------------------------------------------------  
# read more at http://dev.w3.org/html5/markup/meta.name.html               
# -------------------------------------------------------------------------
response.meta.author = configuration.get('app.author')
response.meta.description = configuration.get('app.description')
response.meta.keywords = configuration.get('app.keywords')
response.meta.generator = configuration.get('app.generator')
response.show_toolbar = configuration.get('app.toolbar')

# -------------------------------------------------------------------------
# your http://google.com/analytics id                                      
# -------------------------------------------------------------------------
response.google_analytics_id = configuration.get('google.analytics_id')

# -------------------------------------------------------------------------
# maybe use the scheduler
# -------------------------------------------------------------------------
if configuration.get('scheduler.enabled'):
    from gluon.scheduler import Scheduler
    scheduler = Scheduler(db, heartbeat=configuration.get('heartbeat'))

# -------------------------------------------------------------------------
# Define your tables below (or better in another model file) for example
#
# >>> db.define_table('mytable', Field('myfield', 'string'))
#
# Fields can be 'string','text','password','integer','double','boolean'
#       'date','time','datetime','blob','upload', 'reference TABLENAME'
# There is an implicit 'id integer autoincrement' field
# Consult manual for more options, validators, etc.
#
# More API examples for controllers:
#
# >>> db.mytable.insert(myfield='value')
# >>> rows = db(db.mytable.myfield == 'value').select(db.mytable.ALL)
# >>> for row in rows: print row.id, row.myfield
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# after defining tables, uncomment below to enable auditing
# -------------------------------------------------------------------------
# auth.enable_record_versioning(db)

if auth.is_logged_in():
    print 'workspace', auth.user.workspace

# Notes table
db.define_table('notemaker',
                Field('workspace', length=128, default=auth.user.workspace if auth.is_logged_in() else None, writable=False),
                Field('written_on', 'datetime', default=request.now),
                Field('written_by', default=session.user_name),
                Field('note_type', 'string'),
                Field('note_title', ),
                Field('reference', ),  # requires=IS_EMPTY_OR(IS_IN_SET(projects)) ),
                Field('note', 'text', requires=IS_NOT_EMPTY()),
                Field('attachment1', 'upload', label='Attachment-1', autodelete=True),
                Field('attachment2', 'upload', label='Attachment-2', autodelete=True),
                common_filter=lambda query: db.notemaker.workspace==auth.user.workspace if auth.is_logged_in() else None)
{{extend 'layout.html'}} {{=grid}}

Attachment: storage.sqlite
Description: Binary data

Reply via email to