<reponame>RCOSDP/osf.io
from __future__ import unicode_literals

import logging

from django.db.models import Q
from django.shortcuts import redirect
from django.urls import reverse
from django.views import View
from django.views.defaults import page_not_found, permission_denied
from django.views.generic import FormView
from django.views.generic import ListView
from rest_framework import status as http_status

from admin.base.views import GuidView
from admin.rdm.utils import RdmPermissionMixin
from admin.user_emails.forms import UserEmailsSearchForm
from framework.exceptions import HTTPError
from osf.models.user import OSFUser, Email
from website import mailchimp_utils
from website import mails
from website import settings

logger = logging.getLogger(__name__)


class UserEmailsFormView(RdmPermissionMixin, FormView):
    template_name = 'user_emails/search.html'
    object_type = 'osfuser'
    permission_required = ()
    raise_exception = True
    form_class = UserEmailsSearchForm

    def __init__(self, *args, **kwargs):
        self.redirect_url = reverse('user-emails:search')
        super(UserEmailsFormView, self).__init__(*args, **kwargs)

    def form_valid(self, form):
        guid = form.cleaned_data['guid']
        name = form.cleaned_data['name']
        email = form.cleaned_data['email']
        request_user = self.request.user

        if guid or email:
            if email:
                try:
                    users_query = OSFUser.objects.filter(is_active=True, is_registered=True)
                    users_query = users_query.filter(Q(username=email) | Q(emails__address=email))
                    if self.is_admin:
                        now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
                        users_query = users_query.filter(affiliated_institutions__in=now_institutions_id)
                    user = users_query.distinct('id').get()
                    guid = user.guids.first()._id
                except OSFUser.DoesNotExist:
                    msg = 'User with email address {} not found.'.format(email)
                    return page_not_found(self.request, AttributeError(msg))
                except OSFUser.MultipleObjectsReturned:
                    msg = 'Multiple users with email address {} found, please notify DevOps.'.format(email)
                    return page_not_found(self.request, AttributeError(msg))
            self.redirect_url = reverse('user-emails:search_list_guid', kwargs={'guid': guid})
        elif name:
            self.redirect_url = reverse('user-emails:search_list', kwargs={'name': name})

        return super(UserEmailsFormView, self).form_valid(form)

    @property
    def success_url(self):
        return self.redirect_url


class UserEmailsSearchList(RdmPermissionMixin, ListView):
    template_name = 'user_emails/user_list.html'
    permission_required = 'osf.view_osfuser'
    raise_exception = True
    form_class = UserEmailsSearchForm
    paginate_by = 25

    def get_queryset(self):
        keyword = self.kwargs.get('name')
        guid = self.kwargs.get('guid')
        request_user = self.request.user

        if not keyword and not guid:
            raise HTTPError(http_status.HTTP_400_BAD_REQUEST)
        if guid:
            users_query = OSFUser.objects.filter(guids___id=guid)
        else:
            users_query = OSFUser.objects.filter(is_active=True, is_registered=True)
            users_query = users_query.filter(fullname__icontains=keyword)
        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            users_query = users_query.filter(affiliated_institutions__in=now_institutions_id)
        users_query = users_query.order_by('fullname').only(
            'guids', 'eppn', 'username', 'fullname'
        )
        return users_query

    def get_context_data(self, **kwargs):
        users = self.get_queryset()
        page_size = self.get_paginate_by(users)
        paginator, page, query_set, is_paginated = self.paginate_queryset(users, page_size)
        kwargs['page'] = page
        kwargs['users'] = [{
            'id': user.guids.first()._id,
            'eppn': user.eppn,
            'username': user.username,
            'name': user.fullname,
            'affiliation': user.affiliated_institutions.first(),
        } for user in query_set]
        return super(UserEmailsSearchList, self).get_context_data(**kwargs)


class UserEmailsView(RdmPermissionMixin, GuidView):
    template_name = 'user_emails/user_emails.html'
    context_object_name = 'user'
    permission_required = 'osf.view_osfuser'
    raise_exception = True

    def get_context_data(self, **kwargs):
        if self.request.session.get('from') == 'post':
            del self.request.session['from']
        elif 'message' in self.request.session:
            del self.request.session['message']
        kwargs = super(UserEmailsView, self).get_context_data(**kwargs)
        return kwargs

    def get_object(self, queryset=None):
        request_user = self.request.user
        user = OSFUser.load(self.kwargs.get('guid'))

        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            all_institution_users_id = list(OSFUser.objects.filter(affiliated_institutions__in=now_institutions_id).distinct().values_list('pk', flat=True))

            if user.pk not in all_institution_users_id:
                raise HTTPError(http_status.HTTP_403_FORBIDDEN)

        return {
            'id': user._id,
            'eppn': user.eppn,
            'username': user.username,
            'name': user.fullname,
            'affiliations': user.affiliated_institutions.all(),
            'emails': user.emails.values_list('address', flat=True),
        }


