| @@ -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.