コード例 #1
0
ファイル: tests.py プロジェクト: django-otp/django-otp
 def test_user_has_device(self):
     with self.subTest(user='******'):
         self.assertFalse(user_has_device(AnonymousUser()))
     with self.subTest(user='******'):
         self.assertTrue(user_has_device(self.alice))
     with self.subTest(user='******'):
         self.assertFalse(user_has_device(self.bob))
コード例 #2
0
    def get(self, request, *args, **kwargs):

        if not user_has_device(self.request.user):
            return redirect(resolve_url("account-admin:edit"))

        form = self.form_class(user=request.user)
        return render(request, self.template_name, {"form": form})
コード例 #3
0
 def has_permission(self, request):
     if user_has_device(request.user):
         # Call django-otp method
         return super().has_permission(request)
     else:
         # Call original django admin method
         return super(OTPAdminSite, self).has_permission(request)
コード例 #4
0
    def test(user: UserProfile) -> bool:
        """
        :if_configured: If ``True``, an authenticated user with no confirmed
        OTP devices will be allowed. Also, non-authenticated users will be
        allowed as web_public_visitor users. Default is ``False``. If ``False``,
        2FA will not do any authentication.
        """
        if_configured = settings.TWO_FACTOR_AUTHENTICATION_ENABLED
        if not if_configured:
            return True

        # User has completed 2FA verification
        if user.is_verified():
            return True

        # This request is unauthenticated (logged-out) access; 2FA is
        # not required or possible.
        if not user.is_authenticated:  # nocoverage
            return True

        # If the user doesn't have 2FA set up, we can't enforce 2FA.
        if not user_has_device(user):
            return True

        # User has configured 2FA and is not verified, so the user
        # fails the test (and we should redirect to the 2FA view).
        return False
コード例 #5
0
def web_user_lookup(request):
    template = "hqadmin/web_user_lookup.html"
    web_user_email = request.GET.get("q")

    context = {
        'current_page': {
            'title': "Look up user by email",
            'page_name': "Look up user by email",
        },
        'section': {
            'page_name': UserAdministration.section_name,
            'url': reverse("default_admin_report"),
        },
    }

    if not web_user_email:
        return render(request, template, context)

    web_user = WebUser.get_by_username(web_user_email)
    context.update({
        'audit_report_url': reverse('admin_report_dispatcher', args=('user_audit_report',)),
    })
    if web_user is None:
        messages.error(
            request, "Sorry, no user found with email {}. Did you enter it correctly?".format(web_user_email)
        )
    else:
        from django_otp import user_has_device
        context['web_user'] = web_user
        django_user = web_user.get_django_user()
        context['has_two_factor'] = user_has_device(django_user)
    return render(request, template, context)
コード例 #6
0
ファイル: user.py プロジェクト: wifihitech/modoboa
def security(request):
    """View to manage security settings."""
    context = {"user_has_device": django_otp.user_has_device(request.user)}
    if not request.user.tfa_enabled:
        device = request.user.staticdevice_set.first()
        if device:
            tokens = device.token_set.all().values_list("token", flat=True)
            context.update({"tokens": tokens})
            # Set enable flag to True so we can't go here anymore
            request.user.tfa_enabled = True
            request.user.save()
        else:
            device = request.user.totpdevice_set.first()
            if device:
                factory = qrcode.image.svg.SvgPathImage
                img = qrcode.make(device.config_url, image_factory=factory)
                buf = io.BytesIO()
                img.save(buf)
                context.update({"qrcode": buf.getvalue().decode()})
    resp = {
        "content": render_to_string("core/user_security.html", context,
                                    request),
        "callback": "security"
    }
    return render_to_json_response(resp)
コード例 #7
0
ファイル: totpviews.py プロジェクト: Maxim-Durand/BowtieTool
    def get(self, request):
        """TOPT generaton"""

        user = request.user
        if user_has_device(user, confirmed=True):
            return Response(
                dict(errors=["2FA is already activated on this account"]),
                status=status.HTTP_400_BAD_REQUEST)

        device = get_user_totp_device(user, False)
        if not device:
            device = user.totpdevice_set.create(confirmed=False)
            user.save()

        try:
            img = qrcode.make(device.config_url)
            bytes_image = io.BytesIO()
            img.save(bytes_image, format='PNG')
            bytes_image.seek(0)
            img = base64.b64encode(bytes_image.read()).decode('utf-8')
            token = TOTPValidityToken().make_token(user)
            return Response({
                "qrImg": img,
                "token": token
            },
                            status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)
