From 4293bba5ab5916a9518bbb5ab9ac0314420ecebb Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 8 Jan 2021 18:53:01 +0100 Subject: [PATCH] add edu upgrade to User admin page --- app/admin_model.py | 64 +++++++++++++++++++++++++++++++++++++++++++++- app/models.py | 29 +++++++++++++++++++++ server.py | 16 ++++++++---- 3 files changed, 103 insertions(+), 6 deletions(-) diff --git a/app/admin_model.py b/app/admin_model.py index f4f436c6..954d5574 100644 --- a/app/admin_model.py +++ b/app/admin_model.py @@ -1,10 +1,21 @@ -from flask import redirect, url_for, request +import arrow +from flask import redirect, url_for, request, flash from flask_admin import expose, AdminIndexView +from flask_admin.actions import action from flask_admin.contrib import sqla from flask_login import current_user +from app.models import User, ManualSubscription + class SLModelView(sqla.ModelView): + column_default_sort = ("id", True) + + can_edit = False + can_create = False + can_delete = False + edit_modal = True + def is_accessible(self): return current_user.is_authenticated and current_user.is_admin @@ -20,3 +31,54 @@ class SLAdminIndexView(AdminIndexView): return redirect(url_for("auth.login", next=request.url)) return super(SLAdminIndexView, self).index() + + +class UserAdmin(SLModelView): + column_searchable_list = ["email", "id"] + column_exclude_list = [ + "salt", + "password", + "otp_secret", + "last_otp", + "fido_uuid", + "profile_picture", + ] + can_edit = True + + def scaffold_list_columns(self): + ret = super().scaffold_list_columns() + ret.insert(0, "upgrade_channel") + return ret + + @action( + "education_upgrade", + "Education upgrade", + "Are you sure you want to edu-upgrade selected users?", + ) + def action_edu_upgrade(self, ids): + query = User.query.filter(User.id.in_(ids)) + + for user in query.all(): + if user.is_premium() and not user.in_trial(): + continue + + ManualSubscription.create( + user_id=user.id, + end_at=arrow.now().shift(years=1, days=1), + comment="Edu", + is_giveaway=True, + commit=True, + ) + + flash(f"{user} is edu upgraded") + + +class EmailLogAdmin(SLModelView): + column_searchable_list = ["id", "user.email", "contact.website_email"] + + can_edit = False + can_create = False + + +class AliasAdmin(SLModelView): + column_searchable_list = ["id", "user.email", "email", "mailbox.email"] diff --git a/app/models.py b/app/models.py index 00a537bd..c7157443 100644 --- a/app/models.py +++ b/app/models.py @@ -440,6 +440,35 @@ class User(db.Model, ModelMixin, UserMixin): return False + @property + def upgrade_channel(self) -> str: + if self.lifetime: + return "Lifetime" + + sub: Subscription = self.get_subscription() + if sub: + return "Paddle Subscription" + + apple_sub: AppleSubscription = AppleSubscription.get_by(user_id=self.id) + if apple_sub and apple_sub.is_valid(): + return "Apple Subscription" + + manual_sub: ManualSubscription = ManualSubscription.get_by(user_id=self.id) + if manual_sub and manual_sub.is_active(): + mode = "Giveaway" if manual_sub.is_giveaway else "Paid" + return f"Manual Subscription {manual_sub.comment} {mode}" + + coinbase_subscription: CoinbaseSubscription = CoinbaseSubscription.get_by( + user_id=self.id + ) + if coinbase_subscription and coinbase_subscription.is_active(): + return "Coinbase Subscription" + + if self.trial_end and arrow.now() < self.trial_end: + return "In Trial" + + return "N/A" + def can_create_new_alias(self) -> bool: if self.is_premium(): return True diff --git a/server.py b/server.py index bea8f00b..fa6e0b87 100644 --- a/server.py +++ b/server.py @@ -27,7 +27,13 @@ from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration from werkzeug.middleware.proxy_fix import ProxyFix from app import paddle_utils -from app.admin_model import SLModelView, SLAdminIndexView +from app.admin_model import ( + SLModelView, + SLAdminIndexView, + UserAdmin, + EmailLogAdmin, + AliasAdmin, +) from app.api.base import api_bp from app.auth.base import auth_bp from app.config import ( @@ -81,6 +87,7 @@ from app.models import ( AliasMailbox, Notification, CoinbaseSubscription, + EmailLog, ) from app.monitor.base import monitor_bp from app.oauth.base import oauth_bp @@ -737,10 +744,9 @@ def init_admin(app): admin = Admin(name="SimpleLogin", template_mode="bootstrap3") admin.init_app(app, index_view=SLAdminIndexView()) - admin.add_view(SLModelView(User, db.session)) - admin.add_view(SLModelView(Client, db.session)) - admin.add_view(SLModelView(Alias, db.session)) - admin.add_view(SLModelView(ClientUser, db.session)) + admin.add_view(UserAdmin(User, db.session)) + admin.add_view(AliasAdmin(Alias, db.session)) + admin.add_view(EmailLogAdmin(EmailLog, db.session)) def setup_do_not_track(app):