feat(legal): imprint & privacy notices, "Über MindSift"
- LEGAL_IMPRINT_/LEGAL_PRIVACY_ URL and Markdown (inline or *_FILE);
only http(s) URLs accepted
- /auth/status exposes legal info; public GET /legal/{imprint|privacy}
- Links on login/setup screen and in the settings footer: URL opens a new
tab, Markdown a reading modal; hidden when nothing is configured
- "Über MindSift" modal (version, license, repository) in settings and help
- Docs and compose/env examples
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a62b204e14
commit
d6c70d7a8e
17 files changed
+318
-2
No files matched your search
@@ -1366,3 +1366,42 @@ func TestFirstBootSetupWithSampleData(t *testing.T) {
|
||||
t.Fatalf("expected sample notes and task lists, got %d notes, %d task lists", len(docs), len(lists))
|
||||
}
|
||||
}
|
||||
|
||||
// Impressum and Datenschutz must be reachable without login; unset texts stay hidden.
|
||||
func TestLegalTextsArePublic(t *testing.T) {
|
||||
dbPath := filepath.Join(t.TempDir(), "legal.db")
|
||||
store, err := storage.NewStore(dbPath)
|
||||
if err != nil {
|
||||
t.Fatalf("NewStore: %v", err)
|
||||
}
|
||||
defer store.Close()
|
||||
cfg := &config.Config{Port: "8080", DatabasePath: dbPath, JWTSecret: "test-jwt-secret-key",
|
||||
Legal: config.LegalTexts{ImprintContent: "# Impressum\nMax Muster", PrivacyURL: "https://example.org/datenschutz"}}
|
||||
router := NewServer(cfg, store, ws.NewHub(), nil).Router()
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/v1/auth/status", nil))
|
||||
var st struct {
|
||||
Legal struct {
|
||||
ImprintURL string `json:"imprintUrl"`
|
||||
HasImprintContent bool `json:"hasImprintContent"`
|
||||
PrivacyURL string `json:"privacyUrl"`
|
||||
HasPrivacyContent bool `json:"hasPrivacyContent"`
|
||||
} `json:"legal"`
|
||||
}
|
||||
_ = json.Unmarshal(rec.Body.Bytes(), &st)
|
||||
if !st.Legal.HasImprintContent || st.Legal.HasPrivacyContent || st.Legal.PrivacyURL != "https://example.org/datenschutz" {
|
||||
t.Fatalf("unexpected legal status: %+v", st.Legal)
|
||||
}
|
||||
|
||||
rec = httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/v1/legal/imprint", nil))
|
||||
if rec.Code != http.StatusOK || !strings.Contains(rec.Body.String(), "Max Muster") {
|
||||
t.Fatalf("imprint without login: %d %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
rec = httptest.NewRecorder()
|
||||
router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/v1/legal/privacy", nil))
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Fatalf("privacy without text should be 404, got %d", rec.Code)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user