def enable_disable_languages(store, request): cur_enabled_langs = EnabledLanguage.list(store) new_enabled_langs = [unicode(y) for y in request['languages_enabled']] if len(new_enabled_langs) < 1: raise errors.InvalidInputFormat("No languages enabled!") if request['default_language'] not in new_enabled_langs: raise errors.InvalidInputFormat( "Invalid lang code for chosen default_language") appdata = None for lang_code in new_enabled_langs: if lang_code not in LANGUAGES_SUPPORTED_CODES: raise errors.InvalidInputFormat("Invalid lang code: %s" % lang_code) if lang_code not in cur_enabled_langs: if appdata is None: appdata = load_appdata() log.debug("Adding a new lang %s" % lang_code) EnabledLanguage.add_new_lang(store, lang_code, appdata) to_remove = list(set(cur_enabled_langs) - set(new_enabled_langs)) if len(to_remove): users = store.find(models.User, In(models.User.language, to_remove)) for user in users: user.language = request['default_language'] EnabledLanguage.remove_old_langs(store, to_remove)
def enable_disable_languages(store, request): cur_enabled_langs = EnabledLanguage.get_all_strings(store) new_enabled_langs = [unicode(y) for y in request['languages_enabled']] if len(new_enabled_langs) < 1: raise errors.InvalidInputFormat("No languages enabled!") if request['default_language'] not in new_enabled_langs: raise errors.InvalidInputFormat( "Invalid lang code for chosen default_language") appdata = None for lang_code in new_enabled_langs: if lang_code not in LANGUAGES_SUPPORTED_CODES: raise errors.InvalidInputFormat("Invalid lang code: %s" % lang_code) if lang_code not in cur_enabled_langs: if appdata is None: appdata = load_appdata() log.debug("Adding a new lang %s" % lang_code) EnabledLanguage.add_new_lang(store, lang_code, appdata) for lang_code in cur_enabled_langs: if lang_code not in new_enabled_langs: EnabledLanguage.remove_old_lang(store, lang_code)
def db_create_context(store, request, language): """ Creates a new context from the request of a client. We associate to the context the list of receivers and if the receiver is not valid we raise a ReceiverIdNotFound exception. Args: (dict) the request containing the keys to set on the model. Returns: (dict) representing the configured context """ receivers = request.get('receivers', []) steps = request.get('steps', []) fill_localized_keys(request, models.Context.localized_strings, language) context = models.Context(request) # Integrity checks related on name (need to exists, need to be unique) # are performed only using the default language at the moment (XXX) try: context_name = request['name'][language] except Exception as excep: raise errors.InvalidInputFormat("language %s do not provide name: %s" % (language, excep)) if len(context_name) < 1: log.err("Invalid request: name is an empty string") raise errors.InvalidInputFormat( "Context name is missing (1 char required)") if request['select_all_receivers']: if request['maximum_selectable_receivers']: log.debug( "Resetting maximum_selectable_receivers (%d) because 'select_all_receivers' is True" % request['maximum_selectable_receivers']) request['maximum_selectable_receivers'] = 0 # tip_timetolive to be converted in seconds since hours and days context.tip_timetolive = acquire_context_timetolive( int(request['tip_timetolive'])) c = store.add(context) for receiver_id in receivers: receiver = models.Receiver.get(store, receiver_id) if not receiver: log.err("Creation error: unexistent context can't be associated") raise errors.ReceiverIdNotFound c.receivers.add(receiver) if steps: db_create_steps(store, c.id, steps, language) else: db_setup_default_steps(store, c.id) log.debug("Created context %s (using %s)" % (context_name, language)) return admin_serialize_context(store, context, language)
def import_receivers(store, submission, receiver_id_list): context = submission.context if not len(receiver_id_list): raise errors.SubmissionValidationFailure( "needed almost one receiver selected [1]") if context.maximum_selectable_receivers and \ len(receiver_id_list) > context.maximum_selectable_receivers: raise errors.InvalidInputFormat( "provided an invalid number of receivers") for receiver in store.find(models.Receiver, In(models.Receiver.id, receiver_id_list)): if context not in receiver.contexts: raise errors.InvalidInputFormat( "forged receiver selection, you fuzzer! <:") if not GLSettings.memory_copy.allow_unencrypted and receiver.user.pgp_key_status != u'enabled': raise errors.SubmissionValidationFailure( "the platform does not allow selection of receivers with encryption disabled" ) continue submission.receivers.add(receiver) log.debug("+receiver [%s] In tip (%s) #%d" % \ (receiver.user.name, submission.id, submission.receivers.count() )) if submission.receivers.count() == 0: raise errors.SubmissionValidationFailure( "needed almost one receiver selected [2]")
def associate_field(store, field, step=None, fieldgroup=None): """ Associate a field to a specified step or fieldgroup :param store: the store on which perform queries. """ if step: if field.is_template: raise errors.InvalidInputFormat( "Cannot associate a field template to a step") step.children.add(field) if fieldgroup: if field.is_template != fieldgroup.is_template: raise errors.InvalidInputFormat( "Cannot associate field templates with fields") ancestors = set(fieldtree_ancestors(store, field.id)) if field.id in [field.template_id, fieldgroup.id] or \ field.template_id == fieldgroup.id or \ field.template_id in ancestors or \ fieldgroup.id in ancestors: raise errors.InvalidInputFormat( "Provided field association would cause recursion loop") fieldgroup.children.add(field)
def dict_v(_self, attr, value): """ Validate dict content, every key, if unicode, have not to overcome the generic length limit. """ if not value: return {} if not isinstance(value, dict): raise errors.InvalidInputFormat("(%s) dict expected" % attr) for key, subvalue in value.iteritems(): if isinstance(subvalue, str): subvalue = unicode(subvalue) if isinstance(subvalue, unicode): if len(subvalue) > GLSettings.memory_copy.maximum_textsize: raise errors.InvalidInputFormat("In dict %s the key %s" \ "overcome length limit of %d" % (attr, key, GLSettings.memory_copy.maximum_textsize)) if isinstance(subvalue, dict): dict_v(_self, attr, subvalue) return value
def associate_field(store, field, template=None, step=None, fieldgroup=None): """ Associate a field to a specified step or fieldgroup :param store: the store on which perform queries :param field: the field to be associated :param template: the template to which bind the field :param step: the step to which associate the field :param fieldgroup: the fieldgroup to which associate the field """ if template: if field.instance != 'reference': raise errors.InvalidInputFormat("Only fields of kind reference can be binded to a template") field.template_id = template.id if step: if field.instance == 'template': raise errors.InvalidInputFormat("Cannot associate a field template to a step") step.children.add(field) if fieldgroup: if field.instance == 'template' and fieldgroup.instance != 'template': raise errors.InvalidInputFormat("Cannot associate field template to a field") ancestors = set(fieldtree_ancestors(store, fieldgroup.id)) if field.id == fieldgroup.id or field.id in ancestors: raise errors.InvalidInputFormat("Provided field association would cause recursion loop") fieldgroup.children.add(field)
def import_receivers(store, submission, receiver_id_list): context = submission.context if not len(receiver_id_list): log.err("Receivers required to be selected, not empty") raise errors.SubmissionValidationFailure("needed almost one receiver selected") if context.maximum_selectable_receivers and \ len(receiver_id_list) > context.maximum_selectable_receivers: raise errors.InvalidInputFormat("provided an invalid number of receivers") for receiver in store.find(Receiver, In(Receiver.id, receiver_id_list)): if context not in receiver.contexts: raise errors.InvalidInputFormat("forged receiver selection, you fuzzer! <:") try: if not GLSettings.memory_copy.allow_unencrypted and \ receiver.pgp_key_status != u'enabled': log.err("Encrypted only submissions are supported. Cannot select [%s]" % receiver.id) continue submission.receivers.add(receiver) except Exception as excep: log.err("Receiver %s can't be assigned to the tip [%s]" % (receiver.id, excep)) continue log.debug("+receiver [%s] In tip (%s) #%d" % \ (receiver.name, submission.id, submission.receivers.count() )) if submission.receivers.count() == 0: log.err("Receivers required to be selected, not empty") raise errors.SubmissionValidationFailure("needed at least one receiver selected [2]")
def update_notification(store, request, language=GLSetting.memory_copy.default_language): try: notif = store.find(Notification).one() except Exception as excep: log.err("Database error or application error: %s" % excep) raise excep mo = structures.Rosetta() mo.acquire_request(language, request, Notification) for attr in mo.get_localized_attrs(): request[attr] = mo.get_localized_dict(attr) if request['security'] in Notification._security_types: notif.security = request['security'] else: log.err("Invalid request: Security option not recognized") log.debug("Invalid Security value: %s" % request['security']) raise errors.InvalidInputFormat("Security selection not recognized") try: notif.update(request) except Exception as dberror: log.err("Unable to update Notification: %s" % dberror) raise errors.InvalidInputFormat(dberror) if request['disable'] != GLSetting.notification_temporary_disable: log.msg("Switching notification mode: was %s and now is %s" % ("DISABLE" if GLSetting.notification_temporary_disable else "ENABLE", "DISABLE" if request['disable'] else "ENABLE")) GLSetting.notification_temporary_disable = request['disable'] return admin_serialize_notification(notif, language)
def _on_request_body(self, data): try: self._request.body = data content_type = self._request.headers.get("Content-Type", "") if self._request.method in ("POST", "PATCH", "PUT"): if content_type.startswith( "application/x-www-form-urlencoded" ) and self.content_length < GLSetting.www_form_urlencoded_maximum_size: arguments = parse_qs_bytes(native_str(self._request.body)) for name, values in arguments.iteritems(): values = [v for v in values if v] if values: self._request.arguments.setdefault( name, []).extend(values) elif content_type.startswith( "application/x-www-form-urlencoded"): raise errors.InvalidInputFormat( "content type application/x-www-form-urlencoded not supported" ) elif content_type.startswith("multipart/form-data"): raise errors.InvalidInputFormat( "content type multipart/form-data not supported") self.request_callback(self._request) except Exception as exception: log.msg("Malformed HTTP request from %s: %s" % (self._remote_ip, exception)) log.exception(exception) if self._request: self._request.finish() if self.transport: self.transport.loseConnection()
def update_field(store, field_id, request, language): """ Update the specified field with the details. raises :class:`globaleaks.errors.FieldIdNotFound` if the field does not exist. :param store: the store on which perform queries. :param: field_id: the field_id of the field to update :param: request: the field definition dict :param: language: the language of the field definition dict :return: a serialization of the object """ errmsg = 'Invalid or not existent field ids in request.' is_template, step_id, fieldgroup_id = field_integrity_check(request) field = models.Field.get(store, field_id) try: if not field: raise errors.InvalidInputFormat(errmsg) fill_localized_keys(request, models.Field.localized_strings, language) field.update(request) # children handling: # - old children are cleared # - new provided childrens are evaluated and added children = request['children'] if children and field.type != 'fieldgroup': raise errors.InvalidInputFormat( "children can be associated only to fields of type fieldgroup") ancestors = set(fieldtree_ancestors(store, field.id)) field.children.clear() for c in children: child = models.Field.get(store, c['id']) # check child do exists and graph is not recursive if not child or child.id == field.id or child.id in ancestors: raise errors.InvalidInputFormat(errmsg) # remove current step/field fieldgroup/field association disassociate_field(store, child.id) field.children.add(child) db_update_options(store, field.id, request['options'], language) # remove current step/field fieldgroup/field association disassociate_field(store, field_id) associate_field(store, field, step_id, fieldgroup_id) except Exception as dberror: log.err('Unable to update field: {e}'.format(e=dberror)) raise errors.InvalidInputFormat(dberror) return anon_serialize_field(store, field, language)
def import_receivers(store, submission, receiver_id_list, required=False): context = submission.context # Clean the previous list of selected Receiver for prevrec in submission.receivers: try: submission.receivers.remove(prevrec) except Exception as excep: log.err( "Unable to remove receiver from Tip, before new reassignment") raise excep # and now clean the received list and import the new Receiver set. receiver_id_list = set(receiver_id_list) if required and (not len(receiver_id_list)): log.err("Receivers required to be selected, not empty") raise errors.SubmissionFailFields( "Needed almost one Receiver selected") if context.maximum_selectable_receivers and \ len(receiver_id_list) > context.maximum_selectable_receivers: raise errors.InvalidInputFormat( "Provided an invalid number of Receivers") for receiver_id in receiver_id_list: try: receiver = store.find(Receiver, Receiver.id == unicode(receiver_id)).one() except Exception as excep: log.err("Receiver requested (%s) can't be found: %s" % (receiver_id, excep)) raise errors.ReceiverIdNotFound if context not in receiver.contexts: raise errors.InvalidInputFormat( "Forged receiver selection, you fuzzer! <:") try: if not GLSetting.memory_copy.allow_unencrypted and \ receiver.gpg_key_status != u'enabled': log.err( "Encrypted only submissions are supported. Cannot select [%s]" % receiver_id) continue submission.receivers.add(receiver) except Exception as excep: log.err("Receiver %s can't be assigned to the tip [%s]" % (receiver_id, excep)) continue log.debug("+receiver [%s] In tip (%s) #%d" %\ (receiver.name, submission.id, submission.receivers.count() ) ) if required and submission.receivers.count() == 0: log.err("Receivers required to be selected, not empty") raise errors.SubmissionFailFields( "Needed at least one Receiver selected [2]")
def validate_message(message, message_template): try: jmessage = json.loads(message) except ValueError: raise errors.InvalidInputFormat("Invalid JSON format") if BaseHandler.validate_jmessage(jmessage, message_template): return jmessage raise errors.InvalidInputFormat("Unexpected condition!?")
def db_create_field(store, field_dict, language): """ Create and add a new field to the store, then return the new serialized object. :param store: the store on which perform queries. :param field_dict: the field definition dict :param language: the language of the field definition dict :return: a serialization of the object """ fill_localized_keys(field_dict, models.Field.localized_keys, language) field = models.Field(field_dict) if field_dict['template_id'] != '': field.template_id = field_dict['template_id'] if field_dict['step_id'] != '': field.step_id = field_dict['step_id'] if field_dict['fieldgroup_id'] != '': ancestors = set(fieldtree_ancestors(store, field_dict['fieldgroup_id'])) if field.id == field_dict['fieldgroup_id'] or field.id in ancestors: raise errors.InvalidInputFormat( "Provided field association would cause recursion loop") field.fieldgroup_id = field_dict['fieldgroup_id'] store.add(field) if field.template: # special handling of the whistleblower_identity field if field.template.key == 'whistleblower_identity': if field.step: if not field.step.questionnaire.enable_whistleblower_identity: field.step.questionnaire.enable_whistleblower_identity = True else: raise errors.InvalidInputFormat( "Whistleblower identity field already present") else: raise errors.InvalidInputFormat( "Cannot associate whistleblower identity field to a fieldgroup" ) else: db_update_fieldattrs(store, field.id, field_dict['attrs'], language) db_update_fieldoptions(store, field.id, field_dict['options'], language) for c in field_dict['children']: c['fieldgroup_id'] = field.id db_create_field(store, c, language) return field
def db_create_field(store, field_dict, language): """ Create and add a new field to the store, then return the new serialized object. :param store: the store on which perform queries. :param field_dict: the field definition dict :param language: the language of the field definition dict :return: a serialization of the object """ fill_localized_keys(field_dict, models.Field.localized_keys, language) if field_dict.get('fieldgroup_id', ''): ancestors = set(fieldtree_ancestors(store, field_dict['fieldgroup_id'])) if field_dict['id'] == field_dict['fieldgroup_id'] or field_dict[ 'id'] in ancestors: raise errors.InvalidInputFormat( "Provided field association would cause recursion loop") field = models.db_forge_obj(store, models.Field, field_dict) if field.template_id is not None: # special handling of the whistleblower_identity field if field.template_id == 'whistleblower_identity': if field.step_id is not None: questionnaire = store.find( models.Questionnaire, models.Field.id == field.id, models.Field.step_id == models.Step.id, models.Step.questionnaire_id == models.Questionnaire.id).one() if questionnaire.enable_whistleblower_identity is False: questionnaire.enable_whistleblower_identity = True else: raise errors.InvalidInputFormat( "Whistleblower identity field already present") else: raise errors.InvalidInputFormat( "Cannot associate whistleblower identity field to a fieldgroup" ) else: db_update_fieldattrs(store, field, field_dict.get('attrs', []), language) db_update_fieldoptions(store, field, field_dict.get('options', []), language) if field.instance != 'reference': for c in field_dict.get('children', []): c['fieldgroup_id'] = field.id db_create_field(store, c, language) return field
def validate_jmessage(jmessage, message_template): """ Takes a string that represents a JSON messages and checks to see if it conforms to the message type it is supposed to be. This message must be either a dict or a list. This function may be called recursively to validate sub-parameters that are also go GLType. message: the message string that should be validated message_type: the GLType class it should match. """ if isinstance(message_template, dict): valid_jmessage = {} for key in message_template.keys(): if key not in jmessage: log.err('validate_message: key %s not in %s' % (key, jmessage)) raise errors.InvalidInputFormat( 'wrong schema: missing %s' % key) else: valid_jmessage[key] = jmessage[key] if GLSetting.loglevel == "DEBUG": # check if wrong keys are reaching the GLBackend, they are # stripped in the previous loop, because valid_jmessage is returned for double_k in jmessage.keys(): if double_k not in message_template.keys(): log.err("[!?] validate_message: key %s not expected" % double_k) jmessage = valid_jmessage for key, value in message_template.iteritems(): if not BaseHandler.validate_type(jmessage[key], value): raise errors.InvalidInputFormat( "REST integrity check 1, fail in %s" % key) for key, value in jmessage.iteritems(): if not BaseHandler.validate_type(value, message_template[key]): raise errors.InvalidInputFormat( "REST integrity check 2, fail in %s" % key) return True elif isinstance(message_template, list): return all( BaseHandler.validate_type(x, message_template[0]) for x in jmessage) else: raise errors.InvalidInputFormat( "invalid json massage: expected dict or list")
def sanitize_gpg_string(self, received_gpgasc): """ @param received_gpgasc: A gpg armored key @return: Sanitized string or raise InvalidInputFormat This function validate the integrity of a GPG key """ lines = received_gpgasc.split("\n") sanitized = "" start = 0 if not len(lines[start]): start += 1 if lines[start] != '-----BEGIN PGP PUBLIC KEY BLOCK-----': raise errors.InvalidInputFormat("GPG invalid format") else: sanitized += lines[start] + "\n" i = 0 while i < len(lines): # the C language as left some archetypes in my code # [ITA] https://www.youtube.com/watch?v=7jI4DnRJP3k i += 1 try: if len(lines[i]) < 2: continue except IndexError: continue main_content = re.compile( r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", re.UNICODE) base64only = main_content.findall(lines[i]) if len(base64only) == 1: sanitized += str(base64only[0]) + "\n" # this GPG/PGP format it's different from the common base64 ? dunno if len(lines[i]) == 5 and lines[i][0] == '=': sanitized += str(lines[i]) + "\n" if lines[i] == '-----END PGP PUBLIC KEY BLOCK-----': sanitized += lines[i] + "\n" return sanitized raise errors.InvalidInputFormat("Malformed PGP key block")
def update_step(store, step_id, request, language): """ Update the specified step with the details. raises :class:`globaleaks.errors.StepIdNotFound` if the step does not exist. :param store: the store on which perform queries. :param step_id: the step_id of the step to update :param request: the step definition dict :param language: the language of the step definition dict :return: a serialization of the object """ step = models.Step.get(store, step_id) try: if not step: raise errors.StepIdNotFound fill_localized_keys(request, models.Step.localized_strings, language) step.update(request) for child in request['children']: db_update_field(store, child['id'], child, language) except Exception as dberror: log.err('Unable to update step: {e}'.format(e=dberror)) raise errors.InvalidInputFormat(dberror) return anon_serialize_step(store, step, language)
def update_context(store, context_id, request, language): """ Updates the specified context. If the key receivers is specified we remove the current receivers of the Context and reset set it to the new specified ones. If no such context exists raises :class:`globaleaks.errors.ContextIdNotFound`. Args: context_id: request: (dict) the request to use to set the attributes of the Context Returns: (dict) the serialized object updated """ context = store.find(models.Context, models.Context.id == context_id).one() if not context: raise errors.ContextIdNotFound receivers = request.get('receivers', []) steps = request.get('steps', []) fill_localized_keys(request, models.Context.localized_strings, language) for receiver in context.receivers: context.receivers.remove(receiver) for receiver_id in receivers: receiver = store.find(models.Receiver, models.Receiver.id == receiver_id).one() if not receiver: log.err("Update error: unexistent receiver can't be associated") raise errors.ReceiverIdNotFound context.receivers.add(receiver) context.tip_timetolive = acquire_context_timetolive( int(request['tip_timetolive'])) if request['select_all_receivers']: if request['maximum_selectable_receivers']: log.debug( "Resetting maximum_selectable_receivers (%d) because 'select_all_receivers' is True" % request['maximum_selectable_receivers']) request['maximum_selectable_receivers'] = 0 try: context.update(request) except DatabaseError as dberror: log.err("Unable to update context %s: %s" % (context.name, dberror)) raise errors.InvalidInputFormat(dberror) if request['reset_steps']: db_update_steps(store, context.id, [], language) db_setup_default_steps(store, context.id) else: db_update_steps(store, context.id, steps, language) return admin_serialize_context(store, context, language)
def shorttext_v(_self, _attr, value): """ Validator for 'name' element, receiver, context, node, and few others are here checked """ if isinstance(value, str): value = unicode(value) if not isinstance(value, unicode): raise errors.InvalidInputFormat("Name expected unicode (%s)" % value) if len(value) > GLSetting.memory_copy.maximum_namesize: raise errors.InvalidInputFormat("Name length need to be < of %d" % GLSetting.memory_copy.maximum_namesize) return value
def verify_fields_recursively(fields, wb_fields): for f in fields: if f not in wb_fields: raise errors.SubmissionFailFields( "missing field (no structure present): %s" % f) if fields[f]['required'] and ('value' not in wb_fields[f] or wb_fields[f]['value'] == ''): raise errors.SubmissionFailFields( "missing required field (no value provided): %s" % f) if isinstance(wb_fields[f]['value'], unicode): if len(wb_fields[f] ['value']) > GLSetting.memory_copy.maximum_textsize: raise errors.InvalidInputFormat( "field value overcomes size limitation") indexed_fields = {} for f_c in fields[f]['children']: indexed_fields[f_c['id']] = copy.deepcopy(f_c) indexed_wb_fields = {} for f_c in wb_fields[f]['children']: indexed_wb_fields[f_c['id']] = copy.deepcopy(f_c) verify_fields_recursively(indexed_fields, indexed_wb_fields) for wbf in wb_fields: if wbf not in fields: raise errors.SubmissionFailFields("provided unexpected field %s" % wbf)
def db_update_memory_variables(store): """ to get fast checks, import (same) of the Node variable in GLSettings, this function is called every time that Node is updated. """ try: node = store.find(models.Node).one() GLSettings.memory_copy.maximum_filesize = node.maximum_filesize GLSettings.memory_copy.maximum_namesize = node.maximum_namesize GLSettings.memory_copy.maximum_textsize = node.maximum_textsize GLSettings.memory_copy.tor2web_admin = node.tor2web_admin GLSettings.memory_copy.tor2web_submission = node.tor2web_submission GLSettings.memory_copy.tor2web_receiver = node.tor2web_receiver GLSettings.memory_copy.tor2web_unauth = node.tor2web_unauth GLSettings.memory_copy.submission_minimum_delay = node.submission_minimum_delay GLSettings.memory_copy.submission_maximum_ttl = node.submission_maximum_ttl GLSettings.memory_copy.allow_unencrypted = node.allow_unencrypted GLSettings.memory_copy.allow_iframes_inclusion = node.allow_iframes_inclusion GLSettings.memory_copy.exception_email = node.exception_email GLSettings.memory_copy.default_language = node.default_language GLSettings.memory_copy.default_timezone = node.default_timezone GLSettings.memory_copy.languages_enabled = node.languages_enabled # Email settings are copyed because they are used when an exception raises # and we can't go to check in the DB, because that's shall be exception source notif = store.find(models.Notification).one() GLSettings.memory_copy.notif_server = notif.server GLSettings.memory_copy.notif_port = notif.port GLSettings.memory_copy.notif_password = notif.password GLSettings.memory_copy.notif_username = notif.username GLSettings.memory_copy.notif_security = notif.security GLSettings.memory_copy.notification_threshold_per_hour = notif.notification_threshold_per_hour GLSettings.memory_copy.notification_suspension_time = notif.notification_suspension_time if GLSettings.developer_name: GLSettings.memory_copy.notif_source_name = GLSettings.developer_name else: GLSettings.memory_copy.notif_source_name = notif.source_name GLSettings.memory_copy.notif_source_name = notif.source_name GLSettings.memory_copy.notif_source_email = notif.source_email GLSettings.memory_copy.notif_uses_tor = notif.torify if GLSettings.disable_mail_notification: GLSettings.memory_copy.disable_receiver_notification_emails = True GLSettings.memory_copy.disable_admin_notification_emails = True else: GLSettings.memory_copy.disable_receiver_notification_emails = notif.disable_receivers_notification_emails GLSettings.memory_copy.disable_admin_notification_emails = notif.disable_admin_notification_emails except Exception as e: raise errors.InvalidInputFormat("Cannot import memory variables: %s" % e)
def delete_field(store, field_id): """ Delete the field object corresponding to field_id If the field has children, remove them as well. If the field is immediately attached to a step object, remove it as well. :param store: the store on which perform queries. :param field_id: the id corresponding to the field. :raises FieldIdNotFound: if no such field is found. """ field = store.find(models.Field, models.Field.id == field_id).one() if not field: raise errors.FieldIdNotFound # TODO: to be uncommented upon completion of fields implementaion # if not field.editable: # raise errors.FieldNotEditable if field.instance == 'template': if store.find(models.Field, models.Field.template_id == field.id).count(): raise errors.InvalidInputFormat( "Cannot remove the field template as it is used by one or more questionnaires" ) if field.template: # special handling of the whistleblower_identity field if field.template.key == 'whistleblower_identity': if field.step is not None: field.step.questionnaire.enable_whistleblower_identity = False store.remove(field)
def get_uploaded_file(self): uploaded_file = self.request.body if not isinstance(uploaded_file, dict) or len(uploaded_file.keys()) != 5: raise errors.InvalidInputFormat("Expected a dict of five keys in uploaded file") for filekey in uploaded_file.keys(): if filekey not in [u'body', u'body_len', u'content_type', u'filename', u'body_filepath']: raise errors.InvalidInputFormat( "Invalid JSON key in uploaded file (%s)" % filekey) return uploaded_file
def delete_field(store, field_id): """ Delete the field object corresponding to field_id If the field has children, remove them as well. If the field is immediately attached to a step object, remove it as well. :param store: the store on which perform queries. :param field_id: the id corresponding to the field. """ field = models.db_get(store, models.Field, id=field_id) if not field.editable: raise errors.FieldNotEditable if field.instance == 'template': if store.find(models.Field, models.Field.template_id == field.id).count(): raise errors.InvalidInputFormat( "Cannot remove the field template as it is used by one or more questionnaires" ) if field.template_id == 'whistleblower_identity' and field.step_id is not None: store.find( models.Questionnaire, models.Step.id == field.step_id, models.Questionnaire.id == models.Step.questionnaire_id).set( enable_whistleblower_identity=False) store.remove(field)
def field_integrity_check(store, field): """ Preliminar validations of field descriptor in relation to: - step_id - fieldgroup_id template_id - instance type :param field: the field dict to be validated """ template = None step = None fieldgroup = None if field['instance'] != 'template' and (field['step_id'] == '' and field['fieldgroup_id'] == ''): raise errors.InvalidInputFormat( "Each field should be a template or be associated to a step/fieldgroup" ) if field['instance'] != 'template' and (field['step_id'] != '' and field['fieldgroup_id'] != ''): raise errors.InvalidInputFormat( "Cannot associate a field to both a step and a fieldgroup") if field['template_id'] != '': template = store.find(models.Field, models.Field.id == field['template_id']).one() if not template: raise errors.FieldIdNotFound if field['step_id'] != '': step = store.find(models.Step, models.Step.id == field['step_id']).one() if not step: raise errors.StepIdNotFound if field['fieldgroup_id'] != '': fieldgroup = store.find( models.Field, models.Field.id == field['fieldgroup_id']).one() if not fieldgroup: raise errors.FieldIdNotFound return field['instance'], template, step, fieldgroup
def db_update_node(store, request, wizard_done, language): """ Update and serialize the node infos :param store: the store on which perform queries. :param language: the language in which to localize data :return: a dictionary representing the serialization of the node """ node = store.find(models.Node).one() fill_localized_keys(request, models.Node.localized_keys, language) # verify that the languages enabled are valid 'code' in the languages supported node.languages_enabled = [] for lang_code in request['languages_enabled']: if lang_code in LANGUAGES_SUPPORTED_CODES: node.languages_enabled.append(lang_code) else: raise errors.InvalidInputFormat("Invalid lang code enabled: %s" % lang_code) if not len(node.languages_enabled): raise errors.InvalidInputFormat("Missing enabled languages") # enforcing of default_language usage (need to be set, need to be _enabled) if request['default_language']: if request['default_language'] not in node.languages_enabled: raise errors.InvalidInputFormat("Invalid lang code as default") node.default_language = request['default_language'] else: node.default_language = node.languages_enabled[0] log.err("Default language not set!? fallback on %s" % node.default_language) if wizard_done: node.wizard_done = True node.update(request) db_refresh_memory_variables(store) return db_admin_serialize_node(store, language)
def get_file_upload(self): try: if len(self.request.files) != 1: raise errors.InvalidInputFormat( "cannot accept more than a file upload at once") chunk_size = len(self.request.files['file'][0]['body']) total_file_size = int( self.request.arguments['flowTotalSize'][0] ) if 'flowTotalSize' in self.request.arguments else chunk_size flow_identifier = self.request.arguments['flowIdentifier'][ 0] if 'flowIdentifier' in self.request.arguments else generateRandomKey( 10) if ((chunk_size / (1024 * 1024)) > GLSettings.memory_copy.maximum_filesize or (total_file_size / (1024 * 1024)) > GLSettings.memory_copy.maximum_filesize): log.err("File upload request rejected: file too big") raise errors.FileTooBig( GLSettings.memory_copy.maximum_filesize) if flow_identifier not in GLUploads: f = GLSecureTemporaryFile(GLSettings.tmp_upload_path) GLUploads[flow_identifier] = f else: f = GLUploads[flow_identifier] f.write(self.request.files['file'][0]['body']) if 'flowChunkNumber' in self.request.arguments and 'flowTotalChunks' in self.request.arguments: if self.request.arguments['flowChunkNumber'][ 0] != self.request.arguments['flowTotalChunks'][0]: return None uploaded_file = {} uploaded_file['filename'] = self.request.files['file'][0][ 'filename'] uploaded_file['content_type'] = self.request.files['file'][0][ 'content_type'] uploaded_file['body_len'] = total_file_size uploaded_file['body_filepath'] = f.filepath uploaded_file['body'] = f upload_time = time.time() - f.creation_date track_handler(self) return uploaded_file except errors.FileTooBig: raise # propagate the exception except Exception as exc: log.err("Error while handling file upload %s" % exc) return None
def post(self): """ This is the /login handler expecting login/password/role, """ request = self.validate_message(self.request.body, requests.authDict) username = request['username'] password = request['password'] role = request['role'] delay = random_login_delay() if delay: yield utility.deferred_sleep(delay) if role not in ['admin', 'wb', 'receiver']: raise errors.InvalidInputFormat( "Denied login request: invalid role requested") if get_tor2web_header(self.request.headers): if not accept_tor2web(role): log.err("Denied login request on Tor2web for role '%s'" % role) raise errors.TorNetworkRequired else: log.debug("Accepted login request on Tor2web for role '%s'" % role) if role == 'admin': user_id, status, pcn = yield login_admin(username, password) elif role == 'wb': user_id = yield login_wb(password) status = 'enabled' pcn = False else: # role == 'receiver' user_id, status, pcn = yield login_receiver(username, password) if user_id is False: GLSetting.failed_login_attempts += 1 raise errors.InvalidAuthRequest session = self.generate_session(user_id, role, status) auth_answer = { 'role': role, 'session_id': session.id, 'user_id': session.user_id, 'session_expiration': int(GLSetting.sessions[session.id].getTime()), 'status': session.user_status, 'password_change_needed': pcn } yield self.uniform_answers_delay() self.write(auth_answer)
def db_create_field(store, field_dict, language): """ Create and add a new field to the store, then return the new serialized object. :param store: the store on which perform queries. :param field: the field definition dict :param language: the language of the field definition dict :return: a serialization of the object """ _, template, step, fieldgroup = field_integrity_check(store, field_dict) fill_localized_keys(field_dict, models.Field.localized_keys, language) field = models.Field.new(store, field_dict) associate_field(store, field, template, step, fieldgroup) if field.template: # special handling of the whistleblower_identity field if field.template.key == 'whistleblower_identity': step = field.steps.one() if step: if not step.context.enable_whistleblower_identity: step.context.enable_whistleblower_identity = True else: raise errors.InvalidInputFormat( "Whistleblower identity field already present") else: raise errors.InvalidInputFormat( "Cannot associate whistleblower identity field to a fieldgroup" ) else: db_update_fieldattrs(store, field.id, field_dict['attrs'], language) db_update_fieldoptions(store, field.id, field_dict['options'], language) for c in field_dict['children']: c['fieldgroup_id'] = field.id db_create_field(store, c, language) return field