-import os
from datetime import datetime, timedelta
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
-FLATNOTES_USERNAME = os.environ["FLATNOTES_USERNAME"]
-FLATNOTES_PASSWORD = os.environ["FLATNOTES_PASSWORD"]
+from config import config
-JWT_SECRET_KEY = os.environ["FLATNOTES_SECRET_KEY"]
-JWT_EXPIRE_DAYS = int(os.environ.get("FLATNOTES_SESSION_EXPIRY_DAYS", 30))
JWT_ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/token")
def create_access_token(data: dict):
to_encode = data.copy()
- expiry_datetime = datetime.utcnow() + timedelta(days=JWT_EXPIRE_DAYS)
+ expiry_datetime = datetime.utcnow() + timedelta(
+ days=config.session_expiry_days
+ )
to_encode.update({"exp": expiry_datetime})
encoded_jwt = jwt.encode(
- to_encode, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM
+ to_encode, config.session_key, algorithm=JWT_ALGORITHM
)
return encoded_jwt
async def validate_token(token: str = Depends(oauth2_scheme)):
try:
- payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM])
+ payload = jwt.decode(
+ token, config.session_key, algorithms=[JWT_ALGORITHM]
+ )
username = payload.get("sub")
- if username is None or username.lower() != FLATNOTES_USERNAME.lower():
+ if username is None or username.lower() != config.username.lower():
raise ValueError
- return FLATNOTES_USERNAME
+ return config.username
except (JWTError, ValueError):
raise HTTPException(
status_code=401,
--- /dev/null
+import os
+
+
+class Config:
+ def __init__(self) -> None:
+ self.data_path = self.load_data_path()
+
+ self.username = self.load_username()
+ self.password = self.load_password()
+
+ self.session_key = self.load_session_key()
+ self.session_expiry_days = self.load_session_expiry_days()
+
+ def load_data_path(self):
+ return os.environ["FLATNOTES_PATH"]
+
+ def load_username(self):
+ return os.environ["FLATNOTES_USERNAME"]
+
+ def load_password(self):
+ return os.environ["FLATNOTES_PASSWORD"]
+
+ def load_session_key(self):
+ return os.environ["FLATNOTES_SECRET_KEY"]
+
+ def load_session_expiry_days(self):
+ return int(os.environ.get("FLATNOTES_SESSION_EXPIRY_DAYS", 30))
+
+
+config = Config()
import secrets
from typing import List, Literal
-from auth import (
- FLATNOTES_PASSWORD,
- FLATNOTES_USERNAME,
- create_access_token,
- validate_token,
-)
+from fastapi import Depends, FastAPI, HTTPException
+from fastapi.responses import HTMLResponse
+from fastapi.staticfiles import StaticFiles
+
+from auth import create_access_token, validate_token
+from config import config
from error_responses import (
invalid_title_response,
note_not_found_response,
title_exists_response,
)
-from fastapi import Depends, FastAPI, HTTPException
-from fastapi.responses import HTMLResponse
-from fastapi.staticfiles import StaticFiles
-from models import LoginModel, NoteModel, NotePatchModel, SearchResultModel
-
from flatnotes import Flatnotes, InvalidTitleError, Note
+from models import LoginModel, NoteModel, NotePatchModel, SearchResultModel
logging.basicConfig(
format="%(asctime)s [%(levelname)s]: %(message)s",
logger.setLevel(os.environ.get("LOGLEVEL", "INFO").upper())
app = FastAPI()
-flatnotes = Flatnotes(os.environ["FLATNOTES_PATH"])
+flatnotes = Flatnotes(config.data_path)
@app.post("/api/token")
async def token(data: LoginModel):
username_correct = secrets.compare_digest(
- FLATNOTES_USERNAME.lower(), data.username.lower()
- )
- password_correct = secrets.compare_digest(
- FLATNOTES_PASSWORD, data.password
+ config.username.lower(), data.username.lower()
)
+ password_correct = secrets.compare_digest(config.password, data.password)
if not (username_correct and password_correct):
raise HTTPException(
status_code=400, detail="Incorrect username or password"
)
- access_token = create_access_token(data={"sub": FLATNOTES_USERNAME})
+ access_token = create_access_token(data={"sub": config.username})
return {"access_token": access_token, "token_type": "bearer"}