Exemplo n.º 1
0
    def decorator(wrapper):
        @functools.wraps(wrapper)
        def view(request):
            if request.method == "POST":
                Spoon.from_request(request, jelly, get_fields, post_fields)
            return wrapper(request)

        if sensitive is not None and getattr(settings, 'JELLYGLASS_HIDE_SENSITIVE_POST_PARAMETERS', False):
            view = sensitive_post_parameters(*sensitive)(view)
        return view
Exemplo n.º 2
0
 def as_view(cls, **kwargs):
     """
     Optionally wrap the base view in
     django.views.decorators.debug.sensitive_post_parameters().
     
     """
     # Normalize the setting.
     parameters = cls.sensitive_post_parameters
     if isinstance(parameters, six.string_types):
         parameters = (parameters,)
     elif isinstance(parameters, collections.Iterable):
         parameters = tuple(parameters)
     elif parameters:
         parameters = ()
     else:
         parameters = None
     
     view = super(SensitivePostParameters, cls).as_view(**kwargs)
     return (
         debug.sensitive_post_parameters(*parameters)(view)
             if parameters is not None
             else view)
Exemplo n.º 3
0
class ChangePasswordView(ModelAdminView):
    model = User
    change_password_form = AdminPasswordChangeForm
    change_user_password_template = None

    @csrf_protect_m
    def get(self, request, object_id):
        if not self.has_change_permission(request):
            raise PermissionDenied
        self.obj = self.get_object(unquote(object_id))
        self.form = self.change_password_form(self.obj)

        return self.get_response()

    def get_media(self):
        media = super(ChangePasswordView, self).get_media()
        media = media + self.vendor('xadmin.form.css',
                                    'xadmin.page.form.js') + self.form.media
        return media

    def get_context(self):
        context = super(ChangePasswordView, self).get_context()
        helper = FormHelper()
        helper.form_tag = False
        helper.include_media = False
        self.form.helper = helper
        context.update({
            'title':
            _('Change password: %s') % escape(unicode(self.obj)),
            'form':
            self.form,
            'has_delete_permission':
            False,
            'has_change_permission':
            True,
            'has_view_permission':
            True,
            'original':
            self.obj,
        })
        return context

    def get_response(self):
        return TemplateResponse(self.request, [
            self.change_user_password_template
            or 'xadmin/auth/user/change_password.html'
        ], self.get_context())

    @method_decorator(sensitive_post_parameters())
    @csrf_protect_m
    def post(self, request, object_id):
        if not self.has_change_permission(request):
            raise PermissionDenied
        self.obj = self.get_object(unquote(object_id))
        self.form = self.change_password_form(self.obj, request.POST)

        if self.form.is_valid():
            self.form.save()
            self.message_user(_('Password changed successfully.'), 'success')
            return HttpResponseRedirect(
                self.model_admin_url('change', self.obj.pk))
        else:
            return self.get_response()
Exemplo n.º 4
0
def sensitive(func):
	return sensitive_post_parameters()(csrf_protect(never_cache(func)))
Exemplo n.º 5
0
class SetExpressCheckout(TemplateView):
    template_name = 'shopping/paypal/cancel.html'

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def post(self, request, *args, **kwargs):
        service = get_service_instance()
        payment_mean = PaymentMean.objects.get(slug='paypal')
        if getattr(settings, 'DEBUG', False):
            paypal = json.loads(payment_mean.credentials)
        else:
            try:
                paypal = json.loads(payment_mean.credentials)
            except:
                return HttpResponse(
                    "Error, Could not parse PayPal parameters.")

        try:
            order = parse_order_info(request)
        except:
            messages.error(request, "Failed to parse order information")
            return HttpResponseRedirect(reverse('mediashop:cart'))

        if getattr(settings, 'UNIT_TESTING', False):
            signature = 'dumb_signature'
        else:
            signature = ''.join([
                random.SystemRandom().choice(string.ascii_letters +
                                             string.digits) for n in range(16)
            ])
        request.session['signature'] = signature
        request.session['return_url'] = service.url + reverse(
            'mediashop:download', args=(order.id, ))

        if getattr(settings, 'UNIT_TESTING', False):
            return HttpResponse(json.dumps({"order_id": order.id}))

        line_items = {}
        for i in range(len(order.album_list)):
            album = order.album_list[i]
            line_items.update({
                "L_PAYMENTREQUEST_0_NAME%d" % i:
                album.title,
                "L_PAYMENTREQUEST_0_DESC%d" % i:
                album.title,
                "L_PAYMENTREQUEST_0_AMT%d" % i:
                do_currency(album.cost, order.currency.code),
                "L_PAYMENTREQUEST_0_QTY%d" % i:
                1,
                "L_PAYMENTREQUEST_0_TAXAMT%d" % i:
                0,
                "L_PAYMENTREQUEST_0_NUMBER%d" % i:
                i + 1,
                "L_PAYMENTREQUEST_0_ITEMURL%d" % i:
                service.url + reverse('mediashop:music_item_detail',
                                      args=(
                                          album.artist.slug,
                                          album.slug,
                                      )),
                "L_PAYMENTREQUEST_0_ITEMCATEGORY%d" % i:
                'Digital'
            })

        for i in range(len(order.song_list)):
            song = order.song_list[i]
            line_items.update({
                "L_PAYMENTREQUEST_0_NAME%d" % i:
                song.title,
                "L_PAYMENTREQUEST_0_DESC%d" % i:
                song.title,
                "L_PAYMENTREQUEST_0_AMT%d" % i:
                do_currency(song.cost, order.currency.code),
                "L_PAYMENTREQUEST_0_QTY%d" % i:
                1,
                "L_PAYMENTREQUEST_0_TAXAMT%d" % i:
                0,
                "L_PAYMENTREQUEST_0_NUMBER%d" % i:
                i + 1,
                "L_PAYMENTREQUEST_0_ITEMURL%d" % i:
                service.url + reverse('mediashop:music_item_detail',
                                      args=(
                                          song.artist.slug,
                                          song.slug,
                                      )),
                "L_PAYMENTREQUEST_0_ITEMCATEGORY%d" % i:
                'Digital'
            })

        ec_data = {
            "USER":
            paypal['username'],
            "PWD":
            paypal['password'],
            "SIGNATURE":
            paypal['signature'],
            "METHOD":
            "SetExpressCheckout",
            "VERSION":
            124.0,
            "RETURNURL":
            service.url + reverse('mediashop:paypal_get_details') +
            '?order_id=' + order.id,
            "CANCELURL":
            service.url + reverse('mediashop:cart'),
            "PAYMENTREQUEST_0_PAYMENTACTION":
            "Sale",
            "PAYMENTREQUEST_0_AMT":
            do_currency(order.total_cost, order.currency.code),
            "PAYMENTREQUEST_0_ITEMAMT":
            do_currency(order.total_cost, order.currency.code),
            "PAYMENTREQUEST_0_SHIPPINGAMT":
            0,
            "PAYMENTREQUEST_0_TAXAMT":
            0,
            "PAYMENTREQUEST_0_CURRENCYCODE":
            order.currency.code,
            "PAYMENTREQUEST_0_DESC":
            "Purchase on " + service.project_name
        }
        ec_data.update(line_items)
        try:
            response = requests.post(EC_ENDPOINT, data=ec_data)
            result = parse_paypal_response(response.content.decode('utf-8'))
            ACK = result['ACK']
            if ACK == 'Success' or ACK == 'SuccessWithWarning':
                if getattr(settings, 'DEBUG', False):
                    redirect_url = 'https://www.sandbox.paypal.com/checkoutnow?token=' + result[
                        'TOKEN']
                else:
                    redirect_url = 'https://www.paypal.com/checkoutnow?token=' + result[
                        'TOKEN']
                return HttpResponseRedirect(redirect_url)
            else:
                order.delete()
                context = self.get_context_data(**kwargs)
                if getattr(settings, 'DEBUG', False):
                    context['paypal_error'] = urlunquote(
                        response.content.decode('utf-8'))
                else:
                    context['paypal_error'] = urlunquote(
                        result['L_LONGMESSAGE0'])
                messages.error(request,
                               'Initiating PayPal transaction failed.')
                return HttpResponseRedirect(reverse('mediashop:cart'))
        except Exception as e:
            logger.error("%s - PayPal error." % service.project_name,
                         exc_info=True)
            if getattr(settings, 'DEBUG', False):
                raise e
            context = self.get_context_data(**kwargs)
            messages.error(
                request,
                'Could not initiate transaction due to server error. Contact administrator.'
            )
            return render(request, 'shopping/paypal/cancel.html', context)
Exemplo n.º 6
0
import qrcode
import qrcode.image.svg

from ..compat import import_string
from ..compat import get_current_site
from ..forms import (MethodForm, TOTPDeviceForm, PhoneNumberMethodForm,
                     DeviceValidationForm, AuthenticationTokenForm,
                     PhoneNumberForm, BackupTokenForm, YubiKeyDeviceForm)
from ..models import PhoneDevice, get_available_phone_methods
from ..utils import (get_otpauth_url, default_device,
                     backup_phones)
from .utils import (IdempotentSessionWizardView, class_view_decorator)


@class_view_decorator(sensitive_post_parameters())
@class_view_decorator(never_cache)
class LoginView(IdempotentSessionWizardView):
    """
    View for handling the login process, including OTP verification.

    The login process is composed like a wizard. The first step asks for the
    user's credentials. If the credentials are correct, the wizard proceeds to
    the OTP verification step. If the user has a default OTP device configured,
    that device is asked to generate a token (send sms / call phone) and the
    user is asked to provide the generated token. The backup devices are also
    listed, allowing the user to select a backup device for verification.
    """
    template_name = 'two_factor/core/login.html'
    form_list = (
        ('auth', AuthenticationForm),
Exemplo n.º 7
0
        __doc__ = decorator.__doc__

        @classmethod
        def as_view(cls, *args, **kwargs):
            view = super(Mixin, cls).as_view(*args, **kwargs)
            return decorator(view)

    Mixin.__name__ = str('DecoratorMixin(%s)' % decorator.__name__)
    return Mixin


NeverCacheMixin = DecoratorMixin(never_cache)
CsrfProtectMixin = DecoratorMixin(csrf_protect)
LoginRequiredMixin = DecoratorMixin(login_required)
SensitivePostParametersMixin = DecoratorMixin(
    sensitive_post_parameters('password', 'old_password', 'password1',
                              'password2', 'new_password1', 'new_password2')
)

class AuthDecoratorsMixin(NeverCacheMixin, CsrfProtectMixin, SensitivePostParametersMixin):
    pass


class LoginView(AuthDecoratorsMixin, WithCurrentSiteMixin, WithNextUrlMixin, FormView):
    form_class = AuthenticationForm
    template_name = 'registration/login.html'
    disallow_authenticated = True
    success_url = resolve_url_lazy(settings.LOGIN_REDIRECT_URL)

    def dispatch(self, *args, **kwargs):
        if self.disallow_authenticated and self.request.user.is_authenticated():
            return redirect(self.get_success_url())
Exemplo n.º 8
0
)
from .utils import sync_user_email_addresses
from .models import EmailAddress, EmailConfirmation

from . import signals
from . import app_settings

from .adapter import get_adapter

try:
    from django.contrib.auth import update_session_auth_hash
except ImportError:
    update_session_auth_hash = None


sensitive_post_parameters_m = method_decorator(sensitive_post_parameters("password", "password1", "password2"))


def _ajax_response(request, response, form=None):
    if request.is_ajax():
        if isinstance(response, HttpResponseRedirect) or isinstance(response, HttpResponsePermanentRedirect):
            redirect_to = response["Location"]
        else:
            redirect_to = None
        response = get_adapter().ajax_response(request, response, form=form, redirect_to=redirect_to)
    return response


class RedirectAuthenticatedUserMixin(object):
    def dispatch(self, request, *args, **kwargs):
        # WORKAROUND: https://code.djangoproject.com/ticket/19316
