Skip to content

Commit

Permalink
Merge pull request #186 from superseriousbusiness/struct_validation
Browse files Browse the repository at this point in the history
Struct validation
  • Loading branch information
NyaaaWhatsUpDoc authored Sep 3, 2021
2 parents ac7c5e8 + 32fe228 commit 25edd57
Show file tree
Hide file tree
Showing 133 changed files with 5,030 additions and 1,476 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,13 @@ The following libraries and frameworks are used by GoToSocial, with gratitude
* [go-fed/activity](https://github.com/go-fed/activity); Golang ActivityPub/ActivityStreams library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [go-fed/httpsig](https://github.com/go-fed/httpsig); secure HTTP signature library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [google/uuid](https://github.com/google/uuid); UUID generation. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html)
* [go-playground/validator](https://github.com/go-playground/validator); struct validation. [MIT License](https://spdx.org/licenses/MIT.html)
* [gorilla/websocket](https://github.com/gorilla/websocket); Websocket connectivity. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
* [h2non/filetype](https://github.com/h2non/filetype); filetype checking. [MIT License](https://spdx.org/licenses/MIT.html).
* [jackc/pgx](https://github.com/jackc/pgx); Postgres driver. [MIT License](https://spdx.org/licenses/MIT.html).
* [modernc.org/sqlite](https://gitlab.com/cznic/sqlite); cgo-free port of SQLite. [Other License](https://gitlab.com/cznic/sqlite/-/blob/master/LICENSE).
* [modernc.org/ccgo](https://gitlab.com/cznic/ccgo); c99 AST -> Go translater. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [modernc.org/libc](https://gitlab.com/cznic/libc); C-runtime services. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday); HTML user-input sanitization. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [mvdan/xurls](https://github.com/mvdan/xurls); URL parsing regular expressions. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [nfnt/resize](https://github.com/nfnt/resize); convenient image resizing. [ISC License](https://spdx.org/licenses/ISC.html).
Expand All @@ -148,9 +152,6 @@ The following libraries and frameworks are used by GoToSocial, with gratitude
* [uptrace/bun](https://github.com/uptrace/bun); database ORM. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
* [urfave/cli](https://github.com/urfave/cli); command-line interface framework. [MIT License](https://spdx.org/licenses/MIT.html).
* [wagslane/go-password-validator](https://github.com/wagslane/go-password-validator); password strength validation. [MIT License](https://spdx.org/licenses/MIT.html).
* [modernc.org/sqlite](sqlite); cgo-free port of SQLite. [Other License](https://gitlab.com/cznic/sqlite/-/blob/master/LICENSE).
* [modernc.org/ccgo](ccgo); c99 AST -> Go translater. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
* [modernc.org/libc](libc); C-runtime services. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).

### Image Attribution

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/go-errors/errors v1.4.0 // indirect
github.com/go-fed/activity v1.0.1-0.20210803212804-d866ba75dd0f
github.com/go-fed/httpsig v1.1.0
github.com/go-playground/validator/v10 v10.7.0 // indirect
github.com/go-playground/validator/v10 v10.7.0
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand Down
72 changes: 72 additions & 0 deletions internal/ap/activitystreams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
GoToSocial
Copyright (C) 2021 GoToSocial Authors [email protected]
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package ap

// https://www.w3.org/TR/activitystreams-vocabulary
const (
ActivityAccept = "Accept" // ActivityStreamsAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept
ActivityAdd = "Add" // ActivityStreamsAdd https://www.w3.org/TR/activitystreams-vocabulary/#dfn-add
ActivityAnnounce = "Announce" // ActivityStreamsAnnounce https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce
ActivityArrive = "Arrive" // ActivityStreamsArrive https://www.w3.org/TR/activitystreams-vocabulary/#dfn-arrive
ActivityBlock = "Block" // ActivityStreamsBlock https://www.w3.org/TR/activitystreams-vocabulary/#dfn-block
ActivityCreate = "Create" // ActivityStreamsCreate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create
ActivityDelete = "Delete" // ActivityStreamsDelete https://www.w3.org/TR/activitystreams-vocabulary/#dfn-delete
ActivityDislike = "Dislike" // ActivityStreamsDislike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-dislike
ActivityFlag = "Flag" // ActivityStreamsFlag https://www.w3.org/TR/activitystreams-vocabulary/#dfn-flag
ActivityFollow = "Follow" // ActivityStreamsFollow https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow
ActivityIgnore = "Ignore" // ActivityStreamsIgnore https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ignore
ActivityInvite = "Invite" // ActivityStreamsInvite https://www.w3.org/TR/activitystreams-vocabulary/#dfn-invite
ActivityJoin = "Join" // ActivityStreamsJoin https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join
ActivityLeave = "Leave" // ActivityStreamsLeave https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave
ActivityLike = "Like" // ActivityStreamsLike https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like
ActivityListen = "Listen" // ActivityStreamsListen https://www.w3.org/TR/activitystreams-vocabulary/#dfn-listen
ActivityMove = "Move" // ActivityStreamsMove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-move
ActivityOffer = "Offer" // ActivityStreamsOffer https://www.w3.org/TR/activitystreams-vocabulary/#dfn-offer
ActivityQuestion = "Question" // ActivityStreamsQuestion https://www.w3.org/TR/activitystreams-vocabulary/#dfn-question
ActivityReject = "Reject" // ActivityStreamsReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject
ActivityRead = "Read" // ActivityStreamsRead https://www.w3.org/TR/activitystreams-vocabulary/#dfn-read
ActivityRemove = "Remove" // ActivityStreamsRemove https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove
ActivityTentativeReject = "TentativeReject" // ActivityStreamsTentativeReject https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativereject
ActivityTentativeAccept = "TentativeAccept" // ActivityStreamsTentativeAccept https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tentativeaccept
ActivityTravel = "Travel" // ActivityStreamsTravel https://www.w3.org/TR/activitystreams-vocabulary/#dfn-travel
ActivityUndo = "Undo" // ActivityStreamsUndo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo
ActivityUpdate = "Update" // ActivityStreamsUpdate https://www.w3.org/TR/activitystreams-vocabulary/#dfn-update
ActivityView = "View" // ActivityStreamsView https://www.w3.org/TR/activitystreams-vocabulary/#dfn-view

ActorApplication = "Application" // ActivityStreamsApplication https://www.w3.org/TR/activitystreams-vocabulary/#dfn-application
ActorGroup = "Group" // ActivityStreamsGroup https://www.w3.org/TR/activitystreams-vocabulary/#dfn-group
ActorOrganization = "Organization" // ActivityStreamsOrganization https://www.w3.org/TR/activitystreams-vocabulary/#dfn-organization
ActorPerson = "Person" // ActivityStreamsPerson https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person
ActorService = "Service" // ActivityStreamsService https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service

ObjectArticle = "Article" // ActivityStreamsArticle https://www.w3.org/TR/activitystreams-vocabulary/#dfn-article
ObjectAudio = "Audio" // ActivityStreamsAudio https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audio
ObjectDocument = "Document" // ActivityStreamsDocument https://www.w3.org/TR/activitystreams-vocabulary/#dfn-document
ObjectEvent = "Event" // ActivityStreamsEvent https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
ObjectImage = "Image" // ActivityStreamsImage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image
ObjectNote = "Note" // ActivityStreamsNote https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
ObjectPage = "Page" // ActivityStreamsPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-page
ObjectPlace = "Place" // ActivityStreamsPlace https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
ObjectProfile = "Profile" // ActivityStreamsProfile https://www.w3.org/TR/activitystreams-vocabulary/#dfn-profile
ObjectRelationship = "Relationship" // ActivityStreamsRelationship https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship
ObjectTombstone = "Tombstone" // ActivityStreamsTombstone https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone
ObjectVideo = "Video" // ActivityStreamsVideo https://www.w3.org/TR/activitystreams-vocabulary/#dfn-video
ObjectCollection = "Collection" //ActivityStreamsCollection https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection
ObjectCollectionPage = "CollectionPage" // ActivityStreamsCollectionPage https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collectionpage
)
5 changes: 2 additions & 3 deletions internal/api/client/account/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/federation"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
)
Expand All @@ -27,8 +26,8 @@ type AccountStandardTestSuite struct {
processor processing.Processor

// standard suite models
testTokens map[string]*oauth.Token
testClients map[string]*oauth.Client
testTokens map[string]*gtsmodel.Token
testClients map[string]*gtsmodel.Client
testApplications map[string]*gtsmodel.Application
testUsers map[string]*gtsmodel.User
testAccounts map[string]*gtsmodel.Account
Expand Down
12 changes: 6 additions & 6 deletions internal/api/client/account/accountcreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/internal/validate"
)

// AccountCreatePOSTHandler swagger:operation POST /api/v1/accounts accountCreate
Expand Down Expand Up @@ -118,27 +118,27 @@ func validateCreateAccount(form *model.AccountCreateRequest, c *config.AccountsC
return errors.New("registration is not open for this server")
}

if err := util.ValidateUsername(form.Username); err != nil {
if err := validate.Username(form.Username); err != nil {
return err
}

if err := util.ValidateEmail(form.Email); err != nil {
if err := validate.Email(form.Email); err != nil {
return err
}

if err := util.ValidateNewPassword(form.Password); err != nil {
if err := validate.NewPassword(form.Password); err != nil {
return err
}

if !form.Agreement {
return errors.New("agreement to terms and conditions not given")
}

if err := util.ValidateLanguage(form.Locale); err != nil {
if err := validate.Language(form.Locale); err != nil {
return err
}

if err := util.ValidateSignUpReason(form.Reason, c.ReasonRequired); err != nil {
if err := validate.SignUpReason(form.Reason, c.ReasonRequired); err != nil {
return err
}

Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/admin/emojicreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/media"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/internal/validate"
)

// emojiCreateRequest swagger:operation POST /api/v1/admin/custom_emojis emojiCreate
Expand Down Expand Up @@ -132,5 +132,5 @@ func validateCreateEmoji(form *model.EmojiCreateRequest) error {
return fmt.Errorf("file size limit exceeded: limit is %d bytes but emoji was %d bytes", media.EmojiMaxBytes, form.Image.Size)
}

return util.ValidateEmojiShortcode(form.Shortcode)
return validate.EmojiShortcode(form.Shortcode)
}
13 changes: 6 additions & 7 deletions internal/api/client/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type AuthTestSuite struct {
testAccount *gtsmodel.Account
testApplication *gtsmodel.Application
testUser *gtsmodel.User
testClient *oauth.Client
testClient *gtsmodel.Client
config *config.Config
}

Expand Down Expand Up @@ -83,7 +83,7 @@ func (suite *AuthTestSuite) SetupSuite() {
Email: "[email protected]",
AccountID: acctID,
}
suite.testClient = &oauth.Client{
suite.testClient = &gtsmodel.Client{
ID: "a-known-client-id",
Secret: "some-secret",
Domain: fmt.Sprintf("%s://%s", c.Protocol, c.Host),
Expand All @@ -95,7 +95,6 @@ func (suite *AuthTestSuite) SetupSuite() {
ClientID: "a-known-client-id",
ClientSecret: "some-secret",
Scopes: "read",
VapidKey: uuid.NewString(),
}
}

Expand All @@ -112,8 +111,8 @@ func (suite *AuthTestSuite) SetupTest() {
suite.db = db

models := []interface{}{
&oauth.Client{},
&oauth.Token{},
&gtsmodel.Client{},
&gtsmodel.Token{},
&gtsmodel.User{},
&gtsmodel.Account{},
&gtsmodel.Application{},
Expand Down Expand Up @@ -145,8 +144,8 @@ func (suite *AuthTestSuite) SetupTest() {
// TearDownTest drops the oauth_clients table and closes the pg connection after each test
func (suite *AuthTestSuite) TearDownTest() {
models := []interface{}{
&oauth.Client{},
&oauth.Token{},
&gtsmodel.Client{},
&gtsmodel.Token{},
&gtsmodel.User{},
&gtsmodel.Account{},
&gtsmodel.Application{},
Expand Down
6 changes: 3 additions & 3 deletions internal/api/client/auth/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/oidc"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/internal/validate"
)

// CallbackGETHandler parses a token from an external auth provider.
Expand Down Expand Up @@ -153,7 +153,7 @@ func (m *Module) parseUserFromClaims(ctx context.Context, claims *oidc.Claims, i
}

// check if we can just use claims.Name as-is
err = util.ValidateUsername(claims.Name)
err = validate.Username(claims.Name)
if err == nil {
// the name we have on the claims is already a valid username
username = claims.Name
Expand All @@ -166,7 +166,7 @@ func (m *Module) parseUserFromClaims(ctx context.Context, claims *oidc.Claims, i
// lowercase the whole thing
lower := strings.ToLower(underscored)
// see if this is valid....
if err := util.ValidateUsername(lower); err == nil {
if err := validate.Username(lower); err == nil {
// we managed to get a valid username
username = lower
} else {
Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/fileserver/servefile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ type ServeFileTestSuite struct {
oauthServer oauth.Server

// standard suite models
testTokens map[string]*oauth.Token
testClients map[string]*oauth.Client
testTokens map[string]*gtsmodel.Token
testClients map[string]*gtsmodel.Client
testApplications map[string]*gtsmodel.Application
testUsers map[string]*gtsmodel.User
testAccounts map[string]*gtsmodel.Account
Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/media/mediacreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ type MediaCreateTestSuite struct {
processor processing.Processor

// standard suite models
testTokens map[string]*oauth.Token
testClients map[string]*oauth.Client
testTokens map[string]*gtsmodel.Token
testClients map[string]*gtsmodel.Client
testApplications map[string]*gtsmodel.Application
testUsers map[string]*gtsmodel.User
testAccounts map[string]*gtsmodel.Account
Expand Down
5 changes: 2 additions & 3 deletions internal/api/client/status/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/federation"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
)
Expand All @@ -45,8 +44,8 @@ type StatusStandardTestSuite struct {
storage blob.Storage

// standard suite models
testTokens map[string]*oauth.Token
testClients map[string]*oauth.Client
testTokens map[string]*gtsmodel.Token
testClients map[string]*gtsmodel.Client
testApplications map[string]*gtsmodel.Application
testUsers map[string]*gtsmodel.User
testAccounts map[string]*gtsmodel.Account
Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/status/statuscreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/internal/validate"
)

// StatusCreatePOSTHandler swagger:operation POST /api/v1/statuses statusCreate
Expand Down Expand Up @@ -157,7 +157,7 @@ func validateCreateStatus(form *model.AdvancedStatusCreateForm, config *config.S

// validate post language
if form.Language != "" {
if err := util.ValidateLanguage(form.Language); err != nil {
if err := validate.Language(form.Language); err != nil {
return err
}
}
Expand Down
8 changes: 4 additions & 4 deletions internal/api/client/streaming/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,13 @@ func (m *Module) StreamGETHandler(c *gin.Context) {
}
defer conn.Close() // whatever happens, when we leave this function we want to close the websocket connection

// inform the processor that we have a new connection and want a stream for it
stream, errWithCode := m.processor.OpenStreamForAccount(c.Request.Context(), account, streamType)
// inform the processor that we have a new connection and want a s for it
s, errWithCode := m.processor.OpenStreamForAccount(c.Request.Context(), account, streamType)
if errWithCode != nil {
c.JSON(errWithCode.Code(), errWithCode.Safe())
return
}
defer close(stream.Hangup) // closing stream.Hangup indicates that we've finished with the connection (the client has gone), so we want to do this on exiting this handler
defer close(s.Hangup) // closing stream.Hangup indicates that we've finished with the connection (the client has gone), so we want to do this on exiting this handler

// spawn a new ticker for pinging the connection periodically
t := time.NewTicker(30 * time.Second)
Expand All @@ -161,7 +161,7 @@ func (m *Module) StreamGETHandler(c *gin.Context) {
sendLoop:
for {
select {
case m := <-stream.Messages:
case m := <-s.Messages:
// we've got a streaming message!!
l.Trace("received message from stream")
if err := conn.WriteJSON(m); err != nil {
Expand Down
Loading

0 comments on commit 25edd57

Please sign in to comment.