From f77785ba5e2f0ddf928861e46527c4b03347edc4 Mon Sep 17 00:00:00 2001 From: chrisjsimpson Date: Mon, 11 Nov 2024 20:22:26 +0000 Subject: [PATCH 1/3] WIP Fix #1421 as-a-shop-owner-i-can-block-sign-ups-from-email-domains-i-choose --- settings.yaml.example | 4 +++- subscribie/blueprints/admin/__init__.py | 7 +++++++ subscribie/settings.py | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/settings.yaml.example b/settings.yaml.example index d353ad9d..a01f7144 100644 --- a/settings.yaml.example +++ b/settings.yaml.example @@ -73,7 +73,9 @@ SUPPORTED_CURRENCIES: "GBP,USD,EUR" # Anti spam ANTI_SPAM_SHOP_NAMES_MODEL_FULL_PATH: "/path/to/classifier.pkl" - +SUSPECTED_SPAM_EMAIL_DOMAINS: + - example.com + - mailfence.com # Optional TELEGRAM_TOKEN: diff --git a/subscribie/blueprints/admin/__init__.py b/subscribie/blueprints/admin/__init__.py index 96855bb5..64933c70 100644 --- a/subscribie/blueprints/admin/__init__.py +++ b/subscribie/blueprints/admin/__init__.py @@ -992,6 +992,13 @@ def set_stripe_livemode(): @admin.route("/connect/stripe-connect", methods=["GET"]) @login_required def stripe_connect(): + # Verify that shop owner email address is not + # a suspected SUSPECTED_SPAM_EMAIL_DOMAINS + user = User.query.first() + SUSPECTED_SPAM_EMAIL_DOMAINS = settings.get("SUSPECTED_SPAM_EMAIL_DOMAINS") + user_email_domain = user.email.split("@")[1] + if user_email_domain in SUSPECTED_SPAM_EMAIL_DOMAINS: + return "

Please contact support before connecting Stripe, thank you.

