| @@ -0,0 +1,204 @@ | |||
| # 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. | |||
Powered by TurnKey Linux.