Monorepo for Tangled

appview/pages: get avatar cid to bust cache

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.org>

authored by

Anirudh Oppiliappan and committed by tangled.org 2e71ee92 c7fbb98c

+38 -10
+32 -7
appview/pages/funcmap.go
··· 26 "github.com/go-enry/go-enry/v2" 27 "github.com/yuin/goldmark" 28 emoji "github.com/yuin/goldmark-emoji" 29 "tangled.org/core/appview/models" 30 "tangled.org/core/appview/oauth" 31 "tangled.org/core/appview/pages/markup" ··· 485 return identity.Handle.String() 486 } 487 488 - func (p *Pages) AvatarUrl(handle, size string) string { 489 - handle = strings.TrimPrefix(handle, "@") 490 491 - handle = p.resolveDid(handle) 492 493 secret := p.avatar.SharedSecret 494 h := hmac.New(sha256.New, []byte(secret)) 495 - h.Write([]byte(handle)) 496 signature := hex.EncodeToString(h.Sum(nil)) 497 498 - sizeArg := "" 499 if size != "" { 500 - sizeArg = fmt.Sprintf("size=%s", size) 501 } 502 - return fmt.Sprintf("%s/%s/%s?%s", p.avatar.Host, signature, handle, sizeArg) 503 } 504 505 func (p *Pages) icon(name string, classes []string) (template.HTML, error) {
··· 26 "github.com/go-enry/go-enry/v2" 27 "github.com/yuin/goldmark" 28 emoji "github.com/yuin/goldmark-emoji" 29 + "tangled.org/core/appview/db" 30 "tangled.org/core/appview/models" 31 "tangled.org/core/appview/oauth" 32 "tangled.org/core/appview/pages/markup" ··· 486 return identity.Handle.String() 487 } 488 489 + func (p *Pages) AvatarUrl(actor, size string) string { 490 + actor = strings.TrimPrefix(actor, "@") 491 492 + identity, err := p.resolver.ResolveIdent(context.Background(), actor) 493 + var did string 494 + if err != nil { 495 + did = actor 496 + } else { 497 + did = identity.DID.String() 498 + } 499 500 secret := p.avatar.SharedSecret 501 h := hmac.New(sha256.New, []byte(secret)) 502 + h.Write([]byte(did)) 503 signature := hex.EncodeToString(h.Sum(nil)) 504 505 + // Get avatar CID for cache busting 506 + profile, err := db.GetProfile(p.db, did) 507 + version := "" 508 + if err == nil && profile != nil && profile.Avatar != "" { 509 + // Use first 8 chars of avatar CID as version 510 + if len(profile.Avatar) > 8 { 511 + version = profile.Avatar[:8] 512 + } else { 513 + version = profile.Avatar 514 + } 515 + } 516 + 517 + baseUrl := fmt.Sprintf("%s/%s/%s", p.avatar.Host, signature, did) 518 if size != "" { 519 + if version != "" { 520 + return fmt.Sprintf("%s?size=%s&v=%s", baseUrl, size, version) 521 + } 522 + return fmt.Sprintf("%s?size=%s", baseUrl, size) 523 + } 524 + if version != "" { 525 + return fmt.Sprintf("%s?v=%s", baseUrl, version) 526 } 527 + return baseUrl 528 } 529 530 func (p *Pages) icon(name string, classes []string) (template.HTML, error) {
+1 -1
appview/pages/funcmap_test.go
··· 22 } 23 for _, tt := range tests { 24 t.Run(tt.name, func(t *testing.T) { 25 - p := NewPages(tt.config, tt.res, tt.l) 26 got := p.funcMap() 27 // TODO: update the condition below to compare got with tt.want. 28 if true {
··· 22 } 23 for _, tt := range tests { 24 t.Run(tt.name, func(t *testing.T) { 25 + p := NewPages(tt.config, tt.res, nil, tt.l) 26 got := p.funcMap() 27 // TODO: update the condition below to compare got with tt.want. 28 if true {
+4 -1
appview/pages/pages.go
··· 19 "tangled.org/core/api/tangled" 20 "tangled.org/core/appview/commitverify" 21 "tangled.org/core/appview/config" 22 "tangled.org/core/appview/models" 23 "tangled.org/core/appview/oauth" 24 "tangled.org/core/appview/pages/markup" ··· 42 43 avatar config.AvatarConfig 44 resolver *idresolver.Resolver 45 dev bool 46 embedFS fs.FS 47 templateDir string // Path to templates on disk for dev mode ··· 49 logger *slog.Logger 50 } 51 52 - func NewPages(config *config.Config, res *idresolver.Resolver, logger *slog.Logger) *Pages { 53 // initialized with safe defaults, can be overriden per use 54 rctx := &markup.RenderContext{ 55 IsDev: config.Core.Dev, ··· 66 avatar: config.Avatar, 67 rctx: rctx, 68 resolver: res, 69 templateDir: "appview/pages", 70 logger: logger, 71 }
··· 19 "tangled.org/core/api/tangled" 20 "tangled.org/core/appview/commitverify" 21 "tangled.org/core/appview/config" 22 + "tangled.org/core/appview/db" 23 "tangled.org/core/appview/models" 24 "tangled.org/core/appview/oauth" 25 "tangled.org/core/appview/pages/markup" ··· 43 44 avatar config.AvatarConfig 45 resolver *idresolver.Resolver 46 + db *db.DB 47 dev bool 48 embedFS fs.FS 49 templateDir string // Path to templates on disk for dev mode ··· 51 logger *slog.Logger 52 } 53 54 + func NewPages(config *config.Config, res *idresolver.Resolver, database *db.DB, logger *slog.Logger) *Pages { 55 // initialized with safe defaults, can be overriden per use 56 rctx := &markup.RenderContext{ 57 IsDev: config.Core.Dev, ··· 68 avatar: config.Avatar, 69 rctx: rctx, 70 resolver: res, 71 + db: database, 72 templateDir: "appview/pages", 73 logger: logger, 74 }
+1 -1
appview/state/state.go
··· 92 return nil, fmt.Errorf("failed to create posthog client: %w", err) 93 } 94 95 - pages := pages.NewPages(config, res, log.SubLogger(logger, "pages")) 96 oauth, err := oauth.New(config, posthog, d, enforcer, res, log.SubLogger(logger, "oauth")) 97 if err != nil { 98 return nil, fmt.Errorf("failed to start oauth handler: %w", err)
··· 92 return nil, fmt.Errorf("failed to create posthog client: %w", err) 93 } 94 95 + pages := pages.NewPages(config, res, d, log.SubLogger(logger, "pages")) 96 oauth, err := oauth.New(config, posthog, d, enforcer, res, log.SubLogger(logger, "oauth")) 97 if err != nil { 98 return nil, fmt.Errorf("failed to start oauth handler: %w", err)