files-server-fastapi 0.1.6__tar.gz → 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/PKG-INFO +1 -1
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/pyproject.toml +1 -1
- files_server_fastapi-0.1.7/src/files_server_fastapi/files/acls_router.py +98 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/dependencies.py +12 -2
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/folder_router.py +1 -1
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/list_router.py +1 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/.gitignore +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/.python-version +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/LICENSE +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/MANIFEST.in +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/README.md +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/__init__.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/__init__.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/constants.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/download_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/open_url_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/tree_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/upload_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/__init__.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/area_model.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/permisos_model.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/rol_model.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/rutas_model.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/models/users_extend_model.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/__init__.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/area_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/files_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/permisos_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/rol_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/rutas_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/routers/users_extend_router.py +0 -0
- {files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: files-server-fastapi
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Este repositorio es un paquete python desarrollado con FastAPI, gestiona la comunicación con un servidor Samba y utiliza PostgreSQL para administrar rutas de archivos y el control de acceso basado en roles (RBAC) de los usuarios.
|
|
5
5
|
Project-URL: Homepage, https://github.com/AldoBP/files-server-fastapi
|
|
6
6
|
Project-URL: Repository, https://github.com/AldoBP/files-server-fastapi
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "files-server-fastapi"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.7"
|
|
4
4
|
description = "Este repositorio es un paquete python desarrollado con FastAPI, gestiona la comunicación con un servidor Samba y utiliza PostgreSQL para administrar rutas de archivos y el control de acceso basado en roles (RBAC) de los usuarios."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
5
|
+
from sqlalchemy import select
|
|
6
|
+
|
|
7
|
+
from pgsqlasync2fast_fastapi.dependencies import get_db_session
|
|
8
|
+
from oauth2fast_fastapi import get_current_user, User
|
|
9
|
+
from files_server_fastapi.models.permisos_model import User_Ruta_Access
|
|
10
|
+
from files_server_fastapi.models.rutas_model import Rutas
|
|
11
|
+
from files_server_fastapi.models.area_model import Area
|
|
12
|
+
|
|
13
|
+
router = APIRouter()
|
|
14
|
+
|
|
15
|
+
class AclDetail(BaseModel):
|
|
16
|
+
path: str
|
|
17
|
+
permission: str
|
|
18
|
+
|
|
19
|
+
class AclCreate(BaseModel):
|
|
20
|
+
area: str
|
|
21
|
+
user_id: int
|
|
22
|
+
acls: list[AclDetail]
|
|
23
|
+
|
|
24
|
+
@router.post("/acls", summary="Asignar acceso a una carpeta específica (ACL)")
|
|
25
|
+
async def create_acl(
|
|
26
|
+
req: AclCreate,
|
|
27
|
+
current_user: User = Depends(get_current_user),
|
|
28
|
+
db: AsyncSession = Depends(get_db_session)
|
|
29
|
+
):
|
|
30
|
+
"""
|
|
31
|
+
Crea o actualiza los accesos (ACLs) enviados desde el frontend.
|
|
32
|
+
"""
|
|
33
|
+
# 0. Validar que el usuario existe en la BD
|
|
34
|
+
user_result = await db.execute(select(User).where(User.id == req.user_id))
|
|
35
|
+
if not user_result.scalars().first():
|
|
36
|
+
raise HTTPException(status_code=404, detail=f"El usuario con ID {req.user_id} no existe en la base de datos.")
|
|
37
|
+
|
|
38
|
+
# 1. Verificar si el Área existe para crear la Ruta adecuadamente
|
|
39
|
+
area_result = await db.execute(select(Area).where(Area.area_name.ilike(req.area)))
|
|
40
|
+
area_obj = area_result.scalars().first()
|
|
41
|
+
if not area_obj:
|
|
42
|
+
raise HTTPException(status_code=404, detail=f"Área '{req.area}' no encontrada")
|
|
43
|
+
|
|
44
|
+
processed_acls = []
|
|
45
|
+
|
|
46
|
+
for acl_item in req.acls:
|
|
47
|
+
# Limpiar subpath y contruir ruta lógica completa
|
|
48
|
+
subpath = acl_item.path.strip("/")
|
|
49
|
+
logical_path_full = f"/{req.area.upper()}/{subpath}".replace("//", "/")
|
|
50
|
+
|
|
51
|
+
parts = logical_path_full.strip("/").split("/")
|
|
52
|
+
folder_name = parts[-1] if len(parts) > 0 else req.area.upper()
|
|
53
|
+
|
|
54
|
+
# Mapear permisos del Frontend ("EDITOR" / "VIEWER") a tipos de DB ("allow_write" / "allow_read")
|
|
55
|
+
db_access_type = "allow_read" # Por defecto
|
|
56
|
+
if acl_item.permission.upper() == "EDITOR":
|
|
57
|
+
db_access_type = "allow_write"
|
|
58
|
+
elif acl_item.permission.upper() == "DENY":
|
|
59
|
+
db_access_type = "deny_all"
|
|
60
|
+
|
|
61
|
+
# 2. Buscar si la ruta ya existe en la tabla Rutas
|
|
62
|
+
ruta_result = await db.execute(select(Rutas).where(Rutas.ruta == logical_path_full))
|
|
63
|
+
ruta_obj = ruta_result.scalars().first()
|
|
64
|
+
|
|
65
|
+
# Si no existe, crearla
|
|
66
|
+
if not ruta_obj:
|
|
67
|
+
ruta_obj = Rutas(
|
|
68
|
+
ruta=logical_path_full,
|
|
69
|
+
name=folder_name,
|
|
70
|
+
area_id=area_obj.id
|
|
71
|
+
)
|
|
72
|
+
db.add(ruta_obj)
|
|
73
|
+
await db.commit()
|
|
74
|
+
await db.refresh(ruta_obj)
|
|
75
|
+
|
|
76
|
+
# 3. Asignar el ACL en User_Ruta_Access
|
|
77
|
+
acl_result = await db.execute(
|
|
78
|
+
select(User_Ruta_Access)
|
|
79
|
+
.where(User_Ruta_Access.user_id == req.user_id)
|
|
80
|
+
.where(User_Ruta_Access.ruta_id == ruta_obj.id)
|
|
81
|
+
)
|
|
82
|
+
existing_acl = acl_result.scalars().first()
|
|
83
|
+
|
|
84
|
+
if existing_acl:
|
|
85
|
+
existing_acl.access_type = db_access_type
|
|
86
|
+
processed_acls.append(existing_acl.id)
|
|
87
|
+
else:
|
|
88
|
+
new_acl = User_Ruta_Access(
|
|
89
|
+
user_id=req.user_id,
|
|
90
|
+
ruta_id=ruta_obj.id,
|
|
91
|
+
access_type=db_access_type
|
|
92
|
+
)
|
|
93
|
+
db.add(new_acl)
|
|
94
|
+
await db.commit()
|
|
95
|
+
await db.refresh(new_acl)
|
|
96
|
+
processed_acls.append(new_acl.id)
|
|
97
|
+
|
|
98
|
+
return {"message": "ACLs asignados correctamente", "processed_acls": processed_acls}
|
|
@@ -21,14 +21,24 @@ async def check_folder_access(
|
|
|
21
21
|
Verifica si el usuario actual tiene acceso al área y subpath indicados.
|
|
22
22
|
required_access: 'allow_read' (por defecto) o 'allow_write'
|
|
23
23
|
"""
|
|
24
|
-
# 1. Obtener extensión de usuario y verificar
|
|
24
|
+
# 1. Obtener extensión de usuario y verificar roles/áreas
|
|
25
25
|
result_ext = await db.execute(
|
|
26
26
|
select(Users_extend).where(Users_extend.user_id == current_user.id)
|
|
27
27
|
)
|
|
28
28
|
user_exts = result_ext.scalars().all()
|
|
29
|
+
|
|
30
|
+
# 2. Verificar si el usuario es SUPER_ADMIN en cualquier área
|
|
31
|
+
for ext in user_exts:
|
|
32
|
+
res_rol = await db.execute(select(Rol).where(Rol.id == ext.rol_id))
|
|
33
|
+
rol = res_rol.scalars().first()
|
|
34
|
+
if rol and rol.role_name.upper() == "SUPER_ADMIN":
|
|
35
|
+
return True # SUPER_ADMIN tiene acceso universal a todas las carpetas, salta otras validaciones.
|
|
29
36
|
|
|
37
|
+
# 3. Si no es SUPER_ADMIN, verificar pertenencia al área indicada
|
|
30
38
|
area_obj = None
|
|
31
39
|
user_ext_match = None
|
|
40
|
+
rol_name = ""
|
|
41
|
+
|
|
32
42
|
for ext in user_exts:
|
|
33
43
|
res_area = await db.execute(select(Area).where(Area.id == ext.area_id))
|
|
34
44
|
a = res_area.scalars().first()
|
|
@@ -40,7 +50,7 @@ async def check_folder_access(
|
|
|
40
50
|
if not area_obj or not user_ext_match:
|
|
41
51
|
raise HTTPException(status_code=403, detail="No perteneces a esta área")
|
|
42
52
|
|
|
43
|
-
# Obtener el Rol Base del usuario en
|
|
53
|
+
# Obtener el Rol Base del usuario en ESTA área específica
|
|
44
54
|
res_rol = await db.execute(select(Rol).where(Rol.id == user_ext_match.rol_id))
|
|
45
55
|
rol_obj = res_rol.scalars().first()
|
|
46
56
|
rol_name = rol_obj.role_name.lower() if rol_obj else ""
|
|
@@ -29,7 +29,7 @@ async def create_folder(
|
|
|
29
29
|
|
|
30
30
|
safe_subpath = req.subpath.strip("/")
|
|
31
31
|
ruta_final = os.path.join(BASE_DIR, req.area.upper(), safe_subpath, req.folder_name) if safe_subpath else os.path.join(BASE_DIR, req.area.upper(), req.folder_name)
|
|
32
|
-
|
|
32
|
+
print(ruta_final)
|
|
33
33
|
try:
|
|
34
34
|
os.makedirs(ruta_final, exist_ok=False)
|
|
35
35
|
return {"message": "Carpeta creada exitosamente", "path": ruta_final}
|
|
@@ -19,6 +19,7 @@ async def list_directory(
|
|
|
19
19
|
|
|
20
20
|
safe_subpath = subpath.strip("/")
|
|
21
21
|
ruta_real = os.path.join(BASE_DIR, area.upper(), safe_subpath) if safe_subpath else os.path.join(BASE_DIR, area.upper())
|
|
22
|
+
print(ruta_real)
|
|
22
23
|
|
|
23
24
|
if not os.path.exists(ruta_real):
|
|
24
25
|
return []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/__init__.py
RENAMED
|
File without changes
|
{files_server_fastapi-0.1.6 → files_server_fastapi-0.1.7}/src/files_server_fastapi/files/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|