# Path: yak/rest_core/permissions.py
# class IsOwnerOrReadOnly(permissions.BasePermission):
#     """
#     Object-level permission to only allow owners of an object to edit it.
#     Unauthenticated users can still read.
#     Assumes the model instance has a `user` attribute.
#     """
#     def has_permission(self, request, view):
#         """
#         This is specifically to use PUT for bulk updates, where it appears DRF does not use `has_object_permission`
#         """
#         if request.method in permissions.SAFE_METHODS:
#             return True
#         else:
#             return request.user.is_authenticated
# 
#     def has_object_permission(self, request, view, obj):
#         # Read permissions are allowed to any request,
#         # so we'll always allow GET, HEAD or OPTIONS requests.
#         if request.method in permissions.SAFE_METHODS:
#             return True
# 
#         if isinstance(obj, User):
#             return obj == request.user
#         else:
#             return obj.user == request.user
# 
# Path: yak/rest_user/serializers.py
# class SignUpSerializer(AuthSerializerMixin, LoginSerializer):
#     password = serializers.CharField(max_length=128, write_only=True, error_messages={'required': 'Password required'})
#     username = serializers.CharField(
#         error_messages={'required': 'Username required'},
#         max_length=30,
#         validators=[RegexValidator(), UniqueValidator(queryset=User.objects.all(), message="Username taken")])
#     email = serializers.EmailField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=75,
#         required=False,
#         validators=[UniqueValidator(queryset=User.objects.all(), message="Email address taken")])
# 
#     class Meta(LoginSerializer.Meta):
#         fields = ('fullname', 'username', 'email', 'password', 'client_id', 'client_secret')
# 
# class LoginSerializer(serializers.ModelSerializer):
#     client_id = serializers.SerializerMethodField()
#     client_secret = serializers.SerializerMethodField()
# 
#     class Meta:
#         model = User
#         fields = ('client_id', 'client_secret')
# 
#     def get_application(self, obj):
#         # If we're using version 0.8.0 or higher
#         if oauth_toolkit_version[0] >= 0 and oauth_toolkit_version[1] >= 8:
#             return obj.oauth2_provider_application.first()
#         else:
#             return obj.oauth2_provider_application.first()
# 
#     def get_client_id(self, obj):
#         return self.get_application(obj).client_id
# 
#     def get_client_secret(self, obj):
#         return self.get_application(obj).client_secret
# 
# class PasswordChangeSerializer(PasswordConfirmSerializer):
#     old_password = serializers.CharField(required=True, error_messages={'required': 'Old password required'})
# 
# class UserSerializer(AuthSerializerMixin, YAKModelSerializer):
# 
#     def __new__(cls, *args, **kwargs):
#         """
#         Can't just inherit in the class definition due to lots of import issues
#         """
#         return yak_settings.USER_SERIALIZER(*args, **kwargs)
# 
# class PasswordResetSerializer(serializers.Serializer):
#     email = serializers.EmailField()
# 
# class PasswordSetSerializer(PasswordConfirmSerializer):
#     uid = serializers.CharField()
#     token = serializers.CharField()
# 
# Path: yak/rest_user/utils.py
# def reset_password(request, email, subject_template_name='users/password_reset_subject.txt',
#                    rich_template_name='users/password_reset_email_rich.html',
#                    template_name='users/password_reset_email.html'):
#     """
#     Inspired by Django's `PasswordResetForm.save()`. Extracted for reuse.
#     Allows password reset emails to be sent to users with unusable passwords
#     """
#     from django.core.mail import send_mail
#     UserModel = get_user_model()
#     active_users = UserModel._default_manager.filter(email__iexact=email, is_active=True)
#     for user in active_users:
#         current_site = get_current_site(request)
#         site_name = current_site.name
#         domain = current_site.domain
#         c = {
#             'email': user.email,
#             'domain': domain,
#             'site_name': site_name,
#             'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
#             'user': user,
#             'token': default_token_generator.make_token(user),
#             'protocol': 'http',  # Your site can handle its own redirects
#         }
#         subject = loader.render_to_string(subject_template_name, c)
#         # Email subject *must not* contain newlines
#         subject = ''.join(subject.splitlines())
#         email = loader.render_to_string(template_name, c)
#         html_email = loader.render_to_string(rich_template_name, c)
#         send_mail(subject, email, settings.DEFAULT_FROM_EMAIL, [user.email], html_message=html_email)


import base64
from django.contrib.auth import get_user_model, authenticate
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from rest_framework import viewsets, generics, status, views
from rest_framework.authentication import BasicAuthentication
from rest_framework.decorators import list_route
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed
from yak.rest_core.permissions import IsOwnerOrReadOnly
from yak.rest_user.permissions import IsAuthenticatedOrCreate
from yak.rest_user.serializers import SignUpSerializer, LoginSerializer, PasswordChangeSerializer, UserSerializer, \
    PasswordResetSerializer, PasswordSetSerializer
from yak.rest_user.utils import reset_password


User = get_user_model()


