diff --git a/app/dashboard/templates/dashboard/billing.html b/app/dashboard/templates/dashboard/billing.html index c3fabb13..e33aec37 100644 --- a/app/dashboard/templates/dashboard/billing.html +++ b/app/dashboard/templates/dashboard/billing.html @@ -13,7 +13,7 @@
- You are on the {{ current_user.plan_name() }} plan. Thank you very much for supporting SimpleLogin. 🙌 + You are on the {{ current_user.get_subscription().plan_name() }} plan. Thank you very much for supporting SimpleLogin. 🙌
{% if sub.cancelled %} diff --git a/app/dashboard/views/custom_alias.py b/app/dashboard/views/custom_alias.py index 250cae09..f1b5d7f2 100644 --- a/app/dashboard/views/custom_alias.py +++ b/app/dashboard/views/custom_alias.py @@ -20,7 +20,10 @@ def custom_alias(): if not current_user.can_create_new_alias(): # notify admin LOG.error("user %s tries to create custom alias", current_user) - flash("ony premium user can choose custom alias", "warning") + flash( + "You have reached free plan limit, please upgrade to create new aliases", + "warning", + ) return redirect(url_for("dashboard.index")) user_custom_domains = [cd.domain for cd in current_user.verified_custom_domains()] diff --git a/app/dashboard/views/lifetime_licence.py b/app/dashboard/views/lifetime_licence.py index 66511abb..e3b6aa3c 100644 --- a/app/dashboard/views/lifetime_licence.py +++ b/app/dashboard/views/lifetime_licence.py @@ -24,7 +24,7 @@ class CouponForm(FlaskForm): @login_required def lifetime_licence(): # sanity check: make sure this page is only for free user - if current_user.is_premium(): + if current_user.lifetime_or_active_subscription(): flash("You are already a premium user", "warning") return redirect(url_for("dashboard.index")) diff --git a/app/dashboard/views/pricing.py b/app/dashboard/views/pricing.py index d29891bc..fcc28919 100644 --- a/app/dashboard/views/pricing.py +++ b/app/dashboard/views/pricing.py @@ -13,8 +13,8 @@ from app.dashboard.base import dashboard_bp @dashboard_bp.route("/pricing", methods=["GET", "POST"]) @login_required def pricing(): - # sanity check: make sure this page is only for free user - if current_user.is_premium(): + # sanity check: make sure this page is only for free or trial user + if not current_user.should_upgrade(): flash("You are already a premium user", "warning") return redirect(url_for("dashboard.index")) diff --git a/app/models.py b/app/models.py index b8a908c3..6061313d 100644 --- a/app/models.py +++ b/app/models.py @@ -124,7 +124,7 @@ class User(db.Model, ModelMixin, UserMixin): # user can use all premium features until this date trial_end = db.Column( - ArrowType, default=lambda: arrow.now().shift(days=7), nullable=True + ArrowType, default=lambda: arrow.now().shift(days=7, hours=1), nullable=True ) profile_picture = db.relationship(File) @@ -146,11 +146,8 @@ class User(db.Model, ModelMixin, UserMixin): return user - def should_upgrade(self): - return not self.is_premium() - - def is_premium(self): - """user is premium if they have a active subscription""" + def lifetime_or_active_subscription(self) -> bool: + """True if user has lifetime licence or active subscription""" if self.lifetime: return True @@ -160,7 +157,29 @@ class User(db.Model, ModelMixin, UserMixin): return False - def can_create_new_alias(self): + def in_trial(self): + """return True if user does not have lifetime licence or an active subscription AND is in trial period""" + if self.lifetime_or_active_subscription(): + return False + + return self.trial_end and arrow.now() < self.trial_end + + def should_upgrade(self): + return not self.lifetime_or_active_subscription() + + def is_premium(self) -> bool: + """ + user is premium if they: + - have a lifetime deal or + - in trial period or + - active subscription + """ + if self.lifetime_or_active_subscription(): + return True + + return self.trial_end and arrow.now() < self.trial_end + + def can_create_new_alias(self) -> bool: if self.is_premium(): return True @@ -202,7 +221,6 @@ class User(db.Model, ModelMixin, UserMixin): def suggested_names(self) -> (str, [str]): """return suggested name and other name choices """ - other_name = convert_to_id(self.name) return self.name, [other_name, "Anonymous", "whoami"] @@ -211,17 +229,6 @@ class User(db.Model, ModelMixin, UserMixin): names = self.name.split(" ") return "".join([n[0].upper() for n in names if n]) - def plan_name(self) -> str: - if self.is_premium(): - sub = self.get_subscription() - - if sub.plan == PlanEnum.monthly: - return "Monthly ($2.99/month)" - else: - return "Yearly ($29.99/year)" - else: - return "Free Plan" - def get_subscription(self): """return *active* subscription TODO: support user unsubscribe and re-subscribe @@ -643,6 +650,12 @@ class Subscription(db.Model, ModelMixin): user = db.relationship(User) + def plan_name(self): + if self.plan == PlanEnum.monthly: + return "Monthly ($2.99/month)" + else: + return "Yearly ($29.99/year)" + class DeletedAlias(db.Model, ModelMixin): """Store all deleted alias to make sure they are NOT reused""" diff --git a/server.py b/server.py index 3848f60b..49391a2a 100644 --- a/server.py +++ b/server.py @@ -381,7 +381,7 @@ def setup_paddle_callback(app: Flask): elif request.form.get("alert_name") == "subscription_cancelled": subscription_id = request.form.get("subscription_id") - LOG.debug("Cancel subscription %s", subscription_id) + LOG.error("Cancel subscription %s", subscription_id) sub: Subscription = Subscription.get_by(subscription_id=subscription_id) if sub: diff --git a/templates/header.html b/templates/header.html index 8e246774..c1e3d471 100644 --- a/templates/header.html +++ b/templates/header.html @@ -25,15 +25,16 @@ {{ current_user.name }} - {% if current_user.is_premium() %} + {% if current_user.in_trial() %} + Trial ends in {{ current_user.trial_end|dt }} + {% elif current_user.lifetime_or_active_subscription() %} Premium {% endif %} +