From 31fc204ef20433afbae15226f0c27295902431f3 Mon Sep 17 00:00:00 2001 From: db123-test Date: Tue, 5 May 2026 17:44:52 +0330 Subject: [PATCH] refactor: rename entry field to ip across whitelist API Rename the `entry` field to `ip` throughout the whitelist API for clarity and consistency. This affects API request/response bodies, path parameters, OpenAPI spec, documentation, and database queries in the audit log endpoint. --- docs/api.md | 8 ++++---- docs/security.md | 2 +- openapi.yaml | 22 +++++++++------------- src/auth.go | 35 ++++++++++++++++------------------- src/db.go | 38 +++++++++++++++++++------------------- src/main.go | 2 +- 6 files changed, 50 insertions(+), 57 deletions(-) diff --git a/docs/api.md b/docs/api.md index 8d632fe..2d63d37 100644 --- a/docs/api.md +++ b/docs/api.md @@ -79,7 +79,7 @@ Add a permanent whitelisted IP or CIDR range. ```json { - "entry": "1.2.3.4" + "ip": "1.2.3.4" } ``` @@ -91,7 +91,7 @@ Add a permanent whitelisted IP or CIDR range. curl -X POST http://127.0.0.1:8080/api/whitelist/perm \ -H "Authorization: Bearer CHANGE_ME" \ -H "Content-Type: application/json" \ - -d '{"entry":"203.0.113.10"}' + -d '{"ip":"203.0.113.10"}' ``` ### GET /api/whitelist/perm/list @@ -112,7 +112,7 @@ List all currently active permanent whitelisted IPs. ```json [ { - "entry": "203.0.113.10" + "ip": "203.0.113.10" } ] ``` @@ -124,7 +124,7 @@ curl -X GET "http://127.0.0.1:8080/api/whitelist/perm/list?limit=50&offset=0" \ -H "Authorization: Bearer CHANGE_ME" ``` -### DELETE /api/whitelist/perm/{entry} +### DELETE /api/whitelist/perm/{ip} Remove a permanent whitelisted IP or CIDR range. diff --git a/docs/security.md b/docs/security.md index 7230181..56a5fac 100644 --- a/docs/security.md +++ b/docs/security.md @@ -41,7 +41,7 @@ All whitelist operations are logged to the `audit_log` table in SQLite. Each entry records: - `action` — what happened (`add_temp`, `delete_temp`, `add_perm`, `delete_perm`, `expire_temp`) -- `ip` or `cidr` — the affected IP or CIDR +- `ip` — the affected IP or CIDR range - `ttl_seconds` — for temp entries - `reason` — the reason provided - `api_client_ip` — the IP that made the API call (from NGINX `X-Real-IP`) diff --git a/openapi.yaml b/openapi.yaml index 68339ca..df28df4 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -191,9 +191,9 @@ paths: schema: type: object required: - - entry + - ip properties: - entry: + ip: type: string description: IP address or CIDR range to whitelist example: "203.0.113.10" @@ -201,16 +201,16 @@ paths: '204': description: Created '400': - description: Bad request — missing entry or invalid entry (must be valid IP or CIDR range) + description: Bad request — missing ip or invalid ip (must be valid IP or CIDR range) '401': description: Unauthorized — invalid API token '409': - description: Conflict — entry already exists + description: Conflict — ip already exists content: text/plain: schema: type: string - example: "entry already exists" + example: "ip already exists" '500': description: Internal error @@ -247,7 +247,7 @@ paths: items: type: object properties: - entry: + ip: type: string example: "203.0.113.10" '401': @@ -255,13 +255,13 @@ paths: '500': description: Internal error — database failure - /api/whitelist/perm/{entry}: + /api/whitelist/perm/{ip}: delete: summary: Remove a permanent whitelisted IP or CIDR description: Remove a permanent whitelisted IP address or CIDR range. operationId: deletePermWhitelist parameters: - - name: entry + - name: ip in: path required: true schema: @@ -271,7 +271,7 @@ paths: '204': description: Deleted '400': - description: Bad request — entry required + description: Bad request — ip required '401': description: Unauthorized — invalid API token '500': @@ -337,10 +337,6 @@ paths: type: string nullable: true example: "1.2.3.4" - cidr: - type: string - nullable: true - example: "10.0.0.0/24" ttl_seconds: type: integer nullable: true diff --git a/src/auth.go b/src/auth.go index c3584e4..97efe56 100644 --- a/src/auth.go +++ b/src/auth.go @@ -169,7 +169,7 @@ func logsHandler(cfg Config, db *sql.DB) http.HandlerFunc { return } - query := `SELECT timestamp, action, ip, cidr, ttl_seconds, reason, api_client_ip FROM audit_log` + query := `SELECT timestamp, action, entry, ttl_seconds, reason, api_client_ip FROM audit_log` var args []any filterAction := r.URL.Query().Get("action") @@ -218,9 +218,9 @@ func logsHandler(cfg Config, db *sql.DB) http.HandlerFunc { for rows.Next() { var ts time.Time var action, apiClientIP string - var ip, cidr, reason sql.NullString + var ip, reason sql.NullString var ttlSeconds sql.NullInt64 - if err := rows.Scan(&ts, &action, &ip, &cidr, &ttlSeconds, &reason, &apiClientIP); err != nil { + if err := rows.Scan(&ts, &action, &ip, &ttlSeconds, &reason, &apiClientIP); err != nil { continue } entry := map[string]interface{}{ @@ -232,9 +232,6 @@ func logsHandler(cfg Config, db *sql.DB) http.HandlerFunc { if ip.Valid { entry["ip"] = ip.String } - if cidr.Valid { - entry["cidr"] = cidr.String - } if ttlSeconds.Valid { entry["ttl_seconds"] = ttlSeconds.Int64 } @@ -252,29 +249,29 @@ func permWhitelistAddHandler(cfg Config, db *sql.DB) http.HandlerFunc { return } type request struct { - Entry string `json:"entry"` + IP string `json:"ip"` } var req request if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "bad request", http.StatusBadRequest) return } - if req.Entry == "" { - http.Error(w, "entry required", http.StatusBadRequest) + if req.IP == "" { + http.Error(w, "ip required", http.StatusBadRequest) return } - if !IsIP(req.Entry) && !IsCIDR(req.Entry) { - http.Error(w, "invalid entry (must be valid IP or CIDR range)", http.StatusBadRequest) + if !IsIP(req.IP) && !IsCIDR(req.IP) { + http.Error(w, "invalid ip (must be valid IP or CIDR range)", http.StatusBadRequest) return } - ok, err := AddPermanentEntry(db, req.Entry, getClientIP(r)) + ok, err := AddPermanentEntry(db, req.IP, getClientIP(r)) if err != nil { - slog.Error("failed to add perm entry", "error", err) + slog.Error("failed to add perm ip", "error", err) http.Error(w, "internal error", http.StatusInternalServerError) return } if !ok { - http.Error(w, "entry already exists", http.StatusConflict) + http.Error(w, "ip already exists", http.StatusConflict) return } w.WriteHeader(http.StatusNoContent) @@ -287,13 +284,13 @@ func permWhitelistDeleteHandler(cfg Config, db *sql.DB) http.HandlerFunc { http.Error(w, "unauthorized", http.StatusUnauthorized) return } - entry := r.PathValue("entry") - if entry == "" { - http.Error(w, "entry required", http.StatusBadRequest) + ip := r.PathValue("ip") + if ip == "" { + http.Error(w, "ip required", http.StatusBadRequest) return } - if err := DeletePermanentEntry(db, entry, getClientIP(r)); err != nil { - slog.Error("failed to delete perm entry", "error", err) + if err := DeletePermanentEntry(db, ip, getClientIP(r)); err != nil { + slog.Error("failed to delete perm ip", "error", err) http.Error(w, "internal error", http.StatusInternalServerError) return } diff --git a/src/db.go b/src/db.go index 079a1ab..8457113 100644 --- a/src/db.go +++ b/src/db.go @@ -24,7 +24,7 @@ func InitDB(dbPath string) (*sql.DB, error) { schema := ` CREATE TABLE IF NOT EXISTS perm_whitelist ( id INTEGER PRIMARY KEY AUTOINCREMENT, - entry TEXT NOT NULL UNIQUE, + ip TEXT NOT NULL UNIQUE, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); @@ -41,7 +41,7 @@ func InitDB(dbPath string) (*sql.DB, error) { id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, action TEXT NOT NULL, - ip TEXT, + entry TEXT, ttl_seconds INTEGER, reason TEXT, api_client_ip TEXT @@ -56,11 +56,11 @@ func InitDB(dbPath string) (*sql.DB, error) { } func AddPermanentEntry(db *sql.DB, entry, apiClientIP string) (bool, error) { - _, err := db.Exec(`INSERT INTO perm_whitelist(entry) VALUES(?)`, entry) + _, err := db.Exec(`INSERT INTO perm_whitelist(ip) VALUES(?)`, entry) if err != nil { if isUniqueConstraintError(err) { _, err = db.Exec(` - INSERT INTO audit_log(action, ip, api_client_ip) + INSERT INTO audit_log(action, entry, api_client_ip) VALUES('add_perm_duplicate', ?, ?) `, entry, apiClientIP) if err != nil { @@ -71,7 +71,7 @@ func AddPermanentEntry(db *sql.DB, entry, apiClientIP string) (bool, error) { return false, err } _, err = db.Exec(` - INSERT INTO audit_log(action, ip, api_client_ip) + INSERT INTO audit_log(action, entry, api_client_ip) VALUES('add_perm', ?, ?) `, entry, apiClientIP) if err != nil { @@ -83,13 +83,13 @@ func AddPermanentEntry(db *sql.DB, entry, apiClientIP string) (bool, error) { func DeletePermanentEntry(db *sql.DB, entry, apiClientIP string) error { _, err := db.Exec(` DELETE FROM perm_whitelist - WHERE entry = ? + WHERE ip = ? `, entry) if err != nil { return err } _, err = db.Exec(` - INSERT INTO audit_log(action, ip, api_client_ip) + INSERT INTO audit_log(action, entry, api_client_ip) VALUES('delete_perm', ?, ?) `, entry, apiClientIP) if err != nil { @@ -100,7 +100,7 @@ func DeletePermanentEntry(db *sql.DB, entry, apiClientIP string) error { func IsPermanentWhitelisted(db *sql.DB, ip string) (bool, error) { rows, err := db.Query(` - SELECT entry + SELECT ip FROM perm_whitelist `) if err != nil { @@ -135,7 +135,7 @@ func AddTempEntry(db *sql.DB, ip string, ttlSeconds int, reason, apiClientIP str return err } _, err = db.Exec(` - INSERT INTO audit_log(action, ip, ttl_seconds, reason, api_client_ip) + INSERT INTO audit_log(action, entry, ttl_seconds, reason, api_client_ip) VALUES('add_temp', ?, ?, ?, ?) `, ip, ttlSeconds, reason, apiClientIP) if err != nil { @@ -153,7 +153,7 @@ func DeleteTempEntry(db *sql.DB, ip, apiClientIP string) error { return err } _, err = db.Exec(` - INSERT INTO audit_log(action, ip, api_client_ip) + INSERT INTO audit_log(action, entry, api_client_ip) VALUES('delete_temp', ?, ?) `, ip, apiClientIP) if err != nil { @@ -209,7 +209,7 @@ func CleanupExpiredTemp(db *sql.DB) error { for _, ip := range expiredIPs { _, err = db.Exec(` - INSERT INTO audit_log(action, ip, reason) + INSERT INTO audit_log(action, entry, reason) VALUES('expire_temp', ?, ?) `, ip, reason) if err != nil { @@ -250,7 +250,7 @@ func ListTempEntries(db *sql.DB) ([]map[string]interface{}, error) { func ListPermEntries(db *sql.DB) ([]map[string]interface{}, error) { rows, err := db.Query(` - SELECT entry + SELECT ip FROM perm_whitelist ORDER BY created_at `) @@ -260,12 +260,12 @@ func ListPermEntries(db *sql.DB) ([]map[string]interface{}, error) { defer rows.Close() var list []map[string]interface{} = make([]map[string]interface{}, 0) for rows.Next() { - var entry string - if err := rows.Scan(&entry); err != nil { + var ip string + if err := rows.Scan(&ip); err != nil { continue } list = append(list, map[string]interface{}{ - "entry": entry, + "ip": ip, }) } return list, nil @@ -302,7 +302,7 @@ func ListTempEntriesPaginated(db *sql.DB, limit, offset int) ([]map[string]inter func ListPermEntriesPaginated(db *sql.DB, limit, offset int) ([]map[string]interface{}, error) { rows, err := db.Query(` - SELECT entry + SELECT ip FROM perm_whitelist ORDER BY created_at LIMIT ? OFFSET ? @@ -313,12 +313,12 @@ func ListPermEntriesPaginated(db *sql.DB, limit, offset int) ([]map[string]inter defer rows.Close() var list []map[string]interface{} = make([]map[string]interface{}, 0) for rows.Next() { - var entry string - if err := rows.Scan(&entry); err != nil { + var ip string + if err := rows.Scan(&ip); err != nil { continue } list = append(list, map[string]interface{}{ - "entry": entry, + "ip": ip, }) } return list, nil diff --git a/src/main.go b/src/main.go index 7f5f834..bced388 100644 --- a/src/main.go +++ b/src/main.go @@ -38,7 +38,7 @@ func main() { mux.HandleFunc("/api/whitelist/temp/{ip}", whitelistDeleteHandler(cfg, db)) mux.HandleFunc("/api/whitelist/perm", permWhitelistAddHandler(cfg, db)) mux.HandleFunc("/api/whitelist/perm/list", permWhitelistListHandler(cfg, db)) - mux.HandleFunc("/api/whitelist/perm/{entry}", permWhitelistDeleteHandler(cfg, db)) + mux.HandleFunc("/api/whitelist/perm/{ip}", permWhitelistDeleteHandler(cfg, db)) mux.HandleFunc("/api/logs", logsHandler(cfg, db)) mux.HandleFunc("/status", statusHandler(db))