Beispiel #1
0
def rest_create(request, callback=None):
    """Create a new item of type clazz. The item will be
    initialised with the data provided in the submitted POST request.
    The submitted data will be validated before the item is actually
    saved. If the submission fails the item is not saved in the
    database. In all cases the item is returned as JSON object with the
    item and updated values back to the client. The JSON Response will
    include further details on the reason why the validation failed.

    :clazz: Class of item to create
    :request: Current request
    :returns: JSON object.

    """
    clazz = request.context.__model__
    # Create a new item.
    factory = clazz.get_item_factory()
    item = factory.create(request.user)
    # Initialise the create form for the item to be able to validate the
    # submitted data.
    form = Form(get_form_config(item, 'create'),
                item, request.db, translate=request.translate,
                csrf_token=request.session.get_csrf_token())
    if form.validate(request.params):
            sitem = form.save()
            return JSONResponse(True, sitem)
    else:
        # Validation fails! return item
        return JSONResponse(False, sitem)
Beispiel #2
0
 def test_get_form_config(self):
     from ringo.model.modul import ModulItem
     from ringo.lib.form import get_form_config
     factory = ModulItem.get_item_factory()
     item = factory.load(1)
     result = get_form_config(item, 'create')
     self.assertEqual(result.id, 'create')
Beispiel #3
0
def get_blobform_config(request, item, formname):
    """Helper function used in the create_ method to setup the create
    forms for blogform items. To create a new blogform item the
    creation is done in three steps:

    1. Stage 1: The user selects a form from a list
    2. Stage 2: The create dialog is rendered with the selected form
    3. Stage 3: The item is validated and saved.

    :request: current request
    :item: item to build the form
    :formname: name of the form in the formconfig
    :returns: formconfig, item used to build a form.

    """
    # First check if the fid parameter is provided
    fid = request.params.get('fid') or item.fid
    blobform = request.params.get('blobforms')
    if fid:
        log.debug("Stage 3: User has submitted data to create a new item")
        setattr(item, 'fid', fid)
        formfactory = BlobformForm.get_item_factory()
        formconfig = Config(parse(formfactory.load(fid).definition))
        return item, formconfig.get_form(formname)
    elif blobform:
        log.debug("Stage 2: User has selected a blobform %s " % blobform)
        setattr(item, 'fid', blobform)
        formfactory = BlobformForm.get_item_factory()
        formconfig = Config(parse(formfactory.load(blobform).definition))
        return item, formconfig.get_form(formname)
    else:
        log.debug("Stage 1: User is selecting a blobform")
        modul = get_item_modul(request, item)
        formconfig = get_form_config(modul, "blobform")
        return modul, formconfig
Beispiel #4
0
def get_blobform_config(request, item, formname):
    """Helper function used in the create_ method to setup the create
    forms for blogform items. To create a new blogform item the
    creation is done in three steps:

    1. Stage 1: The user selects a form from a list
    2. Stage 2: The create dialog is rendered with the selected form
    3. Stage 3: The item is validated and saved.

    :request: current request
    :item: item to build the form
    :formname: name of the form in the formconfig
    :returns: formconfig, item used to build a form.

    """
    # First check if the fid parameter is provided
    fid = request.params.get('fid') or item.fid
    blobform = request.params.get('blobforms')
    if fid:
        log.debug("Stage 3: User has submitted data to create a new item")
        setattr(item, 'fid', fid)
        formfactory = BlobformForm.get_item_factory()
        formconfig = Config(parse(formfactory.load(fid).definition))
        return item, formconfig.get_form(formname)
    elif blobform:
        log.debug("Stage 2: User has selected a blobform %s " % blobform)
        setattr(item, 'fid', blobform)
        formfactory = BlobformForm.get_item_factory()
        formconfig = Config(parse(formfactory.load(blobform).definition))
        return item, formconfig.get_form(formname)
    else:
        log.debug("Stage 1: User is selecting a blobform")
        modul = get_item_modul(request, item)
        formconfig = get_form_config(modul, "blobform")
        return modul, formconfig
