# Path: sitegate/models.py
# class InvitationCode(InheritedModel, ModelWithCode):
# 
#     creator = models.ForeignKey(
#         USER_MODEL, related_name='creators', verbose_name=_('Creator'), on_delete=models.CASCADE)
# 
#     acceptor = models.ForeignKey(
#         USER_MODEL, related_name='acceptors', verbose_name=_('Acceptor'), null=True, blank=True,
#         editable=False, on_delete=models.CASCADE)
# 
#     class Meta:
#         verbose_name = _('Invitation code')
#         verbose_name_plural = _('Invitation codes')
# 
#     class Fields:
#         code = _('Invitation code')
#         expired = {'help_text': _('Visitors won\'t be able to sign up with an expired code.')}
# 
#     @classmethod
#     def add(cls, creator: 'User') -> 'InvitationCode':
#         new_code = cls(creator=creator)
#         new_code.save(force_insert=True)
#         return new_code
# 
#     @classmethod
#     def accept(cls, code: str, acceptor: 'User'):
#         return cls.objects.filter(code=code).update(acceptor=acceptor, expired=True, time_accepted=timezone.now())
# 
# class BlacklistedDomain(models.Model):
# 
#     domain = models.CharField(_('Domain name'), max_length=253, unique=True)
# 
#     enabled = models.BooleanField(
#         _('Enabled'),
#         help_text=_('If enabled visitors won\'t be able to sign up with this domain name in e-mail.'),
#         db_index=True, default=True)
# 
#     class Meta:
#         verbose_name = _('Blacklisted domain')
#         verbose_name_plural = _('Blacklisted domains')
# 
#     @classmethod
#     def is_blacklisted(cls, email: str) -> bool:
#         """Checks whether the given e-mail is blacklisted.
# 
#         :param email:
# 
#         """
#         domain = email.split('@', 1)[1].lower()
# 
#         # 'some.denied.co.uk' -> ['some.denied.co.uk', 'denied.co.uk', 'co.uk']
#         sub_domains = [domain]
#         for i in range(domain.count('.') - 1):
#             sub_domains.append(sub_domains[i].split('.', 1)[-1])
# 
#         return cls.objects.filter(enabled=True, domain__in=sub_domains).exists()
# 
#     def __str__(self):
#         return self.domain
# 
# class EmailConfirmation(InheritedModel, ModelWithCode):
# 
#     user = models.ForeignKey(USER_MODEL, verbose_name=_('User'), on_delete=models.CASCADE)
# 
#     class Meta:
#         verbose_name = _('Activation code')
#         verbose_name_plural = _('Activation codes')
# 
#     class Fields:
#         code = _('Activation code')
#         expired = {'help_text': _('Expired codes couldn\'t be used for repeated account activations.')}
# 
#     @classmethod
#     def add(cls, user: 'User') -> 'EmailConfirmation':
#         new_code = cls(user=user)
#         new_code.save(force_insert=True)
#         return new_code
# 
#     def activate(self):
#         self.expired = True
#         self.time_accepted = timezone.now()
#         self.save()
# 
#         user = self.user
#         user.is_active = True
#         user.save()
# 
# class RemoteRecord(ModelWithCode):
#     """Stores data used for sign ins using remote services."""
# 
#     remote = models.CharField(_('Remote alias'), max_length=20, db_index=True)
# 
#     remote_id = models.CharField(
#         _('Remote ID'), null=True, default=None, max_length=64, db_index=True, db_column='rid')
# 
#     user = models.ForeignKey(
#         USER_MODEL, null=True, blank=True,
#         related_name='remotes', verbose_name=_('User'), on_delete=models.CASCADE)
# 
#     expired = None
# 
#     class Meta:
#         verbose_name = _('Remote record')
#         verbose_name_plural = _('Remotes records')
# 
#     def __str__(self):
#         return f'{self.remote} {self.code}'
# 
#     @classmethod
#     def add(cls, *, remote: str, user: Optional['User']) -> 'RemoteRecord':
#         record = cls(
#             remote=remote,
#             user=user,
#         )
#         record.save(force_insert=True)
#         return record
# 
#     @classmethod
#     def cleanup(cls, *, ago: int = None):
#         """Removes remote records not linked to certain user.
#         Useful for periodic background cleaning.
# 
#         :param ago: Days. Allows cleanup for stale records created X days ago.
#             Defaults to None (cleanup all stale).
# 
#         """
#         filter_kwargs = {
#             'remote_id__isnull': True,
#             'user_id__isnull': True,
#         }
# 
#         if ago:
#             filter_kwargs['time_created__lte'] = timezone.now() - timedelta(days=int(ago))
# 
#         cls.objects.filter(**filter_kwargs).delete()


from django.contrib import admin
from .models import InvitationCode, BlacklistedDomain, EmailConfirmation, RemoteRecord



@admin.register(InvitationCode)
class InvitationCodeAdmin(admin.ModelAdmin):

    list_display = ('code', 'time_created', 'time_accepted', 'expired')
    list_display_links = ('code',)
    search_fields = ('code', 'creator', 'acceptor')
    list_filter = ('time_accepted',)
    ordering = ('-time_created',)
    date_hierarchy = 'time_created'
    readonly_fields = ('time_accepted',)
    raw_id_fields = ('creator', 'acceptor')



