Abuse Registration API POC

A stripped-down, in-memory API proof-of-concept. It keeps the important authentication shape from the original API while removing backend/database business logic.

The demo data is synthetic, stored in memory, and reset to the base dataset every 10 minutes. The base dataset contains 546 rows with registered_at dates from 1988 through 1991.

The HTML template, CSS, JavaScript, and favicon are embedded with Go embed. A built binary can be copied and run by itself; it does not need a neighboring static/, templates/, or favicon.ico file.

The JSON model is intentionally small:

{
  "id": "bb8d39a6-8fef-48af-9f9c-27a41c8f8baf",
  "registered_at": "1989-04-13T15:22:00Z",
  "gender": "female",
  "location": "Tórshavn",
  "abuse_type": "psychological",
  "status": "new"
}

id is generated by the server as a UUID. registered_at defaults to time.Now().UTC() when omitted on create or update.

Run locally

go run ./cmd/api

Or with Task:

task run

Then open:

http://localhost:8080/

Optional environment variables:

PORT=:9999 JWT_SECRET=change-me RESET_INTERVAL=10m go run ./cmd/api

Build

The Taskfile follows the FLÓ-style build version format:

version [<git-sha>-<branch>/<random-word>-<random-word>]. git is [clean|dirty].

build/words.txt is copied from the FLÓ website project.

task build
./bin/abuse-registration-poc

The resulting ./bin/abuse-registration-poc is self-contained. You can copy just that file to another Linux host and run it.

Project layout

The POC is intentionally small, but it is no longer a single-file prototype. The code is split in the same broad shape as the original API:

cmd/api/main.go                  binary entry point and flags
internal/config                  environment/default configuration
internal/models                  user and registration models plus allowed values
internal/auth                    static POC users replacing the auth database
internal/utils                   JWT and UUID helpers
internal/store                   in-memory registration store and reset logic
internal/handlers                HTTP handlers for login, health, page, and data
internal/middlewares             authentication, authorization, and CORS
internal/routes                  route registration and protected route wiring
internal/web/templates/index.html single HTML page template, embedded into the binary
internal/web/static              embedded CSS and browser JavaScript
internal/web/favicon.ico         embedded favicon

The real database/repository layer is deliberately replaced by internal/store, but the login response shape, raw Authorization JWT usage, role split, and route-permission middleware are kept close to the original API. Web assets are separate source files, but are compiled into the binary at build time.

Demo users

User Password Role Access
reader reader-password Reader Read protected endpoints
admin admin-password Admin Full create/read/update/delete and manual reset

Auth workflow

The site does not contain a login form and does not acquire a token in the browser. Use curl or PowerShell only.

Reader with curl:

READER_TOKEN=$(curl -s -X POST http://localhost:8080/login \
  -H 'Content-Type: application/json' \
  -d '{"user_name":"reader","password":"reader-password"}' \
  | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')

curl -s 'http://localhost:8080/api/v1/registrations?location=Tórshavn&limit=5' \
  -H "Authorization: $READER_TOKEN"

curl -s 'http://localhost:8080/api/v1/registrations?gender=female&abuse_type=psychological&status=open&limit=10' \
  -H "Authorization: $READER_TOKEN"

curl -s 'http://localhost:8080/api/v1/registrations?from=1989-01-01&to=1990-01-01&offset=20&limit=10' \
  -H "Authorization: $READER_TOKEN"

Reader with PowerShell:

$reader = Invoke-RestMethod `
  -Method Post `
  -Uri "http://localhost:8080/login" `
  -ContentType "application/json" `
  -Body '{"user_name":"reader","password":"reader-password"}'

$READER_TOKEN = $reader.token

Invoke-RestMethod `
  -Uri "http://localhost:8080/api/v1/registrations?location=Tórshavn&limit=5" `
  -Headers @{Authorization=$READER_TOKEN}

Admin workflow:

ADMIN_TOKEN=$(curl -s -X POST http://localhost:8080/login \
  -H 'Content-Type: application/json' \
  -d '{"user_name":"admin","password":"admin-password"}' \
  | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')

CREATED_ID=$(curl -s -X POST http://localhost:8080/api/v1/registrations \
  -H "Authorization: $ADMIN_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"gender":"unknown","location":"Tórshavn","abuse_type":"psychological","status":"new"}' \
  | sed -n 's/.*"id":"\([^"]*\)".*/\1/p')

curl -s -X PUT "http://localhost:8080/api/v1/registrations/$CREATED_ID" \
  -H "Authorization: $ADMIN_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"gender":"female","location":"Skopun","abuse_type":"digital","status":"referred"}'

curl -s -X DELETE "http://localhost:8080/api/v1/registrations/$CREATED_ID" \
  -H "Authorization: $ADMIN_TOKEN"

Endpoint behavior

Public:

  • GET / returns the single HTML page only. It does not embed all 546 registrations into the HTML.
  • GET /health
  • POST /login
  • GET /demo/registrations is the public demo snapshot used by the page JSON viewer.

Protected read:

  • GET /api/v1/categories
  • GET /api/v1/locations
  • GET /api/v1/registrations
  • GET /api/v1/registrations/{uuid}

Admin create/read/update/delete:

  • POST /api/v1/registrations
  • PUT /api/v1/registrations/{uuid}
  • DELETE /api/v1/registrations/{uuid}
  • POST /api/v1/reset

Unknown normal pages return a plain text message. Unknown /api/... routes return JSON.

Allowed values

Allowed gender values:

  • female
  • male
  • non_binary
  • unknown

Allowed abuse_type values:

  • physical
  • psychological
  • sexual
  • economic
  • material
  • digital
  • stalking
  • threats
  • honor_related

Allowed location values are fixed to the included Faroese town/village list in internal/models/registration.go. The browser filter dropdown uses this same list, and create/update rejects anything else.

Filters for GET /api/v1/registrations and /demo/registrations:

  • abuse_type
  • gender
  • location — exact match against the fixed list
  • status
  • from and to, matched against registered_at, accepting YYYY-MM-DD or RFC3339 values
  • search
  • limit
  • offset
S
Description
Web API til at heinta dátur frá backend, skrivað í Go. Hettar er eitt tonkt dømi um skráseting av ágangi til eitt API endpoint, bæði sum registreringstól og til seinni greining. Verður deploya sum bert 1 binary uttan nakrar dependencies ella runtime environment. Allur front end er embeddaður í binary. Verkætlanin brúkar bert Go standard library, onga eksterna dependency.
https://abuse-registration-api.poc.fló.fo
Readme
11 MiB
Languages
Go 57%
CSS 19.7%
HTML 16.6%
JavaScript 6.7%