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}
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'], }
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)]
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()
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)}
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')
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}
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)
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()
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)))
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)]
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) )
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()
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 {}
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)}
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)
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)))
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
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)))
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']), }
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
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, }
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()
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 {}
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}
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, }
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, }
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
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
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"]), }
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']],
def raise_invalid_email(node, value): raise colander.Invalid( node, _(u"A user with that email already exists."))
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)))
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."))
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)
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)
def first_heading(self): return _(u'Edit ${title}', mapping=dict(title=self.context.title))
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)
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, }