forked from tangled.org/core
Monorepo for Tangled

appview/pages: resolve did on render

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>

authored by boltless.me and committed by Tangled 4143799e a47c25c0

+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 "github.com/yuin/goldmark" 29 "tangled.org/core/appview/filetree" 30 "tangled.org/core/appview/pages/markup" 31 "tangled.org/core/crypto" 32 ) ··· 71 } 72 73 return identity.Handle.String() 74 }, 75 "truncateAt30": func(s string) string { 76 if len(s) <= 30 { ··· 140 } 141 142 return b 143 - }, 144 - "didOrHandle": func(did, handle string) string { 145 - if handle != "" && handle != syntax.HandleInvalid.String() { 146 - return handle 147 - } else { 148 - return did 149 - } 150 }, 151 "assoc": func(values ...string) ([][]string, error) { 152 if len(values)%2 != 0 { ··· 379 } 380 } 381 382 func (p *Pages) AvatarUrl(handle, size string) string { 383 handle = strings.TrimPrefix(handle, "@") 384 385 secret := p.avatar.SharedSecret 386 h := hmac.New(sha256.New, []byte(secret))
··· 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 "github.com/yuin/goldmark" 28 "tangled.org/core/appview/filetree" 29 + "tangled.org/core/appview/models" 30 "tangled.org/core/appview/pages/markup" 31 "tangled.org/core/crypto" 32 ) ··· 71 } 72 73 return identity.Handle.String() 74 + }, 75 + "ownerSlashRepo": func(repo *models.Repo) string { 76 + ownerId, err := p.resolver.ResolveIdent(context.Background(), repo.Did) 77 + if err != nil { 78 + return repo.DidSlashRepo() 79 + } 80 + handle := ownerId.Handle 81 + if handle != "" && !handle.IsInvalidHandle() { 82 + return string(handle) + "/" + repo.Name 83 + } 84 + return repo.DidSlashRepo() 85 }, 86 "truncateAt30": func(s string) string { 87 if len(s) <= 30 { ··· 151 } 152 153 return b 154 }, 155 "assoc": func(values ...string) ([][]string, error) { 156 if len(values)%2 != 0 { ··· 383 } 384 } 385 386 + func (p *Pages) resolveDid(did string) string { 387 + identity, err := p.resolver.ResolveIdent(context.Background(), did) 388 + 389 + if err != nil { 390 + return did 391 + } 392 + 393 + if identity.Handle.IsInvalidHandle() { 394 + return "handle.invalid" 395 + } 396 + 397 + return identity.Handle.String() 398 + } 399 + 400 func (p *Pages) AvatarUrl(handle, size string) string { 401 handle = strings.TrimPrefix(handle, "@") 402 + 403 + handle = p.resolveDid(handle) 404 405 secret := p.avatar.SharedSecret 406 h := hmac.New(sha256.New, []byte(secret))
+2 -4
appview/pages/pages.go
··· 492 493 type ProfileCard struct { 494 UserDid string 495 - UserHandle string 496 FollowStatus models.FollowStatus 497 Punchcard *models.Punchcard 498 Profile *models.Profile ··· 841 } 842 843 type Collaborator struct { 844 - Did string 845 - Handle string 846 - Role string 847 } 848 849 type RepoSettingsParams struct {
··· 492 493 type ProfileCard struct { 494 UserDid string 495 FollowStatus models.FollowStatus 496 Punchcard *models.Punchcard 497 Profile *models.Profile ··· 840 } 841 842 type Collaborator struct { 843 + Did string 844 + Role string 845 } 846 847 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
··· 113 114 c := pages.Collaborator{ 115 Did: did, 116 Role: role, 117 } 118 collaborators = append(collaborators, c) 119 } 120 121 return collaborators, nil
+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.GetRepoStars(s.db, 0, db.FilterEq("did", profile.UserDid)) 215 if err != nil { ··· 238 s.pages.Error500(w) 239 return 240 } 241 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 242 243 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 244 if err != nil { ··· 270 if err != nil { 271 return nil, err 272 } 273 - l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 274 275 loggedInUser := s.oauth.GetUser(r) 276 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.GetRepoStars(s.db, 0, db.FilterEq("did", profile.UserDid)) 214 if err != nil { ··· 237 s.pages.Error500(w) 238 return 239 } 240 + l = l.With("profileDid", profile.UserDid) 241 242 strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 243 if err != nil { ··· 269 if err != nil { 270 return nil, err 271 } 272 + l = l.With("profileDid", profile.UserDid) 273 274 loggedInUser := s.oauth.GetUser(r) 275 params := FollowsPageParams{