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
+71 -65
Interdiff #5 #6
appview/oauth/handler.go

This file has not been changed.

appview/oauth/session.go

This file has not been changed.

+24 -40
appview/service/issue/issue.go
··· 2 2 3 3 import ( 4 4 "context" 5 - "errors" 6 5 "log/slog" 7 6 "time" 8 7 ··· 13 12 "tangled.org/core/appview/config" 14 13 "tangled.org/core/appview/db" 15 14 issues_indexer "tangled.org/core/appview/indexer/issues" 15 + "tangled.org/core/appview/mentions" 16 16 "tangled.org/core/appview/models" 17 17 "tangled.org/core/appview/notify" 18 - "tangled.org/core/appview/pages/markup" 19 18 "tangled.org/core/appview/session" 20 19 "tangled.org/core/appview/validator" 21 20 "tangled.org/core/idresolver" ··· 24 23 ) 25 24 26 25 type Service struct { 27 - config *config.Config 28 - db *db.DB 29 - enforcer *rbac.Enforcer 30 - indexer *issues_indexer.Indexer 31 - logger *slog.Logger 32 - notifier notify.Notifier 33 - idResolver *idresolver.Resolver 34 - validator *validator.Validator 26 + config *config.Config 27 + db *db.DB 28 + enforcer *rbac.Enforcer 29 + indexer *issues_indexer.Indexer 30 + logger *slog.Logger 31 + notifier notify.Notifier 32 + idResolver *idresolver.Resolver 33 + refResolver *mentions.Resolver 34 + validator *validator.Validator 35 35 } 36 36 37 37 func NewService( ··· 41 41 enforcer *rbac.Enforcer, 42 42 notifier notify.Notifier, 43 43 idResolver *idresolver.Resolver, 44 + refResolver *mentions.Resolver, 44 45 indexer *issues_indexer.Indexer, 45 46 validator *validator.Validator, 46 47 ) Service { ··· 52 53 logger, 53 54 notifier, 54 55 idResolver, 56 + refResolver, 55 57 validator, 56 58 } 57 59 } 58 60 59 - var ( 60 - ErrUnAuthenticated = errors.New("user session missing") 61 - ErrForbidden = errors.New("unauthorized operation") 62 - ErrDatabaseFail = errors.New("db op fail") 63 - ErrPDSFail = errors.New("pds op fail") 64 - ErrValidationFail = errors.New("issue validation fail") 65 - ) 66 - 67 61 func (s *Service) NewIssue(ctx context.Context, repo *models.Repo, title, body string) (*models.Issue, error) { 68 62 l := s.logger.With("method", "NewIssue") 69 63 sess := session.FromContext(ctx) ··· 74 68 authorDid := sess.Data.AccountDID 75 69 l = l.With("did", authorDid) 76 70 77 - // mentions, references := s.refResolver.Resolve(ctx, body) 78 - mentions := func() []syntax.DID { 79 - rawMentions := markup.FindUserMentions(body) 80 - idents := s.idResolver.ResolveIdents(ctx, rawMentions) 81 - l.Debug("parsed mentions", "raw", rawMentions, "idents", idents) 82 - var mentions []syntax.DID 83 - for _, ident := range idents { 84 - if ident != nil && !ident.Handle.IsInvalidHandle() { 85 - mentions = append(mentions, ident.DID) 86 - } 87 - } 88 - return mentions 89 - }() 71 + mentions, references := s.refResolver.Resolve(ctx, body) 90 72 91 73 issue := models.Issue{ 92 - RepoAt: repo.RepoAt(), 93 - Rkey: tid.TID(), 94 - Title: title, 95 - Body: body, 96 - Open: true, 97 - Did: authorDid.String(), 98 - Created: time.Now(), 99 - Repo: repo, 74 + RepoAt: repo.RepoAt(), 75 + Rkey: tid.TID(), 76 + Title: title, 77 + Body: body, 78 + Open: true, 79 + Did: authorDid.String(), 80 + Created: time.Now(), 81 + Mentions: mentions, 82 + References: references, 83 + Repo: repo, 100 84 } 101 85 102 86 if err := s.validator.ValidateIssue(&issue); err != nil { ··· 260 244 } 261 245 defer tx.Rollback() 262 246 263 - if err := db.DeleteIssues(tx, db.FilterEq("id", issue.Id)); err != nil { 247 + if err := db.DeleteIssues(tx, issue.Did, issue.Rkey); err != nil { 264 248 l.Error("db.DeleteIssues failed", "err", err) 265 249 return ErrDatabaseFail 266 250 }
appview/service/issue/state.go

This file has not been changed.

+16 -10
appview/service/repo/repo.go
··· 2 2 3 3 import ( 4 4 "context" 5 - "fmt" 6 5 "log/slog" 7 6 "time" 8 7 9 8 "github.com/bluesky-social/indigo/api/atproto" 10 - "github.com/bluesky-social/indigo/atproto/auth/oauth" 11 9 "tangled.org/core/api/tangled" 12 10 "tangled.org/core/appview/config" 13 11 "tangled.org/core/appview/db" 14 12 "tangled.org/core/appview/models" 13 + "tangled.org/core/appview/session" 15 14 "tangled.org/core/rbac" 16 15 "tangled.org/core/tid" 17 16 ) ··· 39 38 40 39 // NewRepo creates a repository 41 40 // It expects atproto session to be passed in `ctx` 42 - func (s *Service) NewRepo(ctx context.Context, name, description, knot string) error { 41 + func (s *Service) NewRepo(ctx context.Context, name, description, knot string) (*models.Repo, error) { 43 42 l := s.logger.With("method", "NewRepo") 44 - sess := fromContext(ctx) 43 + sess := session.FromContext(ctx) 44 + if sess == nil { 45 + l.Error("user session is missing in context") 46 + return nil, ErrForbidden 47 + } 45 48 46 49 ownerDid := sess.Data.AccountDID 47 50 l = l.With("did", ownerDid) ··· 59 62 60 63 tx, err := s.db.BeginTx(ctx, nil) 61 64 if err != nil { 62 - return fmt.Errorf("db.BeginTx: %w", err) 65 + l.Error("db.BeginTx failed", "err", err) 66 + return nil, ErrDatabaseFail 63 67 } 64 68 defer tx.Rollback() 65 69 70 + if err = db.AddRepo(tx, &repo); err != nil { 71 + l.Error("db.AddRepo failed", "err", err) 72 + return nil, ErrDatabaseFail 73 + } 74 + 66 75 atpclient := sess.APIClient() 67 76 _, err = atproto.RepoPutRecord(ctx, atpclient, &atproto.RepoPutRecord_Input{ 68 77 Collection: tangled.RepoNSID, 69 78 Repo: repo.Did, 70 79 }) 71 80 if err != nil { 72 - return fmt.Errorf("atproto.RepoPutRecord: %w", err) 81 + l.Error("atproto.RepoPutRecord failed", "err", err) 82 + return nil, ErrPDSFail 73 83 } 74 84 l.Info("wrote to PDS") 75 85 ··· 77 87 // ) 78 88 panic("unimplemented") 79 89 } 80 - 81 - func fromContext(ctx context.Context) oauth.ClientSession { 82 - panic("todo") 83 - }
appview/service/repo/repoinfo.go

This file has not been changed.

appview/session/context.go

This file has not been changed.

appview/session/session.go

This file has not been changed.

+4 -1
appview/state/legacy_bridge.go
··· 7 7 "tangled.org/core/appview/db" 8 8 "tangled.org/core/appview/indexer" 9 9 "tangled.org/core/appview/issues" 10 + "tangled.org/core/appview/mentions" 10 11 "tangled.org/core/appview/middleware" 11 12 "tangled.org/core/appview/notify" 12 13 "tangled.org/core/appview/oauth" ··· 24 25 *db.DB, 25 26 *rbac.Enforcer, 26 27 *idresolver.Resolver, 28 + *mentions.Resolver, 27 29 *indexer.Indexer, 28 30 *slog.Logger, 29 31 notify.Notifier, ··· 31 33 *pages.Pages, 32 34 *validator.Validator, 33 35 ) { 34 - return s.config, s.db, s.enforcer, s.idResolver, s.indexer, s.logger, s.notifier, s.oauth, s.pages, s.validator 36 + return s.config, s.db, s.enforcer, s.idResolver, s.mentionsResolver, s.indexer, s.logger, s.notifier, s.oauth, s.pages, s.validator 35 37 } 36 38 37 39 func (s *State) ExposeIssue() *issues.Issues { ··· 41 43 s.enforcer, 42 44 s.pages, 43 45 s.idResolver, 46 + s.mentionsResolver, 44 47 s.db, 45 48 s.config, 46 49 s.notifier,
appview/web/handler/oauth_client_metadata.go

This file has not been changed.

appview/web/handler/oauth_jwks.go

This file has not been changed.

appview/web/handler/user_repo_issues.go

This file has not been changed.

appview/web/handler/user_repo_issues_issue.go

This file has not been changed.

appview/web/handler/user_repo_issues_issue_close.go

This file has not been changed.

appview/web/handler/user_repo_issues_issue_edit.go

This file has not been changed.

-13
appview/web/handler/user_repo_issues_issue_opengraph.go
··· 1 - package handler 2 - 3 - import ( 4 - "net/http" 5 - 6 - "tangled.org/core/appview/service/issue" 7 - ) 8 - 9 - func IssueOpenGraph(s issue.Service) http.HandlerFunc { 10 - return func(w http.ResponseWriter, r *http.Request) { 11 - panic("unimplemented") 12 - } 13 - }
appview/web/handler/user_repo_issues_issue_reopen.go

This file has not been changed.

appview/web/handler/user_repo_issues_new.go

This file has not been changed.

appview/web/middleware/auth.go

This file has not been changed.

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.

appview/web/middleware/normalize.go

This file has not been changed.

appview/web/middleware/paginate.go

This file has not been changed.

appview/web/middleware/resolve.go

This file has not been changed.

appview/web/request/context.go

This file has not been changed.

+5 -1
appview/web/routes.go
··· 8 8 "tangled.org/core/appview/config" 9 9 "tangled.org/core/appview/db" 10 10 "tangled.org/core/appview/indexer" 11 + "tangled.org/core/appview/mentions" 11 12 "tangled.org/core/appview/notify" 12 13 "tangled.org/core/appview/oauth" 13 14 "tangled.org/core/appview/pages" ··· 32 33 // RouterFromState creates a web router from `state.State`. This exist to 33 34 // bridge between legacy web routers under `State` and new architecture 34 35 func RouterFromState(s *state.State) http.Handler { 35 - config, db, enforcer, idResolver, indexer, logger, notifier, oauth, pages, validator := s.Expose() 36 + config, db, enforcer, idResolver, refResolver, indexer, logger, notifier, oauth, pages, validator := s.Expose() 36 37 37 38 return Router( 38 39 logger, ··· 40 41 db, 41 42 enforcer, 42 43 idResolver, 44 + refResolver, 43 45 indexer, 44 46 notifier, 45 47 oauth, ··· 56 58 db *db.DB, 57 59 enforcer *rbac.Enforcer, 58 60 idResolver *idresolver.Resolver, 61 + mentionsResolver *mentions.Resolver, 59 62 indexer *indexer.Indexer, 60 63 notifier notify.Notifier, 61 64 oauth *oauth.OAuth, ··· 77 80 enforcer, 78 81 notifier, 79 82 idResolver, 83 + mentionsResolver, 80 84 indexer.Issues, 81 85 validator, 82 86 )
cmd/appview/main.go

This file has not been changed.

+11
appview/service/issue/errors.go
··· 1 + package issue 2 + 3 + import "errors" 4 + 5 + var ( 6 + ErrUnAuthenticated = errors.New("user session missing") 7 + ErrForbidden = errors.New("unauthorized operation") 8 + ErrDatabaseFail = errors.New("db op fail") 9 + ErrPDSFail = errors.New("pds op fail") 10 + ErrValidationFail = errors.New("issue validation fail") 11 + )
+11
appview/service/repo/errors.go
··· 1 + package repo 2 + 3 + import "errors" 4 + 5 + var ( 6 + ErrUnAuthenticated = errors.New("user session missing") 7 + ErrForbidden = errors.New("unauthorized operation") 8 + ErrDatabaseFail = errors.New("db op fail") 9 + ErrPDSFail = errors.New("pds op fail") 10 + ErrValidationFail = errors.New("repo validation fail") 11 + )

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