class UserPrimaryEmail(RdmPermissionMixin, View):
    permission_required = 'osf.view_osfuser'
    raise_exception = True

    def post(self, request, *args, **kwargs):
        request_user = self.request.user
        user = OSFUser.load(self.kwargs.get('guid'))
        primary_email = request.POST.get('primary_email')
        username = None

        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            all_institution_users_id = list(OSFUser.objects.filter(affiliated_institutions__in=now_institutions_id).distinct().values_list('pk', flat=True))

            if user.pk not in all_institution_users_id:
                # raise HTTPError(http_status.HTTP_403_FORBIDDEN)
                return permission_denied(self.request, Exception('You cannot access this specific page'))

        # Refer to website.profile.views.update_user
        if primary_email:
            primary_email_address = primary_email.strip().lower()
            user_emails = [each.strip().lower() for each in user.emails.values_list('address', flat=True)]
            all_emails = [each.strip().lower() for each in Email.objects.values_list('address', flat=True)]
            unavailable_emails = [each for each in all_emails if each not in user_emails]
            if primary_email_address in unavailable_emails:
                request.session['from'] = 'post'
                request.session['message'] = 'Email "{}" cannot be used'.format(primary_email_address)
                return redirect(reverse('user-emails:user', kwargs={'guid': user._id}))

            if primary_email_address not in user_emails:
                # raise HTTPError(http_status.HTTP_403_FORBIDDEN)
                # return permission_denied(self.request)
                user.emails.create(address=primary_email_address.lower().strip())
            username = primary_email_address

        # make sure the new username has already been confirmed
        old_primary_email = ''
        if username and username != user.username and user.emails.filter(address=username).exists():

            mails.send_mail(
                user.username,
                mails.PRIMARY_EMAIL_CHANGED,
                user=user,
                new_address=username,
                can_change_preferences=False,
                osf_contact_email=settings.OSF_CONTACT_EMAIL
            )

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.items():
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(list_name, user._id, username=user.username)

            old_primary_email = user.username
            user.username = username

        user.save()
        # remove old primary email to use for other purposes
        user.emails.filter(address=old_primary_email).delete()

        return redirect(reverse('user-emails:user', kwargs={'guid': user._id}))

from __future__ import unicode_literals

import logging

from django.db.models import Q
from django.shortcuts import redirect
from django.urls import reverse
from django.views import View
from django.views.defaults import page_not_found, permission_denied
from django.views.generic import FormView
from django.views.generic import ListView
from rest_framework import status as http_status

from admin.base.views import GuidView
from admin.rdm.utils import RdmPermissionMixin
from admin.user_emails.forms import UserEmailsSearchForm
from framework.exceptions import HTTPError
from osf.models.user import OSFUser, Email
from website import mailchimp_utils
from website import mails
from website import settings

logger = logging.getLogger(__name__)


class UserEmailsFormView(RdmPermissionMixin, FormView):
    template_name = 'user_emails/search.html'
    object_type = 'osfuser'
    permission_required = ()
    raise_exception = True
    form_class = UserEmailsSearchForm

    def __init__(self, *args, **kwargs):
        self.redirect_url = reverse('user-emails:search')
        super(UserEmailsFormView, self).__init__(*args, **kwargs)

    def form_valid(self, form):
        guid = form.cleaned_data['guid']
        name = form.cleaned_data['name']
        email = form.cleaned_data['email']
        request_user = self.request.user

        if guid or email:
            if email:
                try:
                    users_query = OSFUser.objects.filter(is_active=True, is_registered=True)
                    users_query = users_query.filter(Q(username=email) | Q(emails__address=email))
                    if self.is_admin:
                        now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
                        users_query = users_query.filter(affiliated_institutions__in=now_institutions_id)
                    user = users_query.distinct('id').get()
                    guid = user.guids.first()._id
                except OSFUser.DoesNotExist:
                    msg = 'User with email address {} not found.'.format(email)
                    return page_not_found(self.request, AttributeError(msg))
                except OSFUser.MultipleObjectsReturned:
                    msg = 'Multiple users with email address {} found, please notify DevOps.'.format(email)
                    return page_not_found(self.request, AttributeError(msg))
            self.redirect_url = reverse('user-emails:search_list_guid', kwargs={'guid': guid})
        elif name:
            self.redirect_url = reverse('user-emails:search_list', kwargs={'name': name})

        return super(UserEmailsFormView, self).form_valid(form)

    @property
    def success_url(self):
        return self.redirect_url


