5.12 Управление правами доступа в FastAPI
5 из 5 шагов пройдено

Приступим к установке прав доступа для конечных точек товаров. В файле routers/products.py мы добавили следующие пути:

  • all_products - Метод получения всех товаров
  • create_product - Метод создания товара
  • product_by_category - Метод получения товаров определенной категории
  • product_detail - Метод получения детальной информации о товаре
  • update_product - Метод изменения товара
  • delete_product - Метод удаления товара

Начнем реализацию, в файле routers/products.py изменим конечную точку создания товаров:

@router.post('/create')
async def create_product(db: Annotated[AsyncSession, Depends(get_db)], create_product: CreateProduct,
                         get_user: Annotated[dict, Depends(get_current_user)]):
    if get_user.get('is_supplier') or get_user.get('is_admin'):
        await db.execute(insert(Product).values(name=create_product.name,
                                                description=create_product.description,
                                                price=create_product.price,
                                                image_url=create_product.image_url,
                                                stock=create_product.stock,
                                                category_id=create_product.category,
                                                rating=0.0,
                                                slug=slugify(create_product.name),
                                                supplier_id=get_user.get('id')))
        await db.commit()
        return {
            'status_code': status.HTTP_201_CREATED,
            'transaction': 'Successful'
        }
    else:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail='You are not authorized to use this method'
        )

Первым делом мы добавили условие, кто может создавать товары, get_user.get('is_supplier') или get_user.get('is_admin'). Мы получаем данные параметры из JWT токена, чтобы создавать товар мог, только пользователь со статусом продавец или администратор. Также обратите внимание, что теперь при создании товара, мы  заполняем поле продавца товара supplier_id=get_user.get('id'), чтобы закрепить за продавцем данный товар.

В ином случае мы вызываем 401 ошибку с текстом "You are not authorized to use this method"

По аналогии изменим конечные точки отвечающие за изменение товаров:

@router.put('/detail/{product_slug}')
async def update_product(db: Annotated[AsyncSession, Depends(get_db)], product_slug: str,
                         update_product_model: CreateProduct, get_user: Annotated[dict, Depends(get_current_user)]):
    product_update = await db.scalar(select(Product).where(Product.slug == product_slug))
    if product_update is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail='There is no product found'
        )
    if get_user.get('is_supplier') or get_user.get('is_admin'):
        if get_user.get('id') == product_update.supplier_id or get_user.get('is_admin'):
            await db.execute(
                update(Product).where(Product.slug == product_slug)
                .values(name=update_product_model.name,
                        description=update_product_model.description,
                        price=update_product_model.price,
                        image_url=update_product_model.image_url,
                        stock=update_product_model.stock,
                        category_id=update_product_model.category,
                        slug=slugify(update_product_model.name)))
            await db.commit()
            return {
                'status_code': status.HTTP_200_OK,
                'transaction': 'Product update is successful'
            }
        else:

            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail='You are not authorized to use this method'
            )
    else:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail='You are not authorized to use this method'
        )

Но в данной конечной точке мы проверяем условие, кто отправляет запрос, продавец или администратор.

Далее в строке if get_user.get('id') == product_update.supplier_id or get_user.get('is_admin') мы проверяем, у того кто обратился, id равен id продавцу товара или это администратор.

По аналогии поступим и для конечной точки удаления товаров.

@router.delete('/delete')
async def delete_product(db: Annotated[AsyncSession, Depends(get_db)], product_id: int,
                         get_user: Annotated[dict, Depends(get_current_user)]):
    product_delete = await db.scalar(select(Product).where(Product.id == product_id))
    if product_delete is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail='There is no product found'
        )
    if get_user.get('is_supplier') or get_user.get('is_admin'):
        if get_user.get('id') == product_delete.supplier_id or get_user.get('is_admin'):
            await db.execute(update(Product).where(Product.id == product_id).values(is_active=False))
            await db.commit()
            return {
                'status_code': status.HTTP_200_OK,
                'transaction': 'Product delete is successful'
            }
        else:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail='You are not authorized to use this method'
            )
    else:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail='You are not authorized to use this method'
        )

 

Заключение.

Безопасность любых приложений всегда является главным приоритетом при создании качественного проекта. FastAPI — это одна из платформ API, которая имеет встроенную поддержку многих популярных процессов аутентификации, от базовой до спецификации OpenID Connect. Он полностью поддерживает все эффективные схемы аутентификации OAuth2 и даже доступен для дальнейшей настройки API безопасности.

В нашем случае метод get_current_user() должен быть внедрен в каждую реализацию сервиса, чтобы ограничить доступ пользователей. Он не только проверит учетные данные, но и выполнит декодирование полезной нагрузки JWT.


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Нет обсуждений. Начните первое.