コード例 #8
0
    def user_allowed(self, user):
        if not settings.WAGTAIL_2FA_REQUIRED:
            return True

        return user.is_verified() or (self.if_configured
                                      and user.is_authenticated
                                      and not user_has_device(user))
コード例 #9
0
ファイル: middleware.py プロジェクト: jlodonia/django-otp
def is_verified(user):

    has_device = user_has_device(user)
    if has_device:
        return user.otp_device is not None

    return True
コード例 #10
0
ファイル: middleware.py プロジェクト: jlodonia/django-otp
    def _verify_user(self, request, user):
        """
        Sets OTP-related fields on an authenticated user.
        """
        user.otp_device = None
        user.is_verified = functools.partial(is_verified, user)

        if user.is_authenticated:

            if not user_has_device(user):
                return user

            persistent_id = request.session.get(DEVICE_ID_SESSION_KEY)
            device = self._device_from_persistent_id(
                persistent_id) if persistent_id else None

            if (device is not None) and (device.user_id != user.pk):
                device = None

            if (device is None) and (DEVICE_ID_SESSION_KEY in request.session):
                del request.session[DEVICE_ID_SESSION_KEY]

            user.otp_device = device

        return user
コード例 #11
0
ファイル: views.py プロジェクト: BuildAMovement/whistler-kpi
    def post(self, request, *args, **kwargs):
        user = request.user
        tfa_activated = user_has_device(user)
        reqdata = request.POST.copy()
        if tfa_activated:
            form = TwoFactorAuthFormEnabled(prefix='to_enable', data=reqdata)
            if form.is_valid():
                if form.cleaned_data['status']:
                    for device in devices_for_user(user):
                        device.delete()
                return render(
                    request,
                    'registration/2fa-disabled-now.html',
                    {
                        'form': form,
                        'tfa_activated': tfa_activated,
                        'status_changed': form.cleaned_data['status']
                    },
                )
            else:
                return render(
                    request,
                    'registration/2fa.html',
                    {
                        'form': form,
                        'tfa_activated': tfa_activated,
                    },
                )
        else:
            form = TwoFactorAuthFormDisabled(prefix='to_disable', data=reqdata)
            if form.is_valid():
                if form.cleaned_data['status']:
                    device = TOTPDevice(user=user,
                                        name=user.username + '\'s device')
                    device.save()

                from base64 import b32encode
                secret_key = b32encode(device.bin_key)

                return render(
                    request,
                    'registration/2fa-enabled-now.html',
                    {
                        'form': form,
                        'tfa_activated': tfa_activated,
                        'status_changed': form.cleaned_data['status'],
                        'device': device,
                        'secret_key': secret_key,
                    },
                )
            else:
                return render(
                    request,
                    'registration/2fa.html',
                    {
                        'form': form,
                        'tfa_activated': tfa_activated,
                    },
                )
コード例 #12
0
    def authenticate(self, request):
        response = super().authenticate(request)

        # response[0] is the user
        if (response and response[0] and
            (not user_has_device(response[0]) or response[0].is_verified())):
            return response
        else:
            return None
コード例 #13
0
ファイル: views.py プロジェクト: HelloLily/hellolily
    def dispatch(self, request, *args, **kwargs):
        # This view is only used to add backup phone numbers, so the user must be authenticated and have 2fa enabled.
        if not request.user.is_authenticated() or not user_has_device(request.user):
            return redirect(self.success_url)

        # Call the super of PhoneSetupView to strip it of the decorators.
        # PhoneSetupView sets the otp_required decorator, it checks if the user was logged in using 2fa. If not it
        # tries redirecting to the login page, but using if 2fa is not setup or user logged in using social auth, it
        # results in a redirect loop.
        return super(PhoneSetupView, self).dispatch(request, *args, **kwargs)
コード例 #14
0
 def has_permission(self, request):
     return (
         super(OTPAdminSite, self).has_permission(request)
         and request.session[BACKEND_SESSION_KEY]
         == "agir.people.backend.PersonBackend"
         and (
             request.user.is_verified()
             or not django_otp.user_has_device(request.user)
         )
     )
