diff --git a/alembic/env.py b/alembic/env.py index e69c895e..2f14acfe 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -8,10 +8,10 @@ from alembic import context from private_gpt.users.db.base_class import Base from private_gpt.users.core.config import SQLALCHEMY_DATABASE_URI + from private_gpt.users.models.user import User from private_gpt.users.models.role import Role from private_gpt.users.models.user_role import UserRole - # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config diff --git a/alembic/versions/9491fd6d6fad_create_user_model.py b/alembic/versions/3cd055fe81a3_create_user_model.py similarity index 60% rename from alembic/versions/9491fd6d6fad_create_user_model.py rename to alembic/versions/3cd055fe81a3_create_user_model.py index 9b291fc2..131c087e 100644 --- a/alembic/versions/9491fd6d6fad_create_user_model.py +++ b/alembic/versions/3cd055fe81a3_create_user_model.py @@ -1,8 +1,8 @@ """Create user model -Revision ID: 9491fd6d6fad -Revises: 19e9eccf2c81 -Create Date: 2024-01-11 17:02:25.882848 +Revision ID: 3cd055fe81a3 +Revises: +Create Date: 2024-01-14 10:44:37.040428 """ from typing import Sequence, Union @@ -12,19 +12,19 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision: str = '9491fd6d6fad' -down_revision: Union[str, None] = '19e9eccf2c81' +revision: str = '3cd055fe81a3' +down_revision: Union[str, None] = None 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.create_unique_constraint('unique_user_role', 'user_roles', ['user_id', 'role_id']) + pass # ### end Alembic commands ### def downgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint('unique_user_role', 'user_roles', type_='unique') + pass # ### end Alembic commands ### diff --git a/alembic/versions/19e9eccf2c81_create_user_model_role_model_and_user_.py b/alembic/versions/cba9e6e394ca_create_user_model_and_role.py similarity index 88% rename from alembic/versions/19e9eccf2c81_create_user_model_role_model_and_user_.py rename to alembic/versions/cba9e6e394ca_create_user_model_and_role.py index 5830206f..e85e6192 100644 --- a/alembic/versions/19e9eccf2c81_create_user_model_role_model_and_user_.py +++ b/alembic/versions/cba9e6e394ca_create_user_model_and_role.py @@ -1,8 +1,8 @@ -"""Create user model, role model and user role model +"""Create user model and role -Revision ID: 19e9eccf2c81 -Revises: -Create Date: 2024-01-11 16:33:53.253969 +Revision ID: cba9e6e394ca +Revises: 3cd055fe81a3 +Create Date: 2024-01-14 10:46:33.847333 """ from typing import Sequence, Union @@ -12,8 +12,8 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision: str = '19e9eccf2c81' -down_revision: Union[str, None] = None +revision: str = 'cba9e6e394ca' +down_revision: Union[str, None] = '3cd055fe81a3' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None @@ -31,7 +31,7 @@ def upgrade() -> None: op.create_table('users', sa.Column('id', sa.Integer(), nullable=False), sa.Column('email', sa.String(length=225), nullable=False), - sa.Column('hashed_password', sa.LargeBinary(), nullable=False), + sa.Column('hashed_password', sa.String(), nullable=False), sa.Column('fullname', sa.String(length=225), nullable=False), sa.Column('is_active', sa.Boolean(), nullable=True), sa.Column('last_login', sa.DateTime(), nullable=True), diff --git a/private_gpt/alembic.ini b/private_gpt/alembic.ini deleted file mode 100644 index c10d4ca0..00000000 --- a/private_gpt/alembic.ini +++ /dev/null @@ -1,116 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# path to migration scripts -script_location = alembic - -# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s -# Uncomment the line below if you want the files to be prepended with date and time -# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file -# for all available tokens -# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s - -# sys.path path, will be prepended to sys.path if present. -# defaults to the current working directory. -prepend_sys_path = . - -# timezone to use when rendering the date within the migration file -# as well as the filename. -# If specified, requires the python>=3.9 or backports.zoneinfo library. -# Any required deps can installed by adding `alembic[tz]` to the pip requirements -# string value is passed to ZoneInfo() -# leave blank for localtime -# timezone = - -# max length of characters to apply to the -# "slug" field -# truncate_slug_length = 40 - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - -# set to 'true' to allow .pyc and .pyo files without -# a source .py file to be detected as revisions in the -# versions/ directory -# sourceless = false - -# version location specification; This defaults -# to alembic/versions. When using multiple version -# directories, initial revisions must be specified with --version-path. -# The path separator used here should be the separator specified by "version_path_separator" below. -# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions - -# version path separator; As mentioned above, this is the character used to split -# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep. -# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas. -# Valid values for version_path_separator are: -# -# version_path_separator = : -# version_path_separator = ; -# version_path_separator = space -version_path_separator = os # Use os.pathsep. Default configuration used for new projects. - -# set to 'true' to search source files recursively -# in each "version_locations" directory -# new in Alembic version 1.10 -# recursive_version_locations = false - -# the output encoding used when revision files -# are written from script.py.mako -# output_encoding = utf-8 - -sqlalchemy.url = driver://user:pass@localhost/dbname - - -[post_write_hooks] -# post_write_hooks defines scripts or Python functions that are run -# on newly generated revision scripts. See the documentation for further -# detail and examples - -# format using "black" - use the console_scripts runner, against the "black" entrypoint -# hooks = black -# black.type = console_scripts -# black.entrypoint = black -# black.options = -l 79 REVISION_SCRIPT_FILENAME - -# lint with attempts to fix using "ruff" - use the exec runner, execute a binary -# hooks = ruff -# ruff.type = exec -# ruff.executable = %(here)s/.venv/bin/ruff -# ruff.options = --fix REVISION_SCRIPT_FILENAME - -# Logging configuration -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/private_gpt/users/api/v1/api.py b/private_gpt/users/api/v1/api.py index da97144c..bc9f6709 100644 --- a/private_gpt/users/api/v1/api.py +++ b/private_gpt/users/api/v1/api.py @@ -1,9 +1,9 @@ from private_gpt.users.api.v1.routers import auth, roles, user_roles, users from fastapi import APIRouter -api_router = APIRouter() +api_router = APIRouter(prefix="/v1") api_router.include_router(auth.router) -# api_router.include_router(users.router) -# api_router.include_router(roles.router) -# api_router.include_router(user_roles.router) \ No newline at end of file +api_router.include_router(users.router) +api_router.include_router(roles.router) +api_router.include_router(user_roles.router) \ No newline at end of file diff --git a/private_gpt/users/api/v1/routers/auth.py b/private_gpt/users/api/v1/routers/auth.py index 570b3b90..24ba8a7a 100644 --- a/private_gpt/users/api/v1/routers/auth.py +++ b/private_gpt/users/api/v1/routers/auth.py @@ -25,12 +25,13 @@ def login_access_token( user = crud.user.authenticate( db, email=form_data.username, password=form_data.password ) + print("USER object", user) if not user: raise HTTPException( status_code=400, detail="Incorrect email or password" ) - elif not crud.user.is_active(user): - raise HTTPException(status_code=400, detail="Inactive user") + # elif not crud.user.is_active(user): + # raise HTTPException(status_code=400, detail="Inactive user") access_token_expires = timedelta( minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES @@ -38,12 +39,15 @@ def login_access_token( refresh_token_expires = timedelta( minutes=settings.REFRESH_TOKEN_EXPIRE_MINUTES ) - + print(f"Access Token expires: {access_token_expires}\n Refresh token expires: {refresh_token_expires}") user_in = schemas.UserUpdate( + email = user.email, + fullname = user.fullname, last_login=datetime.now() ) + print("Update last login schema: ", user_in) user = crud.user.update(db, db_obj=user, obj_in=user_in) - + print("update in database:", user) if not user.user_role: role = "GUEST" else: @@ -81,23 +85,18 @@ def register( status_code=409, detail="The user with this username already exists in the system", ) - print("here 1...") user_in = schemas.UserCreate( email=email, password=password, fullname=fullname, ) - print("here 2...") # create user user = crud.user.create(db, obj_in=user_in) - print("here 4...") - # get role - role = crud.role.get_by_name(db, name=Role.ACCOUNT_ADMIN["name"]) - - print("here 4...") + role = crud.role.get_by_name(db, name=Role.GUEST["name"]) + print("ROLE:", role) # assign user_role user_role_in = schemas.UserRoleCreate( user_id=user.id, @@ -105,8 +104,7 @@ def register( ) user_role = crud.user_role.create(db, obj_in=user_role_in) - print("here 5...") - + print(user) access_token_expires = timedelta( minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES @@ -118,6 +116,7 @@ def register( role = "GUEST" else: role = user.user_role.role.name + token_payload = { "id": str(user.id), "role": role, diff --git a/private_gpt/users/api/v1/routers/roles.py b/private_gpt/users/api/v1/routers/roles.py index e8f64318..2d7db2ef 100644 --- a/private_gpt/users/api/v1/routers/roles.py +++ b/private_gpt/users/api/v1/routers/roles.py @@ -7,12 +7,12 @@ from sqlalchemy.orm import Session router = APIRouter(prefix='/roles', tags=['roles']) -@router.get("/", response_model= List[schemas.Role]) +@router.get("/", response_model=List[schemas.Role]) def get_roles( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, ) -> Any: """ - Retrieve all avaiable user roles. + Retrieve all available user roles. """ - roles = crud.roles_crud.get_multi(db, skip=skip, limit=limit) + roles = crud.role.get_multi(db, skip=skip, limit=limit) return roles \ No newline at end of file diff --git a/private_gpt/users/models/user.py b/private_gpt/users/models/user.py index ef476ee4..fd2c2f4c 100644 --- a/private_gpt/users/models/user.py +++ b/private_gpt/users/models/user.py @@ -19,7 +19,7 @@ class User(Base): id = Column(Integer, nullable=False, primary_key=True) email = Column(String(225), nullable=False, unique=True) - hashed_password = Column(LargeBinary, nullable=False) + hashed_password = Column(String, nullable=False) fullname = Column(String(225), nullable=False) UniqueConstraint("email", name="uq_user_email") diff --git a/private_gpt/users/schemas/user.py b/private_gpt/users/schemas/user.py index 3f4f3d98..6a8a4488 100644 --- a/private_gpt/users/schemas/user.py +++ b/private_gpt/users/schemas/user.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Optional from pydantic import BaseModel, Field, EmailStr -from private_gpt.users.models.user_role import UserRole +from private_gpt.users.schemas.user_role import UserRole class UserBaseSchema(BaseModel): diff --git a/private_gpt/users/schemas/user_role.py b/private_gpt/users/schemas/user_role.py index 6bf2bf20..091a2747 100644 --- a/private_gpt/users/schemas/user_role.py +++ b/private_gpt/users/schemas/user_role.py @@ -1,6 +1,6 @@ from typing import Optional -from private_gpt.users.models.role import Role +from private_gpt.users.schemas.role import Role from pydantic import BaseModel # Shared properties