# Path: sitegate/models.py
# 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 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
# 
# Path: sitegate/signup_flows/base.py
# class SignupFlow(FlowsBase):
#     """Base class for signup flows."""
# 
#     flow_type: str = 'signup'
#     auto_signin: bool = True
#     activate_user: bool = True
#     enabled: bool = SIGNUP_ENABLED
#     disabled_text: str = SIGNUP_DISABLED_TEXT
# 
#     def handle_form_valid(self, request: HttpRequest, form: ModelForm) -> Optional[HttpResponse]:
#         flow_name = self.get_flow_name()
# 
#         if not self.get_arg_or_attr('activate_user'):
#             form.instance.is_active = False
# 
#         signup_result = self.add_user(request, form)
# 
#         if signup_result:
#             sig_user_signup_success.send(self, signup_result=signup_result, flow=flow_name, request=request)
# 
#             if self.get_arg_or_attr('auto_signin'):
#                 self.sign_in(request, form, signup_result)
# 
#             redirect_to = self.flow_args.get('redirect_to', self.default_redirect_to)
# 
#             if redirect_to:  # TODO Handle lambda variant with user as arg.
#                 return redirect(redirect_to)
# 
#         else:
#             sig_user_signup_fail.send(self, signup_result=signup_result, flow=flow_name, request=request)
# 
#     def add_user(self, request: HttpRequest, form: ModelForm) -> 'User':
#         """Adds (creates) user using form data."""
#         raise NotImplementedError  # pragma: nocover
# 
#     def sign_in(self, request: HttpRequest, form: ModelForm, signup_result: 'User') -> bool:
#         """Signs in a user."""
#         raise NotImplementedError  # pragma: nocover
# 
# Path: sitegate/signup_flows/modern.py
# class ModernSignup(SimpleClassicWithEmailSignup):
#     """Modernized registration flow based on classic from Django built-in
#     with unique e-mail field, without username and second password fields.
# 
#     """
#     form = ModernSignupForm
# 
#     def sign_in(self, request: HttpRequest, form: ModelForm, signup_result: 'User') -> bool:
#         form_data = form.cleaned_data
#         return self.login_generic(request, form_data['email'], form_data['password1'])
# 
#     def add_user(self, request: HttpRequest, form: ModelForm) -> 'User':
# 
#         user = super(form.__class__, form).save(commit=False)
# 
#         if not hasattr(user, 'USERNAME_FIELD') or user.USERNAME_FIELD == 'username':
#             user.username = form.cleaned_data['email']
# 
#         user.email = form.cleaned_data['email']
#         user.set_password(form.cleaned_data['password1'])
#         user.save()
# 
#         self.send_email(request, user)
# 
#         return user


import pytest
from django.urls import reverse
from sitegate.models import EmailConfirmation, BlacklistedDomain
from sitegate.signup_flows.base import SignupFlow
from sitegate.signup_flows.modern import ModernSignup



def test_verify_email(user, request_client, messages):
    result = request_client().get(reverse('verify_email', args=['42']))

    headers = getattr(result, 'headers', None)
    if headers is None:
        # pre Django 3.2
        location = result._headers['location'][1]
    else:
        location = headers['location']

    assert location.endswith('/')
    assert len(messages) == 1
    assert 'Unable to verify' in messages

    result = request_client().get(reverse('verify_email', args=[EmailConfirmation.add(user)]))
    assert 'successfully verified' in messages
    assert len(messages) == 2


def test_is_blacklisted():

    domain = BlacklistedDomain(domain='denied1.com', enabled=False)
    assert 'denied1.com' in f'{domain}'


# Path: sitegate/models.py
# 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 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
# 
# Path: sitegate/signup_flows/base.py
# class SignupFlow(FlowsBase):
#     """Base class for signup flows."""
# 
#     flow_type: str = 'signup'
#     auto_signin: bool = True
#     activate_user: bool = True
#     enabled: bool = SIGNUP_ENABLED
#     disabled_text: str = SIGNUP_DISABLED_TEXT
# 
#     def handle_form_valid(self, request: HttpRequest, form: ModelForm) -> Optional[HttpResponse]:
#         flow_name = self.get_flow_name()
# 
#         if not self.get_arg_or_attr('activate_user'):
#             form.instance.is_active = False
# 
#         signup_result = self.add_user(request, form)
# 
#         if signup_result:
#             sig_user_signup_success.send(self, signup_result=signup_result, flow=flow_name, request=request)
# 
#             if self.get_arg_or_attr('auto_signin'):
#                 self.sign_in(request, form, signup_result)
# 
#             redirect_to = self.flow_args.get('redirect_to', self.default_redirect_to)
# 
#             if redirect_to:  # TODO Handle lambda variant with user as arg.
#                 return redirect(redirect_to)
# 
#         else:
#             sig_user_signup_fail.send(self, signup_result=signup_result, flow=flow_name, request=request)
# 
#     def add_user(self, request: HttpRequest, form: ModelForm) -> 'User':
#         """Adds (creates) user using form data."""
#         raise NotImplementedError  # pragma: nocover
# 
#     def sign_in(self, request: HttpRequest, form: ModelForm, signup_result: 'User') -> bool:
#         """Signs in a user."""
#         raise NotImplementedError  # pragma: nocover
# 
# Path: sitegate/signup_flows/modern.py
# class ModernSignup(SimpleClassicWithEmailSignup):
#     """Modernized registration flow based on classic from Django built-in
#     with unique e-mail field, without username and second password fields.
# 
#     """
#     form = ModernSignupForm
# 
#     def sign_in(self, request: HttpRequest, form: ModelForm, signup_result: 'User') -> bool:
#         form_data = form.cleaned_data
#         return self.login_generic(request, form_data['email'], form_data['password1'])
# 
#     def add_user(self, request: HttpRequest, form: ModelForm) -> 'User':
# 
#         user = super(form.__class__, form).save(commit=False)
# 
#         if not hasattr(user, 'USERNAME_FIELD') or user.USERNAME_FIELD == 'username':
#             user.username = form.cleaned_data['email']
# 
#         user.email = form.cleaned_data['email']
#         user.set_password(form.cleaned_data['password1'])
#         user.save()
# 
#         self.send_email(request, user)
# 
#         return user


# Path: sitegate/tests/test_basic.py
import pytest
from django.urls import reverse
from sitegate.models import EmailConfirmation, BlacklistedDomain
from sitegate.signup_flows.base import SignupFlow
from sitegate.signup_flows.modern import ModernSignup




def test_verify_email(user, request_client, messages):
    result = request_client().get(reverse('verify_email', args=['42']))

    headers = getattr(result, 'headers', None)
    if headers is None:
        # pre Django 3.2
        location = result._headers['location'][1]
    else:
        location = headers['location']

    assert location.endswith('/')
    assert len(messages) == 1
    assert 'Unable to verify' in messages

    result = request_client().get(reverse('verify_email', args=[EmailConfirmation.add(user)]))
    assert 'successfully verified' in messages
    assert len(messages) == 2


def test_is_blacklisted():

    domain = BlacklistedDomain(domain='denied1.com', enabled=False)
    assert 'denied1.com' in f'{domain}'


    BlacklistedDomain.objects.bulk_create([