Add option to filter by user auth mode

Pass in type=password or type=oidc to pick the mode
This commit is contained in:
Abin Simon
2022-04-06 15:03:01 +05:30
parent 66c7cc7f10
commit df72864d09
5 changed files with 121 additions and 12 deletions
+9 -1
View File
@@ -97,8 +97,16 @@ func GetQueryFilteredUsers(ctx context.Context, db bun.IDB, partner, org, group,
}
// ListFilteredUsers will return the list of users fileterd by query
func ListFilteredUsers(ctx context.Context, db bun.IDB, users *[]models.KratosIdentities, fusers []uuid.UUID, query string, orderBy string, order string, limit int, offset int) (*[]models.KratosIdentities, error) {
func ListFilteredUsers(ctx context.Context, db bun.IDB, users *[]models.KratosIdentities, fusers []uuid.UUID, query string, utype string, orderBy string, order string, limit int, offset int) (*[]models.KratosIdentities, error) {
q := db.NewSelect().Model(users)
if utype != "" {
q.Relation("IdentityCredential").
Relation("IdentityCredential.IdentityCredentialType", func(q *bun.SelectQuery) *bun.SelectQuery {
return q.Where("name = ?", utype)
})
}
if len(fusers) > 0 {
// filter with precomputed users if we have any
q.Where("id IN (?)", bun.In(fusers))
+25 -8
View File
@@ -7,15 +7,32 @@ import (
"github.com/uptrace/bun"
)
type KratosIdentityCredentialTypes struct {
bun.BaseModel `bun:"table:identity_credential_types,alias:ict"`
ID uuid.UUID `bun:"id,type:uuid,pk"`
Name string `bun:"name,type:string"`
}
type KratosIdentityCredentials struct {
bun.BaseModel `bun:"table:identity_credentials,alias:ic"`
ID uuid.UUID `bun:"id,type:uuid,pk"`
IdentityID uuid.UUID `bun:"identity_id,type:uuid"`
IdentityCredentialTypeID uuid.UUID `bun:"identity_credential_type_id,type:uuid"`
IdentityCredentialType KratosIdentityCredentialTypes `bun:"rel:has-one,join:identity_credential_type_id=id"`
}
type KratosIdentities struct {
bun.BaseModel `bun:"table:identities,alias:identities"`
ID uuid.UUID `bun:"id,type:uuid,pk"`
SchemaId string `bun:"schema_id,notnull"`
Traits map[string]interface{} `bun:"traits,type:jsonb"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp"`
State string `bun:"state,notnull"`
StateChangedAt time.Time `bun:"state_changed_at,notnull,default:current_timestamp"`
NId uuid.UUID `bun:"nid,type:uuid,pk"`
ID uuid.UUID `bun:"id,type:uuid,pk"`
SchemaId string `bun:"schema_id,notnull"`
Traits map[string]interface{} `bun:"traits,type:jsonb"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp"`
State string `bun:"state,notnull"`
StateChangedAt time.Time `bun:"state_changed_at,notnull,default:current_timestamp"`
NId uuid.UUID `bun:"nid,type:uuid,pk"`
IdentityCredential KratosIdentityCredentials `bun:"rel:has-one,join:id=identity_id"`
}
+1 -1
View File
@@ -276,7 +276,7 @@ spec:
project: :project
# Get all users
GET :host/auth/v3/users
GET :host/auth/v3/users?partner=:partner&organization=:org&type=password
Content-Type: application/yaml
X-Session-Token: :token
+2 -2
View File
@@ -718,7 +718,7 @@ func (s *userService) List(ctx context.Context, opts ...query.Option) (*userv3.U
if len(uids) != 0 {
// TODO: maybe merge this with the previous one into single sql
usrs, err = dao.ListFilteredUsers(ctx, s.db, &accs,
uids, queryOptions.Q,
uids, queryOptions.Q, queryOptions.Type,
queryOptions.OrderBy, queryOptions.Order,
int(queryOptions.Limit), int(queryOptions.Offset))
if err != nil {
@@ -728,7 +728,7 @@ func (s *userService) List(ctx context.Context, opts ...query.Option) (*userv3.U
} else {
// If no filters are available we have to list just using identities table
usrs, err = dao.ListFilteredUsers(ctx, s.db, &accs,
[]uuid.UUID{}, queryOptions.Q,
[]uuid.UUID{}, queryOptions.Q, queryOptions.Type,
queryOptions.OrderBy, queryOptions.Order,
int(queryOptions.Limit), int(queryOptions.Offset))
if err != nil {
+84
View File
@@ -490,6 +490,90 @@ func TestUserList(t *testing.T) {
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
}
func TestUserListWithType(t *testing.T) {
// TODO: merge these tests
db, mock := getDB(t)
defer db.Close()
ap := &mockAuthProvider{}
mazc := mockAuthzClient{}
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
uuuid1 := uuid.New().String()
uuuid2 := uuid.New().String()
puuid := uuid.New().String()
ouuid := uuid.New().String()
guuid := uuid.New().String()
ruuid := uuid.New().String()
pruuid := uuid.New().String()
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
mock.ExpectQuery(`SELECT "identities"."id", "identities"."schema_id", "identities"."traits", "identities"."created_at", "identities"."updated_at", "identities"."state", "identities"."state_changed_at", "identities"."nid", "identity_credential"."id" AS "identity_credential__id", "identity_credential"."identity_id" AS "identity_credential__identity_id", "identity_credential"."identity_credential_type_id" AS "identity_credential__identity_credential_type_id", "identity_credential__identity_credential_type"."id" AS "identity_credential__identity_credential_type__id", "identity_credential__identity_credential_type"."name" AS "identity_credential__identity_credential_type__name" FROM "identities" LEFT JOIN "identity_credentials" AS "identity_credential" ON ."identity_credential"."identity_id" = "identities"."id". LEFT JOIN "identity_credential_types" AS "identity_credential__identity_credential_type" ON ."identity_credential__identity_credential_type"."id" = "identity_credential"."identity_credential_type_id". WHERE .name = 'password'. LIMIT 10`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
AddRow("group-" + guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
AddRow("group-" + guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_group.name as group FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id JOIN authsrv_group ON authsrv_group.id=authsrv_grouprole.group_id WHERE`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "group"}).AddRow("role-"+ruuid, "group-"+guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, authsrv_group.name as group FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id JOIN authsrv_group ON authsrv_group.id=authsrv_projectgrouprole.group_id WHERE`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace, authsrv_group.name as group FROM "authsrv_projectgroupnamespacerole"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+puuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT distinct authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
qo := &commonv3.QueryOptions{Organization: ouuid, Partner: puuid, Type: "password"}
userlist, err := us.List(context.Background(), query.WithOptions(qo))
if err != nil {
t.Fatal("could not list users:", err)
}
if userlist.Metadata.Count != 2 {
t.Fatalf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
}
if userlist.Items[0].Metadata.Name != "johndoe@provider.com" || userlist.Items[1].Metadata.Name != "johndoe@provider.com" {
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
}
if len(userlist.Items[0].GetSpec().GetGroups()) != 1 {
t.Errorf("invalid number of groups returned for user, expected 1; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
}
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 6 {
t.Errorf("invalid number of roles returned for user, expected 6; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
}
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
}
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
}
func TestUserFiltered(t *testing.T) {
db, mock := getDB(t)
defer db.Close()