Files

7.1 KiB

fid REST API (v1)

Token-based JSON REST API for the fid inventory app, modeled after ppb/archive's API. Base URL:

https://fid.fhi.mpg.de/api/v1/<command>[/<id>]

Requests are POST with a JSON body (except where noted GET also works). Responses are always JSON with a success field (1 or 0); on failure there's also an error field. HTTP status codes are set as well (200 on success, 401/403/404/503 on the various failure cases) but success is the authoritative field to check.

Unlike the archive API, fid's device table already has descriptive column names (f_name, l_type, f_mac, ...) instead of a generic f0..f31 scheme, so there's a single get/fields shape — no getraw equivalent needed. fid also has no per-entry file attachments, so there are no upload/download endpoints.

Authentication

login performs an LDAP simple bind against 141.14.132.180:389 (uid=<user>,ou=people,dc=ppb,dc=rz-berlin,dc=mpg,dc=de) — the same mechanism the web login uses. The user must also exist in the local user table (for role/grp), same requirement as the web UI. Tokens are random 64-char hex strings stored in the api_token table with a 24h expiry.

login

curl -s -X POST -d '{"user":"USER","password":"PASSWORD"}' https://fid.fhi.mpg.de/api/v1/login

{ "success": 1, "token": "64-char-hex-token" }

renew

Issues a new token and invalidates the old one.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/renew

{ "success": 1, "token": "new-64-char-hex-token" }

Every other endpoint below requires "token":"TOKEN" in the request body.

Reading

list

Ids of all active (non-deleted) devices.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/list

{ "success": 1, "ids": [19, 21, 27, "..."] }

Optionally pass "columns":["f_name","f_ip",...] to get partial device records instead of bare ids — only the requested columns (plus id) are selected, so a caller building a table over every device doesn't have to pull all ~30 columns for each row:

curl -s -X POST -d '{"token":"TOKEN","columns":["f_name","f_ip"]}' https://fid.fhi.mpg.de/api/v1/list

{ "success": 1, "devices": [{"id":"19","f_name":"twilightzone","f_ip":"141.14.142.157"}, "..."] }

get

Full device record(s). Ids as a comma-separated list in the URL, or as an array in the body.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/get/40

curl -s -X POST -d '{"token":"TOKEN","ids":[40,41]}' https://fid.fhi.mpg.de/api/v1/get

{
  "success": 1,
  "devices": [
    {
      "id": "40",
      "user": "ropers",
      "grp": "ppb",
      "rm": "0",
      "f_name": "buntfink",
      "l_dep": "3",
      "f_os": "None",
      "f_mac": "00:04:00:9a:87:10",
      "...": "... (all device columns)"
    }
  ]
}

Same substring/regex search across text fields as the web UI's search box. Also accepts the same optional "columns":[...] as list, returning matching devices instead of bare ids.

curl -s -X POST -d '{"token":"TOKEN","key":"mina"}' https://fid.fhi.mpg.de/api/v1/search

{ "success": 1, "ids": [104, 244, 1723] }

types / departments

Value lists for the l_type / l_dep select fields.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/types

{ "success": 1, "types": [{"id":"1","name":"Desktop"}, {"id":"2","name":"Server"}] }

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/departments

{ "success": 1, "departments": [{"id":"1","name":"AC"}, {"id":"2","name":"CP"}] }

vlans

Value list for the l_vlan select field.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/vlans

{ "success": 1, "vlans": [{"id":"10","name":"FHI"}, {"id":"400","name":"GNZ"}] }

fields

Column metadata for the device table (name, input type, whether it's mandatory on new). Key order in the JSON object is the DB column order (same as the web UI's edit form) - the CLI's interactive form relies on it for field layout.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/fields

{
  "success": 1,
  "fields": {
    "f_name": { "name": "Name", "type": "text", "mandatory": 1 },
    "l_dep":  { "name": "Department", "type": "select", "mandatory": 1 },
    "c_selfadmin": { "name": "Self Admin", "type": "checkbox", "mandatory": 0 }
  }
}

Writing

Requires role <= 2 (same restriction edit.php applies to the whole app for the web UI). Field validation mirrors edit.php: on new, f_name, l_dep, f_os and f_contact are mandatory; f_ip (must be in 172.16.0.0/12, 141.14.128.0/20, 10.0.0.0/8 or 141.14.248.0/23), f_mac (aa:bb:cc:dd:ee:ff) and f_acquisition (mm.dd.yyyy) are format- checked when present. edit only validates/updates the fields you actually send (partial update), unlike the web form which always resubmits every field.

new

curl -s -X POST -d '{"token":"TOKEN","f_name":"newhost","l_dep":1,"f_os":"Linux","f_contact":"Mike"}' https://fid.fhi.mpg.de/api/v1/new

{ "success": 1, "id": 4701 }

Ownership (user/grp columns) defaults to the logged-in user; only role 0 (admin) can set them explicitly via "user":"...","grp":"...".

edit

curl -s -X POST -d '{"token":"TOKEN","f_comment":"replaced disk"}' https://fid.fhi.mpg.de/api/v1/edit/4701

{ "success": 1, "id": 4701 }

Same access rule as the web UI's chkaccess(): role 0 can edit anything, role 1 anything in their own user/group, role 2 only their own entries, role >2 nothing.

delete / recover

Soft-delete (sets rm=1) / undelete (rm=0) — same as the web UI, no hard delete via the API.

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/delete/4701

curl -s -X POST -d '{"token":"TOKEN"}' https://fid.fhi.mpg.de/api/v1/recover/4701

{ "success": 1, "id": 4701 }

Implementation notes

  • Router: Apache RewriteRule in config/fid-apache.conf maps /api/v1/<cmd>[/<id>] to /api/v1.php?cmd=<cmd>&idparam=<id>.
  • Handler: api/v1.php — self-contained, uses mysqli with prepared statements throughout (does not use the app's legacy mysql_* compat shim, despite that being auto-prepended for the rest of the app).
  • Tokens live in a new api_token table (token, user, role, grp, created, expires) in the fid database.
  • Not implemented / known limitations: no rate limiting, no per-token scoping beyond role/user/grp, no audit log of API writes, get/list only return active (rm=0) devices (no way to fetch deleted ones via the API yet).
  • The device table's text is a mix of genuine latin1 bytes and (from years of inconsistent form submissions) UTF-8 bytes stored raw in a latin1 column — json_encode() requires valid UTF-8 and silently returns false (i.e. an empty response body, no error) if it isn't. respond() runs every string through fix_utf8() first, which leaves already-valid UTF-8 alone and reinterprets everything else as latin1. Found via list with columns returning an empty body for the full (~3000 row) result set.