annotate roundup/cgi/TranslationService.py @ 8411:ef1ea918b07a reauth-confirm_id

feat(security): Add user confirmation/reauth for sensitive changes Auditors can raise Reauth(reason) exception to require the user to enter a token (e.g. account password) to verify the user is performing the change. Naming is subject to change. actions.py: New ReauthAction class handler and verifyPassword() method for overriding if needed. client.py: Handle Reauth exception by calling Client:reauth() method. Default client:reauth method. Add 'reauth' action declaration. exceptions.py: Define and document Reauth exception as a subclass of RoundupCGIException. templating.py: Define method utils.embed_form_fields(). The original form making a change to the database has a lot of form fields. These need to be resubmitted to Roundup as part of the form submission that verifies the user's password. This method turns all non file form fields into type=hidden inputs. It escapes the names and values to prevent XSS. For file form fields, it base64 encodes the contents and puts them in hidden pre blocks. The pre blocks have data attributes for the filename, filetype and the original field name. (Note the original field name is not used.) This stops the file content data (maybe binary e.g. jpegs) from breaking the html page. The reauth template runs JavaScript that turns the encoded data inside the pre tags back into a file. Then it adds a multiple file input control to the page and attaches all the files to it. This file input is submitted with the rest of the fields. _generic.reauth.html (multiple tracker templates): Generates a form with id=reauth_form to: display any message from the Reauth exception to the user (e.g. why user is asked to auth). get the user's password submit the form embed all the form data that triggered the reauth recreate any file data that was submitted as part of the form and generate a new file input to push the data to the back end It has the JavaScript routine (as an IIFE) that regenerates a file input without user intervention. All the TAL based tracker templates use the same form. There is also one for the jinja2 template. The JavaScript for both is the same. reference.txt: document embed_form_fields utility method. upgrading.txt: initial upgrading docs. TODO: Finalize naming. I am leaning toward ConfirmID rather than Reauth. Still looking for a standard name for this workflow. Externalize the javascript in _generic.reauth.html to a seperate file and use utils.readfile() to embed it or change the script to load it from a @@file url. Clean up upgrading.txt with just steps to implement and less feature detail/internals. Document internals/troubleshooting in reference.txt. Add tests using live server.
author John Rouillard <rouilj@ieee.org>
date Mon, 11 Aug 2025 14:01:12 -0400
parents 07ce4e4110f5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
1 # TranslationService for Roundup templates
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
2 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
3 # This module is free software, you may redistribute it
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
4 # and/or modify under the same terms as Python.
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
5 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
6 # This module provides National Language Support
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
7 # for Roundup templating - much like roundup.i18n
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
8 # module for Roundup command line interface.
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
9 # The only difference is that translator objects
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
10 # returned by get_translation() have one additional
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
11 # method which is used by TAL engines:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
12 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
13 # translate(domain, msgid, mapping, context, target_language, default)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
14 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
15
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
16 from roundup import i18n
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
17 from roundup.cgi.PageTemplates import Expressions, PathIterator, TALES
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
18 from roundup.cgi.TAL import TALInterpreter
5416
56c9bcdea47f Python 3 preparation: unicode.
Joseph Myers <jsm@polyomino.org.uk>
parents: 4570
diff changeset
19 from roundup.anypy.strings import us2u, u2s
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
20
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
21 ### Translation classes
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
22
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
23
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
24 class TranslationServiceMixin:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
25
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
26 def translate(self, domain, msgid, mapping=None,
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
27 context=None, target_language=None, default=None):
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
28 _msg = self.gettext(msgid)
7228
07ce4e4110f5 flake8 fixes: whitespace, remove unused imports
John Rouillard <rouilj@ieee.org>
parents: 6200
diff changeset
29 # print ("TRANSLATE", msgid, _msg, mapping, context)
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
30 _msg = TALInterpreter.interpolate(_msg, mapping)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
31 return _msg
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
32
5447
41532b2ab141 better detection if we need a gettext workaround
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5446
diff changeset
33 if hasattr(i18n.RoundupTranslations, 'ugettext'):
5446
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
34 def gettext(self, msgid):
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
35 msgid = us2u(msgid)
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
36 msgtrans = self.ugettext(msgid)
5446
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
37 return u2s(msgtrans)
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
38
5446
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
39 def ngettext(self, singular, plural, number):
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
40 singular = us2u(singular)
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
41 plural = us2u(plural)
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
42 msgtrans = self.ungettext(singular, plural, number)
5446
214f34e18678 fix infinite recursion in Python3
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5416
diff changeset
43 return u2s(msgtrans)
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
44
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
45
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
46 class TranslationService(TranslationServiceMixin, i18n.RoundupTranslations):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
47 pass
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
48
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
49
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
50 class NullTranslationService(TranslationServiceMixin,
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
51 i18n.RoundupNullTranslations):
5477
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
52 if hasattr(i18n.RoundupNullTranslations, 'ugettext'):
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
53 def ugettext(self, message):
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
54 if self._fallback:
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
55 return self._fallback.ugettext(message)
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
56 # Sometimes the untranslatable message is a UTF-8 encoded string
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
57 # (thanks to PageTemplate's internals).
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
58 message = us2u(message)
b0c2307be3d1 applied remaining part of original patch 045 (slightly modified)
Christof Meerwald <cmeerw@cmeerw.org>
parents: 5447
diff changeset
59 return message
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
60
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
61 ### TAL patching
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
62 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
63 # Template Attribute Language (TAL) uses only global translation service,
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
64 # which is not thread-safe. We will use context variable 'i18n'
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
65 # to access request-dependent transalation service (with domain
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
66 # and target language set during initializations of the roundup
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
67 # client interface.
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
68 #
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
69
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
70
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
71 class Context(TALES.Context):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
72
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
73 def __init__(self, compiler, contexts):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
74 TALES.Context.__init__(self, compiler, contexts)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
75 if not self.contexts.get('i18n', None):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
76 # if the context contains no TranslationService,
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
77 # create default one
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
78 self.contexts['i18n'] = get_translation()
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
79 self.i18n = self.contexts['i18n']
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
80
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
81 def translate(self, domain, msgid, mapping=None,
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
82 context=None, target_language=None, default=None):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
83 if context is None:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
84 context = self.contexts.get('here')
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
85 return self.i18n.translate(domain, msgid,
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
86 mapping=mapping, context=context,
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
87 default=default,
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
88 target_language=target_language)
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
89
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
90
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
91 class Engine(TALES.Engine):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
92
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
93 def getContext(self, contexts=None, **kwcontexts):
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
94 if contexts is not None:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
95 if kwcontexts:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
96 kwcontexts.update(contexts)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
97 else:
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
98 kwcontexts = contexts
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
99 return Context(self, kwcontexts)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
100
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
101
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
102 # patching TAL like this is a dirty hack,
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
103 # but i see no other way to specify different Context class
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
104 Expressions._engine = Engine(PathIterator.Iterator)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
105 Expressions.installHandlers(Expressions._engine)
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
106
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
107 ### main API function
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
108
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
109
2807
aa0316a1b2aa get_translation: removed 'domain' argument, added 'tracker_home' argument
Alexander Smishlajev <a1s@users.sourceforge.net>
parents: 2556
diff changeset
110 def get_translation(language=None, tracker_home=None,
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
111 translation_class=TranslationService,
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
112 null_translation_class=NullTranslationService):
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
113 """Return Translation object for given language and domain
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
114
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
115 Arguments 'translation_class' and 'null_translation_class'
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
116 specify the classes that are instantiated for existing
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
117 and non-existing translations, respectively.
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
118 """
2807
aa0316a1b2aa get_translation: removed 'domain' argument, added 'tracker_home' argument
Alexander Smishlajev <a1s@users.sourceforge.net>
parents: 2556
diff changeset
119 return i18n.get_translation(language=language,
6200
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
120 tracker_home=tracker_home,
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
121 translation_class=translation_class,
718f205dbe50 pep8 fixes.
John Rouillard <rouilj@ieee.org>
parents: 5477
diff changeset
122 null_translation_class=null_translation_class)
2556
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
123
297dedb7226e TranslationService for Roundup templates
Alexander Smishlajev <a1s@users.sourceforge.net>
parents:
diff changeset
124 # vim: set et sts=4 sw=4 :

Roundup Issue Tracker: http://roundup-tracker.org/