diff --git a/.trellis/spec/backend/database-guidelines.md b/.trellis/spec/backend/database-guidelines.md index 493028b..fe3d779 100644 --- a/.trellis/spec/backend/database-guidelines.md +++ b/.trellis/spec/backend/database-guidelines.md @@ -7,28 +7,34 @@ ## Overview MySQL is the project data layer. DAO classes perform CRUD and query operations -against MySQL. Application source and schema files are not present yet, so table -and class names here are illustrative conventions for future implementation. +against MySQL. The initial scaffold schema exists at +`src/main/resources/db/schema.sql`; future module tables should follow the same +DDL style and DAO boundaries. --- ## Core Tables Use primary keys for every table and foreign keys for cross-entity integrity. -Illustrative table names: + +Implemented scaffold tables: + +- `roles`: administrator, librarian, reader, and future role definitions. +- `permissions`: permission definitions for protected actions. +- `role_permissions`: role-to-permission mapping. +- `users`: login accounts for administrator, librarian, and reader roles. +- `system_logs`: key operation logs, backup events, and exception traces. + +Planned module tables: - `books`: book information, inventory count/status, category reference. - `book_categories`: category names and descriptions. - `readers`: reader profiles, borrowing eligibility, contact information. - `borrow_records`: book-reader borrowing, return, renew, and overdue data. -- `administrators`: administrator/librarian login and profile data. -- `roles`: administrator, librarian, reader, and future role definitions. -- `permissions`: permission definitions for protected actions. -- `role_permissions`: role-to-permission mapping. - `system_logs`: key operation logs, backup events, and exception traces. -When schema files are introduced, record the actual path, DDL style, and exact -table names here. +Record new schema changes in `src/main/resources/db/schema.sql` and update this +spec with exact table names, key columns, and DAO/service contracts. --- @@ -42,8 +48,9 @@ table names here. inventory status. - Return entities or small query result objects to services, not HTML or servlet response objects. -- Keep MySQL connection details in a shared configuration/helper once one - exists, for example `JdbcUtil` plus `db.properties`. +- Keep MySQL connection details in `src/main/resources/db.properties` loaded by + `JdbcUtil`. The required keys are `db.driver`, `db.url`, `db.username`, and + `db.password`. --- @@ -66,6 +73,9 @@ table names here. - `borrow_records.reader_id` should reference `readers`. - Administrator-role and role-permission mapping tables should use foreign keys to preserve authorization integrity. +- `users.role_code` must reference `roles.code`. +- `role_permissions.role_code` must reference `roles.code`. +- `role_permissions.permission_code` must reference `permissions.code`. - Prefer explicit status columns/enums for inventory and borrowing states, then document the chosen values once code exists. @@ -83,6 +93,12 @@ table names here. - DAO signature: `UserDao.findActiveByUsername(String username)`. - Service signature: `AuthService.authenticate(String username, String password)`. - Permission signature: `AuthService.hasPermission(AuthenticatedUser user, Permission permission)`. +- Servlet route: `POST /login` with `username`, `password`, and optional + same-application `redirect`. +- Protected routes: `/dashboard`, `/admin/home`, `/librarian/home`, and + `/reader/home`. +- Session keys: `authenticatedUser`, `userRole`, and `userPermissions`. +- DB config keys: `db.driver`, `db.url`, `db.username`, and `db.password`. - Login tables: `roles`, `permissions`, `role_permissions`, `users`, and `system_logs`. @@ -93,9 +109,16 @@ table names here. `pbkdf2_sha256$iterations$saltBase64$hashBase64` format. - `users.role_code`: foreign key to `roles.code`; supported scaffold values are `administrator`, `librarian`, and `reader`. +- `users.active`: only rows with `active = 1` can authenticate. +- `roles.code`, `permissions.code`, and `role_permissions` must match the Java + `Role` and `Permission` enum codes exactly. +- `db.properties` must be local configuration. Commit + `db.properties.example`, but do not commit real credentials. - Session state stores an `AuthenticatedUser` snapshot, role code, and permission-code set. It must not store raw passwords or DAO result objects with password hashes. +- Login redirects must stay inside the current application context. Reject + values that do not start with a single `/` or that contain CR/LF characters. ### 4. Validation & Error Matrix @@ -103,6 +126,7 @@ table names here. `Username and password are required.` - Unknown user, inactive user, or hash mismatch -> request returns to login JSP with `Invalid username or password.` +- Unsafe or blank redirect -> ignore and route to `/dashboard` after success. - Missing `db.properties`, JDBC failure, or unsupported role code -> request returns a generic service-unavailable message and logs server-side details. - Authenticated user missing a required permission -> HTTP 403 and @@ -123,6 +147,8 @@ table names here. unavailable. - Run `PermissionPolicyCheck` or equivalent assertions for administrator, librarian, and reader permissions. +- Run `AuthServiceCheck` or equivalent assertions for required-field failures, + invalid credentials, success, permission checks, and DAO failure fallback. - When Maven/Tomcat dependencies are installed, run `mvn test` or `mvn clean package` to compile Servlet and JSP integration. @@ -131,11 +157,12 @@ table names here. #### Wrong ```java -// JSP or Servlet opens JDBC and checks passwords directly. +// JSP, Servlet, or session code opens JDBC and stores password_hash. ``` #### Correct ```text login.jsp -> LoginServlet -> AuthService -> UserDao -> users/roles tables +session -> AuthenticatedUser snapshot + role/permission codes only ``` diff --git a/.trellis/spec/backend/index.md b/.trellis/spec/backend/index.md index 93c2c66..6a697d4 100644 --- a/.trellis/spec/backend/index.md +++ b/.trellis/spec/backend/index.md @@ -7,10 +7,9 @@ ## Overview The developer has established the backend architecture as a B/S Java web -application using JSP + Servlet, MySQL, Tomcat, and IDEA. Application source -code does not exist in this workspace yet, so package names, class names, and -table names below are illustrative project conventions for future code rather -than references to existing files. +application using JSP + Servlet, MySQL, Tomcat, and IDEA. The initial scaffold +now exists under `src/main/`; remaining module names below describe conventions +for future feature work. Use a layered design: @@ -46,7 +45,7 @@ Before backend implementation, read: - `.trellis/spec/backend/error-handling.md` - `.trellis/spec/backend/logging-guidelines.md` - `.trellis/spec/backend/quality-guidelines.md` -- `.trellis/tasks/00-bootstrap-guidelines/research/project-requirements.md` +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md` --- @@ -67,9 +66,9 @@ Before backend implementation, read: ## Evidence -- `.trellis/tasks/00-bootstrap-guidelines/research/repo-scan.md` records that - no application source code exists yet. -- `.trellis/tasks/00-bootstrap-guidelines/research/project-requirements.md` +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/repo-scan.md` + records the initial pre-scaffold repo scan. +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md` records the developer-provided stack, architecture, modules, and data model. --- diff --git a/.trellis/spec/frontend/index.md b/.trellis/spec/frontend/index.md index 1bf736c..ad8d9e4 100644 --- a/.trellis/spec/frontend/index.md +++ b/.trellis/spec/frontend/index.md @@ -40,15 +40,15 @@ Before frontend implementation, read: - `.trellis/spec/frontend/state-management.md` - `.trellis/spec/frontend/type-safety.md` - `.trellis/spec/frontend/quality-guidelines.md` -- `.trellis/tasks/00-bootstrap-guidelines/research/project-requirements.md` +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md` --- ## Evidence -- `.trellis/tasks/00-bootstrap-guidelines/research/repo-scan.md` records that - no application source code exists yet. -- `.trellis/tasks/00-bootstrap-guidelines/research/project-requirements.md` +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/repo-scan.md` + records the initial pre-scaffold repo scan. +- `.trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md` records the developer-provided JSP presentation approach and image-to-JSP workflow. diff --git a/.trellis/spec/frontend/type-safety.md b/.trellis/spec/frontend/type-safety.md index 96e4117..9c8e545 100644 --- a/.trellis/spec/frontend/type-safety.md +++ b/.trellis/spec/frontend/type-safety.md @@ -23,6 +23,81 @@ rendering. --- +## Scenario: Login JSP And Servlet Contract + +### 1. Scope / Trigger + +- Trigger: the initial login scaffold introduced a cross-layer JSP/Servlet + contract for authentication screens and protected role pages. + +### 2. Signatures + +- Login form: `POST /login`. +- Request fields: `username`, `password`, and optional `redirect`. +- Login JSP request attributes: `errorMessage`, `username`, and `redirect`. +- Dashboard/role JSP session attributes: `authenticatedUser`, `userRole`, and + `userPermissions`. +- Role page request attributes: `areaName` and `areaSummary`. + +### 3. Contracts + +- `username` is trimmed in the Servlet before service authentication and may be + echoed back only through JSP escaping. +- `password` is submitted to the Servlet and must never be written to a request + attribute or session attribute. +- `redirect` must be a same-application path beginning with one `/`; invalid + values are ignored. +- JSPs render data with JSP EL/JSTL, not scriptlet Java. +- JSPs may read safe session snapshots, but they must not call DAOs or inspect + password hashes. + +### 4. Validation & Error Matrix + +- Missing `username` or `password` -> `errorMessage` displays + `Username and password are required.` +- Invalid credentials -> `errorMessage` displays + `Invalid username or password.` +- Login service unavailable -> `errorMessage` displays a generic unavailable + message; details stay in server logs. +- Missing authenticated session on protected pages -> redirect to `/login` with + a safe `redirect` value. +- Insufficient role permission -> render `/unauthorized`. + +### 5. Good/Base/Bad Cases + +- Good: failed login keeps the escaped username and never redisplays the + password. +- Base: dashboard reads `sessionScope.authenticatedUser.displayName` and + `sessionScope.userRole` only for display/navigation. +- Bad: JSP uses scriptlets, JDBC, or raw request parameters to decide + authentication. + +### 6. Tests Required + +- Scan JSPs to confirm there are no scriptlets beyond directives. +- Scan JSP/static assets to confirm no SQL/JDBC access exists in presentation + files. +- Run service-level auth checks for required fields, invalid credentials, + success, DAO fallback, and permission checks. +- When Maven/Tomcat is available, run a Servlet/JSP compile or package check. + +### 7. Wrong vs Correct + +#### Wrong + +```jsp +<%-- JSP checks request.getParameter("password") or runs SQL directly. --%> +``` + +#### Correct + +```text +login.jsp displays attributes set by LoginServlet; AuthService and UserDao own +authentication and database access. +``` + +--- + ## Validation - Parse and validate IDs, dates, enum/status values, and required strings in diff --git a/.trellis/tasks/04-27-start-coding/prd.md b/.trellis/tasks/04-27-start-coding/prd.md index 7987d60..06b35f6 100644 --- a/.trellis/tasks/04-27-start-coding/prd.md +++ b/.trellis/tasks/04-27-start-coding/prd.md @@ -39,14 +39,14 @@ Build the initial Java Web project scaffold and a login/permission skeleton for ## Acceptance Criteria (evolving) * [x] The selected first module or feature is explicitly confirmed. -* [ ] The implementation follows the documented JSP + Servlet + MySQL layered architecture. -* [ ] A fresh checkout has recognizable Java Web/Tomcat project structure and build configuration. -* [ ] Login page submits credentials to a Servlet controller and displays validation/authentication failures safely. -* [ ] Authentication logic is represented through service and DAO boundaries rather than embedded in JSP. -* [ ] Session state stores the authenticated user and role in a controlled way. -* [ ] Basic role/permission constants or helpers exist for administrator, librarian, and reader. -* [ ] SQL/schema guidance exists for the minimal account/role tables needed by login. -* [ ] Lint, type-check, compile, or equivalent project validation is run where available. +* [x] The implementation follows the documented JSP + Servlet + MySQL layered architecture. +* [x] A fresh checkout has recognizable Java Web/Tomcat project structure and build configuration. +* [x] Login page submits credentials to a Servlet controller and displays validation/authentication failures safely. +* [x] Authentication logic is represented through service and DAO boundaries rather than embedded in JSP. +* [x] Session state stores the authenticated user and role in a controlled way. +* [x] Basic role/permission constants or helpers exist for administrator, librarian, and reader. +* [x] SQL/schema guidance exists for the minimal account/role tables needed by login. +* [x] Lint, type-check, compile, or equivalent project validation is run where available. ## Definition of Done (team quality bar) @@ -68,3 +68,6 @@ Build the initial Java Web project scaffold and a login/permission skeleton for * Frontend pre-development checklist includes directory structure, JSP component guidelines, state management, type safety, and quality guidelines. * Codebase retrieval on 2026-04-27 found no application source code and surfaced the project specs as the main implementation context. * Spec indexes reference `.trellis/tasks/00-bootstrap-guidelines/research/project-requirements.md`, but that file is absent in the current workspace, so context curation uses only present spec files. +* Implementation completed the scaffold under `src/main/`, added two standalone service checks under `src/test/`, and updated code-specs for the login database/JSP contracts. +* Local verification passed for non-Servlet Java compilation, `PermissionPolicyCheck`, `AuthServiceCheck`, and JSP/static boundary scans. +* Full Maven/Tomcat compile remains blocked in this environment because `mvn` is not installed and no local Servlet API jar is available outside Maven. diff --git a/src/test/java/com/mzh/library/service/AuthServiceCheck.java b/src/test/java/com/mzh/library/service/AuthServiceCheck.java index 9a47538..738374e 100644 --- a/src/test/java/com/mzh/library/service/AuthServiceCheck.java +++ b/src/test/java/com/mzh/library/service/AuthServiceCheck.java @@ -10,6 +10,8 @@ import com.mzh.library.service.impl.AuthServiceImpl; import com.mzh.library.util.PasswordHasher; import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; public final class AuthServiceCheck { private static final String REQUIRED_MESSAGE = "Username and password are required."; @@ -21,6 +23,8 @@ public final class AuthServiceCheck { } public static void main(String[] args) { + Logger.getLogger(AuthServiceImpl.class.getName()).setLevel(Level.OFF); + User admin = user(1L, "admin", "System Administrator", Role.ADMINISTRATOR, "correct-password"); AuthService authService = new AuthServiceImpl(username -> "admin".equals(username) ? Optional.of(admin)