views.py 14.5 KB
from django.shortcuts import render,redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from dashboard.decorator import level_required
from django.shortcuts import get_object_or_404
from dashboard.forms import UserForm
from .forms import PyrosUserCreationForm,UserPasswordResetForm
from django.core.mail import send_mail
from common.models import ScientificProgram, PyrosUser,UserLevel, SP_Period, SP_Period_User
from django.urls import reverse
from django.http import HttpResponseRedirect,HttpResponse
from obsconfig.configpyros import ConfigPyros
from django.conf import settings as pyros_settings

LOGGED_PAGE = "../../dashboard/templates/dashboard/index.html"

def home(request):
    '''
        Initial login view when coming on the website
    '''
    if request.user.is_authenticated:
        return(render(request, LOGGED_PAGE, {'USER_LEVEL': request.user.get_priority(), 'base_template' : "base.html", 'weather_img': "normal"}))
    return(render(request, LOGGED_PAGE, {"USER_LEVEL" : "Visitor", 'base_template' : 'base_unlogged.html', 'weather_img': "red"}))

def roles_description(request):
    return (render(request,"user_manager/roles_description.html"))
    
def create_user(request):
    '''
        View called to open the user creation form
    '''
    """
    if request.user.is_authenticated:
        return(render(request, LOGGED_PAGE, {'USER_LEVEL': request.user.get_priority(), 'base_template' : "base.html", 'weather_img': "normal"}))
    """
    form = PyrosUserCreationForm()
    return (render(request, "user_manager/home_user_creation.html", locals()))

def forgotten_password(request):
    form = UserPasswordResetForm()
    message=""
    if request.POST:
        password = PyrosUser.objects.make_random_password()
        user = PyrosUser.objects.get(email=request.POST["email"])
        if user != None:
            user.set_password(password)
            user.save()
            send_mail(
                '[PyROS CC] Registration',
                f"Hello,\nYou recently took steps to reset the password for your PyROS account. A temporary password has been assigned, please log in with the following password: '{password}'. \n\nCordially,\n\nPyROS Control Center'",
                '',
                [request.POST['email']],
                fail_silently=False,
            )
            message="The email has been send !"
    return render(request, 'user_manager/forgotten_password.html',{"form":form,"message":message})

def user_signup_validation(request):
    '''
        View called to validate the user creation (form submitted)
    '''
    """
    if request.user.is_authenticated:
        return(render(request, LOGGED_PAGE, {'USER_LEVEL': request.user.get_priority(), 'base_template' : "base.html", 'weather_img': "normal"}))
    """
    form = PyrosUserCreationForm(request.POST)
    if request.POST:
        if form.is_valid():
            form.save()
            message = "Account creation successful ! Login to continue"
            success = True
            if request.user.is_authenticated:
                
                if request.POST.get("next"):
                    return redirect(request.POST.get('next'))
                else:
                    return redirect(reverse("users"))
            else:
                return(render(request, "user_manager/home_login.html", locals()))
        else:
            message = "One or more fields contain errors. Please try again"
            form_errors = form.errors
    else:
        message = "The system encountered an error. Please try again"

    error = True
    return (render(request, "user_manager/home_user_creation.html", locals()))

def login_validation(request):
    '''
        View called when the user log in (form submitted)
    '''
    if request.user.is_authenticated:
        config = ConfigPyros(pyros_settings.PATH_TO_OBSCONF_FILE)
        observatory_name = config.get_obs_name()
        first_unit_name = config.get_units_name()[0]
        request.session["obsname"] = observatory_name+" "+first_unit_name
        if request.POST.get("next"):
            return redirect(request.POST.get('next'))
        # initiate variable session for telling which role the user is using if this user has multiple roles
        # default role is the role with maximum priority
        request.session["role"] = str(UserLevel.objects.get(priority=request.user.get_priority()))
        return(render(request, LOGGED_PAGE, {'USER_LEVEL': request.user.get_priority(),'base_template' : "base.html", 'weather_img': "normal"}))
    username = password = ''
    if request.POST:
        email = request.POST.get('email')
        password = request.POST.get('password')
        try:
            is_user_active = PyrosUser.objects.get(username=email).is_active
        except:
            is_user_active = None
        user = authenticate(username=email, password=password)
        if user is not None:
            success = False
            if user.is_active:
                login(request, user)
                request.session['user'] = email
                message = "Oui"
                success = True
                # initiate variable session for telling which role the user is using if this user has multiple roles
                # default role is the role with maximum priority
                request.session["role"] = str(UserLevel.objects.get(priority=request.user.get_priority()))
                if request.POST.get("next"):
                    return redirect(request.POST.get('next'))
                return(render(request, LOGGED_PAGE, {'USER_LEVEL': request.user.get_priority(), 'base_template' : "base.html", 'weather_img': "normal", 'success' : success}))
            else:
                message = "Your account is not active, please contact the Unit-PI."
        else:
            if is_user_active != None and not is_user_active:
                message = "Your account is not active, please contact the Unit-PI."
            elif is_user_active or is_user_active == None:
                message = "Your email and/or password were incorrect."
            
    else:
        message = "An unexpected error has occurred"
    error = True
    return(render(request, "user_manager/home_login.html", locals()))

