<commit_before>'''
ARCHES - a program developed to inventory and manage immovable cultural heritage.
Copyright (C) 2013 <NAME> and World Monuments Fund

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''

import base64
import hashlib
import time
from datetime import datetime, timedelta
from django import forms
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.utils.translation import ugettext as _
from django.utils.http import urlencode
from django.shortcuts import render, redirect
from django.views.decorators.cache import never_cache
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, EmailMultiAlternatives
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from arches.app.models.system_settings import settings
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer
from Crypto.Cipher import AES
from Crypto import Random

def index(request):
    return render(request, 'index.htm', {
        'main_script': 'index',
        'active_page': 'Home',
        'app_title': settings.APP_TITLE,
        'copyright_text': settings.COPYRIGHT_TEXT,
        'copyright_year': settings.COPYRIGHT_YEAR
    })

@never_cache
def auth(request):
    auth_attempt_success = None
    # POST request is taken to mean user is logging in
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None and user.is_active:
            login(request, user)
            user.password = ''
            auth_attempt_success = True
        else:
            auth_attempt_success = False

    next = request.GET.get('next', reverse('home'))
    if auth_attempt_success:
        return redirect(next)
    else:
        if request.GET.get('logout', None) is not None:
            logout(request)
            # need to redirect to 'auth' so that the user is set to anonymous via the middleware
            return redirect('auth')
        else:
            return render(request, 'login.htm', {
                'app_name': settings.APP_NAME,
                'auth_failed': (auth_attempt_success is not None),
                'next': next
            })

@never_cache
def change_password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Important!
            messages.success(request, _('Your password has been updated'))
            return redirect('change_password')
    else:
        form = PasswordChangeForm(request.user)
    return render(request, 'change_password.htm', {
        'form': form
    })

@never_cache
def signup(request):

    postdata = {
        'first_name': '',
        'last_name': '',
        'email': ''
    }
    showform = True

    if request.method == 'POST':
        postdata = request.POST.copy()
        postdata['username'] = postdata['email']
        postdate['ts'] = int(time.time())
        form = ArchesUserCreationForm(postdata)
        if form.is_valid():
            AES = AESCipher(settings.SECRET_KEY)
            userinfo = JSONSerializer().serialize(form.cleaned_data)
            encrypted_userinfo = AES.encrypt(userinfo)
            url_encrypted_userinfo = urlencode({'link':encrypted_userinfo})

            context = {
                'host': request.get_host(),
                'link':request.build_absolute_uri(reverse('confirm_signup') + '?' + url_encrypted_userinfo,),
                'greeting': _('Thanks for your interest in Arches. Click on link below to confirm your email address! Use your email address to login.'),
                'closing': _('This link expires in 24 hours.  If you can\'t get to it before then, don\'t worry, you can always try again with the same email address.'),
            }

            html_content = render_to_string('email/signup_link.htm', context) # ...
            text_content = strip_tags(html_content) # this strips the html, so people will have the text as well.

            # create the email, and attach the HTML version as well.
            msg = EmailMultiAlternatives(_('Welcome to Arches!'), text_content, '<EMAIL>', [form.cleaned_data['email']])
            msg.attach_alternative(html_content, "text/html")
            msg.send()

            messages.success(request, _('An email has been sent to %s with a link to actiivate your account' % form.cleaned_data['email']))
            showform = False
    else:
        form = ArchesUserCreationForm()

    return render(request, 'signup.htm', {
        'form': form,
        'postdata': postdata,
        'showform': showform
    })

def confirm_signup(request):
    if request.method == 'GET':
        link = request.GET.get('link', None)
        AES = AESCipher(settings.SECRET_KEY)
        userinfo = JSONDeserializer().deserialize(AES.decrypt(link))
        form = ArchesUserCreationForm(userinfo)
        if datetime.fromtimestamp(userinfo['ts']) + timedelta(days=1) >= datetime.fromtimestamp(int(time.time())):
            if form.is_valid():
                user = form.save()
                # user = authenticate(username=user.username, password=str(userinfo['<PASSWORD>']))
                # if user is not None and user.is_active:
                #     login(request, user)

                return redirect('auth')
            else:
                try:
                    for error in form.errors.as_data()['username']:
                        if error.code == 'unique':
                            return redirect('auth')
                            # form.add_error('email', forms.ValidationError(
                            #     _('This email address had already been regisitered with the system.  ?'),
                            #     code='unique',
                            # ))
                except:
                    pass
        else:
            form.errors['ts'] = [_('The signup link has expired, please re-enter a new password and try again.  Thanks!')]<commit_msg>warn the user if this email has already been submitted, re #2453<commit_after>'''
ARCHES - a program developed to inventory and manage immovable cultural heritage.
Copyright (C) 2013 <NAME>ty Trust and World Monuments Fund

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''

