Text Extraction Done, UI Fixes Done, Extracted Template Layout Saved in DB

This commit is contained in:
2026-07-12 14:24:17 +05:30
parent 3163bb213e
commit 3d6614f408
79 changed files with 3139 additions and 81 deletions

38
docengine/app/core/aes.py Normal file
View 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

View File

@@ -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

View File

@@ -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",

View File

@@ -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