Example #1
0
    def rename_nodes(self):
        """
        Rename nodes view. Renders either a view to change the titles and
        names for multiple nodes or handle the changes and get back to the
        referrer of the request.

        :result: Either a redirect response or a dictionary passed to the
                 template for rendering.
        :rtype: pyramid.httpexceptions.HTTPFound or dict
        """
        if "rename_nodes" in self.request.POST:
            ids = self.request.POST.getall("children-to-rename")
            for id in ids:
                item = DBSession.query(Node).get(id)
                name = self.request.POST[id + "-name"]
                title = self.request.POST[id + "-title"]
                if not name or not title:
                    self.request.session.flash(_(u"Name and title are required."), "error")
                    location = resource_url(self.context, self.request) + "@@rename_nodes"
                    return HTTPFound(location=location)
                else:
                    item.name = title_to_name(name, blacklist=self.context.keys())
                    item.title = title
            self.request.session.flash(_(u"Your changes have been saved."), "success")
            return self.back("@@contents")

        if "cancel" in self.request.POST:
            self.request.session.flash(_(u"No changes made."), "info")
            return self.back("@@contents")

        ids = self._selected_children(add_context=False)
        items = []
        if ids is not None:
            items = DBSession.query(Node).filter(Node.id.in_(ids)).all()
        return {"items": items}
Example #2
0
File: users.py Project: j23d/Kotti
    def __call__(self):
        user_or_group = self.request.params['name']
        principal = get_principals()[user_or_group]

        is_group = user_or_group.startswith("group:")
        principal_type = _(u"Group") if is_group else _(u"User")

        api = template_api(
            self.context, self.request,
            page_title=_(u"Edit ${principal_type} ${title}",
                         mapping=dict(principal_type=principal_type,
                                      title=self.context.title)),
            cp_links=CONTROL_PANEL_LINKS,
            principal=principal)

        form_view = self.GroupManageFormView if is_group \
            else self.UserManageFormView
        form = form_view(principal, self.request)()
        if self.request.is_response(form):
            return form

        return {
            'api': api,
            'form': form['form'],
            }
Example #3
0
def contents_buttons(context, request):
    """
    Build the action buttons for the contents view based on the current
    state and the persmissions of the user.

    :result: List of ActionButtons.
    :rtype: list
    """
    buttons = []
    if get_paste_items(context, request):
        buttons.append(ActionButton('paste', title=_(u'Paste'),
                                    no_children=True))
    if context.children:
        buttons.append(ActionButton('copy', title=_(u'Copy')))
        buttons.append(ActionButton('cut', title=_(u'Cut')))
        buttons.append(ActionButton('rename_nodes', title=_(u'Rename'),
                                    css_class=u'btn btn-warning'))
        buttons.append(ActionButton('delete_nodes', title=_(u'Delete'),
                                    css_class=u'btn btn-danger'))
        if get_workflow(context) is not None:
            buttons.append(ActionButton('change_state',
                                        title=_(u'Change State')))
        buttons.append(ActionButton('up', title=_(u'Move up')))
        buttons.append(ActionButton('down', title=_(u'Move down')))
        buttons.append(ActionButton('show', title=_(u'Show')))
        buttons.append(ActionButton('hide', title=_(u'Hide')))
    return [button for button in buttons if button.permitted(context, request)]
Example #4
0
    def paste_nodes(self):
        """ Paste nodes view.  Paste formerly copied or cutted nodes into the
        current context.  Note that a cutted node can not be pasted into itself.

        :result: Redirect response to the referrer of the request.
        :rtype: pyramid.httpexceptions.HTTPFound
        """
        ids, action = self.request.session["kotti.paste"]
        for count, id in enumerate(ids):
            item = DBSession.query(Node).get(id)
            if item is not None:
                if action == "cut":
                    if not self.request.has_permission("edit", item):
                        raise Forbidden()
                    item.__parent__.children.remove(item)
                    item.name = title_to_name(item.name, blacklist=self.context.keys())
                    self.context[item.name] = item
                    if count is len(ids) - 1:
                        del self.request.session["kotti.paste"]
                elif action == "copy":
                    copy = item.copy()
                    name = copy.name
                    if not name:  # for root
                        name = copy.title
                    name = title_to_name(name, blacklist=self.context.keys())
                    copy.name = name
                    self.context[name] = copy
                self.flash(
                    _("${title} was pasted.", mapping=dict(title=item.title)), "success"
                )
            else:
                self.flash(_("Could not paste node. It no longer exists."), "error")
        DBSession.flush()
        if not self.request.is_xhr:
            return self.back()
