feat(site_domain): restore access_key enforcement for FQDN lookups
- api_crud_v3: strip falsy access_key values; restrict keyless queries to public domains (both site_access_key and site_domain_access_key must be NULL/empty); 75-line recursive block replaced with ~16 lines - lib_sql_search: expand virtual 'access_key' field into priority SQL — site_access_key first, site_domain_access_key as fallback - cms.py: add site_domain_access_key to site_domain searchable_fields - docs: update frontend guide with access key behavior and examples - e2e test: expand to cover all valid/invalid access key scenarios (15/15) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,37 @@ When the frontend first loads and doesn't know the `account_id`, it performs a "
|
||||
* Returns 200 + a list containing the `account_id` (random string ID) and `site_id` (random string ID).
|
||||
* ** デザイン Choice:** If the domain is not found, it returns **200 OK with an empty list `[]`**. It is NOT a 404.
|
||||
|
||||
> **Access Key Support**
|
||||
>
|
||||
> Some client deployments restrict their domain via an access key passed in the browser URL (e.g. `?key=abc123`). The frontend reads this param and forwards it as `access_key` in the POST body.
|
||||
>
|
||||
> **How to pass the key:**
|
||||
> ```json
|
||||
> {
|
||||
> "and": [
|
||||
> { "field": "fqdn", "op": "eq", "value": "client.example.com" },
|
||||
> { "field": "access_key", "op": "eq", "value": "abc123" }
|
||||
> ]
|
||||
> }
|
||||
> ```
|
||||
> If `key` is absent, empty, or falsy — **omit `access_key` from the payload entirely**. Do not send `"access_key": ""`.
|
||||
>
|
||||
> **Server behavior:**
|
||||
> - `site_access_key` (site-level key) takes priority. If set, all domains under that site require it.
|
||||
> - `site_domain_access_key` (domain-level key) is used as fallback when `site_access_key` is not set.
|
||||
> - A domain is **public** only when **both** key columns are NULL/empty.
|
||||
> - Falsy `access_key` values are ignored server-side as a safety net.
|
||||
> - Match → `200` with the record. No match → `200` with empty list `[]`.
|
||||
> - Do **not** use `access_code_kv_json` for this — that field is for UI features only.
|
||||
>
|
||||
> | Browser URL | `access_key` in payload | Result |
|
||||
> |---|---|---|
|
||||
> | `https://dev-demo.oneskyit.com` | *(omit)* | ✅ Returns record (public) |
|
||||
> | `https://client.example.com/?key=correct` | `"correct"` | ✅ Returns record |
|
||||
> | `https://client.example.com/` | *(omit)* | ❌ Empty (key required) |
|
||||
> | `https://client.example.com/?key=wrong` | `"wrong"` | ❌ Empty (wrong key) |
|
||||
> | `https://client.example.com/?key=` | *(omit — strip empty)* | ❌ Empty (key required) |
|
||||
>
|
||||
---
|
||||
|
||||
## 3. Standard CRUD Patterns
|
||||
|
||||
Reference in New Issue
Block a user