Exemplo n.º 1
0
    def post(self, request):
        form = Auth2faForm.Basic.create_from_request(request)

        if not request.token:
            raise ApiException(request,
                               _('User is unauthorized.'),
                               status_code=HTTPStatus.FORBIDDEN)

        if not form.is_valid():
            raise ValidationException(request, form)

        code = form.cleaned_data.get('code')
        user = request.user
        token = request.token

        if user.is_2fa:
            totp = pyotp.TOTP(user.additional_data.get('otp_secret'))
            totp.now()

            if totp.verify(code):
                token.active_2fa = True
                token.save()
            else:
                raise ApiException(request,
                                   _('Invalid or missing credentials'),
                                   status_code=HTTPStatus.UNAUTHORIZED)
        else:
            raise ApiException(request,
                               _('User is unauthorized.'),
                               status_code=HTTPStatus.FORBIDDEN)

        return SingleResponse(request,
                              token,
                              status=HTTPStatus.OK,
                              serializer=TokenSerializer.Base)
Exemplo n.º 2
0
    def put(self, request, service_id):
        try:
            service = Service.objects.get(pk=service_id)
        except Service.DoesNotExist:
            raise ApiException(request, _('Service does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        form = ServiceForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        if service.name != form.cleaned_data['name']:
            if form.cleaned_data['remote_id'].services.filter(name=form.cleaned_data['name']).exists():
                raise ApiException(
                    request=request,
                    message=_('Assigned remote already has service with name: "{service_name}"').format(
                        service_name=form.cleaned_data['name']
                    ),
                    status_code=HTTPStatus.CONFLICT
                )

        form.fill(service)
        service.save()

        return SingleResponse(request, data=service, status=HTTPStatus.OK, serializer=ServiceSerializer.Base)
Exemplo n.º 3
0
    def put(self, request, remote_id):
        try:
            remote = Remote.objects.get(pk=remote_id)
        except Remote.DoesNotExist:
            raise ApiException(request, _('Remote does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        form = RemoteForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        if remote.name != form.cleaned_data['name']:
            if form.cleaned_data['project_id'].remotes.filter(name=form.cleaned_data['name']).exists():
                raise ApiException(
                    request=request,
                    message=_('Assigned project already has remote with name: "{remote_name}"').format(
                        remote_name=form.cleaned_data['name']
                    ),
                    status_code=HTTPStatus.CONFLICT
                )

        form.fill(remote)
        remote.save()

        return SingleResponse(request, data=remote, status=HTTPStatus.OK, serializer=RemoteSerializer.Base)
Exemplo n.º 4
0
    def get(self, request, remote_id):
        try:
            remote = Remote.objects.get(pk=remote_id)
        except Remote.DoesNotExist:
            raise ApiException(request, _('Remote does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        if not has_object_permission('check_remote', request.user, remote):
            raise ApiException(request, _('User is unauthorized.'), status_code=HTTPStatus.FORBIDDEN)

        return SingleResponse(request, remote, serializer=RemoteSerializer.Base)
    def inner(request, *args, **kwargs):
        if not hasattr(
                request, 'user'
        ) or not request.user or not request.user.is_authenticated:
            raise ApiException(request,
                               _("Invalid or missing credentials"),
                               status_code=HTTPStatus.UNAUTHORIZED)
        elif request.user.is_2fa and not request.token.active_2fa:
            raise ApiException(request,
                               _("Invalid or missing credentials"),
                               status_code=HTTPStatus.UNAUTHORIZED)

        return func(request, *args, **kwargs)
Exemplo n.º 6
0
    def __call__(self, request):
        auth_header = request.headers.get('Authorization', b'').split()

        if not auth_header:
            return self.get_response(request)

        if len(auth_header) != 2:
            return ErrorResponse.create_from_exception(
                ApiException(request, _("Improperly formatted token"), status_code=HTTPStatus.BAD_REQUEST)
            )

        try:
            Token.objects.filter(expires_at__lt=timezone.now()).hard_delete()
        except AttributeError:
            pass

        try:
            user = auth.authenticate(request, token=auth_header[1])
        except ApiException:
            user = None

        if user:
            request.user = user
            request.token = user.tokens.get(pk=auth_header[1])

        return self.get_response(request)
Exemplo n.º 7
0
    def get(self, request, service_id):
        try:
            service = Service.objects.get(pk=service_id)
        except Service.DoesNotExist:
            raise ApiException(request, _('Service does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        return SingleResponse(request, service, serializer=ServiceSerializer.Base)
Exemplo n.º 8
0
    def get(self, request, project_id):
        try:
            project = Project.objects.get(pk=project_id)
        except Project.DoesNotExist:
            raise ApiException(request,
                               _('Project does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        if not has_object_permission('check_project', request.user, project):
            raise ApiException(request,
                               _('User is unauthorized.'),
                               status_code=HTTPStatus.FORBIDDEN)

        return SingleResponse(request,
                              project,
                              serializer=ProjectSerializer.Detail)
 def _function(request, *args, **kwargs):
     if request.user.has_perm(perm):
         return function(request, *args, **kwargs)
     else:
         raise ApiException(request,
                            _('Permission denied.'),
                            status_code=HTTPStatus.FORBIDDEN)
Exemplo n.º 10
0
    def inner(request, *args, **kwargs):
        if not request.user.is_authenticated or not request.user.is_superuser:
            raise ApiException(request,
                               _('User is unauthorized.'),
                               status_code=HTTPStatus.FORBIDDEN)

        return func(request, *args, **kwargs)
Exemplo n.º 11
0
    def delete(self, request, service_id):
        try:
            service = Service.objects.get(pk=service_id)
        except Service.DoesNotExist:
            raise ApiException(request, _('Service does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        service.delete()

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 12
0
    def get(self, request, user_id):
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            raise ApiException(request,
                               _('User does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        return SingleResponse(request, user, serializer=UserSerializer.Detail)
Exemplo n.º 13
0
    def __init__(self, request: HttpRequest, variables: dict):
        self._request = request
        self._variables = variables

        if hasattr(self._request, 'api_key'):
            self._api_key = self._request.api_key
        else:
            raise ApiException(self._request,
                               _('Request does not have any api_key.'),
                               status_code=HTTPStatus.NOT_FOUND)
Exemplo n.º 14
0
    def delete(self, request, remote_id):
        try:
            remote = Remote.objects.get(pk=remote_id)
        except Remote.DoesNotExist:
            raise ApiException(request, _('Remote does not exist.'), status_code=HTTPStatus.NOT_FOUND)

        remote.services.all().delete()
        remote.delete()

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 15
0
    def delete(self, request, api_key_id):
        try:
            api_key = ApiKey.objects.get(pk=api_key_id)
        except ApiKey.DoesNotExist:
            raise ApiException(request,
                               _('Api key does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        api_key.delete()

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 16
0
    def delete(self, request, user_id):
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            raise ApiException(request,
                               _('User does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        user.delete()

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 17
0
    def delete(self, request):
        user = request.user

        if user.is_temporary:
            user.delete()
        else:
            raise ApiException(request,
                               _('Permission denied.'),
                               status_code=HTTPStatus.FORBIDDEN)

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 18
0
    def get(self, request, api_key_id):
        try:
            api_key = ApiKey.objects.get(pk=api_key_id)
        except ApiKey.DoesNotExist:
            raise ApiException(request,
                               _('Api key does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        return SingleResponse(request,
                              api_key,
                              serializer=ApiKeySerializer.Base)
Exemplo n.º 19
0
    def process_view(request, view_func, view_args, view_kwargs):
        # View functions
        if hasattr(view_func,
                   'signature_exempt') and view_func.signature_exempt:
            return None

        # View classes
        if hasattr(view_func, 'view_class') \
            and hasattr(view_func.view_class, 'skip_signature') \
            and request.method.lower() in view_func.view_class.skip_signature:
            return None

        api_key = request.headers.get('X-Apikey')
        signature = request.headers.get('X-Signature', '')
        try:
            api_key_model = ApiKey.objects.get(key=api_key, is_active=True)
        except ApiKey.DoesNotExist:
            return ErrorResponse.create_from_exception(
                ApiException(request, _('Invalid api key.')))

        request.api_key = api_key_model

        # # Do not check signature for GitLab API keys
        # if api_key_model.platform == ApiKey.ApiKeyType.GIT:
        #     return None
        #
        # message = f"{request.body.decode('utf-8')}:{request.path}"
        # signature_check = hmac.new(
        #     api_key_model.secret.encode('utf-8'),
        #     msg=message.encode('utf-8'),
        #     digestmod=hashlib.sha256
        # ).hexdigest()
        #
        # # Do not check signature for DEBUG API keys in DEBUG environment
        # if api_key_model.platform == ApiKey.ApiKeyType.DEBUG and settings.DEBUG:
        #     return None
        #
        # if signature != signature_check:
        #     return ErrorResponse.create_from_exception(
        #         ApiException(
        #             request,
        #             _('Invalid signature.'),
        #             HTTPStatus.FORBIDDEN,
        #             to_sentry=True,
        #             additional_data={
        #                 'received': signature,
        #                 'expected': signature_check,
        #                 'message': message,
        #             }
        #         )
        #     )
        return None
Exemplo n.º 20
0
    def __call__(self, request):
        if request.user and not isinstance(request.user, AnonymousUser):
            logged_device = self._get_logged_device(request.user, request)

            if logged_device is not None:
                request.logged_device = logged_device
            else:
                raise ApiException(
                    request,
                    _('You are trying to connect from a unknown device.'),
                    status_code=HTTPStatus.FORBIDDEN)

        return self.get_response(request)
Exemplo n.º 21
0
    def delete(self, request, project_id):
        try:
            project = Project.objects.get(pk=project_id)
        except Project.DoesNotExist:
            raise ApiException(request,
                               _('Project does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        for remote in project.remotes.all():
            remote.services.all().delete()
            remote.delete()
        project.delete()

        return HttpResponse(status=HTTPStatus.NO_CONTENT)
Exemplo n.º 22
0
    def put(self, request, user_id):
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            raise ApiException(request,
                               _('User does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        form = UserForms.Update.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        email = form.cleaned_data.get('email')
        assign_projects = form.cleaned_data.get('assign_projects')
        role = form.cleaned_data.get('role')

        if email != user.email:
            if User.objects.filter(email=email).exists():
                raise ApiException(request,
                                   _('Email is already used.'),
                                   status_code=HTTPStatus.CONFLICT)

        form.fill(user)
        user.username = email
        if assign_projects is not None:
            user.assign_projects(request, assign_projects)
        if role:
            clear_roles(user)
            assign_role(user, role.value)
        user.save()

        return SingleResponse(request,
                              data=user,
                              status=HTTPStatus.OK,
                              serializer=UserSerializer.Base)
Exemplo n.º 23
0
    def assign_projects(self, request, projects_devices):
        self.projects_devices.all().delete()

        for project_devices in projects_devices:
            project = project_devices.get('project_id')
            devices = project_devices.get('devices')

            for device in devices:
                if device.user != self:
                    raise ApiException(
                        request,
                        _('The device does not belong to specified user.'),
                        status_code=HTTPStatus.CONFLICT)

                self.projects_devices.create(project=project, device=device)
Exemplo n.º 24
0
    def get(self, request, email):
        try:
            user = User.objects.get(email=email)
        except User.DoesNotExist:
            raise ApiException(request,
                               _('User with specified email does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        timestamp = int(datetime.utcnow().timestamp())
        ts_b36 = int_to_base36(timestamp)
        login_timestamp = '' if user.last_login is None else user.last_login.replace(
            microsecond=0, tzinfo=None)
        hash_value = six.text_type(user.pk) + user.password + six.text_type(
            login_timestamp) + six.text_type(timestamp)

        recovery_hash = salted_hmac(
            settings.SECRET_KEY,
            hash_value,
        ).hexdigest()[::2]

        password_recovery = PasswordRecovery.objects.create(
            value="%s-%s" % (ts_b36, recovery_hash),
            user=user,
            expires_at=timezone.now() + settings.PASSWORD_RECOVERY_TIME)

        recovery_url = f'{settings.BASE_URL}/password/activate/{password_recovery.value}'

        NotificationService.create(
            recipients=[user.email],
            sender=f"{settings.EMAIL_SENDER_NAME} <{settings.EMAIL_SENDER}>",
            subject=_('[Praetorian API] - Email recovery'),
            content={
                'message': _('test'),
                'recovery_url': recovery_url,
                'email_text': _('Your recovery link to Praetorian API is: ')
            },
            template='_emails/password_recovery.html').send_email()

        return SingleResponse(request,
                              password_recovery,
                              status=HTTPStatus.CREATED,
                              serializer=PasswordRecoverySerializer.Base)
Exemplo n.º 25
0
    def post(self, request):
        form = ServiceForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        if form.cleaned_data['remote_id'].services.filter(name=form.cleaned_data['name']).exists():
            raise ApiException(
                request=request,
                message=_('Assigned remote already has service with name: "{service_name}"').format(
                    service_name=form.cleaned_data['name']
                ),
                status_code=HTTPStatus.CONFLICT
            )

        service = Service()
        form.fill(service)
        service.save()

        return SingleResponse(request, service, status=HTTPStatus.CREATED, serializer=ServiceSerializer.Base)
Exemplo n.º 26
0
    def put(self, request, project_id):
        try:
            project = Project.objects.get(pk=project_id)
        except Project.DoesNotExist:
            raise ApiException(request,
                               _('Project does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        form = ProjectForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        form.fill(project)
        project.save()

        return SingleResponse(request,
                              data=project,
                              status=HTTPStatus.OK,
                              serializer=ProjectSerializer.Detail)
Exemplo n.º 27
0
    def put(self, request, api_key_id):
        try:
            api_key = ApiKey.objects.get(pk=api_key_id)
        except ApiKey.DoesNotExist:
            raise ApiException(request,
                               _('Api key does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        form = ApiKeyForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        form.fill(api_key)
        api_key.save()

        return SingleResponse(request,
                              data=api_key,
                              status=HTTPStatus.OK,
                              serializer=ApiKeySerializer.Base)
Exemplo n.º 28
0
    def post(self, request):
        form = RemoteForms.Basic.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        if form.cleaned_data['project_id'].remotes.filter(name=form.cleaned_data['name']).exists():
            raise ApiException(
                request=request,
                message=_('Assigned project already has remote with name: "{remote_name}"').format(
                    remote_name=form.cleaned_data['name']
                ),
                status_code=HTTPStatus.CONFLICT
            )

        remote = Remote()
        form.fill(remote)
        remote.variables = {}
        remote.save()

        return SingleResponse(request, remote, status=HTTPStatus.CREATED, serializer=RemoteSerializer.Base)
Exemplo n.º 29
0
    def post(self, request):
        form = PasswordActivateForm.create_from_request(request)

        if not form.is_valid():
            raise ValidationException(request, form)

        request_data = form.cleaned_data

        try:
            password_recovery = PasswordRecovery.objects.get(
                value=request_data.get('hashed_recovery'),
                expires_at__gt=timezone.now())
        except PasswordRecovery.DoesNotExist:
            raise ApiException(request,
                               _('Password recovery does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        password_recovery.user.set_password(request_data.get('password'))
        password_recovery.user.save()
        PasswordRecovery.objects.filter(user=password_recovery.user).delete()

        return SingleResponse(request, None, status=HTTPStatus.NO_CONTENT)
Exemplo n.º 30
0
    def get(self, request, user_id):
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            raise ApiException(request,
                               _('User does not exist.'),
                               status_code=HTTPStatus.NOT_FOUND)

        otp_secret = pyotp.random_base32()
        qr_code_url = pyotp.totp.TOTP(otp_secret).provisioning_uri(
            name=user.email, issuer_name="Praetorian API")
        response = {'qr_code': qr_code_url}

        if user.additional_data:
            user.additional_data['otp_secret'] = otp_secret
        else:
            user.additional_data = {'otp_secret': otp_secret}
        user.is_2fa = True
        user.save()

        NotificationService.create(
            recipients=[user.email],
            sender=f"{settings.EMAIL_SENDER_NAME} <{settings.EMAIL_SENDER}>",
            subject=_('[Praetorian API] - Two factor authentication'),
            content={
                'message':
                _('test'),
                'qr_code_url':
                self.make_qr_code(qr_code_url),
                'email_text':
                _('QR code to activate your two factor authentication.')
            },
            template='_emails/2fa_activation.html').send_email()

        return SingleResponse(request,
                              response,
                              status=HTTPStatus.CREATED,
                              serializer=UserSerializer.Base)