Example #5
0
    def delete_nodes(self):
        """
        Delete nodes view. Renders either a view to delete multiple nodes or
        delete the selected nodes and get back to the referrer of the request.

        :result: Either a redirect response or a dictionary passed to the
                 template for rendering.
        :rtype: pyramid.httpexceptions.HTTPFound or dict
        """
        if 'delete_nodes' in self.request.POST:
            ids = self.request.POST.getall('children-to-delete')
            if not ids:
                self.flash(_(u"Nothing was deleted."), 'info')
            for id in ids:
                item = DBSession.query(Node).get(id)
                self.flash(_(u'${title} was deleted.',
                             mapping=dict(title=item.title)), 'success')
                del self.context[item.name]
            return self.back('@@contents')

        if 'cancel' in self.request.POST:
            self.flash(_(u'No changes were made.'), 'info')
            return self.back('@@contents')

        ids = self._selected_children(add_context=False)
        items = []
        if ids is not None:
            items = DBSession.query(Node).filter(Node.id.in_(ids)).\
                order_by(Node.position).all()
        return {'items': items,
                'states': _states(self.context, self.request)}
Example #6
0
def set_password(context, request,
                 success_msg=_(u"You've reset your password successfully.")):
    form = Form(SetPasswordSchema(), buttons=(Button('submit', _(u'Submit')),))
    rendered_form = None

    if 'submit' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure, e:
            request.session.flash(_(u"There was an error."), 'error')
            rendered_form = e.render()
        else:
            token = appstruct['token']
            email = appstruct['email']
            user = _find_user(email)
            if (user is not None and
                validate_token(user, token) and
                token == user.confirm_token):
                password = appstruct['password']
                user.password = get_principals().hash_password(password)
                user.confirm_token = None
                headers = remember(request, user.name)
                location = (appstruct['continue_to'] or
                            resource_url(context, request))
                request.session.flash(success_msg, 'success')
                return HTTPFound(location=location, headers=headers)
            else:
                request.session.flash(
                    _(u"Your password reset token may have expired."), 'error')
Example #7
0
def login(context, request):
    principals = get_principals()

    came_from = request.params.get("came_from", request.resource_url(context))
    login, password = u"", u""

    if "submit" in request.POST:
        login = request.params["login"].lower()
        password = request.params["password"]
        user = _find_user(login)

        if user is not None and user.active and principals.validate_password(password, user.password):
            headers = remember(request, login)
            request.session.flash(_(u"Welcome, ${user}!", mapping=dict(user=user.title or user.name)), "success")
            user.last_login_date = datetime.now()
            return HTTPFound(location=came_from, headers=headers)
        request.session.flash(_(u"Login failed."), "error")

    if "reset-password" in request.POST:
        login = request.params["login"]
        user = _find_user(login)
        if user is not None:
            send_set_password(user, request, templates="reset-password")
            request.session.flash(
                _(u"You should receive an email with a link to reset your " u"password momentarily."), "success"
            )
        else:
            request.session.flash(_(u"That username or email is not known to us."), "error")

    return {"url": request.application_url + "/@@login", "came_from": came_from, "login": login, "password": password}
Example #8
0
def register(context, request):
    schema = RegisterSchema().bind(request=request)
    form = Form(schema, buttons=(Button('register', _(u'Register')),))
    rendered_form = None

    if 'register' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure, e:
            request.session.flash(_(u"There was an error."), 'error')
            rendered_form = e.render()
        else:
            settings = get_settings()

            appstruct['groups'] = u''
            appstruct['roles'] = u''

            register_groups = settings['kotti.register.group']
            if register_groups:
                appstruct['groups'] = [register_groups]

            register_roles = settings['kotti.register.role']
            if register_roles:
                appstruct['roles'] = set(['role:' + register_roles])

            appstruct['send_email'] = True
            form = UserAddFormView(context, request)
            form.add_user_success(appstruct)
            success_msg = _(
                'Congratulations! You are successfully registered. '
                'You should receive an email with a link to set your '
                'password momentarily.'
                )
            request.session.flash(success_msg, 'success')
            return HTTPFound(location=request.application_url)
Example #9
0
    def set_visibility(self, show):
        """ Do the real work to set the visibility of nodes in the menu. Called
        by the show and the hide view.

        :result: Redirect response to the referrer of the request.
        :rtype: pyramid.httpexceptions.HTTPFound
        """
        ids = self._selected_children()
        for id in ids:
            child = DBSession.query(Node).get(id)
            if child.in_navigation != show:
                child.in_navigation = show
                mapping = dict(title=child.title)
                if show:
                    mg = _(
                        "${title} is now visible in the navigation.", mapping=mapping
                    )
                else:
                    mg = _(
                        "${title} is no longer visible in the navigation.",
                        mapping=mapping,
                    )
                self.flash(mg, "success")
        if not self.request.is_xhr:
            return self.back()
Example #10
0
 def first_heading(self):
     context_title = getattr(self.request.context, "title", None)
     type_title = self.item_type or self.add.type_info.title
     if context_title:
         return _(u"Add ${type} to ${title}.", mapping=dict(type=translate(type_title), title=context_title))
     else:
         return _(u"Add ${type}.", mapping=dict(type=translate(type_title)))