" setting = Setting.query.first() shop_activated = setting.shop_activated SERVER_NAME = settings.get("SERVER_NAME") diff --git a/subscribie/settings.py b/subscribie/settings.py index 512bf788..d07e2d31 100644 --- a/subscribie/settings.py +++ b/subscribie/settings.py @@ -1,4 +1,4 @@ -from strictyaml import load, Map, Email, Str, Url, Int, Bool, Regex, CommaSeparated +from strictyaml import load, Map, Email, Str, Url, Int, Bool, Regex, CommaSeparated, Seq import os # Load application settings according to schema @@ -47,6 +47,7 @@ "PUBLIC_KEY": Str(), "SUPPORTED_CURRENCIES": CommaSeparated(Str()), "ANTI_SPAM_SHOP_NAMES_MODEL_FULL_PATH": Str(), + "SUSPECTED_SPAM_EMAIL_DOMAINS": Seq(Str()), "TELEGRAM_TOKEN": Str(), "TELEGRAM_CHAT_ID": Str(), "TELEGRAM_PYTHON_LOG_LEVEL": Str(), From c8893afe58391601d8ef70967ed013813837201c Mon Sep 17 00:00:00 2001 From: chrisjsimpson Date: Mon, 11 Nov 2024 21:40:12 +0000 Subject: [PATCH 2/3] Fix #1421 as an operator I can maintain a list of suspected spam email domains and block them from connecting to a payment provider --- .../abfb5c2f77e6_add_spamemaildomain.py | 34 +++++++++++++++++++ settings.yaml.example | 3 -- subscribie/blueprints/admin/__init__.py | 7 +++- subscribie/models.py | 11 +++++- subscribie/settings.py | 3 +- 5 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 migrations/versions/abfb5c2f77e6_add_spamemaildomain.py diff --git a/migrations/versions/abfb5c2f77e6_add_spamemaildomain.py b/migrations/versions/abfb5c2f77e6_add_spamemaildomain.py new file mode 100644 index 00000000..6e13a089 --- /dev/null +++ b/migrations/versions/abfb5c2f77e6_add_spamemaildomain.py @@ -0,0 +1,34 @@ +"""add SpamEmailDomain + +Revision ID: abfb5c2f77e6 +Revises: abc1ff0c85e0 +Create Date: 2024-11-11 21:27:48.094799 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "abfb5c2f77e6" +down_revision = "abc1ff0c85e0" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "spam_email_domain", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("uuid", sa.String(), nullable=True), + sa.Column("ts", sa.DateTime(), nullable=True), + sa.Column("domain", sa.String(), nullable=True), + sa.Column("archived", sa.Boolean(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint("id"), + ) + + +def downgrade(): + pass diff --git a/settings.yaml.example b/settings.yaml.example index a01f7144..735f4451 100644 --- a/settings.yaml.example +++ b/settings.yaml.example @@ -73,9 +73,6 @@ SUPPORTED_CURRENCIES: "GBP,USD,EUR" # Anti spam ANTI_SPAM_SHOP_NAMES_MODEL_FULL_PATH: "/path/to/classifier.pkl" -SUSPECTED_SPAM_EMAIL_DOMAINS: - - example.com - - mailfence.com # Optional TELEGRAM_TOKEN: diff --git a/subscribie/blueprints/admin/__init__.py b/subscribie/blueprints/admin/__init__.py index 64933c70..3c398717 100644 --- a/subscribie/blueprints/admin/__init__.py +++ b/subscribie/blueprints/admin/__init__.py @@ -83,6 +83,7 @@ UpcomingInvoice, Document, PlanQuestionAssociation, + SpamEmailDomain, ) from .subscription import ( update_stripe_subscription_statuses, @@ -995,9 +996,13 @@ def stripe_connect(): # Verify that shop owner email address is not # a suspected SUSPECTED_SPAM_EMAIL_DOMAINS user = User.query.first() - SUSPECTED_SPAM_EMAIL_DOMAINS = settings.get("SUSPECTED_SPAM_EMAIL_DOMAINS") + SUSPECTED_SPAM_EMAIL_DOMAINS = [d.domain for d in SpamEmailDomain.query.all()] user_email_domain = user.email.split("@")[1] if user_email_domain in SUSPECTED_SPAM_EMAIL_DOMAINS: + log.error( + f"SUSPECTED_SPAM_EMAIL_DOMAIN {user_email_domain} " + "attempted to connect stripe" + ) return "

Please contact support before connecting Stripe, thank you.

" setting = Setting.query.first() shop_activated = setting.shop_activated diff --git a/subscribie/models.py b/subscribie/models.py index 2bd89763..c94d2734 100644 --- a/subscribie/models.py +++ b/subscribie/models.py @@ -7,7 +7,6 @@ from sqlalchemy import Column from sqlalchemy import Boolean from sqlalchemy import PrimaryKeyConstraint -from sqlalchemy import desc from typing import Optional import datetime @@ -1400,3 +1399,13 @@ class PriceListRule(database.Model, HasCreatedAt): secondary=association_table_price_list_to_rule, back_populates="rules", ) + + +class SpamEmailDomain(database.Model, HasArchived, HasCreatedAt): + __tablename__ = "spam_email_domain" + id = database.Column(database.Integer(), primary_key=True) + uuid = database.Column(database.String(), default=uuid_string) + ts = database.Column( + database.DateTime, default=lambda: datetime.datetime.now(datetime.UTC) + ) + domain = database.Column(database.String()) diff --git a/subscribie/settings.py b/subscribie/settings.py index d07e2d31..512bf788 100644 --- a/subscribie/settings.py +++ b/subscribie/settings.py @@ -1,4 +1,4 @@ -from strictyaml import load, Map, Email, Str, Url, Int, Bool, Regex, CommaSeparated, Seq +from strictyaml import load, Map, Email, Str, Url, Int, Bool, Regex, CommaSeparated import os # Load application settings according to schema @@ -47,7 +47,6 @@ "PUBLIC_KEY": Str(), "SUPPORTED_CURRENCIES": CommaSeparated(Str()), "ANTI_SPAM_SHOP_NAMES_MODEL_FULL_PATH": Str(), - "SUSPECTED_SPAM_EMAIL_DOMAINS": Seq(Str()), "TELEGRAM_TOKEN": Str(), "TELEGRAM_CHAT_ID": Str(), "TELEGRAM_PYTHON_LOG_LEVEL": Str(), From 3c179468315860b54dc1f4e71ce1bef204c7b9e6 Mon Sep 17 00:00:00 2001 From: chrisjsimpson Date: Mon, 11 Nov 2024 21:49:35 +0000 Subject: [PATCH 3/3] bump action/download-artifact @v2 -> @v4 in pr-demo-deploy.yml --- .github/workflows/pr-demo-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-demo-deploy.yml b/.github/workflows/pr-demo-deploy.yml index 01052084..04bc5830 100644 --- a/.github/workflows/pr-demo-deploy.yml +++ b/.github/workflows/pr-demo-deploy.yml @@ -124,7 +124,7 @@ jobs: cd tests/browser-automated-tests-playwright python3 run-playwright-tests.py - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 if: ${{ always() }} with: name: Screenshots-and-video-artifacts