1package models
2
3import (
4 "fmt"
5 "sync"
6
7 "github.com/git-bug/git-bug/cache"
8 "github.com/git-bug/git-bug/entities/identity"
9 "github.com/git-bug/git-bug/entity"
10)
11
12// IdentityWrapper is an interface used by the GraphQL resolvers to handle an identity.
13// Depending on the situation, an Identity can already be fully loaded in memory or not.
14// This interface is used to wrap either a lazyIdentity or a loadedIdentity depending on the situation.
15type IdentityWrapper interface {
16 Id() entity.Id
17 Name() string
18 Email() (string, error)
19 Login() (string, error)
20 AvatarUrl() (string, error)
21 Keys() ([]*identity.Key, error)
22 DisplayName() string
23 IsProtected() (bool, error)
24
25 // IsEntity is a sign post-method for gqlgen, to mark compliance to an interface.
26 IsEntity()
27}
28
29var _ IdentityWrapper = &lazyIdentity{}
30
31type lazyIdentity struct {
32 cache *cache.RepoCache
33 excerpt *cache.IdentityExcerpt
34
35 mu sync.Mutex
36 id *cache.IdentityCache
37}
38
39func NewLazyIdentity(cache *cache.RepoCache, excerpt *cache.IdentityExcerpt) *lazyIdentity {
40 return &lazyIdentity{
41 cache: cache,
42 excerpt: excerpt,
43 }
44}
45
46func (li *lazyIdentity) load() (*cache.IdentityCache, error) {
47 li.mu.Lock()
48 defer li.mu.Unlock()
49
50 if li.id != nil {
51 return li.id, nil
52 }
53
54 id, err := li.cache.Identities().Resolve(li.excerpt.Id())
55 if err != nil {
56 return nil, fmt.Errorf("cache: missing identity %v", li.excerpt.Id())
57 }
58 li.id = id
59 return id, nil
60}
61
62func (li *lazyIdentity) Id() entity.Id {
63 return li.excerpt.Id()
64}
65
66func (li *lazyIdentity) Name() string {
67 return li.excerpt.Name
68}
69
70func (li *lazyIdentity) DisplayName() string {
71 return li.excerpt.DisplayName()
72}
73
74func (li *lazyIdentity) Email() (string, error) {
75 id, err := li.load()
76 if err != nil {
77 return "", err
78 }
79 return id.Email(), nil
80}
81
82func (li *lazyIdentity) Login() (string, error) {
83 id, err := li.load()
84 if err != nil {
85 return "", err
86 }
87 return id.Login(), nil
88}
89
90func (li *lazyIdentity) AvatarUrl() (string, error) {
91 id, err := li.load()
92 if err != nil {
93 return "", err
94 }
95 return id.AvatarUrl(), nil
96}
97
98func (li *lazyIdentity) Keys() ([]*identity.Key, error) {
99 id, err := li.load()
100 if err != nil {
101 return nil, err
102 }
103 return id.Keys(), nil
104}
105
106func (li *lazyIdentity) IsProtected() (bool, error) {
107 id, err := li.load()
108 if err != nil {
109 return false, err
110 }
111 return id.IsProtected(), nil
112}
113
114// IsEntity is a sign post-method for gqlgen, to mark compliance to an interface.
115func (li *lazyIdentity) IsEntity() {}
116
117var _ IdentityWrapper = &loadedIdentity{}
118
119type loadedIdentity struct {
120 identity.Interface
121}
122
123func NewLoadedIdentity(id identity.Interface) *loadedIdentity {
124 return &loadedIdentity{Interface: id}
125}
126
127func (l loadedIdentity) Email() (string, error) {
128 return l.Interface.Email(), nil
129}
130
131func (l loadedIdentity) Login() (string, error) {
132 return l.Interface.Login(), nil
133}
134
135func (l loadedIdentity) AvatarUrl() (string, error) {
136 return l.Interface.AvatarUrl(), nil
137}
138
139func (l loadedIdentity) Keys() ([]*identity.Key, error) {
140 return l.Interface.Keys(), nil
141}
142
143func (l loadedIdentity) IsProtected() (bool, error) {
144 return l.Interface.IsProtected(), nil
145}
146
147// IsEntity is a sign post-method for gqlgen, to mark compliance to an interface.
148func (l loadedIdentity) IsEntity() {}