Source code for oioioi.base.views

import traceback
from django.conf import settings

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.views import LogoutView as AuthLogoutView
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.http import HttpResponse, HttpResponseForbidden
from django.shortcuts import redirect, render
from django.template.loader import render_to_string
from django.template.response import TemplateResponse
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
from django.views.decorators.cache import cache_control
from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.vary import vary_on_cookie, vary_on_headers
from two_factor.views import LoginView as Login2FAView

import oioioi.base.forms
from oioioi.base.forms import handle_new_preference_fields
from oioioi.base.menu import account_menu_registry
from oioioi.base.permissions import enforce_condition, not_anonymous
from oioioi.base.preferences import PreferencesFactory, ensure_preferences_exist_for_user
from oioioi.base.processors import site_name
from oioioi.base.utils import generate_key, is_ajax, jsonify
from oioioi.base.utils.redirect import safe_redirect
from oioioi.base.utils.user import has_valid_username

account_menu_registry.register(
    'change_password',
    _("Change password"),
    lambda request: reverse('auth_password_change'),
    order=100,
)
account_menu_registry.register(
    'two_factor_auth',
    _("Two factor authentication"),
    lambda request: reverse('two_factor:profile'),
    order=150,
)


[docs]class ForcedError(Exception): pass
[docs]def force_error_view(request): raise ForcedError("Visited /force_error")
[docs]def force_permission_denied_view(request): raise PermissionDenied("Visited /force_permission_denied")
[docs]def handler500(request): # pylint: disable=broad-except message = '500 Internal Server Error' tb = '' try: tb = traceback.format_exc() if hasattr(request, 'user') and request.user.is_superuser: message += '\n' + tb except Exception: pass plain_resp = HttpResponse(message, status=500, content_type='text/plain') try: if is_ajax(request): return plain_resp return render(request, '500.html', {'traceback': tb}, status=500) except Exception: return plain_resp
[docs]def handler404(request, exception): if is_ajax(request): return HttpResponse('404 Not Found', status=404, content_type='text/plain') # DO NOT USE django.views.defaults.page_not_found here # It has a known vulnaribility before 1.11.18 # DO NOT DISPLAY request.path without using urllib.parse.quote() first # See: # https://security.archlinux.org/AVG-838 # https://www.djangoproject.com/weblog/2019/jan/04/security-releases/ # https://github.com/django/django/commit/64d2396e83aedba3fcc84ca40f23fbd22f0b9b5b # https://github.com/django/django/commit/1cd00fcf52d089ef0fe03beabd05d59df8ea052a return render(request, '404.html', status=404)
[docs]def handler403(request, exception): if is_ajax(request): return HttpResponse('403 Forbidden', status=403, content_type='text/plain') message = render_to_string('403.html', request=request) return HttpResponseForbidden(message)
@account_menu_registry.register_decorator( _("Edit profile"), lambda request: reverse('edit_profile'), order=99 ) @enforce_condition(not_anonymous)
[docs]def edit_profile_view(request): ensure_preferences_exist_for_user(request.user) if request.method == 'POST': form = PreferencesFactory().create_form( oioioi.base.forms.OioioiUserForm, request.user, request.POST, allow_login_change=not has_valid_username(request.user), ) handle_new_preference_fields(request, request.user) if form.is_valid(): form.save() return redirect('index') else: form = PreferencesFactory().create_form( oioioi.base.forms.OioioiUserForm, request.user, allow_login_change=not has_valid_username(request.user), ) return TemplateResponse( request, 'registration/registration_form.html', {'form': form} )
@account_menu_registry.register_decorator( _("Log out"), lambda request: '#', order=200, attrs={'data-post-url': reverse_lazy('logout')}, ) @require_POST
[docs]def logout_view(request): return AuthLogoutView.as_view()( request, template_name='registration/logout.html', extra_context=site_name(request), )
[docs]def login_view(request, redirect_field_name=REDIRECT_FIELD_NAME, **kwargs): if request.user.is_authenticated: redirect_to = request.GET.get(redirect_field_name, None) return safe_redirect(request, redirect_to) else: return Login2FAView.as_view(**kwargs)(request)
@require_GET @vary_on_headers('Content-Language') @vary_on_cookie @cache_control(public=True, max_age=900) @jsonify
[docs]def translate_view(request): if 'query' in request.GET: return {'answer': gettext(request.GET['query'])} else: raise SuspiciousOperation
[docs]def delete_account_view(request): if not request.user.is_authenticated: return HttpResponseForbidden() failed_password = False if request.POST: auth_password = request.POST['auth-password'] if request.user.check_password(auth_password): for participant in request.user.participant_set.all(): participant.erase_data() request.user.is_active = False request.user.save() return AuthLogoutView.as_view()( request, template_name='registration/delete_account_done.html' ) else: failed_password = True return TemplateResponse( request, 'registration/delete_account_confirmation.html', context={'failed': failed_password}, )
[docs]def generate_key_view(request): return HttpResponse(generate_key())