Skip to content

feat: add admin backend foundation (login, session, health)#641

Draft
Ferryx349 wants to merge 5 commits into
cameri:mainfrom
Ferryx349:ADMIN-CONSOLE-1
Draft

feat: add admin backend foundation (login, session, health)#641
Ferryx349 wants to merge 5 commits into
cameri:mainfrom
Ferryx349:ADMIN-CONSOLE-1

Conversation

@Ferryx349

@Ferryx349 Ferryx349 commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

Description

This is the groundwork for admin console backend with a disabled-by-default admin API. Currently with password login(will replace it with NIP-98 later). API also includes session management, and a protected health endpoint.

Related Issue

#631

Types of changes

  • Non-functional change (docs, style, minor refactor)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my code changes.
  • I added a changeset, or this is docs-only and I added an empty changeset.
  • All new and existing tests passed.
  • My code follows the code style of this project.

Signed-off-by: ABHAY PANDEY <pandeyabhay967@gmail.com>
@changeset-bot

changeset-bot Bot commented Jun 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 92516e3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
nostream Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Ferryx349 Ferryx349 marked this pull request as draft June 7, 2026 08:18
Comment thread src/routes/admin/index.ts Fixed
Comment thread src/routes/admin/index.ts Fixed
@coveralls

coveralls commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 67.248% (+0.3%) from 66.977% — Ferryx349:ADMIN-CONSOLE-1 into cameri:main

Ferryx349 added 4 commits June 8, 2026 23:00
Signed-off-by: ABHAY PANDEY <pandeyabhay967@gmail.com>
Signed-off-by: ABHAY PANDEY <pandeyabhay967@gmail.com>
Comment thread src/routes/admin/index.ts
router.use(rateLimiterMiddleware)

router.post('/login', adminLoginRateLimitMiddleware, json(), withController(createPostAdminLoginController))
router.get('/session', adminRateLimitMiddleware, requireAdminAuth, withController(createGetAdminSessionController))

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added rate limiting using the existing Redis-backed pattern (limits.admin & per-route middleware). CodeQL still warns because it doesn’t recognize our custom limiter, I believe it’s a false positive. @cameri wdyt?

Comment thread src/routes/admin/index.ts

router.post('/login', adminLoginRateLimitMiddleware, json(), withController(createPostAdminLoginController))
router.get('/session', adminRateLimitMiddleware, requireAdminAuth, withController(createGetAdminSessionController))
router.get('/health', adminRateLimitMiddleware, requireAdminAuth, withController(createGetAdminHealthController))
@Ferryx349 Ferryx349 marked this pull request as ready for review June 12, 2026 08:21
@Ferryx349 Ferryx349 requested review from cameri and Copilot June 16, 2026 04:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays the groundwork for an (optionally enabled) admin backend by introducing an /admin API surface with password-based login, signed sessions, and a protected health endpoint, along with supporting settings and unit tests.

Changes:

  • Add a disabled-by-default /admin router with /login, /session, and /health endpoints.
  • Introduce password auth provider + signed session token utilities, plus admin-specific rate limiting.
  • Extend settings/types and defaults to configure admin enablement, session TTL, and admin rate limits; add unit tests and changeset.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/unit/utils/admin-session.spec.ts Unit tests for session token creation/validation and request extraction.
test/unit/utils/admin-rate-limit.spec.ts Unit tests for admin/login rate-limiting behavior.
test/unit/routes/admin.spec.ts Router-level tests for disabled-by-default, login, and protected endpoints.
src/utils/admin-session.ts Signed session token generation/validation + extraction from headers/cookies.
src/utils/admin-rate-limit.ts Admin/login rate-limit helper using configured limits + IP whitelist.
src/utils/admin-password.ts Password hashing/verification helpers (scrypt + timing-safe compare).
src/utils/admin-health.ts Admin health snapshot collection (DB + Redis ping).
src/schemas/admin-login-schema.ts Zod schema for admin login request body.
src/routes/index.ts Mount /admin router into the main routing table.
src/routes/admin/index.ts Admin router implementation: enabled-gate, login/session/health wiring.
src/handlers/request-handlers/admin-rate-limit-middleware.ts Express middlewares for admin and login rate limiting.
src/factories/controllers/post-admin-login-controller-factory.ts Factory wiring for login controller.
src/factories/controllers/get-admin-session-controller-factory.ts Factory wiring for session controller.
src/factories/controllers/get-admin-health-controller-factory.ts Factory wiring for health controller.
src/factories/admin-auth-provider-factory.ts Factory for selecting/admin auth provider (currently password-based).
src/controllers/admin/post-login-controller.ts Controller delegating login to auth provider.
src/controllers/admin/get-session-controller.ts Controller returning session status/expiry.
src/controllers/admin/get-health-controller.ts Controller returning admin health snapshot.
src/admin/password-admin-auth-provider.ts Password auth provider: login + cookie issuance + request auth checks.
src/@types/settings.ts Add admin settings and limits.admin typing.
src/@types/admin.ts Define IAdminAuthProvider interface.
resources/default-settings.yaml Add default admin settings and admin rate-limit defaults.
.changeset/admin-console-phase-1.md Changeset entry for the new admin API foundation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +41
const currentSettings = this.settings()
const ttl = currentSettings.admin?.sessionTtlSeconds ?? DEFAULT_SESSION_TTL_SECONDS
const expiresAt = Math.floor(Date.now() / 1000) + ttl
const token = createAdminSessionToken(expiresAt)

response
.status(200)
.setHeader('content-type', 'application/json')
.setHeader('Set-Cookie', `admin_session=${token}; Path=/admin; HttpOnly; SameSite=Strict; Max-Age=${ttl}`)
.send(JSON.stringify({ authenticated: true, expiresAt }))
Comment on lines +22 to +25
if (validation.error) {
response.status(400).setHeader('content-type', 'application/json').send(JSON.stringify({ error: 'Invalid request' }))
return
}
Comment on lines +27 to +30
if (!this.verifyPassword(validation.value.password)) {
response.status(401).setHeader('content-type', 'application/json').send(JSON.stringify({ error: 'Unauthorized' }))
return
}
Comment on lines +9 to +21
public async handleRequest(request: Request, response: Response): Promise<void> {
if (!this.authProvider.isRequestAuthenticated(request)) {
response.status(401).setHeader('content-type', 'application/json').send(JSON.stringify({ error: 'Unauthorized' }))
return
}

response.status(200).setHeader('content-type', 'application/json').send(
JSON.stringify({
authenticated: true,
expiresAt: this.authProvider.getSessionExpiresAt(request),
}),
)
}
Comment thread src/routes/admin/index.ts
Comment on lines +27 to +34
const requireAdminAuth = (request: Request, response: Response, next: NextFunction) => {
if (!createAdminAuthProvider().isRequestAuthenticated(request)) {
response.status(401).setHeader('content-type', 'application/json').send(JSON.stringify({ error: 'Unauthorized' }))
return
}

next()
}
Comment on lines +7 to +9
const sendTooManyRequests = (response: Response) => {
response.status(429).setHeader('content-type', 'application/json').send(JSON.stringify({ error: 'Too many requests' }))
}
@Ferryx349 Ferryx349 marked this pull request as draft June 16, 2026 18:03
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.

4 participants