Endpoint: POST /auto-provision/assign-types
Descripción general
Endpoint que materializa la asignación de destino de dispositivos desde el Step 2 del wizard de Auto-Provision. Persiste el campo device_type en lote sobre varios DeviceProfile de una org.
POST /api/network/auto-provision/assign-types
Funcionalidad clave: permite cambiar en una pasada el destino (p.ej. de “router” a “wireless_controller”) de múltiples perfiles descobertos, consolidando toda la intención en un único request.
Parámetros
Request
Headers requeridos:
Authorization: Bearer <token>
Content-Type: application/json
Body (JSON):
{
"assignments": [
{
"profile_id": 42,
"device_type": "wireless_controller"
},
{
"profile_id": 43,
"device_type": "access_point"
},
{
"profile_id": 44,
"device_type": "ups"
}
]
}
Tipos válidos (ASSIGNABLE_TYPES):
router,switch,firewall,load_balancer→ racking estándar.wireless_controller,access_point→ monitores Wireless.ups→ monitor UPS.media_player→ Digital Signage.other→ sin categoría.
El endpoint no valida contra DeviceProfile.DEVICE_TYPE_CHOICES porque Django no lo hace en .update(), y el discovery ya usa estos valores. Validación en cliente (wizard).
Response
HTTP 200 — Éxito:
{
"updated": 3
}
HTTP 400 — Error (tipos inválidos, org no encontrada):
{
"error": "Invalid device_type(s): fake_type, another_bad"
}
o
{
"error": "No organization found"
}
Seguridad & Multi-tenancy
- Permiso:
require_perm(request, "network", "edit")— solo usuarios con rol que tenga permisonetwork.editen su org. - Scope:
organization=org— todos los updates acotados a la org actual (RLS implícito en el queryset). - Cross-tenant safe: un usuario de org A no puede tocar perfiles de org B.
Lógica interna
- Valida que todas las
device_typeestén enASSIGNABLE_TYPES. - Agrupa
assignmentspordevice_type. - Un
UPDATEpor tipo (no per-profile, para eficiencia):DeviceProfile.objects.filter(organization=org, id__in=ids).update(device_type=device_type) - Anota la acción en el log:
"NETWORK" / "auto_provision.assign_types" / "N profiles". - Retorna count de filas actualizadas.
Impacto aguas abajo
Una vez actualizado el device_type:
- Monitores (Wireless, UPS, Signage, Observatory) incluyen el equipo en sus listas (Regla 13: no es fake si
device_typeestá en su rango). - Racking: si el tipo es router/switch/firewall, el modal de colocación en rack espera input adicional.
- Perfil: el
DeviceProfileretiene el nuevo tipo en bd; es persistente.
Ejemplos de uso
Caso 1: Asignar varios switches de golpe
POST /api/network/auto-provision/assign-types
{
"assignments": [
{"profile_id": 10, "device_type": "switch"},
{"profile_id": 11, "device_type": "switch"},
{"profile_id": 12, "device_type": "switch"}
]
}
→ 200 OK: {"updated": 3}
Caso 2: Mezcla de tipos
{
"assignments": [
{"profile_id": 20, "device_type": "wireless_controller"},
{"profile_id": 21, "device_type": "access_point"},
{"profile_id": 22, "device_type": "ups"}
]
}
→ 200 OK: {"updated": 3}
Caso 3: Tipo inválido
{
"assignments": [
{"profile_id": 30, "device_type": "invalid_type"}
]
}
→ 400: {"error": "Invalid device_type(s): invalid_type"}
Esquemas Pydantic
class TypeAssignment(Schema):
profile_id: int
device_type: str
class AssignTypesRequest(Schema):
assignments: list[TypeAssignment]
Tests
test_network_assign_types.py — 5 tests:
- Asignación simple (1 perfil, 1 tipo).
- Asignación masiva (múltiples perfiles, múltiples tipos).
- Validación de tipo inválido.
- RLS: usuario no puede tocar otros perfiles de org ajena.
- Sin org → 400.
Notas de implementación
- Endpoint cableado en
network/api/__init__.py(router registration). - Archivo fuente:
network/api/assign.py(69 líneas). - No crea registros nuevos; solo actualiza campo existente.
- No usa batch operations de ORM complejas; loop simple por tipo para claridad.
Véase también
- [[entity—network—model—device-profile]]
- [[feature—network—autoprovision-ux-panel-assign-s115]]
- [[concept—network—device-type-mapping]]
- [[concept—saas—multi-tenancy]]