def ticket_edit_POST(owner, name, ticket_id): tracker, _ = get_tracker(owner, name) if not tracker: abort(404) ticket, access = get_ticket(tracker, ticket_id) if not ticket: abort(404) if not TicketAccess.edit in access: abort(401) valid = Validation(request) title = valid.require("title", friendly_name="Title") desc = valid.optional("description") valid.expect(not title or 3 <= len(title) <= 2048, "Title must be between 3 and 2048 characters.", field="title") valid.expect(not desc or len(desc) < 16384, "Description must be no more than 16384 characters.", field="description") if not valid.ok: return render_template("edit_ticket.html", tracker=tracker, ticket=ticket, **valid.kwargs) ticket.title = title ticket.description = desc db.session.commit() return redirect(ticket_url(ticket))
def test_mark_seen(client): ticket = TicketFactory() user = UserFactory() db.session.commit() url = ticket_url(ticket) query = TicketSeen.query.filter_by(user=user, ticket=ticket) assert query.count() == 0 # Created on first visit with logged_in_as(user): response = client.get(url) assert response.status_code == 200 first_time = query.one().last_view # Updated on second visit with logged_in_as(user): response = client.get(url) assert response.status_code == 200 second_time = query.one().last_view assert second_time > first_time
def ticket_remove_label(owner, name, ticket_id, label_id): tracker, _ = get_tracker(owner, name) if not tracker: abort(404) ticket, access = get_ticket(tracker, ticket_id) if not ticket: abort(404) if not TicketAccess.edit in access: abort(401) label = Label.query.filter(Label.id == label_id).first() if not label: abort(404) ticket_label = (TicketLabel.query.filter( TicketLabel.label_id == label_id).filter( TicketLabel.ticket_id == ticket.id)).first() if ticket_label: event = Event() event.event_type = EventType.label_removed event.user_id = current_user.id event.ticket_id = ticket.id event.label_id = label.id db.session.add(event) db.session.delete(ticket_label) db.session.commit() return redirect(ticket_url(ticket))
def disable_notifications(owner, name, ticket_id): tracker, access = get_tracker(owner, name) if not tracker: abort(404) ticket, access = get_ticket(tracker, ticket_id) if not ticket: abort(404) sub = (TicketSubscription.query.filter( TicketSubscription.tracker_id == None).filter( TicketSubscription.ticket_id == ticket.id).filter( TicketSubscription.user_id == current_user.id)).one_or_none() if not sub: return redirect(ticket_url(ticket)) db.session.delete(sub) db.session.commit() return redirect(ticket_url(ticket))
def ticket_unassign(owner, name, ticket_id): valid = Validation(request) ticket = _assignment_get_ticket(owner, name, ticket_id) user = _assignment_get_user(valid) if not valid.ok: _, access = get_ticket(ticket.tracker, ticket_id) ctx = get_ticket_context(ticket, ticket.tracker, access) return render_template("ticket.html", valid, **ctx) unassign(ticket, user, current_user) db.session.commit() return redirect(ticket_url(ticket))
def ticket_add_label(owner, name, ticket_id): tracker, _ = get_tracker(owner, name) if not tracker: abort(404) ticket, access = get_ticket(tracker, ticket_id) if not ticket: abort(404) if not TicketAccess.edit in access: abort(401) valid = Validation(request) label_id = valid.require("label_id", friendly_name="A label") if not valid.ok: ctx = get_ticket_context(ticket, tracker, access) return render_template("ticket.html", **ctx, **valid.kwargs) valid.expect(re.match(r"^\d+$", label_id), "Label ID must be numeric", field="label_id") if not valid.ok: ctx = get_ticket_context(ticket, tracker, access) return render_template("ticket.html", **ctx, **valid.kwargs) label_id = int(request.form.get('label_id')) label = Label.query.filter(Label.id == label_id).first() if not label: abort(404) ticket_label = (TicketLabel.query.filter( TicketLabel.label_id == label.id).filter( TicketLabel.ticket_id == ticket.id)).first() if not ticket_label: ticket_label = TicketLabel() ticket_label.ticket_id = ticket.id ticket_label.label_id = label.id ticket_label.user_id = current_user.id event = Event() event.event_type = EventType.label_added event.user_id = current_user.id event.ticket_id = ticket.id event.label_id = label.id db.session.add(ticket_label) db.session.add(event) db.session.commit() return redirect(ticket_url(ticket))
def ticket_comment_POST(owner, name, ticket_id): tracker, access = get_tracker(owner, name) if not tracker: abort(404) ticket, access = get_ticket(tracker, ticket_id) if not ticket: abort(404) valid = Validation(request) text = valid.optional("comment") resolve = valid.optional("resolve") resolution = valid.optional("resolution") reopen = valid.optional("reopen") valid.expect(not text or 3 <= len(text) <= 16384, "Comment must be between 3 and 16384 characters.", field="comment") valid.expect(text or resolve or reopen, "Comment is required", field="comment") if (resolve or reopen) and TicketAccess.edit not in access: abort(403) if resolve: try: resolution = TicketResolution(int(resolution)) except Exception as ex: abort(400, "Invalid resolution") else: resolution = None if not valid.ok: ctx = get_ticket_context(ticket, tracker, access) return render_template("ticket.html", **ctx, **valid.kwargs) comment = add_comment(current_user, ticket, text=text, resolve=resolve, resolution=resolution, reopen=reopen) return redirect(ticket_url(ticket, comment))
def notify_assignee(subscription, ticket, assigner, assignee): """ Sends a notification email to the person who was assigned to the issue. """ ticket_path = "{}/{}/#{}".format(ticket.tracker.owner.canonical_name, ticket.tracker.name, ticket.scoped_id) subject = "{}: {}".format(ticket_path, ticket.title) headers = { "From": "~{} <{}>".format(assigner.username, notify_from), "Sender": smtp_user, } context = { "assigner": assigner.canonical_name, "ticket_path": ticket_path, "ticket_url": ticket_url(ticket) } notify(subscription, "ticket_assigned", subject, headers, **context)
def _send_comment_notification(subscription, ticket, user, comment, resolution): subject = "Re: {}/{}/#{}: {}".format(ticket.tracker.owner.canonical_name, ticket.tracker.name, ticket.scoped_id, ticket.title) headers = { "From": "~{} <{}>".format(user.username, notify_from), "Sender": smtp_user, } url = ticket_url(ticket, comment=comment) notify(subscription, "ticket_comment", subject, headers=headers, ticket=ticket, comment=comment, resolution=resolution.name if resolution else None, ticket_url=url)