From b4208f2dda07ab988e99226c044e34b89894c92c Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Tue, 23 Aug 2022 02:24:12 +0100 Subject: [PATCH] Reintroduce New Member rank Fixes #183 --- app/__init__.py | 2 +- app/blueprints/admin/actions.py | 15 +++++++++++++-- app/models/packages.py | 6 +++--- app/models/threads.py | 2 +- app/models/users.py | 14 +++++++++----- app/tasks/__init__.py | 6 +++++- app/tasks/usertasks.py | 27 +++++++++++++++++++++------ app/utils/user.py | 2 +- 8 files changed, 54 insertions(+), 20 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 8cdbc45a..ce09c1e3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -119,7 +119,7 @@ def check_for_ban(): logout_user() return redirect(url_for("users.login")) elif current_user.rank == models.UserRank.NOT_JOINED: - current_user.rank = models.UserRank.MEMBER + current_user.rank = models.UserRank.NEW_MEMBER models.db.session.commit() diff --git a/app/blueprints/admin/actions.py b/app/blueprints/admin/actions.py index 51e31db7..f2e5394c 100644 --- a/app/blueprints/admin/actions.py +++ b/app/blueprints/admin/actions.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +import datetime import os from typing import List @@ -25,7 +25,7 @@ from sqlalchemy import or_, and_ from app.logic.game_support import GameSupportResolver from app.models import PackageRelease, db, Package, PackageState, PackageScreenshot, MetaPackage, User, \ - NotificationType, PackageUpdateConfig, License, UserRank, PackageType, PackageGameSupport + NotificationType, PackageUpdateConfig, License, UserRank, PackageType, PackageGameSupport, ThreadReply from app.tasks.emails import send_pending_digests from app.tasks.forumtasks import importTopicList, checkAllForumAccounts from app.tasks.importtasks import importRepoScreenshot, checkZipRelease, check_for_updates, updateAllGameSupport @@ -335,3 +335,14 @@ def detect_game_support(): @action("Send pending notif digests") def do_send_pending_digests(): send_pending_digests.delay() + + +@action("Set users to new member") +def set_new_members(): + threshold = datetime.datetime.now() - datetime.timedelta(days=7) + + User.query.filter(User.rank == UserRank.MEMBER, + ~User.replies.any(ThreadReply.created_at < threshold), + ~User.packages.any(Package.approved_at < threshold)).update({"rank": UserRank.NEW_MEMBER}, synchronize_session=False) + + db.session.commit() diff --git a/app/models/packages.py b/app/models/packages.py index 55656e52..a52c7281 100644 --- a/app/models/packages.py +++ b/app/models/packages.py @@ -666,14 +666,14 @@ class Package(db.Model): isApprover = user.rank.atLeast(UserRank.APPROVER) if perm == Permission.CREATE_THREAD: - return user.rank.atLeast(UserRank.MEMBER) + return user.rank.atLeast(UserRank.NEW_MEMBER) # Members can edit their own packages, and editors can edit any packages elif perm == Permission.MAKE_RELEASE or perm == Permission.ADD_SCREENSHOTS: return isMaintainer elif perm == Permission.EDIT_PACKAGE: - return isMaintainer and user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER) + return isMaintainer and user.rank.atLeast(UserRank.NEW_MEMBER) elif perm == Permission.APPROVE_RELEASE: return (isMaintainer or isApprover) and user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER) @@ -688,7 +688,7 @@ class Package(db.Model): elif perm == Permission.APPROVE_SCREENSHOT: return (isMaintainer or isApprover) and \ - user.rank.atLeast(UserRank.TRUSTED_MEMBER if self.approved else UserRank.NEW_MEMBER) + user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER) elif perm == Permission.EDIT_MAINTAINERS or perm == Permission.DELETE_PACKAGE: return isOwner or user.rank.atLeast(UserRank.EDITOR) diff --git a/app/models/threads.py b/app/models/threads.py index a344aefc..95e87dae 100644 --- a/app/models/threads.py +++ b/app/models/threads.py @@ -153,7 +153,7 @@ class ThreadReply(db.Model): raise Exception("Unknown permission given to ThreadReply.checkPerm()") if perm == Permission.EDIT_REPLY: - return user.rank.atLeast(UserRank.MEMBER if user == self.author else UserRank.MODERATOR) and not self.thread.locked + return user.rank.atLeast(UserRank.NEW_MEMBER if user == self.author else UserRank.MODERATOR) and not self.thread.locked elif perm == Permission.DELETE_REPLY: return user.rank.atLeast(UserRank.MODERATOR) and self.thread.replies[0] != self diff --git a/app/models/users.py b/app/models/users.py index a6846098..3a815206 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -227,7 +227,7 @@ class User(db.Model, UserMixin): elif perm == Permission.CHANGE_EMAIL or perm == Permission.CHANGE_PROFILE_URLS: return user == self or (user.rank.atLeast(UserRank.MODERATOR) and not self.rank.atLeast(user.rank)) elif perm == Permission.CHANGE_DISPLAY_NAME: - return user.rank.atLeast(UserRank.MEMBER if user == self else UserRank.MODERATOR) + return user.rank.atLeast(UserRank.NEW_MEMBER if user == self else UserRank.MODERATOR) elif perm == Permission.CREATE_TOKEN: if user == self: return user.rank.atLeast(UserRank.MEMBER) @@ -243,16 +243,18 @@ class User(db.Model, UserMixin): if self.rank.atLeast(UserRank.ADMIN): return True elif self.rank.atLeast(UserRank.TRUSTED_MEMBER): - factor *= 2 + factor = 3 + elif self.rank.atLeast(UserRank.MEMBER): + factor = 2 one_min_ago = datetime.datetime.utcnow() - datetime.timedelta(minutes=1) if ThreadReply.query.filter_by(author=self) \ - .filter(ThreadReply.created_at > one_min_ago).count() >= 3 * factor: + .filter(ThreadReply.created_at > one_min_ago).count() >= 2 * factor: return False hour_ago = datetime.datetime.utcnow() - datetime.timedelta(hours=1) if ThreadReply.query.filter_by(author=self) \ - .filter(ThreadReply.created_at > hour_ago).count() >= 20 * factor: + .filter(ThreadReply.created_at > hour_ago).count() >= 10 * factor: return False return True @@ -264,7 +266,9 @@ class User(db.Model, UserMixin): if self.rank.atLeast(UserRank.ADMIN): return True elif self.rank.atLeast(UserRank.TRUSTED_MEMBER): - factor *= 5 + factor = 5 + elif self.rank.atLeast(UserRank.MEMBER): + factor = 2 hour_ago = datetime.datetime.utcnow() - datetime.timedelta(hours=1) return Thread.query.filter_by(author=self) \ diff --git a/app/tasks/__init__.py b/app/tasks/__init__.py index c945bd9b..c80fd349 100644 --- a/app/tasks/__init__.py +++ b/app/tasks/__init__.py @@ -76,7 +76,7 @@ CELERYBEAT_SCHEDULE = { }, 'check_for_updates': { 'task': 'app.tasks.importtasks.check_for_updates', - 'schedule': crontab(minute=10, hour=1), # 0110 + 'schedule': crontab(minute=10, hour=2), # 0210 }, 'send_pending_notifications': { 'task': 'app.tasks.emails.send_pending_notifications', @@ -90,6 +90,10 @@ CELERYBEAT_SCHEDULE = { 'task': 'app.tasks.usertasks.delete_inactive_users', 'schedule': crontab(minute=15), # every hour at quarter past }, + 'upgrade_new_members': { + 'task': 'app.tasks.usertasks.upgrade_new_members', + 'schedule': crontab(minute=10, hour=3), # 0310 + }, } celery.conf.beat_schedule = CELERYBEAT_SCHEDULE diff --git a/app/tasks/usertasks.py b/app/tasks/usertasks.py index f15c7281..ccc6338b 100644 --- a/app/tasks/usertasks.py +++ b/app/tasks/usertasks.py @@ -16,16 +16,31 @@ import datetime -from app.models import User, db, UserRank + +from sqlalchemy import or_, and_ + +from app.models import User, db, UserRank, ThreadReply, Package from app.tasks import celery @celery.task() def delete_inactive_users(): - threshold = datetime.datetime.now() - datetime.timedelta(hours=5) + threshold = datetime.datetime.now() - datetime.timedelta(hours=5) - users = User.query.filter(User.is_active==False, User.packages==None, User.forum_topics==None, User.created_at<=threshold, User.rank==UserRank.NOT_JOINED).all() - for user in users: - db.session.delete(user) + users = User.query.filter(User.is_active == False, User.packages == None, User.forum_topics == None, + User.created_at <= threshold, User.rank == UserRank.NOT_JOINED).all() + for user in users: + db.session.delete(user) - db.session.commit() + db.session.commit() + + +@celery.task() +def upgrade_new_members(): + threshold = datetime.datetime.now() - datetime.timedelta(days=7) + + User.query.filter(and_(User.rank == UserRank.NEW_MEMBER, or_( + User.replies.any(ThreadReply.created_at < threshold), + User.packages.any(Package.approved_at < threshold)))).update({"rank": UserRank.MEMBER}) + + db.session.commit() diff --git a/app/utils/user.py b/app/utils/user.py index 528fd2d2..05768310 100644 --- a/app/utils/user.py +++ b/app/utils/user.py @@ -59,7 +59,7 @@ def post_login(user: User, next_url): def login_user_set_active(user: User, next_url: str = None, *args, **kwargs): if user.rank == UserRank.NOT_JOINED and user.email is None: - user.rank = UserRank.MEMBER + user.rank = UserRank.NEW_MEMBER user.notification_preferences = UserNotificationPreferences(user) user.is_active = True db.session.commit()