Add notification types

This commit is contained in:
rubenwardy 2020-12-05 03:44:34 +00:00
parent d5263acdf8
commit d32bb30071
8 changed files with 112 additions and 27 deletions

View File

@ -309,7 +309,7 @@ def create_edit(author=None, name=None):
else:
msg = "Edited {}".format(package.title)
addNotification(package.maintainers, current_user,
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT,
msg, package.getDetailsURL(), package)
severity = AuditSeverity.NORMAL if current_user in package.maintainers else AuditSeverity.EDITOR
@ -391,7 +391,7 @@ def move_to_state(package):
msg = "Approved {}".format(package.title)
addNotification(package.maintainers, current_user, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getDetailsURL(), package)
severity = AuditSeverity.NORMAL if current_user in package.maintainers else AuditSeverity.EDITOR
addAuditLog(severity, current_user, msg, package.getDetailsURL(), package)
@ -423,7 +423,7 @@ def remove(package):
url = url_for("users.profile", username=package.author.username)
msg = "Deleted {}".format(package.title)
addNotification(package.maintainers, current_user, msg, url, package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT, msg, url, package)
addAuditLog(AuditSeverity.EDITOR, current_user, msg, url)
db.session.commit()
@ -438,7 +438,7 @@ def remove(package):
package.state = PackageState.WIP
msg = "Unapproved {}".format(package.title)
addNotification(package.maintainers, current_user, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_APPROVAL, msg, package.getDetailsURL(), package)
addAuditLog(AuditSeverity.EDITOR, current_user, msg, package.getDetailsURL(), package)
db.session.commit()
@ -474,12 +474,12 @@ def edit_maintainers(package):
for user in users:
if not user in package.maintainers:
addNotification(user, current_user,
addNotification(user, current_user, NotificationType.MAINTAINER,
"Added you as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
for user in package.maintainers:
if user != package.author and not user in users:
addNotification(user, current_user,
addNotification(user, current_user, NotificationType.MAINTAINER,
"Removed you as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
package.maintainers.clear()
@ -488,7 +488,7 @@ def edit_maintainers(package):
package.maintainers.append(package.author)
msg = "Edited {} maintainers".format(package.title)
addNotification(package.author, current_user, msg, package.getDetailsURL(), package)
addNotification(package.author, current_user, NotificationType.MAINTAINER, msg, package.getDetailsURL(), package)
severity = AuditSeverity.NORMAL if current_user == package.author else AuditSeverity.MODERATION
addAuditLog(severity, current_user, msg, package.getDetailsURL(), package)
@ -515,7 +515,7 @@ def remove_self_maintainers(package):
else:
package.maintainers.remove(current_user)
addNotification(package.author, current_user,
addNotification(package.author, current_user, NotificationType.MAINTAINER,
"Removed themself as a maintainer of {}".format(package.title), package.getDetailsURL(), package)
db.session.commit()
@ -537,7 +537,7 @@ def update_from_release(package):
return redirect(package.getDetailsURL())
msg = "Updated meta from latest release"
addNotification(package.maintainers, current_user,
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT,
msg, package.getDetailsURL(), package)
severity = AuditSeverity.NORMAL if current_user in package.maintainers else AuditSeverity.EDITOR
addAuditLog(severity, current_user, msg, package.getDetailsURL(), package)

View File

@ -90,7 +90,7 @@ def create_release(package):
makeVCSRelease.apply_async((rel.id, form["vcsLabel"].data), task_id=rel.task_id)
msg = "Release {} created".format(rel.title)
addNotification(package.maintainers, current_user, msg, rel.getEditURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT, msg, rel.getEditURL(), package)
db.session.commit()
return redirect(url_for("tasks.check", id=rel.task_id, r=rel.getEditURL()))
@ -111,7 +111,7 @@ def create_release(package):
updateMetaFromRelease.delay(rel.id, uploadedPath)
msg = "Release {} created".format(rel.title)
addNotification(package.maintainers, current_user, msg, rel.getEditURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT, msg, rel.getEditURL(), package)
db.session.commit()
return redirect(url_for("tasks.check", id=rel.task_id, r=rel.getEditURL()))

View File

@ -21,7 +21,7 @@ from flask_login import current_user, login_required
from flask_wtf import FlaskForm
from wtforms import *
from wtforms.validators import *
from app.models import db, PackageReview, Thread, ThreadReply
from app.models import db, PackageReview, Thread, ThreadReply, NotificationType
from app.utils import is_package_page, addNotification, get_int_or_abort
@ -98,13 +98,15 @@ def review(package):
package.recalcScore()
notif_msg = None
if was_new:
notif_msg = "New review '{}'".format(form.title.data)
type = NotificationType.NEW_REVIEW
else:
notif_msg = "Updated review '{}'".format(form.title.data)
type = NotificationType.OTHER
addNotification(package.maintainers, current_user, notif_msg, url_for("threads.view", id=thread.id), package)
addNotification(package.maintainers, current_user, type, notif_msg,
url_for("threads.view", id=thread.id), package)
db.session.commit()
@ -133,7 +135,7 @@ def delete_review(package):
thread.review = None
notif_msg = "Deleted review '{}', comments were kept as a thread".format(thread.title)
addNotification(package.maintainers, current_user, notif_msg, url_for("threads.view", id=thread.id), package)
addNotification(package.maintainers, current_user, NotificationType.OTHER, notif_msg, url_for("threads.view", id=thread.id), package)
db.session.delete(review)
db.session.commit()

View File

@ -59,7 +59,7 @@ def create_screenshot(package):
msg = "Screenshot added {}" \
.format(ss.title)
addNotification(package.maintainers, current_user, msg, package.getDetailsURL(), package)
addNotification(package.maintainers, current_user, NotificationType.PACKAGE_EDIT, msg, package.getDetailsURL(), package)
db.session.commit()
return redirect(package.getDetailsURL())

View File

@ -97,8 +97,8 @@ def set_lock(id):
msg = "Unlocked thread '{}'".format(thread.title)
flash("Unlocked thread", "success")
addNotification(thread.watchers, current_user, msg, thread.getViewURL(), thread.package)
addAuditLog(AuditSeverity.MODERATION, current_user, msg, thread.getViewURL(), thread.package)
addNotification(thread.watchers, current_user, NotificationType.OTHER, msg, thread.getViewURL(), thread.package)
addAuditLog(AuditSeverity.MODERATION, current_user, NotificationType.OTHER, msg, thread.getViewURL(), thread.package)
db.session.commit()
@ -168,7 +168,7 @@ def edit_reply(id):
msg = "Edited reply by {}".format(reply.author.display_name)
severity = AuditSeverity.NORMAL if current_user == reply.author else AuditSeverity.MODERATION
addNotification(reply.author, current_user, msg, thread.getViewURL(), thread.package)
addNotification(reply.author, current_user, NotificationType.OTHER, msg, thread.getViewURL(), thread.package)
addAuditLog(severity, current_user, msg, thread.getViewURL(), thread.package, reply.comment)
reply.comment = comment
@ -208,7 +208,7 @@ def view(id):
thread.watchers.append(current_user)
msg = "New comment on '{}'".format(thread.title)
addNotification(thread.watchers, current_user, msg, thread.getViewURL(), thread.package)
addNotification(thread.watchers, current_user, NotificationType.THREAD_REPLY, msg, thread.getViewURL(), thread.package)
db.session.commit()
return redirect(thread.getViewURL())
@ -302,10 +302,10 @@ def new():
notif_msg = "New thread '{}'".format(thread.title)
if package is not None:
addNotification(package.maintainers, current_user, notif_msg, thread.getViewURL(), package)
addNotification(package.maintainers, current_user, NotificationType.NEW_THREAD, notif_msg, thread.getViewURL(), package)
editors = User.query.filter(User.rank >= UserRank.EDITOR).all()
addNotification(editors, current_user, notif_msg, thread.getViewURL(), package)
addNotification(editors, current_user, NotificationType.EDITOR_MISC, notif_msg, thread.getViewURL(), package)
db.session.commit()

View File

@ -274,6 +274,53 @@ class UserEmailVerification(db.Model):
is_password_reset = db.Column(db.Boolean, nullable=False, default=False)
class NotificationType(enum.Enum):
# Any other
OTHER = 0
# Package / release / etc
PACKAGE_EDIT = 1
# Approval review actions
PACKAGE_APPROVAL = 2
# New thread
NEW_THREAD = 3
# New Review
NEW_REVIEW = 4
# Posted reply to subscribed thread
THREAD_REPLY = 5
# Added / removed as maintainer
MAINTAINER = 6
# Editor misc
EDITOR_ALERT = 7
# Editor misc
EDITOR_MISC = 8
def getTitle(self):
return self.name.replace("_", " ").title()
def toName(self):
return self.name.lower()
def __str__(self):
return self.name
@classmethod
def choices(cls):
return [(choice, choice.getTitle()) for choice in cls]
@classmethod
def coerce(cls, item):
return item if type(item) == NotificationType else NotificationType[item]
class Notification(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -283,6 +330,10 @@ class Notification(db.Model):
causer_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
causer = db.relationship("User", foreign_keys=[causer_id])
type = db.Column(db.Enum(NotificationType), nullable=False, default=NotificationType.OTHER)
emailed = db.Column(db.Boolean(), nullable=False, default=False)
title = db.Column(db.String(100), nullable=False)
url = db.Column(db.String(200), nullable=True)
@ -291,12 +342,13 @@ class Notification(db.Model):
created_at = db.Column(db.DateTime, nullable=True, default=datetime.datetime.utcnow)
def __init__(self, user, causer, title, url, package=None):
def __init__(self, user, causer, type, title, url, package=None):
if len(title) > 100:
title = title[:99] + ""
self.user = user
self.causer = causer
self.type = type
self.title = title
self.url = url
self.package = package

View File

@ -235,18 +235,18 @@ def is_package_page(f):
return decorated_function
def addNotification(target, causer, title, url, package=None):
def addNotification(target: User, causer: User, type: NotificationType, title: str, url: str, package: Package =None):
try:
iter(target)
for x in target:
addNotification(x, causer, title, url, package)
addNotification(x, causer, type, title, url, package)
return
except TypeError:
pass
if target.rank.atLeast(UserRank.NEW_MEMBER) and target != causer:
Notification.query.filter_by(user=target, causer=causer, title=title, url=url, package=package).delete()
notif = Notification(target, causer, title, url, package)
Notification.query.filter_by(user=target, causer=causer, type=type, title=title, url=url, package=package).delete()
notif = Notification(target, causer, type, title, url, package)
db.session.add(notif)

View File

@ -0,0 +1,31 @@
"""empty message
Revision ID: 81de25b72f66
Revises: c154912eaa0c
Create Date: 2020-12-05 03:38:42.004388
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
from sqlalchemy.dialects import postgresql
revision = '81de25b72f66'
down_revision = 'c154912eaa0c'
branch_labels = None
depends_on = None
def upgrade():
status = postgresql.ENUM('OTHER', 'PACKAGE_EDIT', 'PACKAGE_APPROVAL', 'NEW_THREAD', 'NEW_REVIEW', 'THREAD_REPLY', 'MAINTAINER', 'EDITOR_ALERT', 'EDITOR_MISC', name='notificationtype')
status.create(op.get_bind())
op.add_column('notification', sa.Column('emailed', sa.Boolean(), nullable=False, server_default="true"))
op.add_column('notification', sa.Column('type', sa.Enum('OTHER', 'PACKAGE_EDIT', 'PACKAGE_APPROVAL', 'NEW_THREAD', 'NEW_REVIEW', 'THREAD_REPLY', 'MAINTAINER', 'EDITOR_ALERT', 'EDITOR_MISC', name='notificationtype'), nullable=False, server_default="OTHER"))
def downgrade():
op.drop_column('notification', 'type')
op.drop_column('notification', 'emailed')