Beispiel #5
0
    def anonymize_values(self, values, form="create"):
        """Will return a anonymized version of the values dictionary

        :values: Dictionary with values of the item.
        :returns: Dictionary with anonymized values of the item.

        """
        formconfig = get_form_config(self, form)
        anon_values = {}
        fields = formconfig.get_fields()
        for key in fields:
            value = values.get(key)
            if not value:
                continue
            field = fields[key]
            if "anonymize" not in field.tags:
                anon_values[key] = values[key]
                continue
            # Special handling of datatypes:
            if field.type == "date":
                anon_values[key] = None
            else:
                anon_values[key] = None

        # Finally remove some global values
        for key in ["uuid"]:
            anon_values[key] = None
        return anon_values
 def test_get_form_config(self):
     from ringo.model.modul import ModulItem
     from ringo.lib.form import get_form_config
     factory = ModulItem.get_item_factory()
     item = factory.load(1)
     result = get_form_config(item, 'create')
     self.assertEqual(result.id, 'create')
Beispiel #7
0
def removeaccount(request):
    """Method to remove the useraccout by the user."""

    # Check authentification
    # The view is only available for authenticated users and callable
    # if the user is not the admin unser (id=1)
    id = request.matchdict.get('id')
    if not request.user or id == '1':
        raise HTTPUnauthorized

    clazz = User
    _ = request.translate
    # Load the item return 400 if the item can not be found.
    factory = clazz.get_item_factory()
    try:
        item = factory.load(id, request.db)
        # Check authorisation
        if item.id != request.user.id:
            raise HTTPForbidden()
    except sa.orm.exc.NoResultFound:
        raise HTTPBadRequest()

    form = Form(get_form_config(item, 'removeaccount'),
                item,
                request.db,
                translate=_,
                renderers={},
                change_page_callback={
                    'url': 'set_current_form_page',
                    'item': clazz.__tablename__,
                    'itemid': id
                },
                request=request,
                csrf_token=request.session.get_csrf_token(),
                dependencies=create_dependencies(request))

    if request.POST:
        mapping = {'item': item}
        if form.validate(request.params):
            # Delete the account and redirect the user to a result page
            request.db.delete(item)
            headers = forget(request)
            target_url = request.route_path('users-accountremoved')
            return HTTPFound(location=target_url, headers=headers)
        else:
            msg = _('Deleting the account of '
                    '"${item}" failed.',
                    mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'error')

    rvalue = {}
    rvalue['clazz'] = clazz
    rvalue['item'] = item
    rvalue['form'] = form.render(page=get_current_form_page(clazz, request))
    return rvalue
Beispiel #8
0
def get_item_form(name, request, renderers=None, validators=None, values=None):
    """Will return a form for the given item

    :name: Name of the form
    :request: Current request
    :renderers: Dictionary of external renderers which should be used
                for renderering some form elements.
    :validators: List of external formbar validators which should be
                 added to the form for validation
    :values: Dictionary with external values to prefill the form or add
    addional values for rule evaluation.
    :returns: Form
    """
    if renderers is None:
        renderers = {}
    if validators is None:
        validators = []
    if values is None:
        values = {}
    item = get_item_from_request(request)
    renderers = add_renderers(renderers)
    clazz = request.context.__model__
    name = request.session.get("%s.form" % clazz) or name

    # handle blobforms
    if isinstance(item, Blobform):
        # TODO: Why not use the get_form_config method here. This can
        # handle Blobforms and usual form configs. () <2014-08-26 22:21>

        item, formconfig = get_blobform_config(request, item, name)
    else:
        formconfig = get_form_config(item, name)

    form = Form(formconfig,
                item,
                request.db,
                translate=request.translate,
                renderers=renderers,
                change_page_callback={
                    'url': 'set_current_form_page',
                    'item': clazz.__tablename__,
                    'itemid': item.id
                },
                request=request,
                csrf_token=request.session.get_csrf_token(),
                eval_url=get_eval_url(),
                url_prefix=get_app_url(request),
                locale=locale_negotiator(request),
                values=values,
                timezone=get_timezone(request),
                dependencies=create_dependencies(request))
    # Add validators
    for validator in validators:
        form.add_validator(validator)
    return form
