docs: add Reader glossary entry + clarifying comments on specs and query
- GLOSSARY.md: defines "Reader" as the permission-derived role (isReader = !canWrite && !canAnnotate) — addresses @Markus blocker - GeschichteSpecifications.hasAuthor: comment explains null = no restriction (PUBLISHED path) — addresses @Markus suggestion - PersonRepository.findTopByDocumentCount: comment explains alias-in-ORDER-BY is intentional PostgreSQL behaviour — addresses @Markus suggestion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ public final class GeschichteSpecifications {
|
||||
};
|
||||
}
|
||||
|
||||
// null authorId → no restriction (PUBLISHED path passes null; Spring Data skips null predicates)
|
||||
public static Specification<Geschichte> hasAuthor(UUID authorId) {
|
||||
return (root, query, cb) ->
|
||||
authorId == null ? null : cb.equal(root.get("author").get("id"), authorId);
|
||||
|
||||
@@ -69,6 +69,8 @@ public interface PersonRepository extends JpaRepository<Person, UUID> {
|
||||
nativeQuery = true)
|
||||
List<PersonSummaryDTO> searchWithDocumentCount(@Param("query") String query);
|
||||
|
||||
// ORDER BY uses the computed alias "documentCount" — valid PostgreSQL (aliases allowed in ORDER BY,
|
||||
// unlike WHERE/HAVING). This is intentional; it would silently fail on MySQL or H2.
|
||||
@Query(value = """
|
||||
SELECT p.id, p.title, p.first_name AS firstName, p.last_name AS lastName,
|
||||
p.person_type AS personType,
|
||||
|
||||
@@ -13,6 +13,9 @@ For domain package structure see [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) _(com
|
||||
**AppUser** (`AppUser`) — a real person who can log into the system (a family member or administrator). `AppUser` records carry login credentials, group memberships, and notification history.
|
||||
_Not to be confused with [Person](#person-person)_ — an AppUser is never recorded as a document sender, receiver, or historical individual.
|
||||
|
||||
**Reader** — an `AppUser` whose effective permissions include `READ_ALL` but neither `WRITE_ALL` nor `ANNOTATE_ALL`. Readers see a dedicated dashboard (`isReader = !canWrite && !canAnnotate`) focused on browsing documents, persons, and stories rather than contribution tasks. A user who also holds `BLOG_WRITE` is still classified as a Reader and additionally sees a drafts module.
|
||||
_Not to be confused with [AppUser](#appuser-appuser)_ — Reader is a permission-derived role, not an entity.
|
||||
|
||||
**Permission** — a discrete capability string assigned to a `UserGroup` (e.g. `READ_ALL`, `WRITE_ALL`, `ADMIN`, `ADMIN_USER`, `ADMIN_TAG`, `ADMIN_PERMISSION`). Enforced via the `@RequirePermission` AOP annotation on controller methods, checked at runtime by `PermissionAspect`; not via Spring Security's `@PreAuthorize`.
|
||||
|
||||
**Person** (`Person`) — a historical individual in the family archive (sender, receiver of letters, person mentioned in transcriptions). NEVER has a login account and NEVER appears as an `AppUser`.
|
||||
|
||||
Reference in New Issue
Block a user