Skip to content

Feature/token auth rbac and user crud#4

Open
lertrel wants to merge 4 commits into
mate-academy:mainfrom
lertrel:feature/token-auth-rbac-and-user-crud
Open

Feature/token auth rbac and user crud#4
lertrel wants to merge 4 commits into
mate-academy:mainfrom
lertrel:feature/token-auth-rbac-and-user-crud

Conversation

@lertrel

@lertrel lertrel commented Jun 24, 2026

Copy link
Copy Markdown

No description provided.

Ton and others added 4 commits June 21, 2026 23:11
Introduces a /tokens resource for minting and revoking bearer tokens,
and gates all /users endpoints behind Authorization: Bearer authentication.

New endpoints:
  POST   /tokens        — create a bearer token (open, bootstrapping)
  DELETE /tokens/:id    — revoke a token by id; idempotent (always 204)

Auth behaviour:
  - GET/POST/PUT /users now require a valid Authorization: Bearer header
  - GET /health remains open
  - requireToken is mounted as a global default after the open routes, so
    any future router added below it is protected automatically

Implementation details:
  - middleware/auth.js  — requireToken: case-insensitive scheme check,
                          trims extracted value to tolerate extra whitespace
  - routes/tokens.js    — NaN guard on DELETE id (400 before store call);
                          idempotent DELETE returns 204 whether or not the
                          token existed
  - db/store.js         — token collection mirrors users pattern; uses ?? null
                          so empty-string names are preserved; listTokens
                          removed (was dead code)
  - tests/tokens.test.js — covers create, revoke, idempotent re-revoke,
                            never-existing id (204), and non-numeric id (400)
  - tests/users.test.js  — beforeEach mints a token; all /users requests carry
                            the Bearer header; asserts 401 without a token

Seed data extended to 4 users (Grace Hopper id:3, Linus Torvalds id:4);
nextId bumped to 5 accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Input validation:
  - lib/parseId.js (new) — shared helper; rejects NaN, floats, negatives,
    and non-numerics in one check (Number.isInteger && >= 1)
  - routes/tokens.js — use parseId for DELETE /:id; req.body ?? {} on POST
    so a non-JSON body never crashes the handler
  - routes/users.js — use parseId for GET/:id and PUT/:id; req.body ?? {}
    on POST and PUT for the same reason
  - db/store.js — revokeToken no longer returns a boolean; the route is
    idempotent and no caller used the return value
  - package.json — extend lint glob to include lib/

RBAC:
  - middleware/requireAdmin.js (new) — 403 if req.token.role !== 'admin'
  - db/store.js — createToken gains role (default 'client') and value params
  - routes/tokens.js — DELETE /:id now chains requireToken + requireAdmin;
    POST always creates role:'client' regardless of request body
  - server.js — seeds an admin token at startup; logs it once if ADMIN_TOKEN
    env var is not set

Tests:
  - tokens.test.js — admin/client token setup in beforeEach; new tests for
    fractional id (400), non-JSON POST (201 not crash), role-in-body ignored,
    401 without token, 403 for client token
  - users.test.js — new tests for GET/PUT with non-numeric id (400)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Completes full CRUD for the users resource. Mirrors the token revocation
pattern: idempotent (204 whether or not the user existed), id validated
through the shared parseId helper.

  - db/store.js — deleteUser(id): splice by index, no return value
  - routes/users.js — DELETE /:id: parseId guard then store.deleteUser
  - tests/users.test.js — three cases: removes and confirms 404, idempotent
    on missing id, 400 on non-numeric id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Skill (.claude/skills/route-convention-check/SKILL.md):
  Proactive skill that auto-triggers when a route handler is added or
  changed. Checks auth middleware placement, parseId usage, error response
  shape, and store-only data access against project conventions.

Command (.claude/commands/test.md):
  /test slash command — runs npm test and reports a structured pass/fail
  summary with failing test names and assertion errors if any.

MCP servers (.mcp.json):
  - fetch (uvx mcp-server-fetch): lets Claude pull live docs during dev
  - memory (npx @modelcontextprotocol/server-memory): persists project
    context (decisions, conventions) across sessions. Note: MEMORY_FILE_PATH
    is set to an absolute local path and needs adjustment on other machines.

Notes (NOTES.md):
  Course notes documenting the MCP server setup, skill, command, hook, and
  headless run from Project 3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant