diff options
Diffstat (limited to 'users')
| -rw-r--r-- | users/migrations/0005_follow_state_locked_until_follow_state_ready.py | 23 | ||||
| -rw-r--r-- | users/models/__init__.py | 4 | ||||
| -rw-r--r-- | users/models/domain.py | 2 | ||||
| -rw-r--r-- | users/models/follow.py | 14 | ||||
| -rw-r--r-- | users/models/identity.py | 16 | ||||
| -rw-r--r-- | users/shortcuts.py | 9 | ||||
| -rw-r--r-- | users/views/identity.py | 6 | 
7 files changed, 53 insertions, 21 deletions
| diff --git a/users/migrations/0005_follow_state_locked_until_follow_state_ready.py b/users/migrations/0005_follow_state_locked_until_follow_state_ready.py new file mode 100644 index 0000000..3aba08e --- /dev/null +++ b/users/migrations/0005_follow_state_locked_until_follow_state_ready.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.3 on 2022-11-10 03:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + +    dependencies = [ +        ("users", "0004_remove_follow_state_locked_and_more"), +    ] + +    operations = [ +        migrations.AddField( +            model_name="follow", +            name="state_locked_until", +            field=models.DateTimeField(blank=True, null=True), +        ), +        migrations.AddField( +            model_name="follow", +            name="state_ready", +            field=models.BooleanField(default=False), +        ), +    ] diff --git a/users/models/__init__.py b/users/models/__init__.py index e1877bc..d46003f 100644 --- a/users/models/__init__.py +++ b/users/models/__init__.py @@ -1,6 +1,6 @@  from .block import Block  # noqa  from .domain import Domain  # noqa -from .follow import Follow  # noqa -from .identity import Identity  # noqa +from .follow import Follow, FollowStates  # noqa +from .identity import Identity, IdentityStates  # noqa  from .user import User  # noqa  from .user_event import UserEvent  # noqa diff --git a/users/models/domain.py b/users/models/domain.py index 8467ac3..4ac6ee9 100644 --- a/users/models/domain.py +++ b/users/models/domain.py @@ -55,7 +55,7 @@ class Domain(models.Model):              return cls.objects.create(domain=domain, local=False)      @classmethod -    def get_local_domain(cls, domain: str) -> Optional["Domain"]: +    def get_domain(cls, domain: str) -> Optional["Domain"]:          try:              return cls.objects.get(                  models.Q(domain=domain) | models.Q(service_domain=domain) diff --git a/users/models/follow.py b/users/models/follow.py index 04f90ee..3325a0b 100644 --- a/users/models/follow.py +++ b/users/models/follow.py @@ -6,13 +6,13 @@ from stator.models import State, StateField, StateGraph, StatorModel  class FollowStates(StateGraph): -    pending = State(try_interval=3600) +    pending = State(try_interval=30)      requested = State()      accepted = State()      @pending.add_transition(requested) -    async def try_request(cls, instance): -        print("Would have tried to follow") +    async def try_request(instance: "Follow"):  # type:ignore +        print("Would have tried to follow on", instance)          return False      requested.add_manual_transition(accepted) @@ -73,11 +73,3 @@ class Follow(StatorModel):                  follow.state = FollowStates.accepted              follow.save()          return follow - -    def undo(self): -        """ -        Undoes this follow -        """ -        if not self.target.local: -            Task.submit("follow_undo", str(self.pk)) -        self.delete() diff --git a/users/models/identity.py b/users/models/identity.py index 98262bc..5e2cd06 100644 --- a/users/models/identity.py +++ b/users/models/identity.py @@ -14,9 +14,21 @@ from django.utils import timezone  from OpenSSL import crypto  from core.ld import canonicalise +from stator.models import State, StateField, StateGraph, StatorModel  from users.models.domain import Domain +class IdentityStates(StateGraph): +    outdated = State(try_interval=3600) +    updated = State() + +    @outdated.add_transition(updated) +    async def fetch_identity(identity: "Identity"):  # type:ignore +        if identity.local: +            return True +        return await identity.fetch_actor() + +  def upload_namer(prefix, instance, filename):      """      Names uploaded images etc. @@ -26,7 +38,7 @@ def upload_namer(prefix, instance, filename):      return f"{prefix}/{now.year}/{now.month}/{now.day}/{filename}" -class Identity(models.Model): +class Identity(StatorModel):      """      Represents both local and remote Fediverse identities (actors)      """ @@ -35,6 +47,8 @@ class Identity(models.Model):      # one around as well for making nice URLs etc.      actor_uri = models.CharField(max_length=500, unique=True) +    state = StateField(IdentityStates) +      local = models.BooleanField()      users = models.ManyToManyField("users.User", related_name="identities") diff --git a/users/shortcuts.py b/users/shortcuts.py index 65206a3..3e7618a 100644 --- a/users/shortcuts.py +++ b/users/shortcuts.py @@ -3,7 +3,7 @@ from django.http import Http404  from users.models import Domain, Identity -def by_handle_or_404(request, handle, local=True, fetch=False): +def by_handle_or_404(request, handle, local=True, fetch=False) -> Identity:      """      Retrieves an Identity by its long or short handle.      Domain-sensitive, so it will understand short handles on alternate domains. @@ -12,14 +12,17 @@ def by_handle_or_404(request, handle, local=True, fetch=False):          if "HTTP_HOST" not in request.META:              raise Http404("No hostname available")          username = handle -        domain_instance = Domain.get_local_domain(request.META["HTTP_HOST"]) +        domain_instance = Domain.get_domain(request.META["HTTP_HOST"])          if domain_instance is None:              raise Http404("No matching domains found")          domain = domain_instance.domain      else:          username, domain = handle.split("@", 1)          # Resolve the domain to the display domain -        domain = Domain.get_local_domain(request.META["HTTP_HOST"]).domain +        domain_instance = Domain.get_domain(domain) +        if domain_instance is None: +            raise Http404("No matching domains found") +        domain = domain_instance.domain      identity = Identity.by_username_and_domain(          username,          domain, diff --git a/users/views/identity.py b/users/views/identity.py index 41c7880..d02505f 100644 --- a/users/views/identity.py +++ b/users/views/identity.py @@ -17,7 +17,7 @@ from core.forms import FormHelper  from core.ld import canonicalise  from core.signatures import HttpSignature  from users.decorators import identity_required -from users.models import Domain, Follow, Identity +from users.models import Domain, Follow, Identity, IdentityStates  from users.shortcuts import by_handle_or_404 @@ -34,7 +34,7 @@ class ViewIdentity(TemplateView):          )          statuses = identity.statuses.all()[:100]          if identity.data_age > settings.IDENTITY_MAX_AGE: -            Task.submit("identity_fetch", identity.handle) +            identity.transition_perform(IdentityStates.outdated)          return {              "identity": identity,              "statuses": statuses, @@ -129,7 +129,7 @@ class CreateIdentity(FormView):      def form_valid(self, form):          username = form.cleaned_data["username"]          domain = form.cleaned_data["domain"] -        domain_instance = Domain.get_local_domain(domain) +        domain_instance = Domain.get_domain(domain)          new_identity = Identity.objects.create(              actor_uri=f"https://{domain_instance.uri_domain}/@{username}@{domain}/actor/",              username=username, | 