Beispiel #9
0
def removeaccount(request):
    """Method to remove the useraccout by the user."""

    # Check authentification
    # The view is only available for authenticated users and callable
    # if the user is not the admin unser (id=1)
    id = request.matchdict.get('id')
    if not request.user or id == '1':
        raise HTTPUnauthorized

    clazz = User
    _ = request.translate
    handle_history(request)
    handle_params(request)
    # Load the item return 400 if the item can not be found.
    factory = clazz.get_item_factory()

    try:
        item = factory.load(id, request.db)
        # Check authorisation
        if item.id != request.user.id:
            raise HTTPForbidden()
    except sa.orm.exc.NoResultFound:
        raise HTTPBadRequest()

    form = Form(get_form_config(item, 'removeaccount'),
                item, request.db, translate=_,
                renderers={},
                change_page_callback={'url': 'set_current_form_page',
                                      'item': clazz.__tablename__,
                                      'itemid': id},
                request=request, csrf_token=request.session.get_csrf_token())

    if request.POST:
        mapping = {'item': item}
        if form.validate(request.params):
            # Delete the account and redirect the user to a result page
            request.db.delete(item)
            headers = forget(request)
            target_url = request.route_path('users-accountremoved')
            return HTTPFound(location=target_url, headers=headers)
        else:
            msg = _('Deleting the account of '
                    '"${item}" failed.', mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'error')

    rvalue = {}
    rvalue['clazz'] = clazz
    rvalue['item'] = item
    rvalue['form'] = form.render(page=get_current_form_page(clazz, request))
    return rvalue
Beispiel #10
0
def get_item_form(name, request, renderers=None, validators=None, values=None):
    """Will return a form for the given item

    :name: Name of the form
    :request: Current request
    :renderers: Dictionary of external renderers which should be used
                for renderering some form elements.
    :validators: List of external formbar validators which should be
                 added to the form for validation
    :values: Dictionary with external values to prefill the form or add
    addional values for rule evaluation.
    :returns: Form
    """
    if renderers is None:
        renderers = {}
    if validators is None:
        validators = []
    if values is None:
        values = {}
    item = get_item_from_request(request)
    renderers = add_renderers(renderers)
    clazz = request.context.__model__
    name = request.session.get("%s.form" % clazz) or name

    ## handle blobforms
    if isinstance(item, Blobform):
        # TODO: Why not use the get_form_config method here. This can
        # handle Blobforms and usual form configs. () <2014-08-26 22:21>

        item, formconfig = get_blobform_config(request, item, name)
    else:
        formconfig = get_form_config(item, name)

    form = Form(formconfig, item, request.db,
                translate=request.translate,
                renderers=renderers,
                change_page_callback={'url': 'set_current_form_page',
                                      'item': clazz.__tablename__,
                                      'itemid': item.id},
                request=request,
                csrf_token=request.session.get_csrf_token(),
                eval_url=get_eval_url(),
                url_prefix=get_app_url(request),
                locale=locale_negotiator(request),
                values=values)
    # Add validators
    for validator in validators:
        form.add_validator(validator)
    return form
Beispiel #11
0
def changepassword(request):
    """Method to change the users password by the user. The user user
    musst provide his old and the new pasword. Users are only allowed to
    change their own password."""

    # Check authentification
    # As this view has now security configured it is
    # generally callable by all users. For this reason we first check if
    # the user is authenticated. If the user is not authenticated the
    # raise an 401 (unauthorized) exception.
    if not request.user:
        raise HTTPUnauthorized

    clazz = User
    _ = request.translate
    rvalue = {}
    # Load the item return 400 if the item can not be found.
    id = request.matchdict.get('id')
    factory = clazz.get_item_factory()
    try:
        item = factory.load(id, request.db)
        # Check authorisation
        # User are only allowed to set their own password.
        if item.id != request.user.id:
            raise HTTPForbidden()
    except sa.orm.exc.NoResultFound:
        raise HTTPBadRequest()

    form = Form(get_form_config(item, 'changepassword'),
                item, request.db, translate=_,
                renderers={},
                change_page_callback={'url': 'set_current_form_page',
                                      'item': clazz.__tablename__,
                                      'itemid': id},
                request=request, csrf_token=request.session.get_csrf_token())

    if request.POST:
        mapping = {'item': item}
        # Do extra validation which is not handled by formbar.
        # Is the provided old password correct?
        validator = Validator('oldpassword',
                              _('The given password is not correct'),
                              check_password)
        pw_len_validator = Validator('password',
                                     _('Password must be at least 12 '
                                       'characters long.'),
                                     password_minlength_validator)
        pw_nonchar_validator = Validator('password',
                                         _('Password must contain at least 2 '
                                           'non-letters.'),
                                         password_nonletter_validator)

        form.add_validator(validator)
        form.add_validator(pw_len_validator)
        form.add_validator(pw_nonchar_validator)
        if form.validate(request.params):
            form.save()
            # Actually save the password. This is not done in the form
            # as the password needs to be encrypted.
            encrypt_password_callback(request, item)
            msg = _('Changed password for "${item}" successfull.',
                    mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'success')
            route_name = get_action_routename(item, 'changepassword')
            url = request.route_path(route_name, id=item.id)
            # Invalidate cache
            invalidate_cache()
            return HTTPFound(location=url)
        else:
            msg = _('Error on changing the password for '
                    '"${item}".', mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'error')

    rvalue['clazz'] = clazz
    rvalue['item'] = item
    rvalue['form'] = form.render(page=get_current_form_page(clazz, request))
    return rvalue