Example #11
0
def contents_buttons(context, request):
    """ Build the action buttons for the contents view based on the current
    state and the persmissions of the user.

    :result: List of ActionButtons.
    :rtype: list
    """
    buttons = []
    if get_paste_items(context, request):
        buttons.append(ActionButton("paste", title=_("Paste"), no_children=True))
    if context.children:
        buttons.append(ActionButton("copy", title=_("Copy")))
        buttons.append(ActionButton("cut", title=_("Cut")))
        buttons.append(
            ActionButton("rename_nodes", title=_("Rename"), css_class="btn btn-warning")
        )
        buttons.append(
            ActionButton("delete_nodes", title=_("Delete"), css_class="btn btn-danger")
        )
        if get_workflow(context) is not None:
            buttons.append(ActionButton("change_state", title=_("Change State")))
        buttons.append(ActionButton("up", title=_("Move up")))
        buttons.append(ActionButton("down", title=_("Move down")))
        buttons.append(ActionButton("show", title=_("Show")))
        buttons.append(ActionButton("hide", title=_("Hide")))
    return [button for button in buttons if button.permitted(context, request)]
Example #12
0
    def set_default_view(self):
        """
        :summary: Set the node's default view and redirect to it.
        :result: Redirect to the context URL.
        :rtype: pyramid.httpexceptions.HTTPFound
        """

        if 'view_name' in self.request.GET:

            view_name = self.request.GET['view_name']

            if view_name == "default":
                self.context.default_view = None
                self.request.session.flash(
                    _("Default view has been reset to default."),
                    'success'
                )
            else:
                if self._is_valid_view(view_name):
                    self.context.default_view = view_name
                    self.request.session.flash(
                        _("Default view has been set."),
                        'success'
                    )
                else:
                    self.request.session.flash(
                        _("Default view could not be set."),
                        'error'
                    )

        return HTTPFound(
            location=self.request.resource_url(self.context)
        )
Example #13
0
    def paste_nodes(self):
        """
        Paste nodes view. Paste formerly copied or cutted nodes into the
        current context. Note that a cutted node can not be pasted into itself.

        :result: Redirect response to the referrer of the request.
        :rtype: pyramid.httpexceptions.HTTPFound
        """
        ids, action = self.request.session['kotti.paste']
        for count, id in enumerate(ids):
            item = DBSession.query(Node).get(id)
            if item is not None:
                if action == 'cut':
                    if not has_permission('edit', item, self.request):
                        raise Forbidden()
                    item.__parent__.children.remove(item)
                    self.context.children.append(item)
                    if count is len(ids) - 1:
                        del self.request.session['kotti.paste']
                elif action == 'copy':
                    copy = item.copy()
                    name = copy.name
                    if not name:  # for root
                        name = copy.title
                    name = title_to_name(name, blacklist=self.context.keys())
                    copy.name = name
                    self.context.children.append(copy)
                self.flash(_(u'${title} was pasted.',
                             mapping=dict(title=item.title)), 'success')
            else:
                self.flash(_(u'Could not paste node. It no longer exists.'),
                           'error')
        if not self.request.is_xhr:
            return self.back()
Example #14
0
def order_node(context, request):
    P = request.POST

    if 'order-up' in P or 'order-down' in P:
        up, down = P.get('order-up'), P.get('order-down')
        child = DBSession.query(Node).get(int(down or up))
        if up is not None:
            mod = -1
        else:  # pragma: no cover
            mod = 1
        index = context.children.index(child)
        context.children.pop(index)
        context.children.insert(index + mod, child)
        request.session.flash(_(u'${title} moved.',
                                mapping=dict(title=child.title)), 'success')
        if not request.is_xhr:
            return HTTPFound(location=request.url)

    elif 'toggle-visibility' in P:
        child = DBSession.query(Node).get(int(P['toggle-visibility']))
        child.in_navigation ^= True
        mapping = dict(title=child.title)
        if child.in_navigation:
            msg = _(u'${title} is now visible in the navigation.',
                    mapping=mapping)
        else:
            msg = _(u'${title} is no longer visible in the navigation.',
                    mapping=mapping)
        request.session.flash(msg, 'success')
        if not request.is_xhr:
            return HTTPFound(location=request.url)

    return {}
