# Standard imports import os #import sys # Django imports from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required from django.contrib import messages from django.shortcuts import get_object_or_404 from django.core.mail import send_mail from django.urls import reverse from django.http import HttpResponseRedirect, HttpResponse from django.conf import settings from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # Project imports from user_mgmt.models import PyrosUser, UserLevel, ScientificProgram, SP_Period, SP_Period_User #scp_mgmt.models import ScientificProgram, SP_Period, SP_Period_User from dashboard.decorator import level_required #from dashboard.forms import UserForm from .forms import UserForm, PyrosUserCreationForm, UserPasswordResetForm from src.pyros_logger import log from src.core.pyros_django.obs_config.obsconfig_class import OBSConfig 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.html', 'weather_img': "red"})) def roles_description(request): return (render(request, "user_mgmt/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_mgmt/home_user_creation.html", locals())) def forgotten_password(request): form = UserPasswordResetForm() message = "" user = None if request.POST: password = PyrosUser.objects.make_random_password() try: user = PyrosUser.objects.get(email=request.POST["email"]) except PyrosUser.DoesNotExist: message = "The email adress is invalid" 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 !" else: return render(request, 'user_mgmt/forgotten_password.html', {"form": form, "message": message}) return render(request, 'user_mgmt/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 int(request.POST.get("timer")) < 10: error = True message = "(Bot prevention) You were too quick to fill the form, please take at least 10 seconds to send the form" else: if "six" != request.POST.get("question").strip(): error = True message = "Wrong answer to the question (Write the answer in letter and lowercase" else: if form.is_valid() and len(request.POST.get("iambot")) <= 0: 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_mgmt/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_mgmt/home_user_creation.html", locals())) def login_validation(request): ''' View called when the user log in (form submitted) ''' config = OBSConfig( os.environ["PATH_TO_OBSCONF_FILE"], os.environ["unit_name"]) observatory_name = config.get_obs_name() first_unit_name = config.get_units_name()[0] request.session["obsname"] = observatory_name+" "+first_unit_name request.session["pyros_config"] = settings.CONFIG_PYROS if request.user.is_authenticated: 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 redirect(reverse("index")) 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())) log.info(f"User {user} did action login") if request.POST.get("next"): return redirect(request.POST.get('next')) return redirect(reverse("index")) 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_mgmt/home_login.html", locals())) @login_required def superoperator_return(request): current_user = request.user return(render(request, "user_mgmt/user_detail.html", {'user': current_user, 'admin': 0})) @login_required def user_logout(request): ''' View called to log out. Redirects on login page. ''' if request.method == "POST": log.info(f"User {request.user} did action logout") logout(request) config = OBSConfig( os.environ["PATH_TO_OBSCONF_FILE"], os.environ["unit_name"]) observatory_name = config.get_obs_name() first_unit_name = config.get_units_name()[0] request.session["obsname"] = observatory_name+" "+first_unit_name return redirect(reverse("index")) return(render(request, LOGGED_PAGE, {'USER_LEVEL': "Visitor", 'base_template': 'base.html', 'weather_img': "red"})) def user_signin(request): return(render(request, "user_mgmt/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 = [] admin_and_unit_users = [] inactive_pyros_users = 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( is_active=False).order_by("-id") inactive_pyros_users = PyrosUser.objects.filter( is_active=False).order_by("-id") else: sp_of_current_user = current_user.get_scientific_programs() sp_periods_of_current_user = SP_Period.objects.filter( scientific_program__in=sp_of_current_user) common_scientific_programs = sp_of_current_user for sp in sp_periods_of_current_user: for user in SP_Period_User.objects.filter(SP_Period__in=sp_periods_of_current_user).exclude(user=current_user).values_list("user", flat=True): pyros_users_with_roles.append(PyrosUser.objects.get(id=user)) pyros_users_with_roles.append( sp.scientific_program.sp_pi) admin_and_unit_users = PyrosUser.objects.filter( user_level__name__in=("Unit-PI", "Unit-board", "Admin")).distinct() nb_of_scientific_program = ScientificProgram.objects.count() CAN_ADD_USER = request.session.get("role") in ("Admin,Unit-PI,Unit-board") # need the negative to calculate in the template for adjusting correctly the information display negative_nb_scientific_program = -nb_of_scientific_program page = request.GET.get('page', 1) pyros_users_paginator = Paginator( pyros_users_with_roles, settings.NB_ELEMENT_PER_PAGE) try: pyros_users_with_roles = pyros_users_paginator.page(page) except PageNotAnInteger: pyros_users_with_roles = pyros_users_paginator.page(1) except EmptyPage: pyros_users_with_roles = pyros_users_paginator.page( pyros_users_paginator.num_pages) return render(request, 'user_mgmt/users_management.html', { 'pyros_users_with_roles': pyros_users_with_roles, "inactive_pyros_users": inactive_pyros_users, "nb_of_scientific_program": nb_of_scientific_program, "negative_nb_scientific_program": negative_nb_scientific_program, "common_scientific_programs": common_scientific_programs, "admin_and_unit_users": admin_and_unit_users, "CAN_ADD_USER": CAN_ADD_USER }) @login_required @level_required("Admin", "Unit-PI", "Unit-board") def change_activate(request, pk, current_user_id): role = None if request.session.get("role") != None: role = request.session.get("role") else: role = UserLevel.objects.get(priority=request.user.get_priority()).name if role 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 = 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) CAN_VIEW_VALIDATOR = request.user.id == pk or request.session.get( "role") in ("Admin", "Unit-PI", "Unit-board") CAN_DELETE_USER = not is_last_user and request.session.get("role") in ( "Admin", "Unit-PI", "Unit-board") and not user.is_superuser and request.user != user CAN_ACTIVATE_USER = not is_last_user and request.session.get("role") in ( "Admin", "Unit-PI", "Unit-board") and not user.is_superuser and request.user != user CAN_EDIT_USER = request.user.id == pk or request.session.get( "role") in ("Admin", "Unit-PI", "Unit-board") CAN_VIEW_MOTIVE_OF_REGISTRATION = request.session.get("role") in ( "Admin", "Unit-PI", "Unit-board") and len(user.motive_of_registration) > 0 scientific_programs = user.get_scientific_programs() except PyrosUser.DoesNotExist: raise Http404("User does not exist") return render(request, 'user_mgmt/user_detail.html', context={ 'user': user, 'current_user': current_user, 'is_last_user': is_last_user, "roles": roles, "scientific_programs": scientific_programs, "CAN_VIEW_VALIDATOR": CAN_VIEW_VALIDATOR, "CAN_DELETE_USER": CAN_DELETE_USER, "CAN_ACTIVATE_USER": CAN_ACTIVATE_USER, "CAN_EDIT_USER": CAN_EDIT_USER, "CAN_VIEW_MOTIVE_OF_REGISTRATION": CAN_VIEW_MOTIVE_OF_REGISTRATION }) @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 = ScientificProgram.objects.filter(sp_pi=edit).count() > 0 form = UserForm(request.POST or None, instance=edit) CAN_EDIT_ROLE = request.session.get("role") in ( "Admin", "Unit-PI", "Unit-board") CAN_EDIT_INSTITUTE = request.session.get( "role") in ("Admin", "Unit-PI", "Unit-board") CAN_EDIT_REFEREE_THEME = request.session.get("role") != "Visitor" # creating list of roles for the formular excluding visitor of the list roles = UserLevel.objects.exclude(name="Visitor") if request.POST and 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")]) if(len(request.POST.getlist("referee_themes")) > 0): obj.referee_themes.set(request.POST.getlist("referee_themes")) else: obj.referee_themes.set([]) obj.save() if request.user == obj: request.session["role"] = UserLevel.objects.get( priority=request.user.get_priority()).name return redirect('user_detail', pk=pk) return render(request, 'user_mgmt/user_detail_edit.html', { 'form': form, "roles": roles, "pk": pk, "user_edit": edit, "is_sp_pi": is_sp_pi, "CAN_EDIT_ROLE": CAN_EDIT_ROLE, "CAN_EDIT_INSTITUTE": CAN_EDIT_INSTITUTE, "CAN_EDIT_REFEREE_THEME": CAN_EDIT_REFEREE_THEME }) 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")): messages.success( request, f"Role changed from {previous_active_role} to {request.session.get('role')}") text_reponse = f'
\ Role changed from {previous_active_role} to {request.session.get("role")}
' return HttpResponse(text_reponse)