@@ -13,7 +13,7 @@ | |||
## How to launch | |||
First, make sure that python is installed. Create a virtual environment (if you want to) | |||
``` | |||
python -m venv venv | |||
python/python3 -m venv venv | |||
source /venv/bin/activate | |||
``` | |||
(not necessary) | |||
@@ -1 +0,0 @@ | |||
Generic single-database configuration. |
@@ -1,85 +0,0 @@ | |||
from logging.config import fileConfig | |||
from sqlalchemy import engine_from_config | |||
from sqlalchemy import pool | |||
from alembic import context | |||
from core.config import settings | |||
from db.base import Base | |||
# this is the Alembic Config object, which provides | |||
# access to the values within the .ini file in use. | |||
config = context.config | |||
config.set_main_option("sqlalchemy.url", settings.DATABASE_URL) | |||
# Interpret the config file for Python logging. | |||
# This line sets up loggers basically. | |||
if config.config_file_name is not None: | |||
fileConfig(config.config_file_name) | |||
# add your model's MetaData object here | |||
# for 'autogenerate' support | |||
# from myapp import mymodel | |||
# target_metadata = mymodel.Base.metadata | |||
target_metadata = Base.metadata | |||
print("Alembic env.py target_metadata: ", target_metadata) | |||
print("Alembic env.py settings: ", settings.DATABASE_URL) | |||
print("Alembic env.py config: ", Base) | |||
# other values from the config, defined by the needs of env.py, | |||
# can be acquired: | |||
# my_important_option = config.get_main_option("my_important_option") | |||
# ... etc. | |||
def run_migrations_offline() -> None: | |||
"""Run migrations in 'offline' mode. | |||
This configures the context with just a URL | |||
and not an Engine, though an Engine is acceptable | |||
here as well. By skipping the Engine creation | |||
we don't even need a DBAPI to be available. | |||
Calls to context.execute() here emit the given string to the | |||
script output. | |||
""" | |||
url = config.get_main_option("sqlalchemy.url") | |||
context.configure( | |||
url=url, | |||
target_metadata=target_metadata, | |||
literal_binds=True, | |||
dialect_opts={"paramstyle": "named"}, | |||
) | |||
with context.begin_transaction(): | |||
context.run_migrations() | |||
def run_migrations_online() -> None: | |||
"""Run migrations in 'online' mode. | |||
In this scenario we need to create an Engine | |||
and associate a connection with the context. | |||
""" | |||
connectable = engine_from_config( | |||
config.get_section(config.config_ini_section, {}), | |||
prefix="sqlalchemy.", | |||
poolclass=pool.NullPool, | |||
) | |||
with connectable.connect() as connection: | |||
context.configure(connection=connection, target_metadata=target_metadata) | |||
with context.begin_transaction(): | |||
context.run_migrations() | |||
if context.is_offline_mode(): | |||
run_migrations_offline() | |||
else: | |||
run_migrations_online() |
@@ -1,26 +0,0 @@ | |||
"""${message} | |||
Revision ID: ${up_revision} | |||
Revises: ${down_revision | comma,n} | |||
Create Date: ${create_date} | |||
""" | |||
from typing import Sequence, Union | |||
from alembic import op | |||
import sqlalchemy as sa | |||
${imports if imports else ""} | |||
# revision identifiers, used by Alembic. | |||
revision: str = ${repr(up_revision)} | |||
down_revision: Union[str, None] = ${repr(down_revision)} | |||
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} | |||
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} | |||
def upgrade() -> None: | |||
${upgrades if upgrades else "pass"} | |||
def downgrade() -> None: | |||
${downgrades if downgrades else "pass"} |
@@ -1,30 +0,0 @@ | |||
"""Edit vehicle table, fix due to SRS | |||
Revision ID: 47f450cb5e82 | |||
Revises: aa72d2118245 | |||
Create Date: 2023-09-04 15:18:23.713730 | |||
""" | |||
from typing import Sequence, Union | |||
from alembic import op | |||
import sqlalchemy as sa | |||
# revision identifiers, used by Alembic. | |||
revision: str = '47f450cb5e82' | |||
down_revision: Union[str, None] = 'aa72d2118245' | |||
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! ### | |||
pass | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
pass | |||
# ### end Alembic commands ### |
@@ -1,30 +0,0 @@ | |||
"""Fix | |||
Revision ID: 95369c9d99cc | |||
Revises: f272ebbba83d | |||
Create Date: 2023-09-04 16:02:51.465863 | |||
""" | |||
from typing import Sequence, Union | |||
from alembic import op | |||
import sqlalchemy as sa | |||
# revision identifiers, used by Alembic. | |||
revision: str = '95369c9d99cc' | |||
down_revision: Union[str, None] = 'f272ebbba83d' | |||
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! ### | |||
pass | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
pass | |||
# ### end Alembic commands ### |
@@ -1,60 +0,0 @@ | |||
"""create User and Vehicle tables | |||
Revision ID: 9a0214838ac8 | |||
Revises: | |||
Create Date: 2023-09-01 13:31:01.324861 | |||
""" | |||
from typing import Sequence, Union | |||
from alembic import op | |||
import sqlalchemy as sa | |||
# revision identifiers, used by Alembic. | |||
revision: str = '9a0214838ac8' | |||
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_table('users', | |||
sa.Column('Id', sa.Integer(), nullable=False), | |||
sa.Column('Name', sa.String(), nullable=False), | |||
sa.Column('MiddleName', sa.String(), nullable=True), | |||
sa.Column('LastName', sa.String(), nullable=False), | |||
sa.Column('BirthDate', sa.DateTime(), nullable=False), | |||
sa.Column('ContactNumber', sa.String(), nullable=False), | |||
sa.Column('Email', sa.String(), nullable=False), | |||
sa.Column('Role', sa.String(), nullable=False), | |||
sa.Column('DrivingLicenseNumber', sa.String(), nullable=True), | |||
sa.Column('HashedPassword', sa.String(), nullable=False), | |||
sa.PrimaryKeyConstraint('Id') | |||
) | |||
op.create_index(op.f('ix_users_Id'), 'users', ['Id'], unique=False) | |||
op.create_table('vehicles', | |||
sa.Column('Id', sa.Integer(), nullable=False), | |||
sa.Column('Model', sa.String(), nullable=False), | |||
sa.Column('Year', sa.Integer(), nullable=False), | |||
sa.Column('LicensePlate', sa.String(), nullable=False), | |||
sa.Column('Type', sa.String(), nullable=False), | |||
sa.Column('AssignedDriverIds', sa.ARRAY(sa.Integer()), nullable=True), | |||
sa.Column('CurrentLocation', sa.ARRAY(sa.String()), nullable=True), | |||
sa.Column('Fuel', sa.Integer(), nullable=False), | |||
sa.Column('Mileage', sa.Integer(), nullable=False), | |||
sa.Column('MaintenanceNotes', sa.ARRAY(sa.String()), nullable=True), | |||
sa.PrimaryKeyConstraint('Id') | |||
) | |||
op.create_index(op.f('ix_vehicles_Id'), 'vehicles', ['Id'], unique=False) | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
op.drop_index(op.f('ix_vehicles_Id'), table_name='vehicles') | |||
op.drop_table('vehicles') | |||
op.drop_index(op.f('ix_users_Id'), table_name='users') | |||
op.drop_table('users') | |||
# ### end Alembic commands ### |
@@ -1,62 +0,0 @@ | |||
"""Fix | |||
Revision ID: a92339978636 | |||
Revises: 95369c9d99cc | |||
Create Date: 2023-09-04 16:03:42.207089 | |||
""" | |||
from typing import Sequence, Union | |||
from alembic import op | |||
import sqlalchemy as sa | |||
# revision identifiers, used by Alembic. | |||
revision: str = 'a92339978636' | |||
down_revision: Union[str, None] = '95369c9d99cc' | |||
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_table('vehicle', | |||
sa.Column('Id', sa.Integer(), nullable=False), | |||
sa.Column('Model', sa.String(), nullable=False), | |||
sa.Column('Year', sa.Integer(), nullable=False), | |||
sa.Column('LicensePlate', sa.String(), nullable=False), | |||
sa.Column('CurrentLocation', sa.ARRAY(sa.String()), nullable=True), | |||
sa.Column('Fuel', sa.Integer(), nullable=False), | |||
sa.Column('Mileage', sa.Integer(), nullable=False), | |||
sa.Column('Status', sa.String(), nullable=False), | |||
sa.Column('Capacity', sa.Integer(), nullable=False), | |||
sa.Column('MaintenanceNotes', sa.ARRAY(sa.String()), nullable=True), | |||
sa.PrimaryKeyConstraint('Id') | |||
) | |||
op.create_index(op.f('ix_vehicle_Id'), 'vehicle', ['Id'], unique=False) | |||
op.create_table('user', | |||
sa.Column('Id', sa.Integer(), nullable=False), | |||
sa.Column('Name', sa.String(), nullable=False), | |||
sa.Column('MiddleName', sa.String(), nullable=True), | |||
sa.Column('LastName', sa.String(), nullable=False), | |||
sa.Column('BirthDate', sa.DateTime(), nullable=False), | |||
sa.Column('ContactNumber', sa.String(), nullable=False), | |||
sa.Column('Email', sa.String(), nullable=False), | |||
sa.Column('Role', sa.String(), nullable=False), | |||
sa.Column('DrivingLicenseNumber', sa.String(), nullable=True), | |||
sa.Column('AssignedVehicle', sa.Integer(), nullable=True), | |||
sa.Column('HashedPassword', sa.String(), nullable=False), | |||
sa.ForeignKeyConstraint(['AssignedVehicle'], ['vehicle.Id'], ), | |||
sa.PrimaryKeyConstraint('Id') | |||
) | |||
op.create_index(op.f('ix_user_Id'), 'user', ['Id'], unique=False) | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
op.drop_index(op.f('ix_user_Id'), table_name='user') | |||
op.drop_table('user') | |||
op.drop_index(op.f('ix_vehicle_Id'), table_name='vehicle') | |||
op.drop_table('vehicle') | |||
# ### end Alembic commands ### |
@@ -1,60 +0,0 @@ | |||
"""Edit vehicle table, fix due to SRS | |||
Revision ID: aa72d2118245 | |||
Revises: 9a0214838ac8 | |||
Create Date: 2023-09-04 15:16:55.278355 | |||
""" | |||
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 = 'aa72d2118245' | |||
down_revision: Union[str, None] = '9a0214838ac8' | |||
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.drop_index('ix_vehicles_Id', table_name='vehicles') | |||
op.drop_table('vehicles') | |||
op.drop_index('ix_users_Id', table_name='users') | |||
op.drop_table('users') | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
op.create_table('users', | |||
sa.Column('Id', sa.INTEGER(), server_default=sa.text('nextval(\'"users_Id_seq"\'::regclass)'), autoincrement=True, nullable=False), | |||
sa.Column('Name', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('MiddleName', sa.VARCHAR(), autoincrement=False, nullable=True), | |||
sa.Column('LastName', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('BirthDate', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), | |||
sa.Column('ContactNumber', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Email', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Role', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('DrivingLicenseNumber', sa.VARCHAR(), autoincrement=False, nullable=True), | |||
sa.Column('HashedPassword', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.PrimaryKeyConstraint('Id', name='users_pkey') | |||
) | |||
op.create_index('ix_users_Id', 'users', ['Id'], unique=False) | |||
op.create_table('vehicles', | |||
sa.Column('Id', sa.INTEGER(), server_default=sa.text('nextval(\'"vehicles_Id_seq"\'::regclass)'), autoincrement=True, nullable=False), | |||
sa.Column('Model', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Year', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('LicensePlate', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Type', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('AssignedDriverIds', postgresql.ARRAY(sa.INTEGER()), autoincrement=False, nullable=True), | |||
sa.Column('CurrentLocation', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True), | |||
sa.Column('Fuel', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('Mileage', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('MaintenanceNotes', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True), | |||
sa.PrimaryKeyConstraint('Id', name='vehicles_pkey') | |||
) | |||
op.create_index('ix_vehicles_Id', 'vehicles', ['Id'], unique=False) | |||
# ### end Alembic commands ### |
@@ -1,61 +0,0 @@ | |||
"""Edit driver assignment | |||
Revision ID: f272ebbba83d | |||
Revises: 47f450cb5e82 | |||
Create Date: 2023-09-04 15:36:52.916595 | |||
""" | |||
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 = 'f272ebbba83d' | |||
down_revision: Union[str, None] = '47f450cb5e82' | |||
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.drop_index('ix_vehicles_Id', table_name='vehicles') | |||
op.drop_table('vehicles') | |||
op.drop_index('ix_users_Id', table_name='users') | |||
op.drop_table('users') | |||
# ### end Alembic commands ### | |||
def downgrade() -> None: | |||
# ### commands auto generated by Alembic - please adjust! ### | |||
op.create_table('users', | |||
sa.Column('Id', sa.INTEGER(), server_default=sa.text('nextval(\'"users_Id_seq"\'::regclass)'), autoincrement=True, nullable=False), | |||
sa.Column('Name', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('MiddleName', sa.VARCHAR(), autoincrement=False, nullable=True), | |||
sa.Column('LastName', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('BirthDate', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), | |||
sa.Column('ContactNumber', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Email', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Role', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('DrivingLicenseNumber', sa.VARCHAR(), autoincrement=False, nullable=True), | |||
sa.Column('HashedPassword', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.PrimaryKeyConstraint('Id', name='users_pkey') | |||
) | |||
op.create_index('ix_users_Id', 'users', ['Id'], unique=False) | |||
op.create_table('vehicles', | |||
sa.Column('Id', sa.INTEGER(), server_default=sa.text('nextval(\'"vehicles_Id_seq"\'::regclass)'), autoincrement=True, nullable=False), | |||
sa.Column('Model', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Year', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('LicensePlate', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('AssignedDriverIds', postgresql.ARRAY(sa.INTEGER()), autoincrement=False, nullable=True), | |||
sa.Column('CurrentLocation', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True), | |||
sa.Column('Fuel', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('Mileage', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('Status', sa.VARCHAR(), autoincrement=False, nullable=False), | |||
sa.Column('Capacity', sa.INTEGER(), autoincrement=False, nullable=False), | |||
sa.Column('MaintenanceNotes', postgresql.ARRAY(sa.VARCHAR()), autoincrement=False, nullable=True), | |||
sa.PrimaryKeyConstraint('Id', name='vehicles_pkey') | |||
) | |||
op.create_index('ix_vehicles_Id', 'vehicles', ['Id'], unique=False) | |||
# ### end Alembic commands ### |
@@ -58,3 +58,5 @@ def access_token(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = | |||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid username or password") | |||
access_token = create_access_token(data={"sub": user.Email}) | |||
return {"access_token": access_token, "token_type": "bearer"} | |||
@@ -14,3 +14,4 @@ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): | |||
to_encode.update({"exp": expire}) | |||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) | |||
return encoded_jwt | |||
@@ -1,3 +1,5 @@ | |||
class Settings: | |||
PROJECT_NAME: str = "VMS" | |||
PROJECT_VERSION: str = "1.0.0" | |||
@@ -13,3 +15,24 @@ class Settings: | |||
settings = Settings() | |||
def createAdminAcc(): | |||
from db.session import SessionLocal | |||
from db.repository.user import create_new_user | |||
from schemas.user import UserCreate | |||
from core.hashing import Hasher | |||
from db.models.user import User | |||
db = SessionLocal() | |||
user = UserCreate( | |||
Email="madi.turgunov@nu.edu.kz", | |||
Password="1234567", | |||
Name="Madi", | |||
LastName="Turgunov", | |||
ContactNumber="+77071234567", | |||
Role="Admin", | |||
BirthDate="2000-01-01T00:00:00+06:00") | |||
if (db.query(User).filter(User.Email == user.Email).first()): | |||
return False | |||
create_new_user(user=user, db=db) | |||
return True |
@@ -1,5 +1,5 @@ | |||
from fastapi import FastAPI | |||
from core.config import settings | |||
from core.config import settings, createAdminAcc | |||
from db.session import engine | |||
from db.base import Base | |||
from apis.base import api_router | |||
@@ -12,6 +12,7 @@ def include_routes(app): # include all routes from our api/v1/ | |||
def startup(): # start the project, and create the tables | |||
app = FastAPI(title=settings.PROJECT_NAME, version=settings.PROJECT_VERSION) | |||
Base.metadata.create_all(bind=engine) | |||
createAdminAcc() | |||
include_routes(app) | |||
return app | |||