Example #1
0
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

    fill_localized_keys(request, Notification.localized_strings, language)

    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 DatabaseError 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)
Example #2
0
def db_create_user(store, request, language):
    fill_localized_keys(request, models.User.localized_keys, language)

    user = models.User({
        'username': request['username'],
        'role': request['role'],
        'state': u'enabled',
        'deletable': request['deletable'],
        'name': request['name'],
        'description': request['description'],
        'public_name': request['public_name'] if request['public_name'] != '' else request['name'],
        'language': language,
        'password_change_needed': request['password_change_needed'],
        'mail_address': request['mail_address']
    })

    if request['username'] == '':
        user.username = user.id

    password = request['password']
    if len(password) == 0:
        password = GLSettings.memory_copy.default_password

    user.salt = security.generateRandomSalt()
    user.password = security.hash_password(password, user.salt)

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    store.add(user)

    return user
Example #3
0
def update_receiver(store, receiver_id, request, language):
    """
    Updates the specified receiver with the details.
    raises :class:`globaleaks.errors.ReceiverIdNotFound` if the receiver does
    not exist.
    """
    receiver = models.Receiver.get(store, receiver_id)
    if not receiver:
        raise errors.ReceiverIdNotFound

    fill_localized_keys(request, models.Receiver.localized_keys, language)

    contexts = request.get('contexts', [])

    receiver.contexts.clear()

    for context_id in contexts:
        context = models.Context.get(store, context_id)
        if not context:
            raise errors.ContextIdNotFound

        receiver.contexts.add(context)

    receiver.update(request)

    return admin_serialize_receiver(receiver, language)
Example #4
0
def db_create_step(store, context_id, steps, language):
    """
    Add a new step to the store, then return the new serialized object.
    """
    context = models.Context.get(store, context_id)
    if context is None:
        raise errors.ContextIdNotFound

    n = 1
    for step in steps:
        step['context_id'] = context_id
        step['number'] = n

        fill_localized_keys(step, models.Step.localized_strings, language)

        s = models.Step.new(store, step)
        for f in step['children']:
            field = models.Field.get(store, f['id'])
            if not field:
                log.err("Creation error: unexistent field can't be associated")
                raise errors.FieldIdNotFound

            # remove current step/field fieldgroup/field association
            a_s, a_f = get_field_association(store, field.id)
            if a_s != s.id:
                disassociate_field(store, field.id)
                s.children.add(field)

        n += 1
