Extract commenting logic from blueprints

Only refactored parts required to separate the view from logic code.
This commit is contained in:
Ivan Habunek 2018-10-30 11:20:04 +01:00 committed by Drew DeVault
parent 5b47c3734d
commit c9b33b7627
2 changed files with 132 additions and 117 deletions

View File

@ -1,27 +1,17 @@
import re
import string
from flask import Blueprint, render_template, request, url_for, abort, redirect
from flask import session
from flask_login import current_user
from todosrht.access import get_tracker, get_ticket
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess
from todosrht.types import TicketComment, TicketResolution, TicketSeen
from todosrht.types import TicketSubscription
from todosrht.types import Event, EventType, EventNotification
from todosrht.types import Label, TicketLabel
from todosrht.email import notify
from srht.config import cfg
from srht.database import db
from srht.flask import loginrequired
from srht.validation import Validation
from datetime import datetime
from todosrht.access import get_tracker, get_ticket
from todosrht.tickets import add_comment
from todosrht.types import Event, EventType
from todosrht.types import Label, TicketLabel
from todosrht.types import TicketAccess, TicketResolution, TicketSeen
from todosrht.types import TicketSubscription
ticket = Blueprint("ticket", __name__)
smtp_user = cfg("mail", "smtp-user", default=None)
smtp_from = cfg("mail", "smtp-from", default=None)
notify_from = cfg("todo.sr.ht", "notify-from", default=smtp_from)
@ticket.route("/<owner>/<name>/<int:ticket_id>")
def ticket_GET(owner, name, ticket_id):
tracker, _ = get_tracker(owner, name)
@ -135,40 +125,17 @@ def ticket_comment_POST(owner, name, ticket_id):
valid.expect(text or resolve or reopen,
"Comment is required", field="comment")
if not valid.ok:
return render_template("ticket.html",
tracker=tracker,
ticket=ticket,
access=access,
**valid.kwargs)
if (resolve or reopen) and TicketAccess.edit not in access:
abort(403)
if text:
comment = TicketComment()
comment.text = text
# TODO: anonymous comments (when configured appropriately)
comment.submitter_id = current_user.id
comment.ticket_id = ticket.id
db.session.add(comment)
ticket.updated = comment.created
else:
comment = None
old_status = ticket.status
old_resolution = ticket.resolution
if resolve and TicketAccess.edit in access:
if resolve:
try:
resolution = TicketResolution(int(resolution))
ticket.status = TicketStatus.resolved
ticket.resolution = resolution
except Exception as ex:
valid.expect(text, "Comment is required", field="comment")
abort(400, "Invalid resolution")
else:
resolution = None
if reopen and TicketAccess.edit in access:
ticket.status = TicketStatus.reported
if not valid.ok:
return render_template("ticket.html",
tracker=tracker,
@ -176,85 +143,15 @@ def ticket_comment_POST(owner, name, ticket_id):
access=access,
**valid.kwargs)
tracker.updated = datetime.utcnow()
db.session.flush()
comment = add_comment(current_user, ticket,
text=text, resolve=resolve, resolution=resolution, reopen=reopen)
if comment:
ticket_url = url_for(".ticket_GET",
owner=tracker.owner.canonical_name(),
name=tracker.name,
ticket_id=ticket.scoped_id) + "#comment-" + str(comment.id)
else:
ticket_url = url_for(".ticket_GET",
ticket_url = url_for(".ticket_GET",
owner=tracker.owner.canonical_name(),
name=tracker.name,
ticket_id=ticket.scoped_id)
subscribed = False
def _notify(sub):
notify(sub, "ticket_comment", "Re: {}/{}/#{}: {}".format(
tracker.owner.canonical_name(), tracker.name,
ticket.scoped_id, ticket.title),
headers={
"From": "~{} <{}>".format(
current_user.username, notify_from),
"Sender": smtp_user,
},
ticket=ticket,
comment=comment,
resolution=resolution.name if resolution else None,
ticket_url=ticket_url.replace("%7E", "~")) # hack
event = Event()
event.event_type = 0
event.user_id = current_user.id
event.ticket_id = ticket.id
if comment:
event.event_type |= EventType.comment
event.comment_id = comment.id
if ticket.status != old_status or ticket.resolution != old_resolution:
event.event_type |= EventType.status_change
event.old_status = old_status
event.old_resolution = old_resolution
event.new_status = ticket.status
event.new_resolution = ticket.resolution
db.session.add(event)
db.session.flush()
def _add_notification(sub):
notification = EventNotification()
notification.user_id = sub.user_id
notification.event_id = event.id
db.session.add(notification)
subscribed = False
updated_users = set()
for sub in tracker.subscriptions:
updated_users.update([sub.user_id])
_add_notification(sub)
if sub.user_id == current_user.id:
subscribed = True
continue
_notify(sub)
for sub in ticket.subscriptions:
if sub.user_id in updated_users:
continue
_add_notification(sub)
if sub.user_id == current_user.id:
subscribed = True
continue
_notify(sub)
if not subscribed:
sub = TicketSubscription()
sub.ticket_id = ticket.id
sub.user_id = current_user.id
db.session.add(sub)
_add_notification(sub)
db.session.commit()
ticket_url += "#comment-" + str(comment.id)
return redirect(ticket_url)

118
todosrht/tickets.py Normal file
View File

@ -0,0 +1,118 @@
from datetime import datetime
from flask import url_for
from srht.config import cfg
from srht.database import db
from todosrht.email import notify
from todosrht.types import Event, EventType, EventNotification
from todosrht.types import TicketComment, TicketStatus, TicketSubscription
smtp_user = cfg("mail", "smtp-user", default=None)
smtp_from = cfg("mail", "smtp-from", default=None)
notify_from = cfg("todo.sr.ht", "notify-from", default=smtp_from)
def add_comment(user, ticket,
text=None, resolve=False, resolution=None, reopen=False):
assert text or resolve or reopen
tracker = ticket.tracker
if text:
comment = TicketComment()
comment.text = text
# TODO: anonymous comments (when configured appropriately)
comment.submitter_id = user.id
comment.ticket_id = ticket.id
db.session.add(comment)
ticket.updated = comment.created
else:
comment = None
old_status = ticket.status
old_resolution = ticket.resolution
if resolution:
ticket.status = TicketStatus.resolved
ticket.resolution = resolution
if reopen:
ticket.status = TicketStatus.reported
tracker.updated = datetime.utcnow()
db.session.flush()
subscribed = False
ticket_url = url_for("ticket.ticket_GET",
owner=tracker.owner.canonical_name(),
name=tracker.name,
ticket_id=ticket.scoped_id)
if comment:
ticket_url += "#comment-" + str(comment.id)
def _notify(sub):
notify(sub, "ticket_comment", "Re: {}/{}/#{}: {}".format(
tracker.owner.canonical_name(), tracker.name,
ticket.scoped_id, ticket.title),
headers={
"From": "~{} <{}>".format(
user.username, notify_from),
"Sender": smtp_user,
},
ticket=ticket,
comment=comment,
resolution=resolution.name if resolution else None,
ticket_url=ticket_url.replace("%7E", "~")) # hack
event = Event()
event.event_type = 0
event.user_id = user.id
event.ticket_id = ticket.id
if comment:
event.event_type |= EventType.comment
event.comment_id = comment.id
if ticket.status != old_status or ticket.resolution != old_resolution:
event.event_type |= EventType.status_change
event.old_status = old_status
event.old_resolution = old_resolution
event.new_status = ticket.status
event.new_resolution = ticket.resolution
db.session.add(event)
db.session.flush()
def _add_notification(sub):
notification = EventNotification()
notification.user_id = sub.user_id
notification.event_id = event.id
db.session.add(notification)
subscribed = False
updated_users = set()
for sub in tracker.subscriptions:
updated_users.update([sub.user_id])
_add_notification(sub)
if sub.user_id == user.id:
subscribed = True
continue
_notify(sub)
for sub in ticket.subscriptions:
if sub.user_id in updated_users:
continue
_add_notification(sub)
if sub.user_id == user.id:
subscribed = True
continue
_notify(sub)
if not subscribed:
sub = TicketSubscription()
sub.ticket_id = ticket.id
sub.user_id = user.id
db.session.add(sub)
_add_notification(sub)
db.session.commit()
return comment