0001-general-remove-obsolete-identification-token-feature.patch
wcs/admin/settings.py | ||
---|---|---|
756 | 756 |
def misc(self): |
757 | 757 |
misc_cfg = get_cfg('misc', {}) |
758 | 758 |
form = Form(enctype="multipart/form-data") |
759 |
form.add(CheckboxWidget, 'do-not-token', |
|
760 |
title = _('Do not show anything about identification tokens'), |
|
761 |
value = misc_cfg.get('do-not-token', False)) |
|
762 | 759 |
form.add(WidgetDict, 'namespaces', |
763 | 760 |
title = _('Namespaces for prefilling'), |
764 | 761 |
value = misc_cfg.get('namespaces', {})) |
... | ... | |
775 | 772 |
r += form.render() |
776 | 773 |
return r.getvalue() |
777 | 774 |
else: |
778 |
cfg_submit(form, 'misc', ('do-not-token', 'namespaces'))
|
|
775 |
cfg_submit(form, 'misc', ('namespaces',))
|
|
779 | 776 |
return redirect('.') |
780 | 777 | |
781 | 778 |
def export(self): |
wcs/anonylink.py | ||
---|---|---|
1 |
# w.c.s. - web application for online forms |
|
2 |
# Copyright (C) 2005-2010 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software; you can redistribute it and/or modify |
|
5 |
# it under the terms of the GNU General Public License as published by |
|
6 |
# the Free Software Foundation; either version 2 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU General Public License |
|
15 |
# along with this program; if not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from qommon.storage import StorableObject |
|
18 | ||
19 |
class AnonymityLink(StorableObject): |
|
20 |
_names = 'anonylinks' |
|
21 | ||
22 |
key = None |
|
23 |
name_identifier = None |
|
24 |
formdata_type = None |
|
25 |
formdata_def_id = None |
|
26 |
formdata_id = None |
|
27 |
wcs/forms/common.py | ||
---|---|---|
23 | 23 |
from qommon import template |
24 | 24 |
from qommon import get_logger |
25 | 25 |
from qommon.form import * |
26 |
from wcs.anonylink import AnonymityLink |
|
27 | 26 |
from qommon.strftime import strftime |
28 | 27 | |
29 | 28 |
from qommon.admin.texts import TextsDirectory |
... | ... | |
99 | 98 |
user = get_user_from_api_query_string() or get_request().user |
100 | 99 |
else: |
101 | 100 |
user = get_request().user |
102 |
if user: |
|
103 |
if user.anonymous: |
|
104 |
anonylink = AnonymityLink.select( |
|
105 |
lambda x: x.name_identifier == session.name_identifier and |
|
106 |
x.formdata_type == 'form' and |
|
107 |
x.formdata_def_id == self.formdef.id) |
|
108 |
if len(anonylink) == 1: |
|
109 |
mine = True |
|
110 |
elif self.filled.is_submitter(user): |
|
101 |
if user and not user.anonymous: |
|
102 |
if self.filled.is_submitter(user): |
|
111 | 103 |
mine = True |
112 | 104 |
else: |
113 | 105 |
if get_session() and get_session().is_anonymous_submitter(self.filled): |
wcs/forms/root.py | ||
---|---|---|
39 | 39 |
from qommon import tokens |
40 | 40 |
from qommon import emails |
41 | 41 | |
42 |
from wcs.anonylink import AnonymityLink |
|
43 | 42 |
from wcs.categories import Category |
44 | 43 |
from wcs.formdef import FormDef |
45 | 44 |
from wcs.formdata import FormData |
... | ... | |
63 | 62 |
session = get_session() |
64 | 63 |
user = session.get_user() |
65 | 64 |
user_forms = [] |
66 |
if user: |
|
67 |
if user.anonymous: |
|
68 |
anonylinks = AnonymityLink.select( |
|
69 |
lambda x: x.name_identifier == session.name_identifier and |
|
70 |
x.formdata_type == 'form') |
|
71 |
for anonylink in anonylinks: |
|
72 |
if anonylink.formdata_def_id != formdef.id: |
|
73 |
continue |
|
74 |
user_forms.append(formdef.data_class().get(anonylink.formdata_id)) |
|
75 |
else: |
|
76 |
user_forms.extend(formdef.data_class().get_with_indexed_value('user_id', user.id)) |
|
77 |
try: |
|
78 |
user_forms.extend(formdef.data_class().get_with_indexed_value('user_hash', user.hash)) |
|
79 |
except AttributeError: |
|
80 |
pass |
|
81 | ||
65 |
if user and not user.anonymous: |
|
66 |
user_forms.extend(formdef.data_class().get_with_indexed_value('user_id', user.id)) |
|
67 |
try: |
|
68 |
user_forms.extend(formdef.data_class().get_with_indexed_value('user_hash', user.hash)) |
|
69 |
except AttributeError: |
|
70 |
pass |
|
82 | 71 |
return user_forms |
83 | 72 | |
84 | 73 |
from wcs.forms.common import FormStatusPage |
... | ... | |
809 | 798 |
self.keep_tracking_code(filled) |
810 | 799 |
session.remove_magictoken(get_request().form.get('magictoken')) |
811 | 800 | |
812 |
if not filled.user_id and existing_formdata is None: |
|
813 |
a = AnonymityLink() |
|
814 |
a.formdata_type = 'form' |
|
815 |
a.formdata_def_id = self.formdef.id |
|
816 |
a.formdata_id = filled.id |
|
817 |
if session.name_identifier: |
|
818 |
a.name_identifier = session.name_identifier |
|
819 |
# XXX nothing with anonylink.key ? |
|
820 |
a.store() |
|
821 | 801 |
get_logger().info('form %s - done (id: %s)' % (self.formdef.name, filled.id)) |
822 | 802 |
url = None |
823 | 803 |
if existing_formdata is None: |
... | ... | |
1119 | 1099 |
if user.can_go_in_backoffice(): |
1120 | 1100 |
r += htmltext('<a href="%sbackoffice/">%s</a> - ') % (root_url, _('Back Office')) |
1121 | 1101 |
if user.anonymous: |
1122 |
if not get_cfg('misc', {}).get('do-not-token', False): |
|
1123 |
r += htmltext('<a href="%stoken">%s</a> - ') % (root_url, _('Enter Identification Token')) |
|
1124 | ||
1125 | 1102 |
if get_cfg('saml_identities', {}).get('creation', 'admin') != 'admin': |
1126 | 1103 |
r += htmltext('<a href="%sregister">%s</a> - ') % (root_url, _('Register')) |
1127 | 1104 |
wcs/root.py | ||
---|---|---|
48 | 48 |
from categories import Category |
49 | 49 |
from data_sources import NamedDataSource |
50 | 50 |
from formdef import FormDef |
51 |
from anonylink import AnonymityLink |
|
52 | 51 |
from roles import Role |
53 | 52 |
from wcs.api import get_user_from_api_query_string, ApiDirectory |
54 | 53 |
from myspace import MyspaceDirectory |
... | ... | |
193 | 192 | |
194 | 193 | |
195 | 194 |
class RootDirectory(Directory): |
196 |
_q_exports = ['admin', 'backoffice', 'forms', 'login', 'logout', 'token', 'saml',
|
|
195 |
_q_exports = ['admin', 'backoffice', 'forms', 'login', 'logout', 'saml', |
|
197 | 196 |
'ident', 'register', 'afterjobs', 'themes', 'myspace', 'user', 'roles', |
198 | 197 |
'pages', ('tmp-upload', 'tmp_upload'), 'api', '__version__', |
199 | 198 |
'tryauth', 'auth', 'preview'] |
... | ... | |
233 | 232 |
# (and to set it as none/get/soap?) |
234 | 233 |
return self.saml.slo_sp() |
235 | 234 | |
236 |
def token(self): |
|
237 |
if not get_request().user: |
|
238 |
raise errors.AccessUnauthorizedError() |
|
239 | ||
240 |
form = Form(enctype='multipart/form-data') |
|
241 |
form.add(StringWidget, 'token', title = _('Identification Token'), |
|
242 |
required = True, size = 30) |
|
243 |
form.add_submit('submit', _('Submit')) |
|
244 |
form.add_submit('cancel', _('Cancel')) |
|
245 | ||
246 |
if form.get_widget('cancel').parse(): |
|
247 |
return redirect('.') |
|
248 | ||
249 |
if not form.is_submitted() or form.has_errors(): |
|
250 |
template.html_top(_('Identification Token')) |
|
251 |
# TODO: include explanation about identification token (?) |
|
252 |
r = TemplateIO(html=True) |
|
253 |
r += htmltext('<p>%s</p>') % _('Please enter your identification token.') |
|
254 |
r += htmltext(form.render()) |
|
255 |
return r.getvalue() |
|
256 |
else: |
|
257 |
session = get_session() |
|
258 |
if get_request().user: |
|
259 |
lasso_dump = get_request().user.lasso_dump |
|
260 |
else: |
|
261 |
return template.error_page('No Lasso Identity Dump (???)') |
|
262 |
token = form.get_widget('token').parse() |
|
263 |
users_with_token = list(get_publisher().user_class.get_users_with_identification_token(token)) |
|
264 |
if len(users_with_token) == 0: |
|
265 |
return template.error_page(_('Unknown Token')) |
|
266 | ||
267 |
user = users_with_token[0] |
|
268 |
user.name_identifiers.append(session.name_identifier) |
|
269 |
user.lasso_dump = str(lasso_dump) |
|
270 |
user.identification_token = None |
|
271 |
user.store() |
|
272 | ||
273 |
session.set_user(user.id) |
|
274 | ||
275 |
for anonylink in AnonymityLink.select( |
|
276 |
lambda x: x.name_identifier == session.name_identifier): |
|
277 |
if anonylink.formdata_type == 'form': |
|
278 |
fdef = FormDef.get(anonylink.formdata_def_id) |
|
279 |
else: |
|
280 |
continue # ? |
|
281 |
data = fdef.data_class().get(anonylink.formdata_id) |
|
282 |
data.user_id = user.id |
|
283 |
data.store() |
|
284 |
anonylink.remove_self() |
|
285 | ||
286 |
return redirect('.') |
|
287 | ||
288 | 235 |
def user(self): |
289 | 236 |
if get_request().is_json(): |
290 | 237 |
return self.user_json() |
wcs/sql.py | ||
---|---|---|
392 | 392 |
is_admin bool, |
393 | 393 |
anonymous bool, |
394 | 394 |
name_identifiers text[], |
395 |
identification_token varchar, |
|
396 | 395 |
lasso_dump text, |
397 | 396 |
last_seen timestamp)''' % table_name) |
398 | 397 |
cur.execute('''SELECT column_name FROM information_schema.columns |
... | ... | |
400 | 399 |
existing_fields = set([x[0] for x in cur.fetchall()]) |
401 | 400 | |
402 | 401 |
needed_fields = set(['id', 'name', 'email', 'roles', 'is_admin', |
403 |
'anonymous', 'name_identifiers', 'identification_token',
|
|
402 |
'anonymous', 'name_identifiers', |
|
404 | 403 |
'lasso_dump', 'last_seen']) |
405 | 404 | |
406 | 405 |
from admin.settings import UserFieldsFormDef |
... | ... | |
1241 | 1240 |
('is_admin', 'bool'), |
1242 | 1241 |
('anonymous', 'bool'), |
1243 | 1242 |
('name_identifiers', 'varchar[]'), |
1244 |
('identification_token', 'varchar'), |
|
1245 | 1243 |
('lasso_dump', 'text'), |
1246 | 1244 |
('last_seen', 'timestamp') |
1247 | 1245 |
] |
... | ... | |
1262 | 1260 |
'is_admin': self.is_admin, |
1263 | 1261 |
'anonymous': self.anonymous, |
1264 | 1262 |
'name_identifiers': self.name_identifiers, |
1265 |
'identification_token': self.identification_token, |
|
1266 | 1263 |
'lasso_dump': self.lasso_dump, |
1267 | 1264 |
'last_seen': None, |
1268 | 1265 |
} |
... | ... | |
1303 | 1300 |
def _row2ob(cls, row): |
1304 | 1301 |
o = cls() |
1305 | 1302 |
(o.id, o.name, o.email, o.roles, o.is_admin, o.anonymous, |
1306 |
o.name_identifiers, o.identification_token, o.lasso_dump,
|
|
1307 |
o.last_seen) = tuple(row[:10])
|
|
1303 |
o.name_identifiers, o.lasso_dump, |
|
1304 |
o.last_seen) = tuple(row[:9])
|
|
1308 | 1305 |
if o.last_seen: |
1309 | 1306 |
o.last_seen = time.mktime(o.last_seen.timetuple()) |
1310 | 1307 |
if o.roles: |
... | ... | |
1587 | 1584 |
return result |
1588 | 1585 | |
1589 | 1586 | |
1590 |
SQL_LEVEL = 3
|
|
1587 |
SQL_LEVEL = 4
|
|
1591 | 1588 | |
1592 | 1589 |
def migrate_global_views(conn, cur): |
1593 | 1590 |
cur.execute('''SELECT COUNT(*) FROM information_schema.tables |
... | ... | |
1620 | 1617 |
# make sure all formdefs have up-to-date views |
1621 | 1618 |
do_formdef_tables(formdef, conn=conn, cur=cur, rebuild_views=True) |
1622 | 1619 |
migrate_global_views(conn, cur) |
1623 |
if sql_level < 3: # 3: introduction of _structured for user fields |
|
1620 |
if sql_level < 4: |
|
1621 |
# 3: introduction of _structured for user fields |
|
1622 |
# 4: removal of identification_token |
|
1624 | 1623 |
do_user_table() |
1625 | 1624 | |
1626 | 1625 |
cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', ( |
wcs/users.py | ||
---|---|---|
34 | 34 |
form_data = None # dumping ground for custom fields |
35 | 35 | |
36 | 36 |
name_identifiers = None |
37 |
identification_token = None |
|
38 | 37 |
lasso_dump = None |
39 | 38 | |
40 | 39 |
last_seen = None |
... | ... | |
147 | 146 |
return cls.select([st.Equal('email', email)]) |
148 | 147 |
get_users_with_email = classmethod(get_users_with_email) |
149 | 148 | |
150 |
def get_users_with_identification_token(cls, token): |
|
151 |
return cls.select([st.Equal('identification_token', token)]) |
|
152 |
get_users_with_identification_token = classmethod(get_users_with_identification_token) |
|
153 | ||
154 | 149 |
def get_substitution_variables(self, prefix='session_'): |
155 | 150 |
d = { |
156 | 151 |
prefix+'user': self, |
157 |
- |