mirror of
https://github.com/simple-login/app.git
synced 2024-11-16 08:58:30 +01:00
262 lines
7.7 KiB
Python
262 lines
7.7 KiB
Python
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, login_user
|
|
|
|
from app.db import Session
|
|
from app.models import User, ManualSubscription, Fido, Subscription, AppleSubscription
|
|
|
|
|
|
class SLModelView(sqla.ModelView):
|
|
column_default_sort = ("id", True)
|
|
column_display_pk = 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
|
|
|
|
def inaccessible_callback(self, name, **kwargs):
|
|
# redirect to login page if user doesn't have access
|
|
return redirect(url_for("auth.login", next=request.url))
|
|
|
|
|
|
class SLAdminIndexView(AdminIndexView):
|
|
@expose("/")
|
|
def index(self):
|
|
if not current_user.is_authenticated or not current_user.is_admin:
|
|
return redirect(url_for("auth.login", next=request.url))
|
|
|
|
return redirect("/admin/user")
|
|
|
|
|
|
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):
|
|
manual_upgrade("Edu", ids, is_giveaway=True)
|
|
|
|
@action(
|
|
"charity_org_upgrade",
|
|
"Charity Organization upgrade",
|
|
"Are you sure you want to upgrade selected users using the Charity organization program?",
|
|
)
|
|
def action_charity_org_upgrade(self, ids):
|
|
manual_upgrade("Charity Organization", ids, is_giveaway=True)
|
|
|
|
@action(
|
|
"journalist_upgrade",
|
|
"Journalist upgrade",
|
|
"Are you sure you want to upgrade selected users using the Journalist program?",
|
|
)
|
|
def action_journalist_upgrade(self, ids):
|
|
manual_upgrade("Journalist", ids, is_giveaway=True)
|
|
|
|
@action(
|
|
"cash_upgrade",
|
|
"Cash upgrade",
|
|
"Are you sure you want to cash-upgrade selected users?",
|
|
)
|
|
def action_cash_upgrade(self, ids):
|
|
manual_upgrade("Cash", ids, is_giveaway=False)
|
|
|
|
@action(
|
|
"crypto_upgrade",
|
|
"Crypto upgrade",
|
|
"Are you sure you want to crypto-upgrade selected users?",
|
|
)
|
|
def action_monero_upgrade(self, ids):
|
|
manual_upgrade("Crypto", ids, is_giveaway=False)
|
|
|
|
@action(
|
|
"extend_trial_1w",
|
|
"Extend trial for 1 week more",
|
|
"Extend trial for 1 week more?",
|
|
)
|
|
def extend_trial_1w(self, ids):
|
|
for user in User.filter(User.id.in_(ids)):
|
|
if user.trial_end and user.trial_end > arrow.now():
|
|
user.trial_end = user.trial_end.shift(weeks=1)
|
|
else:
|
|
user.trial_end = arrow.now().shift(weeks=1)
|
|
|
|
flash(f"Extend trial for {user} to {user.trial_end}", "success")
|
|
|
|
Session.commit()
|
|
|
|
@action(
|
|
"disable_otp_fido",
|
|
"Disable OTP & FIDO",
|
|
"Disable OTP & FIDO?",
|
|
)
|
|
def disable_otp_fido(self, ids):
|
|
for user in User.filter(User.id.in_(ids)):
|
|
if user.enable_otp:
|
|
user.enable_otp = False
|
|
flash(f"Disable OTP for {user}", "info")
|
|
|
|
if user.fido_uuid:
|
|
Fido.filter_by(uuid=user.fido_uuid).delete()
|
|
user.fido_uuid = None
|
|
flash(f"Disable FIDO for {user}", "info")
|
|
|
|
Session.commit()
|
|
|
|
@action(
|
|
"login_as",
|
|
"Login as this user",
|
|
"Login as this user?",
|
|
)
|
|
def login_as(self, ids):
|
|
if len(ids) != 1:
|
|
flash("only 1 user can be selected", "error")
|
|
return
|
|
|
|
for user in User.filter(User.id.in_(ids)):
|
|
login_user(user)
|
|
flash(f"Login as user {user}", "success")
|
|
return redirect("/")
|
|
|
|
|
|
def manual_upgrade(way: str, ids: [int], is_giveaway: bool):
|
|
for user in User.filter(User.id.in_(ids)).all():
|
|
if user.lifetime:
|
|
flash(f"user {user} already has a lifetime license", "warning")
|
|
continue
|
|
|
|
sub: Subscription = user.get_subscription()
|
|
if sub and not sub.cancelled:
|
|
flash(
|
|
f"user {user} already has a Paddle license, they have to cancel it first",
|
|
"warning",
|
|
)
|
|
continue
|
|
|
|
apple_sub: AppleSubscription = AppleSubscription.get_by(user_id=user.id)
|
|
if apple_sub and apple_sub.is_valid():
|
|
flash(
|
|
f"user {user} already has a Apple subscription, they have to cancel it first",
|
|
"warning",
|
|
)
|
|
continue
|
|
|
|
manual_sub: ManualSubscription = ManualSubscription.get_by(user_id=user.id)
|
|
if manual_sub:
|
|
# renew existing subscription
|
|
if manual_sub.end_at > arrow.now():
|
|
manual_sub.end_at = manual_sub.end_at.shift(years=1)
|
|
else:
|
|
manual_sub.end_at = arrow.now().shift(years=1, days=1)
|
|
Session.commit()
|
|
flash(f"Subscription extended to {manual_sub.end_at.humanize()}", "success")
|
|
continue
|
|
|
|
ManualSubscription.create(
|
|
user_id=user.id,
|
|
end_at=arrow.now().shift(years=1, days=1),
|
|
comment=way,
|
|
is_giveaway=is_giveaway,
|
|
commit=True,
|
|
)
|
|
|
|
flash(f"New {way} manual subscription for {user} is created", "success")
|
|
|
|
|
|
class EmailLogAdmin(SLModelView):
|
|
column_searchable_list = ["id"]
|
|
column_filters = ["id", "user.email", "mailbox.email", "contact.website_email"]
|
|
|
|
can_edit = False
|
|
can_create = False
|
|
|
|
|
|
class AliasAdmin(SLModelView):
|
|
column_searchable_list = ["id", "user.email", "email", "mailbox.email"]
|
|
column_filters = ["id", "user.email", "email", "mailbox.email"]
|
|
|
|
|
|
class MailboxAdmin(SLModelView):
|
|
column_searchable_list = ["id", "user.email", "email"]
|
|
column_filters = ["id", "user.email", "email"]
|
|
|
|
|
|
class LifetimeCouponAdmin(SLModelView):
|
|
can_edit = True
|
|
can_create = True
|
|
|
|
|
|
class CouponAdmin(SLModelView):
|
|
can_edit = True
|
|
can_create = True
|
|
|
|
|
|
class ManualSubscriptionAdmin(SLModelView):
|
|
can_edit = True
|
|
column_searchable_list = ["id", "user.email"]
|
|
|
|
@action(
|
|
"extend_1y",
|
|
"Extend for 1 year",
|
|
"Extend 1 year more?",
|
|
)
|
|
def extend_1y(self, ids):
|
|
for ms in ManualSubscription.filter(ManualSubscription.id.in_(ids)):
|
|
ms.end_at = ms.end_at.shift(years=1)
|
|
flash(f"Extend subscription for {ms.user}", "success")
|
|
|
|
Session.commit()
|
|
|
|
|
|
class ClientAdmin(SLModelView):
|
|
column_searchable_list = ["name", "description", "user.email"]
|
|
column_exclude_list = ["oauth_client_secret", "home_url"]
|
|
can_edit = True
|
|
|
|
|
|
class CustomDomainAdmin(SLModelView):
|
|
column_searchable_list = ["domain", "user.email", "user.id"]
|
|
column_exclude_list = ["ownership_txt_token"]
|
|
can_edit = False
|
|
|
|
|
|
class ReferralAdmin(SLModelView):
|
|
column_searchable_list = ["id", "user.email", "code", "name"]
|
|
column_filters = ["id", "user.email", "code", "name"]
|
|
|
|
def scaffold_list_columns(self):
|
|
ret = super().scaffold_list_columns()
|
|
ret.insert(0, "nb_user")
|
|
ret.insert(0, "nb_paid_user")
|
|
return ret
|
|
|
|
|
|
class PayoutAdmin(SLModelView):
|
|
column_searchable_list = ["id", "user.email"]
|
|
column_filters = ["id", "user.email"]
|
|
can_edit = True
|
|
can_create = True
|
|
can_delete = True
|