コード例 #1
0
ファイル: catalogs.py プロジェクト: Sibyx/EvilFlowersCatalog
    def post(self, request):
        form = CatalogForm.create_from_request(request)

        if not request.user.has_perm('core.add_catalog'):
            raise ProblemDetailException(request,
                                         _("Insufficient permissions"),
                                         status=HTTPStatus.FORBIDDEN)

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

        if Catalog.objects.filter(
                url_name=form.cleaned_data['url_name']).exists():
            raise ProblemDetailException(
                request,
                title=_('Catalog url_name already taken'),
                status=HTTPStatus.CONFLICT)

        service = CatalogService()
        catalog = service.populate(catalog=Catalog(creator=request.user),
                                   form=form)

        if not catalog.users.contains(request.user):
            UserCatalog.objects.create(catalog=catalog,
                                       user=request.user,
                                       mode=UserCatalog.Mode.MANAGE)

        return SingleResponse(request,
                              catalog,
                              serializer=CatalogSerializer.Detailed,
                              status=HTTPStatus.CREATED)
コード例 #2
0
    def post(self, request):
        form = RefreshTokenForm.create_from_request(request)

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

        try:
            claims = JWTFactory.decode(form.cleaned_data['refresh'])
        except JoseError as e:
            raise ProblemDetailException(request,
                                         _('Invalid token.'),
                                         status=HTTPStatus.UNAUTHORIZED,
                                         previous=e)

        redis = Redis(host=settings.REDIS_HOST,
                      port=settings.REDIS_PORT,
                      db=settings.REDIS_DATABASE)

        if not redis.exists(f"refresh_token:{claims['jti']}"):
            raise UnauthorizedException(request)

        access_token = JWTFactory(claims['sub']).access()

        return SingleResponse(request, {'access_token': access_token},
                              status=HTTPStatus.OK)
コード例 #3
0
    def post(self, request):
        form = AccessTokenForm.create_from_request(request)

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

        backend = ModelBackend()
        user = backend.authenticate(request,
                                    username=form.cleaned_data['username'],
                                    password=form.cleaned_data['password'])

        if not user:
            raise UnauthorizedException(request)

        access_token = JWTFactory(user.pk).access()
        jti, refresh_token = JWTFactory(user.pk).refresh()

        redis = Redis(host=settings.REDIS_HOST,
                      port=settings.REDIS_PORT,
                      db=settings.REDIS_DATABASE)

        redis.set(f"refresh_token:{jti}", jti)
        redis.expire(f"refresh_token:{jti}",
                     settings.SECURED_VIEW_JWT_REFRESH_TOKEN_EXPIRATION)

        return SingleResponse(request, {
            'access_token': access_token,
            'refresh_token': refresh_token
        },
                              status=HTTPStatus.OK)
コード例 #4
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)
コード例 #5
0
ファイル: users.py プロジェクト: Sibyx/EvilFlowersCatalog
    def post(self, request):
        form = CreateUserForm.create_from_request(request)

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

        if not request.user.has_perm('core.add_user'):
            raise ProblemDetailException(request,
                                         _("Insufficient permissions"),
                                         status=HTTPStatus.FORBIDDEN)

        if User.objects.filter(email=form.cleaned_data['email']).exists():
            raise ProblemDetailException(
                request,
                _("User with same email already exists"),
                status=HTTPStatus.CONFLICT)

        user = User()
        form.populate(user)
        user.set_password(form.cleaned_data['password'])
        user.save()

        return SingleResponse(request,
                              user,
                              serializer=UserSerializer.Base,
                              status=HTTPStatus.CREATED)
コード例 #6
0
    def post(self, request):
        form = FeedForm.create_from_request(request)

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

        if not has_object_permission('check_catalog_manage', request.user,
                                     form.cleaned_data['catalog_id']):
            raise ProblemDetailException(request,
                                         _("Insufficient permissions"),
                                         status=HTTPStatus.FORBIDDEN)

        if Feed.objects.filter(
                catalog=form.cleaned_data['catalog_id'],
                url_name=form.cleaned_data['url_name']).exists():
            raise ProblemDetailException(
                request,
                _("Feed with same url_name already exists in same catalog"),
                status=HTTPStatus.CONFLICT)

        feed = Feed(creator=request.user)
        form.populate(feed)
        feed.save()

        if 'entries' in form.cleaned_data.keys():
            feed.entries.add(*form.cleaned_data['entries'])

        if 'parents' in form.cleaned_data.keys():
            feed.parents.add(*form.cleaned_data['parents'])

        return SingleResponse(request,
                              feed,
                              serializer=FeedSerializer.Base,
                              status=HTTPStatus.CREATED)
