unit PM.Handler.Audit; (* POST /audit body {action, site} -> {ok:true} Light-weight endpoint that lets the JS layer append an entry to audit_log without going through the full entries pipeline. Used by the autofill feature to record which site was filled (action = "autofill:"). The bearer token identifies the user — no data beyond the action string is stored. *) interface implementation uses System.SysUtils, System.JSON, IdCustomHTTPServer, PM.Router, PM.JSON, PM.Session, PM.Audit; function GetClientIP(ARequest: TIdHTTPRequestInfo): string; begin Result := ARequest.RemoteIP; if Result = '' then Result := '127.0.0.1'; end; procedure HandlePostAudit(ARequest: TIdHTTPRequestInfo; AResponse: TIdHTTPResponseInfo; const AParams: TArray); var LUserId: Integer; LBody: TJSONObject; LAction, LSite: string; begin LUserId := Authenticate(ARequest, AResponse); RequireCSRF(ARequest, AResponse, LUserId); LBody := TJSONHelper.ReadBody(ARequest); try LAction := LBody.GetValue('action', ''); LSite := LBody.GetValue('site', ''); finally LBody.Free; end; if LAction = '' then begin TJSONHelper.SendError(AResponse, 400, 'action required'); Exit; end; // Keep the log compact: "autofill:github.com" rather than repeating // structured columns we don't have in the current schema. if LSite <> '' then LAction := LAction + ':' + LSite; LogAudit(LUserId, LAction, GetClientIP(ARequest)); TJSONHelper.SendOK(AResponse); end; initialization Router.Register('POST', '/audit', HandlePostAudit); end.