zitadel/internal/query/user_schema_test.go
Livio Spring 7494a7b6d9
feat(api): add possibility to retrieve user schemas (#7614)
This PR extends the user schema service (V3 API) with the possibility to ListUserSchemas and GetUserSchemaByID.
The previously started guide is extended to demonstrate how to retrieve the schema(s) and notes the generated revision property.
2024-03-22 13:26:13 +00:00

291 lines
8.7 KiB
Go

package query
import (
"database/sql"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"regexp"
"testing"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors"
)
var (
prepareUserSchemasStmt = `SELECT projections.user_schemas.id,` +
` projections.user_schemas.change_date,` +
` projections.user_schemas.sequence,` +
` projections.user_schemas.instance_id,` +
` projections.user_schemas.state,` +
` projections.user_schemas.type,` +
` projections.user_schemas.revision,` +
` projections.user_schemas.schema,` +
` projections.user_schemas.possible_authenticators,` +
` COUNT(*) OVER ()` +
` FROM projections.user_schemas`
prepareUserSchemasCols = []string{
"id",
"change_date",
"sequence",
"instance_id",
"state",
"type",
"revision",
"schema",
"possible_authenticators",
"count",
}
prepareUserSchemaStmt = `SELECT projections.user_schemas.id,` +
` projections.user_schemas.change_date,` +
` projections.user_schemas.sequence,` +
` projections.user_schemas.instance_id,` +
` projections.user_schemas.state,` +
` projections.user_schemas.type,` +
` projections.user_schemas.revision,` +
` projections.user_schemas.schema,` +
` projections.user_schemas.possible_authenticators` +
` FROM projections.user_schemas`
prepareUserSchemaCols = []string{
"id",
"change_date",
"sequence",
"instance_id",
"state",
"type",
"revision",
"schema",
"possible_authenticators",
}
)
func Test_UserSchemaPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
err checkErr
}
tests := []struct {
name string
prepare interface{}
want want
object interface{}
}{
{
name: "prepareUserSchemasQuery no result",
prepare: prepareUserSchemasQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(prepareUserSchemasStmt),
nil,
nil,
),
},
object: &UserSchemas{UserSchemas: []*UserSchema{}},
},
{
name: "prepareUserSchemasQuery one result",
prepare: prepareUserSchemasQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(prepareUserSchemasStmt),
prepareUserSchemasCols,
[][]driver.Value{
{
"id",
testNow,
uint64(20211109),
"instance-id",
domain.UserSchemaStateActive,
"type",
1,
json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
},
),
},
object: &UserSchemas{
SearchResponse: SearchResponse{
Count: 1,
},
UserSchemas: []*UserSchema{
{
ID: "id",
ObjectDetails: domain.ObjectDetails{
EventDate: testNow,
Sequence: 20211109,
ResourceOwner: "instance-id",
},
State: domain.UserSchemaStateActive,
Type: "type",
Revision: 1,
Schema: json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
PossibleAuthenticators: database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
},
},
},
{
name: "prepareUserSchemasQuery multiple result",
prepare: prepareUserSchemasQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(prepareUserSchemasStmt),
prepareUserSchemasCols,
[][]driver.Value{
{
"id-1",
testNow,
uint64(20211109),
"instance-id",
domain.UserSchemaStateActive,
"type1",
1,
json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
{
"id-2",
testNow,
uint64(20211110),
"instance-id",
domain.UserSchemaStateInactive,
"type2",
2,
json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
},
),
},
object: &UserSchemas{
SearchResponse: SearchResponse{
Count: 2,
},
UserSchemas: []*UserSchema{
{
ID: "id-1",
ObjectDetails: domain.ObjectDetails{
EventDate: testNow,
Sequence: 20211109,
ResourceOwner: "instance-id",
},
State: domain.UserSchemaStateActive,
Type: "type1",
Revision: 1,
Schema: json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
PossibleAuthenticators: database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
{
ID: "id-2",
ObjectDetails: domain.ObjectDetails{
EventDate: testNow,
Sequence: 20211110,
ResourceOwner: "instance-id",
},
State: domain.UserSchemaStateInactive,
Type: "type2",
Revision: 2,
Schema: json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
PossibleAuthenticators: database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
},
},
},
{
name: "prepareUserSchemasQuery sql err",
prepare: prepareUserSchemasQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(prepareUserSchemasStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
if !errors.Is(err, sql.ErrConnDone) {
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
}
return nil, true
},
},
object: (*UserSchema)(nil),
},
{
name: "prepareUserSchemaQuery no result",
prepare: prepareUserSchemaQuery,
want: want{
sqlExpectations: mockQueriesScanErr(
regexp.QuoteMeta(prepareUserSchemaStmt),
nil,
nil,
),
err: func(err error) (error, bool) {
if !zerrors.IsNotFound(err) {
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
}
return nil, true
},
},
object: (*UserSchema)(nil),
},
{
name: "prepareUserSchemaQuery found",
prepare: prepareUserSchemaQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(prepareUserSchemaStmt),
prepareUserSchemaCols,
[]driver.Value{
"id",
testNow,
uint64(20211109),
"instance-id",
domain.UserSchemaStateActive,
"type",
1,
json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
),
},
object: &UserSchema{
ID: "id",
ObjectDetails: domain.ObjectDetails{
EventDate: testNow,
Sequence: 20211109,
ResourceOwner: "instance-id",
},
State: domain.UserSchemaStateActive,
Type: "type",
Revision: 1,
Schema: json.RawMessage(`{"$schema":"urn:zitadel:schema:v1","properties":{"name":{"type":"string","urn:zitadel:schema:permission":{"self":"rw"}}},"type":"object"}`),
PossibleAuthenticators: database.Array[domain.AuthenticatorType]{domain.AuthenticatorTypeUsername, domain.AuthenticatorTypePassword},
},
},
{
name: "prepareUserSchemaQuery sql err",
prepare: prepareUserSchemaQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(prepareUserSchemaStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
if !errors.Is(err, sql.ErrConnDone) {
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
}
return nil, true
},
},
object: (*UserSchema)(nil),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
})
}
}