From 0ce78d546a2ec888575e0a223ed77e4f340e06a4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 3 Sep 2023 21:25:30 +0000 Subject: [PATCH] subscribe to default relay unless disabled in config --- boofilsic/settings.py | 9 ++++++ common/setup.py | 47 +++++++++++++++++++++++++++++ docker-compose.yml | 1 + takahe/migrations/0001_initial.py | 23 ++++++++++++++ takahe/utils.py | 4 +++ users/management/commands/invite.py | 33 ++++++++++++++++++++ 6 files changed, 117 insertions(+) create mode 100644 users/management/commands/invite.py diff --git a/boofilsic/settings.py b/boofilsic/settings.py index 9457f6c0..cd61aceb 100644 --- a/boofilsic/settings.py +++ b/boofilsic/settings.py @@ -91,8 +91,15 @@ SETUP_ADMIN_USERNAMES = [ u for u in os.environ.get("NEODB_ADMIN_USERNAMES", "").split(",") if u ] +# True: user will not be able to register unless with invite token (generated by `neodb-manage invite --create`) INVITE_ONLY = os.environ.get("NEODB_INVITE_ONLY", "") != "" +# By default, NeoDB will relay with relay.neodb.net so that public user ratings/etc can be shared across instances +# If you are running a development server, set this to True to disable this behavior +DISABLE_DEFAULT_RELAY = ( + os.environ.get("NEODB_DISABLE_DEFAULT_RELAY", "1" if DEBUG else "") != "" +) + # Mastodon/Pleroma instance allowed to login, keep empty to allow any instance to login MASTODON_ALLOWED_SITES = [] @@ -430,3 +437,5 @@ OAUTH2_PROVIDER = { OAUTH2_PROVIDER_APPLICATION_MODEL = "developer.Application" DEVELOPER_CONSOLE_APPLICATION_CLIENT_ID = "NEODB_DEVELOPER_CONSOLE" + +DEFAULT_RELAY_SERVER = "https://relay.neodb.net/actor" diff --git a/common/setup.py b/common/setup.py index 24abc6ce..8b23fcd5 100644 --- a/common/setup.py +++ b/common/setup.py @@ -4,8 +4,10 @@ from loguru import logger from catalog.search.typesense import Indexer from takahe.models import Config as TakaheConfig from takahe.models import Domain as TakaheDomain +from takahe.models import Follow as TakaheFollow from takahe.models import Identity as TakaheIdentity from takahe.models import User as TakaheUser +from takahe.utils import Takahe from users.models import User @@ -90,6 +92,48 @@ class Setup: TakaheUser.objects.filter(email=f"@{user.username}").update(admin=True) logger.info(f"Updated user {user.username} as admin") + def sync_relay(self): + relay_follow = TakaheFollow.objects.filter( + source__username="__relay__", + source__local=True, + target__actor_uri=settings.DEFAULT_RELAY_SERVER, + ).first() + if settings.DISABLE_DEFAULT_RELAY: + if relay_follow: + logger.info("Default relay is disabled, unsubscribing...") + Takahe.create_internal_message( + { + "type": "UnfollowRelay", + "actor_uri": settings.DEFAULT_RELAY_SERVER, + } + ) + else: + logger.debug(f"Default relay is disabled.") + else: + if relay_follow: + logger.debug( + f"Default relay is enabled and subscribed, state: {relay_follow.state}" + ) + else: + logger.info("Default relay is enabled, subscribing...") + relay_actor = TakaheIdentity.objects.filter( + username="__relay__", + local=True, + ).first() + if not relay_actor: + logger.warning( + f"Default relay is enabled but relay actor does not exist." + ) + return + Takahe.create_internal_message( + { + "type": "AddFollow", + "source": relay_actor.pk, + "target_actor": settings.DEFAULT_RELAY_SERVER, + "boosts": False, + } + ) + def run(self): logger.info("Running post-migration setup...") # Update site name if changed @@ -98,6 +142,9 @@ class Setup: # Create/update admin user if configured in env self.sync_admin_user() + # Subscribe to default relay if enabled + self.sync_relay() + # Create basic emoji if not exists # Create search index if not exists diff --git a/docker-compose.yml b/docker-compose.yml index ca79bb49..44505e3c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,7 @@ x-shared: NEODB_SECRET_KEY: NEODB_ADMIN_USERNAMES: NEODB_INVITE_ONLY: + NEODB_DISABLE_DEFAULT_RELAY: NEODB_DB_NAME: neodb NEODB_DB_USER: neodb NEODB_DB_PASSWORD: aubergine diff --git a/takahe/migrations/0001_initial.py b/takahe/migrations/0001_initial.py index b7c8e206..842280d6 100644 --- a/takahe/migrations/0001_initial.py +++ b/takahe/migrations/0001_initial.py @@ -602,4 +602,27 @@ class Migration(migrations.Migration): "unique_together": {("key", "user", "identity", "domain")}, }, ), + migrations.CreateModel( + name="Invite", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("token", models.CharField(max_length=500, unique=True)), + ("note", models.TextField(blank=True, null=True)), + ("uses", models.IntegerField(blank=True, null=True)), + ("expires", models.DateTimeField(blank=True, null=True)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), + ], + options={ + "db_table": "users_invite", + }, + ), ] diff --git a/takahe/utils.py b/takahe/utils.py index 34931d02..3c3975ca 100644 --- a/takahe/utils.py +++ b/takahe/utils.py @@ -130,6 +130,10 @@ class Takahe: username__iexact=username, domain__domain__iexact=domain ).first() + @staticmethod + def create_internal_message(message: dict): + InboxMessage.create_internal(message) + @staticmethod def fetch_remote_identity(handler: str) -> int | None: InboxMessage.create_internal({"type": "FetchIdentity", "handle": handler}) diff --git a/users/management/commands/invite.py b/users/management/commands/invite.py new file mode 100644 index 00000000..a61e6b86 --- /dev/null +++ b/users/management/commands/invite.py @@ -0,0 +1,33 @@ +from datetime import timedelta + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.urls import reverse +from django.utils import timezone +from loguru import logger + +from takahe.utils import Invite + + +class Command(BaseCommand): + help = "Manage invite" + + def add_arguments(self, parser): + parser.add_argument( + "--create", + action="store_true", + ) + # parser.add_argument( + # "--revoke", + # action="store_true", + # ) + + def handle(self, *args, **options): + if options["create"]: + inv = Invite.create_random() + self.stdout.write(self.style.SUCCESS(f"Invite created: {inv.token}")) + self.stdout.write( + self.style.SUCCESS( + f"Link: {settings.SITE_INFO['site_url']}{reverse('users:login')}?invite={inv.token}" + ) + )