class SignUp(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = SignUpSerializer
    permission_classes = (IsAuthenticatedOrCreate,)


class Login(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = LoginSerializer
    authentication_classes = (BasicAuthentication,)

    def get_queryset(self):
        queryset = super(Login, self).get_queryset()
        return queryset.filter(pk=self.request.user.pk)



# Path: yak/rest_core/permissions.py
# class IsOwnerOrReadOnly(permissions.BasePermission):
#     """
#     Object-level permission to only allow owners of an object to edit it.
#     Unauthenticated users can still read.
#     Assumes the model instance has a `user` attribute.
#     """
#     def has_permission(self, request, view):
#         """
#         This is specifically to use PUT for bulk updates, where it appears DRF does not use `has_object_permission`
#         """
#         if request.method in permissions.SAFE_METHODS:
#             return True
#         else:
#             return request.user.is_authenticated
# 
#     def has_object_permission(self, request, view, obj):
#         # Read permissions are allowed to any request,
#         # so we'll always allow GET, HEAD or OPTIONS requests.
#         if request.method in permissions.SAFE_METHODS:
#             return True
# 
#         if isinstance(obj, User):
#             return obj == request.user
#         else:
#             return obj.user == request.user
# 
# Path: yak/rest_user/serializers.py
# class SignUpSerializer(AuthSerializerMixin, LoginSerializer):
#     password = serializers.CharField(max_length=128, write_only=True, error_messages={'required': 'Password required'})
#     username = serializers.CharField(
#         error_messages={'required': 'Username required'},
#         max_length=30,
#         validators=[RegexValidator(), UniqueValidator(queryset=User.objects.all(), message="Username taken")])
#     email = serializers.EmailField(
#         allow_blank=True,
#         allow_null=True,
#         max_length=75,
#         required=False,
#         validators=[UniqueValidator(queryset=User.objects.all(), message="Email address taken")])
# 
#     class Meta(LoginSerializer.Meta):
#         fields = ('fullname', 'username', 'email', 'password', 'client_id', 'client_secret')
# 
# class LoginSerializer(serializers.ModelSerializer):
#     client_id = serializers.SerializerMethodField()
#     client_secret = serializers.SerializerMethodField()
# 
#     class Meta:
#         model = User
#         fields = ('client_id', 'client_secret')
# 
#     def get_application(self, obj):
#         # If we're using version 0.8.0 or higher
#         if oauth_toolkit_version[0] >= 0 and oauth_toolkit_version[1] >= 8:
#             return obj.oauth2_provider_application.first()
#         else:
#             return obj.oauth2_provider_application.first()
# 
#     def get_client_id(self, obj):
#         return self.get_application(obj).client_id
# 
#     def get_client_secret(self, obj):
#         return self.get_application(obj).client_secret
# 
# class PasswordChangeSerializer(PasswordConfirmSerializer):
#     old_password = serializers.CharField(required=True, error_messages={'required': 'Old password required'})
# 
# class UserSerializer(AuthSerializerMixin, YAKModelSerializer):
# 
#     def __new__(cls, *args, **kwargs):
#         """
#         Can't just inherit in the class definition due to lots of import issues
#         """
#         return yak_settings.USER_SERIALIZER(*args, **kwargs)
# 
# class PasswordResetSerializer(serializers.Serializer):
#     email = serializers.EmailField()
# 
# class PasswordSetSerializer(PasswordConfirmSerializer):
#     uid = serializers.CharField()
#     token = serializers.CharField()
# 
# Path: yak/rest_user/utils.py
# def reset_password(request, email, subject_template_name='users/password_reset_subject.txt',
#                    rich_template_name='users/password_reset_email_rich.html',
#                    template_name='users/password_reset_email.html'):
#     """
#     Inspired by Django's `PasswordResetForm.save()`. Extracted for reuse.
#     Allows password reset emails to be sent to users with unusable passwords
#     """
#     from django.core.mail import send_mail
#     UserModel = get_user_model()
#     active_users = UserModel._default_manager.filter(email__iexact=email, is_active=True)
#     for user in active_users:
#         current_site = get_current_site(request)
#         site_name = current_site.name
#         domain = current_site.domain
#         c = {
#             'email': user.email,
#             'domain': domain,
#             'site_name': site_name,
#             'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
#             'user': user,
#             'token': default_token_generator.make_token(user),
#             'protocol': 'http',  # Your site can handle its own redirects
#         }
#         subject = loader.render_to_string(subject_template_name, c)
#         # Email subject *must not* contain newlines
#         subject = ''.join(subject.splitlines())
#         email = loader.render_to_string(template_name, c)
#         html_email = loader.render_to_string(rich_template_name, c)
#         send_mail(subject, email, settings.DEFAULT_FROM_EMAIL, [user.email], html_message=html_email)


# Path: yak/rest_user/views.py
import base64
from django.contrib.auth import get_user_model, authenticate
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from rest_framework import viewsets, generics, status, views
from rest_framework.authentication import BasicAuthentication
from rest_framework.decorators import list_route
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed
from yak.rest_core.permissions import IsOwnerOrReadOnly
from yak.rest_user.permissions import IsAuthenticatedOrCreate
from yak.rest_user.serializers import SignUpSerializer, LoginSerializer, PasswordChangeSerializer, UserSerializer, \
    PasswordResetSerializer, PasswordSetSerializer
from yak.rest_user.utils import reset_password



User = get_user_model()


class SignUp(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = SignUpSerializer
    permission_classes = (IsAuthenticatedOrCreate,)


class Login(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = LoginSerializer
    authentication_classes = (BasicAuthentication,)

    def get_queryset(self):
        queryset = super(Login, self).get_queryset()
        return queryset.filter(pk=self.request.user.pk)



class SignIn(views.APIView):