Example #15
0
    def delete_nodes(self):
        """
        Delete nodes view. Renders either a view to delete multiple nodes or
        delete the selected nodes and get back to the referrer of the request.

        :result: Either a redirect response or a dictionary passed to the
                 template for rendering.
        :rtype: pyramid.httpexceptions.HTTPFound or dict
        """
        if "delete_nodes" in self.request.POST:
            ids = self.request.POST.getall("children-to-delete")
            if not ids:
                self.request.session.flash(_(u"Nothing deleted."), "info")
            for id in ids:
                item = DBSession.query(Node).get(id)
                self.request.session.flash(_(u"${title} deleted.", mapping=dict(title=item.title)), "success")
                del self.context[item.name]
            return self.back("@@contents")

        if "cancel" in self.request.POST:
            self.request.session.flash(_(u"No changes made."), "info")
            return self.back("@@contents")

        ids = self._selected_children(add_context=False)
        items = []
        if ids is not None:
            items = DBSession.query(Node).filter(Node.id.in_(ids)).order_by(Node.position).all()
        return {"items": items, "states": _states(self.context, self.request)}
Example #16
0
def paste_node(context, request):
    session = DBSession()
    id, action = request.session['kotti.paste']
    item = session.query(Node).get(id)
    if item is not None:
        if action == 'cut':
            if not has_permission('edit', item, request):
                raise Forbidden()
            item.__parent__.children.remove(item)
            context.children.append(item)
            del request.session['kotti.paste']
        elif action == 'copy':
            copy = item.copy()
            name = copy.name
            if not name:  # for root
                name = copy.title
            name = title_to_name(name, blacklist=context.keys())
            copy.name = name
            context.children.append(copy)
        request.session.flash(_(u'${title} pasted.',
                                mapping=dict(title=item.title)), 'success')
    else:
        request.session.flash(_(u'Could not paste node. It does not exist anymore.'), 'error')
    if not request.is_xhr:
        location = resource_url(context, request)
        return HTTPFound(location=location)
Example #17
0
File: util.py Project: dnouri/Kotti
 def first_heading(self):
     context_title = getattr(self.request.context, 'title', None)
     type_title = self.item_type or self.add.type_info.title
     if context_title:
         return _(
             u'Add ${type} to <em>${title}</em>',
             mapping=dict(type=translate(type_title), title=context_title))
     else:
         return _(u'Add ${type}', mapping=dict(type=translate(type_title)))
Example #18
0
def includeme_static_views(config):
    try:
        import openid_selector
        config.add_static_view(name='js',     path='openid_selector:/js')
        config.add_static_view(name='css',    path='openid_selector:/css')
        config.add_static_view(name='images', path='openid_selector:/images')
        log.info(_(u'openid_selector loaded successfully'))
    except Exception as e:
        log.exception(_(u'Failure loading openid-selector.\nStacktrace follows:\n{}').format(e))
        raise e
Example #19
0
File: form.py Project: gjo/Kotti
 def first_heading(self):
     from kotti.views.util import translate  # prevent circular import
     context_title = getattr(self.request.context, 'title', None)
     type_title = self.item_type or self.add.type_info.title
     if context_title:
         return _(u'Add ${type} to <em>${title}</em>.',
                  mapping=dict(type=translate(type_title),
                               title=context_title))
     else:
         return _(u'Add ${type}.', mapping=dict(type=translate(type_title)))
Example #20
0
def login(context, request):
    """
    Login view.  Renders either the login or password forgot form templates or
    handles their form submission and redirects to came_from on success.

    :result: Either a redirect response or a dictionary passed to the template
             for rendering
    :rtype: pyramid.httpexceptions.HTTPFound or dict
    """

    principals = get_principals()

    came_from = request.params.get(
        'came_from', request.resource_url(context))
    login, password = u'', u''

    if 'submit' in request.POST:
        login = request.params['login'].lower()
        password = request.params['password']
        user = _find_user(login)

        if (user is not None and user.active and
                principals.validate_password(password, user.password)):
            headers = remember(request, user.name)
            request.session.flash(
                _(u"Welcome, ${user}!",
                  mapping=dict(user=user.title or user.name)), 'success')
            user.last_login_date = datetime.now()
            return HTTPFound(location=came_from, headers=headers)
        request.session.flash(_(u"Login failed."), 'error')

    if 'reset-password' in request.POST:
        login = request.params['login']
        user = _find_user(login)
        if user is not None and user.active:
            email_set_password(
                user, request,
                template_name='kotti:templates/email-reset-password.pt')
            request.session.flash(_(
                u"You should be receiving an email with a link to reset your "
                u"password. Doing so will activate your account."), 'success')
        else:
            request.session.flash(
                _(u"That username or email is not known by this system."),
                'error')
        headers = remember(request, user.name)
        return HTTPFound(location=came_from, headers=headers)

    return {
        'url': request.application_url + '/@@login',
        'came_from': came_from,
        'login': login,
        'password': password,
        'register': asbool(get_settings()['kotti.register']),
        }
Example #21
0
def user_schema(base=PrincipalFull()):
    schema = principal_schema(base)
    has_password = True
    try:
        schema['password']
    except KeyError:
        has_password = False
    if has_password:
        schema['password'].description = _(
            u"Leave this empty and tick the 'Send password registration' box below to have the user set their own password.")
    schema['title'].title = _(u"Full name")
    return schema
