Class: KairosMcp::Admin::Router
- Inherits:
-
Object
- Object
- KairosMcp::Admin::Router
- Includes:
- Helpers
- Defined in:
- lib/kairos_mcp/admin/router.rb
Overview
Router: Handles all /admin/* requests for the admin UI
Provides lightweight session-based authentication (using existing Bearer tokens), CSRF protection, and delegates to page-specific handlers.
Pages:
GET /admin/login - Login form
POST /admin/login - Authenticate with Bearer token
GET /admin/logout - Clear session
GET /admin - Dashboard
GET /admin/tokens - Token management
POST /admin/tokens/* - Token operations (htmx)
GET /admin/chain - Chain explorer
POST /admin/chain/* - Chain operations (htmx)
GET /admin/skills - Skills viewer
GET /admin/knowledge - Knowledge viewer
GET /admin/config - Config viewer
GET /admin/static/* - Static files (CSS, JS)
Constant Summary
Constants included from Helpers
Helpers::SESSION_COOKIE, Helpers::SESSION_SECRET, Helpers::STATIC_DIR, Helpers::VIEWS_DIR
Instance Attribute Summary collapse
-
#authenticator ⇒ Object
readonly
Returns the value of attribute authenticator.
-
#token_store ⇒ Object
readonly
Returns the value of attribute token_store.
Instance Method Summary collapse
-
#call(env) ⇒ Array
Main entry point: route an admin request.
-
#initialize(token_store:, authenticator:) ⇒ Router
constructor
A new instance of Router.
Methods included from Helpers
#clear_session_cookie, #decode_session, #encode_session, #generate_csrf_token, #get_session, #h, #html_response, #parse_cookies, #parse_form_body, #parse_query, #redirect, #render, #render_layout, #render_partial, #serve_static, #session_cookie, #valid_csrf?
Constructor Details
#initialize(token_store:, authenticator:) ⇒ Router
Returns a new instance of Router.
34 35 36 37 38 |
# File 'lib/kairos_mcp/admin/router.rb', line 34 def initialize(token_store:, authenticator:) @token_store = token_store @authenticator = authenticator @flash = nil end |
Instance Attribute Details
#authenticator ⇒ Object (readonly)
Returns the value of attribute authenticator.
32 33 34 |
# File 'lib/kairos_mcp/admin/router.rb', line 32 def authenticator @authenticator end |
#token_store ⇒ Object (readonly)
Returns the value of attribute token_store.
32 33 34 |
# File 'lib/kairos_mcp/admin/router.rb', line 32 def token_store @token_store end |
Instance Method Details
#call(env) ⇒ Array
Main entry point: route an admin request
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/kairos_mcp/admin/router.rb', line 44 def call(env) method = env['REQUEST_METHOD'] path = env['PATH_INFO'] # Static files: no auth required if path.start_with?('/admin/static/') filename = path.sub('/admin/static/', '') return serve_static(filename) end # Login page: no auth required case [method, path] when ['GET', '/admin/login'] return handle_login_page(env) when ['POST', '/admin/login'] return handle_login(env) end # All other routes require authentication session = get_session(env) unless session && session[:token] return redirect('/admin/login') end # Verify token is still valid user_info = @token_store.verify(session[:token]) unless user_info return redirect_with_flash('/admin/login', 'Session expired. Please login again.') end # Verify owner role unless user_info[:role] == 'owner' return redirect_with_flash('/admin/login', 'Admin access requires owner role.') end @current_user = Protocol.apply_all_filters(user_info) @csrf_token = session[:csrf_token] # CSRF check for POST requests if method == 'POST' && !valid_csrf?(env, session) return html_response(403, render('layout', content: '<p>CSRF validation failed. Please try again.</p>')) end # Authenticated routes — set thread-scoped user context for PgBackend Thread.current[:kairos_user_context] = @current_user route(method, path, env) rescue StandardError => e $stderr.puts "[ADMIN ERROR] #{e.}" $stderr.puts e.backtrace.first(5).join("\n") html_response(500, render('_error', layout: true, error: e.)) ensure Thread.current[:kairos_user_context] = nil end |