コード例 #15
0
ファイル: serializers.py プロジェクト: ernsyn/hellolily
    def get_has_two_factor(self, obj):
        if self.context.get('request'):
            user = self.context.get('request').user

            if user.is_admin:
                # Only admins are allowed to see the 2FA status.
                return user_has_device(obj)
            else:
                return None
        else:
            return None
コード例 #16
0
    def handle_no_permission(self, request):
        """Redirect unauthenticated users."""
        if not request.user.is_authenticated:
            return redirect_to_login(request.get_full_path(),
                                     settings.LOGIN_URL, REDIRECT_FIELD_NAME)

        if user_has_device(request.user):
            return redirect_to_login(request.get_full_path(),
                                     login_url=reverse("wagtail_2fa_auth"))

        raise PermissionDenied
コード例 #17
0
ファイル: serializers.py プロジェクト: HelloLily/hellolily
    def get_has_two_factor(self, obj):
        if self.context.get('request'):
            user = self.context.get('request').user

            if user.is_admin:
                # Only admins are allowed to see the 2FA status.
                return user_has_device(obj)
            else:
                return None
        else:
            return None
コード例 #18
0
    def dispatch(self, request, *args, **kwargs):
        # This view is only used to add backup phone numbers, so the user must be authenticated and have 2fa enabled.
        if not request.user.is_authenticated() or not user_has_device(
                request.user):
            return redirect(self.success_url)

        # Call the super of PhoneSetupView to strip it of the decorators.
        # PhoneSetupView sets the otp_required decorator, it checks if the user was logged in using 2fa. If not it
        # tries redirecting to the login page, but using if 2fa is not setup or user logged in using social auth, it
        # results in a redirect loop.
        return super(PhoneSetupView, self).dispatch(request, *args, **kwargs)
コード例 #19
0
    def clean(self):
        self.cleaned_data = super(LoginForm, self).clean()
        if user_has_device(self.get_user()):
            self.clean_otp(self.get_user())

        if not self.get_user().is_staff:
            raise forms.ValidationError(
                self.error_messages['inactive'],
                code='inactive',
            )

        return self.cleaned_data
コード例 #20
0
    def test(user: UserProfile) -> bool:
        """
        :if_configured: If ``True``, an authenticated user with no confirmed
        OTP devices will be allowed. Default is ``False``. If ``False``,
        2FA will not do any authentication.
        """
        if_configured = settings.TWO_FACTOR_AUTHENTICATION_ENABLED
        if not if_configured:
            return True

        return user.is_verified() or (_user_is_authenticated(user)
                                      and not user_has_device(user))
コード例 #21
0
    def clean_otp_token(self):
        otp_token = self.cleaned_data["otp_token"]
        user = self.user
        if not user_has_device(user):
            raise ValidationError(
                "Le système n'a pas trouvé d'appareil (carte OTP ou générateur sur téléphone) pour votre compte. Contactez le support pour en ajouter un."
            )

        for device in devices_for_user(user):
            if device.verify_is_allowed() and device.verify_token(otp_token):
                return otp_token

        raise ValidationError("Ce code n'est pas valide.")
コード例 #22
0
ファイル: forms.py プロジェクト: josewails/django-magicauth
    def clean_otp_token(self):
        otp_token = self.cleaned_data["otp_token"]
        user = self.user
        if not user_has_device(user):
            raise ValidationError(
                _("The system could not find a device (OTP card or generator on phone) for your account."
                  "Contact support to add one."))

        for device in devices_for_user(user):
            if device.verify_is_allowed() and device.verify_token(otp_token):
                return otp_token

        raise ValidationError(_("OTP token is not valid."))
コード例 #23
0
ファイル: test_mixins.py プロジェクト: labd/wagtail-2fa
    def test_user_allowed_when_no_device_and_if_configured_returns_true(self, rf, user):
        with override_settings(WAGTAIL_2FA_REQUIRED=True):
            request = rf.get("/admin/")
            request.user = user
            middleware = _OTPMiddleware()
            user = middleware._verify_user(request, user)
            assert not user_has_device(user)
            assert user.is_authenticated

            mixin = OtpRequiredMixin()
            mixin.if_configured = True
            result = mixin.user_allowed(user)
            assert result is True
