def edit_profile(self): user = self.request.context if not user: return HTTPNotFound() if self.request.method == 'GET': username = user.username email = user.email appstruct = {'username': username, 'email': email if email else ''} return render_form(self.request, self.form, appstruct) elif self.request.method == 'POST': controls = self.request.POST.items() try: captured = validate_form(controls, self.form) except FormValidationFailure as e: # We pre-populate username return e.result(self.request, username=user.username) email = captured.get('email', None) if email: email_user = self.User.get_by_email(self.request, email) if email_user: if email_user.id != user.id: FlashMessage(self.request, _('That e-mail is already used.'), kind='error') return HTTPFound(location=self.request.url) user.email = email password = captured.get('password') if password: user.password = password FlashMessage(self.request, self.Str.edit_profile_done, kind='success') self.db.add(user) self.request.registry.notify( ProfileUpdatedEvent(self.request, user, captured)) return HTTPFound(location=self.request.url)
def create_user(self): schema = AdminUserSchema() schema = schema.bind(request=self.request) form = HorusForm(schema) if self.request.method == 'GET': if isinstance(self.request.context, RootFactory): return dict(form=form) else: return dict(form=form, appstruct=self.request.context.__json__( self.request)) else: try: controls = self.request.POST.items() captured = form.validate(controls) except deform.ValidationFailure as e: return dict(form=e, errors=e.error.children) if isinstance(self.request.context, RootFactory): user = self.User(username=captured['username'], email=captured['email']) else: user = self.request.context if captured['password']: user.password = captured['password'] self.db.add(user) FlashMessage(self.request, self.Str.admin_create_user_done, 'success') return HTTPFound( location=self.request.route_url('admin_users_index'))
def activate(self): request = self.request schema = request.registry.getUtility(interfaces.IActivateSchema) schema = schema().bind(request=self.request) form = request.registry.getUtility(interfaces.IActivateForm)(schema) appstruct = None result = None try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: result = dict(form=e.render(), errors=e.error.children) else: code = appstruct['code'] activation = self.Activation.get_by_code(request, code) user = None if activation: user = self.User.get_by_activation(request, activation) request.user = user if user: user.password = appstruct['password'] self.db.add(user) self.db.delete(activation) FlashMessage(request, self.Str.authenticated, kind='success') else: form.error = colander.Invalid( form.schema, _('This activation code is not valid.')) result = dict(form=form.render(), errors=[form.error]) return self.respond(result)
def login(self): if self.request.method == 'GET': if self.request.user: return HTTPFound(location=self.login_redirect_view) return render_form(self.request, self.form) elif self.request.method == 'POST': controls = self.request.POST.items() try: captured = validate_form(controls, self.form) except FormValidationFailure as e: return e.result(self.request) username = captured['username'] password = captured['password'] try: user = self.check_credentials(username, password) except AuthenticationFailure as e: FlashMessage(self.request, str(e), kind='error') return render_form(self.request, self.form, captured, errors=[e]) self.request.user = user # Please keep this line, my app needs it return authenticated(self.request, user.id_value)
def logout(self): """Removes the auth cookies and redirects to the view defined in horus.logout_redirect, which defaults to a view named 'index'. """ self.request.session.invalidate() FlashMessage(self.request, self.Str.logout, kind='success') headers = forget(self.request) return HTTPFound(location=self.logout_redirect_view, headers=headers)
def register(self): if self.request.method == 'GET': if self.request.user: return HTTPFound(location=self.after_register_url) return render_form(self.request, self.form) elif self.request.method != 'POST': return # If the request is a POST: controls = self.request.POST.items() try: captured = validate_form(controls, self.form) except FormValidationFailure as e: return e.result(self.request) # With the form validated, we know email and username are unique. del captured['csrf_token'] user = self.persist_user(captured) autologin = asbool(self.settings.get('horus.autologin', False)) if self.require_activation: # SEND EMAIL ACTIVATION create_activation(self.request, user) FlashMessage(self.request, self.Str.activation_check_email, kind='success') elif not autologin: FlashMessage(self.request, self.Str.registration_done, kind='success') self.request.registry.notify( NewRegistrationEvent(self.request, user, None, controls)) if autologin: self.db.flush() # in order to get the id return authenticated(self.request, user.id) else: # not autologin: user must log in just after registering. return HTTPFound(location=self.after_register_url)
def forgot_password(self): req = self.request schema = req.registry.getUtility(IForgotPasswordSchema) schema = schema().bind(request=req) form = req.registry.getUtility(IForgotPasswordForm) form = form(schema) if req.method == 'GET': if req.user: return httpexceptions.HTTPFound( location=self.forgot_password_redirect_view) else: return {'form': form.render()} controls = req.POST.items() try: captured = form.validate(controls) except deform.ValidationFailure as e: return {'form': e.render(), 'errors': e.error.children} user = self.User.get_by_email(req, captured['email']) activation = self.Activation() self.db.add(activation) user.activation = activation mailer = get_mailer(req) username = getattr(user, 'short_name', '') or \ getattr(user, 'full_name', '') or \ getattr(user, 'username', '') or user.email emailtext = ("Hello, {username}!\n\n" "Someone requested resetting your password. If it was " "you, reset your password by using this reset code:\n\n" "{code}\n\n" "Alternatively, you can reset your password by " "clicking on this link:\n\n" "{link}\n\n" "If you don't want to change your password, please " "ignore this email message.\n\n" "Regards,\n" "The Hypothesis Team\n") body = emailtext.format(code=user.activation.code, link=route_url('reset_password', req, code=user.activation.code), username=username) subject = self.Str.reset_password_email_subject message = Message(subject=subject, recipients=[user.email], body=body) mailer.send(message) FlashMessage(self.request, self.Str.reset_password_email_sent, kind='success') return httpexceptions.HTTPFound( location=self.reset_password_redirect_view)
def authenticated(request, userid): """Sets the auth cookies and redirects to the page defined in horus.login_redirect, which defaults to a view named 'index'. """ settings = request.registry.settings headers = remember(request, userid) autologin = asbool(settings.get('horus.autologin', False)) if not autologin: Str = request.registry.getUtility(IUIStrings) FlashMessage(request, Str.authenticated, kind='success') location = get_config_route(request, 'horus.login_redirect') return HTTPFound(location=location, headers=headers)
def respond(self, result): errors = isinstance(result, dict) and result.pop('errors', []) or [] if len(errors): for e in errors: if isinstance(e, colander.Invalid): msgs = e.messages() else: msgs = [str(e)] for m in msgs: FlashMessage(self.request, m, kind='error') return self.failure( _('Your submission is invalid. ' 'Please try again.')) else: return self.success()
def forgot_password(self): req = self.request schema = req.registry.getUtility(IForgotPasswordSchema) schema = schema().bind(request=req) form = req.registry.getUtility(IForgotPasswordForm) form = form(schema) if req.method == 'GET': if req.user: return HTTPFound(location=self.forgot_password_redirect_view) else: return render_form(req, form) # From here on, we know it's a POST. Let's validate the form controls = req.POST.items() try: captured = validate_form(controls, form) except FormValidationFailure as e: return e.result(req) user = self.User.get_by_email(req, captured['email']) activation = self.Activation() self.db.add(activation) user.activation = activation self.db.flush() # initialize activation.code Str = self.Str # TODO: Generate msg in a separate method so subclasses can override mailer = get_mailer(req) username = getattr(user, 'short_name', '') or \ getattr(user, 'full_name', '') or \ getattr(user, 'username', '') or user.email body = Str.reset_password_email_body.format(link=route_url( 'reset_password', req, code=user.activation.code), username=username, domain=req.application_url) subject = Str.reset_password_email_subject message = Message(subject=subject, recipients=[user.email], body=body) mailer.send(message) FlashMessage(self.request, Str.reset_password_email_sent, kind='success') return HTTPFound(location=self.reset_password_redirect_view)
def update_account(request): user = _validate_request(request) form = _form_for_update_account(request) try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure: return {'form': form} # The token is valid and the form validates, so we can go ahead and claim # the account: user.password = appstruct['password'] msg = _('Your account has been successfully claimed.') FlashMessage(request, msg, kind='success') request.registry.notify(LoginEvent(request, user)) return exc.HTTPFound(location=request.route_url('index'))
def reset_password(self): schema = self.request.registry.getUtility(IResetPasswordSchema) schema = schema().bind(request=self.request) form = self.request.registry.getUtility(IResetPasswordForm) form = form(schema) code = self.request.matchdict.get('code', None) activation = self.Activation.get_by_code(self.request, code) if activation: user = self.User.get_by_activation(self.request, activation) if user: if self.request.method == 'GET': appstruct = {'username': user.username} return render_form(self.request, form, appstruct) elif self.request.method == 'POST': controls = self.request.POST.items() try: captured = validate_form(controls, form) except FormValidationFailure as e: return e.result(self.request) password = captured['password'] user.password = password self.db.add(user) self.db.delete(activation) FlashMessage(self.request, self.Str.reset_password_done, kind='success') self.request.registry.notify( PasswordResetEvent(self.request, user, password)) location = self.reset_password_redirect_view return HTTPFound(location=location) return HTTPNotFound()
def activate(self): """Activate a user and set a password given an activation code. This view is different from the activation view in horus because it does not require the user id to be passed. It trusts the activation code and updates the password. """ request = self.request Str = self.Str schema = schemas.ActivationSchema.bind(request=request) form = forms.ActivateForm(schema) appstruct = None try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: return dict(errors=e.error.children) code = appstruct['code'] activation = models.Activation.get_by_code(request, code) user = None if activation: user = self.User.get_by_activation(request, activation) if user is None: return dict(errors=[_('This activation code is not valid.')]) user.password = appstruct['password'] self.db.delete(activation) self.db.add(user) FlashMessage(request, Str.reset_password_done, kind='success') # XXX: Horus should maybe do this for us event = events.RegistrationActivatedEvent(request, user, activation) request.registry.notify(event) return {}
def disable_user(self): request = self.request schema = schemas.EditProfileSchema().bind(request=request) form = deform.Form(schema) try: appstruct = form.validate(request.POST.items()) except deform.ValidationFailure as e: return dict(errors=e.error.children) username = appstruct['username'] pwd = appstruct['pwd'] # Password check user = self.User.get_user(request, username, pwd) if user: # TODO: maybe have an explicit disabled flag in the status user.password = self.User.generate_random_password() self.db.add(user) FlashMessage(self.request, _('Account disabled.'), kind='success') return {} else: return dict(errors=[{'pwd': _('Invalid password')}], code=401)
def activate(self): code = self.request.matchdict.get('code', None) user_id = self.request.matchdict.get('user_id', None) activation = self.Activation.get_by_code(self.request, code) if activation: user = self.User.get_by_id(self.request, user_id) if user.activation != activation: return HTTPNotFound() if user: self.db.delete(activation) # self.db.add(user) # not necessary self.db.flush() FlashMessage(self.request, self.Str.activation_email_verified, kind='success') self.request.registry.notify( RegistrationActivatedEvent(self.request, user, activation)) return HTTPFound(location=self.after_activate_url) return HTTPNotFound()
def _perform_logged_in_redirect(request): msg = _('You are already signed in, please log out to claim an account.') FlashMessage(request, msg, kind='error') raise exc.HTTPFound(location=request.route_url('stream'))
def _perform_already_claimed_redirect(request): msg = _('This account has already been claimed.') FlashMessage(request, msg, kind='error') raise exc.HTTPFound(location=request.route_url('stream'))