# Path: sitegate/models.py
# class InvitationCode(InheritedModel, ModelWithCode):
# 
#     creator = models.ForeignKey(
#         USER_MODEL, related_name='creators', verbose_name=_('Creator'), on_delete=models.CASCADE)
# 
#     acceptor = models.ForeignKey(
#         USER_MODEL, related_name='acceptors', verbose_name=_('Acceptor'), null=True, blank=True,
#         editable=False, on_delete=models.CASCADE)
# 
#     class Meta:
#         verbose_name = _('Invitation code')
#         verbose_name_plural = _('Invitation codes')
# 
#     class Fields:
#         code = _('Invitation code')
#         expired = {'help_text': _('Visitors won\'t be able to sign up with an expired code.')}
# 
#     @classmethod
#     def add(cls, creator: 'User') -> 'InvitationCode':
#         new_code = cls(creator=creator)
#         new_code.save(force_insert=True)
#         return new_code
# 
#     @classmethod
#     def accept(cls, code: str, acceptor: 'User'):
#         return cls.objects.filter(code=code).update(acceptor=acceptor, expired=True, time_accepted=timezone.now())
# 
# class BlacklistedDomain(models.Model):
# 
#     domain = models.CharField(_('Domain name'), max_length=253, unique=True)
# 
#     enabled = models.BooleanField(
#         _('Enabled'),
#         help_text=_('If enabled visitors won\'t be able to sign up with this domain name in e-mail.'),
#         db_index=True, default=True)
# 
#     class Meta:
#         verbose_name = _('Blacklisted domain')
#         verbose_name_plural = _('Blacklisted domains')
# 
#     @classmethod
#     def is_blacklisted(cls, email: str) -> bool:
#         """Checks whether the given e-mail is blacklisted.
# 
#         :param email:
# 
#         """
#         domain = email.split('@', 1)[1].lower()
# 
#         # 'some.denied.co.uk' -> ['some.denied.co.uk', 'denied.co.uk', 'co.uk']
#         sub_domains = [domain]
#         for i in range(domain.count('.') - 1):
#             sub_domains.append(sub_domains[i].split('.', 1)[-1])
# 
#         return cls.objects.filter(enabled=True, domain__in=sub_domains).exists()
# 
#     def __str__(self):
#         return self.domain
# 
# class EmailConfirmation(InheritedModel, ModelWithCode):
# 
#     user = models.ForeignKey(USER_MODEL, verbose_name=_('User'), on_delete=models.CASCADE)
# 
#     class Meta:
#         verbose_name = _('Activation code')
#         verbose_name_plural = _('Activation codes')
# 
#     class Fields:
#         code = _('Activation code')
#         expired = {'help_text': _('Expired codes couldn\'t be used for repeated account activations.')}
# 
#     @classmethod
#     def add(cls, user: 'User') -> 'EmailConfirmation':
#         new_code = cls(user=user)
#         new_code.save(force_insert=True)
#         return new_code
# 
#     def activate(self):
#         self.expired = True
#         self.time_accepted = timezone.now()
#         self.save()
# 
#         user = self.user
#         user.is_active = True
#         user.save()
# 
# class RemoteRecord(ModelWithCode):
#     """Stores data used for sign ins using remote services."""
# 
#     remote = models.CharField(_('Remote alias'), max_length=20, db_index=True)
# 
#     remote_id = models.CharField(
#         _('Remote ID'), null=True, default=None, max_length=64, db_index=True, db_column='rid')
# 
#     user = models.ForeignKey(
#         USER_MODEL, null=True, blank=True,
#         related_name='remotes', verbose_name=_('User'), on_delete=models.CASCADE)
# 
#     expired = None
# 
#     class Meta:
#         verbose_name = _('Remote record')
#         verbose_name_plural = _('Remotes records')
# 
#     def __str__(self):
#         return f'{self.remote} {self.code}'
# 
#     @classmethod
#     def add(cls, *, remote: str, user: Optional['User']) -> 'RemoteRecord':
#         record = cls(
#             remote=remote,
#             user=user,
#         )
#         record.save(force_insert=True)
#         return record
# 
#     @classmethod
#     def cleanup(cls, *, ago: int = None):
#         """Removes remote records not linked to certain user.
#         Useful for periodic background cleaning.
# 
#         :param ago: Days. Allows cleanup for stale records created X days ago.
#             Defaults to None (cleanup all stale).
# 
#         """
#         filter_kwargs = {
#             'remote_id__isnull': True,
#             'user_id__isnull': True,
#         }
# 
#         if ago:
#             filter_kwargs['time_created__lte'] = timezone.now() - timedelta(days=int(ago))
# 
#         cls.objects.filter(**filter_kwargs).delete()


# Path: sitegate/admin.py
from django.contrib import admin
from .models import InvitationCode, BlacklistedDomain, EmailConfirmation, RemoteRecord




@admin.register(InvitationCode)
class InvitationCodeAdmin(admin.ModelAdmin):

    list_display = ('code', 'time_created', 'time_accepted', 'expired')
    list_display_links = ('code',)
    search_fields = ('code', 'creator', 'acceptor')
    list_filter = ('time_accepted',)
    ordering = ('-time_created',)
    date_hierarchy = 'time_created'
    readonly_fields = ('time_accepted',)
    raw_id_fields = ('creator', 'acceptor')



@admin.register(EmailConfirmation)