github.com/decred/politeia@v1.4.0/politeiawww/legacy/cmsuser_test.go (about) 1 // Copyright (c) 2020 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package legacy 6 7 import ( 8 "encoding/hex" 9 "testing" 10 "time" 11 12 cms "github.com/decred/politeia/politeiawww/api/cms/v1" 13 www "github.com/decred/politeia/politeiawww/api/www/v1" 14 "github.com/decred/politeia/politeiawww/cmd/shared" 15 "github.com/decred/politeia/politeiawww/legacy/user" 16 "github.com/decred/politeia/util" 17 ) 18 19 func TestInviteNewUser(t *testing.T) { 20 p, cleanup := newTestCMSwww(t) 21 defer cleanup() 22 23 emailVerified := "test1@example.org" 24 inviteUserReq := cms.InviteNewUser{ 25 Email: emailVerified, 26 Temporary: false, 27 } 28 reply, err := p.processInviteNewUser(inviteUserReq) 29 if err != nil { 30 t.Fatalf("error inviting user %v", err) 31 } 32 33 id, err := shared.NewIdentity() 34 if err != nil { 35 t.Fatalf("error another generating identity") 36 } 37 registerReq := cms.RegisterUser{ 38 Email: emailVerified, 39 Username: "test1", 40 Password: "password", 41 VerificationToken: reply.VerificationToken, 42 PublicKey: hex.EncodeToString(id.Public.Key[:]), 43 } 44 _, err = p.processRegisterUser(registerReq) 45 if err != nil { 46 t.Fatalf("error registering user %v", err) 47 } 48 49 emailFreshToken := "test2@example.org" 50 inviteUserReq = cms.InviteNewUser{ 51 Email: emailFreshToken, 52 Temporary: false, 53 } 54 replyFresh, err := p.processInviteNewUser(inviteUserReq) 55 if err != nil { 56 t.Fatalf("error inviting user %v", err) 57 } 58 59 var tests = []struct { 60 name string 61 email string 62 wantError error 63 tokenEmpty bool 64 tokenFresh bool 65 }{ 66 { 67 "success", 68 "test@example.com", 69 nil, 70 false, 71 false, 72 }, 73 { 74 "success new token", 75 emailFreshToken, 76 nil, 77 false, 78 true, 79 }, 80 { 81 "success already verified", 82 emailVerified, 83 nil, 84 true, 85 false, 86 }, 87 { 88 "error malformed", 89 "testemailmalformed", 90 www.UserError{ 91 ErrorCode: www.ErrorStatusMalformedEmail, 92 }, 93 false, 94 false, 95 }, 96 } 97 98 for _, v := range tests { 99 t.Run(v.name, func(t *testing.T) { 100 inviteUserReq := cms.InviteNewUser{ 101 Email: v.email, 102 Temporary: false, 103 } 104 replyInvite, err := p.processInviteNewUser(inviteUserReq) 105 106 got := errToStr(err) 107 want := errToStr(v.wantError) 108 if got != want { 109 t.Errorf("got error %v, want %v", got, want) 110 return 111 } 112 // exit tests if err was received since error matched as expected 113 if err != nil { 114 return 115 } 116 if replyInvite == nil { 117 t.Errorf("invite reply should not be nil here") 118 return 119 } 120 if v.tokenEmpty && len(replyInvite.VerificationToken) > 0 { 121 // If token is expected to be empty 122 t.Errorf("expecting an empty verification token but got %v", 123 replyInvite.VerificationToken) 124 } 125 if !v.tokenEmpty && len(replyInvite.VerificationToken) == 0 { 126 // If token is expected to be non-empty 127 t.Errorf("expecting an non-empty verification token but got empty") 128 } 129 if v.tokenFresh && 130 replyInvite.VerificationToken == replyFresh.VerificationToken { 131 // If token is expected to be fresh from one previously received 132 t.Errorf("expecting fresh token but got the same") 133 } 134 }) 135 } 136 137 emailFirst := "testtemp1@example.org" 138 139 emailSecond := "testtemp2@example.org" 140 141 var testsTempInvite = []struct { 142 name string 143 email string 144 temp bool 145 expectedContractorType cms.ContractorTypeT 146 }{ 147 { 148 "success", 149 emailFirst, 150 false, 151 cms.ContractorTypeNominee, 152 }, 153 { 154 "success temp", 155 emailSecond, 156 true, 157 cms.ContractorTypeTemp, 158 }, 159 } 160 161 for _, v := range testsTempInvite { 162 t.Run(v.name, func(t *testing.T) { 163 inviteUserReq := cms.InviteNewUser{ 164 Email: v.email, 165 Temporary: v.temp, 166 } 167 _, err := p.processInviteNewUser(inviteUserReq) 168 if err != nil { 169 t.Errorf("error inviting user %v %v", v.email, err) 170 return 171 } 172 u, err := p.userByEmail(v.email) 173 if err != nil { 174 t.Errorf("error getting user by email %v %v", v.email, err) 175 return 176 } 177 178 cmsUser, err := p.getCMSUserByID(u.ID.String()) 179 if err != nil { 180 t.Errorf("error getting cms user by id %v %v", u.ID.String(), 181 err) 182 return 183 } 184 185 if cmsUser.ContractorType != v.expectedContractorType { 186 t.Errorf("unexpected contractor type got %v, want %v", 187 cmsUser.ContractorType, v.expectedContractorType) 188 } 189 }) 190 } 191 } 192 193 func TestRegisterUser(t *testing.T) { 194 p, cleanup := newTestCMSwww(t) 195 defer cleanup() 196 197 // Create user identity and save it to disk 198 id, err := shared.NewIdentity() 199 if err != nil { 200 t.Fatalf("error generating identity") 201 } 202 203 email := "test1@example.org" 204 username := "test1" 205 pwd := "password1" 206 207 inviteUserReq := cms.InviteNewUser{ 208 Email: email, 209 Temporary: false, 210 } 211 reply, err := p.processInviteNewUser(inviteUserReq) 212 if err != nil { 213 t.Fatalf("error inviting user %v", err) 214 } 215 216 // Create another user identity and save it to disk 217 idFresh, err := shared.NewIdentity() 218 if err != nil { 219 t.Fatalf("error another generating identity") 220 } 221 emailFresh := "test2@example.org" 222 usernameFresh := "test2" 223 224 inviteUserReqFresh := cms.InviteNewUser{ 225 Email: emailFresh, 226 Temporary: false, 227 } 228 replyFresh, err := p.processInviteNewUser(inviteUserReqFresh) 229 if err != nil { 230 t.Fatalf("error inviting user %v", err) 231 } 232 233 usernameTooShort := "a" 234 usernameTooLong := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 235 usernameRegExp := "?blahg!" 236 237 passwordTooShort := "a" 238 239 usernameExpired := "test3" 240 emailExpired := "test3@example.org" 241 tokenb, err := util.Random(www.VerificationTokenSize) 242 if err != nil { 243 t.Fatalf("unable to generate verification token %v", err) 244 } 245 d := time.Duration(www.VerificationExpiryHours) * time.Hour 246 expiry := time.Now().Add(-1 * d).Unix() 247 248 idExpired, err := shared.NewIdentity() 249 if err != nil { 250 t.Fatalf("error another generating identity") 251 } 252 253 // Create a new User record 254 u := user.User{ 255 Email: emailExpired, 256 Username: emailExpired, 257 NewUserVerificationToken: tokenb, 258 NewUserVerificationExpiry: expiry, 259 } 260 err = p.db.UserNew(u) 261 if err != nil { 262 t.Fatalf("error creating expired token user %v", err) 263 } 264 265 usr, err := p.db.UserGetByUsername(u.Username) 266 if err != nil { 267 t.Fatalf("error getting user by username %v", err) 268 } 269 p.setUserEmailsCache(usr.Email, usr.ID) 270 var tests = []struct { 271 name string 272 email string 273 username string 274 pwd string 275 token string 276 wantError error 277 pubkey string 278 }{ 279 { 280 "success", 281 email, 282 username, 283 pwd, 284 reply.VerificationToken, 285 nil, 286 hex.EncodeToString(id.Public.Key[:]), 287 }, 288 { 289 "error expired verification token", 290 emailExpired, 291 usernameExpired, 292 pwd, 293 hex.EncodeToString(tokenb), 294 www.UserError{ 295 ErrorCode: www.ErrorStatusVerificationTokenExpired, 296 }, 297 hex.EncodeToString(idExpired.Public.Key[:]), 298 }, 299 { 300 "error invalid verification", 301 emailFresh, 302 usernameFresh, 303 pwd, 304 "123456", 305 www.UserError{ 306 ErrorCode: www.ErrorStatusVerificationTokenInvalid, 307 }, 308 hex.EncodeToString(idFresh.Public.Key[:]), 309 }, 310 { 311 "error wrong verification", 312 emailFresh, 313 usernameFresh, 314 pwd, 315 "this is an invalid verification token", 316 www.UserError{ 317 ErrorCode: www.ErrorStatusVerificationTokenInvalid, 318 }, 319 hex.EncodeToString(idFresh.Public.Key[:]), 320 }, 321 { 322 "error duplicate pubkey", 323 emailFresh, 324 usernameFresh, 325 pwd, 326 replyFresh.VerificationToken, 327 www.UserError{ 328 ErrorCode: www.ErrorStatusDuplicatePublicKey, 329 }, 330 hex.EncodeToString(id.Public.Key[:]), 331 }, 332 { 333 "error invalid pubkey", 334 emailFresh, 335 usernameFresh, 336 pwd, 337 replyFresh.VerificationToken, 338 www.UserError{ 339 ErrorCode: www.ErrorStatusInvalidPublicKey, 340 }, 341 "this is a bad pubkey", 342 }, 343 { 344 "error duplicate username", 345 emailFresh, 346 username, 347 pwd, 348 "12345", 349 www.UserError{ 350 ErrorCode: www.ErrorStatusDuplicateUsername, 351 }, 352 hex.EncodeToString(idFresh.Public.Key[:]), 353 }, 354 { 355 "error malformed username too short", 356 emailFresh, 357 usernameTooShort, 358 pwd, 359 "123456", 360 www.UserError{ 361 ErrorCode: www.ErrorStatusMalformedUsername, 362 }, 363 hex.EncodeToString(idFresh.Public.Key[:]), 364 }, 365 { 366 "error malformed username too long", 367 emailFresh, 368 usernameTooLong, 369 pwd, 370 "123456", 371 www.UserError{ 372 ErrorCode: www.ErrorStatusMalformedUsername, 373 }, 374 hex.EncodeToString(idFresh.Public.Key[:]), 375 }, 376 { 377 "error malformed username reg exp", 378 emailFresh, 379 usernameRegExp, 380 pwd, 381 "123456", 382 www.UserError{ 383 ErrorCode: www.ErrorStatusMalformedUsername, 384 }, 385 hex.EncodeToString(idFresh.Public.Key[:]), 386 }, 387 { 388 "error malformed password too short", 389 emailFresh, 390 usernameFresh, 391 passwordTooShort, 392 "123456", 393 www.UserError{ 394 ErrorCode: www.ErrorStatusMalformedPassword, 395 }, 396 hex.EncodeToString(idFresh.Public.Key[:]), 397 }, 398 { 399 "success fresh", 400 emailFresh, 401 usernameFresh, 402 pwd, 403 replyFresh.VerificationToken, 404 nil, 405 hex.EncodeToString(idFresh.Public.Key[:]), 406 }, 407 { 408 "error user not found", 409 "notfound@example.org", 410 "notfound", 411 pwd, 412 "123456", 413 www.UserError{ 414 ErrorCode: www.ErrorStatusVerificationTokenInvalid, 415 }, 416 hex.EncodeToString(idFresh.Public.Key[:]), 417 }, 418 } 419 420 for _, v := range tests { 421 t.Run(v.name, func(t *testing.T) { 422 registerReq := cms.RegisterUser{ 423 Email: v.email, 424 Username: v.username, 425 Password: v.pwd, 426 VerificationToken: v.token, 427 PublicKey: v.pubkey, 428 } 429 _, err = p.processRegisterUser(registerReq) 430 got := errToStr(err) 431 want := errToStr(v.wantError) 432 if got != want { 433 t.Errorf("got error %v, want %v", got, want) 434 } 435 }) 436 } 437 }