コード例 #24
0
    def post(self, request):
        assert 'delete' in request.POST
        device = device_from_persistent_id(request.user, request.POST['persistent_id'])
        device.delete()

        other_devices_same_type = type(device).objects.devices_for_user(request.user, confirmed=None)
        if other_devices_same_type.filter(name='default').count() == 0 and other_devices_same_type.count() > 0:
            new_default_device = other_devices_same_type.first()
            new_default_device.name = 'default'
            new_default_device.save()

        if django_otp.user_has_device(request.user, confirmed=None):
            return HttpResponseRedirect(reverse('two_factor:manage_keys'))
        return HttpResponseRedirect(reverse('two_factor:profile'))
コード例 #25
0
    def get(self, request, uuid, *args, **kwargs):

        # Superuser only.
        if not request.user.is_superuser:
            raise PermissionDenied

        user = self.get_user(uuid)

        if not user_has_device(user):
            return redirect(
                resolve_url("account-admin:user-detail", pk=user.id))

        form = self.form_class(user=request.user)
        return render(request, self.template_name, {"form": form})
コード例 #26
0
ファイル: views.py プロジェクト: BuildAMovement/whistler-kpi
 def get(self, request, *args, **kwargs):
     user = request.user
     tfa_activated = user_has_device(user)
     if tfa_activated:
         form = TwoFactorAuthFormEnabled(prefix='to_enable')
     else:
         form = TwoFactorAuthFormDisabled(prefix='to_disable')
     return render(
         request,
         'registration/2fa.html',
         {
             'form': form,
             'tfa_activated': tfa_activated,
         },
     )
コード例 #27
0
def exchange(request):
    return {
        'PROJECT_NAME': settings.PROJECT_NAME,
        'USER_HAS_DEVICE': lambda: user_has_device(request.user),
        'BRL_CURRENCY_CODE': settings.BRL_CURRENCY_CODE,
        'GOOGLE_ANALYTICS_TRACK_ID': settings.GOOGLE_ANALYTICS_TRACK_ID,
        'DOMAIN': settings.DOMAIN,
        'HOME_VIEW': settings.HOME_VIEW,
        'ENABLE_SIGNUP_ADDRESS': settings.ENABLE_SIGNUP_ADDRESS,
        'BR_DEPOSIT_MIN': settings.BR_DEPOSIT_MIN,
        'BR_DEPOSIT_MAX': settings.BR_DEPOSIT_MAX,
        'BR_DEPOSIT_DAILY_LIMIT': settings.BR_DEPOSIT_DAILY_LIMIT,
        'DEFAULT_ADDRESS_COUNTRY': settings.DEFAULT_ADDRESS_COUNTRY,
        'DEFAULT_USERNAME': settings.DEFAULT_USERNAME,
        'DEFAULT_PASSWORD': settings.DEFAULT_PASSWORD,
    }
コード例 #28
0
def userdetail(request, uid):
    user = get_object_or_404(User, pk=uid)
    if settings.LDAP_ENABLED:
        from django_auth_ldap.backend import LDAPBackend
        popuser = LDAPBackend().populate_user(user.username)
        if popuser is None:
            user.is_active = False
            user.save()
            return HttpResponseRedirect(reverse('cred.views.list',
                args=('changeadvice', user.id)))
    credlogs = CredAudit.objects.filter(user=user, cred__group__in=request.user.groups.all())[:5]
    morelink = reverse('staff.views.audit', args=('user', user.id))
    return render(request, 'staff_userdetail.html', {
        'viewuser': user,
        'credlogs': credlogs,
        'morelink': morelink,
        'hastoken': user_has_device(user)})
コード例 #29
0
ファイル: middleware.py プロジェクト: robmoorman/wagtail-2fa
    def process_request(self, request):
        super().process_request(request)
        user = request.user

        if self._require_verified_user(request):
            user_has_device = django_otp.user_has_device(user, confirmed=True)

            if user_has_device and not user.is_verified():
                return redirect_to_login(request.get_full_path(),
                                         login_url=reverse('wagtail_2fa_auth'))

            elif not user_has_device and settings.WAGTAIL_2FA_REQUIRED:
                # only allow the user to visit the admin index page and the
                # admin setup page
                return redirect_to_login(
                    request.get_full_path(),
                    login_url=reverse('wagtail_2fa_device_new'))
