progress in file service

This commit is contained in:
Hesabix 2025-09-21 20:31:52 +03:30
parent b690e115d4
commit 754d61e622
17 changed files with 31 additions and 62 deletions

View file

@ -7,12 +7,12 @@ from adapters.db.session import get_db
from app.core.auth_dependency import get_current_user from app.core.auth_dependency import get_current_user
from app.core.permissions import require_permission from app.core.permissions import require_permission
from app.core.responses import success_response from app.core.responses import success_response
from app.core.error_handlers import ApiError from app.core.responses import ApiError
from app.core.i18n import locale_dependency from app.core.i18n import locale_dependency
from app.services.file_storage_service import FileStorageService from app.services.file_storage_service import FileStorageService
from adapters.db.repositories.file_storage_repository import StorageConfigRepository, FileStorageRepository from adapters.db.repositories.file_storage_repository import StorageConfigRepository, FileStorageRepository
from adapters.db.models.user import User from adapters.db.models.user import User
from adapters.api.v1.schemas.file_storage import ( from adapters.api.v1.schema_models.file_storage import (
StorageConfigCreateRequest, StorageConfigCreateRequest,
StorageConfigUpdateRequest, StorageConfigUpdateRequest,
FileUploadRequest, FileUploadRequest,

View file

@ -1,5 +1,5 @@
from fastapi import APIRouter from fastapi import APIRouter
from .schemas import SuccessResponse from adapters.api.v1.schemas import SuccessResponse
router = APIRouter(prefix="/health", tags=["health"]) router = APIRouter(prefix="/health", tags=["health"])

View file

@ -0,0 +1,10 @@
# This file makes the directory a Python package
# Import from file_storage module
from .file_storage import *
# Re-export from parent schemas module
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from schemas import *

View file

@ -1,2 +0,0 @@
# Import all schemas
from .file_storage import *

View file

@ -1,5 +1,4 @@
from sqlalchemy import Column, String, Integer, DateTime, Boolean, Text, ForeignKey, JSON from sqlalchemy import Column, String, Integer, DateTime, Boolean, Text, ForeignKey, JSON, BigInteger
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql import func from sqlalchemy.sql import func
import uuid import uuid
@ -10,17 +9,17 @@ from adapters.db.session import Base
class FileStorage(Base): class FileStorage(Base):
__tablename__ = "file_storage" __tablename__ = "file_storage"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
original_name = Column(String(255), nullable=False) original_name = Column(String(255), nullable=False)
stored_name = Column(String(255), nullable=False) stored_name = Column(String(255), nullable=False)
file_path = Column(String(500), nullable=False) file_path = Column(String(500), nullable=False)
file_size = Column(Integer, nullable=False) file_size = Column(Integer, nullable=False)
mime_type = Column(String(100), nullable=False) mime_type = Column(String(100), nullable=False)
storage_type = Column(String(20), nullable=False) # local, ftp storage_type = Column(String(20), nullable=False) # local, ftp
storage_config_id = Column(UUID(as_uuid=True), ForeignKey("storage_configs.id"), nullable=True) storage_config_id = Column(String(36), ForeignKey("storage_configs.id"), nullable=True)
uploaded_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False) uploaded_by = Column(Integer, ForeignKey("users.id"), nullable=False)
module_context = Column(String(50), nullable=False) # tickets, accounting, business_logo, etc. module_context = Column(String(50), nullable=False) # tickets, accounting, business_logo, etc.
context_id = Column(UUID(as_uuid=True), nullable=True) # ticket_id, document_id, etc. context_id = Column(String(36), nullable=True) # ticket_id, document_id, etc.
developer_data = Column(JSON, nullable=True) developer_data = Column(JSON, nullable=True)
checksum = Column(String(64), nullable=True) checksum = Column(String(64), nullable=True)
is_active = Column(Boolean, default=True, nullable=False) is_active = Column(Boolean, default=True, nullable=False)
@ -41,13 +40,13 @@ class FileStorage(Base):
class StorageConfig(Base): class StorageConfig(Base):
__tablename__ = "storage_configs" __tablename__ = "storage_configs"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
name = Column(String(100), nullable=False) name = Column(String(100), nullable=False)
storage_type = Column(String(20), nullable=False) # local, ftp storage_type = Column(String(20), nullable=False) # local, ftp
is_default = Column(Boolean, default=False, nullable=False) is_default = Column(Boolean, default=False, nullable=False)
is_active = Column(Boolean, default=True, nullable=False) is_active = Column(Boolean, default=True, nullable=False)
config_data = Column(JSON, nullable=False) config_data = Column(JSON, nullable=False)
created_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False) created_by = Column(Integer, ForeignKey("users.id"), nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
@ -58,12 +57,12 @@ class StorageConfig(Base):
class FileVerification(Base): class FileVerification(Base):
__tablename__ = "file_verifications" __tablename__ = "file_verifications"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
file_id = Column(UUID(as_uuid=True), ForeignKey("file_storage.id"), nullable=False) file_id = Column(String(36), ForeignKey("file_storage.id"), nullable=False)
module_name = Column(String(50), nullable=False) module_name = Column(String(50), nullable=False)
verification_token = Column(String(100), nullable=False) verification_token = Column(String(100), nullable=False)
verified_at = Column(DateTime(timezone=True), nullable=True) verified_at = Column(DateTime(timezone=True), nullable=True)
verified_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True) verified_by = Column(Integer, ForeignKey("users.id"), nullable=True)
verification_data = Column(JSON, nullable=True) verification_data = Column(JSON, nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)

