from ..form import UserForm, LoginForm, SendResetForm, ResetForm, EditUserPasswordForm, EditUserAvatarForm, EditUserEmailForm, EmailUserForm from .common import ViewBase, validate_captcha from pyramid.view import view_config, forbidden_view_config from pyramid.httpexceptions import HTTPFound, HTTPForbidden from ..security import check_pass, password_hash from pyramid.security import remember, forget import packassembler.views.email as email from pyramid.response import Response from random import getrandbits from datetime import datetime from hashlib import md5 from ..schema import * ehash = lambda e: md5(e.strip().encode()).hexdigest() class UserViews(ViewBase): @view_config(route_name='userlist', renderer='userlist.mak') def userlist(self): post = self.request.params if 'q' in post: users = User.objects(username__icontains=post['q']) else: users = User.objects return self.return_dict(title="Users", users=users) @view_config(route_name='signup', renderer='signup.mak') def signup(self): error = '' post = self.request.params form = UserForm(post) # Make sure no one is logged in if self.logged_in is not None: return HTTPFound(location=self.request.route_url('home')) if 'submit' in post and form.validate(): password = password_hash(form.password.data) captcha_pass, captcha_error = validate_captcha(self.request) if captcha_pass: try: user = User(username=form.username.data, password=password, email=form.email.data, email_hash=ehash(form.email.data), activate=getrandbits(32)).save() self.send_confirmation(user) self.request.flash('Successfully created an account please check your email to activate it.') return HTTPFound(self.request.route_url('login')) except NotUniqueError: error = 'Username or Email Already in Use.' else: error = captcha_error return self.return_dict(title='Signup', error=error, f=form) @view_config(route_name='activate') def activate(self): user = self.get_db_object(User, perm=False) if user.activate == int(self.request.matchdict['key']): user.activate = None user.save() self.request.flash('Account activated. Please login.') else: self.request.flash_error('Invalid Key.') return HTTPFound(self.request.route_url('login')) @view_config(route_name='login', renderer='login.mak') @forbidden_view_config(renderer='login.mak') def login(self): error = '' post = self.request.params form = LoginForm(post) # Get referrer referrer = self.request.url if referrer == self.request.route_url('login'): referrer = '/' came_from = post.get('came_from', referrer) form.came_from.data = came_from # Make sure no one is logged in if self.logged_in is not None: # If this is happening because the user has no permission if isinstance(self.request.exception, HTTPForbidden): self.request.flash_error('You may not create nor adopt mods unless you are a contributor.') return HTTPFound(self.request.route_url('home')) if 'submit' in post and form.validate(): username = form.username.data user = check_pass(username, form.password.data) if user: user.last_login = datetime.now() user.save() return HTTPFound(location=came_from, headers=remember(self.request, user.username)) error = 'Invalid username or password.' return self.return_dict(title='Login', error=error, f=form) @forbidden_view_config(renderer='json', xhr=True) def forbidden_json(self): return {'success': False, 'error': 'not_logged_in'} @view_config(route_name='logout') def logout(self): return HTTPFound(location=self.request.referer, headers=forget(self.request)) @view_config(route_name='sendreset', renderer='genericform.mak') def sendreset(self): post = self.request.params form = SendResetForm(post) if 'submit' in post and form.validate(): user = User.objects.get(email=form.email.data) user.reset = getrandbits(32) user.save() self.send_password_reset(user) self.request.flash('Please check your email to continue resetting your password.') return HTTPFound(self.request.route_url('login')) return self.return_dict(title='Forgot Password', f=form, cancel=self.request.route_url('login')) @view_config(route_name='reset', renderer='genericform.mak') def reset(self): user = self.get_db_object(User, perm=False) post = self.request.params form = ResetForm(post) # Make sure the key is correct if user.reset != int(self.request.matchdict['key']): return Response('Invalid Key') if 'submit' in post and form.validate(): user.password = password_hash(form.password.data) user.reset = None user.save() self.request.flash('Password reset successfully.') return HTTPFound(self.request.route_url('login')) return self.return_dict(title='Reset Password', f=form, cancel=self.request.route_url('login')) @view_config(route_name='emailuser', renderer='genericform.mak', permission='user') def emailuser(self): user = self.get_db_object(User, perm=False) post = self.request.params form = EmailUserForm(post) if 'submit' in post and form.validate(): email.user_email(self.request.registry, user, self.current_user, form.message.data) return HTTPFound(self.request.route_url('profile', id=user.id)) return self.return_dict(title='Send Email to ' + user.username, f=form, cancel=self.request.route_url('profile', id=user.id)) @view_config(route_name='edituser', renderer='edituser.mak', permission='user') def edituser(self): user = self.get_db_object(User) post = self.request.params # Create forms password_form = EditUserPasswordForm(post) email_form = EditUserEmailForm(post) avatar_form = EditUserAvatarForm(post, user) password_form.current_user.data = self.logged_in email_form.current_user.data = self.logged_in rval = HTTPFound( location=self.request.route_url( 'profile', id=user.id)) if 'password_submit' in post and password_form.validate(): user.password = password_hash(password_form.password.data) user.save() return rval elif 'email_submit' in post and email_form.validate(): user.email = email_form.email.data user.email_hash = ehash(email_form.email.data) try: user.save() return rval except NotUniqueError: email_form.email.errors.append('Email not unique.') elif 'avatar_submit' in post and avatar_form.validate(): avatar_form.populate_obj(user) user.save() return rval elif 'group' in post and self.specperm('admin'): user.group = post['group'] user.save() return rval return self.return_dict( title="Edit Account", pf=password_form, ef=email_form, af=avatar_form, cancel=self.request.route_url('profile', id=user.id) ) @view_config(route_name='deleteuser', permission='user') def deleteuser(self): # Get user user = self.get_db_object(User) user.delete() self.request.flash('User deleted successfully.') headers = forget(self.request) if self.logged_in == user.username else None return HTTPFound(self.request.route_url('home'), headers=headers) @view_config(route_name='profile', renderer='profile.mak') def profile(self): # Get user user = self.get_db_object(User, perm=False) return self.return_dict( title=user.username, owner=user, mods=Mod.objects(owner=user), packs=Pack.objects(owner=user), servers=Server.objects(owner=user), perm=self.has_perm(user), admin=self.specperm('admin')) def send_confirmation(self, user): url = self.request.route_url('activate', id=user.id, key=user.activate) email.confirmation(self.request.registry, user, url) def send_password_reset(self, user): url = self.request.route_url('reset', id=user.id, key=user.reset) email.password_reset(self.request.registry, user, url)