Example #22
0
    def change_state(self):
        """
        Change state view. Renders either a view to handle workflow changes
        for multiple nodes or handle the selected workflow changes and get
        back to the referrer of the request.

        :result: Either a redirect response or a dictionary passed to the
                 template for rendering.
        :rtype: pyramid.httpexceptions.HTTPFound or dict
        """
        if 'change_state' in self.request.POST:
            ids = self.request.POST.getall('children-to-change-state')
            to_state = self.request.POST.get('to-state', u'no-change')
            include_children = self.request.POST.get('include-children', None)
            if to_state != u'no-change':
                items = DBSession.query(Node).filter(Node.id.in_(ids)).all()
                for item in items:
                    wf = get_workflow(item)
                    if wf is not None:
                        wf.transition_to_state(item, self.request, to_state)
                    if include_children:
                        childs = self._all_children(item,
                                                    permission='state_change')
                        for child in childs:
                            wf = get_workflow(child)
                            if wf is not None:
                                wf.transition_to_state(child,
                                                       self.request,
                                                       to_state, )
                self.request.session.flash(
                    _(u'Your changes have been saved.'), 'success')
            else:
                self.request.session.flash(_(u'No changes made.'), 'info')
            return self.back('@@contents')

        if 'cancel' in self.request.POST:
            self.request.session.flash(_(u'No changes made.'), 'info')
            return self.back('@@contents')

        ids = self._selected_children(add_context=False)
        items = transitions = []
        if ids is not None:
            wf = get_workflow(self.context)
            if wf is not None:
                items = DBSession.query(Node).filter(Node.id.in_(ids)).all()
                for item in items:
                        trans_info = wf.get_transitions(item, self.request)
                        for tran_info in trans_info:
                            if tran_info not in transitions:
                                transitions.append(tran_info)
        return {'items': items,
                'states': _states(self.context, self.request),
                'transitions': transitions, }
Example #23
0
    def paste_nodes(self):
        """
        Paste nodes view. Paste formerly copied or cutted nodes into the
        current context. Note that a cutted node can not be pasted into itself.

        :result: Redirect response to the referrer of the request.
        :rtype: pyramid.httpexceptions.HTTPFound

        kotti_multilingual override:
        If you paste objects after a cut action we want to
        clear all translations (prevent edge case problems)

        """

        def unlink_translation(content):
            content_id = content.id
            DBSession.query(Translation).filter(
                or_(Translation.target_id == content_id, Translation.source_id == content_id)
            ).delete()

        ids, action = self.request.session["kotti.paste"]
        for count, id in enumerate(ids):
            item = DBSession.query(Node).get(id)
            if item is not None:
                if action == "cut":
                    if not has_permission("edit", item, self.request):
                        raise Forbidden()

                    # unlink translations for each child
                    children = self._all_children(item, permission="edit")
                    unlink_translation(item)
                    for child in children:
                        unlink_translation(child)

                    item.__parent__.children.remove(item)
                    item.name = title_to_name(item.name, blacklist=self.context.keys())
                    self.context.children.append(item)
                    if count is len(ids) - 1:
                        del self.request.session["kotti.paste"]
                elif action == "copy":
                    copy = item.copy()
                    name = copy.name
                    if not name:  # for root
                        name = copy.title
                    name = title_to_name(name, blacklist=self.context.keys())
                    copy.name = name
                    self.context.children.append(copy)
                self.flash(_(u"${title} was pasted.", mapping=dict(title=item.title)), "success")
            else:
                self.flash(_(u"Could not paste node. It no longer exists."), "error")
        if not self.request.is_xhr:
            return self.back()
Example #24
0
def rename_node(context, request):
    if 'rename' in request.POST:
        name = request.POST['name']
        title = request.POST['title']
        if not name or not title:
            request.session.flash(_(u'Name and title are required.'), 'error')
        else:
            context.name = name.replace('/', '')
            context.title = title
            request.session.flash(_(u'Item renamed'), 'success')
            location = resource_url(context, request)
            return HTTPFound(location=location)
    return {}
