commit 4dc8435d6f856ddb996fe4b8a3ac88eb54b13025 Author: Nemanja Latkovic Date: Sun Nov 16 14:29:01 2025 +0100 lvl 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1a2308 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.venv +database.db \ No newline at end of file diff --git a/database.py b/database.py new file mode 100644 index 0000000..aa196a9 --- /dev/null +++ b/database.py @@ -0,0 +1,49 @@ +from models import User +from passlib.context import CryptContext +import sqlite3 +import jwt +import datetime + +JWT_SECRET = "secret" + +connection = sqlite3.connect('database.db') +connection.row_factory = sqlite3.Row +cursor = connection.cursor() + +password_context = CryptContext(schemes=["sha256_crypt"], deprecated="auto") + +def init() -> None: + # create users table + cursor.execute(''' + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL UNIQUE, + password TEXT NOT NULL + ) + ''') + +def close() -> None: + connection.close() + + +def register(user: User) -> None: + password = password_context.hash(user.password) + cursor.execute("INSERT INTO users (name, password) VALUES (?, ?)", (user.name, password)) + connection.commit() + +def login(user: User) -> str: + cursor.execute("SELECT id, name, password FROM users WHERE name = ?", (user.name,)) + row = cursor.fetchone() + + if not row: + raise Exception('User not found') + if not password_context.verify(user.password, row["password"]): + raise Exception('Invalid password') + + exp = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=1) + payload = { + "id": row["id"], + "exp": exp + } + + return jwt.encode(payload=payload, key=JWT_SECRET, algorithm="HS256") \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..70c4d17 --- /dev/null +++ b/main.py @@ -0,0 +1,26 @@ +from fastapi import FastAPI +from contextlib import asynccontextmanager +import database +import models + +@asynccontextmanager +async def lifespan(app: FastAPI): + database.init() + yield + database.close() + +app = FastAPI(lifespan=lifespan) + + +@app.get("/") +async def root(): + return {"message": "Hello World"} + +@app.post("/users") +async def register(user: models.User): + database.register(user) + return user + +@app.post("/login") +async def login(user: models.User): + return database.login(user) \ No newline at end of file diff --git a/models.py b/models.py new file mode 100644 index 0000000..8f458c7 --- /dev/null +++ b/models.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + +class User(BaseModel): + name: str + password: str