Monorepo for Tangled tangled.org

draft: appview: service layer #800

open opened by boltless.me targeting master from sl/uvpzuszrulvq

Obviously file naming of appview/web/handler/*.go files are directly against to go convention. Though I think flattening all handler files can significantly reduce the effort involved in file naming and structuring. We are already grouping core services by domains, and doing same for web handers is just over-complicating.

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

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:xasnlahkri4ewmbuzly2rlc5/sh.tangled.repo.pull/3m5jyyj76xa22
+96 -140
Interdiff #10 #11
appview/oauth/handler.go

This patch was likely rebased, as context lines do not match.

-10
appview/oauth/session.go
··· 1 - package oauth 2 - 3 - import ( 4 - "net/http" 5 - 6 - "github.com/bluesky-social/indigo/atproto/auth/oauth" 7 - ) 8 - 9 - func (o *OAuth) SaveSession2(w http.ResponseWriter, r *http.Request, sessData *oauth.ClientSessionData) { 10 - }
···
appview/service/issue/errors.go

This file has not been changed.

+21 -21
appview/service/issue/issue.go
··· 61 62 func (s *Service) NewIssue(ctx context.Context, repo *models.Repo, title, body string) (*models.Issue, error) { 63 l := s.logger.With("method", "NewIssue") 64 - sess := session.FromContext(ctx) 65 - if sess == nil { 66 l.Error("user session is missing in context") 67 return nil, ErrForbidden 68 } 69 - authorDid := sess.Data.AccountDID 70 l = l.With("did", authorDid) 71 72 mentions, references := s.refResolver.Resolve(ctx, body) 73 74 issue := models.Issue{ 75 - RepoAt: repo.RepoAt(), 76 Rkey: tid.TID(), 77 Title: title, 78 Body: body, 79 - Open: true, 80 - Did: authorDid.String(), 81 Created: time.Now(), 82 Mentions: mentions, 83 References: references, 84 Repo: repo, 85 } 86 ··· 101 return nil, ErrDatabaseFail 102 } 103 104 - atpclient := sess.APIClient() 105 record := issue.AsRecord() 106 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 107 - Repo: authorDid.String(), 108 Collection: tangled.RepoIssueNSID, 109 Rkey: issue.Rkey, 110 Record: &lexutil.LexiconTypeDecoder{ ··· 163 164 func (s *Service) EditIssue(ctx context.Context, issue *models.Issue) error { 165 l := s.logger.With("method", "EditIssue") 166 - sess := session.FromContext(ctx) 167 - if sess == nil { 168 l.Error("user session is missing in context") 169 return ErrForbidden 170 } 171 - sessDid := sess.Data.AccountDID 172 - l = l.With("did", sessDid) 173 174 mentions, references := s.refResolver.Resolve(ctx, issue.Body) 175 issue.Mentions = mentions 176 issue.References = references 177 178 - if sessDid != syntax.DID(issue.Did) { 179 l.Error("only author can edit the issue") 180 return ErrForbidden 181 } ··· 197 return ErrDatabaseFail 198 } 199 200 - atpclient := sess.APIClient() 201 record := issue.AsRecord() 202 203 ex, err := atproto.RepoGetRecord(ctx, atpclient, "", tangled.RepoIssueNSID, issue.Did, issue.Rkey) ··· 206 return ErrPDSFail 207 } 208 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 209 Collection: tangled.RepoIssueNSID, 210 SwapRecord: ex.Cid, 211 Record: &lexutil.LexiconTypeDecoder{ 212 Val: &record, ··· 222 return ErrDatabaseFail 223 } 224 225 - // TODO: notify PutIssue 226 227 return nil 228 } 229 230 func (s *Service) DeleteIssue(ctx context.Context, issue *models.Issue) error { 231 l := s.logger.With("method", "DeleteIssue") 232 - sess := session.FromContext(ctx) 233 - if sess == nil { 234 l.Error("user session is missing in context") 235 return ErrForbidden 236 } 237 - sessDid := sess.Data.AccountDID 238 - l = l.With("did", sessDid) 239 240 - if sessDid != syntax.DID(issue.Did) { 241 l.Error("only author can edit the issue") 242 return ErrForbidden 243 } ··· 254 return ErrDatabaseFail 255 } 256 257 - atpclient := sess.APIClient() 258 _, err = atproto.RepoDeleteRecord(ctx, atpclient, &atproto.RepoDeleteRecord_Input{ 259 Collection: tangled.RepoIssueNSID, 260 Repo: issue.Did,
··· 61 62 func (s *Service) NewIssue(ctx context.Context, repo *models.Repo, title, body string) (*models.Issue, error) { 63 l := s.logger.With("method", "NewIssue") 64 + sess, ok := session.FromContext(ctx) 65 + if !ok { 66 l.Error("user session is missing in context") 67 return nil, ErrForbidden 68 } 69 + authorDid := syntax.DID(sess.User.Did) 70 + atpclient := sess.AtpClient 71 l = l.With("did", authorDid) 72 73 mentions, references := s.refResolver.Resolve(ctx, body) 74 75 issue := models.Issue{ 76 + Did: authorDid.String(), 77 Rkey: tid.TID(), 78 + RepoAt: repo.RepoAt(), 79 Title: title, 80 Body: body, 81 Created: time.Now(), 82 Mentions: mentions, 83 References: references, 84 + Open: true, 85 Repo: repo, 86 } 87 ··· 102 return nil, ErrDatabaseFail 103 } 104 105 record := issue.AsRecord() 106 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 107 + Repo: issue.Did, 108 Collection: tangled.RepoIssueNSID, 109 Rkey: issue.Rkey, 110 Record: &lexutil.LexiconTypeDecoder{ ··· 163 164 func (s *Service) EditIssue(ctx context.Context, issue *models.Issue) error { 165 l := s.logger.With("method", "EditIssue") 166 + sess, ok := session.FromContext(ctx) 167 + if !ok { 168 l.Error("user session is missing in context") 169 return ErrForbidden 170 } 171 + atpclient := sess.AtpClient 172 + l = l.With("did", sess.User.Did) 173 174 mentions, references := s.refResolver.Resolve(ctx, issue.Body) 175 issue.Mentions = mentions 176 issue.References = references 177 178 + if sess.User.Did != issue.Did { 179 l.Error("only author can edit the issue") 180 return ErrForbidden 181 } ··· 197 return ErrDatabaseFail 198 } 199 200 record := issue.AsRecord() 201 202 ex, err := atproto.RepoGetRecord(ctx, atpclient, "", tangled.RepoIssueNSID, issue.Did, issue.Rkey) ··· 205 return ErrPDSFail 206 } 207 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 208 + Repo: issue.Did, 209 Collection: tangled.RepoIssueNSID, 210 + Rkey: issue.Rkey, 211 SwapRecord: ex.Cid, 212 Record: &lexutil.LexiconTypeDecoder{ 213 Val: &record, ··· 223 return ErrDatabaseFail 224 } 225 226 + // TODO: notify EditIssue 227 228 return nil 229 } 230 231 func (s *Service) DeleteIssue(ctx context.Context, issue *models.Issue) error { 232 l := s.logger.With("method", "DeleteIssue") 233 + sess, ok := session.FromContext(ctx) 234 + if !ok { 235 l.Error("user session is missing in context") 236 return ErrForbidden 237 } 238 + atpclient := sess.AtpClient 239 + l = l.With("did", sess.User.Did) 240 241 + if sess.User.Did != issue.Did { 242 l.Error("only author can edit the issue") 243 return ErrForbidden 244 } ··· 255 return ErrDatabaseFail 256 } 257 258 _, err = atproto.RepoDeleteRecord(ctx, atpclient, &atproto.RepoDeleteRecord_Input{ 259 Collection: tangled.RepoIssueNSID, 260 Repo: issue.Did,
+6 -6
appview/service/issue/state.go
··· 13 14 func (s *Service) CloseIssue(ctx context.Context, issue *models.Issue) error { 15 l := s.logger.With("method", "CloseIssue") 16 - sess := session.FromContext(ctx) 17 - if sess == nil { 18 l.Error("user session is missing in context") 19 return ErrUnAuthenticated 20 } 21 - sessDid := sess.Data.AccountDID 22 l = l.With("did", sessDid) 23 24 // TODO: make this more granular ··· 49 50 func (s *Service) ReopenIssue(ctx context.Context, issue *models.Issue) error { 51 l := s.logger.With("method", "ReopenIssue") 52 - sess := session.FromContext(ctx) 53 - if sess == nil { 54 l.Error("user session is missing in context") 55 return ErrUnAuthenticated 56 } 57 - sessDid := sess.Data.AccountDID 58 l = l.With("did", sessDid) 59 60 // TODO: make this more granular
··· 13 14 func (s *Service) CloseIssue(ctx context.Context, issue *models.Issue) error { 15 l := s.logger.With("method", "CloseIssue") 16 + sess, ok := session.FromContext(ctx) 17 + if !ok { 18 l.Error("user session is missing in context") 19 return ErrUnAuthenticated 20 } 21 + sessDid := syntax.DID(sess.User.Did) 22 l = l.With("did", sessDid) 23 24 // TODO: make this more granular ··· 49 50 func (s *Service) ReopenIssue(ctx context.Context, issue *models.Issue) error { 51 l := s.logger.With("method", "ReopenIssue") 52 + sess, ok := session.FromContext(ctx) 53 + if !ok { 54 l.Error("user session is missing in context") 55 return ErrUnAuthenticated 56 } 57 + sessDid := syntax.DID(sess.User.Did) 58 l = l.With("did", sessDid) 59 60 // TODO: make this more granular
appview/service/repo/errors.go

This file has not been changed.

+12 -7
appview/service/repo/repo.go
··· 6 "time" 7 8 "github.com/bluesky-social/indigo/api/atproto" 9 "tangled.org/core/api/tangled" 10 "tangled.org/core/appview/config" 11 "tangled.org/core/appview/db" ··· 40 // It expects atproto session to be passed in `ctx` 41 func (s *Service) NewRepo(ctx context.Context, name, description, knot string) (*models.Repo, error) { 42 l := s.logger.With("method", "NewRepo") 43 - sess := session.FromContext(ctx) 44 - if sess == nil { 45 l.Error("user session is missing in context") 46 return nil, ErrForbidden 47 } 48 49 - ownerDid := sess.Data.AccountDID 50 - l = l.With("did", ownerDid) 51 52 repo := models.Repo{ 53 - Did: ownerDid.String(), 54 Name: name, 55 Knot: knot, 56 Rkey: tid.TID(), ··· 72 return nil, ErrDatabaseFail 73 } 74 75 - atpclient := sess.APIClient() 76 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 77 - Collection: tangled.RepoNSID, 78 Repo: repo.Did, 79 }) 80 if err != nil { 81 l.Error("atproto.RepoPutRecord failed", "err", err)
··· 6 "time" 7 8 "github.com/bluesky-social/indigo/api/atproto" 9 + lexutil "github.com/bluesky-social/indigo/lex/util" 10 "tangled.org/core/api/tangled" 11 "tangled.org/core/appview/config" 12 "tangled.org/core/appview/db" ··· 41 // It expects atproto session to be passed in `ctx` 42 func (s *Service) NewRepo(ctx context.Context, name, description, knot string) (*models.Repo, error) { 43 l := s.logger.With("method", "NewRepo") 44 + sess, ok := session.FromContext(ctx) 45 + if !ok { 46 l.Error("user session is missing in context") 47 return nil, ErrForbidden 48 } 49 50 + atpclient := sess.AtpClient 51 + l = l.With("did", sess.User.Did) 52 53 repo := models.Repo{ 54 + Did: sess.User.Did, 55 Name: name, 56 Knot: knot, 57 Rkey: tid.TID(), ··· 73 return nil, ErrDatabaseFail 74 } 75 76 + record := repo.AsRecord() 77 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 78 Repo: repo.Did, 79 + Collection: tangled.RepoNSID, 80 + Rkey: repo.Rkey, 81 + Record: &lexutil.LexiconTypeDecoder{ 82 + Val: &record, 83 + }, 84 }) 85 if err != nil { 86 l.Error("atproto.RepoPutRecord failed", "err", err)
+18 -19
appview/service/repo/repoinfo.go
··· 6 "github.com/bluesky-social/indigo/atproto/identity" 7 "tangled.org/core/appview/db" 8 "tangled.org/core/appview/models" 9 - "tangled.org/core/appview/oauth" 10 "tangled.org/core/appview/pages/repoinfo" 11 ) 12 13 - // GetRepoInfo converts given `Repo` to `RepoInfo` object. 14 - // The `user` can be nil. 15 - // NOTE: RepoInfo is bad design and should be removed in future. 16 - // avoid using this method if you can. 17 - func (s *Service) GetRepoInfo( 18 ctx context.Context, 19 ownerId *identity.Identity, 20 baseRepo *models.Repo, 21 currentDir, ref string, 22 - user *oauth.User, 23 - ) (*repoinfo.RepoInfo, error) { 24 var ( 25 repoAt = baseRepo.RepoAt() 26 isStarred = false 27 roles = repoinfo.RolesInRepo{} 28 ) 29 - if user != nil { 30 - isStarred = db.GetStarStatus(s.db, user.Did, repoAt) 31 - roles.Roles = s.enforcer.GetPermissionsInRepo(user.Did, baseRepo.Knot, baseRepo.DidSlashRepo()) 32 } 33 34 stats := baseRepo.RepoStats 35 if stats == nil { 36 starCount, err := db.GetStarCount(s.db, repoAt) 37 if err != nil { 38 - return nil, err 39 } 40 issueCount, err := db.GetIssueCount(s.db, repoAt) 41 if err != nil { 42 - return nil, err 43 } 44 pullCount, err := db.GetPullCount(s.db, repoAt) 45 if err != nil { 46 - return nil, err 47 } 48 stats = &models.RepoStats{ 49 StarCount: starCount, ··· 57 if baseRepo.Source != "" { 58 sourceRepo, err = db.GetRepoByAtUri(s.db, baseRepo.Source) 59 if err != nil { 60 - return nil, err 61 } 62 } 63 64 - repoInfo := &repoinfo.RepoInfo{ 65 - // ok this is basically a models.Repo 66 OwnerDid: baseRepo.Did, 67 OwnerHandle: ownerId.Handle.String(), // TODO: shouldn't use 68 Name: baseRepo.Name, ··· 85 IsStarred: isStarred, 86 Roles: roles, 87 } 88 - 89 - return repoInfo, nil 90 }
··· 6 "github.com/bluesky-social/indigo/atproto/identity" 7 "tangled.org/core/appview/db" 8 "tangled.org/core/appview/models" 9 "tangled.org/core/appview/pages/repoinfo" 10 + "tangled.org/core/appview/session" 11 ) 12 13 + // MakeRepoInfo constructs [repoinfo.RepoInfo] object from given [models.Repo]. 14 + // 15 + // NOTE: [repoinfo.RepoInfo] is bad design and should be removed in future. 16 + // Avoid using this method if you can. 17 + func (s *Service) MakeRepoInfo( 18 ctx context.Context, 19 ownerId *identity.Identity, 20 baseRepo *models.Repo, 21 currentDir, ref string, 22 + ) repoinfo.RepoInfo { 23 var ( 24 repoAt = baseRepo.RepoAt() 25 isStarred = false 26 roles = repoinfo.RolesInRepo{} 27 + l = s.logger.With("method", "MakeRepoInfo").With("repoAt", repoAt) 28 ) 29 + sess, ok := session.FromContext(ctx) 30 + if ok { 31 + isStarred = db.GetStarStatus(s.db, sess.User.Did, repoAt) 32 + roles.Roles = s.enforcer.GetPermissionsInRepo(sess.User.Did, baseRepo.Knot, baseRepo.DidSlashRepo()) 33 } 34 35 stats := baseRepo.RepoStats 36 if stats == nil { 37 starCount, err := db.GetStarCount(s.db, repoAt) 38 if err != nil { 39 + l.Error("failed to get star count", "err", err) 40 } 41 issueCount, err := db.GetIssueCount(s.db, repoAt) 42 if err != nil { 43 + l.Error("failed to get issue count", "err", err) 44 } 45 pullCount, err := db.GetPullCount(s.db, repoAt) 46 if err != nil { 47 + l.Error("failed to get pull count", "err", err) 48 } 49 stats = &models.RepoStats{ 50 StarCount: starCount, ··· 58 if baseRepo.Source != "" { 59 sourceRepo, err = db.GetRepoByAtUri(s.db, baseRepo.Source) 60 if err != nil { 61 + l.Error("failed to get source repo", "source", baseRepo.Source, "err", err) 62 } 63 } 64 65 + return repoinfo.RepoInfo{ 66 + // this is basically a models.Repo 67 OwnerDid: baseRepo.Did, 68 OwnerHandle: ownerId.Handle.String(), // TODO: shouldn't use 69 Name: baseRepo.Name, ··· 86 IsStarred: isStarred, 87 Roles: roles, 88 } 89 }
+8 -10
appview/session/context.go
··· 3 import ( 4 "context" 5 6 - toauth "tangled.org/core/appview/oauth" 7 ) 8 9 type ctxKey struct{} ··· 12 return context.WithValue(ctx, ctxKey{}, &sess) 13 } 14 15 - func FromContext(ctx context.Context) *Session { 16 sess, ok := ctx.Value(ctxKey{}).(*Session) 17 - if !ok { 18 - return nil 19 - } 20 - return sess 21 } 22 23 - func UserFromContext(ctx context.Context) *toauth.User { 24 - sess := FromContext(ctx) 25 - if sess == nil { 26 return nil 27 } 28 - return sess.User() 29 }
··· 3 import ( 4 "context" 5 6 + "tangled.org/core/appview/oauth" 7 ) 8 9 type ctxKey struct{} ··· 12 return context.WithValue(ctx, ctxKey{}, &sess) 13 } 14 15 + func FromContext(ctx context.Context) (*Session, bool) { 16 sess, ok := ctx.Value(ctxKey{}).(*Session) 17 + return sess, ok 18 } 19 20 + // UserFromContext returns optional MultiAccountUser from context. 21 + func UserFromContext(ctx context.Context) *oauth.MultiAccountUser { 22 + sess, ok := ctx.Value(ctxKey{}).(*Session) 23 + if !ok { 24 return nil 25 } 26 + return sess.User 27 }
+4 -17
appview/session/session.go
··· 1 package session 2 3 import ( 4 - "github.com/bluesky-social/indigo/atproto/auth/oauth" 5 - toauth "tangled.org/core/appview/oauth" 6 ) 7 8 - // Session is a lightweight wrapper over indigo-oauth ClientSession 9 type Session struct { 10 - *oauth.ClientSession 11 - } 12 - 13 - func New(atSess *oauth.ClientSession) Session { 14 - return Session{ 15 - atSess, 16 - } 17 - } 18 - 19 - func (s *Session) User() *toauth.User { 20 - return &toauth.User{ 21 - Did: string(s.Data.AccountDID), 22 - Pds: s.Data.HostURL, 23 - } 24 }
··· 1 package session 2 3 import ( 4 + "github.com/bluesky-social/indigo/atproto/client" 5 + "tangled.org/core/appview/oauth" 6 ) 7 8 type Session struct { 9 + User *oauth.MultiAccountUser // TODO: move MultiAccountUser def to here 10 + AtpClient *client.APIClient 11 }
appview/state/legacy_bridge.go

This file has not been changed.

appview/web/handler/oauth.go

This file has not been changed.

+13 -35
appview/web/handler/user_repo_issues.go
··· 53 54 // render page 55 err = func() error { 56 - user := session.UserFromContext(ctx) 57 - repoinfo, err := rs.GetRepoInfo(ctx, repoOwnerId, repo, "", "", user) 58 - if err != nil { 59 - return err 60 - } 61 labelDefs, err := db.GetLabelDefinitions( 62 d, 63 orm.FilterIn("at_uri", repo.Labels), ··· 71 defs[l.AtUri().String()] = &l 72 } 73 return p.RepoIssues(w, pages.RepoIssuesParams{ 74 - LoggedInUser: user, 75 - RepoInfo: *repoinfo, 76 77 Issues: issues, 78 LabelDefs: defs, ··· 108 109 // render 110 err := func() error { 111 - user := session.UserFromContext(ctx) 112 - repoinfo, err := rs.GetRepoInfo(ctx, repoOwnerId, issue.Repo, "", "", user) 113 - if err != nil { 114 - l.Error("failed to load repo", "err", err) 115 - return err 116 - } 117 - 118 reactionMap, err := db.GetReactionMap(d, 20, issue.AtUri()) 119 if err != nil { 120 l.Error("failed to get issue reactions", "err", err) ··· 122 } 123 124 userReactions := map[models.ReactionKind]bool{} 125 - if user != nil { 126 - userReactions = db.GetReactionStatusMap(d, user.Did, issue.AtUri()) 127 } 128 129 backlinks, err := db.GetBacklinks(d, issue.AtUri()) ··· 148 } 149 150 return p.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 151 - LoggedInUser: user, 152 - RepoInfo: *repoinfo, 153 Issue: issue, 154 CommentList: issue.CommentList(), 155 Backlinks: backlinks, 156 - OrderedReactionKinds: models.OrderedReactionKinds, 157 Reactions: reactionMap, 158 UserReacted: userReactions, 159 LabelDefs: defs, ··· 174 175 // render 176 err := func() error { 177 - user := session.UserFromContext(ctx) 178 repo, ok := request.RepoFromContext(ctx) 179 if !ok { 180 return fmt.Errorf("malformed request") ··· 183 if !ok { 184 return fmt.Errorf("malformed request") 185 } 186 - repoinfo, err := rs.GetRepoInfo(ctx, repoOwnerId, repo, "", "", user) 187 - if err != nil { 188 - return err 189 - } 190 return p.RepoNewIssue(w, pages.RepoNewIssueParams{ 191 - LoggedInUser: user, 192 - RepoInfo: *repoinfo, 193 }) 194 }() 195 if err != nil { ··· 217 body = r.FormValue("body") 218 ) 219 220 - _, err := is.NewIssue(ctx, repo, title, body) 221 if err != nil { 222 if errors.Is(err, isvc.ErrDatabaseFail) { 223 p.Notice(w, noticeId, "Failed to create issue.") ··· 228 } 229 return 230 } 231 - p.HxLocation(w, "/") 232 } 233 } 234 ··· 251 252 // render 253 err := func() error { 254 - user := session.UserFromContext(ctx) 255 - repoinfo, err := rs.GetRepoInfo(ctx, repoOwnerId, issue.Repo, "", "", user) 256 - if err != nil { 257 - return err 258 - } 259 return p.EditIssueFragment(w, pages.EditIssueParams{ 260 - LoggedInUser: user, 261 - RepoInfo: *repoinfo, 262 263 Issue: issue, 264 })
··· 53 54 // render page 55 err = func() error { 56 labelDefs, err := db.GetLabelDefinitions( 57 d, 58 orm.FilterIn("at_uri", repo.Labels), ··· 66 defs[l.AtUri().String()] = &l 67 } 68 return p.RepoIssues(w, pages.RepoIssuesParams{ 69 + LoggedInUser: session.UserFromContext(ctx), 70 + RepoInfo: rs.MakeRepoInfo(ctx, repoOwnerId, repo, "", ""), 71 72 Issues: issues, 73 LabelDefs: defs, ··· 103 104 // render 105 err := func() error { 106 reactionMap, err := db.GetReactionMap(d, 20, issue.AtUri()) 107 if err != nil { 108 l.Error("failed to get issue reactions", "err", err) ··· 110 } 111 112 userReactions := map[models.ReactionKind]bool{} 113 + if sess, ok := session.FromContext(ctx); ok { 114 + userReactions = db.GetReactionStatusMap(d, sess.User.Did, issue.AtUri()) 115 } 116 117 backlinks, err := db.GetBacklinks(d, issue.AtUri()) ··· 136 } 137 138 return p.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 139 + LoggedInUser: session.UserFromContext(ctx), 140 + RepoInfo: rs.MakeRepoInfo(ctx, repoOwnerId, issue.Repo, "", ""), 141 Issue: issue, 142 CommentList: issue.CommentList(), 143 Backlinks: backlinks, 144 Reactions: reactionMap, 145 UserReacted: userReactions, 146 LabelDefs: defs, ··· 161 162 // render 163 err := func() error { 164 repo, ok := request.RepoFromContext(ctx) 165 if !ok { 166 return fmt.Errorf("malformed request") ··· 169 if !ok { 170 return fmt.Errorf("malformed request") 171 } 172 return p.RepoNewIssue(w, pages.RepoNewIssueParams{ 173 + LoggedInUser: session.UserFromContext(ctx), 174 + RepoInfo: rs.MakeRepoInfo(ctx, repoOwnerId, repo, "", ""), 175 }) 176 }() 177 if err != nil { ··· 199 body = r.FormValue("body") 200 ) 201 202 + issue, err := is.NewIssue(ctx, repo, title, body) 203 if err != nil { 204 if errors.Is(err, isvc.ErrDatabaseFail) { 205 p.Notice(w, noticeId, "Failed to create issue.") ··· 210 } 211 return 212 } 213 + ownerSlashRepo := reporesolver.GetBaseRepoPath(r, issue.Repo) 214 + p.HxLocation(w, fmt.Sprintf("/%s/issues/%d", ownerSlashRepo, issue.IssueId)) 215 } 216 } 217 ··· 234 235 // render 236 err := func() error { 237 return p.EditIssueFragment(w, pages.EditIssueParams{ 238 + LoggedInUser: session.UserFromContext(ctx), 239 + RepoInfo: rs.MakeRepoInfo(ctx, repoOwnerId, issue.Repo, "", ""), 240 241 Issue: issue, 242 })
+13 -13
appview/web/middleware/auth.go
··· 21 return 22 } 23 24 - sess := session.New(atSess) 25 - 26 ctx := session.IntoContext(r.Context(), sess) 27 next.ServeHTTP(w, r.WithContext(ctx)) 28 }) ··· 44 45 loginURL := fmt.Sprintf("/login?return_url=%s", url.QueryEscape(returnURL)) 46 47 - redirectFunc := func(w http.ResponseWriter, r *http.Request) { 48 - http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) 49 - } 50 - if r.Header.Get("HX-Request") == "true" { 51 - redirectFunc = func(w http.ResponseWriter, _ *http.Request) { 52 w.Header().Set("HX-Redirect", loginURL) 53 w.WriteHeader(http.StatusOK) 54 } 55 - } 56 - 57 - sess := session.FromContext(ctx) 58 - if sess == nil { 59 - l.Debug("no session, redirecting...") 60 - redirectFunc(w, r) 61 return 62 } 63
··· 21 return 22 } 23 24 + registry := o.GetAccounts(r) 25 + sess := session.Session{ 26 + User: &oauth.MultiAccountUser{ 27 + Did: atSess.Data.AccountDID.String(), 28 + Accounts: registry.Accounts, 29 + }, 30 + AtpClient: atSess.APIClient(), 31 + } 32 ctx := session.IntoContext(r.Context(), sess) 33 next.ServeHTTP(w, r.WithContext(ctx)) 34 }) ··· 50 51 loginURL := fmt.Sprintf("/login?return_url=%s", url.QueryEscape(returnURL)) 52 53 + if _, ok := session.FromContext(ctx); !ok { 54 + l.Debug("no session, redirecting...") 55 + if r.Header.Get("HX-Request") == "true" { 56 w.Header().Set("HX-Redirect", loginURL) 57 w.WriteHeader(http.StatusOK) 58 + } else { 59 + http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) 60 } 61 return 62 } 63
appview/web/middleware/ensuredidorhandle.go

This file has not been changed.

appview/web/middleware/log.go

This file has not been changed.

appview/web/middleware/middleware.go

This file has not been changed.

-1
appview/web/middleware/normalize.go
··· 44 } 45 46 next.ServeHTTP(w, r) 47 - return 48 }) 49 } 50 }
··· 44 } 45 46 next.ServeHTTP(w, r) 47 }) 48 } 49 }
appview/web/middleware/paginate.go

This file has not been changed.

appview/web/middleware/resolve.go

This file has not been changed.

appview/web/readme.md

This file has not been changed.

appview/web/request/context.go

This file has not been changed.

+1 -1
appview/web/routes.go
··· 187 }) 188 189 r.Mount("/pulls", s.PullsRouter(mw)) 190 - r.Mount("/pipelines", s.PipelinesRouter()) 191 r.Mount("/labels", s.LabelsRouter()) 192 193 // These routes get proxied to the knot
··· 187 }) 188 189 r.Mount("/pulls", s.PullsRouter(mw)) 190 + r.Mount("/pipelines", s.PipelinesRouter(mw)) 191 r.Mount("/labels", s.LabelsRouter()) 192 193 // These routes get proxied to the knot
cmd/appview/main.go

This file has not been changed.

History

14 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
appview/{service,web}: service layer
1/3 failed, 2/3 success
expand
merge conflicts detected
expand
  • appview/pages/templates/user/login.html:33
  • appview/state/profile.go:817
  • appview/pages/templates/user/login.html:31
  • appview/pages/templates/user/login.html:93
  • appview/repo/artifact.go:251
  • appview/state/profile.go:528
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
1/3 failed, 2/3 success
expand
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
3/3 failed
expand
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
2/3 failed, 1/3 success
expand
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
appview/{service,web}: service layer
1/3 failed, 2/3 timeout
expand
expand 0 comments
1 commit
expand
draft: appview/service: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
draft: appview/service: service layer
1/3 failed, 1/3 timeout, 1/3 success
expand
expand 0 comments
1 commit
expand
draft: appview/service: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
draft: appview/service: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
draft: appview/service: service layer
3/3 success
expand
expand 0 comments
1 commit
expand
draft: appview: service layer
3/3 failed
expand
expand 0 comments
1 commit
expand
draft: appview: service layer
3/3 failed
expand
expand 0 comments