Enhance license management: allow optional retrieval of license and create new license if none exists
taylorwalton committed
Oct 18, 2025 at 11:26 UTC
72538b3f751984f386ef26be1865a988d5424020
1 file changed
+49
-13
backend/app/middleware/license.py
+49
-13
@@ -388,17 +388,21 @@ async def add_license_to_db(session: AsyncSession, result, request: AddLicenseTo
388
return new_license
389
390
391
-async def get_license(session: AsyncSession) -> License:
391
+async def get_license(session: AsyncSession, raise_on_missing: bool = True) -> Optional[License]:
392
"""
393
Get the license from the database
394
395
:param session: The AsyncSession object for the database
396
- :return: The License object
396
+ :param raise_on_missing: If True, raise HTTPException when no license found. If False, return None.
397
+ :return: The License object or None
398
"""
399
result = await session.execute(select(License))
400
license = result.scalars().first()
401
if license is None:
401
- raise HTTPException(status_code=404, detail="No license found. A license must be created first.")
402
+ if raise_on_missing:
403
+ raise HTTPException(status_code=404, detail="No license found. A license must be created first.")
404
+ else:
405
+ return None
406
else:
407
return license
408
@@ -1045,21 +1049,53 @@ async def get_license_features(session: AsyncSession = Depends(get_db)) -> GetLi
1049
1050
@license_router.post(
1051
"/replace_license_in_db",
1048
- description="Replace a license",
1052
+ description="Replace a license or create one if it doesn't exist",
1053
)
1054
async def replace_license_in_db(request: ReplaceLicenseRequest, session: AsyncSession = Depends(get_db)):
1051
- # ! Remove get_license becasue we don't need to fetch old license
1052
- #license = await get_license(session)
1055
+ # Get license without raising error if it doesn't exist
1056
+ license = await get_license(session, raise_on_missing=False)
1057
1054
- # Invalidate cache for old license
1055
- await invalidate_license_cache(session, license.license_key)
1058
+ if license:
1059
+ # Existing license - replace it
1060
+ logger.info(f"Replacing existing license {license.license_key[:8]}... with {request.license_key[:8]}...")
1061
1057
- # Update license key
1058
- license.license_key = request.license_key
1059
- await session.commit()
1062
+ # Invalidate cache for old license
1063
+ await invalidate_license_cache(session, license.license_key)
1064
+
1065
+ # Update license key
1066
+ license.license_key = request.license_key
1067
+ await session.commit()
1068
+
1069
+ logger.info("License replaced successfully")
1070
+ return {"success": True, "message": "License replaced successfully"}
1071
+ else:
1072
+ # No existing license - create a new one
1073
+ logger.info("No existing license found, creating new license")
1074
+
1075
+ # Verify the new license key first to get customer details
1076
+ results = await send_post_request("verify-license", data={"license_key": request.license_key})
1077
+ normalized_results = normalize_api_response(results)
1078
+
1079
+ if not normalized_results.get("success", True):
1080
+ raise HTTPException(status_code=400, detail="Invalid license key")
1081
+
1082
+ # Extract customer info from license verification
1083
+ license_data = normalized_results["data"]["license"]
1084
+ customer_data = license_data["customer"]
1085
+
1086
+ # Create new license in database
1087
+ await add_license_to_db(
1088
+ session,
1089
+ request.license_key,
1090
+ AddLicenseToDB(
1091
+ customer_email=customer_data["email"],
1092
+ customer_name=customer_data["name"],
1093
+ company_name=customer_data["companyName"],
1094
+ ),
1095
+ )
1096
1061
- logger.info("License replaced successfully")
1062
- return {"success": True, "message": "License replaced successfully"}
1097
+ logger.info("License created successfully")
1098
+ return {"success": True, "message": "License created successfully"}
1099
1100
1101
@license_router.post(