def post(self): """ Accept the form fields and create new organisation under current user. """ form = OrganisationForm(TornadoMultiDict(self)) organisation = Organisation.objects(slug=form.slug.data).first() if organisation: self.flash( _( "An organisation with the same short code already exists." ), 'Warning' ) elif form.validate(): organisation = Organisation( name = form.name.data, slug = form.slug.data ) organisation.save() team = Team( name="Administrators", organisation=organisation, memebers=[self.current_user] ) team.save() self.flash( _("Created a new organisation %(name)s", name=organisation.name ), "info" ) self.redirect( self.reverse_url('projects.organisation', organisation.slug) ) return self.render("projects/organisations.html", organisation_form=form)
def _on_auth(self, user_data): """Call back handler for twitter authentication""" User = self.get_user_model() logger.info(user_data) if not user_data: self.flash(_("Login using Twitter failed, please try again")) self.redirect(self.application.reverse_url("contrib.auth.login")) self.finish() logging.info(user_data) user = User.objects(twitter_username=user_data['username']).first() if user: self.flash(_("Welcome back %(name)s", name=user.name), 'info') else: user = User( name = user_data['name'], twitter_id = user_data['id_str'], twitter_username = user_data['username'], twitter_profile_picture = user_data['profile_image_url_https'], twitter_description = user_data['description'], ) user.save() self.flash( _("Thank you for registering %(name)s", name=user.name) ) self.set_secure_cookie("user", unicode(user.id)) # Finally redirect to the home page once the user has been created self.redirect( self.get_argument('next', None) or \ self.application.reverse_url("home") )
def _on_auth(self, user_data): """ Callback Function """ User = self.get_user_model() logger.info(user_data) if not user_data: self.flash(_("Login using Google failed, please try again")) self.redirect(self.application.reverse_url("contrib.auth.login")) self.finish() logger.info(user_data) user = User.objects(email=user_data['email']).first() if user: self.flash(_("Welcome back %(name)s", name=user.name), 'info') else: user = User( name = user_data['name'], email = user_data['email'], ) user.save() self.flash( _("Thank you for regsitering %(name)s", name=user.name) ) self.set_secure_cookie("user", unicode(user.id)) # Finally issue a redirect if the login was successful self.redirect( self.get_argument('next', None) or \ self.application.reverse_url("home") )
def post(self): """ Try to authenticate the user and log the user if successful """ User = self.get_user_model() form = LoginForm(TornadoMultiDict(self)) if form.validate(): user = User.authenticate(form.email.data, form.password.data) if user: if options.require_activation and not user.active: self.flash( _("User not activated yet, please activate your\ account" ), "warning" ) self.redirect( self.reverse_url("contrib.auth.activation_resend") ) return self.set_secure_cookie("user", unicode(user.id)) self.flash(_("Welcome back %(name)s", name=user.name), 'info') self.redirect( self.get_argument('next', None) or \ self.reverse_url("home") ) return self.flash(_("The email or password is invalid"), 'error') self.render('user/login.html', login_form=form)
def post(self): "Do password reset" form = DoPasswordResetForm(TornadoMultiDict(self)) reset_key = self.get_argument('reset_key', None) email = self.get_argument('email', None) User = self.get_user_model() user = User.objects(email=email, reset_key=reset_key).first() if not reset_key or not user: self.flash(_( "Invalid user, Try again." ), "warning" ) self.redirect(self.reverse_url('send.reset.key')) return if form.validate(): user.set_password(form.password.data) user.reset_key = None user.save(safe=True) self.flash( _('Password has been successfully reset.'), 'info' ) self.redirect(self.reverse_url('home')) return return self.render( 'user/password_reset.html', form=form, user=user )
def post(self, organisation_slug): """ Accept the form fields and create a new project under the current Organisation """ form = ProjectForm(TornadoMultiDict(self)) for organisation in self.current_user.organisations: if organisation.slug == organisation_slug: break else: raise tornado.web.HTTPError(404) form.team.choices = [ (unicode(team.id), team.name) for team in organisation.teams ] existing = Project.objects( slug=form.slug.data, organisation=organisation ).first() if existing: self.flash( _( "A project with the same short code already exists with\ in current organisation." ), 'Warning' ) elif form.validate(): admin_team = Team.objects().with_id(form.team.data) if self.current_user not in admin_team.members: self.flash( _( "You are not an administrator. Only administrators can\ create projects" ) ) self.send_error(403) return acl_admin = AccessControlList(team=admin_team, role="admin") project = Organisation( name = form.name.data, acl = [acl_admin], slug = form.slug.data, organisation = organisation ) project.save() self.flash( _("Created a new project %(name)s", name=project.name ), "info" ) self.redirect( self.reverse_url( 'projects.project', organisation.slug, project.slug ) ) return self.render("projects/projects.html", form=form)
def post(self, organisation_slug): """ Add new team to current organisation. :param organisation_slug: Slug of organisation. It is used to select the exact organisation from 'organisation' collection. """ current_user = User.objects.with_id(self.current_user.id) for organisation in current_user.organisations: if organisation.slug == organisation_slug: break else: raise tornado.web.HTTPError(404) form = TeamForm(TornadoMultiDict(self)) admin_team = Team.objects( organisation=organisation, name="Administrators" ).first() if form.validate() and current_user in admin_team.members: team = Team(name=form.name.data, organisation=organisation, members=[current_user] ) team.save() self.flash( _("A new team have been added to this organisation"), "info" ) self.redirect( self.reverse_url('projects.organisation', organisation.slug) ) return elif not form.validate(): self.flash( _( "Something went wrong while submitting the form." ), "warning" ) else: self.flash( _("You have no permission for creating a team under this\ organisation.") ) organisations = self.current_user.organisations projects = self.find_projects(organisation) self.render( 'projects/organisation.html', organisation=organisation, organisations=organisations, projects=projects, form=TeamForm(), invite_form=InvitationForm(), remove_form=RemoveForm() ) return
def post(self): """ Accept registrations """ User = self.get_user_model() form = RegistrationForm(TornadoMultiDict(self)) if form.validate(): # First check if user exists user = User.objects(email=form.email.data).first() if user: self.flash(_( "This email is already registered. Click on Sign In" ), "warning" ) else: user = User( company_name = form.company_name.data, name = form.name.data, email = form.email.data, ) user.set_password(form.password.data) user.save(safe=True) if options.require_activation: self.create_activation_key(user) self.flash( _("Thank you for registering %(name)s. Please check\ your Inbox and follow the instructions", name=user.name), 'info' ) self.redirect(self.reverse_url("home")) return else: user.active = True user.save() self.flash( _("Thank you for registering %(name)s", name=user.name), 'info' ) self.set_secure_cookie("user", unicode(user.id)) self.redirect( self.get_argument('next', None) or \ self.reverse_url("home") ) return else: self.flash( _("There were error(s) in processing your registration."), 'error' ) self.render('user/registration.html', registration_form=form)
def _on_login(self, user_data): """ Callback function to handle facebook response """ User = self.get_user_model() logger.info(user_data) if not user_data: login_failure.send(self) self.flash(_("Login using Facebook failed, please try again")) self.redirect(self.application.reverse_url("contrib.auth.login")) self.finish() user = User.objects( Q(facebook_id=int(user_data['id'])) | Q(email=user_data['email']) ).first() if user: self.flash(_("Welcome back %(name)s", name=user.name), 'info') if not user.facebook_id: user.facebook_id = user_data['id'] user.facebook_picture = user_data['picture'] user.facebook_username = user_data['username'] user.facebook_link = user_data['link'] user.save() self.flash( _("Your facebook account is now connected to your account") ) else: user = User( facebook_id = user_data['id'], facebook_picture = user_data['picture'], facebook_username = user_data['username'], facebook_link = user_data['link'], name = user_data['name'], email = user_data['email'] ) user.save() self.flash( _("Thank you for registering %(name)s", name=user.name) ) self.set_secure_cookie("user", unicode(user.id)) login_success.send(self, user=user) self.redirect( self.get_argument('next', None) or \ self.application.reverse_url("home") )
def get(self, ticket_id=None): """ Render specified ticket """ if ticket_id: ticket = Ticket.objects( id=ticket_id, user=self.current_user ).first() if not ticket: self.flash(_('Ticket not found!'), 'warning') self.redirect(self.get_argument('next', None) or \ self.reverse_url('home')) return if self.is_xhr: self.write({ 'id': ticket.id, 'subject': ticket.subject, 'message': ticket.message, 'user': ticket.user, 'status': ticket.status, 'comments': ticket.comments, 'assigned_to' : ticket.assigned_to, }) else: self.render( 'ticket/ticket.html', ticket=ticket ) else: form = TicketForm() self.render( 'ticket/ticket.html', ticket_form=TicketForm, ) return
def post(self, organisation_slug, project_slug): """ Accept the form fields and create a new lasklist under the project. :param organisation_slug: Slug of organisation. It is used to select the exact organisation from 'organisation' collection. :param project_slug: Slug of project. It is used to select the exact project from the 'project' collection. """ organisation = self.security_check(organisation_slug) form = TaskListForm(TornadoMultiDict(self)) project = Project.objects(slug=project_slug).first() if form.validate() and project: tasklist = TaskList(name=form.name.data, project=project) tasklist.save() self.flash( _("Created a new task list %(name)s", name=tasklist.name), 'Info' ) self.redirect( self.reverse_url( 'projects.tasklist', organisation.slug, project.slug, tasklist.sequence ) ) return tasklists = self.find_tasklists(organisation, project_slug) organisations = self.current_user.organisations projects = self.find_projects(organisation) self.flash( _( "Something went wrong while creating the task list! Try Again" ), 'error' ) self.render('projects/task_lists.html', form=form, organisation=organisation, project=project, tasklists=tasklists, organisations=organisations, projects=projects )
def get(self, invitation_key): """ Accept the invitation key and add the user to current user. :param invitation_key: It includes the organisation_slug, project_slug and email. Extract these values from invitation_key and add the user to exact project. """ signer = URLSafeSerializer(self.application.settings["cookie_secret"]) invitation_key = signer.loads(invitation_key) user = User.objects(email=invitation_key[2]).first() project = Project.objects(slug=invitation_key[1]).first() organisation = Organisation.objects(slug=invitation_key[0]).first() team = [ team.team for team in project.acl if team.role == "admin" ][0] if user and user not in team.members: team.reload() team.members.append(user) team.save() self.flash( _("You are added to this project"), "info" ) self.redirect( self.reverse_url( "projects.project", organisation.slug, project.slug ) ) return elif not user: self.flash( _( 'Invalid invitation key!' ), 'error' ) else: self.flash( _( "User already existing on current project" ),"info" ) self.redirect( self.reverse_url("projects.organisations") )
def post(self): """ Accept the form fields and create new organisation under current user. """ current_user = User.objects.with_id(self.current_user.id) form = OrganisationForm(TornadoMultiDict(self)) organisation = Organisation.objects(slug=form.slug.data).first() if organisation: self.flash( _( "An organisation with the same short code already exists." ), 'Warning' ) elif form.validate(): organisation = Organisation( name=form.name.data, slug=form.slug.data ) organisation.save() team = Team( name="Administrators", organisation=organisation, members=[current_user] ) team.save() self.flash( _("Created a new organisation %(name)s", name=organisation.name ), "info" ) self.redirect( self.reverse_url('projects.organisation', organisation.slug) ) return organisations = self.find_organisations() self.flash( _("Something went wrong while submitting the form.\ Please try again!" ), "warning" ) self.render( "projects/organisations.html", form=form, organisations=organisations, )
def get(self, activation_key): """ Acccept the Activation key from url and activate the user account """ signer = URLSafeSerializer(self.application.settings["cookie_secret"]) User = self.get_user_model() user = User.objects(email=signer.loads(activation_key)).first() if not user: self.flash( _('Invalid Activation Key, Please register.'), 'warning' ) self.redirect(self.reverse_url("contrib.auth.registration")) return user.active = True user.save() self.flash( _("Thank you for activating your account. Please login again."), 'info' ) self.redirect(self.reverse_url('contrib.auth.login'))
def post(self): "Sends the reset key" form = SendPasswordResetForm(TornadoMultiDict(self)) if form.validate(): User = self.get_user_model() email = form.email.data # Check if email exists in database user = User.objects(email=email).first() if not user: self.flash( _('Email entered is not registered with us'), 'error' ) self.render('user/send_reset_key.html', form=form) return reset_key = ''.join( random.sample(string.letters + string.digits, 15) ) user.reset_key = reset_key user.save() # Send him a mail with invite self.send_password_reset_mail(user) self.flash( _('Instructions for resetting your password have been \ emailed to %s' % email), 'info' ) self.redirect( self.get_argument('next', None) or \ self.application.reverse_url("home") ) return else: return self.render('user/send_reset_key.html', form=form)
def post(self): form = TicketForm(TornadoMultiDict(self)) if form.validate(): ticket = Ticket( subject = form.subject.data, message = form.message.data, status = form.status.data, user = self.current_user, comment = [] ) ticket.save() self.flash(_("Your ticket has been created"), "info") self.redirect( self.reverse_url("ticket.ticket", ticket.id) ) return self.flash( _( "Something went wrong while saving your comment! Try Again" ), 'error' ) self.render('ticket/ticket.html', ticket_form=form)
def post(self): """ Accept the email Id from the user and create a new activation key also send it to the given email id. """ User = self.get_user_model() form = ActivationResendForm(TornadoMultiDict(self)) if form.validate(): user = User.objects(email=form.email.data).first() if user: self.create_activation_key(user) self.flash( _("An email has been send to the given email Id. Please\ check your inbox and follow the instructions ") ) self.redirect(self.reverse_url('contrib.auth.login')) return self.flash( _("Oops! we could not match your email with any of our users"), "error" ) self.render('user/activation_resend.html', form=form)
def post(self, ticket_id): """ Add comment to ticket """ ticket = Ticket.objects(id=ticket_id, user=self.current_user).first() if not ticket: self.flash('Requested ticket not found,', 'warning') self.redirect( self.get_argument('next', None) or self.reverse_url('home') ) return form = CommentForm(TornadoMultiDict(self)) if form.validate(): comment = Comment( comment=form.comment.data, user=self.current_user, status=form.status.data ) if not ticket.comments: ticket.comments = [comment] else: ticket.comments.append(comment) ticket.save() self.flash( _("Your comment has been added to the ticket"), "Info" ) self.redirect( self.reverse_url("ticket.ticket", ticket_id) ) else: self.flash( _( "Something went wrong while saving your comment! Try Again" ), "warning" ) self.render('ticket/ticket.html', ticket=ticket) return
def create_activation_key(self, user): """ Build an account activation key and build the email """ signer = URLSafeSerializer(self.application.settings["cookie_secret"]) activation_key = signer.dumps(user.email) parts = [] try: parts.append( MIMEText( self.render_string( 'emails/activation-html.html', activation_key=activation_key ), 'html' ) ) except IOError: logging.warning('No HTML template emails/activation-html.html') try: parts.append( MIMEText( self.render_string( "emails/activation-text.html", activation_key=activation_key ), 'text' ) ) except IOError: logging.warning("No TEXT template emails/activation-text.html") if not parts: # Fallback to simple string replace since no templates have been # defined. parts.append( MIMEText( 'To activate click: %s' % self.reverse_url('contrib.auth.activation', activation_key) , 'text' ) ) message = MIMEMultipart('alternative') message['Subject'] = _("Activate your Account") message['From'] = options.email_sender message['To'] = user.email for part in parts: message.attach(part) self.send_mail(options.email_sender, user.email, message.as_string())
def get(self): "Render password reset form" User = self.get_user_model() form = DoPasswordResetForm(TornadoMultiDict(self)) reset_key = self.get_argument('reset_key', None) email = self.get_argument('email', None) user = User.objects(email=email, reset_key=reset_key).first() if not reset_key or not user: self.flash(_('No Valid Password Reset Key found'), 'error') self.redirect(self.reverse_url('send.reset.key')) return return self.render( 'user/password_reset.html', form=form, user=user )
:license: BSD, see LICENSE for more details. """ from __future__ import absolute_import from wtforms import validators from monstor.utils.i18n import _ class TornadoMultiDict(object): """A wrapper to make the tornado request handler to be compatible with the multidict format used by WTForms """ def __init__(self, handler): self.handler = handler def __iter__(self): return iter(self.handler.request.arguments) def __len__(self): return len(self.handler.request.arguments) def __contains__(self, name): return (name in self.handler.request.arguments) def getlist(self, name): return self.handler.get_arguments(name, strip=False) REQUIRED_VALIDATOR = validators.Required(message=_("This field is required")) EMAIL_VALIDATOR = validators.Email(message=_('Invalid email address'))
def post(self, organisation_slug, project_slug, tasklist_sequence, task_sequence): """ Add a new comment :param organisation_slug: Slug of organisation. It is used to select the exact organisation from 'organisation' collection. :param project_slug: Slug of project. It is used to select the exact project from the 'project' collection. :param tasklist_sequence: An incremental Id is assigned with each tasklist. This tasklist id used to select the exact tasklist from the 'tasklist' collection. :param task_sequence: An incremental Id is assigned with each task. This task id used to select the exact tasklist from the 'task' collection. """ organisation = self.security_check(organisation_slug) project = Project.objects( slug=project_slug, organisation=organisation ).first() tasklist = TaskList.objects( project=project, sequence=tasklist_sequence ).first() form = CommentForm(TornadoMultiDict(self)) team = [ team.team if team.role == "admin" else ''\ for team in project.acl ][0] form.assigned_to.choices = [ (unicode(user.id), user.name) for user in team.members ] task = Task.objects(task_list=tasklist, sequence=task_sequence).first() if form.validate(): assigned_user = User.objects().with_id(form.assigned_to.data) comment = FollowUp( message=form.comment.data, to_status=form.status.data, to_assignee=assigned_user ) if not task.follow_ups: task.follow_ups = [comment] else: task.follow_ups.append(comment) task.assigned_to = assigned_user task.save() parts = [] try: parts.append( MIMEText( self.render_string( 'emails/comment_mail-html.html', organisation_slug=organisation_slug, project_slug=project_slug, tasklist_sequence=tasklist_sequence, task_sequence=task_sequence, project=project, task=task, user=assigned_user, message=form.comment.data, assigner=self.current_user.name ), 'html' ) ) except IOError: logging.warning( 'No HTML template emails/comment_mail-html.html' ) try: parts.append( MIMEText( self.render_string( "emails/comment_mail-text.html", organisation_slug=organisation_slug, project_slug=project_slug, tasklist_sequence=tasklist_sequence, task_sequence=task_sequence, project=project, task=task, user=assigned_user ), 'text' ) ) except IOError: logging.warning( "No TEXT template emails/comment_mail-text.html" ) if not parts: # Fallback to simple string replace since no templates # have been defined. parts.append( MIMEText( 'To view click: %s' % self.reverse_url( 'projects.task.comment-email', organisation_slug=organisation_slug, project_slug=project_slug, tasklist_sequence=tasklist_sequence, task_sequence=task_sequence, ), 'text' ) ) message = MIMEMultipart('alternative') message['Subject'] = _("Task Assigned to you") message['From'] = options.email_sender message['To'] = assigned_user.email for part in parts: message.attach(part) self.send_mail( options.email_sender, assigned_user.email, message.as_string() ) self.flash( _( "Your comment has been added to the task." ), "Info" ) self.redirect( self.reverse_url( "projects.task", organisation_slug, project_slug, tasklist_sequence, task.sequence ) ) return else: organisations = self.current_user.organisations projects = self.find_projects(organisation) tasks = Task.objects(task_list = tasklist).all() self.flash( _( "Something went wrong while adding new comment! Try Again" ), "warning" ) self.render( 'projects/task.html', task=task, organisation=organisation, project=project, tasklist=tasklist, form=form, organisations=organisations, projects=projects, tasks=tasks ) return
def post(self, organisation_slug): """ Accept the form fields and create a new project under the current Organisation :param organisation_slug: Slug of organisation. It is used to select the exact organisation from 'organisation' collection. """ form = ProjectForm(TornadoMultiDict(self)) current_user = User.objects.with_id(self.current_user.id) for organisation in current_user.organisations: if organisation.slug == organisation_slug: break else: raise tornado.web.HTTPError(404) projects = self.find_projects(organisation) organisations = self.current_user.organisations form.team.choices = [ (unicode(team.id), team.name) for team in organisation.teams ] existing = Project.objects( slug=form.slug.data, organisation=organisation ).first() if existing: self.flash( _( "A project with the same short code already exists with\ in current organisation." ), 'Warning' ) elif form.validate(): admin_team = Team.objects().with_id(form.team.data) if current_user not in admin_team.members: self.flash( _( "You are not an administrator. Only administrators can\ create projects" ), 'warning' ) self.render( "projects/projects.html", form=form, organisation=organisation, projects=projects ) return acl_admin = AccessControlList(team=admin_team, role="admin") project = Project( name=form.name.data, acl=[acl_admin], slug=form.slug.data, organisation=organisation ) project.save() self.flash( _( "Created a new project %(name)s", name=project.name ), "info" ) self.redirect( self.reverse_url( 'projects.project', organisation.slug, project.slug ) ) return self.flash( _( "Something went wrong while submitting the form.\ Please try again!" ), "Error" ) self.render( "projects/projects.html", form=form, organisation=organisation, organisations=organisations, projects=projects )
def post(self, organisation_slug, project_slug): """ Invite peoples to current project """ organisation = self.security_check(organisation_slug) form = InvitationForm(TornadoMultiDict(self)) current_user = User.objects.with_id(self.current_user.id) project = Project.objects( organisation=organisation, slug=project_slug ).first() tasklists = self.find_tasklists(organisation, project_slug) admin_team = Team.objects( organisation=organisation, name="Administrators" ).first() if form.validate() and current_user in admin_team.members: signer = URLSafeSerializer( self.application.settings["cookie_secret"] ) invitation_key = signer.dumps( (organisation_slug, project_slug, form.email.data) ) parts = [] try: parts.append( MIMEText( self.render_string( 'emails/invitation-html.html', invitation_key=invitation_key, project=project, ), 'html' ) ) except IOError: logging.warning('No HTML template emails/invitation-html.html') try: parts.append( MIMEText( self.render_string( "emails/invitation-text.html", invitation_key=invitation_key, project=project, ), 'text' ) ) except IOError: logging.warning("No TEXT template emails/invitation-text.html") if not parts: # Fallback to simple string replace since no templates # have been defined. parts.append( MIMEText( 'To accept click: %s' % self.reverse_url( 'projects.project.invitation', invitation_key ), 'text' ) ) message = MIMEMultipart('alternative') message['Subject'] = _("Invitation") message['From'] = options.email_sender message['To'] = form.email.data for part in parts: message.attach(part) self.send_mail( options.email_sender, form.email.data, message.as_string() ) self.flash(_("Invitation sent")) elif not form.validate(): self.flash( _("Something went wrong while submitting the form.\ Please try again." ), "Error" ) else: self.flash( _("You have no permission for inviting another users\ in to this project" ),"info" ) organisations = self.current_user.organisations projects = self.find_projects(organisation) self.render( "projects/project.html", form=form, organisation=organisation, project=project, tasklists=tasklists, organisations=organisations, projects=projects ) return
def get(self): message = _("United States") self.write(unicode(message))
def post(self, organisation_slug, project_slug, tasklist_sequence): """ Create a new task :param organisation_slug: Slug of organisation. It is used to select the exact organisation from 'organisation' collection. :param project_slug: Slug of project. It is used to select the exact project from the 'project' collection. :param tasklist_sequence: An incremental Id is assigned with each tasklist. This tasklist id used to select the exact tasklist from the 'tasklist' collection. """ organisation = self.security_check(organisation_slug) project = Project.objects( slug=project_slug, organisation=organisation ).first() tasklist = TaskList.objects( project=project, sequence=tasklist_sequence ).first() if project == None or tasklist == None: raise tornado.web.HTTPError(403) form = TaskForm(TornadoMultiDict(self)) if form.validate() and tasklist: task = Task( title=form.title.data, status=form.status.data, task_list=tasklist, follow_ups=[], ) task.save() self.flash( _("A new task has been created successfully."), "Info" ) self.redirect( self.reverse_url( "projects.task", organisation_slug, project_slug, tasklist_sequence, task.sequence ) ) return else: tasklists = self.find_tasklists(organisation, project_slug) organisations = self.current_user.organisations projects = self.find_projects(organisation) self.flash( _( "Something went wrong while creating a new task! Try Again" ), "warning" ) self.render( "projects/task_list.html", form=form, organisation=organisation, project=project, tasklist=tasklist, tasklists=tasklists, projects=projects, organisations=organisations ) return