This commit is contained in:
parent
10e5270273
commit
47f18e9ef3
4 changed files with 264 additions and 35 deletions
|
|
@ -227,6 +227,108 @@ attribute :search_vector, AshPostgres.Tsvector,
|
|||
|
||||
---
|
||||
|
||||
#### Phase 6: Search Enhancement & OIDC Improvements (Sprint 9)
|
||||
|
||||
**Sprint 9 - 01.11 - 13.11 (finalized)**
|
||||
|
||||
**PR #187:** *Implement fuzzy search* (closes #162) 🔍
|
||||
- PostgreSQL `pg_trgm` extension for trigram-based fuzzy search
|
||||
- 6 new GIN trigram indexes on members table:
|
||||
- first_name, last_name, email, city, street, notes
|
||||
- Combined search strategy: Full-text (tsvector) + Trigram similarity
|
||||
- Configurable similarity threshold (default 0.2)
|
||||
- Migration: `20251001141005_add_trigram_to_members.exs`
|
||||
- 443 lines of comprehensive tests
|
||||
|
||||
**Key learnings:**
|
||||
- Trigram indexes significantly improve fuzzy matching
|
||||
- Combined FTS + trigram provides best user experience
|
||||
- word_similarity() better for partial word matching than similarity()
|
||||
- Similarity threshold of 0.2 balances precision and recall
|
||||
|
||||
**Implementation highlights:**
|
||||
```elixir
|
||||
# New Ash action: :search with fuzzy matching
|
||||
read :search do
|
||||
argument :query, :string, allow_nil?: true
|
||||
argument :similarity_threshold, :float, allow_nil?: true
|
||||
# Uses fragment() for pg_trgm operators: %, similarity(), word_similarity()
|
||||
end
|
||||
|
||||
# Public function for LiveView usage
|
||||
def fuzzy_search(query, opts) do
|
||||
Ash.Query.for_read(query, :search, %{query: query_string})
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**PR #192:** *OIDC handling and linking* (closes #171) 🔐
|
||||
- Secure OIDC account linking with password verification
|
||||
- Security fix: Filter OIDC sign-in by `oidc_id` instead of email
|
||||
- New custom error: `PasswordVerificationRequired`
|
||||
- New validation: `OidcEmailCollision` for email conflict detection
|
||||
- New LiveView: `LinkOidcAccountLive` for interactive linking
|
||||
- Automatic linking for passwordless users (no password prompt)
|
||||
- Password verification required for password-protected accounts
|
||||
- Comprehensive security logging for audit trail
|
||||
- Locale persistence via secure cookie (1 year TTL)
|
||||
- Documentation: `docs/oidc-account-linking.md`
|
||||
|
||||
**Security improvements:**
|
||||
- Prevents account takeover via OIDC email matching
|
||||
- Password verification before linking OIDC to password accounts
|
||||
- All linking attempts logged with appropriate severity
|
||||
- CSRF protection on linking forms
|
||||
- Secure cookie flags: `http_only`, `secure`, `same_site: "Lax"`
|
||||
|
||||
**Test coverage:**
|
||||
- 5 new comprehensive test files (1,793 lines total):
|
||||
- `user_authentication_test.exs` (265 lines)
|
||||
- `oidc_e2e_flow_test.exs` (415 lines)
|
||||
- `oidc_email_update_test.exs` (271 lines)
|
||||
- `oidc_password_linking_test.exs` (496 lines)
|
||||
- `oidc_passwordless_linking_test.exs` (210 lines)
|
||||
- Extended `oidc_integration_test.exs` (+136 lines)
|
||||
|
||||
**Key learnings:**
|
||||
- Account linking requires careful security considerations
|
||||
- Passwordless users should be auto-linked (better UX)
|
||||
- Audit logging essential for security-critical operations
|
||||
- Locale persistence improves user experience post-logout
|
||||
|
||||
---
|
||||
|
||||
**PR #193:** *Docs, Code Guidelines and Progress Log* 📚
|
||||
- Complete project documentation suite (5,554 lines)
|
||||
- New documentation files:
|
||||
- `CODE_GUIDELINES.md` (2,578 lines) - Comprehensive development guidelines
|
||||
- `docs/database-schema-readme.md` (392 lines) - Database documentation
|
||||
- `docs/database_schema.dbml` (329 lines) - DBML schema definition
|
||||
- `docs/development-progress-log.md` (1,227 lines) - This file
|
||||
- `docs/feature-roadmap.md` (743 lines) - Feature planning and roadmap
|
||||
- Reduced redundancy in README.md (links to detailed docs)
|
||||
- Cross-referenced documentation for easy navigation
|
||||
|
||||
---
|
||||
|
||||
**PR #201:** *Code documentation and refactoring* 🔧
|
||||
- @moduledoc for ALL modules (51 modules documented)
|
||||
- @doc for all public functions
|
||||
- Enabled Credo `ModuleDoc` check (enforces documentation standards)
|
||||
- Refactored complex functions:
|
||||
- `MemberLive.Index.handle_event/3` - Split sorting logic into smaller functions
|
||||
- `AuthController.handle_auth_failure/2` - Reduced cyclomatic complexity
|
||||
- Documentation coverage: 100% for core modules
|
||||
|
||||
**Key learnings:**
|
||||
- @moduledoc enforcement improves code maintainability
|
||||
- Refactoring complex functions improves readability
|
||||
- Documentation should explain "why" not just "what"
|
||||
- Credo helps maintain consistent code quality
|
||||
|
||||
---
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
### Architecture Patterns
|
||||
|
|
@ -369,9 +471,11 @@ end
|
|||
- ✅ Consistent styling
|
||||
- ✅ Mobile-responsive out of the box
|
||||
|
||||
#### 7. Full-Text Search Implementation
|
||||
#### 7. Search Implementation (Full-Text + Fuzzy)
|
||||
|
||||
**PostgreSQL tsvector + GIN Index**
|
||||
**Two-Tiered Search Strategy:**
|
||||
|
||||
**A) Full-Text Search (tsvector + GIN Index)**
|
||||
|
||||
```sql
|
||||
-- Auto-updating trigger
|
||||
|
|
@ -389,16 +493,40 @@ END
|
|||
$$ LANGUAGE plpgsql;
|
||||
```
|
||||
|
||||
**B) Fuzzy Search (pg_trgm + Trigram GIN Indexes)**
|
||||
|
||||
Added November 2025 (PR #187):
|
||||
|
||||
```elixir
|
||||
# Ash action combining FTS + trigram similarity
|
||||
read :search do
|
||||
argument :query, :string
|
||||
argument :similarity_threshold, :float
|
||||
|
||||
prepare fn query, _ctx ->
|
||||
# 1. Full-text search (tsvector)
|
||||
# 2. Trigram similarity (%, similarity(), word_similarity())
|
||||
# 3. Substring matching (contains, ilike)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**6 Trigram Indexes:**
|
||||
- first_name, last_name, email, city, street, notes
|
||||
- GIN index with `gin_trgm_ops` operator class
|
||||
|
||||
**Reasoning:**
|
||||
- Native PostgreSQL feature (no external service)
|
||||
- Fast with GIN index
|
||||
- Weighted fields (names more important than dates)
|
||||
- Native PostgreSQL features (no external service)
|
||||
- Combined approach handles typos + partial matches
|
||||
- Fast with GIN indexes
|
||||
- Simple lexer (no German stemming initially)
|
||||
- Similarity threshold configurable (default 0.2)
|
||||
|
||||
**Why not Elasticsearch/Meilisearch?**
|
||||
- Overkill for small to mid-sized clubs
|
||||
- Additional infrastructure complexity
|
||||
- PostgreSQL full-text sufficient for 10k+ members
|
||||
- PostgreSQL full-text + fuzzy sufficient for 10k+ members
|
||||
- Better integration with existing stack
|
||||
|
||||
### Deviations from Initial Plans
|
||||
|
||||
|
|
@ -470,7 +598,8 @@ end
|
|||
3. `20250620110850_add_accounts_domain.exs` - Users & tokens tables
|
||||
4. `20250912085235_AddSearchVectorToMembers.exs` - Full-text search (tsvector + GIN index)
|
||||
5. `20250926164519_member_relation.exs` - User-Member link (optional 1:1)
|
||||
6. `20251016130855_add_constraints_for_user_member_and_property.exs` - Email sync constraints
|
||||
6. `20251001141005_add_trigram_to_members.exs` - Fuzzy search (pg_trgm + 6 GIN trigram indexes)
|
||||
7. `20251016130855_add_constraints_for_user_member_and_property.exs` - Email sync constraints
|
||||
|
||||
**Learning:** Ash's code generation from resources ensures schema always matches code.
|
||||
|
||||
|
|
@ -1220,8 +1349,8 @@ This project demonstrates a modern Phoenix application built with:
|
|||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0
|
||||
**Last Updated:** 2025-11-10
|
||||
**Document Version:** 1.1
|
||||
**Last Updated:** 2025-11-13
|
||||
**Maintainer:** Development Team
|
||||
**Status:** Living Document (update as project evolves)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue