From e03cd93353861f9a133ddeca69a1b33c96ae5e5d Mon Sep 17 00:00:00 2001 From: Xeronith Date: Sat, 17 Sep 2022 16:24:23 +0430 Subject: [PATCH] refactor(workspace): :art: improve structure and format of the code --- greataped/app/models/repos/auth.go | 61 +++++++++++++++++++++++++++--- greataped/app/models/types/auth.go | 4 -- greataped/app/routes/follow.go | 6 +-- greataped/app/routes/followers.go | 24 +++++------- greataped/app/routes/following.go | 8 ++-- greataped/app/routes/inbox.go | 17 ++++----- greataped/app/routes/login.go | 41 +++++++++----------- greataped/app/routes/outbox.go | 18 ++++----- greataped/app/routes/profile.go | 24 +++--------- greataped/app/routes/signup.go | 8 +--- greataped/app/routes/upload.go | 4 +- greataped/app/routes/user.go | 14 +++---- greataped/app/routes/webfinger.go | 17 +++------ greataped/contracts/context.go | 6 +-- greataped/server/http_context.go | 12 +++--- 15 files changed, 133 insertions(+), 131 deletions(-) diff --git a/greataped/app/models/repos/auth.go b/greataped/app/models/repos/auth.go index 537555d..22cd80a 100644 --- a/greataped/app/models/repos/auth.go +++ b/greataped/app/models/repos/auth.go @@ -1,8 +1,12 @@ package repos import ( + "contracts" "db" + "errors" + "fmt" + "github.com/gofiber/fiber/v2" "gorm.io/gorm" ) @@ -41,18 +45,63 @@ func FindUser(dest interface{}, conds ...interface{}) *gorm.DB { } // FindUserById searches the user's table with the id given -func FindUserById(dest interface{}, id uint) *gorm.DB { - return FindUser(dest, "id = ?", id) +func FindUserById(id uint) (*User, error) { + user := &User{} + if err := FindUser(user, "id = ?", id).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &fiber.Error{ + Code: contracts.StatusNotFound, + Message: "user not found", + } + } else { + return nil, &fiber.Error{ + Code: contracts.StatusInternalServerError, + Message: err.Error(), + } + } + } + + return user, nil } // FindUserByEmail searches the user's table with the email given -func FindUserByEmail(dest interface{}, email string) *gorm.DB { - return FindUser(dest, "email = ?", email) +func FindUserByEmail(email string) (*User, error) { + user := &User{} + if err := FindUser(user, "email = ?", email).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &fiber.Error{ + Code: contracts.StatusNotFound, + Message: "user not found", + } + } else { + return nil, &fiber.Error{ + Code: contracts.StatusInternalServerError, + Message: err.Error(), + } + } + } + + return user, nil } // FindUserByUsername searches the user's table with the name given -func FindUserByUsername(dest interface{}, name string) *gorm.DB { - return FindUser(dest, "username = ?", name) +func FindUserByUsername(username string) (*User, error) { + user := &User{} + if err := FindUser(user, "username = ?", username).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, &fiber.Error{ + Code: contracts.StatusNotFound, + Message: fmt.Sprintf("user '%s' not found", username), + } + } else { + return nil, &fiber.Error{ + Code: contracts.StatusInternalServerError, + Message: err.Error(), + } + } + } + + return user, nil } // UpdateProfile updates the user's profile with the info given diff --git a/greataped/app/models/types/auth.go b/greataped/app/models/types/auth.go index 89c50e6..1d4bc57 100644 --- a/greataped/app/models/types/auth.go +++ b/greataped/app/models/types/auth.go @@ -36,10 +36,6 @@ type UserResponse struct { PrivateProfile bool `json:"private_profile"` } -type KeyResponse struct { - PrivateKey string `json:"privateKey"` -} - type AccessResponse struct { Token string `json:"token"` } diff --git a/greataped/app/routes/follow.go b/greataped/app/routes/follow.go index 7c84275..ad4902b 100644 --- a/greataped/app/routes/follow.go +++ b/greataped/app/routes/follow.go @@ -23,17 +23,17 @@ var Follow = route.New(HttpGet, "/u/:name/follow", func(x IContext) error { webfingerUrl := x.StringUtil().Format("https://%s/.well-known/webfinger?resource=acct:%s", parts[1], follower) resp, err := http.Get(webfingerUrl) if err != nil { - x.InternalServerError(err) + return err } data, err := io.ReadAll(resp.Body) if err != nil { - x.InternalServerError(err) + return err } webfinger, err := activitypub.UnmarshalWebfinger(data) if err != nil { - x.InternalServerError(err) + return err } template := "" diff --git a/greataped/app/routes/followers.go b/greataped/app/routes/followers.go index 46c3d0d..cacaec1 100644 --- a/greataped/app/routes/followers.go +++ b/greataped/app/routes/followers.go @@ -8,11 +8,8 @@ import ( "config" . "contracts" "encoding/json" - "errors" "server/route" "strconv" - - "gorm.io/gorm" ) var Followers = route.New(HttpGet, "/u/:username/followers", func(x IContext) error { @@ -24,17 +21,17 @@ var Followers = route.New(HttpGet, "/u/:username/followers", func(x IContext) er if username.IsFederated() { webfinger, err := x.GetWebFinger(username) if err != nil { - return x.InternalServerError(err) + return err } actor, err := x.GetActor(webfinger) if err != nil { - return x.InternalServerError(err) + return err } followers, err := x.GetOrderedCollection(actor.Followers) if err != nil { - return x.InternalServerError(err) + return err } return x.Activity(followers) @@ -45,7 +42,7 @@ var Followers = route.New(HttpGet, "/u/:username/followers", func(x IContext) er followers := &[]types.FollowerResponse{} err := repos.FindFollowers(followers, actor).Error if err != nil { - x.InternalServerError(err) + return err } items := []string{} @@ -75,7 +72,7 @@ var AcceptFollowRequest = route.New(HttpPut, "/u/:username/followers/:id/accept" follower := &repos.Follower{} if err := repos.FindFollowerById(follower, followerId).Error; err != nil { - return x.InternalServerError(err) + return err } data, _ := json.Marshal(&activitypub.Activity{ @@ -86,20 +83,19 @@ var AcceptFollowRequest = route.New(HttpPut, "/u/:username/followers/:id/accept" Object: follower.Activity, }) - user := &repos.User{} - err = repos.FindUserByUsername(user, username).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.NotFound("No record found for %s.", username) + user, err := repos.FindUserByUsername(username) + if err != nil { + return err } keyId := x.StringUtil().Format("%s://%s/u/%s#main-key", config.PROTOCOL, config.DOMAIN, username) if err := x.PostActivityStreamSigned(follower.HandleInbox, keyId, user.PrivateKey, data, nil); err != nil { - return x.InternalServerError(err) + return err } if err := repos.AcceptFollower(follower.ID).Error; err != nil { - return x.InternalServerError(err) + return err } return x.Nothing() diff --git a/greataped/app/routes/following.go b/greataped/app/routes/following.go index de538da..fefd216 100644 --- a/greataped/app/routes/following.go +++ b/greataped/app/routes/following.go @@ -19,17 +19,17 @@ var Following = route.New(HttpGet, "/u/:username/following", func(x IContext) er if username.IsFederated() { webfinger, err := x.GetWebFinger(username) if err != nil { - return x.InternalServerError(err) + return err } actor, err := x.GetActor(webfinger) if err != nil { - return x.InternalServerError(err) + return err } following, err := x.GetOrderedCollection(actor.Following) if err != nil { - return x.InternalServerError(err) + return err } return x.Activity(following) @@ -40,7 +40,7 @@ var Following = route.New(HttpGet, "/u/:username/following", func(x IContext) er followings := &[]types.FollowerResponse{} err := repos.FindFollowing(followings, actor).Error if err != nil { - x.InternalServerError(err) + return err } items := []string{} diff --git a/greataped/app/routes/inbox.go b/greataped/app/routes/inbox.go index 0f7a1ff..bab7a49 100644 --- a/greataped/app/routes/inbox.go +++ b/greataped/app/routes/inbox.go @@ -7,12 +7,10 @@ import ( "config" . "contracts" "encoding/json" - "errors" "server/route" "time" "github.com/mitchellh/mapstructure" - "gorm.io/gorm" ) var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error { @@ -23,10 +21,9 @@ var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error return x.BadRequest("Bad request") } - user := &repos.User{} - err := repos.FindUserByUsername(user, username).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.NotFound("No record found for %s.", username) + user, err := repos.FindUserByUsername(username) + if err != nil { + return err } keyId := x.StringUtil().Format("%s://%s/u/%s#main-key", config.PROTOCOL, config.DOMAIN, username) @@ -45,7 +42,7 @@ var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error { actor := &activitypub.Actor{} if err := x.GetActivityStreamSigned(url, keyId, user.PrivateKey, nil, actor); err != nil { - return x.InternalServerError(err) + return err } inbox = actor.Inbox @@ -53,7 +50,7 @@ var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error data, err := json.Marshal(activity) if err != nil { - return x.InternalServerError(err) + return err } follower := &repos.Follower{ @@ -78,12 +75,12 @@ var InboxPost = route.New(HttpPost, "/u/:username/inbox", func(x IContext) error }) if err := x.PostActivityStreamSigned(inbox, keyId, user.PrivateKey, data, nil); err != nil { - return x.InternalServerError(err) + return err } err := repos.AcceptFollower(follower.ID).Error if err != nil { - return x.InternalServerError(err) + return err } } diff --git a/greataped/app/routes/login.go b/greataped/app/routes/login.go index be66496..bf4c0bb 100644 --- a/greataped/app/routes/login.go +++ b/greataped/app/routes/login.go @@ -5,12 +5,9 @@ import ( "app/models/types" . "contracts" "encoding/json" - "errors" "server/route" "utility/jwt" "utility/password" - - "gorm.io/gorm" ) var Login = route.New(HttpPost, "/api/v1/login", func(x IContext) error { @@ -20,35 +17,33 @@ var Login = route.New(HttpPost, "/api/v1/login", func(x IContext) error { return err } - u := &repos.User{} - - err := repos.FindUserByEmail(u, body.Email).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.Unauthorized("Invalid email or password") + user, err := repos.FindUserByEmail(body.Email) + if err != nil { + return x.Unauthorized("invalid email or password") } - if err := password.Verify(u.Password, body.Password); err != nil { - return x.Unauthorized("Invalid email or password") + if err := password.Verify(user.Password, body.Password); err != nil { + return x.Unauthorized("invalid email or password") } token := jwt.Generate(&jwt.TokenPayload{ - ID: u.ID, + ID: user.ID, }) - actor, _ := json.MarshalIndent(createActor(u), "", " ") - webfinger, _ := json.MarshalIndent(createWebfinger(u), "", " ") + actor, _ := json.MarshalIndent(createActor(user), "", " ") + webfinger, _ := json.MarshalIndent(createWebfinger(user), "", " ") return x.Json(&types.AuthResponse{ User: &types.UserResponse{ - ID: u.ID, - Username: u.Username, - DisplayName: u.DisplayName, - Email: u.Email, - Bio: u.Bio, - Github: u.Github, - Avatar: u.Avatar, - Banner: u.Banner, - ApiKey: u.ApiKey, - PublicKey: u.PublicKey, + ID: user.ID, + Username: user.Username, + DisplayName: user.DisplayName, + Email: user.Email, + Bio: user.Bio, + Github: user.Github, + Avatar: user.Avatar, + Banner: user.Banner, + ApiKey: user.ApiKey, + PublicKey: user.PublicKey, Actor: string(actor), Webfinger: string(webfinger), }, diff --git a/greataped/app/routes/outbox.go b/greataped/app/routes/outbox.go index fc8f19a..dc501a6 100644 --- a/greataped/app/routes/outbox.go +++ b/greataped/app/routes/outbox.go @@ -7,11 +7,8 @@ import ( "config" . "contracts" "encoding/json" - "errors" "server/route" "time" - - "gorm.io/gorm" ) var OutboxPost = route.New(HttpPost, "/u/:username/outbox", func(x IContext) error { @@ -22,10 +19,9 @@ var OutboxPost = route.New(HttpPost, "/u/:username/outbox", func(x IContext) err return x.BadRequest(err) } - key := &types.KeyResponse{} - err := repos.FindUserByUsername(key, username).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.NotFound("No record found for %s.", username) + user, err := repos.FindUserByUsername(username) + if err != nil { + return err } keyId := x.StringUtil().Format("%s://%s/u/%s#main-key", config.PROTOCOL, config.DOMAIN, username) @@ -44,16 +40,16 @@ var OutboxPost = route.New(HttpPost, "/u/:username/outbox", func(x IContext) err if to != activitypub.Public { recipient := &activitypub.Actor{} - if err := x.GetActivityStreamSigned(to, keyId, key.PrivateKey, nil, recipient); err != nil { - return x.InternalServerError(err) + if err := x.GetActivityStreamSigned(to, keyId, user.PrivateKey, nil, recipient); err != nil { + return err } to = recipient.ID data, _ := json.Marshal(activity) output := &struct{}{} - if err := x.PostActivityStreamSigned(recipient.Inbox, keyId, key.PrivateKey, data, output); err != nil { - return x.InternalServerError(err) + if err := x.PostActivityStreamSigned(recipient.Inbox, keyId, user.PrivateKey, data, output); err != nil { + return err } } diff --git a/greataped/app/routes/profile.go b/greataped/app/routes/profile.go index 1758581..90b927d 100644 --- a/greataped/app/routes/profile.go +++ b/greataped/app/routes/profile.go @@ -6,10 +6,7 @@ import ( "config" . "contracts" "encoding/json" - "errors" "server/route" - - "gorm.io/gorm" ) var Profile = route.New(HttpGet, "/profile", func(x IContext) error { @@ -21,15 +18,9 @@ var Profile = route.New(HttpGet, "/profile", func(x IContext) error { }) var GetProfile = route.New(HttpGet, "/api/v1/profile", func(x IContext) error { - userId := x.GetUser() - user := &repos.User{} - - if err := repos.FindUserById(user, userId).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.Unauthorized("not_found") - } else { - return x.InternalServerError(err) - } + user, err := repos.FindUserById(x.GetUser()) + if err != nil { + return x.Unauthorized(err) } actor, _ := json.MarshalIndent(createActor(user), "", " ") @@ -55,12 +46,9 @@ var UpdateProfile = route.New(HttpPost, "/api/v1/profile", func(x IContext) erro return err } - userId := x.GetUser() - user := &repos.User{} - - err := repos.FindUserById(user, userId).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.Unauthorized("not_found") + user, err := repos.FindUserById(x.GetUser()) + if err != nil { + return x.Unauthorized(err) } access := repos.ACCESS_PUBLIC diff --git a/greataped/app/routes/signup.go b/greataped/app/routes/signup.go index 8584c8b..66db1b8 100644 --- a/greataped/app/routes/signup.go +++ b/greataped/app/routes/signup.go @@ -4,13 +4,10 @@ import ( "app/models/repos" "app/models/types" . "contracts" - "errors" "server/route" "utility" "utility/jwt" "utility/password" - - "gorm.io/gorm" ) var Signup = route.New(HttpPost, "/api/v1/signup", func(x IContext) error { @@ -19,9 +16,8 @@ var Signup = route.New(HttpPost, "/api/v1/signup", func(x IContext) error { return err } - err := repos.FindUserByEmail(&struct{ ID string }{}, body.Email).Error - if !errors.Is(err, gorm.ErrRecordNotFound) { - return x.Conflict("Email already exists") + if _, err := repos.FindUserByEmail(body.Email); err == nil { + return x.Conflict("email already exists") } privateKey, publicKey, err := utility.GenerateRSAKeyPair() diff --git a/greataped/app/routes/upload.go b/greataped/app/routes/upload.go index 2fa7869..bf06d93 100644 --- a/greataped/app/routes/upload.go +++ b/greataped/app/routes/upload.go @@ -12,7 +12,7 @@ import ( var Upload = route.New(contracts.HttpPost, "/upload", func(x contracts.IContext) error { file, err := x.Request().FormFile("file") if err != nil { - return x.InternalServerError(err) + return err } uuid := uuid.New().String() @@ -21,7 +21,7 @@ var Upload = route.New(contracts.HttpPost, "/upload", func(x contracts.IContext) filePath := path.Join(config.UPLOAD_PATH, fileName) if err = x.SaveFile(file, filePath); err != nil { - return x.InternalServerError(err) + return err } return x.Json(struct { diff --git a/greataped/app/routes/user.go b/greataped/app/routes/user.go index 5f4e47e..e58db46 100644 --- a/greataped/app/routes/user.go +++ b/greataped/app/routes/user.go @@ -5,10 +5,7 @@ import ( "app/models/repos" "config" "contracts" - "errors" "server/route" - - "gorm.io/gorm" ) var User = route.New(contracts.HttpGet, "/u/:username", func(x contracts.IContext) error { @@ -20,20 +17,19 @@ var User = route.New(contracts.HttpGet, "/u/:username", func(x contracts.IContex if username.IsFederated() { webfinger, err := x.GetWebFinger(username) if err != nil { - return x.InternalServerError(err) + return err } actor, err := x.GetActor(webfinger) if err != nil { - return x.InternalServerError(err) + return err } return x.Activity(actor) } else { - user := &repos.User{} - err := repos.FindUserByUsername(user, username.String()).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.NotFound("No record found for %s.", username) + user, err := repos.FindUserByUsername(username.String()) + if err != nil { + return err } str := x.StringUtil() diff --git a/greataped/app/routes/webfinger.go b/greataped/app/routes/webfinger.go index 3cb2bb4..9112702 100644 --- a/greataped/app/routes/webfinger.go +++ b/greataped/app/routes/webfinger.go @@ -4,11 +4,8 @@ import ( "app/models/repos" "config" . "contracts" - "errors" "fmt" "server/route" - - "gorm.io/gorm" ) var WebFinger = route.New(HttpGet, "/.well-known/webfinger", func(x IContext) error { @@ -17,16 +14,12 @@ var WebFinger = route.New(HttpGet, "/.well-known/webfinger", func(x IContext) er return x.BadRequest("Bad request. Please make sure 'acct:user@domain' is what you are sending as the 'resource' query parameter.") } - name := x.StringUtil().Replace(resource, "acct:", "", -1) - name = x.StringUtil().Replace(name, fmt.Sprintf("@%s", config.DOMAIN), "", -1) + username := x.StringUtil().Replace(resource, "acct:", "", -1) + username = x.StringUtil().Replace(username, fmt.Sprintf("@%s", config.DOMAIN), "", -1) - user := &repos.User{} - if err := repos.FindUserByUsername(user, name).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return x.NotFound("No record found for %s.", name) - } else { - return x.InternalServerError(err) - } + user, err := repos.FindUserByUsername(username) + if err != nil { + return err } webfinger := createWebfinger(user) diff --git a/greataped/contracts/context.go b/greataped/contracts/context.go index 48e1d1e..595c16e 100644 --- a/greataped/contracts/context.go +++ b/greataped/contracts/context.go @@ -32,9 +32,9 @@ type ( GetActivityStreamSigned(url, keyId, privateKey string, data []byte, output interface{}) error PostActivityStreamSigned(url, keyId, privateKey string, data []byte, output interface{}) error - GetWebFinger(username domain.Username) (activitypub.Webfinger, error) - GetActor(activitypub.Webfinger) (activitypub.Actor, error) - GetOrderedCollection(url string) (activitypub.OrderedCollection, error) + GetWebFinger(username domain.Username) (*activitypub.Webfinger, error) + GetActor(*activitypub.Webfinger) (*activitypub.Actor, error) + GetOrderedCollection(url string) (*activitypub.OrderedCollection, error) BadRequest(interface{}, ...any) IServerError NotFound(interface{}, ...any) IServerError diff --git a/greataped/server/http_context.go b/greataped/server/http_context.go index 17018c8..4b21c5b 100644 --- a/greataped/server/http_context.go +++ b/greataped/server/http_context.go @@ -238,19 +238,19 @@ func (context *httpServerContext) PostActivityStreamSigned(url, keyId, privateKe return context.requestActivityStream(http.MethodPost, url, keyId, privateKey, data, output) } -func (context *httpServerContext) GetWebFinger(username domain.Username) (activitypub.Webfinger, error) { +func (context *httpServerContext) GetWebFinger(username domain.Username) (*activitypub.Webfinger, error) { result, err := context.GetObject(username.Webfinger(), &activitypub.Webfinger{}) - return result.(activitypub.Webfinger), err + return result.(*activitypub.Webfinger), err } -func (context *httpServerContext) GetActor(webfinger activitypub.Webfinger) (activitypub.Actor, error) { +func (context *httpServerContext) GetActor(webfinger *activitypub.Webfinger) (*activitypub.Actor, error) { result, err := context.GetObject(webfinger.Self(), &activitypub.Actor{}) - return result.(activitypub.Actor), err + return result.(*activitypub.Actor), err } -func (context *httpServerContext) GetOrderedCollection(url string) (activitypub.OrderedCollection, error) { +func (context *httpServerContext) GetOrderedCollection(url string) (*activitypub.OrderedCollection, error) { result, err := context.GetObject(url, &activitypub.OrderedCollection{}) - return result.(activitypub.OrderedCollection), err + return result.(*activitypub.OrderedCollection), err } func (context *httpServerContext) GetObject(url string, result interface{}) (interface{}, error) {