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 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 import os from src.pyros_logger import log 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_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="" 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_manager/forgotten_password.html',{"form":form,"message":message}) 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 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_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(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 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_manager/home_login.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. ''' log.info(f"User {request.user} did action logout") logout(request) config = ConfigPyros(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(render(request, LOGGED_PAGE, {'USER_LEVEL' : "Visitor", 'base_template' : 'base.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 = [] 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 = 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)) pyros_users_with_roles.append(sp.SP_Period.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 return render(request, 'user_manager/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_program() except PyrosUser.DoesNotExist: raise Http404("User does not exist") return render(request, 'user_manager/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_manager/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'