Example #25
0
File: login.py Project: Kotti/Kotti
def set_password(context, request, success_msg=_(u"You have reset your password.")):
    """ Set password view.  Displays the set password form and handles its form
    submission.

    :param context: Current context
    :type context: :class:`kotti.resources.Content`

    :param request: Current request
    :type request: :class:`kotti.request.Request`

    :param success_msg: Message to display on successful submission handling
    :type success_msg: str or TranslationString

    :result: Redirect response or dictionary passed to the template for
             rendering.
    :rtype: pyramid.httpexceptions.HTTPFound or dict
    """

    form = Form(SetPasswordSchema(), buttons=(Button("submit", _(u"Set password")),))
    rendered_form = None

    if "submit" in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure as e:
            rendered_form = e.render()
        else:
            token = appstruct["token"]
            email = appstruct["email"]
            user = _find_user(email)
            if user is not None and validate_token(user, token) and token == user.confirm_token and user.active:
                password = appstruct["password"]
                user.password = get_principals().hash_password(password)
                user.confirm_token = None
                headers = remember(request, user.name)
                user.last_login_date = datetime.now()

                location = appstruct["continue_to"] or resource_url(context, request)
                request.session.flash(success_msg, "success")
                return HTTPFound(location=location, headers=headers)
            else:
                request.session.flash(_(u"Your password reset token may have expired."), "error")

    if rendered_form is None:
        rendered_form = form.render(request.params)

    api = template_api(
        context, request, page_title=_(u"Reset your password - ${title}.", mapping=dict(title=context.title))
    )

    return {"api": api, "form": rendered_form}
Example #26
0
def register(context, request):
    schema = RegisterSchema().bind(request=request)
    form = Form(schema, buttons=(Button('register', _('Register')),))
    rendered_form = None

    if 'register' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure as e:
            request.session.flash(_("There was an error."), 'error')
            rendered_form = e.render()
        else:
            settings = get_settings()

            appstruct['groups'] = ''
            appstruct['roles'] = ''

            register_groups = settings['kotti.register.group']
            if register_groups:
                appstruct['groups'] = [register_groups]

            register_roles = settings['kotti.register.role']
            if register_roles:
                appstruct['roles'] = {'role:' + register_roles}

            appstruct['send_email'] = True
            form = UserAddFormView(context, request)
            form.add_user_success(appstruct)
            success_msg = _(
                'Congratulations! You are successfully registered. '
                'You should be receiving an email with a link to set your '
                'password. Doing so will activate your account.'
                )
            request.session.flash(success_msg, 'success')
            name = appstruct['name']
            notify(UserSelfRegistered(get_principals()[name], request))
            return HTTPFound(location=request.application_url)

    if rendered_form is None:
        rendered_form = form.render(request.params)

    api = template_api(
        context, request,
        page_title=_("Register - ${title}",
                     mapping=dict(title=context.title)),
    )

    return {
        'api': api,
        'form': rendered_form,
        }
Example #27
0
    def change_state(self):
        """ Change state view. Renders either a view to handle workflow changes
        for multiple nodes or handle the selected workflow changes and get
        back to the referrer of the request.

        :result: Either a redirect response or a dictionary passed to the
                 template for rendering.
        :rtype: pyramid.httpexceptions.HTTPFound or dict
        """
        if "change_state" in self.request.POST:
            ids = self.request.POST.getall("children-to-change-state")
            to_state = self.request.POST.get("to-state", "no-change")
            include_children = self.request.POST.get("include-children")
            if to_state != "no-change":
                items = DBSession.query(Node).filter(Node.id.in_(ids)).all()
                for item in items:
                    wf = get_workflow(item)
                    if wf is not None:
                        wf.transition_to_state(item, self.request, to_state)
                    if include_children:
                        childs = self._all_children(item, permission="state_change")
                        for child in childs:
                            wf = get_workflow(child)
                            if wf is not None:
                                wf.transition_to_state(child, self.request, to_state)
                self.flash(_("Your changes have been saved."), "success")
            else:
                self.flash(_("No changes were made."), "info")
            return self.back("@@contents")

        if "cancel" in self.request.POST:
            self.flash(_("No changes were made."), "info")
            return self.back("@@contents")

        ids = self._selected_children(add_context=False)
        items = transitions = []
        if ids is not None:
            wf = get_workflow(self.context)
            if wf is not None:
                items = DBSession.query(Node).filter(Node.id.in_(ids)).all()
                for item in items:
                    trans_info = wf.get_transitions(item, self.request)
                    for tran_info in trans_info:
                        if tran_info not in transitions:
                            transitions.append(tran_info)
        return {
            "items": items,
            "states": _states(self.context, self.request),
            "transitions": transitions,
        }
