Created basic backend structure, auth and CRUD endpoints.

This commit is contained in:
2025-02-22 13:42:10 +03:00
parent ed5fac3432
commit cabcf837f9
14 changed files with 470 additions and 3 deletions

40
core/dependencies.py Normal file
View File

@@ -0,0 +1,40 @@
# dependencies.py
from fastapi import Depends, HTTPException, status, Security
from fastapi.security import APIKeyHeader
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from data.db import SessionLocal
from data.models import User, UserRole
from pydantic import BaseModel
# class UserInDB(User):
# hashed_password: str
async def get_db():
async with SessionLocal() as session:
yield session
API_KEY_NAME = "Authorization"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
async def get_current_user(db: AsyncSession = Depends(get_db), api_key:str = Security(api_key_header)):
if api_key_header is None:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="API key missing"
)
if not api_key:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="API key missing, provide it in the header value [Authorization]"
)
user = await db.execute(select(User).filter(User.api_key == api_key))
user = user.scalars().first()
if user is None:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
return user
async def get_admin_user(current_user: User = Depends(get_current_user)):
if current_user.role != UserRole.admin:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions")
return current_user

9
core/enums.py Normal file
View File

@@ -0,0 +1,9 @@
import enum
class ConnectionTypes(str, enum.Enum):
mysql = "mysql"
postgresql = 'postgresql'
class UserRole(enum.Enum):
admin = "admin"
user = "user"

19
core/exceptions.py Normal file
View File

@@ -0,0 +1,19 @@
from fastapi import HTTPException
class ObjectNotFoundInDB(Exception):
def __init__(self, *args):
super().__init__(*args)
class UserNotFound(HTTPException):
def __init__(
self,
status_code=404,
detail={
"message": "Didn't find a user with the provided id.",
"code": "user-not-found",
},
headers=None,
):
super().__init__(status_code, detail, headers)

44
core/scripts.py Normal file
View File

@@ -0,0 +1,44 @@
# add_user.py
import asyncio
import secrets
from sqlalchemy.future import select
from sqlalchemy.exc import IntegrityError
from getpass import getpass
from data.db import engine, SessionLocal
from data.models import Base, User, UserRole
def create_secret():
return secrets.token_hex(32)
async def create_user():
async with SessionLocal() as session:
username = input("Enter username: ").strip()
role_input = input("Enter role (admin/user): ").strip().lower()
print('\n')
if role_input not in UserRole._value2member_map_:
print("> Invalid role. Please enter 'admin' or 'user'.")
return
role = UserRole(role_input)
# Check if username already exists
result = await session.execute(select(User).filter_by(username=username))
existing_user = result.scalars().first()
if existing_user:
print(f"> Username '{username}' is already taken.")
return
# Create new user
api_key = create_secret()
new_user = User(username=username, role=role, api_key=api_key)
session.add(new_user)
await session.commit()
await session.refresh(new_user)
print(f"> User '{username}' with role '{role.value}' created successfully.")
print(f"> API Key: {api_key}")
if __name__ == "__main__":
asyncio.run(create_user())