Add development-only user simulation using local file

This change introduces a fallback mechanism for development environments, allowing authentication to simulate a user from a local file named "user" when not found in the mock database. The file must include a username on the first line and a space-delimited list of pgroups on the second line. This enhancement helps streamline development workflows while maintaining error handling for missing or malformed files.
This commit is contained in:
GotthardG 2025-02-27 10:45:16 +01:00
parent 7a9cc24e05
commit 2f5cb3032a

View File

@ -77,19 +77,20 @@ async def get_current_user(token: str = Depends(oauth2_scheme)) -> loginData:
@router.post("/token/login", response_model=loginToken) @router.post("/token/login", response_model=loginToken)
async def login(form_data: OAuth2PasswordRequestForm = Depends()): async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# Attempt to find the user in the normal DB
user = mock_users_db.get(form_data.username) user = mock_users_db.get(form_data.username)
if user is None or user["password"] != form_data.password: if user is not None:
raise HTTPException( # Verify password as usual for known users
status_code=status.HTTP_401_UNAUTHORIZED, if user["password"] != form_data.password:
detail="Incorrect username or password", raise HTTPException(
headers={"WWW-Authenticate": "Bearer"}, status_code=status.HTTP_401_UNAUTHORIZED,
) detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
else: else:
# For development only: if the user is not in the mock db, # For development: use the local user file.
# then simulate authentication. # Any password is accepted for the file-based user.
# Read the pgroups from the local file called "user" that lives only on file_path = "user" # Adjust path if your file is somewhere else.
# your machine.
file_path = "user" # Adjust path as needed
if not os.path.exists(file_path): if not os.path.exists(file_path):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@ -100,24 +101,30 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()):
if len(lines) < 2: if len(lines) < 2:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="User file must have at least two lines: " detail="User file must have at least two lines:"
"a username on the first and the list of pgroups on the second", " one for username and one for pgroups",
) )
# The first line of the file is the username
file_username = lines[0].strip() file_username = lines[0].strip()
# The second line is the list of pgroups (space-delimited) # If desired, you can check if the provided username matches the one in
# your file:
if form_data.username != file_username:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Username not found",
headers={"WWW-Authenticate": "Bearer"},
)
# Second line: pgroups are assumed to be space-delimited.
pgroups = lines[1].strip().split() pgroups = lines[1].strip().split()
user = { user = {
"username": file_username, "username": file_username,
"pgroups": pgroups, "pgroups": pgroups,
} }
# Note: Any provided password is accepted for the user defined in the file.
# Create token # Create access token from the user details
access_token = create_access_token( access_token = create_access_token(
data={"sub": user["username"], "pgroups": user["pgroups"]} data={"sub": user["username"], "pgroups": user["pgroups"]}
# data = {"sub": user["username"], "pgroups": user["pgroups"],
# "role": user["role"]}
) )
return loginToken(access_token=access_token, token_type="bearer") return loginToken(access_token=access_token, token_type="bearer")