コード例 #7
0
    def put(self, request, feed_id: UUID):
        feed = self._get_feed(request, feed_id)

        form = FeedForm.create_from_request(request)
        form['parents'].queryset = form['parents'].queryset.exclude(pk=feed.pk)

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

        if Feed.objects.filter(catalog=form.cleaned_data['catalog_id'],
                               url_name=form.cleaned_data['url_name']).exclude(
                                   pk=feed.id).exists():
            raise ProblemDetailException(
                request,
                _("Feed with same url_name already exists in same catalog"),
                status=HTTPStatus.CONFLICT)

        form.populate(feed)
        feed.save()

        if feed.kind == Feed.FeedKind.ACQUISITION and 'entries' in form.cleaned_data.keys(
        ):
            feed.entries.clear()
            feed.entries.add(*form.cleaned_data['entries'])

        if feed.kind == Feed.FeedKind.NAVIGATION and 'parents' in form.cleaned_data.keys(
        ):
            feed.parents.clear()
            feed.parents.add(*form.cleaned_data['parents'])

        return SingleResponse(request, feed, serializer=FeedSerializer.Base)
コード例 #8
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)
コード例 #9
0
ファイル: users.py プロジェクト: Sibyx/EvilFlowersCatalog
    def delete(self, request, user_id: UUID):
        user = self._get_user(
            request, user_id,
            lambda: request.user.has_perm('core.delete_user'))
        user.hard_delete()

        return SingleResponse(request)
コード例 #10
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)
コード例 #11
0
    def get(self, request, acquisition_id: UUID):
        acquisition = self._get_acquisition(request, acquisition_id,
                                            'check_catalog_read')

        return SingleResponse(request,
                              acquisition,
                              serializer=AcquisitionSerializer.Detailed)
コード例 #12
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)
コード例 #13
0
    def post(self, request):
        form = CreateAuthorForm.create_from_request(request)

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

        if not has_object_permission('check_catalog_write', request.user,
                                     form.cleaned_data['catalog_id']):
            raise ProblemDetailException(request,
                                         _("Insufficient permissions"),
                                         status=HTTPStatus.FORBIDDEN)

        if Author.objects.filter(
                catalog=form.cleaned_data['catalog_id'],
                name=form.cleaned_data['name'],
                surname=form.cleaned_data['surname']).exists():
            raise ProblemDetailException(
                request,
                _("Author already exists in the catalog"),
                status=HTTPStatus.CONFLICT)

        author = Author()
        form.populate(author)
        author.save()

        return SingleResponse(request,
                              author,
                              serializer=AuthorSerializer.Detailed,
                              status=HTTPStatus.CREATED)
コード例 #14
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)
コード例 #15
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)
コード例 #16
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)
コード例 #17
0
    def post(self, request):
        form = ProjectForms.Basic.create_from_request(request)

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

        project = Project()
        form.fill(project)
        project.save()

        return SingleResponse(request,
                              project,
                              status=HTTPStatus.CREATED,
                              serializer=ProjectSerializer.Detail)
コード例 #18
0
ファイル: entries.py プロジェクト: Sibyx/EvilFlowersCatalog
    def put(self, request, catalog_id: uuid.UUID, entry_id: uuid.UUID):
        entry = self._get_entry(request, catalog_id, entry_id)

        form = EntryForm.create_from_request(request)
        form.fields['category_ids'].queryset = form.fields['category_ids'].queryset.filter(catalog_id=catalog_id)
        form.fields['author_id'].queryset = form.fields['author_id'].queryset.filter(catalog_id=catalog_id)

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

        service = EntryService(
            Catalog.objects.get(pk=catalog_id), request.user
        )
        service.populate(entry, form)

        return SingleResponse(request, entry, serializer=EntrySerializer.Detailed)
