diff options
Diffstat (limited to 'internal/gtsmodel')
| -rw-r--r-- | internal/gtsmodel/statusmute.go | 23 | ||||
| -rw-r--r-- | internal/gtsmodel/tag.go | 29 | ||||
| -rw-r--r-- | internal/gtsmodel/tag_test.go | 92 | ||||
| -rw-r--r-- | internal/gtsmodel/user.go | 134 | ||||
| -rw-r--r-- | internal/gtsmodel/user_test.go | 106 | ||||
| -rw-r--r-- | internal/gtsmodel/validate.go | 78 | ||||
| -rw-r--r-- | internal/gtsmodel/validate_test.go | 64 | 
7 files changed, 400 insertions, 126 deletions
| diff --git a/internal/gtsmodel/statusmute.go b/internal/gtsmodel/statusmute.go index 56a792ab4..90eb41bdb 100644 --- a/internal/gtsmodel/statusmute.go +++ b/internal/gtsmodel/statusmute.go @@ -20,19 +20,14 @@ package gtsmodel  import "time" -// StatusMute refers to one account having muted the status of another account or its own +// StatusMute refers to one account having muted the status of another account or its own.  type StatusMute struct { -	// id of this mute in the database -	ID string `bun:"type:CHAR(26),pk,notnull,unique"` -	// when was this mute created -	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` -	// id of the account that created ('did') the mute -	AccountID string   `bun:"type:CHAR(26),notnull"` -	Account   *Account `bun:"rel:belongs-to"` -	// id the account owning the muted status (can be the same as accountID) -	TargetAccountID string   `bun:"type:CHAR(26),notnull"` -	TargetAccount   *Account `bun:"rel:belongs-to"` -	// database id of the status that has been muted -	StatusID string  `bun:"type:CHAR(26),notnull"` -	Status   *Status `bun:"rel:belongs-to"` +	ID              string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt       time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created +	AccountID       string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id of the account that created ('did') the mute +	Account         *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by accountID +	TargetAccountID string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // id the account owning the muted status (can be the same as accountID) +	TargetAccount   *Account  `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the account specified by targetAccountID +	StatusID        string    `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"`           // database id of the status that has been muted +	Status          *Status   `validate:"-" bun:"rel:belongs-to"`                                       // pointer to the muted status specified by statusID  } diff --git a/internal/gtsmodel/tag.go b/internal/gtsmodel/tag.go index d4be0b66c..359f9a91c 100644 --- a/internal/gtsmodel/tag.go +++ b/internal/gtsmodel/tag.go @@ -20,24 +20,15 @@ package gtsmodel  import "time" -// Tag represents a hashtag for gathering public statuses together +// Tag represents a hashtag for gathering public statuses together.  type Tag struct { -	// id of this tag in the database -	ID string `bun:",unique,type:CHAR(26),pk,notnull"` -	// Href of this tag, eg https://example.org/tags/somehashtag -	URL string `bun:",nullzero"` -	// name of this tag -- the tag without the hash part -	Name string `bun:",unique,notnull"` -	// Which account ID is the first one we saw using this tag? -	FirstSeenFromAccountID string `bun:"type:CHAR(26),nullzero"` -	// when was this tag created -	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` -	// when was this tag last updated -	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` -	// can our instance users use this tag? -	Useable bool `bun:",notnull,default:true"` -	// can our instance users look up this tag? -	Listable bool `bun:",notnull,default:true"` -	// when was this tag last used? -	LastStatusAt time.Time `bun:",nullzero"` +	ID                     string    `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt              time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created +	UpdatedAt              time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item last updated +	URL                    string    `validate:"required,url" bun:",nullzero,notnull"`                         // Href of this tag, eg https://example.org/tags/somehashtag +	Name                   string    `validate:"required" bun:",unique,nullzero,notnull"`                      // name of this tag -- the tag without the hash part +	FirstSeenFromAccountID string    `validate:"ulid" bun:"type:CHAR(26),nullzero"`                            // Which account ID is the first one we saw using this tag? +	Useable                bool      `validate:"-" bun:",nullzero,notnull,default:true"`                       // can our instance users use this tag? +	Listable               bool      `validate:"-" bun:",nullzero,notnull,default:true"`                       // can our instance users look up this tag? +	LastStatusAt           time.Time `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was this tag last used?  } diff --git a/internal/gtsmodel/tag_test.go b/internal/gtsmodel/tag_test.go new file mode 100644 index 000000000..baafe55bd --- /dev/null +++ b/internal/gtsmodel/tag_test.go @@ -0,0 +1,92 @@ +/* +   GoToSocial +   Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org + +   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 gtsmodel_test + +import ( +	"testing" +	"time" + +	"github.com/stretchr/testify/suite" +	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +func happyTag() *gtsmodel.Tag { +	return >smodel.Tag{ +		ID:                     "01FE91RJR88PSEEE30EV35QR8N", +		CreatedAt:              time.Now(), +		UpdatedAt:              time.Now(), +		URL:                    "https://example.org/tags/some_tag", +		Name:                   "some_tag", +		FirstSeenFromAccountID: "01FE91SR5P2GW06K3AJ98P72MT", +		Useable:                true, +		Listable:               true, +		LastStatusAt:           time.Now(), +	} +} + +type TagValidateTestSuite struct { +	suite.Suite +} + +func (suite *TagValidateTestSuite) TestValidateTagHappyPath() { +	// no problem here +	t := happyTag() +	err := gtsmodel.ValidateStruct(*t) +	suite.NoError(err) +} + +func (suite *TagValidateTestSuite) TestValidateTagNoName() { +	t := happyTag() +	t.Name = "" + +	err := gtsmodel.ValidateStruct(*t) +	suite.EqualError(err, "Key: 'Tag.Name' Error:Field validation for 'Name' failed on the 'required' tag") +} + +func (suite *TagValidateTestSuite) TestValidateTagBadURL() { +	t := happyTag() + +	t.URL = "" +	err := gtsmodel.ValidateStruct(*t) +	suite.EqualError(err, "Key: 'Tag.URL' Error:Field validation for 'URL' failed on the 'required' tag") + +	t.URL = "no-schema.com" +	err = gtsmodel.ValidateStruct(*t) +	suite.EqualError(err, "Key: 'Tag.URL' Error:Field validation for 'URL' failed on the 'url' tag") + +	t.URL = "justastring" +	err = gtsmodel.ValidateStruct(*t) +	suite.EqualError(err, "Key: 'Tag.URL' Error:Field validation for 'URL' failed on the 'url' tag") + +	t.URL = "https://aaa\n\n\naaaaaaaa" +	err = gtsmodel.ValidateStruct(*t) +	suite.EqualError(err, "Key: 'Tag.URL' Error:Field validation for 'URL' failed on the 'url' tag") +} + +func (suite *TagValidateTestSuite) TestValidateTagNoFirstSeenFromAccountID() { +	t := happyTag() +	t.FirstSeenFromAccountID = "" + +	err := gtsmodel.ValidateStruct(*t) +	suite.NoError(err) +} + +func TestTagValidateTestSuite(t *testing.T) { +	suite.Run(t, new(TagValidateTestSuite)) +} diff --git a/internal/gtsmodel/user.go b/internal/gtsmodel/user.go index c36d75c8c..27089763d 100644 --- a/internal/gtsmodel/user.go +++ b/internal/gtsmodel/user.go @@ -26,97 +26,45 @@ import (  // User represents an actual human user of gotosocial. Note, this is a LOCAL gotosocial user, not a remote account.  // To cross reference this local user with their account (which can be local or remote), use the AccountID field.  type User struct { -	/* -		BASIC INFO -	*/ - -	// id of this user in the local database; the end-user will never need to know this, it's strictly internal -	ID string `bun:"type:CHAR(26),pk,notnull,unique"` -	// confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported -	Email string `bun:"default:null,unique,nullzero"` -	// The id of the local gtsmodel.Account entry for this user, if it exists (unconfirmed users don't have an account yet) -	AccountID string   `bun:"type:CHAR(26),unique,nullzero"` -	Account   *Account `bun:"rel:belongs-to"` -	// The encrypted password of this user, generated using https://pkg.go.dev/golang.org/x/crypto/bcrypt#GenerateFromPassword. A salt is included so we're safe against 🌈 tables -	EncryptedPassword string `bun:",notnull"` - -	/* -		USER METADATA -	*/ - -	// When was this user created? -	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` -	// From what IP was this user created? -	SignUpIP net.IP `bun:",nullzero"` -	// When was this user updated (eg., password changed, email address changed)? -	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"` -	// When did this user sign in for their current session? -	CurrentSignInAt time.Time `bun:",nullzero"` -	// What's the most recent IP of this user -	CurrentSignInIP net.IP `bun:",nullzero"` -	// When did this user last sign in? -	LastSignInAt time.Time `bun:",nullzero"` -	// What's the previous IP of this user? -	LastSignInIP net.IP `bun:",nullzero"` -	// How many times has this user signed in? -	SignInCount int -	// id of the user who invited this user (who let this guy in?) -	InviteID string `bun:"type:CHAR(26),nullzero"` -	// What languages does this user want to see? -	ChosenLanguages []string -	// What languages does this user not want to see? -	FilteredLanguages []string -	// In what timezone/locale is this user located? -	Locale string `bun:",nullzero"` -	// Which application id created this user? See gtsmodel.Application -	CreatedByApplicationID string       `bun:"type:CHAR(26),nullzero"` -	CreatedByApplication   *Application `bun:"rel:belongs-to"` -	// When did we last contact this user -	LastEmailedAt time.Time `bun:",nullzero"` - -	/* -		USER CONFIRMATION -	*/ - -	// What confirmation token did we send this user/what are we expecting back? -	ConfirmationToken string `bun:",nullzero"` -	// When did the user confirm their email address -	ConfirmedAt time.Time `bun:",nullzero"` -	// When did we send email confirmation to this user? -	ConfirmationSentAt time.Time `bun:",nullzero"` -	// Email address that hasn't yet been confirmed -	UnconfirmedEmail string `bun:",nullzero"` - -	/* -		ACL FLAGS -	*/ - -	// Is this user a moderator? -	Moderator bool -	// Is this user an admin? -	Admin bool -	// Is this user disabled from posting? -	Disabled bool -	// Has this user been approved by a moderator? -	Approved bool - -	/* -		USER SECURITY -	*/ - -	// The generated token that the user can use to reset their password -	ResetPasswordToken string `bun:",nullzero"` -	// When did we email the user their reset-password email? -	ResetPasswordSentAt time.Time `bun:",nullzero"` - -	EncryptedOTPSecret     string `bun:",nullzero"` -	EncryptedOTPSecretIv   string `bun:",nullzero"` -	EncryptedOTPSecretSalt string `bun:",nullzero"` -	OTPRequiredForLogin    bool -	OTPBackupCodes         []string -	ConsumedTimestamp      int -	RememberToken          string    `bun:",nullzero"` -	SignInToken            string    `bun:",nullzero"` -	SignInTokenSentAt      time.Time `bun:",nullzero"` -	WebauthnID             string    `bun:",nullzero"` +	ID                     string       `validate:"required,ulid" bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database +	CreatedAt              time.Time    `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item created +	UpdatedAt              time.Time    `validate:"required" bun:",nullzero,notnull,default:current_timestamp"`   // when was item last updated +	Email                  string       `validate:"required_with=ConfirmedAt" bun:",nullzero,notnull,unique"`     // confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported +	AccountID              string       `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull,unique"`    // The id of the local gtsmodel.Account entry for this user. +	Account                *Account     `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the account of this user that corresponds to AccountID. +	EncryptedPassword      string       `validate:"required" bun:",nullzero,notnull"`                             // The encrypted password of this user, generated using https://pkg.go.dev/golang.org/x/crypto/bcrypt#GenerateFromPassword. A salt is included so we're safe against 🌈 tables. +	SignUpIP               net.IP       `validate:"-" bun:",nullzero"`                                            // From what IP was this user created? +	CurrentSignInAt        time.Time    `validate:"-" bun:",nullzero"`                                            // When did the user sign in with their current session. +	CurrentSignInIP        net.IP       `validate:"-" bun:",nullzero"`                                            // What's the most recent IP of this user +	LastSignInAt           time.Time    `validate:"-" bun:",nullzero"`                                            // When did this user last sign in? +	LastSignInIP           net.IP       `validate:"-" bun:",nullzero"`                                            // What's the previous IP of this user? +	SignInCount            int          `validate:"-" bun:",nullzero,notnull,default:0"`                          // How many times has this user signed in? +	InviteID               string       `validate:"ulid" bun:"type:CHAR(26),nullzero"`                            // id of the user who invited this user (who let this joker in?) +	ChosenLanguages        []string     `validate:"-" bun:",nullzero"`                                            // What languages does this user want to see? +	FilteredLanguages      []string     `validate:"-" bun:",nullzero"`                                            // What languages does this user not want to see? +	Locale                 string       `validate:"-" bun:",nullzero"`                                            // In what timezone/locale is this user located? +	CreatedByApplicationID string       `validate:"ulid" bun:"type:CHAR(26),nullzero,notnull"`                    // Which application id created this user? See gtsmodel.Application +	CreatedByApplication   *Application `validate:"-" bun:"rel:belongs-to"`                                       // Pointer to the application corresponding to createdbyapplicationID. +	LastEmailedAt          time.Time    `validate:"-" bun:",nullzero"`                                            // When was this user last contacted by email. +	ConfirmationToken      string       `validate:"required_with=ConfirmationSentAt" bun:",nullzero"`             // What confirmation token did we send this user/what are we expecting back? +	ConfirmationSentAt     time.Time    `validate:"required_with=ConfirmationToken" bun:",nullzero"`              // When did we send email confirmation to this user? +	ConfirmedAt            time.Time    `validate:"required_with=Email" bun:",nullzero"`                          // When did the user confirm their email address +	UnconfirmedEmail       string       `validate:"required_without=Email" bun:",nullzero"`                       // Email address that hasn't yet been confirmed +	Moderator              bool         `validate:"-" bun:",nullzero,notnull,default:false"`                      // Is this user a moderator? +	Admin                  bool         `validate:"-" bun:",nullzero,notnull,default:false"`                      // Is this user an admin? +	Disabled               bool         `validate:"-" bun:",nullzero,notnull,default:false"`                      // Is this user disabled from posting? +	Approved               bool         `validate:"-" bun:",nullzero,notnull,default:false"`                      // Has this user been approved by a moderator? +	ResetPasswordToken     string       `validate:"required_with=ResetPasswordSentAt" bun:",nullzero"`            // The generated token that the user can use to reset their password +	ResetPasswordSentAt    time.Time    `validate:"required_with=ResetPasswordToken" bun:",nullzero"`             // When did we email the user their reset-password email? + +	EncryptedOTPSecret     string    `validate:"-" bun:",nullzero"` +	EncryptedOTPSecretIv   string    `validate:"-" bun:",nullzero"` +	EncryptedOTPSecretSalt string    `validate:"-" bun:",nullzero"` +	OTPRequiredForLogin    bool      `validate:"-" bun:",nullzero"` +	OTPBackupCodes         []string  `validate:"-" bun:",nullzero"` +	ConsumedTimestamp      int       `validate:"-" bun:",nullzero"` +	RememberToken          string    `validate:"-" bun:",nullzero"` +	SignInToken            string    `validate:"-" bun:",nullzero"` +	SignInTokenSentAt      time.Time `validate:"-" bun:",nullzero"` +	WebauthnID             string    `validate:"-" bun:",nullzero"`  } diff --git a/internal/gtsmodel/user_test.go b/internal/gtsmodel/user_test.go new file mode 100644 index 000000000..c1a9bf849 --- /dev/null +++ b/internal/gtsmodel/user_test.go @@ -0,0 +1,106 @@ +package gtsmodel_test + +import ( +	"net" +	"testing" +	"time" + +	"github.com/stretchr/testify/suite" +	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +func happyUser() *gtsmodel.User { +	return >smodel.User{ +		ID:                     "01FE8TTK9F34BR0KG7639AJQTX", +		Email:                  "whatever@example.org", +		AccountID:              "01FE8TWA7CN8J7237K5DFS1RY5", +		Account:                nil, +		EncryptedPassword:      "$2y$10$tkRapNGW.RWkEuCMWdgArunABFvsPGRvFQY3OibfSJo0RDL3z8WfC", +		CreatedAt:              time.Now(), +		UpdatedAt:              time.Now(), +		SignUpIP:               net.ParseIP("128.64.32.16"), +		CurrentSignInAt:        time.Now(), +		CurrentSignInIP:        net.ParseIP("128.64.32.16"), +		LastSignInAt:           time.Now(), +		LastSignInIP:           net.ParseIP("128.64.32.16"), +		SignInCount:            0, +		InviteID:               "", +		ChosenLanguages:        []string{}, +		FilteredLanguages:      []string{}, +		Locale:                 "en", +		CreatedByApplicationID: "01FE8Y5EHMWCA1MHMTNHRVZ1X4", +		CreatedByApplication:   nil, +		LastEmailedAt:          time.Now(), +		ConfirmationToken:      "", +		ConfirmedAt:            time.Now(), +		ConfirmationSentAt:     time.Now(), +		UnconfirmedEmail:       "", +		Moderator:              false, +		Admin:                  false, +		Disabled:               false, +		Approved:               true, +	} +} + +type UserValidateTestSuite struct { +	suite.Suite +} + +func (suite *UserValidateTestSuite) TestValidateUserHappyPath() { +	// no problem here +	u := happyUser() +	err := gtsmodel.ValidateStruct(*u) +	suite.NoError(err) +} + +func (suite *UserValidateTestSuite) TestValidateUserNoID() { +	// user has no id set +	u := happyUser() +	u.ID = "" + +	err := gtsmodel.ValidateStruct(*u) +	suite.EqualError(err, "Key: 'User.ID' Error:Field validation for 'ID' failed on the 'required' tag") +} + +func (suite *UserValidateTestSuite) TestValidateUserNoEmail() { +	// user has no email or unconfirmed email set +	u := happyUser() +	u.Email = "" + +	err := gtsmodel.ValidateStruct(*u) +	suite.EqualError(err, "Key: 'User.Email' Error:Field validation for 'Email' failed on the 'required_with' tag\nKey: 'User.UnconfirmedEmail' Error:Field validation for 'UnconfirmedEmail' failed on the 'required_without' tag") +} + +func (suite *UserValidateTestSuite) TestValidateUserOnlyUnconfirmedEmail() { +	// user has only UnconfirmedEmail but ConfirmedAt is set +	u := happyUser() +	u.Email = "" +	u.UnconfirmedEmail = "whatever@example.org" + +	err := gtsmodel.ValidateStruct(*u) +	suite.EqualError(err, "Key: 'User.Email' Error:Field validation for 'Email' failed on the 'required_with' tag") +} + +func (suite *UserValidateTestSuite) TestValidateUserOnlyUnconfirmedEmailOK() { +	// user has only UnconfirmedEmail and ConfirmedAt is not set +	u := happyUser() +	u.Email = "" +	u.UnconfirmedEmail = "whatever@example.org" +	u.ConfirmedAt = time.Time{} + +	err := gtsmodel.ValidateStruct(*u) +	suite.NoError(err) +} + +func (suite *UserValidateTestSuite) TestValidateUserNoConfirmedAt() { +	// user has Email but no ConfirmedAt +	u := happyUser() +	u.ConfirmedAt = time.Time{} + +	err := gtsmodel.ValidateStruct(*u) +	suite.EqualError(err, "Key: 'User.ConfirmedAt' Error:Field validation for 'ConfirmedAt' failed on the 'required_with' tag") +} + +func TestUserValidateTestSuite(t *testing.T) { +	suite.Run(t, new(UserValidateTestSuite)) +} diff --git a/internal/gtsmodel/validate.go b/internal/gtsmodel/validate.go new file mode 100644 index 000000000..720aad463 --- /dev/null +++ b/internal/gtsmodel/validate.go @@ -0,0 +1,78 @@ +/* +   GoToSocial +   Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org + +   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 gtsmodel + +import ( +	"reflect" + +	"github.com/go-playground/validator/v10" +	"github.com/superseriousbusiness/gotosocial/internal/util" +) + +var v *validator.Validate + +const ( +	PointerValidationPanic = "validate function was passed pointer" +	InvalidValidationPanic = "validate function was passed invalid item" +) + +var ulidValidator = func(fl validator.FieldLevel) bool { +	value, kind, _ := fl.ExtractType(fl.Field()) + +	if kind != reflect.String { +		return false +	} + +	// we want either an empty string, or a proper ULID, nothing else +	// if the string is empty, the `required` tag will take care of it so we don't need to worry about it here +	s := value.String() +	if len(s) == 0 { +		return true +	} +	return util.ValidateULID(s) +} + +func init() { +	v = validator.New() +	v.RegisterValidation("ulid", ulidValidator) +} + +func ValidateStruct(s interface{}) error { +	switch reflect.ValueOf(s).Kind() { +	case reflect.Invalid: +		panic(InvalidValidationPanic) +	case reflect.Ptr: +		panic(PointerValidationPanic) +	} + +	err := v.Struct(s) +	return processValidationError(err) +} + +func processValidationError(err error) error { +	if err == nil { +		return nil +	} + +	if ive, ok := err.(*validator.InvalidValidationError); ok { +		panic(ive) +	} + +	return err.(validator.ValidationErrors) +} diff --git a/internal/gtsmodel/validate_test.go b/internal/gtsmodel/validate_test.go new file mode 100644 index 000000000..7200522bc --- /dev/null +++ b/internal/gtsmodel/validate_test.go @@ -0,0 +1,64 @@ +/* +   GoToSocial +   Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org + +   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 gtsmodel_test + +import ( +	"testing" + +	"github.com/stretchr/testify/suite" +	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +type ValidateTestSuite struct { +	suite.Suite +} + +func (suite *ValidateTestSuite) TestValidatePointer() { +	var nilUser *gtsmodel.User +	suite.PanicsWithValue(gtsmodel.PointerValidationPanic, func() { +		gtsmodel.ValidateStruct(nilUser) +	}) +} + +func (suite *ValidateTestSuite) TestValidateNil() { +	suite.PanicsWithValue(gtsmodel.InvalidValidationPanic, func() { +		gtsmodel.ValidateStruct(nil) +	}) +} + +func (suite *ValidateTestSuite) TestValidateWeirdULID() { +	type a struct { +		ID bool `validate:"required,ulid"` +	} + +	err := gtsmodel.ValidateStruct(a{ID: true}) +	suite.Error(err) +} + +func (suite *ValidateTestSuite) TestValidateNotStruct() { +	type aaaaaaa string +	aaaaaa := aaaaaaa("aaaa") +	suite.Panics(func() { +		gtsmodel.ValidateStruct(aaaaaa) +	}) +} + +func TestValidateTestSuite(t *testing.T) { +	suite.Run(t, new(ValidateTestSuite)) +} | 