Beispiel #12
0
    def get_value(self, name, form_id="read", expand=False):
        """Return the value of the given attribute of the item. Unlike
        accessing the value directly this function this function
        optionally supports the expansion of the value before
        returning it. On default no expansion is done.

        Expansion is relevant for values which are saved as integer
        values in the database but have another literal meaning. This is
        typically true for values in selection lists. E.g the literal
        values for 'Yes' and 'No' are saves as value '1' and '0' in the
        database. To expand the value the method will try to get the
        literal value from the value in the database by looking in the
        form identified by the `form_id` attribute.

        :name: Name of the attribute with the value
        :form_id: ID of the form which will be used for expansion
        :expand: Expand the value before returning it
        :returns: Value of the named attribute
        """

        try:
            raw_value = getattr(self, name)
        except:
            # This error is only acceptable for blobforms as attributes
            # can be added and removed by the user on the fly. So there
            # is a good chance that older items do not have this attribute.
            if hasattr(self, 'id'):
                log.error("Attribute '%s' not found in '%s'; id:%s"
                          % (name, repr(self), self.id))
            else:
                log.error("Attribute '%s' not found in '%s'"
                          % (name, repr(self)))
            raw_value = None
        if expand:
            # In case the fieldname is dotted and refers to values in
            # related items then we need some special logic.
            elements = name.split(".")
            if len(elements) == 2:
                obj = getattr(self, elements[0])
                name = elements[1]
            elif len(elements) > 2:
                obj = getattr(self, ".".join(elements[0:-1]))
                name = elements[-1]
            else:
                obj = self

            # Expanding the value means to get the "literal" value for the
            # given value from the form.
            form_config = get_form_config(obj, form_id)
            try:
                field_config = form_config.get_field(name)
                options = []
                for option in field_config.options:
                    # Handle "list" values "{"",1,2}"
                    if str(raw_value).startswith("{") and str(raw_value).endswith("}"):
                        for value in raw_value.strip("}").strip("{").split(","):
                            if str(value) == str(option[1]):
                                options.append(option[0])
                    elif str(raw_value) == str(option[1]):
                        options.append(option[0])
                        break
                # If we can not match a value we return the raw value.
                # This can also happen if the user tries to expand value
                # which do not have options.
                if len(options) > 0:
                    return ", ".join(options)
                return raw_value
            except KeyError:
                # If the field/value which should to be expanded is not
                # included in the form the form library will raise a
                # KeyError exception. However this is not a big deal as
                # we still have the raw value and only the expandation
                # fails. So silently ignore this one. The exception is
                # already logged in the form library.
                pass
        return raw_value