@login_required
def profile(request):
    '''
        View called to see the current user profile
    '''
    current_user = request.user
    USER_LEVEL = request.user.get_priority()
    if (current_user.get_priority() < 4):
        return(render(request, "user_manager/user_detail.html", {'user': current_user, 'admin': 0}))
    return(render(request, "user_manager/profile.html", locals()))

@login_required
def superoperator_return(request):
    current_user = request.user
    return(render(request, "user_manager/user_detail.html", {'user': current_user, 'admin': 0}))

@login_required
def user_logout(request):
    '''
        View called to log out. Redirects on login page.
    '''

    logout(request)
    config = ConfigPyros(pyros_settings.PATH_TO_OBSCONF_FILE)
    observatory_name = config.get_obs_name()
    first_unit_name = config.get_units_name()[0]
    request.session["obsname"] = observatory_name+" "+first_unit_name
    return(render(request, LOGGED_PAGE, {'USER_LEVEL' :  "Visitor", 'base_template' : 'base_unlogged.html', 'weather_img': "red"}))

def user_signin(request):
    return(render(request, "user_manager/home_login.html",{"next": request.GET.get("next")}))


@login_required
@level_required("Admin","Unit-PI")
def delete_user(request,pk):
    user_to_be_deleted = get_object_or_404(PyrosUser,pk=pk)
    if request.user != user_to_be_deleted and request.method == "POST":
        user_to_be_deleted.delete()
        return HttpResponseRedirect(reverse('users'))
    else:
        return HttpResponseRedirect(reverse("user_detail",kwargs={"pk":pk}))


@login_required
@level_required("Admin","Observer","Management","Operator","Unit-PI","TAC","Unit board")
def users(request):
    current_user = request.user
    pyros_users_with_roles = []
    pyros_users_without_roles = None
    common_scientific_programs = None
    if request.session.get("role"):
        role = request.session.get("role")
    else:
        role = current_user.get_priority()
    if role in "Admin,Unit-PI,Unit board":
        pyros_users_with_roles = PyrosUser.objects.exclude(user_level__name="Visitor").order_by("-id")
        pyros_users_without_roles = PyrosUser.objects.filter(user_level__name="Visitor").order_by("-id")
    else:
        sp_of_current_user = SP_Period_User.objects.filter(user=current_user)
        common_scientific_programs = sp_of_current_user
        for sp in sp_of_current_user:
            for user in SP_Period_User.objects.filter(SP_Period=sp.SP_Period).exclude(user=current_user).values_list("user",flat=True):
                pyros_users_with_roles.append(PyrosUser.objects.get(id=user))
    nb_of_scientific_program = ScientificProgram.objects.count()
    # need the negative to calculate in the template for adjusting correctly the information display
    negative_nb_scientific_program = -nb_of_scientific_program
    return render(request, 'user_manager/users_management.html', {'pyros_users_with_roles': pyros_users_with_roles,"pyros_users_without_roles":pyros_users_without_roles,"nb_of_scientific_program": nb_of_scientific_program,"negative_nb_scientific_program":negative_nb_scientific_program,"common_scientific_programs":common_scientific_programs})                     