Example #28
0
def login_verify(context, request):
    import pdb; pdb.set_trace()
    ######################################################################################
    #                                                                                    #
    # Let's clarify the difference between "provider" and "method" in this function:     #
    #                                                                                    #
    # * Conceptually, [authentication] methods can be understood pretty much like        #
    #   protocols or transports. So, methods would be for example: OpenID, OAuth2 and    #
    #   other authentication protocols supported by Velruse.                             #
    #                                                                                    #
    # * A provider is simply an entity, like Google, Yahoo, Twitter, Facebook, Verisign, #
    #   Github, Launchpad and hundreds of other entities which employ authentication     #
    #   methods like OpenID, OAuth2 and others supported by Velruse.                     #
    #                                                                                    #
    # * In particular, certain entities implement their own authentication methods or    #
    #   they eventually offer several authentication methods. For this reason, there are #
    #   specific methods for "yahoo", "tweeter", "google_hybrid", "google_oauth2", etc.  #
    #                                                                                    #
    ######################################################################################

    log.debug( sys._getframe().f_code.co_name )

    ####################################################################################
    #TODO: should pass "came_from" to view "logged_in" so that we can redirect
    #      to the previous page. Sorry... I failed to make it work :(
    #-- came_from = request.params.get('came_from', request.resource_url(context))
    ####################################################################################

    provider = request.params['provider']
    method = request.params['method']

    settings = request.registry.settings
    if not method in find_providers(settings):
        raise HTTPNotFound('Provider/method {}/{} is not configured'.format(provider, method)).exception

    payload = dict(request.params)
    payload['format'] = 'json'
    if 'yahoo'  == method: payload['oauth'] = 'true'
    if 'openid' == method: payload['use_popup'] = 'false'
    del payload['provider']
    del payload['method']

    try:
        url = login_url(request, method)
        response = request.invoke_subrequest( Request.blank(url, POST=payload) )
        return response
    except Exception as e:
        message = _(u'Provider/method: {}/{} :: {}.').format(provider, method, e.message)
        log.exception(_(u'{}\nStacktrace follows:\n{}').format(message, e))
        raise HTTPNotFound(message).exception
Example #29
0
def logged_in(context, request):
    """Velruse redirects to /logged_in when authentication succeeds"""

    log.debug( sys._getframe().f_code.co_name )

    ####################################################################################
    #TODO: should receive "came_from" somehow so that we can redirect to the previous
    #      page. Sorry... I failed to make it work :(
    #-- came_from = request.params.get('came_from', request.resource_url(context))
    ####################################################################################

    token = request.params['token']
    storage = request.registry.velruse_store
    json = None
    try:
        user = request.user
        json = storage.retrieve(token)
        obj = AfterLoggedInObject(json, user, request)
        after_kotti_velruse_loggedin(obj)
        principal = obj.principal
        identities = obj.identities
        if principal is None or identities is None:
            raise RuntimeError(_(u'Authentication events not being handled properly'))

        log.debug(_('User authenticated: id={}, name="{}", email="{}"').format(
            principal.id, principal.name, principal.email))
        headers = remember(request, principal.name)

        ###########################################################################################
        #TODO: at this point, we should actually redirect to the address which should be passed on
        #      variable "came_from". Because I failed to pass this variable around, I at least
        #      return to page @@prefs when user is not None.
        ###########################################################################################
        redirect = request.resource_url(context)
        if user is None:
            request.session.flash(
                _(u"Welcome, ${user}!", mapping=dict(user=principal.title or principal.name)), 'success')
        else:
            redirect += "@@prefs"

        log.debug('redirect to {} with headers = {}'.format(redirect, headers))
        return HTTPFound(location=redirect, headers=headers)
    except Exception as e:
        if json:
            log.exception(_(u'JSON received from provider: {}\nStacktrace follows:\n{}').format(json, e))
        else:
            log.exception(_("No JSON found in storage for token {}.\nStacktrace follows:\n{}").format(token, e))

        raise HTTPNotFound(e.message).exception
Example #30
0
def login(context, request):
    """
    Login view.  Renders either the login or password forgot form templates or
    handles their form submission and redirects to came_from on success.

    :result: Either a redirect response or a dictionary passed to the template
             for rendering
    :rtype: pyramid.httpexceptions.HTTPFound or dict
    """

    principals = get_principals()

    came_from = request.params.get("came_from", request.resource_url(context))
    login, password = u"", u""

    if "submit" in request.POST:
        login = request.params["login"].lower()
        password = request.params["password"]
        user = _find_user(login)

        if user is not None and user.active and principals.validate_password(password, user.password):
            headers = remember(request, user.name)
            request.session.flash(_(u"Welcome, ${user}!", mapping=dict(user=user.title or user.name)), "success")
            user.last_login_date = datetime.now()
            return HTTPFound(location=came_from, headers=headers)
        request.session.flash(_(u"Login failed."), "error")

    if "reset-password" in request.POST:
        login = request.params["login"]
        user = _find_user(login)
        if user is not None and user.active:
            email_set_password(user, request, template_name="kotti:templates/email-reset-password.pt")
            request.session.flash(
                _(
                    u"You should be receiving an email with a link to reset your "
                    u"password. Doing so will activate your account."
                ),
                "success",
            )
        else:
            request.session.flash(_(u"That username or email is not known by this system."), "error")

    return {
        "url": request.application_url + "/@@login",
        "came_from": came_from,
        "login": login,
        "password": password,
        "register": asbool(get_settings()["kotti.register"]),
    }
