various bugs fixing

This commit is contained in:
GotthardG 2024-12-06 14:53:27 +01:00
parent 996fc66d76
commit 29a9d16bc3
10 changed files with 123 additions and 87 deletions

View File

@ -1,6 +1,6 @@
import logging
from sqlalchemy.orm import Session, joinedload
from app.models import Shipment
from .models import Shipment
def get_shipments(db: Session):
logging.info("Fetching all shipments from the database.")

View File

@ -3,7 +3,7 @@ from sqlalchemy.orm import Session
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from app import models
from . import models
import os
# Get username and password from environment variables
@ -31,12 +31,12 @@ def get_db():
def init_db():
# Import models inside function to avoid circular dependency
from app import models
from . import models
Base.metadata.create_all(bind=engine)
def load_sample_data(session: Session):
# Import models inside function to avoid circular dependency
from app.data import contacts, return_addresses, dewars, proposals, shipments, pucks, samples, dewar_types, serial_numbers, slots, sample_events
from .data import contacts, return_addresses, dewars, proposals, shipments, pucks, samples, dewar_types, serial_numbers, slots, sample_events
# If any data already exists, skip seeding
if session.query(models.ContactPerson).first():

View File

@ -1,5 +1,5 @@
# app/dependencies.py
from app.database import SessionLocal # Import SessionLocal from database.py
from .database import SessionLocal # Import SessionLocal from database.py
def get_db():
db = SessionLocal()

View File

@ -1,4 +1,4 @@
from app.database import init_db
from .database import init_db
def initialize_database():

View File

@ -1,6 +1,6 @@
from sqlalchemy import Column, Integer, String, Date, ForeignKey, JSON, Interval, DateTime, Boolean
from sqlalchemy.orm import relationship
from app.database import Base
from .database import Base
from datetime import datetime, timedelta
import uuid

View File

@ -191,84 +191,84 @@ class SpreadsheetModel(BaseModel):
raise ValueError(f" '{v}' is not valid. Value must be one of {allowed}.")
return v
@field_validator('spacegroupnumber', mode="before")
@classmethod
def spacegroupnumber_allowed(cls, v):
if v is not None:
try:
v = int(v)
if not (1 <= v <= 230):
raise ValueError(f" '{v}' is not valid. Value must be an integer between 1 and 230.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be an integer between 1 and 230.") from e
return v
@field_validator('spacegroupnumber', mode="before")
@classmethod
def spacegroupnumber_allowed(cls, v):
if v is not None:
try:
v = int(v)
if not (1 <= v <= 230):
raise ValueError(f" '{v}' is not valid. Value must be an integer between 1 and 230.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be an integer between 1 and 230.") from e
return v
@field_validator('cellparameters', mode="before")
@classmethod
def cellparameters_format(cls, v):
if v:
values = [float(i) for i in v.split(",")]
if len(values) != 6 or any(val <= 0 for val in values):
raise ValueError(f" '{v}' is not valid. Value must be a set of six positive floats or integers.")
return v
@field_validator('cellparameters', mode="before")
@classmethod
def cellparameters_format(cls, v):
if v:
values = [float(i) for i in v.split(",")]
if len(values) != 6 or any(val <= 0 for val in values):
raise ValueError(f" '{v}' is not valid. Value must be a set of six positive floats or integers.")
return v
@field_validator('rescutkey', 'rescutvalue', mode="before")
@classmethod
def rescutkey_value_pair(cls, values):
rescutkey = values.get('rescutkey')
rescutvalue = values.get('rescutvalue')
if rescutkey and rescutvalue:
if rescutkey not in {"is", "cchalf"}:
raise ValueError("Rescutkey must be either 'is' or 'cchalf'")
if not isinstance(rescutvalue, float) or rescutvalue <= 0:
raise ValueError("Rescutvalue must be a positive float if rescutkey is provided")
return values
@field_validator('rescutkey', 'rescutvalue', mode="before")
@classmethod
def rescutkey_value_pair(cls, values):
rescutkey = values.get('rescutkey')
rescutvalue = values.get('rescutvalue')
if rescutkey and rescutvalue:
if rescutkey not in {"is", "cchalf"}:
raise ValueError("Rescutkey must be either 'is' or 'cchalf'")
if not isinstance(rescutvalue, float) or rescutvalue <= 0:
raise ValueError("Rescutvalue must be a positive float if rescutkey is provided")
return values
@field_validator('trustedhigh', mode="before")
@classmethod
def trustedhigh_allowed(cls, v):
if v is not None:
try:
v = float(v)
if not (0 <= v <= 2.0):
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 2.0.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 2.0.") from e
return v
@field_validator('trustedhigh', mode="before")
@classmethod
def trustedhigh_allowed(cls, v):
if v is not None:
try:
v = float(v)
if not (0 <= v <= 2.0):
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 2.0.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 2.0.") from e
return v
@field_validator('chiphiangles', mode="before")
@classmethod
def chiphiangles_allowed(cls, v):
if v is not None:
try:
v = float(v)
if not (0 <= v <= 30):
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 30.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 30.") from e
return v
@field_validator('chiphiangles', mode="before")
@classmethod
def chiphiangles_allowed(cls, v):
if v is not None:
try:
v = float(v)
if not (0 <= v <= 30):
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 30.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a float between 0 and 30.") from e
return v
@field_validator('dose', mode="before")
@classmethod
def dose_positive(cls, v):
if v is not None:
try:
v = float(v)
if v <= 0:
raise ValueError(f" '{v}' is not valid. Value must be a positive float.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a positive float.") from e
return v
@field_validator('dose', mode="before")
@classmethod
def dose_positive(cls, v):
if v is not None:
try:
v = float(v)
if v <= 0:
raise ValueError(f" '{v}' is not valid. Value must be a positive float.")
except (ValueError, TypeError) as e:
raise ValueError(f" '{v}' is not valid. Value must be a positive float.") from e
return v
class TELLModel(SpreadsheetModel):
input_order: int
samplemountcount: int = 0
samplestatus: str = "not present"
puckaddress: str = "---"
username: str
puck_number: int
prefix: Optional[str]
folder: Optional[str]
class TELLModel(SpreadsheetModel):
input_order: int
samplemountcount: int = 0
samplestatus: str = "not present"
puckaddress: str = "---"
username: str
puck_number: int
prefix: Optional[str]
folder: Optional[str]
class SpreadsheetResponse(BaseModel):
data: List[SpreadsheetModel] # Validated data rows as SpreadsheetModel instances

