diff --git a/.gitignore b/.gitignore index 2077560..b0d6771 100644 --- a/.gitignore +++ b/.gitignore @@ -144,6 +144,7 @@ data/trash/ data/gtfs/ data/grfs data/tmp +data/agencyconf/** #these files are under app/static but they get copied to the outside directory on startup logging.conf diff --git a/amarillo/models/AgencyConf.py b/amarillo/models/AgencyConf.py index 29ac2f5..9a6af77 100644 --- a/amarillo/models/AgencyConf.py +++ b/amarillo/models/AgencyConf.py @@ -15,12 +15,18 @@ class AgencyConf(BaseModel): max_length=256, pattern=r'^[a-zA-Z0-9]+$', examples=["d8yLuY4DqMEUCLcfJASi"]) + password: str = Field( + description="The agency's password for generating JWT tokens", + min_length=8, + max_length=256, + examples=["$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"]) model_config = ConfigDict(json_schema_extra={ "title": "Agency Configuration", "description": "Configuration for an agency.", "example": { "agency_id": "mfdz", - "api_key": "d8yLuY4DqMEUCLcfJASi" + "api_key": "d8yLuY4DqMEUCLcfJASi", + "password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW" } }) diff --git a/amarillo/services/agencyconf.py b/amarillo/services/agencyconf.py index 30431dc..88ec94e 100644 --- a/amarillo/services/agencyconf.py +++ b/amarillo/services/agencyconf.py @@ -8,6 +8,7 @@ from fastapi import HTTPException, status from amarillo.models.AgencyConf import AgencyConf from amarillo.services.config import config +from amarillo.services.passwords import get_password_hash logger = logging.getLogger(__name__) @@ -85,6 +86,8 @@ class AgencyConfService: logger.error(message) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=message) + agency_conf.password = get_password_hash(agency_conf.password) + with open(f'{agency_conf_directory}/{agency_id}.json', 'w', encoding='utf-8') as f: f.write(agency_conf.json()) diff --git a/amarillo/services/oauth2.py b/amarillo/services/oauth2.py index 214870c..6134db0 100644 --- a/amarillo/services/oauth2.py +++ b/amarillo/services/oauth2.py @@ -7,9 +7,9 @@ import logging from fastapi import Depends, HTTPException, Header, status, APIRouter from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import JWTError, jwt -from passlib.context import CryptContext from pydantic import BaseModel from amarillo.routers.agencyconf import verify_api_key +from amarillo.services.passwords import verify_password from amarillo.services.config import config @@ -60,21 +60,11 @@ class User(BaseModel): class UserInDB(User): hashed_password: str - -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") - oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", auto_error=False) async def verify_optional_api_key(X_API_Key: Optional[str] = Header(None)): if X_API_Key == None: return None return await verify_api_key(X_API_Key) -def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) - - -def get_password_hash(password): - return pwd_context.hash(password) - def get_agency(db, agency_id: str): if agency_id in db: user_dict = db[agency_id] diff --git a/amarillo/services/passwords.py b/amarillo/services/passwords.py new file mode 100644 index 0000000..fa010dc --- /dev/null +++ b/amarillo/services/passwords.py @@ -0,0 +1,10 @@ +from passlib.context import CryptContext + +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + +def verify_password(plain_password, hashed_password): + return pwd_context.verify(plain_password, hashed_password) + + +def get_password_hash(password): + return pwd_context.hash(password) \ No newline at end of file