Example #31
0
          get_principals().search(name=u'bob', foo=u'bar')
        """

    def hash_password(self, password):
        """Return a hash of the given password.

        This is what's stored in the database as 'principal.password'.
        """

    def validate_password(self, clear, hashed):
        """Returns True if the clear text password matches the hash.
        """


ROLES = {
    u'role:viewer': Principal(u'role:viewer', title=_(u'Viewer')),
    u'role:editor': Principal(u'role:editor', title=_(u'Editor')),
    u'role:owner': Principal(u'role:owner', title=_(u'Owner')),
    u'role:admin': Principal(u'role:admin', title=_(u'Admin')),
}
_DEFAULT_ROLES = ROLES.copy()

# These roles are visible in the sharing tab
SHARING_ROLES = [u'role:viewer', u'role:editor', u'role:owner']
USER_MANAGEMENT_ROLES = SHARING_ROLES + ['role:admin']
_DEFAULT_SHARING_ROLES = SHARING_ROLES[:]
_DEFAULT_USER_MANAGEMENT_ROLES = USER_MANAGEMENT_ROLES[:]

# This is the ACL that gets set on the site root on creation.
SITE_ACL = [
    ['Allow', 'system.Everyone', ['view']],
Example #32
0
 def raise_invalid_email(node, value):
     raise colander.Invalid(
         node, _(u"A user with that email already exists."))
Example #33
0
def group_validator(node, value):
    principals = get_principals()
    if principals.get('group:' + value) is None:
        raise colander.Invalid(node, _(u"No such group: ${group}",
                                       mapping=dict(group=value)))
Example #34
0
def name_new_validator(node, value):
    if get_principals().get(value.lower()) is not None:
        raise colander.Invalid(
            node, _(u"A user with that name already exists."))
Example #35
0
 def cancel_success(self, appstruct):
     self.request.session.flash(_(u'No changes were made.'), 'info')
     location = "%s/@@setup-users" % self.request.application_url
     return HTTPFound(location=location)
Example #36
0
File: login.py Project: Doik/Kotti
def logout(context, request):
    headers = forget(request)
    request.session.flash(_(u"You have been logged out."))
    location = request.params.get('came_from', request.application_url)
    return HTTPFound(location=location, headers=headers)
Example #37
0
 def first_heading(self):
     return _(u'Edit ${title}', mapping=dict(title=self.context.title))
Example #38
0
File: login.py Project: Doik/Kotti
                user.last_login_date = datetime.now()

                location = (appstruct['continue_to'] or
                            resource_url(context, request))
                request.session.flash(success_msg, 'success')
                return HTTPFound(location=location, headers=headers)
            else:
                request.session.flash(
                    _(u"Your password reset token may have expired."), 'error')

    if rendered_form is None:
        rendered_form = form.render(request.params.items())

    api = template_api(
        context, request,
        page_title=_(u"Reset your password - ${title}",
                     mapping=dict(title=context.title)),
        )

    return {
        'api': api,
        'form': rendered_form,
        }


def forbidden_redirect(context, request):
    if authenticated_userid(request):
        location = request.application_url + '/@@forbidden'
    else:
        location = request.application_url + '/@@login?' + urlencode(
            {'came_from': request.url})
    return HTTPFound(location=location)
Example #39
0
def set_password(context,
                 request,
                 success_msg=_(u"You have reset your password.")):
    """ Set password view.  Displays the set password form and handles its form
    submission.

    :param context: Current context
    :type context: :class:`kotti.resources.Content`

    :param request: Current request
    :type request: :class:`kotti.request.Request`

    :param success_msg: Message to display on successful submission handling
    :type success_msg: str or TranslationString

    :result: Redirect response or dictionary passed to the template for
             rendering.
    :rtype: pyramid.httpexceptions.HTTPFound or dict
    """

    form = Form(SetPasswordSchema(),
                buttons=(Button('submit', _(u'Set password')), ))
    rendered_form = None

    if 'submit' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure as e:
            rendered_form = e.render()
        else:
            token = appstruct['token']
            email = appstruct['email']
            user = _find_user(email)
            if (user is not None and validate_token(user, token)
                    and token == user.confirm_token and user.active):
                password = appstruct['password']
                user.password = get_principals().hash_password(password)
                user.confirm_token = None
                headers = remember(request, user.name)
                user.last_login_date = datetime.now()

                location = (appstruct['continue_to']
                            or resource_url(context, request))
                request.session.flash(success_msg, 'success')
                return HTTPFound(location=location, headers=headers)
            else:
                request.session.flash(
                    _(u"Your password reset token may have expired."), 'error')

    if rendered_form is None:
        rendered_form = form.render(request.params)

    api = template_api(
        context,
        request,
        page_title=_(u"Reset your password - ${title}.",
                     mapping=dict(title=context.title)),
    )

    return {
        'api': api,
        'form': rendered_form,
    }