Mercurial > p > roundup > code
diff roundup/cgi/client.py @ 7692:8fb42f41ef10 issue2550923_computed_property
merge in default branch to see if ti clears a travis-ci build error on 2.7 python; default branch builds fine
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 11 Sep 2023 00:10:29 -0400 |
| parents | 7102de2c8733 |
| children | cc4b11ab2f22 |
line wrap: on
line diff
--- a/roundup/cgi/client.py Mon Jul 10 17:31:34 2023 -0400 +++ b/roundup/cgi/client.py Mon Sep 11 00:10:29 2023 -0400 @@ -4,7 +4,6 @@ import base64 import binascii -import cgi import codecs import email.utils import errno @@ -25,6 +24,7 @@ class SysCallError(Exception): pass +from roundup.anypy.cgi_ import cgi import roundup.anypy.email_ # noqa: F401 -- patches for email library code import roundup.anypy.random_ as random_ # quality of random checked below @@ -43,8 +43,8 @@ Redirect, SendFile, SendStaticFile, SeriousError) from roundup.cgi.form_parser import FormParser -from roundup.exceptions import LoginError, Reject, RejectRaw, \ - Unauthorised, UsageError +from roundup.exceptions import LoginError, RateLimitExceeded, Reject, \ + RejectRaw, Unauthorised, UsageError from roundup.mailer import Mailer, MessageSendError @@ -531,9 +531,9 @@ # strip HTTP_PROXY issue2550925 in case # PROXY header is set. if 'HTTP_PROXY' in self.env: - del(self.env['HTTP_PROXY']) + del (self.env['HTTP_PROXY']) if 'HTTP_PROXY' in os.environ: - del(os.environ['HTTP_PROXY']) + del (os.environ['HTTP_PROXY']) xmlrpc_enabled = self.instance.config.WEB_ENABLE_XMLRPC rest_enabled = self.instance.config.WEB_ENABLE_REST @@ -572,7 +572,7 @@ self.determine_language() # Open the database as the correct user. try: - self.determine_user() + self.determine_user(is_api="xmlrpc") self.db.tx_Source = "xmlrpc" self.db.i18n = self.translator except LoginError as msg: @@ -583,6 +583,14 @@ self.setHeader("Content-Length", str(len(output))) self.write(s2b(output)) return + except RateLimitExceeded as msg: + output = xmlrpc_.client.dumps( + xmlrpc_.client.Fault(429, "%s" % msg), + allow_none=True) + self.setHeader("Content-Type", "text/xml") + self.setHeader("Content-Length", str(len(output))) + self.write(s2b(output)) + return if not self.db.security.hasPermission('Xmlrpc Access', self.userid): output = xmlrpc_.client.dumps( @@ -655,13 +663,19 @@ # Open the database as the correct user. # TODO: add everything to RestfulDispatcher try: - self.determine_user() + self.determine_user(is_api="rest") self.db.tx_Source = "rest" self.db.i18n = self.translator except LoginError as err: output = s2b("Invalid Login - %s" % str(err)) self.reject_request(output, status=http_.client.UNAUTHORIZED) return + except RateLimitExceeded as err: + output = s2b("%s" % str(err)) + # PYTHON2:FIXME http_.client.TOO_MANY_REQUESTS missing + # python2 so use numeric code. + self.reject_request(output, status=429) + return # verify Origin is allowed on all requests including GET. # If a GET, missing origin is allowed (i.e. same site GET request) @@ -854,6 +868,8 @@ except SysCallError: # OpenSSL.SSL.SysCallError is similar to IOError above pass + except RateLimitExceeded: + raise except SeriousError as message: self.write_html(str(message)) @@ -917,6 +933,9 @@ except FormError as e: self.add_error_message(self._('Form Error: ') + str(e)) self.write_html(self.renderContext()) + except RateLimitExceeded as e: + self.add_error_message(str(e)) + self.write_html(self.renderContext()) except IOError: # IOErrors here are due to the client disconnecting before # receiving the reply. @@ -1108,9 +1127,9 @@ self.make_user_anonymous() raise LoginError(str(err)) - return(token) - - def determine_user(self): + return (token) + + def determine_user(self, is_api=False): """Determine who the user is""" self.opendb('admin') @@ -1171,8 +1190,8 @@ # So we set the user to anonymous first. self.make_user_anonymous() login = self.get_action_class('login')(self) - login.verifyLogin(username, password) - except LoginError: + login.verifyLogin(username, password, is_api=is_api) + except (LoginError, RateLimitExceeded): self.make_user_anonymous() raise user = username @@ -1839,7 +1858,7 @@ # mime type detection is performed in cgi.form_parser # everything not here is served as 'application/octet-stream' - whitelist = [ + mime_type_allowlist = [ 'text/plain', 'text/x-csrc', # .c 'text/x-chdr', # .h @@ -1859,7 +1878,7 @@ ] if self.instance.config['WEB_ALLOW_HTML_FILE']: - whitelist.append('text/html') + mime_type_allowlist.append('text/html') try: mime_type = klass.get(nodeid, 'type') @@ -1869,7 +1888,7 @@ if not mime_type: mime_type = 'text/plain' - if mime_type not in whitelist: + if mime_type not in mime_type_allowlist: mime_type = 'application/octet-stream' # --/ mime-type security @@ -2743,7 +2762,7 @@ """ if value is None: try: - del(self.additional_headers[header]) + del (self.additional_headers[header]) except KeyError: pass else: @@ -2764,7 +2783,7 @@ headers['Content-Type'] = 'text/html; charset=utf-8' if response in [204, 304]: # has no body so no content-type - del(headers['Content-Type']) + del (headers['Content-Type']) headers = list(headers.items())