Example #5
0
def db_create_field(store, field, 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
    """
    _, step, fieldgroup = field_integrity_check(store, field)

    fill_localized_keys(field, models.Field.localized_strings, language)

    if field['template_id'] == '':
        field['template_id'] = None

    f = models.Field.new(store, field)

    if field['template_id'] is None:
        db_update_fieldattrs(store, f.id, field['attrs'], language)
        db_update_fieldoptions(store, f.id, field['options'], language)

        for child in field['children']:
            db_update_field(store, child['id'], child, language)

    associate_field(store, f, step, fieldgroup)

    return f
Example #6
0
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)
Example #7
0
def db_create_field(store, request, language):
    """
    Add a new field to the store, then return the new serialized object.
    :param: store: the store reference
    :param: request: the field definition dict
    :param: language: the language of the field definition dict
    :return: a serialization of the object
    """
    is_template, step_id, fieldgroup_id = field_integrity_check(request)

    # XXX you probably want to split this if else statement into two functions
    # that are called create_field_from_template and create_field
    if not 'template_id' in request:
        fill_localized_keys(request, models.Field.localized_strings, language)
        field = models.Field.new(store, request)
        db_update_options(store, field.id, request['options'], language)
    else:
        template = store.find(models.Field, models.Field.id == request['template_id']).one()
        if not template:
            raise errors.InvalidInputFormat("The specified template id %s does not exist" %
                                            request.get('template_id'))
        field = template.copy(store, is_template)

    associate_field(store, field, step_id, fieldgroup_id)

    return anon_serialize_field(store, field, language)
Example #8
0
def db_create_step(store, context, steps, language):
    """
    Add the specified steps

    :param store: the store on which perform queries.
    :param context: the context on which register specified steps.
    :param steps: a dictionary containing the new steps.
    :param language: the language of the specified steps.
    """
    n = 1
    for step in steps:
        step['context_id'] = context.id
        step['number'] = n

        fill_localized_keys(step, models.Step.localized_strings, language)

        s = models.Step.new(store, step)
        for f in step['children']:
            field = models.Field.get(store, f['id'])
            if not field:
                log.err("Creation error: unexistent field can't be associated")
                raise errors.FieldIdNotFound

            # remove current step/field fieldgroup/field association
            a_s, _ = get_field_association(store, field.id)
            if a_s != s.id:
                disassociate_field(store, field.id)
                s.children.add(field)

        n += 1
def db_admin_update_user(store, user_id, request, language):
    """
    Updates the specified user.
    raises: globaleaks.errors.ReceiverIdNotFound` if the receiver does not exist.
    """
    user = models.User.get(store, user_id)
    if not user:
        raise errors.UserIdNotFound

    fill_localized_keys(request, models.User.localized_keys, language)

    user.name = request['name']
    user.description = request['description']

    user.state = request['state']
    user.password_change_needed = request['password_change_needed']
    user.mail_address = request['mail_address']

    user.language = request.get('language', GLSettings.memory_copy.default_language)
    user.timezone = request.get('timezone', GLSettings.memory_copy.default_timezone)

    password = request['password']
    if len(password):
        security.check_password_format(password)
        user.password = security.hash_password(password, user.salt)
        user.password_change_date = datetime_now()

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    return user
Example #10
0
def db_update_step(store, step_id, step, language):
    fill_localized_keys(step, models.Step.localized_strings, language)

    s = store.find(models.Step, models.Step.id == step_id).one()

    s.update(step)

    s.children.clear()

    for child in step['children']:
        child['step_id'] = s.id
        child['fieldgroup_id'] = ''
        db_update_field(store, child['id'], child, language)

        # remove current step/field fieldgroup/field association
        a_s, _ = get_field_association(store, child['id'])
        if a_s is None:
            s.children.add(f)
        elif a_s != s.id:
            disassociate_field(store, f.id)
            s.children.add(f)
        else: # the else condition means a_s == s.id; already associated!
            pass

    return s.id
Example #11
0
def db_create_receiver(store, request, language):
    """
    Creates a new receiver
    Returns:
        (dict) the receiver descriptor
    """
    user = db_create_user(store, request, language)

    fill_localized_keys(request, models.Receiver.localized_keys, language)

    receiver = models.Receiver(request)

    # set receiver.id user.id
    receiver.id = user.id

    store.add(receiver)

    contexts = request.get('contexts', [])
    for context_id in contexts:
        context = models.Context.get(store, context_id)
        if not context:
            raise errors.ContextIdNotFound
        context.receivers.add(receiver)

    log.debug("Created new receiver")

    return receiver
Example #12
0
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_strings, language)

    admin = store.find(models.User, (models.User.username == unicode('admin'))).one()

    admin.mail_address = request['email']
    admin.language = request['admin_language']
    admin.timezone = request['admin_timezone']

    password = request.get('password', None)
    old_password = request.get('old_password', None)

    if password and old_password and len(password) and len(old_password):
        admin.password = security.change_password(admin.password,
                                    old_password, password, admin.salt)

    # 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

    try:
        node.update(request)
    except DatabaseError as dberror:
        log.err("Unable to update node: %s" % dberror)
        raise errors.InvalidInputFormat(dberror)

    db_update_memory_variables(store)

    return db_admin_serialize_node(store, language)
Example #13
0
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 (
                    store.find(
                        models.Field,
                        models.Field.key == u"whistleblower_identity",
                        models.Field.step_id == models.Step.id,
                        models.Step.questionnaire_id == models.Questionnaire.id,
                        models.Questionnaire.id == field.step.questionnaire_id,
                    ).count()
                    == 0
                ):
                    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)

    if field.instance != "reference":
        for c in field_dict["children"]:
            c["fieldgroup_id"] = field.id
            db_create_field(store, c, language)

    return field
Example #14
0
def update_receiver(store, receiver_id, request, language=GLSetting.memory_copy.default_language):
    """
    Updates the specified receiver with the details.
    raises :class:`globaleaks.errors.ReceiverIdNotFound` if the receiver does
    not exist.
    """
    receiver = models.Receiver.get(store, receiver_id)

    if not receiver:
        raise errors.ReceiverIdNotFound

    fill_localized_keys(request, models.Receiver.localized_strings, language)

    mail_address = request['mail_address']

    homonymous = store.find(models.User, models.User.username == mail_address).one()
    if homonymous and homonymous.id != receiver.user_id:
        log.err("Update error: already present receiver with the requested username: %s" % mail_address)
        raise errors.ExpectedUniqueField('mail_address', mail_address)

    receiver.mail_address = mail_address

    # the email address it's also the username, stored in User
    receiver.user.username = mail_address

    receiver.user.state = request['state']

    # The various options related in manage GPG keys are used here.
    gpg_options_parse(receiver, request)

    receiver.user.language = request.get('language', GLSetting.memory_copy.default_language)
    receiver.user.timezone = request.get('timezone', GLSetting.memory_copy.default_timezone)

    password = request['password']
    if len(password):
        security.check_password_format(password)
        receiver.user.password = security.hash_password(password, receiver.user.salt)
        receiver.user.password_change_date = datetime_now()

    contexts = request.get('contexts', [])

    for context in receiver.contexts:
        receiver.contexts.remove(context)

    for context_id in contexts:
        context = models.Context.get(store, context_id)
        if not context:
            log.err("Update error: unexistent context can't be associated")
            raise errors.ContextIdNotFound
        receiver.contexts.add(context)

    receiver.last_update = datetime_now()
    try:
        receiver.update(request)
    except DatabaseError as dberror:
        log.err("Unable to update receiver %s: %s" % (receiver.name, dberror))
        raise errors.InvalidInputFormat(dberror)

    return admin_serialize_receiver(receiver, language)
Example #15
0
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

    context.last_update = datetime_now()

    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, [], language)
        db_setup_default_steps(store, context)
    else:
        db_update_steps(store, context, steps, language)

    return admin_serialize_context(store, context, language)
Example #16
0
    def create_dummy_field(self, store, **custom_attrs):
        field = self.get_dummy_field()

        fill_localized_keys(field, models.Field.localized_keys, 'en')

        field.update(custom_attrs)

        return models.Field.new(store, field).id
Example #17
0
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)
Example #18
0
    def migrate_ArchivedSchema(self):
        # Marking to avoid count check for ArchivedSchema
        self.fail_on_count_mismatch["ArchivedSchema"] = False

        old_node = self.store_old.find(self.model_from["Node"]).one()

        old_objs = self.store_old.find(
            self.model_from["ArchivedSchema"], self.model_from["ArchivedSchema"].language == old_node.default_language
        )
        new_obj_model = self.model_to["ArchivedSchema"]

        def fill_field_localized_keys_recursively(f, language):
            for k in ["label", "description", "hint", "multi_entry_hint"]:
                try:
                    f[k] = {language: f.get(k, "")}
                except Exception:
                    f[k] = {language: ""}

            f["attrs"] = {}

            for o in f.get("options", []):
                try:
                    if "label" in o:
                        o["label"] = {language: o.get("label", "")}
                    elif "attrs" in o:
                        if "name" in o["attrs"]:
                            o["label"] = {language: o["attrs"].get("name", "")}
                            del o["attrs"]
                except Exception:
                    pass

            for c in f.get("children", []):
                fill_field_localized_keys_recursively(c, language)

        for old_obj in old_objs:
            new_obj = self.store_new.find(
                new_obj_model, And(new_obj_model.hash == old_obj.hash, new_obj_model.type == old_obj.type)
            ).one()

            if not new_obj:
                new_obj = new_obj_model()

            for _, v in new_obj._storm_columns.iteritems():
                if v.name == "schema":
                    if not isinstance(new_obj.schema, dict):
                        new_obj.value = {}

                    for step in old_obj.schema:
                        fill_localized_keys(step, models.Step.localized_keys, old_node.default_language)
                        for c in step.get("children", []):
                            fill_field_localized_keys_recursively(c, old_node.default_language)

                    new_obj.schema = old_obj.schema
                    continue

                setattr(new_obj, v.name, getattr(old_obj, v.name))

            self.store_new.add(new_obj)
Example #19
0
def db_create_receiver(store, request, language):
    """
    Creates a new receiver.
    Returns:
        (dict) the configured receiver
    """
    fill_localized_keys(request, models.Receiver.localized_strings, language)

    password = request['password']
    if len(password) and password != GLSettings.default_password:
        security.check_password_format(password)
    else:
        password = GLSettings.default_password

    receiver_salt = security.get_salt(rstr.xeger('[A-Za-z0-9]{56}'))
    receiver_password = security.hash_password(password, receiver_salt)

    # ping_mail_address is duplicated at creation time from mail_address
    request.update({'ping_mail_address': request['mail_address']})

    receiver = models.Receiver(request)

    receiver_user_dict = {
        'username': uuid4(),
        'password': receiver_password,
        'salt': receiver_salt,
        'role': u'receiver',
        'state': u'enabled',
        'language': u'en',
        'timezone': 0,
        'password_change_needed': True,
        'mail_address': request['mail_address']
    }

    receiver_user = models.User(receiver_user_dict)

    # The various options related in manage PGP keys are used here.
    pgp_options_parse(receiver, request)

    # Set receiver.id = receiver.user.username = receiver.user.id
    receiver.id = receiver_user.username = receiver_user.id

    store.add(receiver_user)
    store.add(receiver)

    create_random_receiver_portrait(receiver.id)

    contexts = request.get('contexts', [])
    for context_id in contexts:
        context = models.Context.get(store, context_id)
        if not context:
            log.err("Creation error: invalid Context can't be associated")
            raise errors.ContextIdNotFound
        context.receivers.add(receiver)

    log.debug("Created receiver %s" % receiver.user.username)

    return admin_serialize_receiver(receiver, language)
Example #20
0
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 migrate_ArchivedSchema(self):
        # Marking to avoid count check for ArchivedSchema
        self.fail_on_count_mismatch["ArchivedSchema"] = False

        old_node = self.store_old.find(self.model_from['Node']).one()

        old_objs = self.store_old.find(self.model_from['ArchivedSchema'], self.model_from['ArchivedSchema'].language == old_node.default_language)
        new_obj_model = self.model_to['ArchivedSchema']

        def fill_field_localized_keys_recursively(f, language):
            for k in ['label', 'description', 'hint', 'multi_entry_hint']:
                try:
                    f[k] = {language: f.get(k, '')}
                except Exception:
                    f[k] = {language: ''}

            f['attrs'] = {}

            for o in f.get('options', []):
                try:
                    if 'label' in o:
                        o['label'] = {language: o.get('label', '')}
                    elif 'attrs' in o:
                        if 'name' in o['attrs']:
                            o['label'] = {language: o['attrs'].get('name', '')}
                            del o['attrs']
                except Exception:
                    pass

            for c in f.get('children', []):
                fill_field_localized_keys_recursively(c, language)

        for old_obj in old_objs:
            new_obj = self.store_new.find(new_obj_model,
                                          And(new_obj_model.hash == old_obj.hash,
                                              new_obj_model.type == old_obj.type)).one()

            if not new_obj:
                new_obj = new_obj_model()

            for _, v in new_obj._storm_columns.iteritems():
                if v.name == 'schema':
                    if not isinstance(new_obj.schema, dict):
                        new_obj.value = {}

                    for step in old_obj.schema:
                        fill_localized_keys(step, models.Step.localized_keys, old_node.default_language)
                        for c in step.get('children', []):
                            fill_field_localized_keys_recursively(c, old_node.default_language)

                    new_obj.schema = old_obj.schema
                    continue

                setattr(new_obj, v.name, getattr(old_obj, v.name))

            self.store_new.add(new_obj)
Example #22
0
    def create_dummy_field(self, store, **custom_attrs):
        field = get_dummy_field()

        fill_localized_keys(field, models.Field.localized_keys, 'en')

        field.update(custom_attrs)

        f = models.Field(field)

        store.add(f)

        return f.id
Example #23
0
def fill_context_request(request, language):
    fill_localized_keys(request, models.Context.localized_keys, language)

    request['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

    return request
Example #24
0
def db_update_fieldattrs(store, field_id, field_attrs, language):
    """
    """
    attrs_ids = []

    for name, value in field_attrs.iteritems():
        value['name'] = name
        if value['type'] == u'localized':
            fill_localized_keys(value, ['value'], language)

        attrs_ids.append(db_update_fieldattr(store, field_id, value))

    store.find(models.FieldAttr, And(models.FieldAttr.field_id == field_id, Not(In(models.FieldAttr.id, attrs_ids)))).remove()
Example #25
0
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)

    node.basic_auth = request['basic_auth']
    if request['basic_auth'] and request['basic_auth_username'] != '' and request['basic_auth_password']  != '':
        node.basic_auth = True
        node.basic_auth_username = request['basic_auth_username']
        node.basic_auth_password = request['basic_auth_password']
    else:
        node.basic_auth = False

    if wizard_done:
        node.wizard_done = True

    node.update(request)

    db_refresh_memory_variables(store)

    return db_admin_serialize_node(store, language)
Example #26
0
def update_receiver(store, receiver_id, request, language):
    """
    Updates the specified receiver with the details.
    raises :class:`globaleaks.errors.ReceiverIdNotFound` if the receiver does
    not exist.
    """
    receiver = models.Receiver.get(store, receiver_id)

    if not receiver:
        raise errors.ReceiverIdNotFound

    fill_localized_keys(request, models.Receiver.localized_strings, language)

    receiver.user.state = request['state']
    receiver.user.password_change_needed = request['password_change_needed']

    # The various options related in manage PGP keys are used here.
    pgp_options_parse(receiver, request)

    receiver.user.language = request.get('language', GLSetting.memory_copy.language)
    receiver.user.timezone = request.get('timezone', GLSetting.memory_copy.default_timezone)

    password = request['password']
    if len(password):
        security.check_password_format(password)
        receiver.user.password = security.hash_password(password, receiver.user.salt)
        receiver.user.password_change_date = datetime_now()

    contexts = request.get('contexts', [])

    for context in receiver.contexts:
        receiver.contexts.remove(context)

    for context_id in contexts:
        context = models.Context.get(store, context_id)
        if not context:
            raise errors.ContextIdNotFound

        receiver.contexts.add(context)

    receiver.last_update = datetime_now()

    try:
        receiver.update(request)
    except DatabaseError as dberror:
        log.err("Unable to update receiver %s: %s" % (receiver.name, dberror))
        raise errors.InvalidInputFormat(dberror)

    return admin_serialize_receiver(receiver, language)
Example #27
0
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
Example #28
0
def update_notification(store, request, language):
    notif = store.find(Notification).one()

    fill_localized_keys(request, Notification.localized_strings, language)

    if request['reset_templates']:
        appdata_dict = load_appdata()
        for k in appdata_dict['templates']:
            request[k] = appdata_dict['templates'][k]

    notif.update(request)

    db_update_memory_variables(store)

    return admin_serialize_notification(notif, language)
Example #29
0
def db_create_step(store, step, language):
    """
    Create the specified step

    :param store: the store on which perform queries.
    :param language: the language of the specified steps.
    """
    fill_localized_keys(step, models.Step.localized_keys, language)

    s = models.Step.new(store, step)

    for c in step['children']:
        c['step_id'] = s.id
        db_create_field(store, c, language)

    return s
Example #30
0
def db_update_fieldattr(store, field_id, attr_name, attr_dict, language):
    attr = store.find(models.FieldAttr, And(models.FieldAttr.field_id == field_id, models.FieldAttr.name == attr_name)).one()
    if not attr:
        attr = models.FieldAttr()

    attr_dict['name'] = attr_name
    attr_dict['field_id'] = field_id

    if attr_dict['type'] == 'bool':
        attr_dict['value'] = 'True' if attr_dict['value'] == True else 'False'
    elif attr_dict['type'] == u'localized':
        fill_localized_keys(attr_dict, ['value'], language)

    attr.update(attr_dict)

    store.add(attr)

    return attr.id
Example #31
0
def db_update_field(store, field_id, field_dict, language):
    field = models.Field.get(store, field_id)
    if not field:
        raise errors.FieldIdNotFound

    # To be uncommented upon completion of fields implementaion
    # if not field.editable:
    #     raise errors.FieldNotEditable

    try:
        # make not possible to change field type
        field_dict['type'] = field.type

        if field_dict['instance'] != 'reference':
            fill_localized_keys(field_dict, models.Field.localized_keys,
                                language)

            db_update_fieldattrs(store, field.id, field_dict['attrs'],
                                 language)
            db_update_fieldoptions(store, field.id, field_dict['options'],
                                   language)

            # full update
            field.update(field_dict)

        else:
            # partial update
            partial_update = {
                'x': field_dict['x'],
                'y': field_dict['y'],
                'width': field_dict['width'],
                'multi_entry': field_dict['multi_entry']
            }

            field.update(partial_update)
    except Exception as dberror:
        log.err('Unable to update field: {e}'.format(e=dberror))
        raise errors.InvalidInputFormat(dberror)

    return field
Example #32
0
def db_update_fieldattr(session, tid, field_id, attr_name, attr_dict,
                        language):
    attr_dict['name'] = attr_name
    attr_dict['field_id'] = field_id
    attr_dict['tid'] = tid

    if attr_dict['type'] == 'bool':
        attr_dict['value'] = 'True' if attr_dict['value'] else 'False'
    elif attr_dict['type'] == u'localized':
        fill_localized_keys(attr_dict, ['value'], language)

    a = session.query(models.FieldAttr).filter(
        models.FieldAttr.field_id == field_id,
        models.FieldAttr.name == attr_name,
        models.FieldAttr.field_id == models.Field.id,
        models.Field.tid == tid).one_or_none()
    if not a:
        a = models.db_forge_obj(session, models.FieldAttr, attr_dict)
    else:
        a.update(attr_dict)

    return a.id
Example #33
0
def db_create_receiver_user(store, request, language):
    """
    Creates a new receiver
    Returns:
        (dict) the receiver descriptor
    """
    fill_localized_keys(request, models.Receiver.localized_keys, language)

    user = db_create_user(store, request, language)

    receiver = models.db_forge_obj(store, models.Receiver, request)

    # set receiver.id user.id
    receiver.id = user.id

    contexts = request.get('contexts', [])

    db_associate_context_receivers(store, receiver, contexts)

    log.debug("Created new receiver")

    return receiver, user
Example #34
0
def db_update_step(session, tid, step_id, request, language):
    """
    Update the specified step with the details.

    :param session: the session 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.db_get(session, models.Step, models.Step.id == step_id,
                                               models.Questionnaire.id == models.Step.questionnaire_id,
                                               models.Questionnaire.tid == tid)

    fill_localized_keys(request, models.Step.localized_keys, language)

    step.update(request)

    for child in request['children']:
        db_update_field(session, tid, child['id'], child, language)

    return step
Example #35
0
def db_admin_update_user(store, user_id, request, language):
    """
    Updates the specified user.
    raises: globaleaks.errors.ReceiverIdNotFound` if the receiver does not exist.
    """
    user = models.User.get(store, user_id)
    if not user:
        raise errors.UserIdNotFound

    fill_localized_keys(request, models.User.localized_keys, language)

    user.update(request)

    password = request['password']
    if len(password) > 0:
        user.password = security.hash_password(password, user.salt)
        user.password_change_date = datetime_now()

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    return user
Example #36
0
def db_create_user(store, request, language):
    fill_localized_keys(request, models.User.localized_keys, language)

    password = request['password']
    if len(password) and password != GLSettings.default_password:
        security.check_password_format(password)
    else:
        password = GLSettings.default_password

    password_salt = security.get_salt(rstr.xeger('[A-Za-z0-9]{56}'))
    password_hash = security.hash_password(password, password_salt)

    user = models.User({
        'username': request['username'],
        'password': password_hash,
        'salt': password_salt,
        'role': request['role'],
        'state': u'enabled',
        'deletable': request['deletable'],
        'name': request['name'],
        'description': request['description'],
        'language': u'en',
        'timezone': 0,
        'password_change_needed': True,
        'mail_address': request['mail_address']
    })

    if request['username'] == '':
        user.username = user.id

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    create_user_picture(user.id)

    store.add(user)

    return user
Example #37
0
def db_update_fieldoption(session, tid, field_id, fieldoption_id, option_dict,
                          language, idx):
    option_dict['tid'] = tid
    option_dict['field_id'] = field_id

    fill_localized_keys(option_dict, models.FieldOption.localized_keys,
                        language)

    o = None
    if fieldoption_id is not None:
        o = session.query(models.FieldOption).filter(
            models.FieldOption.id == fieldoption_id,
            models.FieldOption.field_id == models.Field.id,
            models.Field.tid == tid).one_or_none()

    if o is None:
        o = models.db_forge_obj(session, models.FieldOption, option_dict)
    else:
        o.update(option_dict)

    o.presentation_order = idx

    return o.id
Example #38
0
def db_admin_update_user(session, state, tid, user_id, request, language):
    """
    Updates the specified user.
    """
    fill_localized_keys(request, models.User.localized_keys, language)

    user = models.db_get(session, models.User, models.User.tid == tid,
                         models.User.id == user_id)

    user.update(request)

    password = request['password']
    if password:
        user.password = security.hash_password(password, user.salt)
        user.password_change_date = datetime_now()

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(state, user, request)

    if user.role == 'admin':
        db_refresh_memory_variables(session, [tid])

    return user
Example #39
0
def db_admin_update_user(store, user_id, request, language):
    """
    Updates the specified user.
    raises: globaleaks.errors.UserIdNotFound` if the user does not exist.
    """
    fill_localized_keys(request, models.User.localized_keys, language)

    user = models.db_get(store, models.User, id=user_id)

    user.update(request)

    password = request['password']
    if password:
        user.password = security.hash_password(password, user.salt)
        user.password_change_date = datetime_now()

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    if user.role == 'admin':
        db_refresh_exception_delivery_list(store)

    return user
Example #40
0
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':
            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
Example #41
0
def db_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)
    if not step:
        raise errors.StepIdNotFound

    fill_localized_keys(request, models.Step.localized_keys, language)

    step.update(request)

    for child in request['children']:
        db_update_field(store, child['id'], child, language)

    return step
Example #42
0
def db_update_field(store, field_id, field_dict, language):
    field = models.db_get(store, models.Field, id=field_id)

    # make not possible to change field type
    field_dict['type'] = field.type
    if field_dict['instance'] != 'reference':
        fill_localized_keys(field_dict, models.Field.localized_keys, language)

        db_update_fieldattrs(store, field, field_dict['attrs'], language)
        db_update_fieldoptions(store, field, field_dict['options'], language)

        # full update
        field.update(field_dict)

    else:
        # partial update
        field.update({
            'x': field_dict['x'],
            'y': field_dict['y'],
            'width': field_dict['width'],
            'multi_entry': field_dict['multi_entry']
        })

    return field
Example #43
0
def db_update_fieldoption(store, fieldoption_id, option, language):
    fill_localized_keys(option, models.FieldOption.localized_keys, language)

    if fieldoption_id is not None:
        o = store.find(models.FieldOption,
                       models.FieldOption.id == fieldoption_id).one()
    else:
        o = None

    if o is None:
        o = models.FieldOption()
        store.add(o)

    o.update(option)

    for activated_field in option['activated_fields']:
        o.activated_fields.add(
            store.find(models.Field, models.Field.id == activated_field))

    for activated_step in option['activated_steps']:
        o.activated_steps.add(
            store.find(models.Step, models.Step.id == activated_step))

    return o.id
Example #44
0
    def migrate_ArchivedSchema(self):
        # Marking to avoid count check for ArchivedSchema
        self.fail_on_count_mismatch["ArchivedSchema"] = False

        old_node = self.store_old.find(self.model_from['Node']).one()

        old_objs = self.store_old.find(
            self.model_from['ArchivedSchema'],
            self.model_from['ArchivedSchema'].language ==
            old_node.default_language)
        new_obj_model = self.model_to['ArchivedSchema']

        def fill_field_localized_keys_recursively(f, language):
            for k in ['label', 'description', 'hint', 'multi_entry_hint']:
                try:
                    f[k] = {language: f.get(k, '')}
                except Exception:
                    f[k] = {language: ''}

            f['attrs'] = {}

            for o in f.get('options', []):
                try:
                    if 'label' in o:
                        o['label'] = {language: o.get('label', '')}
                    elif 'attrs' in o:
                        if 'name' in o['attrs']:
                            o['label'] = {language: o['attrs'].get('name', '')}
                            del o['attrs']
                except Exception:
                    pass

            for c in f.get('children', []):
                fill_field_localized_keys_recursively(c, language)

        for old_obj in old_objs:
            new_obj = self.store_new.find(
                new_obj_model,
                And(new_obj_model.hash == old_obj.hash,
                    new_obj_model.type == old_obj.type)).one()

            if not new_obj:
                new_obj = new_obj_model()

            for _, v in new_obj._storm_columns.iteritems():
                if v.name == 'schema':
                    if not isinstance(new_obj.schema, dict):
                        new_obj.value = {}

                    for step in old_obj.schema:
                        fill_localized_keys(step, models.Step.localized_keys,
                                            old_node.default_language)
                        for c in step.get('children', []):
                            fill_field_localized_keys_recursively(
                                c, old_node.default_language)

                    new_obj.schema = old_obj.schema
                    continue

                setattr(new_obj, v.name, getattr(old_obj, v.name))

            self.store_new.add(new_obj)
Example #45
0
def db_create_field(session, tid, field_dict, language):
    """
    Create and add a new field to the session, then return the new serialized object.

    :param session: the session 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
    """
    field_dict['tid'] = tid

    fill_localized_keys(field_dict, models.Field.localized_keys, language)

    check_field_association(session, tid, field_dict)

    if field_dict.get('template_id', '') != '':
        if field_dict['template_id'] == 'whistleblower_identity':
            if field_dict.get('step_id', '') == '':
                raise errors.InputValidationError(
                    "Cannot associate whistleblower identity field to a fieldgroup"
                )

            q_id = session.query(models.Questionnaire.id) \
                          .filter(models.Questionnaire.id == models.Step.questionnaire_id,
                                  models.Step.id == field_dict['step_id'])

            field = session.query(models.Field) \
                           .filter(models.Field.template_id == u'whistleblower_identity',
                                   models.Field.step_id == models.Step.id,
                                   models.Step.questionnaire_id.in_(q_id.subquery())).one_or_none()

            if field is not None:
                raise errors.InputValidationError(
                    "Whistleblower identity field already present")

        field = models.db_forge_obj(session, models.Field, field_dict)

        template = session.query(models.Field).filter(
            models.Field.id == field_dict['template_id']).one()

        field.label = template.label
        field.hint = template.hint
        field.description = template.description

        field_attrs = read_json_file(Settings.field_attrs_file)
        attrs = field_attrs.get(field.template_id, {})
        db_add_field_attrs(session, field.id, attrs)

    else:
        field = models.db_forge_obj(session, models.Field, field_dict)
        attrs = field_dict.get('attrs', [])
        options = field_dict.get('options', [])

        db_update_fieldattrs(session, tid, field.id, attrs, language)
        db_update_fieldoptions(session, tid, field.id, options, language)

    if field.instance != 'reference':
        for c in field_dict.get('children', []):
            c['tid'] = field.tid
            c['fieldgroup_id'] = field.id
            db_create_field(session, tid, c, language)

    return field
Example #46
0
def db_update_questionnaire(session, questionnaire, request, language):
    fill_localized_keys(request, models.Questionnaire.localized_keys, language)

    questionnaire.update(request)

    return questionnaire
Example #47
0
def fill_questionnaire_request(request, language):
    fill_localized_keys(request, models.Questionnaire.localized_keys, language)
    return request
Example #48
0
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_strings, language)

    admin = store.find(models.User, (models.User.username == unicode('admin'))).one()

    admin.language = request.get('admin_language', GLSetting.memory_copy.language)
    admin.timezone = request.get('admin_timezone', GLSetting.memory_copy.default_timezone)

    password = request.get('password', None)
    old_password = request.get('old_password', None)

    if password and old_password and len(password) and len(old_password):
        admin.password = security.change_password(admin.password,
                                    old_password, password, admin.salt)

    # 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 LANGUAGES_SUPPORTED_CODES:
            raise errors.InvalidInputFormat("Invalid lang code as default")

        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

    # since change of regexp format to XXXX-XXXX-XXXX-XXXX
    # we removed the possibility to customize the receipt from the GLCllient
    request['receipt_regexp'] = GLSetting.defaults.receipt_regexp

    try:
        node.update(request)
    except DatabaseError as dberror:
        log.err("Unable to update Node: %s" % dberror)
        raise errors.InvalidInputFormat(dberror)

    node.last_update = datetime_now()

    db_import_memory_variables(store)

    return db_admin_serialize_node(store, language)
Example #49
0
def db_update_field(store, field_id, field, language):
    _, step, fieldgroup = field_integrity_check(store, field)

    fill_localized_keys(field, models.Field.localized_strings, language)

    if field['template_id'] == '':
        field['template_id'] = None

    f = models.Field.get(store, field_id)
    if not f:
        raise errors.FieldIdNotFound

    try:
        # make not possible to change field type
        field['type'] = f.type

        if field['template_id'] is None:
            # children handling:
            #  - old children are cleared
            #  - new provided childrens are evaluated and added
            children = field['children']
            if len(children) and f.type != 'fieldgroup':
                raise errors.InvalidInputFormat(
                    "children can be associated only to fields of type fieldgroup"
                )

            ancestors = set(fieldtree_ancestors(store, f.id))

            f.children.clear()
            for child in children:
                if child['id'] == f.id or child['id'] in ancestors:
                    raise errors.FieldIdNotFound

                c = db_update_field(store, child['id'], child, language)

                # remove current step/field fieldgroup/field association
                disassociate_field(store, c.id)

                f.children.add(c)

            db_update_fieldattrs(store, f.id, field['attrs'], language)
            db_update_fieldoptions(store, f.id, field['options'], language)

            # full update
            f.update(field)

        else:
            # partial update
            partial_update = {
                'x': field['x'],
                'y': field['y'],
                'width': field['width'],
                'stats_enabled': field['stats_enabled'],
                'multi_entry': field['multi_entry'],
                'required': field['required']
            }

            f.update(partial_update)

        # remove current step/field fieldgroup/field association
        disassociate_field(store, field_id)

        associate_field(store, f, step, fieldgroup)
    except Exception as dberror:
        log.err('Unable to update field: {e}'.format(e=dberror))
        raise errors.InvalidInputFormat(dberror)

    return f
Example #50
0
def db_update_field(store, field_id, field_dict, language):
    field = models.Field.get(store, field_id)
    if not field:
        raise errors.FieldIdNotFound

    # To be uncommented upon completion of fields implementaion
    # if not field.editable:
    #     raise errors.FieldNotEditable

    _, template, step, fieldgroup = field_integrity_check(store, field_dict)

    try:
        # make not possible to change field type
        field_dict['type'] = field.type

        if field_dict['instance'] != 'reference':
            fill_localized_keys(field_dict, models.Field.localized_keys,
                                language)

            # children handling:
            #  - old children are cleared
            #  - new provided childrens are evaluated and added
            children = field_dict['children']
            if len(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 child in children:
                if child['id'] == field.id or child['id'] in ancestors:
                    raise errors.FieldIdNotFound

                c = db_update_field(store, child['id'], child, language)

                # remove current step/field fieldgroup/field association
                disassociate_field(c)

                field.children.add(c)

            db_update_fieldattrs(store, field.id, field_dict['attrs'],
                                 language)
            db_update_fieldoptions(store, field.id, field_dict['options'],
                                   language)

            # full update
            field.update(field_dict)

        else:
            # partial update
            partial_update = {
                'x': field_dict['x'],
                'y': field_dict['y'],
                'width': field_dict['width'],
                'multi_entry': field_dict['multi_entry']
            }

            field.update(partial_update)

        # remove current step/field fieldgroup/field association
        disassociate_field(field)

        associate_field(store, field, template, step, fieldgroup)
    except Exception as dberror:
        log.err('Unable to update field: {e}'.format(e=dberror))
        raise errors.InvalidInputFormat(dberror)

    return field
Example #51
0
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 store.find(
                        models.Field,
                        models.Field.key == u'whistleblower_identity',
                        models.Field.step_id == models.Step.id,
                        models.Step.questionnaire_id ==
                        models.Questionnaire.id, models.Questionnaire.id ==
                        field.step.questionnaire_id).count() == 0:
                    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)

    if field.instance != 'reference':
        for c in field_dict['children']:
            c['fieldgroup_id'] = field.id
            db_create_field(store, c, language)

    return field
Example #52
0
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 and submission_timetolive need to be converted in seconds since hours and days
    (context.submission_timetolive, context.tip_timetolive) = acquire_context_timetolive(request)

    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_step(store, context.id, steps, language)
    else:
        appdata = store.find(models.ApplicationData).one()
        steps = copy.deepcopy(appdata.fields)
        n_s = 1
        for step in steps:
            for f_child in step['children']:
                if not field_is_present(store, f_child):
                    f_child['is_template'] = False
        for step in steps:
            f_children = copy.deepcopy(step['children'])
            del step['children']
            s = models.db_forge_obj(store, models.Step, step)
            for f_child in f_children:
                o_children = copy.deepcopy(f_child['options'])
                del f_child['options']
                # FIXME currently default updata do not handle fieldgroups
                # all this block must be redesigned in order to be called recursively
                del f_child['children']
                f = models.db_forge_obj(store, models.Field, f_child)
                n_o = 1
                for o_child in o_children:
                    o = models.db_forge_obj(store, models.FieldOption, o_child)
                    o.field_id = f.id
                    o.number = n_o
                    f.options.add(o)
                    n_o += 1
                f.step_id = s.id
                s.children.add(f)
            s.context_id = context.id
            s.number = n_s
            context.steps.add(s)
            n_s += 1

    log.debug("Created context %s (using %s)" % (context_name, language) )

    return admin_serialize_context(store, context, language)
Example #53
0
def db_update_steps(store, context_id, steps, language):
    """
    Update steps

    :param store: the store on which perform queries.
    :param context_id: the id of the context on which register specified steps.
    :param steps: a dictionary containing the steps to be updated.
    :param language: the language of the specified steps.
    """
    context = models.Context.get(store, context_id)
    if context is None:
        raise errors.ContextIdNotFound

    old_steps = store.find(models.Step, models.Step.context_id == context_id)

    indexed_old_steps = {}
    for o in old_steps:
        indexed_old_steps[o.id] = o

    new_steps = []
    n = 1
    for step in steps:
        step['context_id'] = context_id
        step['number'] = n

        fill_localized_keys(step, models.Step.localized_strings, language)

        # check for reuse (needed to keep translations)
        if 'id' in step and step['id'] in indexed_old_steps:
            s = indexed_old_steps[step['id']]
            for field in s.children:
                s.children.remove(field)

            s.update(step)

            new_steps.append(indexed_old_steps[step['id']])
            del indexed_old_steps[step['id']]
        else:
            new_steps.append(models.Step(step))

        i = 1
        for f in step['children']:
            field = models.Field.get(store, f['id'])
            i += 1
            field.y = i
            if not field:
                log.err("Creation error: unexistent field can't be associated")
                raise errors.FieldIdNotFound

            # remove current step/field fieldgroup/field association
            a_s, _ = get_field_association(store, field.id)
            if a_s is None:
                s.children.add(field)
            elif a_s != s.id:
                disassociate_field(store, field.id)
                s.children.add(field)
            else: # the else condition means a_s == s.id; already associated!
                pass

        n += 1

    for o_id in indexed_old_steps:
        store.remove(indexed_old_steps[o_id])

    for n in new_steps:
        store.add(n)