put users into a table
This commit is contained in:
parent
598fcbd020
commit
ee2d853b5c
|
@ -40,7 +40,6 @@ from qommon import emails
|
|||
|
||||
from wcs.formdata import FormData
|
||||
from wcs.formdef import FormDef, FormField
|
||||
from wcs.users import User
|
||||
from wcs.categories import Category
|
||||
from wcs.roles import Role, logged_users_role, get_user_roles
|
||||
from wcs.workflows import Workflow
|
||||
|
@ -561,7 +560,7 @@ class FormDefPage(Directory):
|
|||
if form.get_widget('cancel').parse():
|
||||
return redirect('.')
|
||||
|
||||
users = [x for x in User.select() if x.email]
|
||||
users = [x for x in get_publisher().user_class.select() if x.email]
|
||||
if logged_users_role().id in self.formdef.roles:
|
||||
allowed_users = users
|
||||
else:
|
||||
|
|
|
@ -80,13 +80,13 @@ class RootDirectory(AccessControlled, Directory):
|
|||
|
||||
req = get_request()
|
||||
if req.user:
|
||||
if users.User.count() == 0:
|
||||
if get_publisher().user_class.count() == 0:
|
||||
# this means user logged in anonymously
|
||||
pass
|
||||
elif not req.user.is_admin:
|
||||
raise errors.AccessForbiddenError()
|
||||
else:
|
||||
if users.User.count() > 0:
|
||||
if get_publisher().user_class.count() > 0:
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
return
|
||||
|
|
|
@ -840,8 +840,7 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
role.details = toutf8(role.details)
|
||||
all_elems.append(role)
|
||||
|
||||
from users import User
|
||||
for user in User.select():
|
||||
for user in get_publisher().user_class.select():
|
||||
user.name = toutf8(user.name)
|
||||
if hasattr(user, 'formdata') and user.formdata:
|
||||
for k, v in user.formdata.items():
|
||||
|
@ -902,4 +901,6 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
else:
|
||||
cfg_submit(form, 'postgresql', ['dbname', 'user', 'password',
|
||||
'host', 'port'])
|
||||
import sql
|
||||
sql.do_user_table()
|
||||
redirect('.')
|
||||
|
|
|
@ -29,7 +29,6 @@ from quixote.directory import Directory
|
|||
from qommon import emails
|
||||
from qommon import errors
|
||||
from qommon import misc, get_cfg
|
||||
from wcs.users import User
|
||||
from wcs.roles import Role
|
||||
|
||||
import qommon.ident
|
||||
|
@ -44,7 +43,7 @@ class UserUI:
|
|||
|
||||
def form(self):
|
||||
ident_methods = get_cfg('identification', {}).get('methods', [])
|
||||
formdef = User.get_formdef()
|
||||
formdef = get_publisher().user_class.get_formdef()
|
||||
users_cfg = get_cfg('users', {})
|
||||
|
||||
form = Form(enctype='multipart/form-data')
|
||||
|
@ -78,9 +77,9 @@ class UserUI:
|
|||
return form
|
||||
|
||||
def submit_form(self, form):
|
||||
formdef = User.get_formdef()
|
||||
formdef = get_publisher().user_class.get_formdef()
|
||||
if not self.user:
|
||||
self.user = User()
|
||||
self.user = get_publisher().user_class()
|
||||
for f in ('name', 'email', 'is_admin', 'roles'):
|
||||
widget = form.get_widget(f)
|
||||
if widget:
|
||||
|
@ -110,7 +109,7 @@ class UserPage(Directory):
|
|||
_q_exports = ['', 'edit', 'delete', 'token', 'debug']
|
||||
|
||||
def __init__(self, component):
|
||||
self.user = User.get(component)
|
||||
self.user = get_publisher().user_class.get(component)
|
||||
self.user_ui = UserUI(self.user)
|
||||
get_response().breadcrumb.append((component + '/', self.user.display_name))
|
||||
|
||||
|
@ -315,7 +314,7 @@ class UsersDirectory(Directory):
|
|||
|
||||
debug_cfg = get_cfg('debug', {})
|
||||
|
||||
users = User.select(order_by = 'name')
|
||||
users = get_publisher().user_class.select(order_by = 'name')
|
||||
has_idp_as_ident = 'idp' in get_cfg('identification', {}).get('methods', [])
|
||||
|
||||
checked_roles = None
|
||||
|
@ -403,9 +402,9 @@ class UsersDirectory(Directory):
|
|||
_('Liberty support must be setup before creating users.'))
|
||||
|
||||
# XXX: user must be logged in to get here
|
||||
user = User()
|
||||
user = get_publisher().user_class()
|
||||
user_ui = UserUI(user)
|
||||
first_user = User.count() == 0
|
||||
first_user = get_publisher().user_class.count() == 0
|
||||
if first_user:
|
||||
user.is_admin = first_user
|
||||
form = user_ui.form()
|
||||
|
|
|
@ -26,7 +26,7 @@ except ImportError:
|
|||
|
||||
import qommon
|
||||
|
||||
from qommon.publisher import get_publisher_class, set_publisher_class, QommonPublisher
|
||||
from qommon.publisher import get_publisher_class, set_publisher_class, QommonPublisher, get_cfg
|
||||
|
||||
# this is terribly ugly but import RootDirectory will import a bunch of things,
|
||||
# and some of them need a publisher to be set
|
||||
|
@ -128,6 +128,12 @@ class WcsPublisher(StubWcsPublisher):
|
|||
import wcs.workflows
|
||||
wcs.workflows.load_extra()
|
||||
|
||||
if get_cfg('postgresql', {}):
|
||||
import sql
|
||||
self.user_class = sql.SqlUser
|
||||
else:
|
||||
self.user_class = User
|
||||
|
||||
def try_publish(self, request):
|
||||
if request.get_header('X_WCS_IFRAME_MODE', '') in ('true', 'yes'):
|
||||
request.response.iframe_mode = True
|
||||
|
|
|
@ -36,7 +36,6 @@ import qommon.pages
|
|||
from qommon.afterjobs import AfterJobStatusDirectory
|
||||
|
||||
from categories import Category
|
||||
from users import User
|
||||
from formdef import FormDef
|
||||
from formdata import FormData
|
||||
from anonylink import AnonymityLink
|
||||
|
@ -223,7 +222,7 @@ class RootDirectory(Directory):
|
|||
else:
|
||||
return template.error_page('No Lasso Identity Dump (???)')
|
||||
token = form.get_widget('token').parse()
|
||||
users_with_token = list(User.select(lambda x: x.identification_token == token))
|
||||
users_with_token = list(get_publisher().user_class.select(lambda x: x.identification_token == token))
|
||||
if len(users_with_token) == 0:
|
||||
return template.error_page(_('Unknown Token'))
|
||||
|
||||
|
|
281
wcs/sql.py
281
wcs/sql.py
|
@ -24,6 +24,7 @@ from qommon.storage import _take
|
|||
from qommon import get_cfg
|
||||
|
||||
import wcs.formdata
|
||||
import wcs.users
|
||||
|
||||
SQL_TYPE_MAPPING = {
|
||||
'title': None,
|
||||
|
@ -87,6 +88,44 @@ def do_formdef_tables(formdef):
|
|||
cur.close()
|
||||
|
||||
|
||||
def do_user_table():
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
table_name = 'users'
|
||||
|
||||
cur.execute('''SELECT COUNT(*) FROM information_schema.tables
|
||||
WHERE table_name = %s''', (table_name,))
|
||||
if cur.fetchone()[0] == 0:
|
||||
cur.execute('''CREATE TABLE %s (id serial PRIMARY KEY,
|
||||
name varchar,
|
||||
email varchar,
|
||||
roles text[],
|
||||
is_admin bool,
|
||||
anonymous bool,
|
||||
name_identifiers text[],
|
||||
identification_token varchar,
|
||||
lasso_dump text,
|
||||
last_seen timestamp);''' % table_name)
|
||||
cur.execute('''SELECT column_name FROM information_schema.columns
|
||||
WHERE table_name = %s''', (table_name,))
|
||||
existing_fields = [x[0] for x in cur.fetchall()]
|
||||
|
||||
from admin.settings import UserFieldsFormDef
|
||||
formdef = UserFieldsFormDef()
|
||||
|
||||
for field in formdef.fields:
|
||||
if 'f%s' % field.id not in existing_fields:
|
||||
sql_type = SQL_TYPE_MAPPING.get(field.type, 'varchar')
|
||||
if sql_type is None:
|
||||
continue
|
||||
cur.execute('''ALTER TABLE %s ADD COLUMN %s %s''' % (
|
||||
table_name,
|
||||
'f%s' % field.id,
|
||||
sql_type))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
|
||||
class SqlFormData(wcs.formdata.FormData):
|
||||
_names = None # make sure StorableObject methods fail
|
||||
_formdef = None
|
||||
|
@ -136,7 +175,7 @@ class SqlFormData(wcs.formdata.FormData):
|
|||
sql_statement = '''SELECT id, user_id, user_hash, receipt_time, status, %s
|
||||
FROM %s
|
||||
WHERE %s = %%(value)s''' % (
|
||||
', '.join(['f%s' % x.id for x in cls._formdef.fields]),
|
||||
', '.join(cls.get_data_fields()),
|
||||
cls._table_name,
|
||||
index)
|
||||
cur.execute(sql_statement, {'value': str(value)})
|
||||
|
@ -353,3 +392,243 @@ class SqlFormData(wcs.formdata.FormData):
|
|||
return list(objects)
|
||||
select = classmethod(select)
|
||||
|
||||
|
||||
class SqlUser(wcs.users.User):
|
||||
_table_name = 'users'
|
||||
id = None
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
self.name_identifiers = []
|
||||
self.roles = []
|
||||
|
||||
def get_with_indexed_value(cls, index, value, ignore_errors = False):
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
sql_statement = '''SELECT id, name, email, roles, is_admin, anonymous,
|
||||
name_identifiers, identification_token,
|
||||
lasso_dump, last_seen, %s
|
||||
FROM %s
|
||||
WHERE %s = %%(value)s''' % (
|
||||
', '.join(cls.get_data_fields()),
|
||||
cls._table_name,
|
||||
index)
|
||||
cur.execute(sql_statement, {'value': str(value)})
|
||||
objects = []
|
||||
while True:
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
break
|
||||
objects.append(cls._row2ob(row))
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
if ignore_errors:
|
||||
objects = (x for x in objects if x is not None)
|
||||
|
||||
return list(objects)
|
||||
get_with_indexed_value = classmethod(get_with_indexed_value)
|
||||
|
||||
def store(self):
|
||||
sql_dict = {
|
||||
'name': self.name,
|
||||
'email': self.email,
|
||||
'roles': self.roles,
|
||||
'is_admin': self.is_admin,
|
||||
'anonymous': self.anonymous,
|
||||
'name_identifiers': self.name_identifiers,
|
||||
'identification_token': self.identification_token,
|
||||
'lasso_dump': self.lasso_dump,
|
||||
'last_seen': None,
|
||||
}
|
||||
if self.last_seen:
|
||||
sql_dict['last_seen'] = datetime.datetime.fromtimestamp(self.last_seen),
|
||||
|
||||
columns = self.form_data.keys()
|
||||
for field in self.get_formdef().fields:
|
||||
sql_type = SQL_TYPE_MAPPING.get(field.type, 'varchar')
|
||||
if sql_type is None:
|
||||
continue
|
||||
value = self.form_data.get(field.id)
|
||||
if value is not None:
|
||||
if field.type == 'ranked-items':
|
||||
# turn {'poire': 2, 'abricot': 1, 'pomme': 3} into an array
|
||||
value = [[x, str(y)] for x, y in value.items()]
|
||||
elif sql_type == 'varchar':
|
||||
pass
|
||||
elif sql_type == 'date':
|
||||
value = datetime.datetime.fromtimestamp(time.mktime(value))
|
||||
elif sql_type == 'bytea':
|
||||
value = bytearray(cPickle.dumps(value))
|
||||
elif sql_type == 'boolean':
|
||||
pass
|
||||
sql_dict['f%s' % field.id] = value
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
if not self.id:
|
||||
sql_statement = '''INSERT INTO %s (id, name, email, roles,
|
||||
is_admin, anonymous,
|
||||
name_identifiers,
|
||||
identification_token,
|
||||
lasso_dump, last_seen, %s)
|
||||
VALUES (DEFAULT, %%(name)s, %%(email)s,
|
||||
%%(roles)s, %%(is_admin)s,
|
||||
%%(anonymous)s,
|
||||
%%(name_identifiers)s,
|
||||
%%(identification_token)s,
|
||||
%%(lasso_dump)s,
|
||||
%%(last_seen)s,
|
||||
%s)
|
||||
RETURNING id''' % (
|
||||
self._table_name,
|
||||
', '.join(['f%s' % x for x in columns]),
|
||||
', '.join(['%%(f%s)s' % x for x in columns]))
|
||||
cur.execute(sql_statement, sql_dict)
|
||||
self.id = cur.fetchone()[0]
|
||||
else:
|
||||
sql_dict['id'] = self.id
|
||||
sql_statement = '''UPDATE %s SET name = %%(name)s,
|
||||
email = %%(email)s,
|
||||
roles = %%(roles)s,
|
||||
is_admin = %%(is_admin)s,
|
||||
anonymous = %%(anonymous)s,
|
||||
name_identifiers = %%(name_identifiers)s,
|
||||
identification_token = %%(identification_token)s,
|
||||
lasso_dump = %%(lasso_dump)s,
|
||||
last_seen = %%(last_seen)s,
|
||||
%s''' % (
|
||||
self._table_name,
|
||||
', '.join(['f%s = %%(f%s)s' % (x,x) for x in columns]))
|
||||
cur.execute(sql_statement, sql_dict)
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def keys(cls):
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
sql_statement = 'SELECT id FROM %s' % cls._table_name
|
||||
cur.execute(sql_statement)
|
||||
ids = [x[0] for x in cur.fetchall()]
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return ids
|
||||
keys = classmethod(keys)
|
||||
|
||||
def count(cls):
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
sql_statement = 'SELECT count(*) FROM %s' % cls._table_name
|
||||
cur.execute(sql_statement)
|
||||
count = cur.fetchone()[0]
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return count
|
||||
count = classmethod(count)
|
||||
|
||||
def _row2ob(cls, row):
|
||||
o = cls()
|
||||
(o.id, o.name, o.email, o.roles, o.is_admin, o.anonymous,
|
||||
o.name_identiifers, o.identification_token, o.lasso_dump,
|
||||
o.last_seen) = tuple(row[:10])
|
||||
if o.last_seen:
|
||||
o.last_seen = time.mktime(o.last_seen.timetuple())
|
||||
o.form_data = {}
|
||||
i = 10
|
||||
for field in cls.get_formdef().fields:
|
||||
sql_type = SQL_TYPE_MAPPING.get(field.type, 'varchar')
|
||||
if sql_type is None:
|
||||
continue
|
||||
value = row[i]
|
||||
if value:
|
||||
if field.type == 'ranked-items':
|
||||
d = {}
|
||||
for data, rank in value:
|
||||
d[data] = int(rank)
|
||||
value = d
|
||||
if sql_type == 'date':
|
||||
value = value.timetuple()
|
||||
elif sql_type == 'bytea':
|
||||
value = cPickle.loads(str(value))
|
||||
o.form_data[field.id] = value
|
||||
i += 1
|
||||
return o
|
||||
_row2ob = classmethod(_row2ob)
|
||||
|
||||
def get_data_fields(cls):
|
||||
data_fields = []
|
||||
for field in cls.get_formdef().fields:
|
||||
sql_type = SQL_TYPE_MAPPING.get(field.type, 'varchar')
|
||||
if sql_type is None:
|
||||
continue
|
||||
data_fields.append('f%s' % field.id)
|
||||
return data_fields
|
||||
get_data_fields = classmethod(get_data_fields)
|
||||
|
||||
def get(cls, id, ignore_errors=False, ignore_migration=False):
|
||||
if id is None:
|
||||
if ignore_errors:
|
||||
return None
|
||||
else:
|
||||
raise KeyError()
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
|
||||
sql_statement = '''SELECT id, name, email, roles, is_admin, anonymous,
|
||||
name_identifiers, identification_token,
|
||||
lasso_dump, last_seen, %s
|
||||
FROM %s
|
||||
WHERE id = %%(id)s''' % (
|
||||
', '.join(cls.get_data_fields()),
|
||||
cls._table_name)
|
||||
cur.execute(sql_statement, {'id': str(id)})
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
cur.close()
|
||||
raise KeyError()
|
||||
cur.close()
|
||||
return cls._row2ob(row)
|
||||
get = classmethod(get)
|
||||
|
||||
|
||||
def select(cls, clause = None, order_by = None, ignore_errors = False, limit = None):
|
||||
conn = get_connection()
|
||||
cur = conn.cursor()
|
||||
sql_statement = '''SELECT id, name, email, roles, is_admin, anonymous,
|
||||
name_identifiers, identification_token,
|
||||
lasso_dump, last_seen, %s
|
||||
FROM %s''' % (
|
||||
', '.join(cls.get_data_fields()),
|
||||
cls._table_name)
|
||||
cur.execute(sql_statement)
|
||||
objects = []
|
||||
while True:
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
break
|
||||
objects.append(cls._row2ob(row))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
if ignore_errors:
|
||||
objects = (x for x in objects if x is not None)
|
||||
if clause:
|
||||
objects = (x for x in objects if clause(x))
|
||||
if order_by:
|
||||
order_by = str(order_by)
|
||||
if order_by[0] == '-':
|
||||
reverse = True
|
||||
order_by = order_by[1:]
|
||||
else:
|
||||
reverse = False
|
||||
# only list can be sorted
|
||||
objects = list(objects)
|
||||
objects.sort(lambda x,y: cmp(getattr(x, order_by), getattr(y, order_by)))
|
||||
if reverse:
|
||||
objects.reverse()
|
||||
if limit:
|
||||
objects = _take(objects, limit)
|
||||
return list(objects)
|
||||
select = classmethod(select)
|
||||
|
||||
|
|
Loading…
Reference in New Issue