import base64
import hashlib
import time
from datetime import datetime, timedelta
from django import forms
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.utils.translation import ugettext as _
from django.utils.http import urlencode
from django.shortcuts import render, redirect
from django.views.decorators.cache import never_cache
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, EmailMultiAlternatives
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from arches.app.models.system_settings import settings
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer
from Crypto.Cipher import AES
from Crypto import Random

def index(request):
    return render(request, 'index.htm', {
        'main_script': 'index',
        'active_page': 'Home',
        'app_title': settings.APP_TITLE,
        'copyright_text': settings.COPYRIGHT_TEXT,
        'copyright_year': settings.COPYRIGHT_YEAR
    })

@never_cache
def auth(request):
    auth_attempt_success = None
    # POST request is taken to mean user is logging in
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None and user.is_active:
            login(request, user)
            user.password = ''
            auth_attempt_success = True
        else:
            auth_attempt_success = False

    next = request.GET.get('next', reverse('home'))
    if auth_attempt_success:
        return redirect(next)
    else:
        if request.GET.get('logout', None) is not None:
            logout(request)
            # need to redirect to 'auth' so that the user is set to anonymous via the middleware
            return redirect('auth')
        else:
            return render(request, 'login.htm', {
                'app_name': settings.APP_NAME,
                'auth_failed': (auth_attempt_success is not None),
                'next': next
            })

@never_cache
def change_password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Important!
            messages.success(request, _('Your password has been updated'))
            return redirect('change_password')
    else:
        form = PasswordChangeForm(request.user)
    return render(request, 'change_password.htm', {
        'form': form
    })

@never_cache
def signup(request):

    postdata = {
        'first_name': '',
        'last_name': '',
        'email': ''
    }
    showform = True

    if request.method == 'POST':
        postdata = request.POST.copy()
        postdata['username'] = postdata['email']
        postdata['ts'] = int(time.time())
        form = ArchesUserCreationForm(postdata)
        if form.is_valid():
            AES = AESCipher(settings.SECRET_KEY)
            userinfo = JSONSerializer().serialize(form.cleaned_data)
            encrypted_userinfo = AES.encrypt(userinfo)
            url_encrypted_userinfo = urlencode({'link':encrypted_userinfo})

            context = {
                'host': request.get_host(),
                'link':request.build_absolute_uri(reverse('confirm_signup') + '?' + url_encrypted_userinfo,),
                'greeting': _('Thanks for your interest in Arches. Click on link below to confirm your email address! Use your email address to login.'),
                'closing': _('This link expires in 24 hours.  If you can\'t get to it before then, don\'t worry, you can always try again with the same email address.'),
            }

            html_content = render_to_string('email/signup_link.htm', context) # ...
            text_content = strip_tags(html_content) # this strips the html, so people will have the text as well.

            # create the email, and attach the HTML version as well.
            msg = EmailMultiAlternatives(_('Welcome to Arches!'), text_content, '<EMAIL>', [form.cleaned_data['email']])
            msg.attach_alternative(html_content, "text/html")
            msg.send()

            messages.success(request, _('An email has been sent to %s with a link to actiivate your account' % form.cleaned_data['email']))
            showform = False
        else:
            try:
                for error in form.errors.as_data()['username']:
                    if error.code == 'unique':
                        form.add_error('email', forms.ValidationError(
                            _('This email address has already been regisitered with the system. If you forgot your password, click the "exit" link below and go to the login page to reset your password.'),
                            code='unique',
                        ))
            except:
                pass
    else:
        form = ArchesUserCreationForm()

    return render(request, 'signup.htm', {
        'form': form,
        'postdata': postdata,
        'showform': showform
    })

def confirm_signup(request):
    if request.method == 'GET':
        link = request.GET.get('link', None)
        AES = AESCipher(settings.SECRET_KEY)
        userinfo = JSONDeserializer().deserialize(AES.decrypt(link))
        form = ArchesUserCreationForm(userinfo)
        if datetime.fromtimestamp(userinfo['ts']) + timedelta(days=1) >= datetime.fromtimestamp(int(time.time())):
            if form.is_valid():
                user = form.save()
                return redirect('auth')
            else:
                try:
                    for error in form.errors.as_data()['username']:
                        if error.code == 'unique':
                            return redirect('auth')
                except:
                    pass
        else:
            form.errors['ts'] = [_('The signup link has expired, please try signing up again.  Thanks!')]
{'fraction_non_alphanumeric': 0.09339877649736805, 'fraction_numerical': 0.0017072129748186087, 'mean_word_length': 2.5556398583712694, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3185262', 'n_tokens_mistral': 3788, 'n_tokens_neox': 3627, 'n_words': 1175}