Controller logic is below. Error 1 is occuring under the "dashboard"
function. Errors 2/3 under the user function.
# -*- coding: utf-8 -*-
# this file is released under public domain and you can use without
limitations
###############################################################################
## Launch with all settings via "sudo python run_server.py"
###############################################################################
import operator # needed for manager_status variable
response.title = 'nolabills'
def jspage():
link = URL('static', 'main.js')
return dict(link=link)
def index():
"""
For registered users, redirects to the requests page
For unregistered users, displays intro message
"""
signup = URL(a=request.application, c='default', f='user/register')
return dict(is_logged_in=auth.is_logged_in(), signup=signup)
@auth.requires_membership('manager')
def manage():
"""
This page, accessible by only managers, shows the current employees
of a company as well as any users who are registering themselves as
employees of the company.
From this page a manager can approve a pending user's membership,
as well as revoke the membership of a user on the current employee list.
"""
pending_list = []
approved_list = []
if request.post_vars:
for each in request.post_vars:
key = request.post_vars.keys()[0]
underscore = key.find('_')
id = key[0:underscore]
change = key[underscore+1:len(key)]
change = None if change == "approve" else "unapproved"
# modify db accordingly
record = db(db.auth_user.id==id).select().first()
record.registration_key=change
record.update_record()
for row in db().select():
#for row in db(db.auth_user.company==auth.user.company).select():
if row.registration_key: # if pending approval by manager
pending_list.append({row.id:{"first":row.first_name,"last":row.last_name}})
else:
manager_status = auth.has_membership('manager', row.id)
approved_list.append({row.id:{"first":row.first_name,"last":row.last_name,"manager_status":manager_status}})
return dict(pending_list=pending_list, approved_list=approved_list)
@auth.requires_login()
def dashboard():
"""
This page allows a user to send an email to
a potential customer, requesting access to bill data
"""
i = 0
already_submitted = False # default is false; can only be changed if
request.post_vars == True
# SQLFORM version
data_requests =
SQLFORM.grid(db(db.data_requests.company==auth.user.company),
fields=[db.data_requests.last_name, \
db.data_requests.first_name, \
db.data_requests.email, \
db.data_requests.status, \
db.data_requests.bill_1,
],
headers={'data_requests.bill_1':'Most
Recent Bill'},
sortable=False,
create=False,
editable=False,
deletable=True,
details=False,
maxtextlength=30,
csv=False,
upload=URL('download'),
)
pending_list = db().select(db.data_requests.email)
# if a new request has been made, update the database
if request.post_vars:
while not already_submitted and i <= len(data_requests):
already_submitted = [True for row in pending_list if row.email
== request.post_vars.email]
i += 1
from entergy_scraper import download
from mailer import send_request
if not already_submitted:
# generate token
import random, base64, sha
token =
base64.b64encode(sha.sha(str(random.random())).hexdigest())[:8]
db.tokens.insert(token = token,
first_name = request.post_vars.first_name,
last_name = request.post_vars.last_name,
email = request.post_vars.email,
company = auth.user.company,
)
# send request to user
db.scheduler_task.insert(status = 'QUEUED',
application_name =
request.application+'/default',
task_name = 'request',
group_name = 'email',
function_name = 'send_request',
args = '["{0}", "{1}", "{2}",
"{3}"]'.format( \
request.post_vars.first,
request.post_vars.last, request.post_vars.email, token),
vars = '{}',
enabled = True,
start_time = request.now,
timeout = 500, # should take less than
500 secs
)
# update data_requests to show that the task is
AWAITING_CUSTOMER
db.data_requests.insert(first_name =
request.post_vars.first_name,
last_name = request.post_vars.last_name,
email = request.post_vars.email,
company = auth.user.company,
status = 'AWAITING_CUSTOMER',
)
return dict(already_submitted=already_submitted,
data_requests=data_requests, pending_list=pending_list)
def approve_request():
"""
Allows a customer to approve a data request
"""
submitted = 'submitted'
valid_token = 'valid_token'
invalid_token = 'invalid_token'
# if the user has submitted their data and it's not already in the
database, let them know we'll get their data
if request.post_vars:
status = submitted
token_submitted = True if db(db.data_requests.email ==
request.post_vars.email).select(db.tokens.submitted).first() else False
if token_submitted == False:
# download data
db.data_requests.insert(first_name =
request.post_vars.first_name,
last_name = request.post_vars.last_name,
email = request.post_vars.email,
company = auth.user.company,
energy_username =
request.post_vars.energy_username,
energy_password =
request.post_vars.energy_password,
)
# if no submission of info, try to give them the option to do so
else:
try:
status = valid_token
token = request.get_vars.token
token_row = db(db.tokens.token == token).select().first()
first_name = token_row.first_name
last_name = token_row.last_name
email = token_row.email
except:
status = invalid_token
if status == submitted or status == invalid_token:
return dict(status=status, submitted=submitted,
invalid_token=invalid_token, token_submitted=token_submitted)
else:
return dict(status=status, first_name=first_name,
last_name=last_name, email=email, submitted=False, invalid_token=False,
token_submitted=False)
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())
@cache.action()
def download():
"""
allows downloading of uploaded files
http://..../[app]/default/download/[filename]
"""
return response.download(request, db)
def call():
"""
exposes services. for example:
http://..../[app]/default/call/jsonrpc
decorate with @services.jsonrpc the functions to expose
supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
"""
return service()
On Thursday, June 16, 2016 at 9:36:18 AM UTC-4, Marty Jones wrote:
>
> I uploaded a local application to my DigitalOcean droplet and have been
> having a nightmare of a time with the databases. I get this variety of
> errors on various pages:
>
> *Error 1:*
>
> Traceback (most recent call last):
> File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted
> exec ccode in environment
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 230, in <module>
> File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda>
> self._caller = lambda f: f()
> File "/home/murtyjones/app/gluon/tools.py", line 4241, in f
> return action(*a, **b)
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 73, in dashboard
> data_requests =
> SQLFORM.grid(db(db.data_requests.company==auth.user.company),
> File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 91,
> in __getattr__
> raise AttributeError
> AttributeError
>
>
> *Error 2 (trying to apply changes as a user to own profile):*
>
> Traceback (most recent call last):
> File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted
> exec ccode in environment
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 230, in <module>
> File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda>
> self._caller = lambda f: f()
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 211, in user
> return dict(form=auth())
> File "/home/murtyjones/app/gluon/tools.py", line 1941, in __call__
> return getattr(self, args[0])()
> File "/home/murtyjones/app/gluon/tools.py", line 4026, in profile
> hideerror=self.settings.hideerror):
> File "/home/murtyjones/app/gluon/sqlhtml.py", line 1744, in accepts
> self.id_field_name]).update(**fields)
> File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 2041,
> in update
> ret = db._adapter.update("%s" % table._tablename, self.query, fields)
> File "/home/murtyjones/app/gluon/packages/dal/pydal/adapters/base.py", line
> 519, in update
> raise e
> OperationalError: attempt to write a readonly database
>
>
> *Error 3 (trying to logout as a user):*
>
> Traceback (most recent call last):
> File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted
> exec ccode in environment
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 230, in <module>
> File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda>
> self._caller = lambda f: f()
> File "/home/murtyjones/app/applications/nolabills/controllers/default.py"
> <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>,
> line 211, in user
> return dict(form=auth())
> File "/home/murtyjones/app/gluon/tools.py", line 1941, in __call__
> return getattr(self, args[0])()
> File "/home/murtyjones/app/gluon/tools.py", line 3235, in logout
> self.log_event(log, self.user)
> File "/home/murtyjones/app/gluon/tools.py", line 2530, in log_event
> self.table_event().insert(description=str(description % vars),
> origin=origin, user_id=user_id)
> File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 740,
> in insert
> ret = self._db._adapter.insert(self, self._listify(fields))
> File "/home/murtyjones/app/gluon/packages/dal/pydal/adapters/base.py", line
> 482, in insert
> raise e
> IntegrityError: FOREIGN KEY constraint failed
>
>
> *db.py*
> ## app configuration made easy. Look inside private/appconfig.ini
> from gluon.contrib.appconfig import AppConfig
> ## import current for current.db = db line
> from gluon import current
>
> ## once in production, remove reload=True to gain full speed
> myconf = AppConfig(reload=True)
>
> ## if NOT running on Google App Engine use SQLite or other DB
> db = DAL(myconf.take('db.uri'), pool_size=myconf.take('db.pool_size',
> cast=int), migrate_enabled = myconf.get('db.migrate'),
> check_reserved=['all'])
>
> ## define current.db for module usage
> current.db = db
>
> ## 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 else []
> ## choose a style for forms
> response.formstyle = myconf.take('forms.formstyle') # or
> 'bootstrap3_stacked' or 'bootstrap2' or other
> response.form_label_separator = myconf.take('forms.separator')
>
> from gluon.tools import Auth, Service, PluginManager
>
> auth = Auth(db)
> service = Service()
> plugins = PluginManager()
>
> auth.settings.extra_fields['auth_user']= [
> Field('company'),
> ]
>
> ## create all tables needed by auth if not custom tables
> auth.define_tables(username=False, signature=False, migrate=True,
> fake_migrate=True)
>
> ## configure email
> mail = auth.settings.mailer
> mail.settings.server = 'smtp.gmail.com'
> mail.settings.sender = '[email protected]'
> mail.settings.login = '[email protected]:password'
>
> ## configure auth policy
> auth.settings.registration_requires_verification = True
> auth.settings.registration_requires_approval = True
> auth.settings.reset_password_requires_verification = True
>
> ## after defining tables, uncomment below to enable auditing
> # auth.enable_record_versioning(db)
>
>
> ## create list of companies for which this is available
> db.define_table('company_info',
> Field('name'),
> Field('street_address'),
> )
>
> ## create a table for the queue of not yet fulfilled data requests
> db.define_table('data_requests',
> Field('first_name'),
> Field('last_name'),
> Field('entergy_username'),
> Field('entergy_password'),
> Field('email'),
> Field('company'),
> Field('status', default='QUEUED'),
> Field('runs', 'integer', default=0),
> Field('bill_1', 'upload', uploadfield='bill_1_file'),
> Field('bill_1_file', 'blob'),
> )
>
>
> ## create a table for generating tokens
> db.define_table('tokens',
> Field('first_name'),
> Field('last_name'),
> Field('email'),
> Field('company'),
> Field('token'),
> Field('submitted', default=False),
> )
>
>
>
> *sql.log*
> timestamp: 2016-06-15T14:20:52.811948
> CREATE TABLE auth_user(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> first_name CHAR(128),
> last_name CHAR(128),
> email CHAR(512),
> password CHAR(512),
> registration_key CHAR(512),
> reset_password_key CHAR(512),
> registration_id CHAR(512)
> );
> success!
> timestamp: 2016-06-15T14:20:52.856816
> CREATE TABLE auth_group(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> role CHAR(512),
> description TEXT
> );
> success!
> timestamp: 2016-06-15T14:20:52.899975
> CREATE TABLE auth_membership(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE ,
> group_id INTEGER REFERENCES auth_group (id) ON DELETE CASCADE
> );
> success!
> timestamp: 2016-06-15T14:20:53.040386
> CREATE TABLE auth_permission(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> group_id INTEGER REFERENCES auth_group (id) ON DELETE CASCADE ,
> name CHAR(512),
> table_name CHAR(512),
> record_id INTEGER
> );
> success!
> timestamp: 2016-06-15T14:20:53.092848
> CREATE TABLE auth_event(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> time_stamp TIMESTAMP,
> client_ip CHAR(512),
> user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE ,
> origin CHAR(512),
> description TEXT
> );
> success!
> timestamp: 2016-06-15T14:20:53.223004
> CREATE TABLE auth_cas(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE ,
> created_on TIMESTAMP,
> service CHAR(512),
> ticket CHAR(512),
> renew CHAR(1)
> );
> success!
> timestamp: 2016-06-15T14:22:53.166163
> ALTER TABLE auth_user ADD company CHAR(512);
> success!
> timestamp: 2016-06-15T14:22:53.554653
> CREATE TABLE company_info(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> name CHAR(512),
> street_address CHAR(512)
> );
> success!
> timestamp: 2016-06-15T14:22:53.604055
> CREATE TABLE data_requests(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> first_name CHAR(512),
> last_name CHAR(512),
> entergy_username CHAR(512),
> entergy_password CHAR(512),
> email CHAR(512),
> company CHAR(512),
> status CHAR(512),
> runs INTEGER,
> bill_1 CHAR(512),
> bill_1_file BLOB
> );
> success!
> timestamp: 2016-06-15T14:22:53.645905
> CREATE TABLE tokens(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> first_name CHAR(512),
> last_name CHAR(512),
> email CHAR(512),
> company CHAR(512),
> token CHAR(512),
> submitted CHAR(512)
> );
> success!
> timestamp: 2016-06-15T14:22:56.435830
> CREATE TABLE scheduler_task(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> application_name CHAR(512),
> task_name CHAR(512),
> group_name CHAR(512),
> status CHAR(512),
> function_name CHAR(512),
> uuid CHAR(255) UNIQUE,
> args TEXT,
> vars TEXT,
> enabled CHAR(1),
> start_time TIMESTAMP,
> next_run_time TIMESTAMP,
> stop_time TIMESTAMP,
> repeats INTEGER,
> retry_failed INTEGER,
> period INTEGER,
> prevent_drift CHAR(1),
> timeout INTEGER,
> sync_output INTEGER,
> times_run INTEGER,
> times_failed INTEGER,
> last_run_time TIMESTAMP,
> assigned_worker_name CHAR(512)
> );
> success!
> timestamp: 2016-06-15T14:22:56.501649
> CREATE TABLE scheduler_run(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> task_id INTEGER REFERENCES scheduler_task (id) ON DELETE CASCADE ,
> status CHAR(512),
> start_time TIMESTAMP,
> stop_time TIMESTAMP,
> run_output TEXT,
> run_result TEXT,
> traceback TEXT,
> worker_name CHAR(512)
> );
> success!
> timestamp: 2016-06-15T14:22:56.546304
> CREATE TABLE scheduler_worker(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> worker_name CHAR(255) UNIQUE,
> first_heartbeat TIMESTAMP,
> last_heartbeat TIMESTAMP,
> status CHAR(512),
> is_ticker CHAR(1),
> group_names TEXT,
> worker_stats TEXT
> );
> success!
> timestamp: 2016-06-15T14:22:56.589493
> CREATE TABLE scheduler_task_deps(
> id INTEGER PRIMARY KEY AUTOINCREMENT,
> job_name CHAR(512),
> task_parent INTEGER,
> task_child INTEGER REFERENCES scheduler_task (id) ON DELETE CASCADE ,
> can_visit CHAR(1)
> );
> success!
>
> No idea where to even start with this and would appreciate help.
>
>
--
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.