# Agents Guide — RouteKit Classic ASP / Keycloak Test ## What this project is A Classic ASP MVC web application running on IIS (Windows). It uses the **RouteKit** framework (front-controller pattern) with Keycloak OpenID Connect for authentication. The database is Microsoft Access (`.accdb`). There is no Node, npm, or build step — everything is server-side VBScript served by IIS. --- ## Project layout ``` public/ IIS site root — point IIS here Default.asp Front controller and route table web.config App settings, URL rewrite rules core/ Framework internals — do not modify autoload_core.asp mvc.asp router.wsc lib.*.asp Core libraries (see below) app/ controllers/ Controller classes (one per feature area) views/ View partials (folders match controller name) shared/ Header, footer, layout partials models/ POBO (plain-old business objects) repositories/ Data access classes db/ migrations/ Sequential migration scripts webdata.accdb Access database tests/ Dev-only aspunit test harness (separate IIS app) scripts/ VBScript code generators ``` --- ## Core libraries (core/lib.*.asp) | File | Purpose | |---|---| | `lib.Keycloak.asp` | OpenID Connect / Keycloak auth helper | | `lib.Routes.asp` | Route registration and URL helpers | | `lib.ControllerRegistry.asp` | Controller whitelist (security) | | `lib.DAL.asp` | Database access layer | | `lib.Data.asp` | Data helpers | | `lib.Collections.asp` | Dictionary/list helpers | | `lib.Enumerable.asp` | Collection iteration helpers | | `lib.Validations.asp` | Input validation | | `lib.Flash.asp` | Flash message helpers | | `lib.FormCache.asp` | Form value re-population | | `lib.HTML.asp` | HTML rendering helpers | | `lib.HTML.Security.asp` | XSS escaping (`H()` function) | | `lib.Strings.asp` | String utilities | | `lib.Automapper.asp` | Object mapping helpers | | `lib.ErrorHandler.asp` | Error handling | | `lib.Migrations.asp` | Migration runner | | `lib.json.asp` | JSON parsing/serialization | | `lib.Upload.asp` | File upload helper | | `lib.CDOEmail.asp` | Email via CDO | | `lib.ad.auth.asp` | Active Directory auth | | `lib.crypto.helper.asp` | Crypto utilities | --- ## Routes Defined in [public/Default.asp](public/Default.asp): | Method | Path | Controller | Action | |---|---|---|---| | GET | `/` | HomeController | Index | | GET | `/home` | HomeController | Index | | GET | `/auth/login` | AuthController | Login | | GET | `/auth/callback` | AuthController | Callback | | GET | `/auth/logout` | AuthController | Logout | | GET | `/404` | ErrorController | NotFound | All requests are rewritten through `Default.asp` by the IIS URL Rewrite rule. Static assets (`css/`, `js/`, `images/`, `favicon.ico`) bypass the rewrite. --- ## Configuration (public/web.config appSettings) | Key | Description | |---|---| | `ConnectionString` | ACE OLEDB path to `webdata.accdb` | | `Environment` | `Development`, `Staging`, or `Production` | | `KeycloakBaseUrl` | Keycloak server base URL (no `/realms/...`) | | `KeycloakRealm` | Keycloak realm name | | `KeycloakClientId` | Client ID | | `KeycloakClientSecret` | Client secret — never commit real values | | `KeycloakRedirectUri` | Absolute callback URL, e.g. `http://localhost:8080/auth/callback` | | `KeycloakLogoutRedirectUri` | Post-logout redirect URL | | `KeycloakScope` | OIDC scopes (default: `openid profile email`) | | `KeycloakEnableLogging` | `true`/`false` — diagnostic log for auth failures | | `KeycloakLogPath` | Path to Keycloak log file | | `EnableErrorLogging` | `true`/`false` | | `ErrorLogPath` | Path to error log file | --- ## Authentication (Keycloak) The helper in `core/lib.Keycloak.asp` implements the OpenID Connect authorization-code flow. **Key functions:** ```vbscript KeycloakLogin() ' Redirect to Keycloak KeycloakHandleCallback() ' Exchange code, store tokens — returns True on success KeycloakIsLoggedIn() ' True if access token is in Session KeycloakCurrentUser() ' Returns userinfo dictionary KeycloakAccessToken() ' Raw access token string KeycloakRefreshToken() KeycloakIdToken() KeycloakTokenClaims(token) ' Decode JWT payload into dictionary KeycloakRequireLogin(returnToPath) ' Gate a page — redirects if not logged in KeycloakConsumePostLoginRedirectPath("/") ' Get and clear stored return path KeycloakHasRealmRole("admin") ' Role check against ID token KeycloakHasClientRole(clientId, role) KeycloakLogout("") ' Clear session and redirect to Keycloak logout ``` Session keys use the `Keycloak_` prefix. Tokens are stored in `Session`, not cookies. --- ## Adding a new feature — step by step ### 1. Migration ```bat cscript //nologo scripts\generateMigration.vbs create_my_table cscript //nologo scripts\runMigrations.vbs ``` ### 2. Model and repository ```bat cscript //nologo scripts\GenerateRepo.vbs /table:my_table /pk:id ``` Move generated files to `app/models/` and `app/repositories/`. ### 3. Controller ```bat cscript //nologo scripts\generateController.vbs MyController "Index;Show(id);Create;Store" ``` Move generated file to `app/controllers/`. ### 4. Wire it up 1. Register in [core/lib.ControllerRegistry.asp](core/lib.ControllerRegistry.asp): `RegisterController "mycontroller"` 2. Include in [app/controllers/autoload_controllers.asp](app/controllers/autoload_controllers.asp) 3. Add routes in [public/Default.asp](public/Default.asp) 4. Create views in `app/views/MyController/` --- ## Testing Tests live in `tests/` and run as a **separate IIS application** (never through the production `public/` root). - Framework: `tests/aspunit/` (vendored) - Runner: browse to `run-all.asp` in the test IIS app - Manifest: `tests/test-manifest.asp` — register new test pages here manually - Bootstrap: `tests/bootstrap.asp` — shared setup for all test pages Test tiers: | Folder | Use for | |---|---| | `tests/unit/` | Deterministic helper and registry tests | | `tests/component/` | Controlled controller/object tests | | `tests/integration/` | Router/dispatch smoke tests, config behavior, rendered-page capture | After changing `tests/web.config`, sync nested configs: ```bat cscript //nologo tests\sync-webconfigs.vbs ``` Or sync and open in one step: ```bat tests\run-tests.cmd ``` --- ## Requirements - Windows Server / Windows with IIS - Classic ASP enabled - IIS URL Rewrite module - Microsoft Access Database Engine (ACE OLEDB 12.0) - Keycloak server (for auth flows) --- ## Things to avoid - Do not modify files under `core/` — these are framework internals. - Do not add controllers without registering them in `ControllerRegistry` — the MVC dispatcher will reject unregistered names. - Do not commit real `KeycloakClientSecret` values — inject per environment. - Do not add test routes or test pages under `public/`. - Do not use the production `public/` IIS app to run tests. - Always use `H()` from `lib.HTML.Security.asp` when rendering user-supplied data to prevent XSS.