Skip to content

Commit

Permalink
Merge pull request #44 from tigran-saatchyan/features/26-authenticate…
Browse files Browse the repository at this point in the history
…-and-authorize

[FEATURE] Added authentication and auuthorization - #26
  • Loading branch information
tigran-saatchyan authored Nov 15, 2023
2 parents 25c853e + 3be1168 commit 97ded85
Show file tree
Hide file tree
Showing 34 changed files with 927 additions and 246 deletions.
2 changes: 2 additions & 0 deletions app/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# TODO @Tigran_Saatchyan: refactor pattern of this package to
# implements correct versioning of API
34 changes: 34 additions & 0 deletions app/api/v1/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from fastapi import FastAPI
from fastapi_users import FastAPIUsers

from app.models import User
from app.schemas.users import UserCreate, UserRead, UserUpdate
from app.services.managers import get_user_manager
from app.settings.auth import auth_backend

PREFIX = "/api/v1"
AUTH_TAG = "Authication"


fastapi_users = FastAPIUsers[User, int](
get_user_manager,
[auth_backend],
)


def set_up_auth_routes(application: FastAPI):
application.include_router(
fastapi_users.get_auth_router(auth_backend),
prefix=f"{PREFIX}/jwt",
tags=[AUTH_TAG],
)
application.include_router(
fastapi_users.get_register_router(UserRead, UserCreate),
prefix=PREFIX,
tags=[AUTH_TAG],
)
application.include_router(
fastapi_users.get_users_router(UserRead, UserUpdate),
prefix="/users",
tags=["Users"],
)
3 changes: 3 additions & 0 deletions app/api/v1/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from fastapi import Depends

from app.api.v1.auth import fastapi_users
from app.utils.unitofwork import IUnitOfWork, UnitOfWork

UOWDependency = Annotated[IUnitOfWork, Depends(UnitOfWork)]

current_user = fastapi_users.current_user()
23 changes: 15 additions & 8 deletions app/api/v1/products.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from fastapi import APIRouter
from typing import Annotated

from app.api.v1.dependencies import UOWDependency
from fastapi import APIRouter, Depends

from app.api.v1.dependencies import UOWDependency, current_user
from app.models import User
from app.schemas.products import ProductsSchemaAdd, ProductsSchemaEdit
from app.services.products import ProductsService

Expand All @@ -11,29 +14,33 @@


@router.post("/")
async def add_product(product: ProductsSchemaAdd, uow: UOWDependency) -> int:
return await ProductsService().add(uow, product)
async def add_product(
user: Annotated[User, Depends(current_user)],
product: ProductsSchemaAdd,
uow: UOWDependency,
) -> int:
return await ProductsService().add(uow, product, user)


@router.get("/")
@router.get("/", dependencies=[Depends(current_user)])
async def get_products(uow: UOWDependency):
return await ProductsService().get_all(uow)


@router.get("/{product_id}")
@router.get("/{product_id}", dependencies=[Depends(current_user)])
async def get_product(product_id: int, uow: UOWDependency):
return await ProductsService().get(uow, product_id)


@router.patch("/{product_id}")
@router.patch("/{product_id}", dependencies=[Depends(current_user)])
async def update_product(
product_id: int, product: ProductsSchemaEdit, uow: UOWDependency
):
await ProductsService().update(uow, product_id, product)
return {"message": "Product updated successfully"}


@router.delete("/{product_id}")
@router.delete("/{product_id}", dependencies=[Depends(current_user)])
async def delete_product(product_id: int, uow: UOWDependency):
await ProductsService().delete(uow, product_id)
return {"message": "Product deleted successfully"}
2 changes: 0 additions & 2 deletions app/api/v1/routers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from app.api.v1.products import router as product_router
from app.api.v1.users import router as user_router

all_routers = [
product_router,
user_router,
]
25 changes: 0 additions & 25 deletions app/api/v1/users.py

This file was deleted.

5 changes: 5 additions & 0 deletions app/db/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from app.db.db import Base

__all__ = [
"Base",
]
5 changes: 4 additions & 1 deletion app/db/db.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.ext.asyncio import (
async_sessionmaker,
create_async_engine,
)
from sqlalchemy.orm import declarative_base

from app.settings import config
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""removed password_salt field
Revision ID: 1aeee680cc4d
Revises: 64ad69e55ba4
Create Date: 2023-11-15 14:43:08.233170+04:00
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '1aeee680cc4d'
down_revision: Union[str, None] = '64ad69e55ba4'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.REAL(),
type_=sa.Float(precision=2),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
op.drop_column('users', 'password_salt')
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('password_salt', postgresql.BYTEA(), autoincrement=False, nullable=False))
op.alter_column('products', 'price',
existing_type=sa.Float(precision=2),
type_=sa.REAL(),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###
38 changes: 38 additions & 0 deletions app/migrations/versions/39ccc998471c_updated_last_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""updated last_login
Revision ID: 39ccc998471c
Revises: 1aeee680cc4d
Create Date: 2023-11-15 14:56:26.586220+04:00
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '39ccc998471c'
down_revision: Union[str, None] = '1aeee680cc4d'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.REAL(),
type_=sa.Float(precision=2),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.Float(precision=2),
type_=sa.REAL(),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###
46 changes: 46 additions & 0 deletions app/migrations/versions/49af15ac2ace_updated_last_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""updated last_login
Revision ID: 49af15ac2ace
Revises: 39ccc998471c
Create Date: 2023-11-15 14:59:34.457751+04:00
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '49af15ac2ace'
down_revision: Union[str, None] = '39ccc998471c'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.REAL(),
type_=sa.Float(precision=2),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
op.alter_column('users', 'last_login',
existing_type=postgresql.TIMESTAMP(),
type_=sa.TIMESTAMP(timezone=True),
nullable=False)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('users', 'last_login',
existing_type=sa.TIMESTAMP(timezone=True),
type_=postgresql.TIMESTAMP(),
nullable=True)
op.alter_column('products', 'price',
existing_type=sa.Float(precision=2),
type_=sa.REAL(),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###
40 changes: 40 additions & 0 deletions app/migrations/versions/541102dacd00_updated_users_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""updated Users table
Revision ID: 541102dacd00
Revises: 95adae9f1847
Create Date: 2023-11-15 13:11:34.194328+04:00
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '541102dacd00'
down_revision: Union[str, None] = '95adae9f1847'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.REAL(),
type_=sa.Float(precision=2),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
op.drop_column('users', 'is_staff')
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('is_staff', sa.BOOLEAN(), autoincrement=False, nullable=False))
op.alter_column('products', 'price',
existing_type=sa.Float(precision=2),
type_=sa.REAL(),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""updated password_hash field type
Revision ID: 64ad69e55ba4
Revises: 541102dacd00
Create Date: 2023-11-15 14:42:09.902416+04:00
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '64ad69e55ba4'
down_revision: Union[str, None] = '541102dacd00'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('products', 'price',
existing_type=sa.REAL(),
type_=sa.Float(precision=2),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
op.alter_column('users', 'hashed_password',
existing_type=postgresql.BYTEA(),
type_=sa.String(length=1024),
existing_nullable=False)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('users', 'hashed_password',
existing_type=sa.String(length=1024),
type_=postgresql.BYTEA(),
existing_nullable=False)
op.alter_column('products', 'price',
existing_type=sa.Float(precision=2),
type_=sa.REAL(),
existing_nullable=False,
existing_server_default=sa.text("'0'::real"))
# ### end Alembic commands ###
Loading

0 comments on commit 97ded85

Please sign in to comment.