--- applyTo: "Fuchs/Controllers/**,Fuchs/code/**" --- # IntranetController Instructions ## Overview The Fuchs intranet **is** the entire website, served from `/`. There is a single MVC controller, `IntranetController`, split into **partial files** by domain. There are no areas. ## Routing | Route | Action | Purpose | |-------|--------|---------| | `/{fn?}/{id?}/{code?}` | `Index` | Returns the SPA shell view `intranet`. `[AllowAnonymous]`. | | `/do/{fn?}/{id?}/{code?}` | `Do` | Central API dispatcher (GET + POST). `[AllowAnonymous]`, gated internally. | ## Partial File Layout Each partial lives in `Fuchs/Controllers/` and maps to a VB original under `Fuchs/code/`: | Partial | Domain | Dispatch entry | |---------|--------|----------------| | `IntranetController.cs` | Core: routing, auth, login/logout, account, MFR | `Do(...)` switch | | `IntranetController.Invoices.cs` / `.Invoices2.cs` | Invoices | `Do_Process_Invoices` | | `IntranetController.Reminder.cs` | Reminders | `Do_Process_Reminder` | | `IntranetController.Requests.cs` | Requests | `Do_Process_Requests` | | `IntranetController.Reports.cs` | Reports | `Do_Process_Reports` | | `IntranetController.Banking.cs` | Banking (MT940) | `Do_Process_Bankings` | ## Dispatcher Pattern - `Do(...)` normalizes `fn`/`id`/`code` (lowercase `fn`, null-coalesce others) then routes via a `switch` expression to `Do_Process_*` helpers or inline `Handle*` methods. - Each domain handler is itself a `switch` on `id` (the sub-function) returning an `IActionResult`. - Wrap the whole dispatch in a single `try/catch`; log via `_intranet.debug_log(...)` and return `ServerError()` on unhandled exceptions. Do not add per-case try/catch unless a case needs special recovery. ## Authentication Gate - The unauthenticated allow-list logic in `Do(...)` must keep its braces: unauthenticated users are rejected with `Unauthorized401()` **only** when the function is not in `_allowedNonAuth`, not `login`/`logout`, and not in `_allowedGet` (checked as both `fn` and `fn|id`). - Add new anonymous endpoints by extending `_allowedNonAuth` (full-anonymous) or `_allowedGet` (read-only GET links), never by removing the gate. ## Conventions - Use the `StdParamlist(...)` helpers to build `SqlParameter` lists; they pre-populate `@authuser` from `UserAccountID`. - Use `SqlOpt(fn, id, code)` to pass `FIS_SQLOptions` to OCORE SQL helpers. - Use `DbSec` (`_intranet.GetDbSecurity(UserAccountID)`) for the `Security:` argument on SQL calls. - Return JSON via the OCORE `JSONAsync(...)` helper, not `Json(...)`. - Use the status helpers `Unauthorized401()`, `BadRequest400()`, `ServerError(...)` rather than raw `StatusCode(...)`. - All controller actions that perform I/O must be `async Task`.