Exemplo n.º 9
0
class RegistrationView(APIView):
    """HTTP end-points for creating a new user. """

    DEFAULT_FIELDS = ["email", "name", "username", "password"]

    EXTRA_FIELDS = [
        "confirm_email",
        "first_name",
        "last_name",
        "city",
        "state",
        "country",
        "gender",
        "year_of_birth",
        "level_of_education",
        "company",
        "title",
        "mailing_address",
        "goals",
        "honor_code",
        "terms_of_service",
    ]

    # This end-point is available to anonymous users,
    # so do not require authentication.
    authentication_classes = []

    def _is_field_visible(self, field_name):
        """Check whether a field is visible based on Django settings. """
        return self._extra_fields_setting.get(field_name) in [
            "required", "optional"
        ]

    def _is_field_required(self, field_name):
        """Check whether a field is required based on Django settings. """
        return self._extra_fields_setting.get(field_name) == "required"

    def __init__(self, *args, **kwargs):
        super(RegistrationView, self).__init__(*args, **kwargs)

        # Backwards compatibility: Honor code is required by default, unless
        # explicitly set to "optional" in Django settings.
        self._extra_fields_setting = copy.deepcopy(
            configuration_helpers.get_value('REGISTRATION_EXTRA_FIELDS'))
        if not self._extra_fields_setting:
            self._extra_fields_setting = copy.deepcopy(
                settings.REGISTRATION_EXTRA_FIELDS)
        self._extra_fields_setting[
            "honor_code"] = self._extra_fields_setting.get(
                "honor_code", "required")

        # Check that the setting is configured correctly
        for field_name in self.EXTRA_FIELDS:
            if self._extra_fields_setting.get(field_name, "hidden") not in [
                    "required", "optional", "hidden"
            ]:
                msg = u"Setting REGISTRATION_EXTRA_FIELDS values must be either required, optional, or hidden."
                raise ImproperlyConfigured(msg)

        # Map field names to the instance method used to add the field to the form
        self.field_handlers = {}
        valid_fields = self.DEFAULT_FIELDS + self.EXTRA_FIELDS
        for field_name in valid_fields:
            handler = getattr(
                self, "_add_{field_name}_field".format(field_name=field_name))
            self.field_handlers[field_name] = handler

        field_order = configuration_helpers.get_value(
            'REGISTRATION_FIELD_ORDER')
        if not field_order:
            field_order = settings.REGISTRATION_FIELD_ORDER or valid_fields

        # Check that all of the valid_fields are in the field order and vice versa, if not set to the default order
        if set(valid_fields) != set(field_order):
            field_order = valid_fields

        self.field_order = field_order

    @method_decorator(ensure_csrf_cookie)
    def get(self, request):
        """Return a description of the registration form.

        This decouples clients from the API definition:
        if the API decides to modify the form, clients won't need
        to be updated.

        This is especially important for the registration form,
        since different edx-platform installations might
        collect different demographic information.

        See `user_api.helpers.FormDescription` for examples
        of the JSON-encoded form description.

        Arguments:
            request (HttpRequest)

        Returns:
            HttpResponse

        """
        form_desc = FormDescription("post", reverse("user_api_registration"))
        self._apply_third_party_auth_overrides(request, form_desc)

        # Custom form fields can be added via the form set in settings.REGISTRATION_EXTENSION_FORM
        custom_form = get_registration_extension_form()

        if custom_form:
            # Default fields are always required
            for field_name in self.DEFAULT_FIELDS:
                self.field_handlers[field_name](form_desc, required=True)

            for field_name, field in custom_form.fields.items():
                restrictions = {}
                if getattr(field, 'max_length', None):
                    restrictions['max_length'] = field.max_length
                if getattr(field, 'min_length', None):
                    restrictions['min_length'] = field.min_length
                field_options = getattr(getattr(custom_form, 'Meta',
                                                None), 'serialization_options',
                                        {}).get(field_name, {})
                field_type = field_options.get(
                    'field_type',
                    FormDescription.FIELD_TYPE_MAP.get(field.__class__))
                if not field_type:
                    raise ImproperlyConfigured(
                        "Field type '{}' not recognized for registration extension field '{}'."
                        .format(field_type, field_name))
                form_desc.add_field(
                    field_name,
                    label=field.label,
                    default=field_options.get('default'),
                    field_type=field_options.get(
                        'field_type',
                        FormDescription.FIELD_TYPE_MAP.get(field.__class__)),
                    placeholder=field.initial,
                    instructions=field.help_text,
                    required=field.required,
                    restrictions=restrictions,
                    options=getattr(field, 'choices', None),
                    error_messages=field.error_messages,
                    include_default_option=field_options.get(
                        'include_default_option'),
                )

            # Extra fields configured in Django settings
            # may be required, optional, or hidden
            for field_name in self.EXTRA_FIELDS:
                if self._is_field_visible(field_name):
                    self.field_handlers[field_name](
                        form_desc,
                        required=self._is_field_required(field_name))
        else:
            # Go through the fields in the fields order and add them if they are required or visible
            for field_name in self.field_order:
                if field_name in self.DEFAULT_FIELDS:
                    self.field_handlers[field_name](form_desc, required=True)
                elif self._is_field_visible(field_name):
                    self.field_handlers[field_name](
                        form_desc,
                        required=self._is_field_required(field_name))

        return HttpResponse(form_desc.to_json(),
                            content_type="application/json")

    @method_decorator(csrf_exempt)
    def post(self, request):
        """Create the user's account.

        You must send all required form fields with the request.

        You can optionally send a "course_id" param to indicate in analytics
        events that the user registered while enrolling in a particular course.

        Arguments:
            request (HTTPRequest)

        Returns:
            HttpResponse: 200 on success
            HttpResponse: 400 if the request is not valid.
            HttpResponse: 409 if an account with the given username or email
                address already exists
            HttpResponse: 403 operation not allowed
        """
        data = request.POST.copy()

        email = data.get('email')
        username = data.get('username')

        # Handle duplicate email/username
        conflicts = check_account_exists(email=email, username=username)
        if conflicts:
            conflict_messages = {
                "email":
                accounts.EMAIL_CONFLICT_MSG.format(email_address=email),
                "username":
                accounts.USERNAME_CONFLICT_MSG.format(username=username),
            }
            errors = {
                field: [{
                    "user_message": conflict_messages[field]
                }]
                for field in conflicts
            }
            return JsonResponse(errors, status=409)

        # Backwards compatibility: the student view expects both
        # terms of service and honor code values.  Since we're combining
        # these into a single checkbox, the only value we may get
        # from the new view is "honor_code".
        # Longer term, we will need to make this more flexible to support
        # open source installations that may have separate checkboxes
        # for TOS, privacy policy, etc.
        if data.get("honor_code") and "terms_of_service" not in data:
            data["terms_of_service"] = data["honor_code"]

        try:
            user = create_account_with_params(request, data)
        except AccountValidationError as err:
            errors = {err.field: [{"user_message": err.message}]}
            return JsonResponse(errors, status=409)
        except ValidationError as err:
            # Should only get non-field errors from this function
            assert NON_FIELD_ERRORS not in err.message_dict
            # Only return first error for each field
            errors = {
                field: [{
                    "user_message": error
                } for error in error_list]
                for field, error_list in err.message_dict.items()
            }
            return JsonResponse(errors, status=400)
        except PermissionDenied:
            return HttpResponseForbidden(_("Account creation not allowed."))

        response = JsonResponse({"success": True})
        set_logged_in_cookies(request, response, user)
        return response

    @method_decorator(sensitive_post_parameters("password"))
    def dispatch(self, request, *args, **kwargs):
        return super(RegistrationView, self).dispatch(request, *args, **kwargs)

    def _add_email_field(self, form_desc, required=True):
        """Add an email field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to hold the user's email address.
        email_label = _(u"Email")

        # Translators: This example email address is used as a placeholder in
        # a field on the registration form meant to hold the user's email address.
        email_placeholder = _(u"*****@*****.**")

        # Translators: These instructions appear on the registration form, immediately
        # below a field meant to hold the user's email address.
        email_instructions = _(u"This is what you will use to login.")

        form_desc.add_field("email",
                            field_type="email",
                            label=email_label,
                            placeholder=email_placeholder,
                            instructions=email_instructions,
                            restrictions={
                                "min_length": accounts.EMAIL_MIN_LENGTH,
                                "max_length": accounts.EMAIL_MAX_LENGTH,
                            },
                            required=required)

    def _add_confirm_email_field(self, form_desc, required=True):
        """Add an email confirmation field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to confirm the user's email address.
        email_label = _(u"Confirm Email")
        error_msg = accounts.REQUIRED_FIELD_CONFIRM_EMAIL_MSG

        form_desc.add_field("confirm_email",
                            label=email_label,
                            required=required,
                            error_messages={"required": error_msg})

    def _add_name_field(self, form_desc, required=True):
        """Add a name field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to hold the user's full name.
        name_label = _(u"Full Name")

        # Translators: This example name is used as a placeholder in
        # a field on the registration form meant to hold the user's name.
        name_placeholder = _(u"Jane Q. Learner")

        # Translators: These instructions appear on the registration form, immediately
        # below a field meant to hold the user's full name.
        name_instructions = _(
            u"This name will be used on any certificates that you earn.")

        form_desc.add_field("name",
                            label=name_label,
                            placeholder=name_placeholder,
                            instructions=name_instructions,
                            restrictions={
                                "max_length": accounts.NAME_MAX_LENGTH,
                            },
                            required=required)

    def _add_username_field(self, form_desc, required=True):
        """Add a username field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to hold the user's public username.
        username_label = _(u"Public Username")

        username_instructions = _(
            # Translators: These instructions appear on the registration form, immediately
            # below a field meant to hold the user's public username.
            u"The name that will identify you in your courses. "
            u"It cannot be changed later.")

        # Translators: This example username is used as a placeholder in
        # a field on the registration form meant to hold the user's username.
        username_placeholder = _(u"Jane_Q_Learner")

        form_desc.add_field("username",
                            label=username_label,
                            instructions=username_instructions,
                            placeholder=username_placeholder,
                            restrictions={
                                "min_length": accounts.USERNAME_MIN_LENGTH,
                                "max_length": accounts.USERNAME_MAX_LENGTH,
                            },
                            required=required)

    def _add_password_field(self, form_desc, required=True):
        """Add a password field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to hold the user's password.
        password_label = _(u"Password")

        form_desc.add_field("password",
                            label=password_label,
                            field_type="password",
                            restrictions={
                                "min_length": accounts.PASSWORD_MIN_LENGTH,
                                "max_length": accounts.PASSWORD_MAX_LENGTH,
                            },
                            required=required)

    def _add_level_of_education_field(self, form_desc, required=True):
        """Add a level of education field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a dropdown menu on the registration
        # form used to select the user's highest completed level of education.
        education_level_label = _(u"Highest level of education completed")
        error_msg = accounts.REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG

        # The labels are marked for translation in UserProfile model definition.
        options = [(name, _(label))
                   for name, label in UserProfile.LEVEL_OF_EDUCATION_CHOICES]  # pylint: disable=translation-of-non-string
        form_desc.add_field("level_of_education",
                            label=education_level_label,
                            field_type="select",
                            options=options,
                            include_default_option=True,
                            required=required,
                            error_messages={"required": error_msg})

    def _add_gender_field(self, form_desc, required=True):
        """Add a gender field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a dropdown menu on the registration
        # form used to select the user's gender.
        gender_label = _(u"Gender")

        # The labels are marked for translation in UserProfile model definition.
        options = [(name, _(label))
                   for name, label in UserProfile.GENDER_CHOICES]  # pylint: disable=translation-of-non-string
        form_desc.add_field("gender",
                            label=gender_label,
                            field_type="select",
                            options=options,
                            include_default_option=True,
                            required=required)

    def _add_year_of_birth_field(self, form_desc, required=True):
        """Add a year of birth field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a dropdown menu on the registration
        # form used to select the user's year of birth.
        yob_label = _(u"Year of birth")

        options = [(unicode(year), unicode(year))
                   for year in UserProfile.VALID_YEARS]
        form_desc.add_field("year_of_birth",
                            label=yob_label,
                            field_type="select",
                            options=options,
                            include_default_option=True,
                            required=required)

    def _add_mailing_address_field(self, form_desc, required=True):
        """Add a mailing address field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # meant to hold the user's mailing address.
        mailing_address_label = _(u"Mailing address")
        error_msg = accounts.REQUIRED_FIELD_MAILING_ADDRESS_MSG

        form_desc.add_field("mailing_address",
                            label=mailing_address_label,
                            field_type="textarea",
                            required=required,
                            error_messages={"required": error_msg})

    def _add_goals_field(self, form_desc, required=True):
        """Add a goals field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This phrase appears above a field on the registration form
        # meant to hold the user's reasons for registering with edX.
        goals_label = _(u"Tell us why you're interested in {platform_name}"
                        ).format(platform_name=configuration_helpers.get_value(
                            "PLATFORM_NAME", settings.PLATFORM_NAME))
        error_msg = accounts.REQUIRED_FIELD_GOALS_MSG

        form_desc.add_field("goals",
                            label=goals_label,
                            field_type="textarea",
                            required=required,
                            error_messages={"required": error_msg})

    def _add_city_field(self, form_desc, required=True):
        """Add a city field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the city in which they live.
        city_label = _(u"City")
        error_msg = accounts.REQUIRED_FIELD_CITY_MSG

        form_desc.add_field("city",
                            label=city_label,
                            required=required,
                            error_messages={"required": error_msg})

    def _add_state_field(self, form_desc, required=False):
        """Add a State/Province/Region field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to False

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the State/Province/Region in which they live.
        state_label = _(u"State/Province/Region")

        form_desc.add_field("state", label=state_label, required=required)

    def _add_company_field(self, form_desc, required=False):
        """Add a Company field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to False

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the Company
        company_label = _(u"Company")

        form_desc.add_field("company", label=company_label, required=required)

    def _add_title_field(self, form_desc, required=False):
        """Add a Title field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to False

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the Title
        title_label = _(u"Title")

        form_desc.add_field("title", label=title_label, required=required)

    def _add_first_name_field(self, form_desc, required=False):
        """Add a First Name field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to False

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the First Name
        first_name_label = _(u"First Name")

        form_desc.add_field("first_name",
                            label=first_name_label,
                            required=required)

    def _add_last_name_field(self, form_desc, required=False):
        """Add a Last Name field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to False

        """
        # Translators: This label appears above a field on the registration form
        # which allows the user to input the First Name
        last_name_label = _(u"Last Name")

        form_desc.add_field("last_name",
                            label=last_name_label,
                            required=required)

    def _add_country_field(self, form_desc, required=True):
        """Add a country field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This label appears above a dropdown menu on the registration
        # form used to select the country in which the user lives.
        country_label = _(u"Country")
        error_msg = accounts.REQUIRED_FIELD_COUNTRY_MSG

        # If we set a country code, make sure it's uppercase for the sake of the form.
        default_country = form_desc._field_overrides.get(
            'country', {}).get('defaultValue')
        if default_country:
            form_desc.override_field_properties(
                'country', default=default_country.upper())

        form_desc.add_field("country",
                            label=country_label,
                            field_type="select",
                            options=list(countries),
                            include_default_option=True,
                            required=required,
                            error_messages={"required": error_msg})

    def _add_honor_code_field(self, form_desc, required=True):
        """Add an honor code field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Separate terms of service and honor code checkboxes
        if self._is_field_visible("terms_of_service"):
            terms_label = _(u"Honor Code")
            terms_link = marketing_link("HONOR")
            terms_text = _(u"Review the Honor Code")

        # Combine terms of service and honor code checkboxes
        else:
            # Translators: This is a legal document users must agree to
            # in order to register a new account.
            terms_label = _(u"Terms of Service and Honor Code")
            terms_link = marketing_link("HONOR")
            terms_text = _(u"Review the Terms of Service and Honor Code")

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        label = _(u"I agree to the {platform_name} {terms_of_service}").format(
            platform_name=configuration_helpers.get_value(
                "PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_label)

        # Translators: "Terms of Service" is a legal document users must agree to
        # in order to register a new account.
        error_msg = _(
            u"You must agree to the {platform_name} {terms_of_service}"
        ).format(platform_name=configuration_helpers.get_value(
            "PLATFORM_NAME", settings.PLATFORM_NAME),
                 terms_of_service=terms_label)

        form_desc.add_field("honor_code",
                            label=label,
                            field_type="checkbox",
                            default=False,
                            required=required,
                            error_messages={"required": error_msg},
                            supplementalLink=terms_link,
                            supplementalText=terms_text)

    def _add_terms_of_service_field(self, form_desc, required=True):
        """Add a terms of service field to a form description.

        Arguments:
            form_desc: A form description

        Keyword Arguments:
            required (bool): Whether this field is required; defaults to True

        """
        # Translators: This is a legal document users must agree to
        # in order to register a new account.
        terms_label = _(u"Terms of Service")
        terms_link = marketing_link("TOS")
        terms_text = _(u"Review the Terms of Service")

        # Translators: "Terms of service" is a legal document users must agree to
        # in order to register a new account.
        label = _(u"I agree to the {platform_name} {terms_of_service}").format(
            platform_name=configuration_helpers.get_value(
                "PLATFORM_NAME", settings.PLATFORM_NAME),
            terms_of_service=terms_label)

        # Translators: "Terms of service" is a legal document users must agree to
        # in order to register a new account.
        error_msg = _(
            u"You must agree to the {platform_name} {terms_of_service}"
        ).format(platform_name=configuration_helpers.get_value(
            "PLATFORM_NAME", settings.PLATFORM_NAME),
                 terms_of_service=terms_label)

        form_desc.add_field("terms_of_service",
                            label=label,
                            field_type="checkbox",
                            default=False,
                            required=required,
                            error_messages={"required": error_msg},
                            supplementalLink=terms_link,
                            supplementalText=terms_text)

    def _apply_third_party_auth_overrides(self, request, form_desc):
        """Modify the registration form if the user has authenticated with a third-party provider.

        If a user has successfully authenticated with a third-party provider,
        but does not yet have an account with EdX, we want to fill in
        the registration form with any info that we get from the
        provider.

        This will also hide the password field, since we assign users a default
        (random) password on the assumption that they will be using
        third-party auth to log in.

        Arguments:
            request (HttpRequest): The request for the registration form, used
                to determine if the user has successfully authenticated
                with a third-party provider.

            form_desc (FormDescription): The registration form description

        """
        if third_party_auth.is_enabled():
            running_pipeline = third_party_auth.pipeline.get(request)
            if running_pipeline:
                current_provider = third_party_auth.provider.Registry.get_from_pipeline(
                    running_pipeline)

                if current_provider:
                    # Override username / email / full name
                    field_overrides = current_provider.get_register_form_data(
                        running_pipeline.get('kwargs'))

                    # When the TPA Provider is configured to skip the registration form and we are in an
                    # enterprise context, we need to hide all fields except for terms of service and
                    # ensure that the user explicitly checks that field.
                    hide_registration_fields_except_tos = (
                        current_provider.skip_registration_form
                        and enterprise_customer_for_request(request))

                    for field_name in self.DEFAULT_FIELDS + self.EXTRA_FIELDS:
                        if field_name in field_overrides:
                            form_desc.override_field_properties(
                                field_name,
                                default=field_overrides[field_name])

                            if (field_name
                                    not in ['terms_of_service', 'honor_code']
                                    and field_overrides[field_name]
                                    and hide_registration_fields_except_tos):

                                form_desc.override_field_properties(
                                    field_name,
                                    field_type="hidden",
                                    label="",
                                    instructions="",
                                )

                    # Hide the password field
                    form_desc.override_field_properties("password",
                                                        default="",
                                                        field_type="hidden",
                                                        required=False,
                                                        label="",
                                                        instructions="",
                                                        restrictions={})
                    # used to identify that request is running third party social auth
                    form_desc.add_field(
                        "social_auth_provider",
                        field_type="hidden",
                        label="",
                        default=current_provider.name
                        if current_provider.name else "Third Party",
                        required=False,
                    )
Exemplo n.º 10
0
class LoginView(SuccessURLAllowedHostsMixin, IdempotentSessionWizardView):
    """
    View for handling the login process, including OTP verification.

    The login process is composed like a wizard. The first step asks for the
    user's credentials. If the credentials are correct, the wizard proceeds to
    the OTP verification step. If the user has a default OTP device configured,
    that device is asked to generate a token (send sms / call phone) and the
    user is asked to provide the generated token. The backup devices are also
    listed, allowing the user to select a backup device for verification.
    """
    template_name = 'two_factor/core/login.html'
    form_list = (
        ('auth', AuthenticationForm),
        ('token', AuthenticationTokenForm),
        ('backup', BackupTokenForm),
    )
    idempotent_dict = {
        'token': False,
        'backup': False,
    }
    redirect_authenticated_user = False
    storage_name = 'two_factor.views.utils.LoginStorage'

    def has_token_step(self):
        return (default_device(self.get_user()) and not self.remember_agent)

    def has_backup_step(self):
        return (default_device(self.get_user())
                and 'token' not in self.storage.validated_step_data
                and not self.remember_agent)

    @cached_property
    def expired(self):
        login_timeout = getattr(settings, 'TWO_FACTOR_LOGIN_TIMEOUT', 600)
        if login_timeout == 0:
            return False
        expiration_time = self.storage.data.get("authentication_time",
                                                0) + login_timeout
        return int(time.time()) > expiration_time

    condition_dict = {
        'token': has_token_step,
        'backup': has_backup_step,
    }
    redirect_field_name = REDIRECT_FIELD_NAME

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.user_cache = None
        self.device_cache = None
        self.cookies_to_delete = []
        self.show_timeout_error = False

    def post(self, *args, **kwargs):
        """
        The user can select a particular device to challenge, being the backup
        devices added to the account.
        """
        wizard_goto_step = self.request.POST.get('wizard_goto_step', None)

        if wizard_goto_step == 'auth':
            self.storage.reset()

        if self.expired and self.steps.current != 'auth':
            logger.info("User's authentication flow has timed out. The user "
                        "has been redirected to the initial auth form.")
            self.storage.reset()
            self.show_timeout_error = True
            return self.render_goto_step('auth')

        # Generating a challenge doesn't require to validate the form.
        if 'challenge_device' in self.request.POST:
            return self.render_goto_step('token')

        response = super().post(*args, **kwargs)
        return self.delete_cookies_from_response(response)

    def done(self, form_list, **kwargs):
        """
        Login the user and redirect to the desired page.
        """

        # Check if remember cookie should be set after login
        current_step_data = self.storage.get_step_data(self.steps.current)
        remember = bool(current_step_data
                        and current_step_data.get('token-remember') == 'on')

        login(self.request, self.get_user())

        redirect_to = self.get_success_url()

        device = getattr(self.get_user(), 'otp_device', None)
        response = redirect(redirect_to)

        if device:
            signals.user_verified.send(sender=__name__,
                                       request=self.request,
                                       user=self.get_user(),
                                       device=device)

            # Set a remember cookie if activated

            if getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_AGE',
                       None) and remember:
                # choose a unique cookie key to remember devices for multiple users in the same browser
                cookie_key = REMEMBER_COOKIE_PREFIX + str(uuid4())
                cookie_value = get_remember_device_cookie(
                    user=self.get_user(), otp_device_id=device.persistent_id)
                response.set_cookie(
                    cookie_key,
                    cookie_value,
                    max_age=settings.TWO_FACTOR_REMEMBER_COOKIE_AGE,
                    domain=getattr(settings,
                                   'TWO_FACTOR_REMEMBER_COOKIE_DOMAIN', None),
                    path=getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_PATH',
                                 '/'),
                    secure=getattr(settings,
                                   'TWO_FACTOR_REMEMBER_COOKIE_SECURE', False),
                    httponly=getattr(settings,
                                     'TWO_FACTOR_REMEMBER_COOKIE_HTTPONLY',
                                     True),
                    samesite=getattr(settings,
                                     'TWO_FACTOR_REMEMBER_COOKIE_SAMESITE',
                                     'Lax'),
                )

        return response

    # Copied from django.conrib.auth.views.LoginView (Branch: stable/1.11.x)
    # https://github.com/django/django/blob/58df8aa40fe88f753ba79e091a52f236246260b3/django/contrib/auth/views.py#L63
    def get_success_url(self):
        url = self.get_redirect_url()
        return url or resolve_url(settings.LOGIN_REDIRECT_URL)

    # Copied from django.conrib.auth.views.LoginView (Branch: stable/1.11.x)
    # https://github.com/django/django/blob/58df8aa40fe88f753ba79e091a52f236246260b3/django/contrib/auth/views.py#L67
    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name,
            self.request.GET.get(self.redirect_field_name, ''))
        url_is_safe = url_has_allowed_host_and_scheme(
            url=redirect_to,
            allowed_hosts=self.get_success_url_allowed_hosts(),
            require_https=self.request.is_secure(),
        )
        return redirect_to if url_is_safe else ''

    def get_form_kwargs(self, step=None):
        """
        AuthenticationTokenForm requires the user kwarg.
        """
        if step == 'auth':
            return {'request': self.request}
        if step in ('token', 'backup'):
            return {
                'user': self.get_user(),
                'initial_device': self.get_device(step),
            }
        return {}

    def get_done_form_list(self):
        """
        Return the forms that should be processed during the final step
        """
        # Intentionally do not process the auth form on the final step. We
        # haven't stored this data, and it isn't required to login the user
        form_list = self.get_form_list()
        form_list.pop('auth')
        return form_list

    def process_step(self, form):
        """
        Process an individual step in the flow
        """
        # To prevent saving any private auth data to the session store, we
        # validate the authentication form, determine the resulting user, then
        # only store the minimum needed to login that user (the user's primary
        # key and the backend used)
        if self.steps.current == 'auth':
            user = form.is_valid() and form.user_cache
            self.storage.reset()
            self.storage.authenticated_user = user
            self.storage.data["authentication_time"] = int(time.time())

            # By returning None when the user clicks the "back" button to the
            # auth step the form will be blank with validation warnings
            return None

        return super().process_step(form)

    def process_step_files(self, form):
        """
        Process the files submitted from a specific test
        """
        if self.steps.current == 'auth':
            return {}
        return super().process_step_files(form)

    def get_form(self, *args, **kwargs):
        """
        Returns the form for the step
        """
        form = super().get_form(*args, **kwargs)
        if self.show_timeout_error:
            form.cleaned_data = getattr(form, 'cleaned_data', {})
            form.add_error(
                None,
                ValidationError(
                    _('Your session has timed out. Please login again.')))
        return form

    def get_device(self, step=None):
        """
        Returns the OTP device selected by the user, or his default device.
        """
        if not self.device_cache:
            challenge_device_id = self.request.POST.get(
                'challenge_device', None)
            if challenge_device_id:
                for device in backup_phones(self.get_user()):
                    if device.persistent_id == challenge_device_id:
                        self.device_cache = device
                        break
            if step == 'backup':
                try:
                    self.device_cache = self.get_user().staticdevice_set.get(
                        name='backup')
                except StaticDevice.DoesNotExist:
                    pass
            if not self.device_cache:
                self.device_cache = default_device(self.get_user())
        return self.device_cache

    def render(self, form=None, **kwargs):
        """
        If the user selected a device, ask the device to generate a challenge;
        either making a phone call or sending a text message.
        """
        if self.steps.current == 'token':
            self.get_device().generate_challenge()
        return super().render(form, **kwargs)

    def get_user(self):
        """
        Returns the user authenticated by the AuthenticationForm. Returns False
        if not a valid user; see also issue #65.
        """
        if not self.user_cache:
            self.user_cache = self.storage.authenticated_user
        return self.user_cache

    def get_context_data(self, form, **kwargs):
        """
        Adds user's default and backup OTP devices to the context.
        """
        context = super().get_context_data(form, **kwargs)
        if self.steps.current == 'token':
            context['device'] = self.get_device()
            context['other_devices'] = [
                phone for phone in backup_phones(self.get_user())
                if phone != self.get_device()
            ]
            try:
                context['backup_tokens'] = self.get_user().staticdevice_set\
                    .get(name='backup').token_set.count()
            except StaticDevice.DoesNotExist:
                context['backup_tokens'] = 0

        if getattr(settings, 'LOGOUT_REDIRECT_URL', None):
            context['cancel_url'] = resolve_url(settings.LOGOUT_REDIRECT_URL)
        elif getattr(settings, 'LOGOUT_URL', None):
            warnings.warn(
                "LOGOUT_URL has been replaced by LOGOUT_REDIRECT_URL, please "
                "review the URL and update your settings.", DeprecationWarning)
            context['cancel_url'] = resolve_url(settings.LOGOUT_URL)
        return context

    @cached_property
    def remember_agent(self):
        """
        Returns True if a user, browser and device is remembered using the remember cookie.
        """
        if not getattr(settings, 'TWO_FACTOR_REMEMBER_COOKIE_AGE', None):
            return False

        user = self.get_user()
        devices = list(devices_for_user(user))
        for key, value in self.request.COOKIES.items():
            if key.startswith(REMEMBER_COOKIE_PREFIX) and value:
                for device in devices:
                    verify_is_allowed, extra = device.verify_is_allowed()
                    try:
                        if verify_is_allowed and validate_remember_device_cookie(
                                value,
                                user=user,
                                otp_device_id=device.persistent_id):
                            user.otp_device = device
                            device.throttle_reset()
                            return True
                    except BadSignature:
                        device.throttle_increment()
                        # Remove remember cookies with invalid signature to omit unnecessary throttling
                        self.cookies_to_delete.append(key)
        return False

    def delete_cookies_from_response(self, response):
        """
        Deletes the cookies_to_delete in the response
        """
        for cookie in self.cookies_to_delete:
            response.delete_cookie(cookie)
        return response

    # Copied from django.conrib.auth.views.LoginView  (Branch: stable/1.11.x)
    # https://github.com/django/django/blob/58df8aa40fe88f753ba79e091a52f236246260b3/django/contrib/auth/views.py#L49
    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        if self.redirect_authenticated_user and self.request.user.is_authenticated:
            redirect_to = self.get_success_url()
            if redirect_to == self.request.path:
                raise ValueError(
                    "Redirection loop for authenticated user detected. Check that "
                    "your LOGIN_REDIRECT_URL doesn't point to a login page.")
            return HttpResponseRedirect(redirect_to)
        return super().dispatch(request, *args, **kwargs)
Exemplo n.º 11
0
class RegistrationView(APIView):
    # pylint: disable=missing-docstring
    """HTTP end-points for creating a new user. """

    # This end-point is available to anonymous users,
    # so do not require authentication.
    authentication_classes = []

    @method_decorator(transaction.non_atomic_requests)
    @method_decorator(sensitive_post_parameters("password"))
    def dispatch(self, request, *args, **kwargs):
        return super(RegistrationView, self).dispatch(request, *args, **kwargs)

    @method_decorator(ensure_csrf_cookie)
    def get(self, request):
        return HttpResponse(
            RegistrationFormFactory().get_registration_form(request).to_json(),
            content_type="application/json")

    @method_decorator(csrf_exempt)
    def post(self, request):
        """Create the user's account.

        You must send all required form fields with the request.

        You can optionally send a "course_id" param to indicate in analytics
        events that the user registered while enrolling in a particular course.

        Arguments:
            request (HTTPRequest)

        Returns:
            HttpResponse: 200 on success
            HttpResponse: 400 if the request is not valid.
            HttpResponse: 409 if an account with the given username or email
                address already exists
            HttpResponse: 403 operation not allowed
        """
        data = request.POST.copy()
        self._handle_terms_of_service(data)

        response = self._handle_duplicate_email_username(data)
        if response:
            return response

        response, user = self._create_account(request, data)
        if response:
            return response

        response = self._create_response({}, status_code=200)
        set_logged_in_cookies(request, response, user)
        return response

    def _handle_duplicate_email_username(self, data):
        # TODO Verify whether this check is needed here - it may be duplicated in user_api.
        email = data.get('email')
        username = data.get('username')

        conflicts = check_account_exists(email=email, username=username)
        if conflicts:
            conflict_messages = {
                "email":
                accounts_settings.EMAIL_CONFLICT_MSG.format(
                    email_address=email),  # pylint: disable=no-member
                "username":
                accounts_settings.USERNAME_CONFLICT_MSG.format(
                    username=username),  # pylint: disable=no-member
            }
            errors = {
                field: [{
                    "user_message": conflict_messages[field]
                }]
                for field in conflicts
            }
            return self._create_response(errors, status_code=409)

    def _handle_terms_of_service(self, data):
        # Backwards compatibility: the student view expects both
        # terms of service and honor code values.  Since we're combining
        # these into a single checkbox, the only value we may get
        # from the new view is "honor_code".
        # Longer term, we will need to make this more flexible to support
        # open source installations that may have separate checkboxes
        # for TOS, privacy policy, etc.
        if data.get("honor_code") and "terms_of_service" not in data:
            data["terms_of_service"] = data["honor_code"]

    def _create_account(self, request, data):
        response, user = None, None
        try:
            user = create_account_with_params(request, data)
        except AccountValidationError as err:
            errors = {err.field: [{"user_message": text_type(err)}]}
            response = self._create_response(errors, status_code=409)
        except ValidationError as err:
            # Should only get field errors from this exception
            assert NON_FIELD_ERRORS not in err.message_dict
            # Only return first error for each field
            errors = {
                field: [{
                    "user_message": error
                } for error in error_list]
                for field, error_list in err.message_dict.items()
            }
            response = self._create_response(errors, status_code=400)
        except PermissionDenied:
            response = HttpResponseForbidden(
                _("Account creation not allowed."))

        return response, user

    def _create_response(self, response_dict, status_code):
        if status_code == 200:
            # keeping this `success` field in for now, as we have outstanding clients expecting this
            response_dict['success'] = True
        return JsonResponse(response_dict, status=status_code)
Exemplo n.º 12
0
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.debug import sensitive_post_parameters
from rest_auth.app_settings import (TokenSerializer, JWTSerializer,
                                    create_token)
from rest_auth.models import TokenModel
from rest_auth.utils import jwt_encode
from rest_framework import status
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny

from .serializers import RegisterSerializer

sensitive_post_parameters_m = method_decorator(
    sensitive_post_parameters('password'))


class RegisterView(CreateAPIView):
    serializer_class = RegisterSerializer
    permission_classes = (AllowAny, )
    token_model = TokenModel

    @sensitive_post_parameters_m
    def dispatch(self, *args, **kwargs):
        return super(RegisterView, self).dispatch(*args, **kwargs)

    def get_response_data(self, user):
        if allauth_settings.EMAIL_VERIFICATION == \
                allauth_settings.EmailVerificationMethod.MANDATORY:
            return {"detail": _("Verification e-mail sent.")}
Exemplo n.º 13
0
class UserProfileAdmin(UserAdmin):
    search_fields = [
        'userprofile__persona__num_identificacion',
        'username',
        'email',
    ]
    inlines = [
        UserProfileInline,
    ]
    staff_fieldsets = ((None, {
        'fields': ('username', 'password')
    }), (_('Personal info'), {
        'fields': ('first_name', 'last_name', 'email')
    }), (_('Permissions'), {
        'fields': ('is_active', )
    }), (_('Important dates'), {
        'fields': ('last_login', 'date_joined')
    }), (_('Groups'), {
        'fields': ('groups', )
    }))
    staff_fieldsets_sinpass = ((None, {
        'fields': ('username', )
    }), (_('Personal info'), {
        'fields': ('first_name', 'last_name', 'email')
    }), (_('Permissions'), {
        'fields': ('is_active', )
    }), (_('Important dates'), {
        'fields': ('last_login', 'date_joined')
    }), (_('Groups'), {
        'fields': ('groups', )
    }))
    add_fieldsets = ((None, {
        'classes': ('wide', ),
        'fields': ('username', 'password1', 'password2')
    }), )

    def queryset(self, request):
        qs = super(UserProfileAdmin, self).queryset(request)
        if not request.user.is_superuser:
            qs = qs.exclude(is_superuser=True)
        return qs

    ''' Para poder obtener el usuario desde el formulario UserFormChange definimos la variable aqui'''

    def get_form(self, request, obj=None, **kwargs):
        form = super(UserProfileAdmin, self).get_form(request, obj, **kwargs)
        form.current_user = request.user
        ''' Si se esta editando el mismo usuario  y no es superusuario se muestran los grupos a los que pertenece el usuario, si no es el mismo usuario solo muestra estudiantes '''
        '''
        if not request.user.is_superuser:
            from django.db.models import Q
            if obj==request.user:
                form.base_fields['groups'].queryset=(grupos|request.user.groups.all()).distinct()
            else:
                form.base_fields['groups'].queryset=grupos
        '''
        return form

    ''' Evita escalabilidad de privilegios cuando  un usuario staff NO superUsuario intente cambiar la clave de un SuperUsuario. '''
    from django.views.decorators.debug import sensitive_post_parameters

    @method_decorator(sensitive_post_parameters())
    def user_change_password(self, request, id, form_url=''):
        if not request.user.is_superuser and self.queryset(request).get(
                pk=id).is_superuser:
            from django.core.exceptions import PermissionDenied
            raise PermissionDenied
        else:
            return super(UserProfileAdmin,
                         self).user_change_password(request, id, form_url)

    '''
    No mostrar la opcion de SuperUsuario si no se es un superusuario. Evitar bug de escalabilida de permisos
    '''

    def change_view(self, request, *args, **kwargs):
        # for non-superuser
        if not request.user.is_superuser:
            try:
                #Si el usuario editado es un SuperUsuario y el editor no lo es,o Si el usuario editado es staff  NO se muestra el enlace de cambiar clave. Evitando escalabilidad de privilegios

                if self.queryset(request).get(
                        pk=args[0]).is_superuser or self.queryset(request).get(
                            pk=args[0]).is_staff:
                    self.fieldsets = self.staff_fieldsets_sinpass
                else:
                    self.fieldsets = self.staff_fieldsets
                ''' Se limita los grupos disponibles a los que posee el usuario y a Estudiante'''
                response = super(UserAdmin,
                                 self).change_view(request, *args, **kwargs)

                #response = super(UserAdmin,self).change_view( request, *args, **kwargs)
            finally:
                # Reset fieldsets to its original value
                self.fieldsets = super(UserAdmin, self).fieldsets
            return response
        else:
            return super(UserAdmin, self).change_view(request, *args, **kwargs)
Exemplo n.º 14
0
from django.conf import settings
from django.http import HttpResponseRedirect
from django.contrib.auth.forms import AuthenticationForm
from django.template.response import TemplateResponse
from django.utils.http import is_safe_url
from django.shortcuts import resolve_url
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login
from django.contrib.sites.models import get_current_site


sensitive_post_parameters()
@csrf_protect
@never_cache
def login(request, template_name='admin/login.html',
          redirect_field_name=REDIRECT_FIELD_NAME,
          authentication_form=AuthenticationForm,
          current_app=None, extra_context=None):
    """
    Displays the login form and handles the login action.
    """
    redirect_to = request.REQUEST.get(redirect_field_name, '')

    if request.method == "POST":
        form = authentication_form(data=request.POST)
        if form.is_valid():
        
            # Check for remember me tick.
            if request.REQUEST.get('remember_me', None):
    def update(self, request, *args, **kwargs):
        try:
            self.get_object()
            return Response({}, status=status.HTTP_200_OK)
        except Http404:
            data = {
                'user': self.user.pk,
                'name': kwargs.get('name') or '',
            }
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response({}, status=status.HTTP_201_CREATED)


@method_decorator(sensitive_post_parameters('old_password', 'new_password'), name='dispatch')
class ChangePasswordView(generics.GenericAPIView):
    permission_classes = (IsAuthenticated, AnyAdminClientIDPermissions)
    serializer_class = ChangePasswordSerializer

    @atomic
    @method_decorator(sensitive_variables('old_password', 'new_password'))
    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            old_password = serializer.validated_data['old_password']
            new_password = serializer.validated_data['new_password']

            try:
                if not FailedLoginAttempt.objects.is_locked_out(
                        request.user, request.auth.application):
Exemplo n.º 16
0
)
from django.contrib.auth.models import Group, User
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.html import escape
from django.utils.translation import ugettext, ugettext_lazy as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters

csrf_protect_m = method_decorator(csrf_protect)
sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())


@admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
    search_fields = ('name', )
    ordering = ('name', )
    filter_horizontal = ('permissions', )

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        if db_field.name == 'permissions':
            qs = kwargs.get('queryset', db_field.remote_field.model.objects)
            # Avoid a major performance hit resolving permission names which
            # triggers a content_type load:
            kwargs['queryset'] = qs.select_related('content_type')
        return super(GroupAdmin,
Exemplo n.º 17
0
class LoginView(SuccessURLAllowedHostsMixin, FormView):
    """
    Display the login form and handle the login action.
    """
    form_class = AuthenticationForm
    authentication_form = None
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'registration/login.html'
    redirect_authenticated_user = False
    extra_context = None

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        if self.redirect_authenticated_user and self.request.user.is_authenticated:
            redirect_to = self.get_success_url()
            if redirect_to == self.request.path:
                raise ValueError(
                    "Redirection loop for authenticated user detected. Check that "
                    "your LOGIN_REDIRECT_URL doesn't point to a login page.")
            return HttpResponseRedirect(redirect_to)
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self):
        url = self.get_redirect_url()
        return url or resolve_url(settings.LOGIN_REDIRECT_URL)

    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name,
            self.request.GET.get(self.redirect_field_name, ''))
        url_is_safe = url_has_allowed_host_and_scheme(
            url=redirect_to,
            allowed_hosts=self.get_success_url_allowed_hosts(),
            require_https=self.request.is_secure(),
        )
        return redirect_to if url_is_safe else ''

    def get_form_class(self):
        return self.authentication_form or self.form_class

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_valid(self, form):
        """Security check complete. Log the user in."""
        auth_login(self.request, form.get_user())
        return HttpResponseRedirect(self.get_success_url())

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        current_site = get_current_site(self.request)
        context.update({
            self.redirect_field_name: self.get_redirect_url(),
            'site': current_site,
            'site_name': current_site.name,
            **(self.extra_context or {})
        })
        return context
Exemplo n.º 18
0
class ChangeInformationView(CustomerRequiredMixin, FormView):
    template_name = 'pretixpresale/organizers/customer_info.html'
    form_class = ChangeInfoForm

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        if not request.organizer.settings.customer_accounts:
            raise Http404('Feature not enabled')
        if self.request.customer:
            self.initial_email = self.request.customer.email
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self):
        return eventreverse(self.request.organizer,
                            'presale:organizer.customer.profile',
                            kwargs={})

    def form_valid(self, form):
        if form.cleaned_data['email'] != self.initial_email:
            new_email = form.cleaned_data['email']
            form.cleaned_data[
                'email'] = form.instance.email = self.initial_email
            ctx = form.instance.get_email_context()
            ctx['url'] = build_absolute_uri(
                self.request.organizer,
                'presale:organizer.customer.change.confirm'
            ) + '?token=' + dumps(
                {
                    'customer': form.instance.pk,
                    'email': new_email
                },
                salt='pretix.presale.views.customer.ChangeInformationView')
            mail(
                new_email,
                _('Confirm email address for your account at {organizer}'
                  ).format(organizer=self.request.organizer.name),
                self.request.organizer.settings.
                mail_text_customer_email_change,
                ctx,
                locale=form.instance.locale,
                customer=form.instance,
                organizer=self.request.organizer,
            )
            messages.success(
                self.request,
                _('Your changes have been saved. We\'ve sent you an email with a link to update your '
                  'email address. The email address of your account will be changed as soon as you '
                  'click that link.'))
        else:
            messages.success(self.request, _('Your changes have been saved.'))

        with transaction.atomic():
            form.save()
            d = dict(form.cleaned_data)
            del d['email']
            self.request.customer.log_action('pretix.customer.changed', d)

        update_customer_session_auth_hash(self.request, form.instance)
        return HttpResponseRedirect(self.get_success_url())

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        kwargs['instance'] = self.request.customer
        return kwargs
Exemplo n.º 19
0
class RefreshApiView(CsrfExemptMixin, TokenView):
    @method_decorator(sensitive_post_parameters('password'))
    def post(self, request, *args, **kwargs):
        request = services.config_refresh_request(request)
        url, headers, body, status = self.create_token_response(request)
        return services.create_auth_response(body, headers, status)
Exemplo n.º 20
0
class ProfileUpdate(View):
    """Class for creating user with no priviledges"""

    template_name = "account/dashboard/profile_edit.html"

    profile_form_class = ProfileUpdateForm
    user_form_class = UserUpdateForm

    title = _('CodeTopia | Update Profile')
    extra_context = None

    # Error messages for the view
    error_messages = {
        "already_have_account":
        _("You already have an account and can not create another account.")
    }
    # Success messages for the view
    success_messages = {
        "profile_updated":
        _("Congradulation %s you have updated your profile succesfully.")
    }

    def get_context_data(self, *args, **kwargs):
        """Return all context data by collecting it."""
        current_site = get_current_site(self.request)
        context = {
            "site": current_site,
            "site_name": current_site.name,
            "title": self.title
        }
        context.update(**(self.extra_context or {}))
        return context

    def get_profile_form_class(self, *args, **kwargs):
        """Return the instance of the for class to be used."""
        return self.profile_form_class(*args)

    def get_user_form_class(self, *args, **kwargs):
        """Return the instance of the for class to be used."""
        return self.user_form_class(*args)

    def get(self, request, *args, **kwargs):

        self.extra_context = {
            "user_form": self.user_form_class(instance=request.user),
            "profile_form":
            self.profile_form_class(instance=request.user.profile)
        }
        return render(request=request,
                      template_name=self.template_name,
                      context=self.get_context_data())

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    def post(self, request, *args, **kwargs):
        user_form = self.user_form_class(instance=request.user,
                                         data=request.POST),
        profile_form = self.profile_form_class(instance=request.user.profile,
                                               data=request.POST,
                                               files=request.FILES)

        if user_form.is_valid() and profile_form.is_valid():
            user_cache = user_form.save()
            profile_form.save()
            messages.success(
                request=self.request,
                message=self.success_messages.get("profile_updated") %
                user_cache.username)

            return HttpResponseRedirect(
                reverse(viewname="account:user_dashboard"))

        # If the form is invalid return the form with error messages
        self.extra_context = {
            **self.get_context_data(), "user_form": user_form,
            "profile_form": profile_form
        }
        return render(request=self.request,
                      template_name=self.template_name,
                      context=self.get_context_data())
Exemplo n.º 21
0
from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic import TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormView, UpdateView

from pepysdiary.annotations.models import Annotation
from pepysdiary.common.models import Config
from pepysdiary.membership import forms
from pepysdiary.membership.models import Person


@method_decorator([csrf_protect, never_cache, sensitive_post_parameters('password1', 'password2')], name='dispatch')
class RegisterView(FormView):
    template_name = 'register.html'
    form_class = forms.RegistrationForm

    def get(self, request, *args, **kwargs):
        if request.user.is_authenticated():
            return redirect('home')
        else:
            return super(RegisterView, self).get(request, *args, **kwargs)

    def get_success_url(self):
        if self.success_url:
            return self.success_url
        return reverse('register_complete')
Exemplo n.º 22
0
class UserPasswordChangeView(PasswordContextMixin, FormView):
    """
    View for changing user password using validated old password.
    Interface for UserDashboard
    """
    form_class = PasswordChangeForm
    success_url = None
    template_name = "account/dashboard/change_password.html"
    title = _("CodeTopia | Chnage Password")

    success_messages = {
        "succesfull": _("You have successfully changed your password.")
    }

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

    def get_success_url(self):
        """Return the URL to redirect to after processing a valid form."""
        if self.success_url is not None:
            url = self.success_url.format(**self.object.__dict__)
        url = reverse(viewname="account:user_dashboard",
                      kwargs={"username": self.request.user.username})
        return url

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def form_valid(self, form):
        form.save()

        # Log out the user from other sessions and update the current session with
        # new password hash
        update_session_auth_hash(self.request, form.user)

        # send password changed message
        messages.success(request=self.request,
                         message=self.success_messages.get("succesfull"))

        return super().form_valid(form)

    def post(self, request, *args, **kwargs):
        """
        Handle POST requests: instantiate a form instance with the passed
        POST variables and then check if it's valid.
        """
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    # PUT is a valid HTTP verb for creating (with a known URL) or editing an
    # object, note that browsers only support POST for now.
    def put(self, *args, **kwargs):
        return self.post(*args, **kwargs)
Exemplo n.º 23
0
from common.mixins import DatetimeSearchMixin
from ..models import User, LoginLog
from ..utils import send_reset_password_mail
from ..tasks import write_login_log_async
from .. import forms


__all__ = [
    'UserLoginView', 'UserLogoutView',
    'UserForgotPasswordView', 'UserForgotPasswordSendmailSuccessView',
    'UserResetPasswordView', 'UserResetPasswordSuccessView',
    'UserFirstLoginView', 'LoginLogListView'
]


@method_decorator(sensitive_post_parameters(), name='dispatch')
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(never_cache, name='dispatch')
class UserLoginView(FormView):
    template_name = 'users/login.html'
    form_class = forms.UserLoginForm
    redirect_field_name = 'next'

    def get(self, request, *args, **kwargs):
        if request.user.is_staff:
            return redirect(self.get_success_url())
        request.session.set_test_cookie()
        return super().get(request, *args, **kwargs)

    def form_valid(self, form):
        if not self.request.session.test_cookie_worked():
Exemplo n.º 24
0
class CreateUserView(View):
    """Class for creating user with no priviledges"""

    template_name = "account/create_account.html"

    form_class = UserCreationForm
    title = _('CodeTopia | Create Account')
    extra_context = None

    # Error messages for the view
    error_messages = {
        "already_have_account":
        _("You already have an account and can not create another account.")
    }
    # Success messages for the view
    success_messages = {
        "account_created":
        _("Congradulation %s you have created  an account succesfully.")
    }

    def get_context_data(self, *args, **kwargs):
        """Return all context data by collecting it."""
        current_site = get_current_site(self.request)
        context = {
            "site": current_site,
            "site_name": current_site.name,
            "title": self.title
        }
        context.update(**(self.extra_context or {}))
        return context

    def get_form_class(self, *args, **kwargs):
        """Return the instance of the for class to be used."""
        return self.form_class(*args)

    def get(self, *args, **kwargs):
        if self.request.user.is_authenticated:
            messages.error(
                request=self.request,
                message=self.error_messages.get("already_have_account"))
            return HttpResponseRedirect(reverse("core:homepage"))

        self.extra_context = {"form": self.get_form_class()}
        return render(request=self.request,
                      template_name=self.template_name,
                      context=self.get_context_data())

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    def post(self, *args, **kwargs):
        form = self.get_form_class(self.request.POST)
        if form.is_valid():
            user_cache = form.save()
            messages.success(
                request=self.request,
                message=self.success_messages.get("account_created") %
                user_cache.username)

            return HttpResponseRedirect(reverse(viewname="account:user_login"))

        # If the form is invalid return the form with error messages
        self.extra_context = {**self.get_context_data(), "form": form}
        return render(request=self.request,
                      template_name=self.template_name,
                      context=self.get_context_data())
Exemplo n.º 25
0
from django.views.generic import RedirectView
from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables

from cas_server import views

app_name = "cas_server"

urlpatterns = [
    url(
        r'^$',
        RedirectView.as_view(pattern_name="cas_server:login", permanent=False, query_string=True)
    ),
    url(
        '^login$',
        sensitive_post_parameters('password')(
            views.LoginView.as_view()
        ),
        name='login'
    ),
    url('^logout$', views.LogoutView.as_view(), name='logout'),
    url('^validate$', views.Validate.as_view(), name='validate'),
    url(
        '^serviceValidate$',
        views.ValidateService.as_view(allow_proxy_ticket=False),
        name='serviceValidate'
    ),
    url(
        '^proxyValidate$',
        views.ValidateService.as_view(allow_proxy_ticket=True),
        name='proxyValidate'
    ),
Exemplo n.º 26
0
class PrescriptionSite(AuditSite):
    def has_permission(self, request):
        return request.user.is_active

    def get_urls(self):
        """
        Add a view to clear the current prescription from the session
        """
        from django.conf.urls import patterns, url

        def wrap(view, cacheable=False):
            def wrapper(*args, **kwargs):
                return self.admin_view(view, cacheable)(*args, **kwargs)

            return update_wrapper(wrapper, view)

        urlpatterns = patterns(
            '',
            url(r'^administration/$', wrap(self.site_admin),
                name='site_admin'),
            url(r'^profile/$', wrap(self.profile), name='profile'),
            url(r'^endorse-authorise/$',
                wrap(self.endorse_authorise_summary),
                name='endorse_authorise_summary'),
            #            url(r'^daily-burn-program/$',
            #                wrap(self.daily_burn_program),
            #                name='daily_burn_program'),
            #            url(r'^daily-burn-program/add$',
            #                wrap(self.daily_burn_program_add),
            #                name='daily_burn_program_add'),
            url(r'^endorse-authorise/export_csv/$',
                wrap(self.export_to_csv),
                name='endorse_authorise_exportcsv'),
        )

        return urlpatterns + super(PrescriptionSite, self).get_urls()

    def index(self, request):
        try:
            profile = request.user.profile
        except:
            profile = None

        url = reverse('admin:prescription_prescription_changelist')
        if profile is not None and profile.region:
            url += '?region__id__exact=%s' % profile.region.id
        return HttpResponseRedirect(url)

    def password_change(self, request):
        if request.user.profile.is_fpc_user():
            return super(PrescriptionSite, self).password_change(request)
        else:
            return HttpResponseForbidden("You are not an FPC user. Only FPC "
                                         "users can change their password "
                                         "via this interface.")

    def register(self, model, admin_class=None, **options):
        try:
            super(PrescriptionSite, self).register(model, admin_class,
                                                   **options)
        except ImproperlyConfigured:
            self._registry[model] = admin_class(model, self)

    @method_decorator(sensitive_post_parameters())
    @never_cache
    def login(self,
              request,
              redirect_field_name=REDIRECT_FIELD_NAME,
              authentication_form=PbsAdminAuthenticationForm,
              extra_context=None):
        """
        Displays the login form and handles the login action.
        """
        redirect_to = request.REQUEST.get(redirect_field_name, '')

        if request.method == 'POST':
            form = authentication_form(request, data=request.POST)
            if form.is_valid():

                # Ensure the user-originating redirection url is safe.
                if not is_safe_url(url=redirect_to, host=request.get_host()):
                    redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)

                # If this is the user's first login, redirect them to
                # edit their profile.
                user = form.get_user()
                if user.last_login == user.date_joined:
                    request.session['first_login'] = True
                    redirect_to = reverse('admin:profile')

                # Okay, security check complete. Log the user in.
                login(request, user)

                return HttpResponseRedirect(redirect_to)
        else:
            form = authentication_form(request)

        current_site = get_current_site(request)

        # We won't need this in Django 1.6
        request.session.set_test_cookie()

        context = {
            'title': _('Log in'),
            'app_path': request.get_full_path(),
            'form': form,
            redirect_field_name: request.get_full_path(),
            'site': current_site,
            'site_name': current_site.name,
        }
        if extra_context is not None:
            context.update(extra_context)
        return TemplateResponse(request,
                                self.login_template or 'admin/login.html',
                                context,
                                current_app=self.name)

    @never_cache
    def logout(self, request, extra_context=None):
        from django.contrib.auth.views import logout
        return logout(request, reverse('admin:index', current_app=self.name))

    def site_admin(self, request, extra_context=None):
        context = {}
        context.update(extra_context or {})
        return TemplateResponse(request,
                                "admin/site_admin.html",
                                context,
                                current_app=self.name)

    def profile(self, request):
        profile = request.user.get_profile()
        if request.method == 'POST':
            form = ProfileForm(request.POST, instance=profile)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(
                    reverse('admin:index', current_app=self.name))
        else:
            form = ProfileForm(instance=profile)
        context = {'title': _('Edit profile'), 'form': form}
        return TemplateResponse(request,
                                "admin/profile.html",
                                context,
                                current_app=self.name)

    def endorse_authorise_summary(self, request, extra_context=None):
        """
        Display summaries of prescriptions, approvals and ignitions.

        DEV:

        """
        form = EndorseAuthoriseSummaryForm(request.GET)

        report_set = {'summary', 'approvals', 'ignitions'}
        report = request.GET.get('report', 'summary')
        if report not in report_set:
            report = 'summary'

        export_csv = True if request.GET.get(
            'Export_CSV') == 'export_csv' else False

        if request.GET.get('fromDate'):
            fromDate = request.GET.get('fromDate')
            fromDate = datetime.datetime.strptime(fromDate, '%d-%m-%Y').date()
        else:
            # default - beginning of current financial year
            today = datetime.date.today()
            financial_year = datetime.date(today.year, 7, 1)
            if today < financial_year:
                #today is early than the first day of this year's financial year, set fromDate to last year's financial year
                fromDate = datetime.date(today.year - 1, 7, 1)
            else:
                #today is later than the first day of this year's financial year, set fromDate to this year's financial year
                fromDate = financial_year

        if request.GET.get('toDate'):
            toDate = request.GET.get('toDate')
            toDate = datetime.datetime.strptime(toDate, '%d-%m-%Y').date()
        else:
            toDate = datetime.date.today()

        burns = []
        if report == 'summary':
            title = _("Endorsements summary")
            queryset = Prescription.objects.filter(
                endorsement_status=Prescription.ENDORSEMENT_SUBMITTED)
        elif report == 'approvals':
            title = _("Approvals summary")
            queryset = Prescription.objects.filter(
                approval_status=Prescription.APPROVAL_SUBMITTED)
        elif report == 'ignitions':
            title = _("Ignitions summary")
            queryset = None
            burns = self.get_burns(fromDate, toDate)
        else:
            raise ValueError("Report {} must be in {}".format(
                report, report_set))

        if export_csv:
            return self.export_to_csv(request, fromDate, toDate, burns)
        if queryset:
            queryset.prefetch_related('endorsing_roles')

        if form.is_valid():
            region = form.cleaned_data.get('region', None)
            district = form.cleaned_data.get('district', None)

            if region:
                queryset = queryset.filter(region=region)

            if district:
                queryset = queryset.filter(district=district)

        context = {
            'title': title,
            'prescriptions': queryset,
            'form': form,
            'report': report,
            'burns': burns,
            'fromDate': fromDate,
            'toDate': toDate,
        }
        context.update(extra_context or {})
        return TemplateResponse(request,
                                "admin/endorse_authorise_summary.html",
                                context,
                                current_app=self.name)

    def get_burns(self, fromDate, toDate):

        query_list = []

        for p in Prescription.objects.all():
            for a in p.areaachievement_set.all():
                region_type = 'Forest' if str(
                    p.region) in forest_regions else 'Non-forest'
                if a.ignition >= fromDate and a.ignition <= toDate and p.ignition_status != p.IGNITION_COMPLETE:
                    query_list.append([
                        int(p.id),
                        str(p.burn_id),
                        str(p.region),
                        str(p.district), 'commenced',
                        str(a.ignition),
                        float(a.area_treated), region_type
                    ])

                elif a.ignition >= fromDate and a.ignition <= toDate and p.ignition_status == p.IGNITION_COMPLETE:
                    query_list.append([
                        int(p.id),
                        str(p.burn_id),
                        str(p.region),
                        str(p.district), 'completed',
                        str(a.ignition),
                        float(a.area_treated), region_type
                    ])

        result = []
        # collate the results
        sub_results = self.collate_results(query_list, 'Forest')
        result += sub_results

        sub_results = self.collate_results(query_list, 'Non-forest')
        result += sub_results
        # don't double count Sub-Totals in Total, and ignore blank rows
        total_completed = sum([
            ll[1] for ll in result
            if len(ll) > 0 and re.search('Total', ll[0])
        ])
        total_commenced = sum([
            ll[2] for ll in result
            if len(ll) > 0 and re.search('Total', ll[0])
        ])
        total_area = sum([
            ll[3] for ll in result
            if len(ll) > 0 and re.search('Total', ll[0])
        ])
        result.append(['Total', total_completed, total_commenced, total_area])

        return result

    def collate_results(self, query_list, region_type):
        results = []
        regions = set([ll[2] for ll in query_list
                       if region_type in ll])  # unique list of region's
        for region in regions:
            # count of completed/commenced burns and sum(area) for given region
            completed_burns = len(
                set([
                    ll[1] for ll in query_list
                    if (region in ll and 'completed' in ll)
                ]))
            commenced_burns = len(
                set([
                    ll[1] for ll in query_list
                    if (region in ll and 'commenced' in ll)
                ]))
            area = sum([ll[6] for ll in query_list if (region in ll)])

            results.append([region, completed_burns, commenced_burns, area])

        total_completed = sum([ll[1] for ll in results])
        total_commenced = sum([ll[2] for ll in results])
        total_area = sum([ll[3] for ll in results])
        results.append([
            '{} Sub-Total'.format(region_type), total_completed,
            total_commenced, total_area
        ])
        results.append([] * 4)

        return results

    def export_to_csv(self, request, fromDate, toDate, burns=None):
        local_zone = tz.tzlocal()
        query_list = []
        id_list = []

        for p in Prescription.objects.all():
            for a in p.areaachievement_set.all():

                if a.ignition >= fromDate and a.ignition <= toDate:

                    p_id = p.id
                    p_count = 0 if p_id in id_list else 1  # get a unique count of prescription
                    id_list.append(p_id)
                    region = str(p.region)
                    region_type = 'Forest' if region in forest_regions else 'Non-forest'
                    district = str(p.district)
                    burn_name = str(p.name)
                    burn_id = str(p.burn_id)
                    date_updated = str(
                        p.modified.astimezone(local_zone).strftime(
                            '%d/%m/%Y %H:%M:%S'))
                    ignition_status = p.get_ignition_status_display()
                    burn_closed = "Yes" if p.status == p.STATUS_CLOSED else "No"
                    burn_complexity = p.maximum_complexity
                    burn_priority = p.get_priority_display()
                    burn_risk = p.maximum_risk
                    contentious = "Yes" if p.contentious else "No"
                    year = p.planned_year
                    season = p.financial_year
                    actual_ignitions = ('"%s"' % ",".join(
                        ",".join('{0}:{1}'.format(
                            x.ignition.strftime('%d/%m/%Y'), ignition_type)
                                 for ignition_type in
                                 (x.ignition_types.all() or ("Unset", )))
                        for x in p.areaachievement_set.order_by('ignition')))
                    planned_burn_area = p.area
                    total_treatment_area = p.total_treatment_area
                    burnt_area_estimate = p.total_burnt_area_estimate
                    length_of_edging = p.total_edging_length
                    depth_of_edging = p.total_edging_depth
                    shires = '"%s"' % ",".join(x.name for x in p.shires.all())
                    purposes = '"%s"' % ",".join(x.name
                                                 for x in p.purposes.all())
                    allocations = p.allocations
                    tenures = '"%s"' % ",".join(x.name
                                                for x in p.tenures.all())
                    #escape_dates = ", ".join([datetime.strftime(x.date_escaped, '%d/%m/%Y') for x in a.filter(date_escaped__isnull=False).order_by('ignition')])
                    #dpaw_fire_nums = '"%s"' % ",".join(x.dpaw_fire_no for x in a.exclude(dpaw_fire_no__isnull=True).exclude(dpaw_fire_no__exact='').order_by('ignition'))
                    #dfes_fire_nums = '"%s"' % ",".join(x.dfes_fire_no for x in a.exclude(dfes_fire_no__isnull=True).exclude(dfes_fire_no__exact='').order_by('ignition'))
                    success_criterias = '"%s"' % ",".join(
                        x.criteria
                        for x in p.successcriteria_set.all().order_by('id'))

                    if p.ignition_status != p.IGNITION_COMPLETE:

                        query_list.append([
                            p_id,
                            p_count,
                            burn_id,
                            burn_name,
                            region,
                            district,
                            'commenced',
                            str(a.ignition),
                            float(a.area_treated),
                            region_type,
                            date_updated,
                            ignition_status,
                            burn_closed,
                            burn_complexity,
                            burn_priority,
                            burn_risk,
                            contentious,
                            year,
                            season,
                            actual_ignitions,
                            planned_burn_area,
                            total_treatment_area,
                            burnt_area_estimate,
                            length_of_edging,
                            depth_of_edging,
                            shires,
                            purposes,
                            allocations,
                            tenures,
                            #escape_dates, dpaw_fire_nums, dfes_fire_nums,.
                            success_criterias
                        ])

                    elif p.ignition_status == p.IGNITION_COMPLETE:

                        query_list.append([
                            p_id,
                            p_count,
                            burn_id,
                            burn_name,
                            region,
                            district,
                            'completed',
                            str(a.ignition),
                            float(a.area_treated),
                            region_type,
                            date_updated,
                            ignition_status,
                            burn_closed,
                            burn_complexity,
                            burn_priority,
                            burn_risk,
                            contentious,
                            year,
                            season,
                            actual_ignitions,
                            planned_burn_area,
                            total_treatment_area,
                            burnt_area_estimate,
                            length_of_edging,
                            depth_of_edging,
                            shires,
                            purposes,
                            allocations,
                            tenures,
                            #escape_dates, dpaw_fire_nums, dfes_fire_nums,.
                            success_criterias
                        ])

        filename = 'export_burn_{0}-{1}.csv'.format(
            fromDate.strftime('%d%b%Y'), toDate.strftime('%d%b%Y'))
        response = HttpResponse(content_type="text/csv")
        response['Content-Disposition'] = 'attachment; filename={}'.format(
            filename)
        writer = unicodecsv.writer(response, quoting=unicodecsv.QUOTE_ALL)

        writer.writerow([
            'Prescription_ID', 'Prescription Count', 'Burn ID', 'Name of Burn',
            'Region', 'District', 'Status', 'Ignition Date', 'Burn area (ha)',
            'Region Type', 'Date Updated', 'Ignition Status', 'Burn Closed',
            'Burn Complexity', 'Burn Priority', 'Burn Risk', 'Contentious',
            'Year', 'Season', 'Actual Ignition Type', 'Planned Burn Area',
            'Total Area Where Treatment Is Complete',
            'Total Treatment Activity', 'Length of Edging/Perimeter',
            'Depth of Edging', 'Shire', 'Burn Purpose/s',
            'Program Allocations', 'Land Tenure', 'Success Criteria'
        ])

        for burn in query_list:
            writer.writerow([unicode(s).encode("utf-8") for s in burn])

        return response

    export_to_csv.short_description = ugettext_lazy("Export to CSV")
Exemplo n.º 27
0
class LDAPAuthenticationBackend(ModelBackend):
    """ This class provides LDAP authentication against an LDAP or Active Directory server. """
    @method_decorator(sensitive_post_parameters('password'))
    def authenticate(self,
                     request,
                     username=None,
                     password=None,
                     **keyword_arguments):

        # Check for remote user in extra arguments if no username and password.
        # In case of basic authentication
        if not username or not password:
            if 'remote_user' in keyword_arguments:
                credentials = base_64_decode_basic_auth(
                    keyword_arguments['remote_user'])
                if credentials:
                    username, password = credentials[0], credentials[1]
                else:
                    return None
            else:
                return None

        user = check_user_exists_and_active(self, username)

        is_authenticated_with_ldap = False
        errors = []
        for server in settings.LDAP_SERVERS:
            try:
                port = server.get('port', 636)
                use_ssl = server.get('use_ssl', True)
                bind_as_authentication = server.get('bind_as_authentication',
                                                    True)
                domain = server.get('domain')
                t = Tls(validate=CERT_REQUIRED,
                        version=PROTOCOL_TLSv1_2,
                        ca_certs_file=server.get('certificate'))
                s = Server(server['url'], port=port, use_ssl=use_ssl, tls=t)
                auto_bind = AUTO_BIND_TLS_BEFORE_BIND if use_ssl else AUTO_BIND_NO_TLS
                ldap_bind_user = f"{domain}\\{username}" if domain else username
                if not bind_as_authentication:
                    # binding to LDAP first, then search for user
                    bind_username = server.get('bind_username', None)
                    bind_username = f"{domain}\\{bind_username}" if domain and bind_username else bind_username
                    bind_password = server.get('bind_password', None)
                    authentication = SIMPLE if bind_username and bind_password else ANONYMOUS
                    c = Connection(s,
                                   user=bind_username,
                                   password=bind_password,
                                   auto_bind=auto_bind,
                                   authentication=authentication,
                                   raise_exceptions=True)
                    search_username_field = server.get('search_username_field',
                                                       'uid')
                    search_attribute = server.get('search_attribute', 'cn')
                    search = c.search(server['base_dn'],
                                      f"({search_username_field}={username})",
                                      attributes=[search_attribute])
                    if not search or search_attribute not in c.response[0].get(
                            'attributes', []):
                        # no results, unbind and continue to next server
                        c.unbind()
                        errors.append(
                            f"User {username} attempted to authenticate with LDAP ({server['url']}), but the search with dn:{server['base_dn']}, username_field:{search_username_field} and attribute:{search_attribute} did not return any results. The user was denied access"
                        )
                        continue
                    else:
                        # we got results, get the dn that will be used for binding authentication
                        response = c.response[0]
                        ldap_bind_user = response['dn']
                        c.unbind()

                # let's proceed with binding using the user trying to authenticate
                c = Connection(s,
                               user=ldap_bind_user,
                               password=password,
                               auto_bind=auto_bind,
                               authentication=SIMPLE,
                               raise_exceptions=True)
                c.unbind()
                # At this point the user successfully authenticated to at least one LDAP server.
                is_authenticated_with_ldap = True
                auth_logger.debug(
                    f"User {username} was successfully authenticated with LDAP ({server['url']})"
                )
                break
            except LDAPBindError as e:
                errors.append(
                    f"User {username} attempted to authenticate with LDAP ({server['url']}), but entered an incorrect password. The user was denied access: {str(e)}"
                )
            except LDAPException as e:
                errors.append(
                    f"User {username} attempted to authenticate with LDAP ({server['url']}), but an error occurred. The user was denied access: {str(e)}"
                )

        if is_authenticated_with_ldap:
            return user
        else:
            for error in errors:
                auth_logger.warning(error)
            return None
Exemplo n.º 28
0
class SignupView(PasswordMixin, FormView):

    template_name = "account/signup.html"
    template_name_ajax = "account/ajax/signup.html"
    template_name_email_confirmation_sent = "account/email_confirmation_sent.html"
    template_name_email_confirmation_sent_ajax = "account/ajax/email_confirmation_sent.html"
    template_name_signup_closed = "account/signup_closed.html"
    template_name_signup_closed_ajax = "account/ajax/signup_closed.html"
    form_class = SignupForm
    form_kwargs = {}
    form_password_field = "password"
    redirect_field_name = "next"
    identifier_field = "username"
    messages = {
        "email_confirmation_sent": {
            "level": messages.INFO,
            "text": _("Confirmation email sent to {email}.")
        },
        "invalid_signup_code": {
            "level": messages.WARNING,
            "text": _("The code {code} is invalid.")
        }
    }
    fallback_url_setting = "ACCOUNT_SIGNUP_REDIRECT_URL"

    def __init__(self, *args, **kwargs):
        self.created_user = None
        kwargs["signup_code"] = None
        super(SignupView, self).__init__(*args, **kwargs)

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        self.request = request
        self.args = args
        self.kwargs = kwargs
        self.setup_signup_code()
        return super(SignupView, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SignupView, self).get_context_data(**kwargs)
        context['title'] = "Welcome!"
        return context

    def setup_signup_code(self):
        code = self.get_code()
        if code:
            try:
                self.signup_code = SignupCode.check_code(code)
            except SignupCode.InvalidCode:
                self.signup_code = None
            self.signup_code_present = True
        else:
            self.signup_code = None
            self.signup_code_present = False

    def get(self, *args, **kwargs):
        if is_authenticated(self.request.user):
            return redirect(
                default_redirect(self.request,
                                 settings.ACCOUNT_LOGIN_REDIRECT_URL))
        if not self.is_open():
            return self.closed()
        return super(SignupView, self).get(*args, **kwargs)

    def post(self, *args, **kwargs):
        if is_authenticated(self.request.user):
            raise Http404()
        if not self.is_open():
            return self.closed()
        return super(SignupView, self).post(*args, **kwargs)

    def get_initial(self):
        initial = super(SignupView, self).get_initial()
        if self.signup_code:
            initial["code"] = self.signup_code.code
            if self.signup_code.email:
                initial["email"] = self.signup_code.email
        return initial

    def get_template_names(self):
        if self.request.is_ajax():
            return [self.template_name_ajax]
        else:
            return [self.template_name]

    def get_form_kwargs(self):
        kwargs = super(SignupView, self).get_form_kwargs()
        kwargs.update(self.form_kwargs)
        return kwargs

    def form_invalid(self, form):
        signals.user_sign_up_attempt.send(sender=SignupForm,
                                          username=get_form_data(
                                              form, self.identifier_field),
                                          email=get_form_data(form, "email"),
                                          result=form.is_valid())
        return super(SignupView, self).form_invalid(form)

    def form_valid(self, form):
        self.created_user = self.create_user(form, commit=False)
        # prevent User post_save signal from creating an Account instance
        # we want to handle that ourself.
        self.created_user._disable_account_creation = True
        self.created_user.save()
        self.use_signup_code(self.created_user)
        email_address = self.create_email_address(form)
        if settings.ACCOUNT_EMAIL_CONFIRMATION_REQUIRED and not email_address.verified:
            self.created_user.is_active = False
            self.created_user.save()
        self.create_account(form)
        self.create_password_history(form, self.created_user)
        self.after_signup(form)
        if settings.ACCOUNT_EMAIL_CONFIRMATION_EMAIL and not email_address.verified:
            self.send_email_confirmation(email_address)
        if settings.ACCOUNT_EMAIL_CONFIRMATION_REQUIRED and not email_address.verified:
            return self.email_confirmation_required_response()
        else:
            show_message = [
                settings.ACCOUNT_EMAIL_CONFIRMATION_EMAIL,
                self.messages.get("email_confirmation_sent"),
                not email_address.verified
            ]
            if all(show_message):
                messages.add_message(
                    self.request,
                    self.messages["email_confirmation_sent"]["level"],
                    self.messages["email_confirmation_sent"]["text"].format(
                        **{"email": form.cleaned_data["email"]}))
            # attach form to self to maintain compatibility with login_user
            # API. this should only be relied on by d-u-a and it is not a stable
            # API for site developers.
            self.form = form
            self.login_user()
        return redirect(self.get_success_url())

    def create_user(self, form, commit=True, model=None, **kwargs):
        User = model
        if User is None:
            User = get_user_model()
        user = User(**kwargs)
        username = form.cleaned_data.get("username")
        if username is None:
            username = self.generate_username(form)
        user.username = username
        user.email = form.cleaned_data["email"].strip()
        user.first_name = form.cleaned_data.get("first_name")
        user.last_name = form.cleaned_data.get("last_name")

        password = form.cleaned_data.get("password")
        if password:
            user.set_password(password)
        else:
            user.set_unusable_password()
        if commit:
            user.save()
        return user

    def create_account(self, form):
        new_account = Account.create(request=self.request,
                                     user=self.created_user,
                                     create_email=False)
        # new_account.initial_password = form.cleaned_data.get("initial_password")
        new_account.spouse_name = form.cleaned_data.get("spouse_name")
        new_account.street_address = form.cleaned_data.get("street_address")
        new_account.city = form.cleaned_data.get("city")
        new_account.state = form.cleaned_data.get("state")
        new_account.zip_code = form.cleaned_data.get("zip_code")
        new_account.main_phone = form.cleaned_data.get("main_phone")
        new_account.alt_phone = form.cleaned_data.get("alt_phone")
        new_account.save()

        return new_account

    def generate_username(self, form):
        raise NotImplementedError(
            "Unable to generate username by default. "
            "Override SignupView.generate_username in a subclass.")

    def create_email_address(self, form, **kwargs):
        kwargs.setdefault("primary", True)
        kwargs.setdefault("verified", False)
        if self.signup_code:
            kwargs[
                "verified"] = self.created_user.email == self.signup_code.email if self.signup_code.email else False
        return EmailAddress.objects.add_email(self.created_user,
                                              self.created_user.email,
                                              **kwargs)

    def use_signup_code(self, user):
        if self.signup_code:
            self.signup_code.use(user)

    def send_email_confirmation(self, email_address):
        email_address.send_confirmation(site=get_current_site(self.request))

    def after_signup(self, form):
        signals.user_signed_up.send(sender=SignupForm,
                                    user=self.created_user,
                                    form=form)

    def login_user(self):
        user = auth.authenticate(**self.user_credentials())
        auth.login(self.request, user)
        self.request.session.set_expiry(0)

    def user_credentials(self):
        return hookset.get_user_credentials(self.form, self.identifier_field)

    def get_code(self):
        return self.request.POST.get("code", self.request.GET.get("code"))

    def is_open(self):
        if self.signup_code:
            return True
        else:
            if self.signup_code_present:
                if self.messages.get("invalid_signup_code"):
                    messages.add_message(
                        self.request,
                        self.messages["invalid_signup_code"]["level"],
                        self.messages["invalid_signup_code"]["text"].format(
                            **{
                                "code": self.get_code(),
                            }))
        return settings.ACCOUNT_OPEN_SIGNUP

    def email_confirmation_required_response(self):
        if self.request.is_ajax():
            template_name = self.template_name_email_confirmation_sent_ajax
        else:
            template_name = self.template_name_email_confirmation_sent
        response_kwargs = {
            "request": self.request,
            "template": template_name,
            "context": {
                "email": self.created_user.email,
                "success_url": self.get_success_url(),
            }
        }
        return self.response_class(**response_kwargs)

    def closed(self):
        if self.request.is_ajax():
            template_name = self.template_name_signup_closed_ajax
        else:
            template_name = self.template_name_signup_closed
        response_kwargs = {
            "request": self.request,
            "template": template_name,
        }
        return self.response_class(**response_kwargs)
Exemplo n.º 29
0
    WizardAuthenticationForm,
    YubiKeyDeviceForm,
)
from ..models import PhoneDevice, get_available_phone_methods
from ..utils import backup_phones, default_device, get_otpauth_url
from .utils import IdempotentSessionWizardView, class_view_decorator

try:
    from otp_yubikey.models import ValidationService, RemoteYubikeyDevice
except ImportError:
    ValidationService = RemoteYubikeyDevice = None

logger = logging.getLogger(__name__)


@class_view_decorator(sensitive_post_parameters())
@class_view_decorator(never_cache)
class LoginView(IdempotentSessionWizardView):
    """
    View for handling the login process, including OTP verification.

    The login process is composed like a wizard. The first step asks for the
    user's credentials. If the credentials are correct, the wizard proceeds to
    the OTP verification step. If the user has a default OTP device configured,
    that device is asked to generate a token (send sms / call phone) and the
    user is asked to provide the generated token. The backup devices are also
    listed, allowing the user to select a backup device for verification.
    """
    template_name = 'two_factor/core/login.html'
    form_list = (
        ('auth', WizardAuthenticationForm),
Exemplo n.º 30
0
class LoginView(FormView):

    template_name = "account/login.html"
    template_name_ajax = "account/ajax/login.html"
    form_class = LoginUsernameForm
    form_kwargs = {}
    redirect_field_name = "next"

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, *args, **kwargs):
        return super(LoginView, self).dispatch(*args, **kwargs)

    def get(self, *args, **kwargs):
        if is_authenticated(self.request.user):
            return redirect(self.get_success_url())
        return super(LoginView, self).get(*args, **kwargs)

    def get_template_names(self):
        if self.request.is_ajax():
            return [self.template_name_ajax]
        else:
            return [self.template_name]

    def get_context_data(self, **kwargs):
        ctx = super(LoginView, self).get_context_data(**kwargs)
        redirect_field_name = self.get_redirect_field_name()
        ctx.update({
            "redirect_field_name":
            redirect_field_name,
            "redirect_field_value":
            self.request.POST.get(
                redirect_field_name,
                self.request.GET.get(redirect_field_name, "")),
        })
        return ctx

    def get_form_kwargs(self):
        kwargs = super(LoginView, self).get_form_kwargs()
        kwargs.update(self.form_kwargs)
        return kwargs

    def form_invalid(self, form):
        signals.user_login_attempt.send(sender=LoginView,
                                        username=get_form_data(
                                            form, form.identifier_field),
                                        result=form.is_valid())
        return super(LoginView, self).form_invalid(form)

    def form_valid(self, form):
        self.login_user(form)
        if self.request.user.account.initial_password:
            messages.add_message(
                self.request, messages.INFO,
                "In order to use this site, PLEASE CHANGE OUR TEMPORARY PASSWORD. \
                This is required for security reasons.")
            return redirect("account_password", permanent=True)
        self.after_login(form)
        return redirect(self.get_success_url())

    def after_login(self, form):
        signals.user_logged_in.send(sender=LoginView,
                                    user=form.user,
                                    form=form)

    def get_success_url(self, fallback_url=None, **kwargs):
        if fallback_url is None:
            fallback_url = settings.ACCOUNT_LOGIN_REDIRECT_URL
        kwargs.setdefault("redirect_field_name",
                          self.get_redirect_field_name())
        return default_redirect(self.request, fallback_url, **kwargs)

    def get_redirect_field_name(self):
        return self.redirect_field_name

    def login_user(self, form):
        auth.login(self.request, form.user)
        expiry = settings.ACCOUNT_REMEMBER_ME_EXPIRY if form.cleaned_data.get(
            "remember") else 0
        self.request.session.set_expiry(expiry)
Exemplo n.º 31
0
from common.utils import FlashMessageUtil
from users.utils import (redirect_user_first_login_or_index)
from ..const import RSA_PRIVATE_KEY, RSA_PUBLIC_KEY
from .. import mixins, errors
from ..forms import get_user_login_form_cls

__all__ = [
    'UserLoginView',
    'UserLogoutView',
    'UserLoginGuardView',
    'UserLoginWaitConfirmView',
]


@method_decorator(sensitive_post_parameters(), name='dispatch')
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(never_cache, name='dispatch')
class UserLoginView(mixins.AuthMixin, FormView):
    redirect_field_name = 'next'
    template_name = 'authentication/login.html'

    def redirect_third_party_auth_if_need(self, request):
        # show jumpserver login page if request http://{JUMP-SERVER}/?admin=1
        if self.request.GET.get("admin", 0):
            return None

        auth_types = [
            m for m in self.get_support_auth_methods()
            if m.get('auto_redirect')
        ]
Exemplo n.º 32
0
class PasswordResetTokenView(PasswordMixin, FormView):

    template_name = "account/password_reset_token.html"
    template_name_fail = "account/password_reset_token_fail.html"
    form_class = PasswordResetTokenForm
    token_generator = default_token_generator
    form_password_field = "password"
    fallback_url_setting = "ACCOUNT_PASSWORD_RESET_REDIRECT_URL"

    @method_decorator(sensitive_post_parameters())
    @method_decorator(never_cache)
    def dispatch(self, *args, **kwargs):
        user = self.get_user()
        if user is not None:
            token = kwargs["token"]
            if token == INTERNAL_RESET_URL_TOKEN:
                session_token = self.request.session.get(
                    INTERNAL_RESET_SESSION_TOKEN)
                if self.check_token(user, session_token):
                    return super(PasswordResetTokenView,
                                 self).dispatch(*args, **kwargs)
            else:
                if self.check_token(user, token):
                    # Store the token in the session and redirect to the
                    # password reset form at a URL without the token. That
                    # avoids the possibility of leaking the token in the
                    # HTTP Referer header.
                    self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token
                    redirect_url = self.request.path.replace(
                        token, INTERNAL_RESET_URL_TOKEN)
                    return redirect(redirect_url)
        return self.token_fail()

    def get(self, request, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        ctx = self.get_context_data(form=form)
        return self.render_to_response(ctx)

    def get_context_data(self, **kwargs):
        ctx = super(PasswordResetTokenView, self).get_context_data(**kwargs)
        ctx.update({
            "uidb36": self.kwargs["uidb36"],
            "token": self.kwargs["token"],
        })
        return ctx

    def form_valid(self, form):
        self.change_password(form)
        self.create_password_history(form, self.request.user)
        self.after_change_password()
        return redirect(self.get_success_url())

    def get_user(self):
        try:
            uid_int = base36_to_int(self.kwargs["uidb36"])
        except ValueError:
            raise Http404()
        return get_object_or_404(get_user_model(), id=uid_int)

    def check_token(self, user, token):
        return self.token_generator.check_token(user, token)

    def token_fail(self):
        response_kwargs = {
            "request": self.request,
            "template": self.template_name_fail,
            "context": self.get_context_data()
        }
        return self.response_class(**response_kwargs)
Exemplo n.º 33
0
class PasswordResetConfirmView(PasswordContextMixin, FormView):
    form_class = SetPasswordForm
    post_reset_login = False
    post_reset_login_backend = None
    reset_url_token = 'set-password'
    success_url = reverse_lazy('authy:password_reset_complete')
    template_name = 'registration/password_reset_confirm.html'
    title = _('Enter new password')
    token_generator = default_token_generator

    @method_decorator(sensitive_post_parameters())
    @method_decorator(never_cache)
    def dispatch(self, *args, **kwargs):
        assert 'uidb64' in kwargs and 'token' in kwargs

        self.validlink = False
        self.user = self.get_user(kwargs['uidb64'])

        if self.user is not None:
            token = kwargs['token']
            if token == self.reset_url_token:
                session_token = self.request.session.get(
                    INTERNAL_RESET_SESSION_TOKEN)
                if self.token_generator.check_token(self.user, session_token):
                    # If the token is valid, display the password reset form.
                    self.validlink = True
                    return super().dispatch(*args, **kwargs)
            else:
                if self.token_generator.check_token(self.user, token):
                    # Store the token in the session and redirect to the
                    # password reset form at a URL without the token. That
                    # avoids the possibility of leaking the token in the
                    # HTTP Referer header.
                    self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token
                    redirect_url = self.request.path.replace(
                        token, self.reset_url_token)
                    return HttpResponseRedirect(redirect_url)

        # Display the "Password reset unsuccessful" page.
        return self.render_to_response(self.get_context_data())

    def get_user(self, uidb64):
        try:
            # urlsafe_base64_decode() decodes to bytestring
            uid = urlsafe_base64_decode(uidb64).decode()
            user = UserModel._default_manager.get(pk=uid)
        except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist,
                ValidationError):
            user = None
        return user

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.user
        return kwargs

    def form_valid(self, form):
        user = form.save()
        del self.request.session[INTERNAL_RESET_SESSION_TOKEN]
        if self.post_reset_login:
            auth_login(self.request, user, self.post_reset_login_backend)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.validlink:
            context['validlink'] = True
        else:
            context.update({
                'form': None,
                'title': _('Password reset unsuccessful'),
                'validlink': False,
            })
        return context
Exemplo n.º 34
0
from django.conf import settings
from django.conf.urls import url
from django.contrib import admin, messages
from django.contrib.admin.options import IS_POPUP_VAR
from django.contrib.admin.utils import unquote
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import (
    AdminPasswordChangeForm, UserChangeForm, UserCreationForm,
)
from django.contrib.auth.models import Group, User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.html import escape
from django.utils.translation import ugettext, ugettext_lazy as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
csrf_protect_m = method_decorator(csrf_protect)
sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())

@admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
    search_fields = ('name',)
    ordering = ('name',)
    filter_horizontal = ('permissions',)
    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
Exemplo n.º 35
0
from django.utils.decorators import method_decorator
from django.views.decorators.debug import sensitive_post_parameters
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from rest_framework import status
from allauth.account.utils import complete_signup
from allauth.account import app_settings as allauth_settings
from rest_auth.models import TokenModel
from rest_auth.views import LoginView
from rest_auth.registration.app_settings import RegisterSerializer, register_permission_classes
from django.contrib.auth.models import User

sensitive_post_parameters_m = method_decorator(
    sensitive_post_parameters('password1', 'password2'))


class RegistroView(CreateAPIView):
    serializer_class = RegisterSerializer
    permission_classes = register_permission_classes()
    token_model = TokenModel

    @sensitive_post_parameters_m
    def dispatch(self, *args, **kwargs):
        return super(RegistroView, self).dispatch(*args, **kwargs)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        content = {"details": "Registrado"}
Exemplo n.º 36
0
class RegistrationView(FormView):
    """
    Base class for user registration views.

    """
    disallowed_url = 'registration_disallowed'
    form_class = REGISTRATION_FORM
    http_method_names = ['get', 'post', 'head', 'options', 'trace']
    success_url = None
    template_name = 'registration/registration_form.html'

    @method_decorator(sensitive_post_parameters('password1', 'password2'))
    def dispatch(self, request, *args, **kwargs):
        """
        Check that user signup is allowed and if user is logged in before even bothering to
        dispatch or do other processing.

        """
        if ACCOUNT_AUTHENTICATED_REGISTRATION_REDIRECTS:
            if self.request.user.is_authenticated():
                if settings.LOGIN_REDIRECT_URL is not None:
                    return redirect(settings.LOGIN_REDIRECT_URL)
                else:
                    raise Exception((
                        'You must set a URL with LOGIN_REDIRECT_URL in '
                        'settings.py or set '
                        'ACCOUNT_AUTHENTICATED_REGISTRATION_REDIRECTS=False'))

        if not self.registration_allowed():
            return redirect(self.disallowed_url)
        return super(RegistrationView, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        new_user = self.register(form)
        success_url = self.get_success_url(new_user)

        # success_url may be a simple string, or a tuple providing the
        # full argument set for redirect(). Attempting to unpack it
        # tells us which one it is.
        try:
            to, args, kwargs = success_url
        except ValueError:
            return redirect(success_url)
        else:
            return redirect(to, *args, **kwargs)

    def registration_allowed(self):
        """
        Override this to enable/disable user registration, either
        globally or on a per-request basis.

        """
        return True

    def register(self, form):
        """
        Implement user-registration logic here.

        """
        raise NotImplementedError

    def get_success_url(self, user=None):
        """
        Use the new user when constructing success_url.

        """
        return super(RegistrationView, self).get_success_url()
Exemplo n.º 37
0
    ::
        LoginRequiredMixin = DecoratorMixin(login_required)
        class MyView(LoginRequiredMixin):
            pass
        class SomeView(DecoratorMixin(some_decorator),
                       DecoratorMixin(something_else)):
            pass
    """

    class Mixin(object):
        __doc__ = decorator.__doc__

        @classmethod
        def as_view(cls, *args, **kwargs):
            view = super(Mixin, cls).as_view(*args, **kwargs)
            return decorator(view)

    Mixin.__name__ = str('DecoratorMixin(%s)' % decorator.__name__)
    return Mixin


