standalone
This commit is contained in:
parent
61cec6f430
commit
95bfa36b00
@ -107,8 +107,37 @@ def list_project_ids() -> list[str]:
|
|||||||
return [d.name for d in projects_dir.iterdir() if d.is_dir() and (d / "conf.json").is_file()]
|
return [d.name for d in projects_dir.iterdir() if d.is_dir() and (d / "conf.json").is_file()]
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_conf_to_addresses(auth_to: object) -> set[str]:
|
||||||
|
"""Return set of normalized (lowercase) email addresses from authorized_emails.to.
|
||||||
|
Supports: str (single address), list of str, or list of dict with env keys (e.g. test, pprod, prod).
|
||||||
|
Address pattern AI.<project_id>.<env>@4nkweb.com; project_id and env may be uppercase."""
|
||||||
|
out: set[str] = set()
|
||||||
|
if not auth_to:
|
||||||
|
return out
|
||||||
|
if isinstance(auth_to, str):
|
||||||
|
a = auth_to.strip().lower()
|
||||||
|
if a:
|
||||||
|
out.add(a)
|
||||||
|
return out
|
||||||
|
if isinstance(auth_to, list):
|
||||||
|
for item in auth_to:
|
||||||
|
if isinstance(item, str):
|
||||||
|
a = item.strip().lower()
|
||||||
|
if a:
|
||||||
|
out.add(a)
|
||||||
|
elif isinstance(item, dict):
|
||||||
|
for v in item.values():
|
||||||
|
if isinstance(v, str):
|
||||||
|
a = v.strip().lower()
|
||||||
|
if a:
|
||||||
|
out.add(a)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def resolve_project_id_by_email_to(to_address: str) -> str | None:
|
def resolve_project_id_by_email_to(to_address: str) -> str | None:
|
||||||
"""Find project id whose tickets.authorized_emails.to matches the given address (case-insensitive)."""
|
"""Find project id whose tickets.authorized_emails.to matches the given address (case-insensitive).
|
||||||
|
authorized_emails.to may be a single string or a list of objects { test, pprod, prod } with addresses
|
||||||
|
AI.<project_id>.<env>@4nkweb.com (project_id and env may be uppercase)."""
|
||||||
if not to_address or not to_address.strip():
|
if not to_address or not to_address.strip():
|
||||||
return None
|
return None
|
||||||
to_normalized = to_address.strip().lower()
|
to_normalized = to_address.strip().lower()
|
||||||
@ -121,8 +150,8 @@ def resolve_project_id_by_email_to(to_address: str) -> str | None:
|
|||||||
continue
|
continue
|
||||||
tickets = conf.get("tickets") or {}
|
tickets = conf.get("tickets") or {}
|
||||||
auth = tickets.get("authorized_emails") or {}
|
auth = tickets.get("authorized_emails") or {}
|
||||||
conf_to = (auth.get("to") or "").strip().lower()
|
conf_to_set = _normalize_conf_to_addresses(auth.get("to"))
|
||||||
if conf_to == to_normalized:
|
if to_normalized in conf_to_set:
|
||||||
return pid
|
return pid
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ One JSON file per project: `projects/<id>/conf.json` (e.g. `projects/lecoffreio/
|
|||||||
| `version.splash_app_name` | no | App name used in splash message template |
|
| `version.splash_app_name` | no | App name used in splash message template |
|
||||||
| `mail` | no | Mail/imap bridge config |
|
| `mail` | no | Mail/imap bridge config |
|
||||||
| `git` | no | Git hosting: `wiki_url`, `token_file` (path relative to repo root for token file). Ticketing URL is under `tickets`, not `git`. |
|
| `git` | no | Git hosting: `wiki_url`, `token_file` (path relative to repo root for token file). Ticketing URL is under `tickets`, not `git`. |
|
||||||
| `tickets` | no | Ticketing: `ticketing_url` (Gitea issues URL), `authorized_emails` (`to`: alias, `from`: list of allowed sender addresses for mail-based ticketing). The **to** address is used to resolve the project id when processing mails. See projects/ia_dev/docs/TICKETS_SPOOL_FORMAT.md. |
|
| `tickets` | no | Ticketing: `ticketing_url` (Gitea issues URL), `authorized_emails` (`to`: alias or list of env-keyed objects, `from`: list of allowed sender addresses). **to** resolves the project id when processing mails. It may be a single string or a list of one object with env keys: `[{ "test": "AI.<project_id>.TEST@4nkweb.com", "pprod": "...", "prod": "..." }]`. Pattern: `AI.<project_id>.<env>@4nkweb.com` (`project_id` and `env` may be uppercase). See projects/ia_dev/docs/TICKETS_SPOOL_FORMAT.md. |
|
||||||
|
|
||||||
The API token for ai_working_help is **not** in conf.json. It is found by scanning all projects and all envs (as described above): each file `projects/<id>/.secrets/<env>/ia_token` is read and the Bearer is compared to the file content or to (file content + env). Token value is **base** + **env**; **env** is the environment name (test, pprod, prod), to be adapted per environment. The first match gives project id and env.
|
The API token for ai_working_help is **not** in conf.json. It is found by scanning all projects and all envs (as described above): each file `projects/<id>/.secrets/<env>/ia_token` is read and the Bearer is compared to the file content or to (file content + env). Token value is **base** + **env**; **env** is the environment name (test, pprod, prod), to be adapted per environment. The first match gives project id and env.
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,13 @@
|
|||||||
"tickets": {
|
"tickets": {
|
||||||
"ticketing_url": "https://git.4nkweb.com/nicolas.cantu/algo/issues",
|
"ticketing_url": "https://git.4nkweb.com/nicolas.cantu/algo/issues",
|
||||||
"authorized_emails": {
|
"authorized_emails": {
|
||||||
"to": "ai.support.algo@4nkweb.com",
|
"to": [
|
||||||
|
{
|
||||||
|
"test": "AI.ALGO.TEST@4nkweb.com",
|
||||||
|
"pprod": "AI.ALGO.PPROD@4nkweb.com",
|
||||||
|
"prod": "AI.ALGO.PROD@4nkweb.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
"from": []
|
"from": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
"splash_app_name": "enso"
|
"splash_app_name": "enso"
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"email": "ai.support.enso@4nkweb.com",
|
|
||||||
"imap_bridge_env": ".secrets/gitea-issues/imap-bridge.env"
|
"imap_bridge_env": ".secrets/gitea-issues/imap-bridge.env"
|
||||||
},
|
},
|
||||||
"git": {
|
"git": {
|
||||||
@ -30,7 +29,13 @@
|
|||||||
"tickets": {
|
"tickets": {
|
||||||
"ticketing_url": "https://git.4nkweb.com/nicolas.cantu/enso/issues",
|
"ticketing_url": "https://git.4nkweb.com/nicolas.cantu/enso/issues",
|
||||||
"authorized_emails": {
|
"authorized_emails": {
|
||||||
"to": "ai.support.enso@4nkweb.com",
|
"to": [
|
||||||
|
{
|
||||||
|
"test": "AI.ENSO.TEST@4nkweb.com",
|
||||||
|
"pprod": "AI.ENSO.PPROD@4nkweb.com",
|
||||||
|
"prod": "AI.ENSO.PROD@4nkweb.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
"from": []
|
"from": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "ia_dev",
|
"id": "ia_dev",
|
||||||
"name": "ia_dev",
|
"name": "ia_dev",
|
||||||
"project_path": "../",
|
"project_path": "home/desk/code/ia_dev",
|
||||||
"base_path": "ia_dev",
|
|
||||||
"build_dirs": [],
|
"build_dirs": [],
|
||||||
"deploy": {},
|
"deploy": {},
|
||||||
"version": {
|
"version": {
|
||||||
@ -10,7 +9,6 @@
|
|||||||
"splash_app_name": "ia_dev"
|
"splash_app_name": "ia_dev"
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"email": "ai.support.ia_dev@4nkweb.com",
|
|
||||||
"imap_bridge_env": ".secrets/gitea-issues/imap-bridge.env"
|
"imap_bridge_env": ".secrets/gitea-issues/imap-bridge.env"
|
||||||
},
|
},
|
||||||
"git": {
|
"git": {
|
||||||
@ -20,7 +18,13 @@
|
|||||||
"tickets": {
|
"tickets": {
|
||||||
"ticketing_url": "https://git.4nkweb.com/4nk/ia_dev/issues",
|
"ticketing_url": "https://git.4nkweb.com/4nk/ia_dev/issues",
|
||||||
"authorized_emails": {
|
"authorized_emails": {
|
||||||
"to": "ai.support.ia_dev@4nkweb.com",
|
"to": [
|
||||||
|
{
|
||||||
|
"test": "AI.IA_DEV.TEST@4nkweb.com",
|
||||||
|
"pprod": "AI.IA_DEV.PPROD@4nkweb.com",
|
||||||
|
"prod": "AI.IA_DEV.PROD@4nkweb.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
"from": ["nicolas.cantu@pm.me"]
|
"from": ["nicolas.cantu@pm.me"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,13 @@
|
|||||||
"tickets": {
|
"tickets": {
|
||||||
"ticketing_url": "https://git.4nkweb.com/4nk/lecoffre_ng/issues",
|
"ticketing_url": "https://git.4nkweb.com/4nk/lecoffre_ng/issues",
|
||||||
"authorized_emails": {
|
"authorized_emails": {
|
||||||
"to": "ai.support.lecoffreio@4nkweb.com",
|
"to": [
|
||||||
|
{
|
||||||
|
"test": "AI.LECOFFREIO.TEST@4nkweb.com",
|
||||||
|
"pprod": "AI.LECOFFREIO.PPROD@4nkweb.com",
|
||||||
|
"prod": "AI.LECOFFREIO.PROD@4nkweb.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
"from": [
|
"from": [
|
||||||
"laurence@lecoffre.io",
|
"laurence@lecoffre.io",
|
||||||
"gwendal@lecoffre.io"
|
"gwendal@lecoffre.io"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user