コード例 #30
0
    def get_login_redirect_url(self, request):
        # This ensures that once a user registers, they immediately
        # find the 2FA setup page after login.
        if not user_has_device(request.user):
            path = reverse('two-factor-setup')

        # request.user.otp_device will be None if the user is not
        # verified.  I am not sure why at this point in the request
        # cycle the `is_verified` function (which uses this same
        # logic) has not been added to the user object.
        elif request.user.is_authenticated and request.user.otp_device is None:
            # The session key here seems required to let allauth_2fa
            # know to bypass normal login and request a token.
            request.session['allauth_2fa_user_id'] = request.user.id
            path = reverse('two-factor-authenticate')
        else:
            path = reverse('dashboard')
        return path
コード例 #31
0
ファイル: views.py プロジェクト: neosacode/xfactor
    def post(self, request):
        coin = request.POST['coin']
        # O POST e imutavel por default, sendo assim, 
        # precisamos alterar essa caracteristica do object para alterar seus valores
        request.POST._mutable = True
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        request.POST['address'] = 'whatever'
        # Define um valor padrao para code do two factor, caso o usuario nao tenha configurado ele ainda
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        if not user_has_device(request.user):
            request.POST['code'] = '123'

        account = Accounts.objects.get(user=request.user, currency__code='BTC', currency__type=Currencies.TYPES.investment)
        withdraw_form = NewWithdrawForm(request.POST, user=request.user, account=account)

        if not withdraw_form.is_valid():
            return {'status': 'error', 'errors': withdraw_form.errors}

        fee = (withdraw_form.cleaned_data['amount'] * (account.currency.withdraw_fee / 100)) + account.currency.withdraw_fixed_fee
        checking_account = Accounts.objects.get(user=request.user, currency__code='BTC', currency__type=Currencies.TYPES.checking)

        with transaction.atomic():
            amount = abs(withdraw_form.cleaned_data['amount'])

            statement = Statement()
            statement.account = account
            statement.amount = Decimal('0.00') - amount
            statement.description = 'Income Withdrawal'
            statement.type = 'income_withdraw'
            statement.save()

            account.takeout(amount)

            statement = Statement()
            statement.account = checking_account
            statement.amount = (amount - abs(fee))
            statement.description = 'Income Deposit'
            statement.type = 'income_deposit'
            statement.save()

            checking_account.to_deposit((amount - abs(fee)) )

            return {'status': 'success', 'amount': amount}
コード例 #32
0
def web_user_lookup(request):
    template = "hqadmin/web_user_lookup.html"
    web_user_email = request.GET.get("q")
    if not web_user_email:
        return render(request, template, {})

    web_user = WebUser.get_by_username(web_user_email)
    context = {
        'audit_report_url': reverse('admin_report_dispatcher', args=('user_audit_report',))
    }
    if web_user is None:
        messages.error(
            request, "Sorry, no user found with email {}. Did you enter it correctly?".format(web_user_email)
        )
    else:
        from django_otp import user_has_device
        context['web_user'] = web_user
        django_user = web_user.get_django_user()
        context['has_two_factor'] = user_has_device(django_user)
    return render(request, template, context)
コード例 #33
0
ファイル: decorators.py プロジェクト: altanawealth/django-otp
 def test(user):
     return user.is_verified() or (if_configured and user.is_authenticated() and not user_has_device(user))
コード例 #34
0
 def get(self, request, *args, **kwargs):
     if not user_has_device(self.request.user):
         return redirect(self.redirect_url or resolve_url(settings.LOGIN_REDIRECT_URL))
     return super(DisableView, self).get(request, *args, **kwargs)
コード例 #35
0
ファイル: decorators.py プロジェクト: L1NT/django-otp-project
def otp_required(view=None, redirect_field_name='next', login_url=None, if_configured=False):
    """
    Similar to :func:`~django.contrib.auth.decorators.login_required`, but
    requires the user to be :term:`verified`. By default, this redirects users
    to :setting:`OTP_LOGIN_URL`.

    :param if_configured: If ``True``, an authenticated user with no confirmed
        OTP devices will be allowed. Default is ``False``.
    :type if_configured: bool
    """
    if login_url is None:
        login_url = settings.OTP_LOGIN_URL

    test = lambda user: user.is_verified() or (if_configured and user.is_authenticated() and not user_has_device(user))
    decorator = user_passes_test(test, login_url=login_url, redirect_field_name=redirect_field_name)

    return decorator if (view is None) else decorator(view)