NeverCacheMixin = DecoratorMixin(never_cache)
CsrfProtectMixin = DecoratorMixin(csrf_protect)
LoginRequiredMixin = DecoratorMixin(login_required)
SensitivePostParametersMixin = DecoratorMixin(sensitive_post_parameters('password', 'old_password', 'password1', 'password2', 'new_password1', 'new_password2'))


class AuthDecoratorsMixin(NeverCacheMixin, CsrfProtectMixin, SensitivePostParametersMixin):
    pass

Exemplo n.º 38
0
class LoginView(SuccessURLAllowedHostsMixin, FormView):
    """
    Display the login form and handle the login action.
    """
    form_class = AuthenticationForm
    authentication_form = None
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'landing_page/index.html'
    redirect_authenticated_user = False
    extra_context = None

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        if self.redirect_authenticated_user and self.request.user.is_authenticated:
            redirect_to = self.get_success_url()
            if redirect_to == self.request.path:
                raise ValueError(
                    "Redirection loop for authenticated user detected. Check that "
                    "your LOGIN_REDIRECT_URL doesn't point to a login page.")
            return HttpResponseRedirect(redirect_to)
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self):
        url = self.get_redirect_url()
        return url or resolve_url(settings.LOGIN_REDIRECT_URL)

    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name,
            self.request.GET.get(self.redirect_field_name, ''))
        url_is_safe = is_safe_url(
            url=redirect_to,
            allowed_hosts=self.get_success_url_allowed_hosts(),
            require_https=self.request.is_secure(),
        )
        return redirect_to if url_is_safe else ''

    def get_form_class(self):
        return self.authentication_form or self.form_class

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def form_valid(self, form):
        """Security check complete. Log the user in."""
        auth_login(self.request, form.get_user())
        return HttpResponseRedirect(self.get_success_url())

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        current_site = get_current_site(self.request)
        active = "login"
        teachers = User.objects.filter(is_teacher=True).count()
        students = User.objects.filter(is_student=True).count()
        schools = School.objects.all().count()
        users = User.objects.all().count()
        context.update({
            self.redirect_field_name: self.get_redirect_url(),
            'site': current_site,
            'site_name': current_site.name,
            **(self.extra_context or {}), 'active': active,
            'meta_title': "African Fashion | Login",
            'meta_tags': ["login", 'African fashion'],
            'GOOGLE_RECAPTCHA_SITE_KEY': settings.GOOGLE_RECAPTCHA_SITE_KEY,
            "teachers": teachers,
            "students": students,
            "schools": schools,
            "users": users
        })
        return context
