400 if account already assocaited (#1048)

This commit is contained in:
Louis Ruch authored and GitHub committed 2021-03-30 13:00:48 -07:00
1 parent 06206de387
commit 93bad3cb83
7 files changed
+119 -89

No files matched your search

+15 -14
View File
@@ -21,20 +21,21 @@ const (
Unknown Code = 0 // Unknown will be equal to a zero value for Codes
// General function errors are reserved Codes 100-999
InvalidParameter Code = 100 // InvalidParameter represents an invalid parameter for an operation.
InvalidAddress Code = 101 // InvalidAddress represents an invalid host address for an operation
InvalidPublicId Code = 102 // InvalidPublicId represents an invalid public Id for an operation
InvalidFieldMask Code = 103 // InvalidFieldMask represents an invalid field mast for an operation
EmptyFieldMask Code = 104 // EmptyFieldMask represents an empty field mask for an operation
KeyNotFound Code = 105 // KeyNotFound represents that a key/version was not found in the KMS
TicketAlreadyRedeemed Code = 106 // TicketAlreadyRedeemed represents that the ticket version has already been redeemed
TicketNotFound Code = 107 // TicketNotFound represents that the ticket was not found
Io Code = 108 // Io represents that an io error occurred in an underlying call (i.e binary.Write)
InvalidTimeStamp Code = 109 // InvalidTimeStamp represents an invalid time stamp for an operation
SessionNotFound Code = 110 // SessionNotFound represents that the session was not found
InvalidSessionState Code = 111 // InvalidSessionState represents that the session was in an invalid state
TokenMismatch Code = 112 // TokenMismatch represents that there was a token mismatch
TooShort Code = 113 // TooShort represents an error that means the provided input is not meeting minimum length requirements
InvalidParameter Code = 100 // InvalidParameter represents an invalid parameter for an operation.
InvalidAddress Code = 101 // InvalidAddress represents an invalid host address for an operation
InvalidPublicId Code = 102 // InvalidPublicId represents an invalid public Id for an operation
InvalidFieldMask Code = 103 // InvalidFieldMask represents an invalid field mast for an operation
EmptyFieldMask Code = 104 // EmptyFieldMask represents an empty field mask for an operation
KeyNotFound Code = 105 // KeyNotFound represents that a key/version was not found in the KMS
TicketAlreadyRedeemed Code = 106 // TicketAlreadyRedeemed represents that the ticket version has already been redeemed
TicketNotFound Code = 107 // TicketNotFound represents that the ticket was not found
Io Code = 108 // Io represents that an io error occurred in an underlying call (i.e binary.Write)
InvalidTimeStamp Code = 109 // InvalidTimeStamp represents an invalid time stamp for an operation
SessionNotFound Code = 110 // SessionNotFound represents that the session was not found
InvalidSessionState Code = 111 // InvalidSessionState represents that the session was in an invalid state
TokenMismatch Code = 112 // TokenMismatch represents that there was a token mismatch
TooShort Code = 113 // TooShort represents an error that means the provided input is not meeting minimum length requirements
AccountAlreadyAssociated Code = 114 // AccountAlreadyAssociated represents an attempt to associate an account failed since it was already associated.
// PasswordTooShort results from attempting to set a password which is to short.
PasswordTooShort Code = 200
+5
View File
@@ -97,6 +97,11 @@ func TestCode_Both_String_Info(t *testing.T) {
c: TooShort,
want: TooShort,
},
{
name: "AccountAlreadyAssociated",
c: AccountAlreadyAssociated,
want: AccountAlreadyAssociated,
},
{
name: "InternalError",
c: Internal,
+4
View File
@@ -72,6 +72,10 @@ var errorCodeInfo = map[Code]Info{
Message: "too short",
Kind: Integrity,
},
AccountAlreadyAssociated: {
Message: "account already associated with another user",
Kind: Parameter,
},
PasswordTooShort: {
Message: "too short",
Kind: Password,
+4 -4
View File
@@ -651,7 +651,7 @@ func associateUserWithAccounts(ctx context.Context, repoKms *kms.Kms, reader db.
return errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup account %s", accountId)))
}
if acct.IamUserId != "" && acct.IamUserId != userId {
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("%s account is already associated with another user", accountId))
return errors.New(errors.AccountAlreadyAssociated, op, fmt.Sprintf("%s account is already associated with another user", accountId))
}
authAccounts = append(authAccounts, &acct)
}
@@ -677,7 +677,7 @@ func associateUserWithAccounts(ctx context.Context, repoKms *kms.Kms, reader db.
return errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed to associate %s account", aa.PublicId)))
}
if updatedRows == 0 {
return errors.New(errors.MultipleRecords, op, fmt.Sprintf("failed to associate %s account: it is already associated with another user", aa.PublicId))
return errors.New(errors.AccountAlreadyAssociated, op, fmt.Sprintf("failed to associate %s account: it is already associated with another user", aa.PublicId))
}
if updatedRows > 1 {
return errors.New(errors.MultipleRecords, op, fmt.Sprintf("failed to associate %s account: would have updated too many accounts %d", aa.PublicId, updatedRows))
@@ -715,7 +715,7 @@ func dissociateUserFromAccounts(ctx context.Context, repoKms *kms.Kms, reader db
return errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup account %s", accountId)))
}
if acct.IamUserId != userId {
return errors.New(errors.InvalidParameter, op, fmt.Sprintf("%s account is not associated with user %s", accountId, userId))
return errors.New(errors.AccountAlreadyAssociated, op, fmt.Sprintf("%s account is not associated with user %s", accountId, userId))
}
authAccounts = append(authAccounts, &acct)
}
@@ -741,7 +741,7 @@ func dissociateUserFromAccounts(ctx context.Context, repoKms *kms.Kms, reader db
return errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed to disassociate %s account", aa.PublicId)))
}
if updatedRows == 0 {
return errors.New(errors.MultipleRecords, op, fmt.Sprintf("failed to disassociate %s account: it is already associated with another user", aa.PublicId))
return errors.New(errors.AccountAlreadyAssociated, op, fmt.Sprintf("failed to disassociate %s account: it is already associated with another user", aa.PublicId))
}
if updatedRows > 1 {
return errors.New(errors.MultipleRecords, op, fmt.Sprintf("failed to disassociate %s account: would have updated too many accounts %d", aa.PublicId, updatedRows))
+78 -71
View File
@@ -718,13 +718,13 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
opt []Option
}
tests := []struct {
name string
args args
want *User
want1 *authAccount
wantErr bool
wantErrIs errors.Code
wantAssoc bool
name string
args args
want *User
want1 *authAccount
wantErr bool
wantErrCode errors.Code
wantAssoc bool
}{
{
name: "simple",
@@ -746,8 +746,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{user: id}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "missing-userId",
@@ -757,8 +757,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{accts: []string{id}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "already-properly-assoc",
@@ -781,8 +781,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "assoc-with-diff-user-withDisassociateOption",
@@ -794,8 +794,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-acct-id",
@@ -806,8 +806,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{id}}
}(),
},
wantErr: true,
wantErrIs: errors.RecordNotFound,
wantErr: true,
wantErrCode: errors.RecordNotFound,
},
{
name: "bad-user-id-not-associated-account",
@@ -830,7 +830,8 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
return Ids{user: id, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
}
for _, tt := range tests {
@@ -839,7 +840,7 @@ func TestRepository_associateUserWithAccounts(t *testing.T) {
err := associateUserWithAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...)
if tt.wantErr {
require.Error(err)
assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error())
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err)
return
}
require.NoError(err)
@@ -873,12 +874,12 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
opt []Option
}
tests := []struct {
name string
args args
want *User
want1 *authAccount
wantErr bool
wantErrIs errors.Code
name string
args args
want *User
want1 *authAccount
wantErr bool
wantErrCode errors.Code
}{
{
name: "simple",
@@ -900,8 +901,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: id}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "missing-userId",
@@ -911,8 +912,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{accts: []string{id}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "already-properly-disassoc",
@@ -923,8 +924,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "assoc-with-diff-user",
@@ -936,8 +937,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-acct-id",
@@ -948,8 +949,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: u.PublicId, accts: []string{id}}
}(),
},
wantErr: true,
wantErrIs: errors.RecordNotFound,
wantErr: true,
wantErrCode: errors.RecordNotFound,
},
{
name: "bad-user-id-not-associated-account",
@@ -960,8 +961,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: id, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErrIs: errors.InvalidParameter,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-user-id",
@@ -973,7 +974,8 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
return Ids{user: id, accts: []string{a.PublicId}}
}(),
},
wantErr: true,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
}
for _, tt := range tests {
@@ -983,7 +985,7 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) {
err := dissociateUserFromAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...)
if tt.wantErr {
require.Error(err)
assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error())
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err)
return
}
require.NoError(err)
@@ -1023,10 +1025,10 @@ func TestRepository_AssociateAccounts(t *testing.T) {
opt []Option
}
tests := []struct {
name string
args args
wantErr bool
wantErrIs error
name string
args args
wantErr bool
wantErrCode errors.Code
}{
{
name: "valid",
@@ -1061,7 +1063,8 @@ func TestRepository_AssociateAccounts(t *testing.T) {
return ids
},
},
wantErr: true,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-version",
@@ -1073,7 +1076,8 @@ func TestRepository_AssociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: createAccountsFn,
},
wantErr: true,
wantErr: true,
wantErrCode: errors.MultipleRecords,
},
{
name: "zero-version",
@@ -1085,7 +1089,8 @@ func TestRepository_AssociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: createAccountsFn,
},
wantErr: true,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "no-accounts",
@@ -1093,7 +1098,8 @@ func TestRepository_AssociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: func() []string { return nil },
},
wantErr: true,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
}
for _, tt := range tests {
@@ -1113,9 +1119,7 @@ func TestRepository_AssociateAccounts(t *testing.T) {
got, err := repo.AddUserAccounts(context.Background(), tt.args.userId, version, accountIds, tt.args.opt...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
assert.Truef(errors.Is(err, tt.wantErrIs), "unexpected error %s", err.Error())
}
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err)
return
}
require.NoError(err)
@@ -1167,10 +1171,10 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
opt []Option
}
tests := []struct {
name string
args args
wantErr bool
wantErrIs error
name string
args args
wantErr bool
wantErrCode errors.Code
}{
{
name: "valid",
@@ -1192,7 +1196,8 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
return ids
},
},
wantErr: true,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-version",
@@ -1204,7 +1209,8 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: createAccountsFn,
},
wantErr: true,
wantErr: true,
wantErrCode: errors.MultipleRecords,
},
{
name: "zero-version",
@@ -1216,7 +1222,8 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: createAccountsFn,
},
wantErr: true,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "no-accounts",
@@ -1224,7 +1231,8 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
userId: user.PublicId,
accountIdsFn: func() []string { return nil },
},
wantErr: true,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
}
for _, tt := range tests {
@@ -1243,9 +1251,7 @@ func TestRepository_DisassociateAccounts(t *testing.T) {
got, err := repo.DeleteUserAccounts(context.Background(), tt.args.userId, version, accountIds, tt.args.opt...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
assert.Truef(errors.Is(err, tt.wantErrIs), "unexpected error %s", err.Error())
}
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err)
return
}
require.NoError(err)
@@ -1294,10 +1300,10 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) {
opt []Option
}
tests := []struct {
name string
args args
wantErr bool
wantErrIs error
name string
args args
wantErr bool
wantErrCode errors.Code
}{
{
name: "valid",
@@ -1366,7 +1372,8 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) {
return ids, ids
},
},
wantErr: true,
wantErr: true,
wantErrCode: errors.AccountAlreadyAssociated,
},
{
name: "bad-version",
@@ -1381,7 +1388,8 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) {
return ids, ids
},
},
wantErr: true,
wantErr: true,
wantErrCode: errors.MultipleRecords,
},
{
name: "zero-version",
@@ -1396,7 +1404,8 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) {
return ids, ids
},
},
wantErr: true,
wantErr: true,
wantErrCode: errors.InvalidParameter,
},
{
name: "no-accounts-no-changes",
@@ -1424,9 +1433,7 @@ func TestRepository_SetAssociatedAccounts(t *testing.T) {
got, err := repo.SetUserAccounts(context.Background(), tt.args.userId, version, accountIds, tt.args.opt...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
assert.Truef(errors.Is(err, tt.wantErrIs), "unexpected error %s", err.Error())
}
assert.Truef(errors.Match(errors.T(tt.wantErrCode), err), "unexpected error %s", err)
return
}
require.NoError(err)
@@ -159,6 +159,8 @@ func backendErrorToApiError(inErr error) error {
}
case errors.Match(errors.T(errors.RecordNotFound), inErr):
return NotFoundErrorf(genericNotFoundMsg)
case errors.Match(errors.T(errors.AccountAlreadyAssociated), inErr):
return InvalidArgumentErrorf(inErr.Error(), nil)
case errors.Match(errors.T(errors.InvalidFieldMask), inErr), errors.Match(errors.T(errors.EmptyFieldMask), inErr):
return InvalidArgumentErrorf("Error in provided request", map[string]string{"update_mask": "Invalid update mask provided."})
case errors.IsUniqueError(inErr):
@@ -184,6 +184,17 @@ func TestApiErrorHandler(t *testing.T) {
},
},
},
{
name: "Domain error account already associated",
err: errors.E(errors.WithCode(errors.AccountAlreadyAssociated)),
expected: apiError{
status: http.StatusBadRequest,
inner: &pb.Error{
Kind: "InvalidArgument",
Message: "account already associated with another user, parameter violation: error #114",
},
},
},
{
name: "Wrapped domain error",
err: errors.E(errors.WithCode(errors.InvalidAddress), errors.WithMsg("test msg"), errors.WithWrap(errors.E(errors.WithCode(errors.NotNull), errors.WithMsg("inner msg")))),