gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

account_test.go (13435B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package validate_test
     19 
     20 import (
     21 	"crypto/rand"
     22 	"crypto/rsa"
     23 	"testing"
     24 	"time"
     25 
     26 	"github.com/stretchr/testify/suite"
     27 	"github.com/superseriousbusiness/gotosocial/internal/ap"
     28 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     29 	"github.com/superseriousbusiness/gotosocial/internal/validate"
     30 	"github.com/superseriousbusiness/gotosocial/testrig"
     31 )
     32 
     33 func happyAccount() *gtsmodel.Account {
     34 	priv, err := rsa.GenerateKey(rand.Reader, 2048)
     35 	if err != nil {
     36 		panic(err)
     37 	}
     38 	pub := &priv.PublicKey
     39 
     40 	return &gtsmodel.Account{
     41 		ID:                      "01F8MH1H7YV1Z7D2C8K2730QBF",
     42 		CreatedAt:               time.Now().Add(-48 * time.Hour),
     43 		UpdatedAt:               time.Now().Add(-48 * time.Hour),
     44 		Username:                "the_mighty_zork",
     45 		Domain:                  "",
     46 		AvatarMediaAttachmentID: "01F8MH58A357CV5K7R7TJMSH6S",
     47 		AvatarMediaAttachment:   nil,
     48 		AvatarRemoteURL:         "",
     49 		HeaderMediaAttachmentID: "01PFPMWK2FF0D9WMHEJHR07C3Q",
     50 		HeaderMediaAttachment:   nil,
     51 		HeaderRemoteURL:         "",
     52 		DisplayName:             "original zork (he/they)",
     53 		Fields:                  []*gtsmodel.Field{},
     54 		Note:                    "hey yo this is my profile!",
     55 		Memorial:                testrig.FalseBool(),
     56 		AlsoKnownAs:             "",
     57 		MovedToAccountID:        "",
     58 		Bot:                     testrig.FalseBool(),
     59 		Reason:                  "I wanna be on this damned webbed site so bad! Please! Wow",
     60 		Locked:                  testrig.FalseBool(),
     61 		Discoverable:            testrig.TrueBool(),
     62 		Privacy:                 gtsmodel.VisibilityPublic,
     63 		Sensitive:               testrig.FalseBool(),
     64 		Language:                "en",
     65 		StatusContentType:       "text/plain",
     66 		URI:                     "http://localhost:8080/users/the_mighty_zork",
     67 		URL:                     "http://localhost:8080/@the_mighty_zork",
     68 		FetchedAt:               time.Time{},
     69 		InboxURI:                "http://localhost:8080/users/the_mighty_zork/inbox",
     70 		OutboxURI:               "http://localhost:8080/users/the_mighty_zork/outbox",
     71 		FollowersURI:            "http://localhost:8080/users/the_mighty_zork/followers",
     72 		FollowingURI:            "http://localhost:8080/users/the_mighty_zork/following",
     73 		FeaturedCollectionURI:   "http://localhost:8080/users/the_mighty_zork/collections/featured",
     74 		ActorType:               ap.ActorPerson,
     75 		PrivateKey:              priv,
     76 		PublicKey:               pub,
     77 		PublicKeyURI:            "http://localhost:8080/users/the_mighty_zork#main-key",
     78 		SensitizedAt:            time.Time{},
     79 		SilencedAt:              time.Time{},
     80 		SuspendedAt:             time.Time{},
     81 		HideCollections:         testrig.FalseBool(),
     82 		SuspensionOrigin:        "",
     83 	}
     84 }
     85 
     86 type AccountValidateTestSuite struct {
     87 	suite.Suite
     88 }
     89 
     90 func (suite *AccountValidateTestSuite) TestValidateAccountHappyPath() {
     91 	// no problem here
     92 	a := happyAccount()
     93 	err := validate.Struct(*a)
     94 	suite.NoError(err)
     95 }
     96 
     97 // ID must be set and be valid ULID
     98 func (suite *AccountValidateTestSuite) TestValidateAccountBadID() {
     99 	a := happyAccount()
    100 
    101 	a.ID = ""
    102 	err := validate.Struct(*a)
    103 	suite.EqualError(err, "Key: 'Account.ID' Error:Field validation for 'ID' failed on the 'required' tag")
    104 
    105 	a.ID = "01FE96W293ZPRG9FQQP48HK8N001FE96W32AT24VYBGM12WN3GKB"
    106 	err = validate.Struct(*a)
    107 	suite.EqualError(err, "Key: 'Account.ID' Error:Field validation for 'ID' failed on the 'ulid' tag")
    108 }
    109 
    110 // CreatedAt can be set or not -- it will be set in the database anyway
    111 func (suite *AccountValidateTestSuite) TestValidateAccountNoCreatedAt() {
    112 	a := happyAccount()
    113 
    114 	a.CreatedAt = time.Time{}
    115 	err := validate.Struct(*a)
    116 	suite.NoError(err)
    117 }
    118 
    119 // FetchedAt must be defined if remote account
    120 func (suite *AccountValidateTestSuite) TestValidateAccountNoWebfingeredAt() {
    121 	a := happyAccount()
    122 
    123 	a.Domain = "example.org"
    124 	a.FetchedAt = time.Time{}
    125 	err := validate.Struct(*a)
    126 	suite.EqualError(err, "Key: 'Account.FetchedAt' Error:Field validation for 'FetchedAt' failed on the 'required_with' tag")
    127 }
    128 
    129 // Username must be set
    130 func (suite *AccountValidateTestSuite) TestValidateAccountUsername() {
    131 	a := happyAccount()
    132 
    133 	a.Username = ""
    134 	err := validate.Struct(*a)
    135 	suite.EqualError(err, "Key: 'Account.Username' Error:Field validation for 'Username' failed on the 'required' tag")
    136 }
    137 
    138 // Domain must be either empty (for local accounts) or proper fqdn (for remote accounts)
    139 func (suite *AccountValidateTestSuite) TestValidateAccountDomain() {
    140 	a := happyAccount()
    141 	a.FetchedAt = time.Now()
    142 
    143 	a.Domain = ""
    144 	err := validate.Struct(*a)
    145 	suite.NoError(err)
    146 
    147 	a.Domain = "localhost:8080"
    148 	err = validate.Struct(*a)
    149 	suite.EqualError(err, "Key: 'Account.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag")
    150 
    151 	a.Domain = "ahhhhh"
    152 	err = validate.Struct(*a)
    153 	suite.EqualError(err, "Key: 'Account.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag")
    154 
    155 	a.Domain = "https://www.example.org"
    156 	err = validate.Struct(*a)
    157 	suite.EqualError(err, "Key: 'Account.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag")
    158 
    159 	a.Domain = "example.org:8080"
    160 	err = validate.Struct(*a)
    161 	suite.EqualError(err, "Key: 'Account.Domain' Error:Field validation for 'Domain' failed on the 'fqdn' tag")
    162 
    163 	a.Domain = "example.org"
    164 	err = validate.Struct(*a)
    165 	suite.NoError(err)
    166 }
    167 
    168 // Attachment IDs must either be not set, or must be valid ULID
    169 func (suite *AccountValidateTestSuite) TestValidateAttachmentIDs() {
    170 	a := happyAccount()
    171 
    172 	a.AvatarMediaAttachmentID = ""
    173 	a.HeaderMediaAttachmentID = ""
    174 	err := validate.Struct(*a)
    175 	suite.NoError(err)
    176 
    177 	a.AvatarMediaAttachmentID = "01FE96W293ZPRG9FQQP48HK8N001FE96W32AT24VYBGM12WN3GKB"
    178 	a.HeaderMediaAttachmentID = "aaaa"
    179 	err = validate.Struct(*a)
    180 	suite.EqualError(err, "Key: 'Account.AvatarMediaAttachmentID' Error:Field validation for 'AvatarMediaAttachmentID' failed on the 'ulid' tag\nKey: 'Account.HeaderMediaAttachmentID' Error:Field validation for 'HeaderMediaAttachmentID' failed on the 'ulid' tag")
    181 }
    182 
    183 // Attachment remote URLs must either not be set, or be valid URLs
    184 func (suite *AccountValidateTestSuite) TestValidateAttachmentRemoteURLs() {
    185 	a := happyAccount()
    186 
    187 	a.AvatarRemoteURL = ""
    188 	a.HeaderRemoteURL = ""
    189 	err := validate.Struct(*a)
    190 	suite.NoError(err)
    191 
    192 	a.AvatarRemoteURL = "-------------"
    193 	a.HeaderRemoteURL = "https://valid-url.com"
    194 	err = validate.Struct(*a)
    195 	suite.EqualError(err, "Key: 'Account.AvatarRemoteURL' Error:Field validation for 'AvatarRemoteURL' failed on the 'url' tag")
    196 
    197 	a.AvatarRemoteURL = "https://valid-url.com"
    198 	a.HeaderRemoteURL = ""
    199 	err = validate.Struct(*a)
    200 	suite.NoError(err)
    201 }
    202 
    203 // Default privacy must be set if account is local
    204 func (suite *AccountValidateTestSuite) TestValidatePrivacy() {
    205 	a := happyAccount()
    206 	a.FetchedAt = time.Now()
    207 
    208 	a.Privacy = ""
    209 	err := validate.Struct(*a)
    210 	suite.EqualError(err, "Key: 'Account.Privacy' Error:Field validation for 'Privacy' failed on the 'required_without' tag")
    211 
    212 	a.Privacy = "not valid"
    213 	err = validate.Struct(*a)
    214 	suite.EqualError(err, "Key: 'Account.Privacy' Error:Field validation for 'Privacy' failed on the 'oneof' tag")
    215 
    216 	a.Privacy = gtsmodel.VisibilityFollowersOnly
    217 	err = validate.Struct(*a)
    218 	suite.NoError(err)
    219 
    220 	a.Privacy = ""
    221 	a.Domain = "example.org"
    222 	err = validate.Struct(*a)
    223 	suite.NoError(err)
    224 
    225 	a.Privacy = "invalid"
    226 	err = validate.Struct(*a)
    227 	suite.EqualError(err, "Key: 'Account.Privacy' Error:Field validation for 'Privacy' failed on the 'oneof' tag")
    228 }
    229 
    230 // If set, language must be a valid language
    231 func (suite *AccountValidateTestSuite) TestValidateLanguage() {
    232 	a := happyAccount()
    233 
    234 	a.Language = ""
    235 	err := validate.Struct(*a)
    236 	suite.NoError(err)
    237 
    238 	a.Language = "not valid"
    239 	err = validate.Struct(*a)
    240 	suite.EqualError(err, "Key: 'Account.Language' Error:Field validation for 'Language' failed on the 'bcp47_language_tag' tag")
    241 
    242 	a.Language = "en-uk"
    243 	err = validate.Struct(*a)
    244 	suite.NoError(err)
    245 }
    246 
    247 // Account URI must be set and must be valid
    248 func (suite *AccountValidateTestSuite) TestValidateAccountURI() {
    249 	a := happyAccount()
    250 
    251 	a.URI = "invalid-uri"
    252 	err := validate.Struct(*a)
    253 	suite.EqualError(err, "Key: 'Account.URI' Error:Field validation for 'URI' failed on the 'url' tag")
    254 
    255 	a.URI = ""
    256 	err = validate.Struct(*a)
    257 	suite.EqualError(err, "Key: 'Account.URI' Error:Field validation for 'URI' failed on the 'required' tag")
    258 }
    259 
    260 // ActivityPub URIs must be set on account if it's local
    261 func (suite *AccountValidateTestSuite) TestValidateAccountURIs() {
    262 	a := happyAccount()
    263 	a.FetchedAt = time.Now()
    264 
    265 	a.InboxURI = "invalid-uri"
    266 	a.OutboxURI = "invalid-uri"
    267 	a.FollowersURI = "invalid-uri"
    268 	a.FollowingURI = "invalid-uri"
    269 	a.FeaturedCollectionURI = "invalid-uri"
    270 	a.PublicKeyURI = "invalid-uri"
    271 	err := validate.Struct(*a)
    272 	suite.EqualError(err, "Key: 'Account.InboxURI' Error:Field validation for 'InboxURI' failed on the 'url' tag\nKey: 'Account.OutboxURI' Error:Field validation for 'OutboxURI' failed on the 'url' tag\nKey: 'Account.FollowingURI' Error:Field validation for 'FollowingURI' failed on the 'url' tag\nKey: 'Account.FollowersURI' Error:Field validation for 'FollowersURI' failed on the 'url' tag\nKey: 'Account.FeaturedCollectionURI' Error:Field validation for 'FeaturedCollectionURI' failed on the 'url' tag\nKey: 'Account.PublicKeyURI' Error:Field validation for 'PublicKeyURI' failed on the 'url' tag")
    273 
    274 	a.InboxURI = ""
    275 	a.OutboxURI = ""
    276 	a.FollowersURI = ""
    277 	a.FollowingURI = ""
    278 	a.FeaturedCollectionURI = ""
    279 	a.PublicKeyURI = ""
    280 	err = validate.Struct(*a)
    281 	suite.EqualError(err, "Key: 'Account.InboxURI' Error:Field validation for 'InboxURI' failed on the 'required_without' tag\nKey: 'Account.OutboxURI' Error:Field validation for 'OutboxURI' failed on the 'required_without' tag\nKey: 'Account.FollowingURI' Error:Field validation for 'FollowingURI' failed on the 'required_without' tag\nKey: 'Account.FollowersURI' Error:Field validation for 'FollowersURI' failed on the 'required_without' tag\nKey: 'Account.FeaturedCollectionURI' Error:Field validation for 'FeaturedCollectionURI' failed on the 'required_without' tag\nKey: 'Account.PublicKeyURI' Error:Field validation for 'PublicKeyURI' failed on the 'required' tag")
    282 
    283 	a.Domain = "example.org"
    284 	err = validate.Struct(*a)
    285 	suite.EqualError(err, "Key: 'Account.PublicKeyURI' Error:Field validation for 'PublicKeyURI' failed on the 'required' tag")
    286 
    287 	a.InboxURI = "invalid-uri"
    288 	a.OutboxURI = "invalid-uri"
    289 	a.FollowersURI = "invalid-uri"
    290 	a.FollowingURI = "invalid-uri"
    291 	a.FeaturedCollectionURI = "invalid-uri"
    292 	a.PublicKeyURI = "invalid-uri"
    293 	err = validate.Struct(*a)
    294 	suite.EqualError(err, "Key: 'Account.InboxURI' Error:Field validation for 'InboxURI' failed on the 'url' tag\nKey: 'Account.OutboxURI' Error:Field validation for 'OutboxURI' failed on the 'url' tag\nKey: 'Account.FollowingURI' Error:Field validation for 'FollowingURI' failed on the 'url' tag\nKey: 'Account.FollowersURI' Error:Field validation for 'FollowersURI' failed on the 'url' tag\nKey: 'Account.FeaturedCollectionURI' Error:Field validation for 'FeaturedCollectionURI' failed on the 'url' tag\nKey: 'Account.PublicKeyURI' Error:Field validation for 'PublicKeyURI' failed on the 'url' tag")
    295 }
    296 
    297 // Actor type must be set and valid
    298 func (suite *AccountValidateTestSuite) TestValidateActorType() {
    299 	a := happyAccount()
    300 
    301 	a.ActorType = ""
    302 	err := validate.Struct(*a)
    303 	suite.EqualError(err, "Key: 'Account.ActorType' Error:Field validation for 'ActorType' failed on the 'oneof' tag")
    304 
    305 	a.ActorType = "not valid"
    306 	err = validate.Struct(*a)
    307 	suite.EqualError(err, "Key: 'Account.ActorType' Error:Field validation for 'ActorType' failed on the 'oneof' tag")
    308 
    309 	a.ActorType = ap.ActivityArrive
    310 	err = validate.Struct(*a)
    311 	suite.EqualError(err, "Key: 'Account.ActorType' Error:Field validation for 'ActorType' failed on the 'oneof' tag")
    312 
    313 	a.ActorType = ap.ActorOrganization
    314 	err = validate.Struct(*a)
    315 	suite.NoError(err)
    316 }
    317 
    318 // Private key must be set on local accounts
    319 func (suite *AccountValidateTestSuite) TestValidatePrivateKey() {
    320 	a := happyAccount()
    321 	a.FetchedAt = time.Now()
    322 
    323 	a.PrivateKey = nil
    324 	err := validate.Struct(*a)
    325 	suite.EqualError(err, "Key: 'Account.PrivateKey' Error:Field validation for 'PrivateKey' failed on the 'required_without' tag")
    326 
    327 	a.Domain = "example.org"
    328 	err = validate.Struct(*a)
    329 	suite.NoError(err)
    330 }
    331 
    332 // Public key must be set
    333 func (suite *AccountValidateTestSuite) TestValidatePublicKey() {
    334 	a := happyAccount()
    335 
    336 	a.PublicKey = nil
    337 	err := validate.Struct(*a)
    338 	suite.EqualError(err, "Key: 'Account.PublicKey' Error:Field validation for 'PublicKey' failed on the 'required' tag")
    339 }
    340 
    341 func TestAccountValidateTestSuite(t *testing.T) {
    342 	suite.Run(t, new(AccountValidateTestSuite))
    343 }