109 lines
2.7 KiB
Python
109 lines
2.7 KiB
Python
|
|
"""
|
||
|
|
Endpoints Microsoft Graph para Planner.
|
||
|
|
|
||
|
|
Formato oficial:
|
||
|
|
{HTTP method} https://graph.microsoft.com/{version}/{resource}?{query-parameters}
|
||
|
|
|
||
|
|
Documentacion: https://learn.microsoft.com/graph/api/overview
|
||
|
|
"""
|
||
|
|
|
||
|
|
from dataclasses import dataclass, field
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass(frozen=True)
|
||
|
|
class GraphEndpoint:
|
||
|
|
method: str
|
||
|
|
resource: str
|
||
|
|
query_parameters: dict[str, str] = field(default_factory=dict)
|
||
|
|
description: str = ""
|
||
|
|
|
||
|
|
def path(self) -> str:
|
||
|
|
return f"/{self.resource.lstrip('/')}"
|
||
|
|
|
||
|
|
def label(self, version: str = "v1.0") -> str:
|
||
|
|
query = "&".join(f"{k}={v}" for k, v in self.query_parameters.items())
|
||
|
|
base = f"https://graph.microsoft.com/{version}/{self.resource.lstrip('/')}"
|
||
|
|
if query:
|
||
|
|
return f"{self.method} {base}?{query}"
|
||
|
|
return f"{self.method} {base}"
|
||
|
|
|
||
|
|
|
||
|
|
# --- Endpoints modo delegado (tu cuenta, sin admin) ---
|
||
|
|
|
||
|
|
ME_PROFILE = GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource="me",
|
||
|
|
description="Perfil del usuario autenticado",
|
||
|
|
)
|
||
|
|
|
||
|
|
ME_PLANNER_PLANS = GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource="me/planner/plans",
|
||
|
|
description="Planes de Planner a los que tienes acceso",
|
||
|
|
)
|
||
|
|
|
||
|
|
ME_JOINED_TEAMS = GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource="me/joinedTeams",
|
||
|
|
description="Equipos de Microsoft Teams donde eres miembro",
|
||
|
|
)
|
||
|
|
|
||
|
|
# --- Endpoints de Planner (ambos modos) ---
|
||
|
|
|
||
|
|
def plan_tasks(plan_id: str) -> GraphEndpoint:
|
||
|
|
return GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource=f"planner/plans/{plan_id}/tasks",
|
||
|
|
description=f"Tareas del plan {plan_id}",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def plan_buckets(plan_id: str) -> GraphEndpoint:
|
||
|
|
return GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource=f"planner/plans/{plan_id}/buckets",
|
||
|
|
description=f"Columnas/buckets del plan {plan_id}",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def task_details(task_id: str) -> GraphEndpoint:
|
||
|
|
return GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource=f"planner/tasks/{task_id}/details",
|
||
|
|
description=f"Detalle de la tarea {task_id}",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
# --- Endpoints modo aplicacion (requiere admin) ---
|
||
|
|
|
||
|
|
GROUPS_WITH_TEAMS = GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource="groups",
|
||
|
|
query_parameters={
|
||
|
|
"$filter": "resourceProvisioningOptions/Any(x:x eq 'Team')",
|
||
|
|
"$select": "id,displayName,description",
|
||
|
|
},
|
||
|
|
description="Grupos de M365 con Teams (requiere Group.Read.All)",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def group_plans(group_id: str) -> GraphEndpoint:
|
||
|
|
return GraphEndpoint(
|
||
|
|
method="GET",
|
||
|
|
resource=f"groups/{group_id}/planner/plans",
|
||
|
|
description=f"Planes del grupo {group_id}",
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
# Secuencia de prueba por modo
|
||
|
|
DELEGATED_PROBE_SEQUENCE: list[GraphEndpoint] = [
|
||
|
|
ME_PROFILE,
|
||
|
|
ME_JOINED_TEAMS,
|
||
|
|
ME_PLANNER_PLANS,
|
||
|
|
]
|
||
|
|
|
||
|
|
APPLICATION_PROBE_SEQUENCE: list[GraphEndpoint] = [
|
||
|
|
GROUPS_WITH_TEAMS,
|
||
|
|
]
|