appview/pages: resolve did on render #801

merged
opened by boltless.me targeting master from sl/yurolxtlpsmz

Don't pass resolved user handles from http handlers. The page renderer is capable of resolving DIDs and we are using redis cache, so the performance won't matter much either.

Signed-off-by: Seongmin Lee git@boltless.me

+28 -8
appview/pages/funcmap.go
··· 22 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 23 "github.com/alecthomas/chroma/v2/lexers" 24 "github.com/alecthomas/chroma/v2/styles" 25 - "github.com/bluesky-social/indigo/atproto/syntax" 26 "github.com/dustin/go-humanize" 27 "github.com/go-enry/go-enry/v2" 28 "tangled.org/core/appview/filetree" 29 "tangled.org/core/appview/pages/markup" 30 "tangled.org/core/crypto" 31 ) ··· 71 72 return identity.Handle.String() 73 }, 74 "truncateAt30": func(s string) string { 75 if len(s) <= 30 { 76 return s ··· 131 132 return b 133 }, 134 - "didOrHandle": func(did, handle string) string { 135 - if handle != "" && handle != syntax.HandleInvalid.String() { 136 - return handle 137 - } else { 138 - return did 139 - } 140 - }, 141 "assoc": func(values ...string) ([][]string, error) { 142 if len(values)%2 != 0 { 143 return nil, fmt.Errorf("invalid assoc call, must have an even number of arguments") ··· 369 } 370 } 371 372 func (p *Pages) AvatarUrl(handle, size string) string { 373 handle = strings.TrimPrefix(handle, "@") 374 375 secret := p.avatar.SharedSecret 376 h := hmac.New(sha256.New, []byte(secret)) 377 h.Write([]byte(handle))
··· 22 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 23 "github.com/alecthomas/chroma/v2/lexers" 24 "github.com/alecthomas/chroma/v2/styles" 25 "github.com/dustin/go-humanize" 26 "github.com/go-enry/go-enry/v2" 27 "tangled.org/core/appview/filetree" 28 + "tangled.org/core/appview/models" 29 "tangled.org/core/appview/pages/markup" 30 "tangled.org/core/crypto" 31 ) ··· 71 72 return identity.Handle.String() 73 }, 74 + "ownerSlashRepo": func(repo *models.Repo) string { 75 + ownerId, err := p.resolver.ResolveIdent(context.Background(), repo.Did) 76 + if err != nil { 77 + return repo.DidSlashRepo() 78 + } 79 + handle := ownerId.Handle 80 + if handle != "" && !handle.IsInvalidHandle() { 81 + return string(handle) + "/" + repo.Name 82 + } 83 + return repo.DidSlashRepo() 84 + }, 85 "truncateAt30": func(s string) string { 86 if len(s) <= 30 { 87 return s ··· 142 143 return b 144 }, 145 "assoc": func(values ...string) ([][]string, error) { 146 if len(values)%2 != 0 { 147 return nil, fmt.Errorf("invalid assoc call, must have an even number of arguments") ··· 373 } 374 } 375 376 + func (p *Pages) resolveDid(did string) string { 377 + identity, err := p.resolver.ResolveIdent(context.Background(), did) 378 + 379 + if err != nil { 380 + return did 381 + } 382 + 383 + if identity.Handle.IsInvalidHandle() { 384 + return "handle.invalid" 385 + } 386 + 387 + return identity.Handle.String() 388 + } 389 + 390 func (p *Pages) AvatarUrl(handle, size string) string { 391 handle = strings.TrimPrefix(handle, "@") 392 393 + handle = p.resolveDid(handle) 394 + 395 secret := p.avatar.SharedSecret 396 h := hmac.New(sha256.New, []byte(secret)) 397 h.Write([]byte(handle))
+2 -4
appview/pages/pages.go
··· 482 483 type ProfileCard struct { 484 UserDid string 485 - UserHandle string 486 FollowStatus models.FollowStatus 487 Punchcard *models.Punchcard 488 Profile *models.Profile ··· 831 } 832 833 type Collaborator struct { 834 - Did string 835 - Handle string 836 - Role string 837 } 838 839 type RepoSettingsParams struct {
··· 482 483 type ProfileCard struct { 484 UserDid string 485 FollowStatus models.FollowStatus 486 Punchcard *models.Punchcard 487 Profile *models.Profile ··· 830 } 831 832 type Collaborator struct { 833 + Did string 834 + Role string 835 } 836 837 type RepoSettingsParams struct {
+2 -2
appview/pages/repoinfo/repoinfo.go
··· 9 "tangled.org/core/appview/state/userutil" 10 ) 11 12 - func (r RepoInfo) Owner() string { 13 if r.OwnerHandle != "" { 14 return r.OwnerHandle 15 } else { ··· 18 } 19 20 func (r RepoInfo) FullName() string { 21 - return path.Join(r.Owner(), r.Name) 22 } 23 24 func (r RepoInfo) OwnerWithoutAt() string {
··· 9 "tangled.org/core/appview/state/userutil" 10 ) 11 12 + func (r RepoInfo) owner() string { 13 if r.OwnerHandle != "" { 14 return r.OwnerHandle 15 } else { ··· 18 } 19 20 func (r RepoInfo) FullName() string { 21 + return path.Join(r.owner(), r.Name) 22 } 23 24 func (r RepoInfo) OwnerWithoutAt() string {
+8 -7
appview/pages/templates/layouts/profilebase.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 - {{ $avatarUrl := fullAvatar .Card.UserHandle }} 5 - <meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 6 <meta property="og:type" content="profile" /> 7 - <meta property="og:url" content="https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}?tab={{ .Active }}" /> 8 - <meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 9 <meta property="og:image" content="{{ $avatarUrl }}" /> 10 <meta property="og:image:width" content="512" /> 11 <meta property="og:image:height" content="512" /> 12 13 <meta name="twitter:card" content="summary" /> 14 - <meta name="twitter:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 15 - <meta name="twitter:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 16 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 17 {{ end }} 18
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $handle := resolve .Card.UserDid }} 5 + {{ $avatarUrl := fullAvatar $handle }} 6 + <meta property="og:title" content="{{ $handle }}" /> 7 <meta property="og:type" content="profile" /> 8 + <meta property="og:url" content="https://tangled.org/{{ $handle }}?tab={{ .Active }}" /> 9 + <meta property="og:description" content="{{ or .Card.Profile.Description $handle }}" /> 10 <meta property="og:image" content="{{ $avatarUrl }}" /> 11 <meta property="og:image:width" content="512" /> 12 <meta property="og:image:height" content="512" /> 13 14 <meta name="twitter:card" content="summary" /> 15 + <meta name="twitter:title" content="{{ $handle }}" /> 16 + <meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" /> 17 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 18 {{ end }} 19
+1 -1
appview/pages/templates/repo/empty.html
··· 35 36 <p><span class="{{$bullet}}">1</span>First, generate a new <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" class="underline">SSH key pair</a>.</p> 37 <p><span class="{{$bullet}}">2</span>Then add the public key to your account from the <a href="/settings" class="underline">settings</a> page.</p> 38 - <p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code></p> 39 <p><span class="{{$bullet}}">4</span>Push!</p> 40 </div> 41 </div>
··· 35 36 <p><span class="{{$bullet}}">1</span>First, generate a new <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" class="underline">SSH key pair</a>.</p> 37 <p><span class="{{$bullet}}">2</span>Then add the public key to your account from the <a href="/settings" class="underline">settings</a> page.</p> 38 + <p><span class="{{$bullet}}">3</span>Configure your remote to <code>git@{{ $knot | stripPort }}:{{ resolve .RepoInfo.OwnerDid }}/{{ .RepoInfo.Name }}</code></p> 39 <p><span class="{{$bullet}}">4</span>Push!</p> 40 </div> 41 </div>
+3 -2
appview/pages/templates/repo/fragments/cloneDropdown.html
··· 43 44 <!-- SSH Clone --> 45 <div class="mb-3"> 46 <label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">SSH</label> 47 <div class="flex items-center border border-gray-300 dark:border-gray-600 rounded"> 48 <code 49 class="flex-1 px-3 py-2 text-sm bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-l select-all cursor-pointer whitespace-nowrap overflow-x-auto" 50 onclick="window.getSelection().selectAllChildren(this)" 51 - data-url="git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}" 52 - >git@{{ $knot | stripPort }}:{{ .RepoInfo.OwnerHandle }}/{{ .RepoInfo.Name }}</code> 53 <button 54 onclick="copyToClipboard(this, this.previousElementSibling.getAttribute('data-url'))" 55 class="px-3 py-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 border-l border-gray-300 dark:border-gray-600"
··· 43 44 <!-- SSH Clone --> 45 <div class="mb-3"> 46 + {{ $repoOwnerHandle := resolve .RepoInfo.OwnerDid }} 47 <label class="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">SSH</label> 48 <div class="flex items-center border border-gray-300 dark:border-gray-600 rounded"> 49 <code 50 class="flex-1 px-3 py-2 text-sm bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-l select-all cursor-pointer whitespace-nowrap overflow-x-auto" 51 onclick="window.getSelection().selectAllChildren(this)" 52 + data-url="git@{{ $knot | stripPort }}:{{ $repoOwnerHandle }}/{{ .RepoInfo.Name }}" 53 + >git@{{ $knot | stripPort }}:{{ $repoOwnerHandle }}/{{ .RepoInfo.Name }}</code> 54 <button 55 onclick="copyToClipboard(this, this.previousElementSibling.getAttribute('data-url'))" 56 class="px-3 py-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 border-l border-gray-300 dark:border-gray-600"
+5 -4
appview/pages/templates/repo/settings/access.html
··· 29 {{ template "addCollaboratorButton" . }} 30 {{ end }} 31 {{ range .Collaborators }} 32 <div class="border border-gray-200 dark:border-gray-700 rounded p-4"> 33 <div class="flex items-center gap-3"> 34 <img 35 - src="{{ fullAvatar .Handle }}" 36 - alt="{{ .Handle }}" 37 class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/> 38 39 <div class="flex-1 min-w-0"> 40 - <a href="/{{ .Handle }}" class="block truncate"> 41 - {{ didOrHandle .Did .Handle }} 42 </a> 43 <p class="text-sm text-gray-500 dark:text-gray-400">{{ .Role }}</p> 44 </div>
··· 29 {{ template "addCollaboratorButton" . }} 30 {{ end }} 31 {{ range .Collaborators }} 32 + {{ $handle := resolve .Did }} 33 <div class="border border-gray-200 dark:border-gray-700 rounded p-4"> 34 <div class="flex items-center gap-3"> 35 <img 36 + src="{{ fullAvatar $handle }}" 37 + alt="{{ $handle }}" 38 class="rounded-full h-10 w-10 border border-gray-300 dark:border-gray-600 flex-shrink-0"/> 39 40 <div class="flex-1 min-w-0"> 41 + <a href="/{{ $handle }}" class="block truncate"> 42 + {{ $handle }} 43 </a> 44 <p class="text-sm text-gray-500 dark:text-gray-400">{{ .Role }}</p> 45 </div>
+6 -5
appview/pages/templates/strings/dashboard.html
··· 1 - {{ define "title" }}strings by {{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 - <meta property="og:title" content="{{ or .Card.UserHandle .Card.UserDid }}" /> 5 <meta property="og:type" content="profile" /> 6 - <meta property="og:url" content="https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}" /> 7 - <meta property="og:description" content="{{ or .Card.Profile.Description .Card.UserHandle .Card.UserDid }}" /> 8 {{ end }} 9 10 ··· 35 {{ $s := index . 1 }} 36 <div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800"> 37 <div class="font-medium dark:text-white flex gap-2 items-center"> 38 - <a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 39 </div> 40 {{ with $s.Description }} 41 <div class="text-gray-600 dark:text-gray-300 text-sm">
··· 1 + {{ define "title" }}strings by {{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $handle := resolve .Card.UserDid }} 5 + <meta property="og:title" content="{{ $handle }}" /> 6 <meta property="og:type" content="profile" /> 7 + <meta property="og:url" content="https://tangled.org/{{ $handle }}" /> 8 + <meta property="og:description" content="{{ or .Card.Profile.Description $handle }}" /> 9 {{ end }} 10 11 ··· 36 {{ $s := index . 1 }} 37 <div class="py-4 px-6 drop-shadow-sm rounded bg-white dark:bg-gray-800"> 38 <div class="font-medium dark:text-white flex gap-2 items-center"> 39 + <a href="/strings/{{ resolve $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 40 </div> 41 {{ with $s.Description }} 42 <div class="text-gray-600 dark:text-gray-300 text-sm">
+3 -3
appview/pages/templates/strings/string.html
··· 1 - {{ define "title" }}{{ .String.Filename }} · by {{ didOrHandle .Owner.DID.String .Owner.Handle.String }}{{ end }} 2 3 {{ define "extrameta" }} 4 - {{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }} 5 <meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" /> 6 <meta property="og:type" content="object" /> 7 <meta property="og:url" content="https://tangled.org/strings/{{ $ownerId }}/{{ .String.Rkey }}" /> ··· 9 {{ end }} 10 11 {{ define "content" }} 12 - {{ $ownerId := didOrHandle .Owner.DID.String .Owner.Handle.String }} 13 <section id="string-header" class="mb-4 py-2 px-6 dark:text-white"> 14 <div class="text-lg flex items-center justify-between"> 15 <div>
··· 1 + {{ define "title" }}{{ .String.Filename }} · by {{ resolve .Owner.DID.String }}{{ end }} 2 3 {{ define "extrameta" }} 4 + {{ $ownerId := resolve .Owner.DID.String }} 5 <meta property="og:title" content="{{ .String.Filename }} · by {{ $ownerId }}" /> 6 <meta property="og:type" content="object" /> 7 <meta property="og:url" content="https://tangled.org/strings/{{ $ownerId }}/{{ .String.Rkey }}" /> ··· 9 {{ end }} 10 11 {{ define "content" }} 12 + {{ $ownerId := resolve .Owner.DID.String }} 13 <section id="string-header" class="mb-4 py-2 px-6 dark:text-white"> 14 <div class="text-lg flex items-center justify-between"> 15 <div>
+1 -1
appview/pages/templates/user/followers.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · followers {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-followers" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · followers {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-followers" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/following.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · following {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-following" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · following {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-following" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/fragments/profileCard.html
··· 1 {{ define "user/fragments/profileCard" }} 2 - {{ $userIdent := didOrHandle .UserDid .UserHandle }} 3 <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 <div class="w-3/4 aspect-square relative">
··· 1 {{ define "user/fragments/profileCard" }} 2 + {{ $userIdent := resolve .UserDid }} 3 <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 <div class="w-3/4 aspect-square relative">
+2 -2
appview/pages/templates/user/overview.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }}{{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-4 order-2 md:order-2"> ··· 224 {{ define "ownRepos" }} 225 <div> 226 <div class="text-sm font-bold px-2 pb-4 dark:text-white flex items-center gap-2"> 227 - <a href="/@{{ or $.Card.UserHandle $.Card.UserDid }}?tab=repos" 228 class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group"> 229 <span>PINNED REPOS</span> 230 </a>
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }}{{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-4 order-2 md:order-2"> ··· 224 {{ define "ownRepos" }} 225 <div> 226 <div class="text-sm font-bold px-2 pb-4 dark:text-white flex items-center gap-2"> 227 + <a href="/{{ resolve $.Card.UserDid }}?tab=repos" 228 class="flex text-black dark:text-white items-center gap-2 no-underline hover:no-underline group"> 229 <span>PINNED REPOS</span> 230 </a>
+1 -1
appview/pages/templates/user/repos.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
+1 -1
appview/pages/templates/user/starred.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · repos {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2">
+2 -2
appview/pages/templates/user/strings.html
··· 1 - {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · strings {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-strings" class="md:col-span-8 order-2 md:order-2"> ··· 23 {{ $s := index . 1 }} 24 <div class="py-4 px-6 rounded bg-white dark:bg-gray-800"> 25 <div class="font-medium dark:text-white flex gap-2 items-center"> 26 - <a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 27 </div> 28 {{ with $s.Description }} 29 <div class="text-gray-600 dark:text-gray-300 text-sm">
··· 1 + {{ define "title" }}{{ resolve .Card.UserDid }} · strings {{ end }} 2 3 {{ define "profileContent" }} 4 <div id="all-strings" class="md:col-span-8 order-2 md:order-2"> ··· 23 {{ $s := index . 1 }} 24 <div class="py-4 px-6 rounded bg-white dark:bg-gray-800"> 25 <div class="font-medium dark:text-white flex gap-2 items-center"> 26 + <a href="/strings/{{ resolve $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 27 </div> 28 {{ with $s.Description }} 29 <div class="text-gray-600 dark:text-gray-300 text-sm">
-14
appview/reporesolver/resolver.go
··· 113 114 c := pages.Collaborator{ 115 Did: did, 116 - Handle: "", 117 Role: role, 118 } 119 collaborators = append(collaborators, c) 120 } 121 122 - // populate all collborators with handles 123 - identsToResolve := make([]string, len(collaborators)) 124 - for i, collab := range collaborators { 125 - identsToResolve[i] = collab.Did 126 - } 127 - 128 - resolvedIdents := f.rr.idResolver.ResolveIdents(ctx, identsToResolve) 129 - for i, resolved := range resolvedIdents { 130 - if resolved != nil { 131 - collaborators[i].Handle = resolved.Handle.String() 132 - } 133 - } 134 - 135 return collaborators, nil 136 } 137
··· 113 114 c := pages.Collaborator{ 115 Did: did, 116 Role: role, 117 } 118 collaborators = append(collaborators, c) 119 } 120 121 return collaborators, nil 122 } 123
+5 -6
appview/state/profile.go
··· 96 97 return &pages.ProfileCard{ 98 UserDid: did, 99 - UserHandle: ident.Handle.String(), 100 Profile: profile, 101 FollowStatus: followStatus, 102 Stats: pages.ProfileStats{ ··· 119 s.pages.Error500(w) 120 return 121 } 122 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 123 124 repos, err := db.GetRepos( 125 s.db, ··· 180 s.pages.Error500(w) 181 return 182 } 183 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 184 185 repos, err := db.GetRepos( 186 s.db, ··· 209 s.pages.Error500(w) 210 return 211 } 212 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 213 214 stars, err := db.GetStars(s.db, 0, db.FilterEq("starred_by_did", profile.UserDid)) 215 if err != nil { ··· 240 s.pages.Error500(w) 241 return 242 } 243 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 244 245 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 246 if err != nil { ··· 272 if err != nil { 273 return nil, err 274 } 275 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 276 277 loggedInUser := s.oauth.GetUser(r) 278 params := FollowsPageParams{
··· 96 97 return &pages.ProfileCard{ 98 UserDid: did, 99 Profile: profile, 100 FollowStatus: followStatus, 101 Stats: pages.ProfileStats{ ··· 118 s.pages.Error500(w) 119 return 120 } 121 + l = l.With("profileDid", profile.UserDid) 122 123 repos, err := db.GetRepos( 124 s.db, ··· 179 s.pages.Error500(w) 180 return 181 } 182 + l = l.With("profileDid", profile.UserDid) 183 184 repos, err := db.GetRepos( 185 s.db, ··· 208 s.pages.Error500(w) 209 return 210 } 211 + l = l.With("profileDid", profile.UserDid) 212 213 stars, err := db.GetStars(s.db, 0, db.FilterEq("starred_by_did", profile.UserDid)) 214 if err != nil { ··· 239 s.pages.Error500(w) 240 return 241 } 242 + l = l.With("profileDid", profile.UserDid) 243 244 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 245 if err != nil { ··· 271 if err != nil { 272 return nil, err 273 } 274 + l = l.With("profileDid", profile.UserDid) 275 276 loggedInUser := s.oauth.GetUser(r) 277 params := FollowsPageParams{