View File

@ -4,16 +4,31 @@ from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app import ssl_heidi
from pathlib import Path
import os
import json
from app.routers import address, contact, proposal, dewar, shipment, puck, spreadsheet, logistics, auth, sample
from app.database import Base, engine, SessionLocal, load_sample_data
app = FastAPI()
# Generate SSL Key and Certificate if not exist
Path("ssl").mkdir(parents=True, exist_ok=True)
if not Path("ssl/cert.pem").exists() or not Path("ssl/key.pem").exists():
ssl_heidi.generate_self_signed_cert("ssl/cert.pem", "ssl/key.pem")
# Determine environment and configuration file path
environment = os.getenv('ENVIRONMENT', 'dev')
config_file = Path(__file__).resolve().parent.parent / f'config_{environment}.json'
# Load configuration
with open(config_file) as f:
config = json.load(f)
cert_path = config['ssl_cert_path']
key_path = config['ssl_key_path']
# Generate SSL Key and Certificate if not exist (only for development)
if environment == 'development':
Path("ssl").mkdir(parents=True, exist_ok=True)
if not Path(cert_path).exists() or not Path(key_path).exists():
ssl_heidi.generate_self_signed_cert(cert_path, key_path)
# Apply CORS middleware
app.add_middleware(
@ -52,7 +67,20 @@ app.include_router(sample.router, prefix="/samples", tags=["samples"])
if __name__ == "__main__":
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(certfile="ssl/cert.pem", keyfile="ssl/key.pem")
import uvicorn
import os
uvicorn.run(app, host="127.0.0.1", port=8000, log_level="debug", ssl_context=ssl_context)
# Get environment from an environment variable
environment = os.getenv('ENVIRONMENT', 'dev')
# Paths for SSL certificates
cert_path = "ssl/cert.pem"
key_path = "ssl/key.pem"
if environment == 'testing':
cert_path = "ssl/mx-aare-test.psi.ch.pem"
key_path = "ssl/mx-aare-test.psi.ch.key"
# Run the application with appropriate SSL setup
uvicorn.run(app, host="127.0.0.1", port=8000, log_level="debug",
ssl_keyfile=key_path, ssl_certfile=cert_path)

View File

@ -110,7 +110,7 @@ contacts = [
# Example data for return addresses
return_addresses = [
Address(id=1, street='123 Hobbiton St', city='Shire', zipcode='12345', country='Middle Earth'),
Address(id=2, street='456 Rohan Rd', city='Edoras', zipcode='67890', country='Middle Earth')
Address(id=2, street='456 Rohan Rd', city='Edoras', zipcode='67890', country='Middle Earth'),
Address(id=3, street='789 Greenwood Dr', city='Mirkwood', zipcode='13579', country='Middle Earth'),
Address(id=4, street='321 Gondor Ave', city='Minas Tirith', zipcode='24680', country='Middle Earth'),
Address(id=5, street='654 Falgorn Pass', city='Rivendell', zipcode='11223', country='Middle Earth')

4
config_dev.json Normal file
View File

@ -0,0 +1,4 @@
{
"ssl_cert_path": "ssl/cert.pem",
"ssl_key_path": "ssl/key.pem"
}

4
config_test.json Normal file
View File

@ -0,0 +1,4 @@
{
"ssl_cert_path": "ssl/mx-aare-test.psi.ch.pem",
"ssl_key_path": "ss/mx-aare-test.psi.ch.key"
}