Exemplo n.º 39
0
    """
    def get_object(self, *args, **kwargs):
        """
        Get the beta test application for the logged in user, if any.
        """
        if self.request.user.is_authenticated:
            if hasattr(self.request.user, 'betatestapplication'):
                return self.request.user.betatestapplication
            application = BetaTestApplication()
            application.user = self.request.user
            return application
        return None


@method_decorator(
    sensitive_post_parameters('password', 'password_confirmation'), name='post'
)
class BetaTestApplicationView(BetaTestApplicationMixin, UpdateView):
    """
    Display the beta test application form.
    """
    template_name = 'registration/registration.html'
    form_class = BetaTestApplicationForm
    success_url = reverse_lazy('registration:register')

    @transaction.atomic
    def form_valid(self, form):
        """
        If the form is valid, log the user in and send verification emails for
        the user's email address and the given public contact email.
        """
Exemplo n.º 40
0
class Login(FormView):
    success_url = '/account/dashboard/0'
    form_class = LoginForm
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = "login.html"

    @method_decorator(sensitive_post_parameters('password'))
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        # Sets a test cookie to make sure the user has cookies enabled
        request.session.set_test_cookie()

        return super(Login, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):         
        username = form.cleaned_data['username']
        password = form.cleaned_data['password']         
        if self.kwargs['role'] == 0:	
            user = authenticate(username=username, password=password)
        else:
            teacher = form.cleaned_data['teacher']					
            user = authenticate(username=teacher+"_"+username, password=password)   
        if user is not None:
            auth_login(self.request, user)
        else :
            return redirect("/account/login/"+str(self.kwargs['role']))
        if user.id == 1 and user.first_name == "":          
            user.first_name = "管理員"
            user.save()
            
            # 學習領域
            domains = ['生物']
            for domain_name in domains:
                domain = Domain(title=domain_name)
                domain.save()
            levels = ['高一','高二','高三']
            for level_name in levels:
                level = Level(title=level_name)
                level.save()            
            zones = Zone.objects.all()
            if len(zones) == 0:
                for city_name, zones, mapx, mapy in county:
                    city = County(name=city_name, mapx=mapx, mapy=mapy)
                    city.save()
                    for zone_name in zones:
                        zone = Zone(name=zone_name, county=city.id)
                        zone.save()
                school = School(county=2, zone=38, system=3, name="南港高中")
                school.save()
                user.last_name = "1"
                user.save()
                try :
                    group = Group.objects.get(name="apply")	
                except ObjectDoesNotExist :
                    group = Group(name="apply")
                    group.save()                                         
                group.user_set.add(user)														
                # create Message
                title = "請修改您的姓名"
                url = "/account/realname"
                message = Message(title=title, url=url, time=timezone.now())
                message.save()                        
                    
                # message for group member
                messagepoll = MessagePoll(message_id = message.id,reader_id=1)
                messagepoll.save() 														
        # 記錄訪客資訊
        admin_user = User.objects.get(id=1)
        try:
            profile = Profile.objects.get(user=admin_user)
        except ObjectDoesNotExist:
            profile = Profile(user=admin_user)
            profile.save()
        profile.visitor_count = profile.visitor_count + 1
        profile.save()
                                    
        year = localtime(timezone.now()).year
        month =  localtime(timezone.now()).month
        day =  localtime(timezone.now()).day
        date_number = year * 10000 + month*100 + day
        try:
            visitor = Visitor.objects.get(date=date_number)
        except ObjectDoesNotExist:
            visitor = Visitor(date=date_number)
        visitor.count = visitor.count + 1
        visitor.save()
                                        
        visitorlog = VisitorLog(visitor_id=visitor.id, user_id=user.id, IP=self.request.META.get('REMOTE_ADDR'))
        visitorlog.save()                 
          
        # If the test cookie worked, go ahead and
        # delete it since its no longer needed
        if self.request.session.test_cookie_worked():
            self.request.session.delete_test_cookie()

        return super(Login, self).form_valid(form)

    def get_success_url(self):
        redirect_to = self.request.GET.get(self.redirect_field_name)
        #if not is_safe_url(url=redirect_to, host=self.request.get_host()):
        #    redirect_to = self.success_url
        return redirect_to

    def get_form_class(self):
        if self.kwargs['role'] == 0:
            return LoginForm
        else :
            return LoginStudentForm
Exemplo n.º 41
0
Arquivo: urls.py Projeto: xdstest/test
from django.conf.urls import include, url
from django.contrib import admin
from django.views.decorators.debug import sensitive_post_parameters

from views.user.sign import SignIn, SignUp, SignOut
from views.timeline import BaseTimeline, UserTimeline, TagTimeline, TagUserTimeline
from views.user.photo import EditPhoto, DeletePhoto


urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),

    url(r'^$', BaseTimeline.as_view(), name='index'),
    url(r'^tag/(?P<tag>[\w]+)/$', TagTimeline.as_view(), name='timeline-tag'),
    url(r'^user/(?P<username>[\w.@+-]+)/$', UserTimeline.as_view(), name='timeline-user'),
    url(r'^user/(?P<username>[\w.@+-]+)/tag/(?P<tag>[\w]+)/$', TagUserTimeline.as_view(), name='timeline-user-tag'),

    url(r'^photo/edit/(?P<photo_id>[\d]+)/$', EditPhoto.as_view(), name='photo-edit'),
    url(r'^photo/delete/(?P<photo_id>[\d]+)/$', DeletePhoto.as_view(), name='photo-delete'),

    url(r'^api/$', BaseTimeline.as_view(), {'type': 'api'}, name='api-index'),
    url(r'^api/tag/(?P<tag>[\w]+)/$', TagTimeline.as_view(), {'type': 'api'}, name='api-timeline-tag'),
    url(r'^api/user/(?P<username>[\w.@+-]+)/$', UserTimeline.as_view(), {'type': 'api'}, name='api-timeline-user'),
    url(r'^api/user/(?P<username>[\w.@+-]+)/tag/(?P<tag>[\w]+)/$', TagUserTimeline.as_view(), {'type': 'api'},
        name='api-timeline-user-tag'),

    url(r'^login/$', sensitive_post_parameters()(SignIn.as_view()), name='user-sign-in'),
    url(r'^join/$', SignUp.as_view(), name='user-sign-up'),
    url(r'^logout/$', SignOut.as_view(), name='user-sign-out'),
]
Exemplo n.º 42
0
class LoginView(View):
    """
    Perform user authentication via the web UI.
    """
    template_name = 'login.html'

    @method_decorator(sensitive_post_parameters('password'))
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

    def get(self, request):
        form = LoginForm(request)

        if request.user.is_authenticated:
            logger = logging.getLogger('netbox.auth.login')
            return self.redirect_to_next(request, logger)

        return render(request, self.template_name, {
            'form': form,
            'auth_backends': load_backends(settings.AUTHENTICATION_BACKENDS),
        })

    def post(self, request):
        logger = logging.getLogger('netbox.auth.login')
        form = LoginForm(request, data=request.POST)

        if form.is_valid():
            logger.debug("Login form validation was successful")

            # If maintenance mode is enabled, assume the database is read-only, and disable updating the user's
            # last_login time upon authentication.
            if get_config().MAINTENANCE_MODE:
                logger.warning("Maintenance mode enabled: disabling update of most recent login time")
                user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login')

            # Authenticate user
            auth_login(request, form.get_user())
            logger.info(f"User {request.user} successfully authenticated")
            messages.info(request, "Logged in as {}.".format(request.user))

            return self.redirect_to_next(request, logger)

        else:
            logger.debug("Login form validation failed")

        return render(request, self.template_name, {
            'form': form,
            'auth_backends': load_backends(settings.AUTHENTICATION_BACKENDS),
        })

    def redirect_to_next(self, request, logger):
        if request.method == "POST":
            redirect_to = request.POST.get('next', settings.LOGIN_REDIRECT_URL)
        else:
            redirect_to = request.GET.get('next', settings.LOGIN_REDIRECT_URL)

        if redirect_to and not is_safe_url(url=redirect_to, allowed_hosts=request.get_host()):
            logger.warning(f"Ignoring unsafe 'next' URL passed to login form: {redirect_to}")
            redirect_to = reverse('home')

        logger.debug(f"Redirecting user to {redirect_to}")
        return HttpResponseRedirect(redirect_to)
Exemplo n.º 43
0
        __doc__ = decorator.__doc__

        @classmethod
        def as_view(cls, *args, **kwargs):
            view = super(Mixin, cls).as_view(*args, **kwargs)
            return decorator(view)

    Mixin.__name__ = str("DecoratorMixin(%s)" % decorator.__name__)
    return Mixin


NeverCacheMixin = DecoratorMixin(never_cache)
CsrfProtectMixin = DecoratorMixin(csrf_protect)
LoginRequiredMixin = DecoratorMixin(login_required)
SensitivePostParametersMixin = DecoratorMixin(
    sensitive_post_parameters("password", "old_password", "password1", "password2", "new_password1", "new_password2")
)


class AuthDecoratorsMixin(NeverCacheMixin, CsrfProtectMixin, SensitivePostParametersMixin):
    pass


class LoginView(AuthDecoratorsMixin, WithCurrentSiteMixin, WithNextUrlMixin, FormView):
    form_class = AuthenticationForm
    template_name = "registration/login.html"
    disallow_authenticated = True
    success_url = resolve_url_lazy(settings.LOGIN_REDIRECT_URL)

    def dispatch(self, *args, **kwargs):
        if self.disallow_authenticated and self.request.user.is_authenticated():
Exemplo n.º 44
0

class EmailVerifyConfirmView(generics.GenericAPIView):
    serializer_class = serializers.EmailVerifyConfirmSerializer
    permission_classes = (AllowAny, )

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({'detail': _('Email has been verified.')})


# Source: django-rest-auth v0.9.3 (https://github.com/Tivix/django-rest-auth)
sensitive_post_parameters_m = method_decorator(
    sensitive_post_parameters('password', 'old_password', 'new_password1',
                              'new_password2'))


# Source: django-rest-auth v0.9.3 (https://github.com/Tivix/django-rest-auth)
class PasswordResetView(generics.GenericAPIView):
    serializer_class = serializers.PasswordResetSerializer
    permission_classes = (AllowAny, )

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({'detail': _('Password reset email has been sent.')})


# Source: django-rest-auth v0.9.3 (https://github.com/Tivix/django-rest-auth)
Exemplo n.º 45
0
def login_decorator(func):
    return csrf_protect(never_cache(sensitive_post_parameters()(func)))
Exemplo n.º 46
0
class UserAdmin(admin.ModelAdmin):
    list_display = ('get_name', 'email', 'get_date_joined', 'is_staff',
                    'is_superuser')
    list_filter = ('is_staff', 'is_superuser', 'profile__joined')
    search_fields = ('email', )
    ordering = ('email', )
    list_display_links = ('get_name', 'email')
    add_form = UserCreationForm
    fieldsets = (
        (None, {
            'fields': ('email', 'password')
        }),
        ('Permissions', {
            'classes': ('collapse', ),
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups',
                       'user_permissions')
        }),
        ('Important dates', {
            'classes': ('collapse', ),
            'fields': ('last_login', )
        }),
    )
    filter_horizontal = (
        'groups',
        'user_permissions',
    )
    add_fieldsets = ((None, {
        'classes': ('wide', ),
        'fields': ('name', 'email', 'password1', 'password2')
    }), )
    change_password_form = AdminPasswordChangeForm
    change_user_password_template = 'admin/auth/user/change_password.html'
    form = UserChangeForm
    actions = ['make_staff']

    def get_date_joined(self, user):
        return user.profile.joined

    get_date_joined.short_description = 'Joined'
    get_date_joined.admin_order_field = 'profile__joined'

    def get_name(self, user):
        return user.profile.name

    get_name.short_description = 'Name'
    get_name.admin_order_field = 'profile__name'

    def get_form(self, request, obj=None, **kwargs):
        if obj is None:
            kwargs['form'] = self.add_form
        return super().get_form(request, obj, **kwargs)

    def get_fieldsets(self, request, obj=None):
        if not obj:
            return self.add_fieldsets
        return super().get_fieldsets(request, obj)

    def get_urls(self):
        password_change = [
            url(r'^(.+)/password/$',
                self.admin_site.admin_view(self.user_change_password),
                name='auth_user_password_change'),
        ]
        urls = super().get_urls()
        urls = password_change + urls
        return urls

    @method_decorator(sensitive_post_parameters())
    def user_change_password(self, request, user_id, form_url=''):
        if not self.has_change_permission(request):
            raise PermissionDenied
        user = self.get_object(request, unquote(user_id))
        if user is None:
            raise Http404('{name} object with primary key '
                          '{key} does not exist.'.format(name=force_text(
                              self.model._meta.verbose_name),
                                                         key=escape(user_id)))
        if request.method == 'POST':
            form = self.change_password_form(user, request.POST)
            if form.is_valid():
                form.save()
                change_message = (self.construct_change_message(
                    request, form, None))
                self.log_change(request, user, change_message)
                success(request, 'Password changed.')
                update_session_auth_hash(request, form.user)
                return HttpResponseRedirect('..')
        else:
            form = self.change_password_form(user)
        context = {
            'title':
            'Change password:{}'.format(escape(user.get_username())),
            'form_url':
            form_url,
            'form':
            form,
            'is_popup': (IS_POPUP_VAR in request.POST
                         or IS_POPUP_VAR in request.GET),
            'opts':
            self.model._meta,
            'original':
            user,
        }
        context.update(admin.site.each_context(request))
        request.current_app = self.admin_site.name

        return TemplateResponse(request, self.change_user_password_template,
                                context)

    def get_inline_instances(self, request, obj=None):
        if obj is None:
            return tuple()
        inline_instance = ProfileAdminInline(self.model, self.admin_site)
        return (inline_instance, )

    def make_staff(self, request, queryset):
        rows_updated = queryset.update(is_staff=True)
        if rows_updated == 1:
            message = '1 user was'
        else:
            message = '{} users were'.format(rows_updated)
        message += ' successfully made staff.'
        self.message_user(request, message)

    make_staff.short_description = 'Allow user to access Admin Site.'
Exemplo n.º 47
0
                    passthrough_next_redirect_url,
                    url_str_to_user_pk)
from .forms import AddEmailForm, ChangePasswordForm
from .forms import LoginForm, ResetPasswordKeyForm
from .forms import ResetPasswordForm, SetPasswordForm, SignupForm
from .utils import sync_user_email_addresses
from .models import EmailAddress, EmailConfirmation

from . import signals
from . import app_settings

from .adapter import get_adapter


sensitive_post_parameters_m = method_decorator(
    sensitive_post_parameters('password', 'password1', 'password2'))


def _ajax_response(request, response, form=None):
    if request.is_ajax():
        if (isinstance(response, HttpResponseRedirect)
                or isinstance(response, HttpResponsePermanentRedirect)):
            redirect_to = response['Location']
        else:
            redirect_to = None
        response = get_adapter().ajax_response(request,
                                               response,
                                               form=form,
                                               redirect_to=redirect_to)
    return response
Exemplo n.º 48
0
class DoExpressCheckout(TemplateView):
    template_name = 'shopping/paypal/cancel.html'

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def post(self, request, *args, **kwargs):
        if getattr(settings, 'UNIT_TESTING', False):
            return confirm_checkout(request,
                                    signature=request.session['signature'],
                                    *args,
                                    **kwargs)

        service = get_service_instance()
        paypal = json.loads(PaymentMean.objects.get(slug='paypal').credentials)
        order_id = request.POST['order_id']
        order = Order.objects.get(pk=order_id)
        line_items = {}
        for i in range(len(order.album_list)):
            album = order.album_list[i]
            line_items.update({
                "L_PAYMENTREQUEST_0_NAME%d" % i:
                album.title,
                "L_PAYMENTREQUEST_0_DESC%d" % i:
                album.title,
                "L_PAYMENTREQUEST_0_AMT%d" % i:
                do_currency(album.cost, order.currency.code),
                "L_PAYMENTREQUEST_0_QTY%d" % i:
                1,
                "L_PAYMENTREQUEST_0_TAXAMT%d" % i:
                0,
                "L_PAYMENTREQUEST_0_NUMBER%d" % i:
                i + 1,
                "L_PAYMENTREQUEST_0_ITEMURL%d" % i:
                service.url + reverse('mediashop:music_item_detail',
                                      args=(
                                          album.artist.slug,
                                          album.slug,
                                      )),
                "L_PAYMENTREQUEST_0_ITEMCATEGORY%d" % i:
                'Digital'
            })

        for i in range(len(order.song_list)):
            song = order.song_list[i]
            line_items.update({
                "L_PAYMENTREQUEST_0_NAME%d" % i:
                song.title,
                "L_PAYMENTREQUEST_0_DESC%d" % i:
                song.title,
                "L_PAYMENTREQUEST_0_AMT%d" % i:
                do_currency(song.cost, order.currency.code),
                "L_PAYMENTREQUEST_0_QTY%d" % i:
                1,
                "L_PAYMENTREQUEST_0_TAXAMT%d" % i:
                0,
                "L_PAYMENTREQUEST_0_NUMBER%d" % i:
                i + 1,
                "L_PAYMENTREQUEST_0_ITEMURL%d" % i:
                service.url + reverse('mediashop:music_item_detail',
                                      args=(
                                          song.artist.slug,
                                          song.slug,
                                      )),
                "L_PAYMENTREQUEST_0_ITEMCATEGORY%d" % i:
                'Digital'
            })

        ec_data = {
            "USER":
            paypal['username'],
            "PWD":
            paypal['password'],
            "SIGNATURE":
            paypal['signature'],
            "METHOD":
            "DoExpressCheckoutPayment",
            "VERSION":
            124.0,
            "TOKEN":
            request.session['token'],
            "PAYERID":
            request.session['payer_id'],
            "PAYMENTREQUEST_0_PAYMENTACTION":
            "Sale",
            "PAYMENTREQUEST_0_AMT":
            do_currency(order.total_cost, order.currency.code),
            "PAYMENTREQUEST_0_ITEMAMT":
            do_currency(order.total_cost, order.currency.code),
            "PAYMENTREQUEST_0_SHIPPINGAMT":
            0,
            "PAYMENTREQUEST_0_TAXAMT":
            0,
            "PAYMENTREQUEST_0_CURRENCYCODE":
            order.currency.code,
            "PAYMENTREQUEST_0_DESC":
            "Purchase on " + service.project_name
        }
        ec_data.update(line_items)
        if getattr(settings, 'DEBUG', False):
            response = requests.post(EC_ENDPOINT, data=ec_data)
            result = parse_paypal_response(response.content.decode('utf-8'))
            ACK = result['ACK']
            if ACK == 'Success' or ACK == 'SuccessWithWarning':
                return confirm_checkout(request,
                                        signature=request.session['signature'],
                                        *args,
                                        **kwargs)
            else:
                try:
                    Order.objects.get(pk=request.POST['order_id']).delete()
                except Order.DoesNotExist:
                    pass
                context = self.get_context_data(**kwargs)
                if getattr(settings, 'DEBUG', False):
                    context['paypal_error'] = urlunquote(
                        response.content.decode('utf-8'))
                else:
                    context['paypal_error'] = urlunquote(
                        result['L_LONGMESSAGE0'])
                messages.error(
                    request,
                    'API Error: Terminating PayPal transaction failed.')
                return HttpResponseRedirect(reverse('mediashop:cart'))
        else:
            try:
                response = requests.post(EC_ENDPOINT, data=ec_data)
                result = parse_paypal_response(
                    response.content.decode('utf-8'))
                ACK = result['ACK']
                if ACK == 'Success' or ACK == 'SuccessWithWarning':
                    return confirm_checkout(
                        request,
                        signature=request.session['signature'],
                        *args,
                        **kwargs)
                else:
                    try:
                        Order.objects.get(pk=request.POST['order_id']).delete()
                    except Order.DoesNotExist:
                        pass
                    context = self.get_context_data(**kwargs)
                    if getattr(settings, 'DEBUG', False):
                        context['paypal_error'] = urlunquote(
                            response.content.decode('utf-8'))
                    else:
                        context['paypal_error'] = urlunquote(
                            result['L_LONGMESSAGE0'])
                    messages.error(
                        request,
                        'API Error: Terminating PayPal transaction failed.')
                    return HttpResponseRedirect(reverse('mediashop:cart'))
            except Exception as e:
                logger.error("%s - PayPal error. Order ID: %s" %
                             (service.project_name, order.id),
                             exc_info=True)
                messages.error(
                    request,
                    'Could not terminate transaction due to server error. Contact administrator.'
                )
                return HttpResponseRedirect(reverse('mediashop:cart'))
Exemplo n.º 49
0
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as ContribUserAdmin
from django.utils.translation import ugettext_lazy as _
from django.utils.decorators import method_decorator
from django.views.decorators.debug import sensitive_post_parameters


from .forms import *
# from .models import User, Organization

from reversion.admin import VersionAdmin
from django_inline_wrestler.admin import TabularInlineOrderable

from carbon.atoms.admin.content import BaseVersionableAdmin, BaseVersionableTitleAdmin

sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())

class UserAdmin(ContribUserAdmin):
    def preview(self, obj):
        if obj.image:
            try:
                return mark_safe("<img src='%s' alt='%s preview'/>"%(obj.image.thumbnail_url, obj.image.title))
            except:
                return ""
        return ''
    

    autocomplete_lookup_fields = {
        'fk': ['image',],
    }
    raw_id_fields = ('image',)
Exemplo n.º 50
0
class LoginView(GenericAPIView):
    serializer_class = serializers.LoginSerializer
    permission_classes = (AllowAny,)

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(
            {"detail": _("Login code has been sent.")},
            status=status.HTTP_200_OK
        )


@method_decorator(sensitive_post_parameters('code'), 'dispatch')
class LoginCodeView(GenericAPIView):
    permission_classes = (AllowAny,)
    serializer_class = serializers.LoginCodeSerializer
    token_serializer_class = serializers.TokenSerializer
    token_model = Token

    def process_login(self):
        django_login(self.request, self.user)

    def login(self):
        self.user = self.serializer.validated_data['user']
        self.token, created = self.token_model.objects.get_or_create(user=self.user)

        if getattr(settings, 'REST_SESSION_LOGIN', True):
            self.process_login()