chore: auto-commit (43 archivos)

- .mcp.json
- bash/functions/infra/write_mcp_jupyter_config.md
- bash/functions/infra/write_mcp_jupyter_config.sh
- cpp/CMakeLists.txt
- cpp/apps/chart_demo
- cpp/apps/shaders_lab
- cpp/functions/gfx/gl_framebuffer.cpp
- cpp/functions/gfx/gl_framebuffer.h
- cpp/functions/gfx/gl_framebuffer.md
- cpp/functions/gfx/mesh_gpu.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 17:28:47 +02:00
parent a2efdcf003
commit fd5787c55f
44 changed files with 3924 additions and 64 deletions
@@ -0,0 +1,66 @@
"""Cambia la contrasena de un usuario en la API de administracion de Popelis."""
import json
import urllib.error
import urllib.request
def popelis_set_password(
base_url: str,
admin_token: str,
username: str,
password: str,
timeout: float = 30.0,
) -> dict:
"""Cambia la contrasena de un usuario existente en Popelis.
Hace POST a {base_url}/api/admin/users/password con el token de admin,
el nombre de usuario y la nueva contrasena. Devuelve 404 si el usuario
no existe.
Args:
base_url: URL base del servicio, sin trailing slash.
Ej: "https://popelis.datardos.com"
admin_token: Token de administracion (cabecera X-Admin-Token).
Mantenerlo en secreto — no logear.
username: Nombre de usuario cuya contrasena se quiere cambiar.
password: Nueva contrasena a establecer.
timeout: Timeout en segundos para la peticion HTTP. Default 30.0.
Returns:
Dict con el resultado: {"status": "password updated"}
Raises:
ValueError: Si el servidor devuelve 4xx o 5xx (incluyendo 404 cuando
el usuario no existe). El mensaje incluye el status code
y el campo "error" del body JSON si existe.
urllib.error.URLError: Si no se puede conectar al servidor.
"""
url = f"{base_url.rstrip('/')}/api/admin/users/password"
payload = json.dumps({"username": username, "password": password}).encode("utf-8")
req = urllib.request.Request(
url,
data=payload,
headers={
"Content-Type": "application/json",
"X-Admin-Token": admin_token,
},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
body = resp.read()
return json.loads(body)
except urllib.error.HTTPError as exc:
raw = exc.read()
try:
detail = json.loads(raw).get("error", raw.decode("utf-8", errors="replace"))
except Exception:
detail = raw.decode("utf-8", errors="replace")
if exc.code == 404:
raise ValueError(
f"popelis_set_password: usuario '{username}' no existe (HTTP 404) — {detail}"
) from exc
raise ValueError(
f"popelis_set_password: HTTP {exc.code}{detail}"
) from exc