class UserEmailsSearchList(RdmPermissionMixin, ListView):
    template_name = 'user_emails/user_list.html'
    permission_required = 'osf.view_osfuser'
    raise_exception = True
    form_class = UserEmailsSearchForm
    paginate_by = 25

    def get_queryset(self):
        keyword = self.kwargs.get('name')
        guid = self.kwargs.get('guid')
        request_user = self.request.user

        if not keyword and not guid:
            raise HTTPError(http_status.HTTP_400_BAD_REQUEST)
        if guid:
            users_query = OSFUser.objects.filter(guids___id=guid)
        else:
            users_query = OSFUser.objects.filter(is_active=True, is_registered=True)
            users_query = users_query.filter(fullname__icontains=keyword)
        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            users_query = users_query.filter(affiliated_institutions__in=now_institutions_id)
        users_query = users_query.order_by('fullname').only(
            'guids', 'eppn', 'username', 'fullname'
        )
        return users_query

    def get_context_data(self, **kwargs):
        users = self.get_queryset()
        page_size = self.get_paginate_by(users)
        paginator, page, query_set, is_paginated = self.paginate_queryset(users, page_size)
        kwargs['page'] = page
        kwargs['users'] = [{
            'id': user.guids.first()._id,
            'eppn': user.eppn,
            'username': user.username,
            'name': user.fullname,
            'affiliation': user.affiliated_institutions.first(),
        } for user in query_set]
        return super(UserEmailsSearchList, self).get_context_data(**kwargs)


class UserEmailsView(RdmPermissionMixin, GuidView):
    template_name = 'user_emails/user_emails.html'
    context_object_name = 'user'
    permission_required = 'osf.view_osfuser'
    raise_exception = True

    def get_context_data(self, **kwargs):
        if self.request.session.get('from') == 'post':
            del self.request.session['from']
        elif 'message' in self.request.session:
            del self.request.session['message']
        kwargs = super(UserEmailsView, self).get_context_data(**kwargs)
        return kwargs

    def get_object(self, queryset=None):
        request_user = self.request.user
        user = OSFUser.load(self.kwargs.get('guid'))

        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            all_institution_users_id = list(OSFUser.objects.filter(affiliated_institutions__in=now_institutions_id).distinct().values_list('pk', flat=True))

            if user.pk not in all_institution_users_id:
                raise HTTPError(http_status.HTTP_403_FORBIDDEN)

        return {
            'id': user._id,
            'eppn': user.eppn,
            'username': user.username,
            'name': user.fullname,
            'affiliations': user.affiliated_institutions.all(),
            'emails': user.emails.values_list('address', flat=True),
        }


class UserPrimaryEmail(RdmPermissionMixin, View):
    permission_required = 'osf.view_osfuser'
    raise_exception = True

    def post(self, request, *args, **kwargs):
        request_user = self.request.user
        user = OSFUser.load(self.kwargs.get('guid'))
        primary_email = request.POST.get('primary_email')
        username = None

        if self.is_admin:
            now_institutions_id = list(request_user.affiliated_institutions.all().values_list('pk', flat=True))
            all_institution_users_id = list(OSFUser.objects.filter(affiliated_institutions__in=now_institutions_id).distinct().values_list('pk', flat=True))

            if user.pk not in all_institution_users_id:
                # raise HTTPError(http_status.HTTP_403_FORBIDDEN)
                return permission_denied(self.request, Exception('You cannot access this specific page'))

        # Refer to website.profile.views.update_user
        if primary_email:
            primary_email_address = primary_email.strip().lower()
            user_emails = [each.strip().lower() for each in user.emails.values_list('address', flat=True)]
            all_emails = [each.strip().lower() for each in Email.objects.values_list('address', flat=True)]
            unavailable_emails = [each for each in all_emails if each not in user_emails]
            if primary_email_address in unavailable_emails:
                request.session['from'] = 'post'
                request.session['message'] = 'Email "{}" cannot be used'.format(primary_email_address)
                return redirect(reverse('user-emails:user', kwargs={'guid': user._id}))

            if primary_email_address not in user_emails:
                # raise HTTPError(http_status.HTTP_403_FORBIDDEN)
                # return permission_denied(self.request)
                user.emails.create(address=primary_email_address.lower().strip())
            username = primary_email_address

        # make sure the new username has already been confirmed
        old_primary_email = ''
        if username and username != user.username and user.emails.filter(address=username).exists():

            mails.send_mail(
                user.username,
                mails.PRIMARY_EMAIL_CHANGED,
                user=user,
                new_address=username,
                can_change_preferences=False,
                osf_contact_email=settings.OSF_CONTACT_EMAIL
            )

            # Remove old primary email from subscribed mailing lists
            for list_name, subscription in user.mailchimp_mailing_lists.items():
                if subscription:
                    mailchimp_utils.unsubscribe_mailchimp_async(list_name, user._id, username=user.username)

            old_primary_email = user.username
            user.username = username

        user.save()
        # remove old primary email to use for other purposes
        user.emails.filter(address=old_primary_email).delete()

        return redirect(reverse('user-emails:user', kwargs={'guid': user._id}))
# raise HTTPError(http_status.HTTP_403_FORBIDDEN) # Refer to website.profile.views.update_user # raise HTTPError(http_status.HTTP_403_FORBIDDEN) # return permission_denied(self.request) # make sure the new username has already been confirmed # Remove old primary email from subscribed mailing lists # remove old primary email to use for other purposes