uam update
This commit is contained in:
parent
bf986b4d71
commit
1261e54509
3 changed files with 104 additions and 130 deletions
|
|
@ -154,14 +154,40 @@ class DatabaseConnector:
|
|||
|
||||
path = self._getTablePath(table)
|
||||
try:
|
||||
# Log the path and data being saved
|
||||
logger.debug(f"Attempting to save table {table} to {path}")
|
||||
logger.debug(f"Data to save: {json.dumps(data, indent=2)}")
|
||||
|
||||
# Check if directory exists and is writable
|
||||
dir_path = os.path.dirname(path)
|
||||
if not os.path.exists(dir_path):
|
||||
logger.error(f"Directory does not exist: {dir_path}")
|
||||
return False
|
||||
if not os.access(dir_path, os.W_OK):
|
||||
logger.error(f"Directory is not writable: {dir_path}")
|
||||
return False
|
||||
|
||||
# Check if file exists and is writable
|
||||
if os.path.exists(path) and not os.access(path, os.W_OK):
|
||||
logger.error(f"File exists but is not writable: {path}")
|
||||
return False
|
||||
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
# Verify the file was written correctly
|
||||
if not os.path.exists(path):
|
||||
logger.error(f"File was not created after write: {path}")
|
||||
return False
|
||||
|
||||
# Update the cache
|
||||
self._tablesCache[table] = data
|
||||
logger.debug(f"Successfully saved table {table}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving table {table}: {e}")
|
||||
logger.error(f"Error saving table {table}: {str(e)}")
|
||||
logger.error(f"Error type: {type(e).__name__}")
|
||||
logger.error(f"Error details: {e.__dict__ if hasattr(e, '__dict__') else 'No details available'}")
|
||||
return False
|
||||
|
||||
def _applyRecordFilter(self, records: List[Dict[str, Any]], recordFilter: Dict[str, Any] = None) -> List[Dict[str, Any]]:
|
||||
|
|
|
|||
|
|
@ -279,8 +279,10 @@ class GatewayInterface:
|
|||
users = self.db.getRecordset("users")
|
||||
for user in users:
|
||||
if user.get("username") == username:
|
||||
# Return a copy of the user with all fields, including hashedPassword
|
||||
return user.copy()
|
||||
# Log the fields present in the user record
|
||||
logger.debug(f"Found user {username} with fields: {list(user.keys())}")
|
||||
# Return a complete copy of the user record with all fields
|
||||
return {**user} # Use dict unpacking to ensure we get a complete copy with all fields
|
||||
logger.debug(f"No user found with username {username}")
|
||||
return None
|
||||
|
||||
|
|
@ -341,10 +343,7 @@ class GatewayInterface:
|
|||
|
||||
createdUser = self.db.recordCreate("users", userData)
|
||||
|
||||
# Remove password hash from the response
|
||||
if "hashedPassword" in createdUser:
|
||||
del createdUser["hashedPassword"]
|
||||
|
||||
# Return the complete user record
|
||||
return createdUser
|
||||
|
||||
def authenticateUser(self, username: str, password: str) -> Optional[Dict[str, Any]]:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
from fastapi import APIRouter, HTTPException, Depends, Body, Path
|
||||
from fastapi import APIRouter, HTTPException, Depends, Body, Path, Request
|
||||
from typing import List, Dict, Any, Optional
|
||||
from fastapi import status
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import time
|
||||
import traceback
|
||||
|
||||
# Import auth module
|
||||
from modules.auth import getCurrentActiveUser, getUserContext
|
||||
|
|
@ -11,6 +14,9 @@ from modules.auth import getCurrentActiveUser, getUserContext
|
|||
from modules.gatewayInterface import getGatewayInterface
|
||||
from modules.gatewayModel import User
|
||||
|
||||
# Set up logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Determine all attributes of the model
|
||||
def getModelAttributes(modelClass):
|
||||
return [attr for attr in dir(modelClass)
|
||||
|
|
@ -66,145 +72,88 @@ async def getUsers(currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)):
|
|||
|
||||
|
||||
@router.post("/register", response_model=Dict[str, Any])
|
||||
async def registerUser(userData: dict = Body(...)):
|
||||
"""Register a new user"""
|
||||
# Add debug logging to see what's coming in
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"Registration request data: {userData}")
|
||||
|
||||
# Get the initial IDs for mandate and admin user
|
||||
adminGateway = getGatewayInterface()
|
||||
|
||||
# Get ID of the root mandate - we'll use this for new users
|
||||
rootMandateId = adminGateway.getInitialId("mandates")
|
||||
adminUserId = adminGateway.getInitialId("users")
|
||||
|
||||
logger.info(f"Root mandate ID: {rootMandateId}, Admin user ID: {adminUserId}")
|
||||
|
||||
if not rootMandateId or not adminUserId:
|
||||
logger.error("System initialization error: Missing root mandate or admin user")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="System is not properly initialized with root mandate and admin user"
|
||||
)
|
||||
|
||||
# Use a gateway with admin context for user creation
|
||||
gateway = getGatewayInterface(rootMandateId, adminUserId)
|
||||
|
||||
if "username" not in userData or "password" not in userData:
|
||||
logger.error("Missing required fields in registration data")
|
||||
raise HTTPException(status_code=400, detail="Username and password required")
|
||||
|
||||
async def registerUser(request: Request):
|
||||
"""Register a new user."""
|
||||
try:
|
||||
# Create user data - explicitly set fields
|
||||
userCreateData = {
|
||||
"username": userData["username"],
|
||||
"password": userData["password"],
|
||||
"mandateId": rootMandateId, # Use the Root mandate
|
||||
# Get request data
|
||||
data = await request.json()
|
||||
logger.info(f"Registration request data: {data}")
|
||||
|
||||
# Get root mandate and admin user IDs
|
||||
rootMandateId = 1 # Root mandate is always ID 1
|
||||
adminUserId = 1 # Admin user is always ID 1
|
||||
|
||||
# Create a new gateway interface instance with admin context
|
||||
adminGateway = getGatewayInterface(rootMandateId, adminUserId)
|
||||
|
||||
# Check required fields
|
||||
if not data.get("username") or not data.get("password"):
|
||||
logger.error("Missing required fields in registration request")
|
||||
raise HTTPException(status_code=400, detail="Username and password are required")
|
||||
|
||||
# Create user data
|
||||
userData = {
|
||||
"username": data["username"],
|
||||
"password": data["password"],
|
||||
"email": data.get("email"),
|
||||
"fullName": data.get("fullName"),
|
||||
"language": data.get("language", "de"),
|
||||
"mandateId": rootMandateId,
|
||||
"disabled": False,
|
||||
"privilege": "user",
|
||||
"language": userData.get("language", "de")
|
||||
"privilege": "user"
|
||||
}
|
||||
|
||||
# Explicitly add optional fields - only if they exist and are not empty
|
||||
if "email" in userData and userData["email"]:
|
||||
userCreateData["email"] = userData["email"]
|
||||
|
||||
if "fullName" in userData and userData["fullName"]:
|
||||
userCreateData["fullName"] = userData["fullName"]
|
||||
|
||||
logger.info(f"Attempting to create user with data: {userCreateData}")
|
||||
|
||||
# First check if user already exists
|
||||
existingUser = gateway.getUserByUsername(userData["username"])
|
||||
if existingUser:
|
||||
logger.error(f"User {userData['username']} already exists")
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"User {userData['username']} already exists"
|
||||
)
|
||||
|
||||
# Create the user
|
||||
newUser = gateway.createUser(**userCreateData)
|
||||
logger.info(f"User created successfully: {newUser}")
|
||||
logger.info(f"Attempting to create user with data: {userData}")
|
||||
createdUser = adminGateway.createUser(**userData)
|
||||
logger.info(f"User created successfully: {createdUser}")
|
||||
|
||||
# Wait a short moment to ensure database consistency
|
||||
import time
|
||||
# Add a small delay to ensure database consistency
|
||||
time.sleep(0.5)
|
||||
|
||||
# Verify that the password was properly stored
|
||||
createdUser = gateway.getUserByUsername(userData["username"])
|
||||
logger.info(f"Retrieved created user: {createdUser}")
|
||||
|
||||
if not createdUser:
|
||||
logger.error("User creation verification failed: User not found after creation")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to verify user creation. Please try again."
|
||||
)
|
||||
|
||||
# Verify the user was created and password was stored
|
||||
if "hashedPassword" not in createdUser:
|
||||
logger.error("User creation verification failed: Password not stored")
|
||||
# If password wasn't stored, delete the user and raise an error
|
||||
if createdUser:
|
||||
logger.info(f"Attempting to delete user {createdUser['id']} due to missing password")
|
||||
try:
|
||||
gateway.deleteUser(createdUser["id"])
|
||||
logger.info(f"Successfully deleted user {createdUser['id']} after password storage failure")
|
||||
except Exception as deleteError:
|
||||
logger.error(f"Failed to delete user after password storage failure: {str(deleteError)}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to store password securely. Please try again."
|
||||
)
|
||||
logger.error("Password not stored in user record")
|
||||
# Try to delete the user
|
||||
try:
|
||||
adminGateway.deleteUser(createdUser["id"])
|
||||
logger.info("Successfully deleted user after password storage failure")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete user after password storage failure: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail="Password storage failed")
|
||||
|
||||
# Final verification - try to authenticate the user
|
||||
try:
|
||||
authResult = gateway.authenticateUser(userData["username"], userData["password"])
|
||||
if not authResult:
|
||||
logger.error("Final verification failed: Could not authenticate newly created user")
|
||||
# Delete the user if authentication fails
|
||||
if createdUser:
|
||||
try:
|
||||
gateway.deleteUser(createdUser["id"])
|
||||
logger.info(f"Successfully deleted user {createdUser['id']} after authentication failure")
|
||||
except Exception as deleteError:
|
||||
logger.error(f"Failed to delete user after authentication failure: {str(deleteError)}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to verify user authentication. Please try again."
|
||||
)
|
||||
except Exception as authError:
|
||||
logger.error(f"Authentication verification failed: {str(authError)}")
|
||||
# Delete the user if authentication fails
|
||||
if createdUser:
|
||||
try:
|
||||
gateway.deleteUser(createdUser["id"])
|
||||
logger.info(f"Successfully deleted user {createdUser['id']} after authentication error")
|
||||
except Exception as deleteError:
|
||||
logger.error(f"Failed to delete user after authentication error: {str(deleteError)}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to verify user authentication. Please try again."
|
||||
)
|
||||
logger.info("User verification successful")
|
||||
|
||||
# Test authentication
|
||||
authResult = adminGateway.authenticateUser(userData["username"], userData["password"])
|
||||
if not authResult:
|
||||
logger.error("Authentication test failed after user creation")
|
||||
# Try to delete the user
|
||||
try:
|
||||
# adminGateway.deleteUser(createdUser["id"])
|
||||
logger.info("Successfully NOT deleted user after authentication test failure")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete user after authentication test failure: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail="Authentication test failed")
|
||||
|
||||
logger.info("User registration completed successfully")
|
||||
return newUser
|
||||
logger.info("Authentication test successful")
|
||||
|
||||
# Return success response
|
||||
return {
|
||||
"message": "User registered successfully",
|
||||
"userId": createdUser["id"]
|
||||
}
|
||||
|
||||
except ValueError as e:
|
||||
logger.error(f"ValueError in registration: {str(e)}")
|
||||
logger.error(f"Validation error during registration: {str(e)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except PermissionError as e:
|
||||
logger.error(f"PermissionError in registration: {str(e)}")
|
||||
logger.error(f"Permission error during registration: {str(e)}")
|
||||
raise HTTPException(status_code=403, detail=str(e))
|
||||
except Exception as e:
|
||||
import traceback
|
||||
logger.error(f"Unexpected error in registration: {str(e)}")
|
||||
logger.error("Full traceback:")
|
||||
logger.error(f"Unexpected error during registration: {str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error(f"Error type: {type(e).__name__}")
|
||||
logger.error(f"Error args: {e.args}")
|
||||
raise HTTPException(status_code=500, detail=f"Registration failed: {str(e)}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
@router.post("/register-with-msal", response_model=Dict[str, Any])
|
||||
async def registerUserWithMsal(userData: dict = Body(...)):
|
||||
|
|
|
|||
Loading…
Reference in a new issue