2020-12-21 10:07:34 -08:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2020-06-04 20:05:08 -04:00
package iam
import (
"context"
"testing"
2022-10-28 15:52:06 -04:00
"github.com/hashicorp/boundary/globals"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/iam/store"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
2020-06-04 20:05:08 -04:00
"github.com/stretchr/testify/assert"
2020-06-10 12:10:34 -04:00
"github.com/stretchr/testify/require"
2020-06-04 20:05:08 -04:00
"google.golang.org/protobuf/proto"
)
func TestNewUser ( t * testing . T ) {
t . Parallel ()
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-08-19 16:47:18 -04:00
wrapper := db . TestWrapper ( t )
org , _ := TestScopes ( t , TestRepo ( t , conn , wrapper ))
2020-06-10 12:10:34 -04:00
id := testId ( t )
2020-06-04 20:05:08 -04:00
type args struct {
2020-07-11 12:00:49 -04:00
orgPublicId string
opt [] Option
2020-06-04 20:05:08 -04:00
}
tests := [] struct {
name string
args args
wantErr bool
wantErrMsg string
wantName string
wantDescription string
}{
{
name : "valid" ,
args : args {
2020-07-11 12:00:49 -04:00
orgPublicId : org . PublicId ,
opt : [] Option { WithName ( id ), WithDescription ( id )},
2020-06-04 20:05:08 -04:00
},
wantErr : false ,
wantName : id ,
wantDescription : id ,
},
{
name : "valid-with-no-name" ,
args : args {
2020-07-11 12:00:49 -04:00
orgPublicId : org . PublicId ,
2020-06-04 20:05:08 -04:00
},
wantErr : false ,
},
{
name : "no-org" ,
args : args {
opt : [] Option { WithName ( id )},
},
wantErr : true ,
2020-12-23 11:00:00 -08:00
wantErrMsg : "iam.NewUser: missing scope id: parameter violation: error #100" ,
2020-06-04 20:05:08 -04:00
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2023-06-06 17:09:08 -04:00
got , err := NewUser ( ctx , tt . args . orgPublicId , tt . args . opt ... )
2020-06-04 20:05:08 -04:00
if tt . wantErr {
2020-07-10 15:46:26 -04:00
require . Error ( err )
2020-11-05 16:54:03 -05:00
assert . Contains ( err . Error (), tt . wantErrMsg )
2020-06-04 20:05:08 -04:00
return
}
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . Equal ( tt . wantName , got . Name )
assert . Empty ( got . PublicId )
})
}
}
2020-07-10 15:46:26 -04:00
func Test_UserHardcoded ( t * testing . T ) {
t . Parallel ()
conn , _ := db . TestSetup ( t , "postgres" )
assert , require := assert . New ( t ), require . New ( t )
w := db . New ( conn )
2022-10-28 15:52:06 -04:00
for _ , v := range [] string { globals . AnonymousUserId , globals . AnyAuthenticatedUserId } {
2021-04-20 20:33:56 -04:00
foundUser := AllocUser ()
2020-07-10 15:46:26 -04:00
foundUser . PublicId = v
err := w . LookupByPublicId ( context . Background (), & foundUser )
require . NoError ( err )
assert . Equal ( "global" , foundUser . ScopeId )
assert . Equal ( v , foundUser . PublicId )
}
}
2020-06-04 20:05:08 -04:00
func Test_UserCreate ( t * testing . T ) {
t . Parallel ()
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-08-19 16:47:18 -04:00
wrapper := db . TestWrapper ( t )
org , _ := TestScopes ( t , TestRepo ( t , conn , wrapper ))
2020-06-10 12:10:34 -04:00
id := testId ( t )
2020-06-04 20:05:08 -04:00
t . Run ( "valid-user" , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-04 20:05:08 -04:00
w := db . New ( conn )
2023-06-06 17:09:08 -04:00
user , err := NewUser ( ctx , org . PublicId )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2023-06-06 17:09:08 -04:00
id , err := newUserId ( ctx )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
user . PublicId = id
2023-06-06 17:09:08 -04:00
err = w . Create ( ctx , user )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
require . NotEmpty ( user . PublicId )
2020-06-04 20:05:08 -04:00
2021-04-20 20:33:56 -04:00
foundUser := AllocUser ()
2020-06-04 20:05:08 -04:00
foundUser . PublicId = user . PublicId
2023-06-06 17:09:08 -04:00
err = w . LookupByPublicId ( ctx , & foundUser )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . Equal ( user , & foundUser )
})
t . Run ( "bad-orgid" , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-04 20:05:08 -04:00
w := db . New ( conn )
2023-06-06 17:09:08 -04:00
user , err := NewUser ( ctx , id )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2023-06-06 17:09:08 -04:00
id , err := newUserId ( ctx )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
user . PublicId = id
2023-06-06 17:09:08 -04:00
err = w . Create ( ctx , user )
2020-06-10 12:10:34 -04:00
require . Error ( err )
2022-01-05 14:38:38 -05:00
assert . Equal ( "db.Create: dbw.Create: error before write: iam.(User).VetForWrite: iam.validateScopeForWrite: scope is not found: search issue: error #1100" , err . Error ())
2020-07-10 15:46:26 -04:00
})
2020-06-04 20:05:08 -04:00
}
func Test_UserUpdate ( t * testing . T ) {
t . Parallel ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-04 20:05:08 -04:00
rw := db . New ( conn )
wrapper := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
repo := TestRepo ( t , conn , wrapper )
2020-06-10 12:10:34 -04:00
id := testId ( t )
2020-08-19 16:47:18 -04:00
org , proj := TestScopes ( t , repo )
2021-04-20 20:33:56 -04:00
org2 , _ := TestScopes ( t , repo )
2020-06-04 20:05:08 -04:00
type args struct {
name string
description string
fieldMaskPaths [] string
ScopeId string
2021-04-20 20:33:56 -04:00
dbOpts [] db . Option
2020-06-04 20:05:08 -04:00
}
tests := [] struct {
name string
args args
wantRowsUpdate int
wantErr bool
wantErrMsg string
wantDup bool
}{
{
name : "valid" ,
args : args {
name : "valid" + id ,
fieldMaskPaths : [] string { "Name" },
ScopeId : org . PublicId ,
},
wantErr : false ,
wantRowsUpdate : 1 ,
},
{
name : "proj-scope-id" ,
args : args {
name : "proj-scope-id" + id ,
fieldMaskPaths : [] string { "ScopeId" },
ScopeId : proj . PublicId ,
},
wantErr : true ,
2022-01-05 14:38:38 -05:00
wantErrMsg : "db.Update: dbw.Update: error before write: iam.(User).VetForWrite: iam.validateScopeForWrite: not allowed to change a resource's scope: parameter violation: error #100" ,
2020-06-04 20:05:08 -04:00
},
{
name : "proj-scope-id-not-in-mask" ,
args : args {
name : "proj-scope-id" + id ,
fieldMaskPaths : [] string { "Name" },
ScopeId : proj . PublicId ,
},
wantErr : false ,
wantRowsUpdate : 1 ,
},
{
name : "empty-scope-id" ,
args : args {
name : "empty-scope-id" + id ,
fieldMaskPaths : [] string { "Name" },
ScopeId : "" ,
},
wantErr : false ,
wantRowsUpdate : 1 ,
},
{
name : "dup-name" ,
args : args {
name : "dup-name" + id ,
fieldMaskPaths : [] string { "Name" },
ScopeId : org . PublicId ,
},
wantErr : true ,
wantDup : true ,
2023-05-01 12:40:10 -07:00
wantErrMsg : `db.Update: duplicate key value violates unique constraint "iam_user_name_scope_id_uq": unique constraint violation: integrity violation: error #1002` ,
2020-06-04 20:05:08 -04:00
},
2021-04-20 20:33:56 -04:00
{
name : "modified-scope" ,
args : args {
name : "modified-scope" + id ,
fieldMaskPaths : [] string { "ScopeId" },
ScopeId : org2 . PublicId ,
dbOpts : [] db . Option { db . WithSkipVetForWrite ( true )},
},
wantErr : true ,
2022-01-05 14:38:38 -05:00
wantErrMsg : "integrity violation: error #1003" ,
2021-04-20 20:33:56 -04:00
},
2020-06-04 20:05:08 -04:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-04 20:05:08 -04:00
if tt . wantDup {
2020-08-19 16:47:18 -04:00
u := TestUser ( t , repo , org . PublicId )
2020-06-04 20:05:08 -04:00
u . Name = tt . args . name
2021-04-20 20:33:56 -04:00
_ , err := rw . Update ( context . Background (), u , tt . args . fieldMaskPaths , nil , tt . args . dbOpts ... )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
}
2020-08-19 16:47:18 -04:00
u := TestUser ( t , repo , org . PublicId )
2020-06-04 20:05:08 -04:00
2021-04-20 20:33:56 -04:00
updateUser := AllocUser ()
2020-06-04 20:05:08 -04:00
updateUser . PublicId = u . PublicId
updateUser . ScopeId = tt . args . ScopeId
updateUser . Name = tt . args . name
updateUser . Description = tt . args . description
2021-04-20 20:33:56 -04:00
updatedRows , err := rw . Update ( context . Background (), & updateUser , tt . args . fieldMaskPaths , nil , tt . args . dbOpts ... )
2020-06-04 20:05:08 -04:00
if tt . wantErr {
2020-06-10 12:10:34 -04:00
require . Error ( err )
2020-06-04 20:05:08 -04:00
assert . Equal ( 0 , updatedRows )
2022-01-05 14:38:38 -05:00
assert . Contains ( err . Error (), tt . wantErrMsg )
2020-06-04 20:05:08 -04:00
return
}
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . Equal ( tt . wantRowsUpdate , updatedRows )
assert . NotEqual ( u . UpdateTime , updateUser . UpdateTime )
2020-09-25 13:35:32 -04:00
foundUser , _ , err := repo . LookupUser ( context . Background (), u . PublicId )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . True ( proto . Equal ( updateUser , foundUser ))
})
}
}
func Test_UserDelete ( t * testing . T ) {
t . Parallel ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-04 20:05:08 -04:00
rw := db . New ( conn )
wrapper := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
repo := TestRepo ( t , conn , wrapper )
2020-06-10 12:10:34 -04:00
id := testId ( t )
2020-08-19 16:47:18 -04:00
org , _ := TestScopes ( t , repo )
2020-06-04 20:05:08 -04:00
tests := [] struct {
name string
user * User
wantRowsDeleted int
wantErr bool
wantErrMsg string
}{
{
name : "valid" ,
2020-08-19 16:47:18 -04:00
user : TestUser ( t , repo , org . PublicId ),
2020-06-04 20:05:08 -04:00
wantErr : false ,
wantRowsDeleted : 1 ,
},
{
name : "bad-id" ,
2021-04-20 20:33:56 -04:00
user : func () * User { u := AllocUser (); u . PublicId = id ; return & u }(),
2020-06-04 20:05:08 -04:00
wantErr : false ,
wantRowsDeleted : 0 ,
},
2020-07-10 15:46:26 -04:00
{
name : "anon-user" ,
2022-10-28 15:52:06 -04:00
user : func () * User { u := AllocUser (); u . PublicId = globals . AnonymousUserId ; return & u }(),
2020-07-10 15:46:26 -04:00
wantErr : true ,
wantRowsDeleted : 0 ,
},
{
name : "auth-user" ,
2022-10-28 15:52:06 -04:00
user : func () * User { u := AllocUser (); u . PublicId = globals . AnyAuthenticatedUserId ; return & u }(),
2020-07-10 15:46:26 -04:00
wantErr : true ,
wantRowsDeleted : 0 ,
},
2020-06-04 20:05:08 -04:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2021-04-20 20:33:56 -04:00
deleteUser := AllocUser ()
2020-06-04 20:05:08 -04:00
deleteUser . PublicId = tt . user . GetPublicId ()
deletedRows , err := rw . Delete ( context . Background (), & deleteUser )
if tt . wantRowsDeleted == 0 {
assert . Equal ( tt . wantRowsDeleted , deletedRows )
return
}
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . Equal ( tt . wantRowsDeleted , deletedRows )
2020-09-25 13:35:32 -04:00
foundUser , _ , err := repo . LookupUser ( context . Background (), tt . user . GetPublicId ())
2020-09-04 14:48:11 -07:00
assert . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . Nil ( foundUser )
})
}
}
func Test_UserGetScope ( t * testing . T ) {
t . Parallel ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-08-19 16:47:18 -04:00
wrapper := db . TestWrapper ( t )
repo := TestRepo ( t , conn , wrapper )
org , _ := TestScopes ( t , repo )
2020-06-04 20:05:08 -04:00
t . Run ( "valid-scope" , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-04 20:05:08 -04:00
w := db . New ( conn )
2020-08-19 16:47:18 -04:00
user := TestUser ( t , repo , org . PublicId )
2020-06-04 20:05:08 -04:00
userScope , err := user . GetScope ( context . Background (), w )
2020-06-10 12:10:34 -04:00
require . NoError ( err )
2020-06-04 20:05:08 -04:00
assert . True ( proto . Equal ( org , userScope ))
})
}
func TestUser_Clone ( t * testing . T ) {
t . Parallel ()
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-08-19 16:47:18 -04:00
wrapper := db . TestWrapper ( t )
repo := TestRepo ( t , conn , wrapper )
org , _ := TestScopes ( t , repo )
2020-06-04 20:05:08 -04:00
t . Run ( "valid" , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert := assert . New ( t )
2020-08-19 16:47:18 -04:00
user := TestUser ( t , repo , org . PublicId )
2020-06-04 20:05:08 -04:00
cp := user . Clone ()
assert . True ( proto . Equal ( cp .( * User ). User , user . User ))
})
t . Run ( "not-equal-test" , func ( t * testing . T ) {
2020-06-10 12:10:34 -04:00
assert := assert . New ( t )
2020-06-04 20:05:08 -04:00
w := db . New ( conn )
2023-06-06 17:09:08 -04:00
user , err := NewUser ( ctx , org . PublicId )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
2023-06-06 17:09:08 -04:00
id , err := newUserId ( ctx )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
user . PublicId = id
2023-06-06 17:09:08 -04:00
err = w . Create ( ctx , user )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
2023-06-06 17:09:08 -04:00
user2 , err := NewUser ( ctx , org . PublicId )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
2023-06-06 17:09:08 -04:00
id , err = newUserId ( ctx )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
user2 . PublicId = id
2023-06-06 17:09:08 -04:00
err = w . Create ( ctx , user2 )
2020-06-04 20:05:08 -04:00
assert . NoError ( err )
cp := user . Clone ()
assert . True (! proto . Equal ( cp .( * User ). User , user2 . User ))
})
}
func TestUser_Actions ( t * testing . T ) {
assert := assert . New ( t )
u := & User {}
a := u . Actions ()
2020-06-26 11:00:14 -04:00
assert . Equal ( a [ action . Create . String ()], action . Create )
assert . Equal ( a [ action . Update . String ()], action . Update )
assert . Equal ( a [ action . Read . String ()], action . Read )
assert . Equal ( a [ action . Delete . String ()], action . Delete )
2020-06-04 20:05:08 -04:00
2020-06-26 11:00:14 -04:00
if _ , ok := a [ action . List . String ()]; ok {
t . Errorf ( "users should not include %s as an action" , action . List . String ())
2020-06-04 20:05:08 -04:00
}
}
func TestUser_ResourceType ( t * testing . T ) {
t . Parallel ()
2021-04-20 20:33:56 -04:00
u := AllocUser ()
2023-10-23 15:53:29 -07:00
assert . Equal ( t , resource . User , u . GetResourceType ())
2020-06-04 20:05:08 -04:00
}
2020-07-17 16:20:56 -04:00
func TestUser_SetTableName ( t * testing . T ) {
defaultTableName := defaultUserTableName
tests := [] struct {
name string
initialName string
setNameTo string
want string
}{
{
name : "new-name" ,
initialName : "" ,
setNameTo : "new-name" ,
want : "new-name" ,
},
{
name : "reset to default" ,
initialName : "initial" ,
setNameTo : "" ,
want : defaultTableName ,
},
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
assert , require := assert . New ( t ), require . New ( t )
2021-04-20 20:33:56 -04:00
def := AllocUser ()
2020-07-17 16:20:56 -04:00
require . Equal ( defaultTableName , def . TableName ())
s := & User {
User : & store . User {},
tableName : tt . initialName ,
}
s . SetTableName ( tt . setNameTo )
assert . Equal ( tt . want , s . TableName ())
})
}
}