@login_required
@level_required("Admin","Unit-PI","Unit board")
def change_activate(request, pk, current_user_id):
    if PyrosUser.objects.get(id=current_user_id).get_roles_str() in ["Admin","Unit-PI","Unit board"]:
        try :
            user = get_object_or_404(PyrosUser, pk=pk)
            user.is_active = not user.is_active
            text_mail = ""
            text_object = ""
            if (user.first_time == False and user.is_active == True):
                user.first_time = True
                text_mail = "Hi,\n\nCongratulations, your registration has been approved by the PI. Welcome to the PyROS Control Center.\nIn order to submit observation sequences, you need to be associated to a scientific program.\n\nCordially,\n\nPyROS Control Center"
                text_object = "[PyROS CC] Welcome"
                user.validator = get_object_or_404(PyrosUser,pk=current_user_id)
                send_mail(text_object, text_mail, '', [user.email], fail_silently=False,)

            # We're not sending an email if the account has been desactivated or re-activated 
            # elif (user.is_active == True):
            #     text_mail = "Hi,\n\nYour account on the PyROS Control Center have been re-activated.\n\nCordially,\n\nPyROS Control Center"
            #     text_object = "[PyROS CC] Re-activation"
            # else :
            #     text_mail = "Hi,\n\nYour account on the PyROS Control Center have benn desactivated. Please contact the PI for futher information.\n\nCordially,\n\nPyROS Control Center"
            #     text_object = "[PyROS CC] Desactivation"
            
            user.save()
            
            return redirect('user_detail', pk=pk)
        except PyrosUser.DoesNotExist:
            return redirect('user_detail', pk=pk)
    else:
        return redirect("user_detail",pk=pk)
@login_required
@level_required("Admin","Observer","Management","Operator","Unit-PI","TAC","Unit board")
def user_detail_view(request,pk):
    try:
        is_last_user = PyrosUser.objects.count() == 1
        user_id=PyrosUser.objects.get(pk=pk)
        current_user = request.user
        roles = current_user.get_list_of_roles()
        sp_periods = SP_Period_User.objects.filter(user=user_id)
        scientific_programs = []
        for sp_period in sp_periods:
            
            scientific_programs.append(sp_period.SP_Period.scientific_program)
    except PyrosUser.DoesNotExist:
        raise Http404("User does not exist")
    return render(request, 'user_manager/user_detail.html', context={'user' : user_id, 'current_user' : current_user, 'USER_LEVEL': request.user.get_priority(), 'is_last_user' : is_last_user,"roles" : roles,"scientific_programs":scientific_programs})

@login_required
@level_required()
def user_detail_edit(request,pk):
    if request.session.get("role"):
        role = request.session.get("role")
    else:
        role = request.user.get_priority()
    # If its not his user profile or user isn't Unit-PI, Unit board, Admin or SP-PI, He can't edit this user profile and he is redirected to home page
    if (request.user.id != pk and role not in ("Admin","Unit-PI","Unit board") ):
        return HttpResponseRedirect(reverse('index'))
    edit = get_object_or_404(PyrosUser, pk=pk)
    is_sp_pi = SP_Period_User.objects.filter(is_SP_PI=True,user=edit).count() > 0
    form = UserForm(request.POST or None, instance=edit)
    # creating list of roles for the formular excluding visitor of the list
    roles = UserLevel.objects.exclude(name="Visitor")
    if form.is_valid():
        obj = form.save(commit=False)
        if(len(request.POST.getlist("roles"))>0):
            if("Admin" in request.POST.getlist("roles")):
                # if Admin role has been assigned, add the authorisations to access to django admin pages
                obj.is_staff = True
                obj.is_admin = True
                obj.is_superuser = True
            else:
                # just in case (for example, if user was previously an admin and has been downgraded) we're removing those authorisations 
                obj.is_staff = False
                obj.is_admin = False
            obj.user_level.set(request.POST.getlist("roles"))
        else:
            # No role has been assigned, so the user has the Visitor role
            obj.user_level.set([UserLevel.objects.get(name="Visitor")])
      
        obj.save()
        return redirect('user_detail', pk=pk)
    return render(request, 'user_manager/user_detail_edit.html', {'form': form,"roles":roles, "pk":pk,"user_edit":edit,'USER_LEVEL': request.user.get_priority(),"is_sp_pi":is_sp_pi})


def set_active_role(request):
    previous_active_role = request.session.get("role")
    if request.user.is_authenticated:
        if request.POST.get("role"):
            request.session["role"] = str(UserLevel.objects.get(name=request.POST.get("role")))
            if(previous_active_role is not None and previous_active_role != request.session.get("role")):
                return HttpResponse("Changed !")