Text Extraction Done, UI Fixes Done, Extracted Template Layout Saved in DB
This commit is contained in:
38
docengine/app/core/aes.py
Normal file
38
docengine/app/core/aes.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import base64
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
|
||||
def decrypt(base64_input: str, secret: bytes) -> str | None:
|
||||
try:
|
||||
combined = base64.b64decode(base64_input)
|
||||
|
||||
# IV length is 12 bytes in the Java implementation
|
||||
iv_length = 12
|
||||
if len(combined) <= iv_length + 16:
|
||||
return None
|
||||
|
||||
iv = combined[:iv_length]
|
||||
|
||||
# Java AES/GCM appends a 16-byte authentication tag at the end of cipherBytes
|
||||
# cryptography library expects it to be passed into the modes.GCM(iv, tag)
|
||||
cipher_bytes_with_tag = combined[iv_length:]
|
||||
actual_ciphertext = cipher_bytes_with_tag[:-16]
|
||||
tag = cipher_bytes_with_tag[-16:]
|
||||
|
||||
cipher = Cipher(algorithms.AES(secret), modes.GCM(iv, tag))
|
||||
decryptor = cipher.decryptor()
|
||||
|
||||
plain_bytes = decryptor.update(actual_ciphertext) + decryptor.finalize()
|
||||
return plain_bytes.decode('utf-8')
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def get_string_value(encrypted_id: str, secret: str, secret_key_internal: str) -> str | None:
|
||||
if not secret or not secret_key_internal:
|
||||
return None
|
||||
try:
|
||||
# Replicate Java's logic: (s + secretKeyInternal).substring(0, Math.min(..., 16))
|
||||
combined_str = secret + secret_key_internal
|
||||
combined_secret = combined_str[:16].encode('utf-8')
|
||||
return decrypt(encrypted_id, combined_secret)
|
||||
except Exception:
|
||||
return None
|
||||
@@ -28,30 +28,32 @@ class Settings(BaseSettings):
|
||||
|
||||
# Database
|
||||
db_host: str = "192.168.0.111"
|
||||
db_port: int = 7925
|
||||
db_name: str = "document_engine"
|
||||
db_port: int = 5432
|
||||
db_name: str = "ocr"
|
||||
db_user: str = "postgres"
|
||||
db_password: str = "M@tr!x#149@dm!N"
|
||||
db_password: str = "M@triXPostgr3s@6202"
|
||||
db_schema: str = "admin"
|
||||
db_pool_size: int = 20
|
||||
db_max_overflow: int = 10
|
||||
db_echo: bool = False
|
||||
|
||||
# Redis
|
||||
redis_host: str = "localhost"
|
||||
redis_port: int = 6379
|
||||
redis_host: str = "192.168.0.111"
|
||||
redis_port: int = 7901
|
||||
redis_db: int = 0
|
||||
redis_password: str = ""
|
||||
redis_password: str = "M@triXR3d1s@6202"
|
||||
|
||||
# Celery
|
||||
celery_broker_url: str = "redis://localhost:6379/0"
|
||||
celery_result_backend: str = "redis://localhost:6379/1"
|
||||
celery_broker_url: str = "redis://:M@triXR3d1s@6202@192.168.0.111:7901/0"
|
||||
celery_result_backend: str = "redis://:M@triXR3d1s@6202@192.168.0.111:7901/1"
|
||||
|
||||
# JWT
|
||||
jwt_secret_key: str = "a7f3c9e1d4b8f2a6c0e5d7b3a9f1c4e8d2b6a0f5c3e7d1b9a4f8c2e6d0b5a3"
|
||||
jwt_algorithm: str = "HS256"
|
||||
jwt_access_token_expire_minutes: int = 30
|
||||
jwt_refresh_token_expire_days: int = 7
|
||||
session_encryption_secret: str = ""
|
||||
session_encryption_secret_internal: str = ""
|
||||
|
||||
# Storage
|
||||
storage_provider: str = "local"
|
||||
@@ -67,7 +69,7 @@ class Settings(BaseSettings):
|
||||
log_format: str = "json"
|
||||
|
||||
# CORS
|
||||
cors_origins: list[str] = ["http://localhost:3000", "http://localhost:8080"]
|
||||
cors_origins: list[str] = ["http://localhost:3000", "http://localhost:8080", "http://localhost:4200"]
|
||||
cors_allow_credentials: bool = True
|
||||
|
||||
# Rate Limiting
|
||||
|
||||
@@ -11,17 +11,63 @@ from app.core.security import InvalidTokenError, decode_token
|
||||
from app.models.user import User
|
||||
from app.repositories.user_repository import UserRepository
|
||||
|
||||
security_scheme = HTTPBearer(auto_error=True)
|
||||
import uuid
|
||||
from app.core.config import settings
|
||||
|
||||
security_scheme = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
def get_current_user(
|
||||
credentials: Annotated[HTTPAuthorizationCredentials, Depends(security_scheme)],
|
||||
credentials: Annotated[HTTPAuthorizationCredentials | None, Depends(security_scheme)],
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
) -> User:
|
||||
"""Extract and validate the current user from the JWT token."""
|
||||
if credentials is None:
|
||||
if settings.app_env == "development":
|
||||
# Auto-login as default dev admin user if no token provided in dev
|
||||
user_repo = UserRepository(db)
|
||||
user = db.query(User).first()
|
||||
if user:
|
||||
return user
|
||||
dev_user = User(
|
||||
id=uuid.uuid4(),
|
||||
username="dev_admin",
|
||||
email="admin@docengine.local",
|
||||
hashed_password="mock_password",
|
||||
is_active=True,
|
||||
is_superuser=True,
|
||||
)
|
||||
db.add(dev_user)
|
||||
db.commit()
|
||||
db.refresh(dev_user)
|
||||
return dev_user
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Not authenticated",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
try:
|
||||
payload = decode_token(credentials.credentials)
|
||||
except InvalidTokenError:
|
||||
if settings.app_env == "development":
|
||||
# Fallback to dev admin user on token decode failure in dev
|
||||
user_repo = UserRepository(db)
|
||||
user = db.query(User).first()
|
||||
if user:
|
||||
return user
|
||||
dev_user = User(
|
||||
id=uuid.uuid4(),
|
||||
username="dev_admin",
|
||||
email="admin@docengine.local",
|
||||
hashed_password="mock_password",
|
||||
is_active=True,
|
||||
is_superuser=True,
|
||||
)
|
||||
db.add(dev_user)
|
||||
db.commit()
|
||||
db.refresh(dev_user)
|
||||
return dev_user
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid or expired token",
|
||||
|
||||
@@ -8,6 +8,7 @@ from jose import JWTError, jwt
|
||||
from passlib.context import CryptContext
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.aes import get_string_value
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
@@ -44,8 +45,14 @@ def create_refresh_token(data: dict[str, Any], expires_delta: timedelta | None =
|
||||
|
||||
def decode_token(token: str) -> dict[str, Any]:
|
||||
"""Decode and validate a JWT token."""
|
||||
decrypted_token = get_string_value(
|
||||
token,
|
||||
settings.session_encryption_secret,
|
||||
settings.session_encryption_secret_internal
|
||||
)
|
||||
final_token = decrypted_token if decrypted_token else token
|
||||
try:
|
||||
payload = jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm])
|
||||
payload = jwt.decode(final_token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm])
|
||||
return payload
|
||||
except JWTError as e:
|
||||
raise InvalidTokenError(str(e)) from e
|
||||
|
||||
Reference in New Issue
Block a user