feat: subtitle, description and avatar on the public author object
- GET /_journal/api/v1/authors/{author} adds subtitle and description from
backend_users.metadata and avatar (the admin avatar's public URL or null)
- TestJournalAuthorProfile pins the seven keys and checks the three values
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -70,7 +71,7 @@ func authorProfileOK(t *testing.T, env *adminEnv, param string) (map[string]any,
|
||||
keys = append(keys, k)
|
||||
}
|
||||
slices.Sort(keys)
|
||||
if want := []string{"first_name", "id", "last_name", "slug"}; !slices.Equal(keys, want) {
|
||||
if want := []string{"avatar", "description", "first_name", "id", "last_name", "slug", "subtitle"}; !slices.Equal(keys, want) {
|
||||
t.Fatalf("author keys = %v, want %v", keys, want)
|
||||
}
|
||||
return body.Data, rec.Body.String()
|
||||
@@ -102,6 +103,10 @@ func TestJournalAuthorProfile(t *testing.T) {
|
||||
if id, _ := data["id"].(float64); uint(id) != janeID {
|
||||
t.Fatalf("jane-doe id = %v, want %d", data["id"], janeID)
|
||||
}
|
||||
// No metadata and no avatar: empty strings and null.
|
||||
if data["subtitle"] != "" || data["description"] != "" || data["avatar"] != nil {
|
||||
t.Fatalf("jane-doe profile extras = %v, want empty subtitle and description and a null avatar", data)
|
||||
}
|
||||
for _, secret := range []string{"jdoe@example.test", "authorSecretMarker", authorPersistCode, `"jdoe"`} {
|
||||
if strings.Contains(raw, secret) {
|
||||
t.Fatalf("author body leaks %q: %s", secret, raw)
|
||||
@@ -143,6 +148,27 @@ func TestJournalAuthorProfile(t *testing.T) {
|
||||
expectAuthorNotFound(t, env, authorAPIPrefix+strings.Repeat("a", 300))
|
||||
expectAuthorNotFound(t, env, authorAPIPrefix+"a%09b")
|
||||
|
||||
// subtitle and description come from backend_users.metadata, avatar is
|
||||
// the public URL of the admin avatar (system_files, Backend\Models\User).
|
||||
teamID := insertBackendUser(t, env, "Summer", "Team", "team", "team", false)
|
||||
if err := env.gdb.Exec(`UPDATE backend_users SET metadata = ? WHERE id = ?`,
|
||||
`{"subtitle":"Golem15","description":"We build SummerCMS.","preferences":{"x":1}}`, teamID).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
const avatarDisk = "0123456789abcdef01234567.webp"
|
||||
if err := env.gdb.Exec(`INSERT INTO system_files (disk_name, file_name, file_size, content_type, field, attachment_id, attachment_type, is_public, sort_order, created_at, updated_at)
|
||||
VALUES (?, 'team.webp', 10, 'image/webp', 'avatar', ?, 'Backend\Models\User', TRUE, 0, NOW(), NOW())`,
|
||||
avatarDisk, strconv.FormatUint(uint64(teamID), 10)).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, _ = authorProfileOK(t, env, "team")
|
||||
if data["subtitle"] != "Golem15" || data["description"] != "We build SummerCMS." {
|
||||
t.Fatalf("team profile = %v, want subtitle Golem15 and the description", data)
|
||||
}
|
||||
if avatar, _ := data["avatar"].(string); !strings.HasSuffix(avatar, avatarDisk) {
|
||||
t.Fatalf("team avatar = %v, want a URL ending in %s", data["avatar"], avatarDisk)
|
||||
}
|
||||
|
||||
// A slug is an explicit opt-in: it resolves with no posts at all.
|
||||
insertBackendUser(t, env, "Fresh", "Author", "fresh", "fresh-author", false)
|
||||
data, _ = authorProfileOK(t, env, "fresh-author")
|
||||
|
||||
Reference in New Issue
Block a user