コード例 #19
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)
コード例 #20
0
ファイル: users.py プロジェクト: Sibyx/EvilFlowersCatalog
    def put(self, request, user_id: UUID):
        form = UserForm.create_from_request(request)

        user = self._get_user(
            request, user_id,
            lambda: request.user.has_perm('core.change_user'))

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

        form.populate(user)
        if 'password' in form.cleaned_data.keys():
            user.set_password(form.cleaned_data['password'])
        user.save()

        return SingleResponse(request, user, serializer=UserSerializer.Base)
コード例 #21
0
    def delete(self, request, api_key_id: UUID):
        try:
            api_key = ApiKey.objects.get(pk=api_key_id)
        except ApiKey.DoesNotExist as e:
            raise ProblemDetailException(request,
                                         _("ApiKey not found"),
                                         status=HTTPStatus.NOT_FOUND,
                                         previous=e)

        if not request.user.is_superuser and api_key.user_id != request.user.id:
            raise ProblemDetailException(request,
                                         _("ApiKey not found"),
                                         status=HTTPStatus.NOT_FOUND)

        api_key.hard_delete()

        return SingleResponse(request, status=HTTPStatus.NO_CONTENT)
コード例 #22
0
ファイル: status.py プロジェクト: Sibyx/EvilFlowersCatalog
    def get(self, request):
        response = {
            'timestamp': timezone.now(),
            'version': settings.VERSION,
            'instance': settings.INSTANCE_NAME,
            'stats': {
                'catalogs': Catalog.objects.count(),
                'entries': Entry.objects.count(),
                'acquisitions': Acquisition.objects.count(),
                'users': User.objects.count()
            },
        }

        if settings.DEBUG:
            response['python'] = sys.version

        return SingleResponse(request, response)
コード例 #23
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)
コード例 #24
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)
コード例 #25
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)
コード例 #26
0
    def post(self, request):
        form = ApiKeyForm.create_from_request(request)

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

        if 'user_id' in form.cleaned_data.keys(
        ) and not request.user.is_superuser:
            raise ProblemDetailException(request,
                                         _("Insufficient permissions"),
                                         status=HTTPStatus.FORBIDDEN)

        api_key = ApiKey(user=request.user)
        form.populate(api_key)
        api_key.save()

        return SingleResponse(request,
                              api_key,
                              serializer=ApiKeySerializer.Base,
                              status=HTTPStatus.CREATED)
コード例 #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)
コード例 #28
0
ファイル: catalogs.py プロジェクト: Sibyx/EvilFlowersCatalog
    def put(self, request, catalog_id: UUID):
        form = CatalogForm.create_from_request(request)

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

        catalog = self._get_catalog(request, catalog_id)

        if Catalog.objects.exclude(pk=catalog.pk).filter(
                url_name=form.cleaned_data['url_name']).exists():
            raise ProblemDetailException(
                request,
                title=_('Catalog url_name already taken'),
                status=HTTPStatus.CONFLICT)

        service = CatalogService()
        catalog = service.populate(catalog=catalog, form=form)

        return SingleResponse(request,
                              catalog,
                              serializer=CatalogSerializer.Detailed)
コード例 #29
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)
コード例 #30
0
ファイル: entries.py プロジェクト: Sibyx/EvilFlowersCatalog
    def post(self, request, catalog_id: uuid.UUID):
        try:
            catalog = Catalog.objects.get(pk=catalog_id)
        except Catalog.DoesNotExist as e:
            raise ProblemDetailException(request, _("Catalog not found"), status=HTTPStatus.NOT_FOUND, previous=e)

        if not has_object_permission('check_catalog_write', request.user, catalog):
            raise ProblemDetailException(request, _("Insufficient permissions"), status=HTTPStatus.FORBIDDEN)

        form = EntryForm.create_from_request(request)
        form.fields['category_ids'].queryset = form.fields['category_ids'].queryset.filter(catalog=catalog)
        form.fields['author_id'].queryset = form.fields['author_id'].queryset.filter(catalog=catalog)

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

        entry = Entry(creator=request.user, catalog=catalog)
        service = EntryService(catalog, request.user)
        service.populate(entry, form)

        return SingleResponse(request, entry, serializer=EntrySerializer.Detailed, status=HTTPStatus.CREATED)