Files
fivenode_go/app/api/device-status.prg
Charles KWON OhJun ed956a1504 revert: drop AP_RPUTS single-arg patch and fn_HGet renames
Both workarounds existed because Five was missing two features that
just landed upstream:

  Five 7629f95 (variadic PValue) makes FUNCTION foo(...) / PValue()
  actually return the caller's variadic args instead of the caller's
  first LOCAL slot. AP_RPUTS / AP_ECHO can go back to their `( ... )`
  signature now.

  Five f3e0ffe (file-local STATIC FUNCTION) gives each .prg its own
  namespace for `STATIC FUNCTION name`, so the seven duplicate
  `STATIC FUNCTION fn_HGet` definitions across labdb's api/*.prg
  files no longer collide. The sed-renamed unique names can revert
  to the upstream definitions.

Files

  app/bridge/bridge_request.prg     ← cp from fivenode/native/
  app/api/{device-status,record-detail,records-list,session-detail,
           session-stats,sessions-list,session-export}.prg
                                    ← cp from fivenode/labdb/api/

fivenode-upstream is now byte-identical to fivenode_go's app/ copy
of those files. No more "// fivenode_go patch" comments, no more
file-prefix renames.

Verified end-to-end against the same live postgres@16 cluster:
  /api/admin-stats.prg    -> {"active_sessions":1,"devices":2,...}
  /api/sessions-list.prg  -> 2 rows w/ full session data
  /api/admin-devices.prg  -> 2 devices w/ api_key, created_at
  /api/hello.prg          -> hello (unchanged)
  /                       -> 200 text/html (static)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 17:36:14 +09:00

72 lines
2.3 KiB
Plaintext

// api/device-status.prg — Format device status response
//
// ctx:
// row (JSON) — device row from server.js (or empty hash if not found)
// key_format_valid — "1" if api_key starts with xbk_, "0" otherwise
//
// Logic:
// - row empty + valid format → 404 DEVICE_DELETED
// - row empty + invalid format → 401 INVALID_API_KEY
// - row exists → 200 with status info (active/pending/revoked)
//
// Copyright (c) 2026 Charles KWON OhJun
FUNCTION Main()
LOCAL hRow, cStatus, hOut, lValid
hRow := hb_jsonDecode(ctx_get("row", "{}"))
lValid := ctx_get("key_format_valid", "0") == "1"
IF ! HB_ISHASH(hRow) .OR. Empty(hRow) .OR. ! hb_HHasKey(hRow, "device_id")
// No matching device
IF lValid
AP_JSONRESPONSE({ ;
"error" => { ;
"code" => "DEVICE_DELETED", ;
"message" => "This device has been removed from the server. Please re-register.", ;
"status" => 404 ;
} ;
}, 404)
ELSE
AP_JSONRESPONSE({ ;
"error" => { ;
"code" => "INVALID_API_KEY", ;
"message" => "API key is invalid or malformed.", ;
"status" => 401 ;
} ;
}, 401)
ENDIF
RETURN NIL
ENDIF
cStatus := fn_HGet(hRow, "status", "pending")
hOut := { ;
"deviceId" => fn_HGet(hRow, "device_id"), ;
"status" => cStatus, ;
"deviceName" => fn_HGet(hRow, "device_name"), ;
"appName" => fn_HGet(hRow, "app_name"), ;
"registeredAt" => fn_HGet(hRow, "created_at"), ;
"approvedAt" => fn_HGet(hRow, "approved_at"), ;
"revokedAt" => fn_HGet(hRow, "revoked_at"), ;
"lastSeenAt" => fn_HGet(hRow, "last_seen_at") ;
}
IF cStatus == "active"
hOut[ "sessionCount" ] := fn_HGet(hRow, "session_count", 0)
ELSEIF cStatus == "pending"
hOut[ "message" ] := "Awaiting administrator approval."
ELSEIF cStatus == "revoked"
hOut[ "message" ] := "Device has been revoked. Contact administrator."
ENDIF
AP_JSONRESPONSE(hOut)
RETURN NIL
STATIC FUNCTION fn_HGet(h, k, xDefault)
IF xDefault == NIL ; xDefault := "" ; ENDIF
IF HB_ISHASH(h) .AND. hb_HHasKey(h, k) .AND. h[k] != NIL
RETURN h[k]
ENDIF
RETURN xDefault