formdata: add actions_roles index (#8281)
This commit is contained in:
parent
1c20613197
commit
ff4b2c152c
|
@ -774,6 +774,31 @@ def test_migration_2_formdef_id_in_views():
|
|||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
@postgresql
|
||||
def test_migration_6_actions_roles():
|
||||
conn, cur = sql.get_connection_and_cursor()
|
||||
cur.execute('UPDATE wcs_meta SET value = 5 WHERE key = %s', ('sql_level',))
|
||||
cur.execute('DROP VIEW wcs_all_forms')
|
||||
|
||||
# hack a formdef table the wrong way, to check it is reconstructed
|
||||
# properly before the views are created
|
||||
formdef.fields[4] = fields.StringField(id='4', label='item')
|
||||
cur.execute('DROP VIEW wcs_view_1_tests')
|
||||
cur.execute('ALTER TABLE formdata_1_tests DROP COLUMN actions_roles_array')
|
||||
sql.drop_views(formdef, conn, cur)
|
||||
formdef.fields[4] = fields.ItemField(id='4', label='item', items=('apple', 'pear', 'peach', 'apricot')),
|
||||
assert not column_exists_in_table(cur, 'formdata_1_tests', 'actions_roles_array')
|
||||
|
||||
sql.migrate()
|
||||
|
||||
assert column_exists_in_table(cur, 'formdata_1_tests', 'actions_roles_array')
|
||||
assert column_exists_in_table(cur, 'wcs_view_1_tests', 'actions_roles_array')
|
||||
assert column_exists_in_table(cur, 'wcs_all_forms', 'actions_roles_array')
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
|
||||
def drop_formdef_tables():
|
||||
conn, cur = sql.get_connection_and_cursor()
|
||||
cur.execute('''SELECT table_name FROM information_schema.tables''')
|
||||
|
@ -917,3 +942,62 @@ def test_select_any_formdata():
|
|||
|
||||
objects2 = sql.AnyFormData.select(order_by='receipt_time', limit=10, offset=20)
|
||||
assert [(x.formdef_id, x.id) for x in objects2] == [(x.formdef_id, x.id) for x in objects][20:30]
|
||||
|
||||
@postgresql
|
||||
def test_actions_roles():
|
||||
drop_formdef_tables()
|
||||
conn, cur = sql.get_connection_and_cursor()
|
||||
|
||||
wf = Workflow(name='test endpoint')
|
||||
st1 = wf.add_status('Status1', 'st1')
|
||||
st2 = wf.add_status('Status2', 'st2')
|
||||
|
||||
commentable = CommentableWorkflowStatusItem()
|
||||
commentable.id = '_commentable'
|
||||
commentable.by = ['_submitter', '1']
|
||||
st1.items.append(commentable)
|
||||
commentable.parent = st1
|
||||
|
||||
wf.store()
|
||||
assert [x.id for x in wf.get_endpoint_status()] == ['st2']
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'test actions roles'
|
||||
formdef.fields = []
|
||||
formdef.workflow = wf
|
||||
formdef.store()
|
||||
|
||||
data_class = formdef.data_class(mode='sql')
|
||||
formdata = data_class()
|
||||
formdata.status = 'wf-st1'
|
||||
formdata.store()
|
||||
formdata_id = formdata.id
|
||||
formdata = data_class()
|
||||
formdata.status = 'wf-st2'
|
||||
formdata.store()
|
||||
|
||||
cur.execute('''SELECT COUNT(*) FROM wcs_all_forms''')
|
||||
assert bool(cur.fetchone()[0] == 2)
|
||||
|
||||
cur.execute('''SELECT COUNT(*) FROM wcs_all_forms
|
||||
WHERE actions_roles_array && ARRAY['5', '1', '4']''')
|
||||
assert bool(cur.fetchone()[0] == 1)
|
||||
|
||||
# check a change to workflow is reflected in the database
|
||||
st1.items[0].by = ['2', '3']
|
||||
wf.store()
|
||||
|
||||
cur.execute('''SELECT COUNT(*) FROM wcs_all_forms
|
||||
WHERE actions_roles_array && ARRAY['5', '1', '4']''')
|
||||
assert bool(cur.fetchone()[0] == 0)
|
||||
|
||||
cur.execute('''SELECT COUNT(*) FROM wcs_all_forms
|
||||
WHERE actions_roles_array && ARRAY['2', '3']''')
|
||||
assert bool(cur.fetchone()[0] == 1)
|
||||
|
||||
# using criterias
|
||||
criterias = [st.Intersects('actions_roles_array', ['2', '3'])]
|
||||
total_count = sql.AnyFormData.count(criterias)
|
||||
formdatas = sql.AnyFormData.select(criterias)
|
||||
assert total_count == 1
|
||||
assert formdatas[0].id == formdata_id
|
||||
|
|
|
@ -143,7 +143,7 @@ class Evolution(object):
|
|||
class FormData(StorableObject):
|
||||
_names = 'XX'
|
||||
_hashed_indexes = ['user_id', 'user_hash', 'status', 'workflow_roles',
|
||||
'concerned_roles']
|
||||
'concerned_roles', 'actions_roles']
|
||||
|
||||
id_display = None
|
||||
|
||||
|
@ -462,7 +462,7 @@ class FormData(StorableObject):
|
|||
get_substitution_variables_list = classmethod(get_substitution_variables_list)
|
||||
|
||||
def rebuild_security(cls):
|
||||
cls.rebuild_indexes(indexes=['concerned_roles'])
|
||||
cls.rebuild_indexes(indexes=['concerned_roles', 'actions_roles'])
|
||||
rebuild_security = classmethod(rebuild_security)
|
||||
|
||||
def is_submitter(self, user):
|
||||
|
@ -499,10 +499,22 @@ class FormData(StorableObject):
|
|||
wf_status = self.get_status()
|
||||
if not wf_status:
|
||||
status_action_roles.add('_submitter')
|
||||
return status_action_roles
|
||||
else:
|
||||
status_action_roles |= set(self.get_actions_roles())
|
||||
return status_action_roles
|
||||
|
||||
# people that can act on a workflow status item are considered
|
||||
# 'concerned' by the formdata
|
||||
concerned_roles = property(get_concerned_roles)
|
||||
|
||||
def get_actions_roles(self):
|
||||
if self.is_draft():
|
||||
return []
|
||||
|
||||
wf_status = self.get_status()
|
||||
if not wf_status:
|
||||
return []
|
||||
|
||||
from wcs.workflows import get_role_translation
|
||||
status_action_roles = set()
|
||||
for item in wf_status.items or []:
|
||||
if not hasattr(item, 'by') or not item.by:
|
||||
continue
|
||||
|
@ -510,11 +522,13 @@ class FormData(StorableObject):
|
|||
if role == '_submitter':
|
||||
status_action_roles.add(role)
|
||||
else:
|
||||
status_action_roles.add(get_role_translation(self, role))
|
||||
real_role = get_role_translation(self, role)
|
||||
if real_role:
|
||||
status_action_roles.add(real_role)
|
||||
|
||||
return status_action_roles
|
||||
|
||||
concerned_roles = property(get_concerned_roles)
|
||||
actions_roles = property(get_actions_roles)
|
||||
|
||||
def get_last_update_time(self):
|
||||
if self.evolution and self.evolution[-1].time:
|
||||
|
|
27
wcs/sql.py
27
wcs/sql.py
|
@ -306,7 +306,8 @@ def do_formdef_tables(formdef, conn=None, cur=None, rebuild_views=False, rebuild
|
|||
needed_fields = set(['id', 'user_id', 'user_hash', 'receipt_time',
|
||||
'status', 'workflow_data', 'id_display', 'fts', 'page_no',
|
||||
'anonymised', 'workflow_roles', 'workflow_roles_array',
|
||||
'concerned_roles_array', 'tracking_code'])
|
||||
'concerned_roles_array', 'tracking_code',
|
||||
'actions_roles_array'])
|
||||
|
||||
# migrations
|
||||
if not 'fts' in existing_fields:
|
||||
|
@ -320,6 +321,8 @@ def do_formdef_tables(formdef, conn=None, cur=None, rebuild_views=False, rebuild
|
|||
cur.execute('''ALTER TABLE %s ADD COLUMN workflow_roles_array text[]''' % table_name)
|
||||
if not 'concerned_roles_array' in existing_fields:
|
||||
cur.execute('''ALTER TABLE %s ADD COLUMN concerned_roles_array text[]''' % table_name)
|
||||
if not 'actions_roles_array' in existing_fields:
|
||||
cur.execute('''ALTER TABLE %s ADD COLUMN actions_roles_array text[]''' % table_name)
|
||||
|
||||
if not 'page_no' in existing_fields:
|
||||
cur.execute('''ALTER TABLE %s ADD COLUMN page_no varchar''' % table_name)
|
||||
|
@ -369,6 +372,8 @@ def do_formdef_tables(formdef, conn=None, cur=None, rebuild_views=False, rebuild
|
|||
actions = []
|
||||
if not 'concerned_roles_array' in existing_fields:
|
||||
actions.append('rebuild_security')
|
||||
elif not 'actions_roles_array' in existing_fields:
|
||||
actions.append('rebuild_security')
|
||||
if not 'tracking_code' in existing_fields:
|
||||
# if tracking code has just been added to the table we need to make
|
||||
# sure the tracking code table does exist.
|
||||
|
@ -577,6 +582,7 @@ def do_views(formdef, conn, cur, rebuild_global_views=True):
|
|||
'''is_at_endpoint'''))
|
||||
|
||||
view_fields.append(('concerned_roles_array', 'concerned_roles_array'))
|
||||
view_fields.append(('actions_roles_array', 'actions_roles_array'))
|
||||
view_fields.append(('fts', 'fts'))
|
||||
|
||||
fields_list = ', '.join(['%s AS %s' % x for x in view_fields])
|
||||
|
@ -621,6 +627,7 @@ def do_global_views(conn, cur):
|
|||
fake_formdef = FormDef()
|
||||
common_fields = get_view_fields(fake_formdef)
|
||||
common_fields.append(('concerned_roles_array', 'concerned_roles_array'))
|
||||
common_fields.append(('actions_roles_array', 'actions_roles_array'))
|
||||
common_fields.append(('fts', 'fts'))
|
||||
common_fields.append(('is_at_endpoint', 'is_at_endpoint'))
|
||||
|
||||
|
@ -913,6 +920,7 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
|
|||
('workflow_roles', 'bytea'),
|
||||
('workflow_roles_array', 'text[]'),
|
||||
('concerned_roles_array', 'text[]'),
|
||||
('actions_roles_array', 'text[]'),
|
||||
('tracking_code', 'varchar'),
|
||||
]
|
||||
|
||||
|
@ -1018,6 +1026,7 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
|
|||
sql_dict['workflow_roles_array'] = None
|
||||
|
||||
sql_dict['concerned_roles_array'] = [str(x) for x in self.concerned_roles if x]
|
||||
sql_dict['actions_roles_array'] = [str(x) for x in self.actions_roles if x]
|
||||
|
||||
sql_dict.update(self.get_sql_dict_from_data(self.data, self._formdef))
|
||||
conn, cur = get_connection_and_cursor()
|
||||
|
@ -1229,10 +1238,14 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
|
|||
formdatas = cls.select()
|
||||
conn, cur = get_connection_and_cursor()
|
||||
for formdata in formdatas:
|
||||
sql_statement = '''UPDATE %s SET concerned_roles_array = %%(roles)s WHERE id = %%(id)s''' % cls._table_name
|
||||
sql_statement = '''UPDATE %s
|
||||
SET concerned_roles_array = %%(roles)s,
|
||||
actions_roles_array = %%(actions_roles)s
|
||||
WHERE id = %%(id)s''' % cls._table_name
|
||||
cur.execute(sql_statement, {
|
||||
'id': formdata.id,
|
||||
'roles': [str(x) for x in formdata.concerned_roles if x]})
|
||||
'roles': [str(x) for x in formdata.concerned_roles if x],
|
||||
'actions_roles': [str(x) for x in formdata.actions_roles if x]})
|
||||
conn.commit()
|
||||
cur.close()
|
||||
rebuild_security = classmethod(rebuild_security)
|
||||
|
@ -1640,7 +1653,7 @@ def get_yearly_totals(period_start=None, period_end=None, criterias=None):
|
|||
return result
|
||||
|
||||
|
||||
SQL_LEVEL = 5
|
||||
SQL_LEVEL = 6
|
||||
|
||||
def migrate_global_views(conn, cur):
|
||||
cur.execute('''SELECT COUNT(*) FROM information_schema.tables
|
||||
|
@ -1683,6 +1696,12 @@ def migrate():
|
|||
if sql_level < 5:
|
||||
# 5: add concerned_roles_array, is_at_endpoint and fts to views
|
||||
migrate_views(conn, cur)
|
||||
if sql_level < 6:
|
||||
# 6: add actions_roles_array to tables and views
|
||||
from wcs.formdef import FormDef
|
||||
migrate_views(conn, cur)
|
||||
for formdef in FormDef.select():
|
||||
formdef.data_class().rebuild_security()
|
||||
|
||||
cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', (
|
||||
str(SQL_LEVEL), 'sql_level'))
|
||||
|
|
Loading…
Reference in New Issue