Beispiel #13
0
    def get_value(self, name, form_id="read", expand=False, strict=True):
        """Return the value of the given attribute of the item. Unlike
        accessing the value directly this function this function
        optionally supports the expansion of the value before
        returning it. On default no expansion is done.

        Expansion is relevant for values which are saved as integer
        values in the database but have another literal meaning. This is
        typically true for values in selection lists. E.g the literal
        values for 'Yes' and 'No' are saves as value '1' and '0' in the
        database. To expand the value the method will try to get the
        literal value from the value in the database by looking in the
        form identified by the `form_id` attribute.

        Strict mode means that in case the given attribute `name` can
        not be accesses a error log message will be triggered. However
        there are some cases where the attribute can not be accesses for
        some known reasons and therefor the error should not be logged
        but passed silently. As this is highly situation depended you
        can call this method with `stric=False` to prevent logging. Here
        are two examples where you migh want to disable logging:

            * Overviews. In case you want to display related items like
            'country.code' but the item does not have a related country (yet).
            * For blobforms as attributes can be added and removed by
            the user on the fly. So there is a good chance that older
            items do not have this attribute.

        :name: Name of the attribute with the value
        :form_id: ID of the form which will be used for expansion
        :expand: Expand the value before returning it
        :strict: Log error if the value can not be accessed. Defaults to True.
        :returns: Value of the named attribute
        """

        try:
            raw_value = getattr(self, name)
        except AttributeError:
            if not strict:
                pass
            elif hasattr(self, 'id'):
                log.error("Attribute '%s' not found in '%s'; id:%s" %
                          (name, repr(self), self.id))
            else:
                log.error("Attribute '%s' not found in '%s'" %
                          (name, repr(self)))
            raw_value = None
        if expand:
            # In case the fieldname is dotted and refers to values in
            # related items then we need some special logic.
            elements = name.split(".")
            if len(elements) == 2:
                obj = getattr(self, elements[0])
                name = elements[1]
            elif len(elements) > 2:
                obj = getattr(self, ".".join(elements[0:-1]))
                name = elements[-1]
            else:
                obj = self

            # Expanding the value means to get the "literal" value for the
            # given value from the form.
            form_config = get_form_config(obj, form_id)
            try:
                field_config = form_config.get_field(name)
                options = []
                for option in field_config.options:
                    # Handle "list" values "{"",1,2}"
                    if (str(raw_value).startswith("{")
                            and str(raw_value).endswith("}")):
                        for value in (
                                raw_value.strip("}").strip("{").split(",")):
                            if str(value) == str(option[1]):
                                options.append(option[0])
                    elif str(raw_value) == str(option[1]):
                        options.append(option[0])
                        break
                # If we can not match a value we return the raw value.
                # This can also happen if the user tries to expand value
                # which do not have options.
                if len(options) > 0:
                    return ", ".join(options)
                return raw_value
            except KeyError:
                # If the field/value which should to be expanded is not
                # included in the form the form library will raise a
                # KeyError exception. However this is not a big deal as
                # we still have the raw value and only the expandation
                # fails. So silently ignore this one. The exception is
                # already logged in the form library.
                pass
        return raw_value
Beispiel #14
0
def changepassword(request):
    """Method to change the users password by the user. The user user
    musst provide his old and the new pasword. Users are only allowed to
    change their own password."""

    # Check authentification
    # As this view has now security configured it is
    # generally callable by all users. For this reason we first check if
    # the user is authenticated. If the user is not authenticated the
    # raise an 401 (unauthorized) exception.
    if not request.user:
        raise HTTPUnauthorized

    clazz = User
    handle_history(request)
    handle_params(request)
    _ = request.translate
    rvalue = {}
    # Load the item return 400 if the item can not be found.
    id = request.matchdict.get('id')
    factory = clazz.get_item_factory()
    try:
        item = factory.load(id, request.db)
        # Check authorisation
        # User are only allowed to set their own password.
        if item.id != request.user.id:
            raise HTTPForbidden()
    except sa.orm.exc.NoResultFound:
        raise HTTPBadRequest()

    form = Form(get_form_config(item, 'changepassword'),
                item, request.db, translate=_,
                renderers={},
                change_page_callback={'url': 'set_current_form_page',
                                      'item': clazz.__tablename__,
                                      'itemid': id},
                request=request, csrf_token=request.session.get_csrf_token())

    if request.POST:
        mapping = {'item': item}
        # Do extra validation which is not handled by formbar.
        # Is the provided old password correct?
        validator = Validator('oldpassword',
                              _('The given password is not correct'),
                              check_password)
        pw_len_validator = Validator('password',
                                     _('Password must be at least 12 '
                                       'characters long.'),
                                     password_minlength_validator)
        pw_nonchar_validator = Validator('password',
                                         _('Password must contain at least 2 '
                                           'non-letters.'),
                                         password_nonletter_validator)

        form.add_validator(validator)
        form.add_validator(pw_len_validator)
        form.add_validator(pw_nonchar_validator)
        if form.validate(request.params):
            form.save()
            # Actually save the password. This is not done in the form
            # as the password needs to be encrypted.
            encrypt_password_callback(request, item)
            msg = _('Changed password for "${item}" successfull.',
                    mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'success')
            route_name = get_action_routename(item, 'changepassword')
            url = request.route_path(route_name, id=item.id)
            # Invalidate cache
            invalidate_cache()
            return HTTPFound(location=url)
        else:
            msg = _('Error on changing the password for '
                    '"${item}".', mapping=mapping)
            log.info(msg)
            request.session.flash(msg, 'error')

    rvalue['clazz'] = clazz
    rvalue['item'] = item
    rvalue['form'] = form.render(page=get_current_form_page(clazz, request))
    return rvalue