View file

@ -5,7 +5,7 @@ from sqlalchemy import and_, or_, desc, func
from datetime import datetime, timedelta from datetime import datetime, timedelta
from adapters.db.models.file_storage import FileStorage, StorageConfig, FileVerification from adapters.db.models.file_storage import FileStorage, StorageConfig, FileVerification
from adapters.db.repositories.base import BaseRepository from adapters.db.repositories.base_repo import BaseRepository
class FileStorageRepository(BaseRepository[FileStorage]): class FileStorageRepository(BaseRepository[FileStorage]):

View file

@ -137,3 +137,8 @@ def require_business_management():
def require_system_settings(): def require_system_settings():
"""دسترسی تنظیمات سیستم""" """دسترسی تنظیمات سیستم"""
return require_app_permission("system_settings") return require_app_permission("system_settings")
def require_permission(permission: str):
"""Decorator عمومی برای بررسی دسترسی - wrapper برای require_app_permission"""
return require_app_permission(permission)

View file

@ -9,8 +9,8 @@ adapters/api/v1/health.py
adapters/api/v1/schemas.py adapters/api/v1/schemas.py
adapters/api/v1/users.py adapters/api/v1/users.py
adapters/api/v1/admin/file_storage.py adapters/api/v1/admin/file_storage.py
adapters/api/v1/schemas/__init__.py adapters/api/v1/schema_models/__init__.py
adapters/api/v1/schemas/file_storage.py adapters/api/v1/schema_models/file_storage.py
adapters/api/v1/support/__init__.py adapters/api/v1/support/__init__.py
adapters/api/v1/support/categories.py adapters/api/v1/support/categories.py
adapters/api/v1/support/operator.py adapters/api/v1/support/operator.py
@ -87,7 +87,6 @@ migrations/versions/20250117_000007_create_business_permissions_table.py
migrations/versions/20250915_000001_init_auth_tables.py migrations/versions/20250915_000001_init_auth_tables.py
migrations/versions/20250916_000002_add_referral_fields.py migrations/versions/20250916_000002_add_referral_fields.py
migrations/versions/5553f8745c6e_add_support_tables.py migrations/versions/5553f8745c6e_add_support_tables.py
migrations/versions/8bf0dbb9fba9_add_file_storage_tables.py
tests/__init__.py tests/__init__.py
tests/test_health.py tests/test_health.py
tests/test_permissions.py tests/test_permissions.py

View file

@ -1,28 +0,0 @@
"""add_file_storage_tables
Revision ID: 8bf0dbb9fba9
Revises: 5553f8745c6e
Create Date: 2025-09-21 19:23:10.515694
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '8bf0dbb9fba9'
down_revision = '5553f8745c6e'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###

View file

@ -392,7 +392,6 @@
"apply": "Apply", "apply": "Apply",
"reset": "Reset", "reset": "Reset",
"page": "Page", "page": "Page",
"of": "of",
"itemsPerPage": "Items per page", "itemsPerPage": "Items per page",
"previous": "Previous", "previous": "Previous",
"next": "Next", "next": "Next",

View file

@ -391,7 +391,6 @@
"apply": "اعمال", "apply": "اعمال",
"reset": "بازنشانی", "reset": "بازنشانی",
"page": "صفحه", "page": "صفحه",
"of": "از",
"itemsPerPage": "آیتم در هر صفحه", "itemsPerPage": "آیتم در هر صفحه",
"previous": "قبلی", "previous": "قبلی",
"next": "بعدی", "next": "بعدی",

View file

@ -2198,12 +2198,6 @@ abstract class AppLocalizations {
/// **'Reset'** /// **'Reset'**
String get reset; String get reset;
/// No description provided for @of.
///
/// In en, this message translates to:
/// **'of'**
String get of;
/// No description provided for @itemsPerPage. /// No description provided for @itemsPerPage.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View file

@ -1089,9 +1089,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get reset => 'Reset'; String get reset => 'Reset';
@override
String get of => 'of';
@override @override
String get itemsPerPage => 'Items per page'; String get itemsPerPage => 'Items per page';

View file

@ -1083,9 +1083,6 @@ class AppLocalizationsFa extends AppLocalizations {
@override @override
String get reset => 'بازنشانی'; String get reset => 'بازنشانی';
@override
String get of => 'از';
@override @override
String get itemsPerPage => 'آیتم در هر صفحه'; String get itemsPerPage => 'آیتم در هر صفحه';