perf: query data AS OF SYSTEM TIME (#5231)

Queries the data in the storage layser at the timestamp when the call hit the API layer
This commit is contained in:
Silvan
2023-02-27 22:36:43 +01:00
committed by GitHub
parent 80003939ad
commit e38abdcdf3
170 changed files with 3101 additions and 3169 deletions
+9 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -117,7 +118,7 @@ func (q *Queries) SearchActions(ctx context.Context, queries *ActionSearchQuerie
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareActionsQuery()
query, scan := prepareActionsQuery(ctx, q.client)
eq := sq.Eq{
ActionColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
}
@@ -145,7 +146,7 @@ func (q *Queries) GetActionByID(ctx context.Context, id string, orgID string, wi
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareActionQuery()
stmt, scan := prepareActionQuery(ctx, q.client)
eq := sq.Eq{
ActionColumnID.identifier(): id,
ActionColumnResourceOwner.identifier(): orgID,
@@ -179,7 +180,7 @@ func NewActionIDSearchQuery(id string) (SearchQuery, error) {
return NewTextQuery(ActionColumnID, id, TextEquals)
}
func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, error)) {
func prepareActionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, error)) {
return sq.Select(
ActionColumnID.identifier(),
ActionColumnCreationDate.identifier(),
@@ -192,7 +193,8 @@ func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, er
ActionColumnTimeout.identifier(),
ActionColumnAllowedToFail.identifier(),
countColumn.identifier(),
).From(actionTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(actionTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Actions, error) {
actions := make([]*Action, 0)
var count uint64
@@ -230,7 +232,7 @@ func prepareActionsQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*Actions, er
}
}
func prepareActionQuery() (sq.SelectBuilder, func(row *sql.Row) (*Action, error)) {
func prepareActionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) (*Action, error)) {
return sq.Select(
ActionColumnID.identifier(),
ActionColumnCreationDate.identifier(),
@@ -242,7 +244,8 @@ func prepareActionQuery() (sq.SelectBuilder, func(row *sql.Row) (*Action, error)
ActionColumnScript.identifier(),
ActionColumnTimeout.identifier(),
ActionColumnAllowedToFail.identifier(),
).From(actionTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(actionTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Action, error) {
action := new(Action)
err := row.Scan(
+10 -9
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -70,7 +71,7 @@ func (q *Queries) GetFlow(ctx context.Context, flowType domain.FlowType, orgID s
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareFlowQuery(flowType)
query, scan := prepareFlowQuery(ctx, q.client, flowType)
eq := sq.Eq{
FlowsTriggersColumnFlowType.identifier(): flowType,
FlowsTriggersColumnResourceOwner.identifier(): orgID,
@@ -95,7 +96,7 @@ func (q *Queries) GetActiveActionsByFlowAndTriggerType(ctx context.Context, flow
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareTriggerActionsQuery()
stmt, scan := prepareTriggerActionsQuery(ctx, q.client)
eq := sq.Eq{
FlowsTriggersColumnFlowType.identifier(): flowType,
FlowsTriggersColumnTriggerType.identifier(): triggerType,
@@ -122,7 +123,7 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareFlowTypesQuery()
stmt, scan := prepareFlowTypesQuery(ctx, q.client)
eq := sq.Eq{
FlowsTriggersColumnActionID.identifier(): actionID,
FlowsTriggersColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -143,11 +144,11 @@ func (q *Queries) GetFlowTypesOfActionID(ctx context.Context, actionID string, w
return scan(rows)
}
func prepareFlowTypesQuery() (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowType, error)) {
func prepareFlowTypesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowType, error)) {
return sq.Select(
FlowsTriggersColumnFlowType.identifier(),
).
From(flowsTriggersTable.identifier()).
From(flowsTriggersTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) ([]domain.FlowType, error) {
types := []domain.FlowType{}
@@ -166,7 +167,7 @@ func prepareFlowTypesQuery() (sq.SelectBuilder, func(*sql.Rows) ([]domain.FlowTy
}
func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action, error)) {
func prepareTriggerActionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]*Action, error)) {
return sq.Select(
ActionColumnID.identifier(),
ActionColumnCreationDate.identifier(),
@@ -180,7 +181,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
ActionColumnTimeout.identifier(),
).
From(flowsTriggersTable.name).
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)).
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) ([]*Action, error) {
actions := make([]*Action, 0)
@@ -212,7 +213,7 @@ func prepareTriggerActionsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]*Action,
}
}
func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
func prepareFlowQuery(ctx context.Context, db prepareDatabase, flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return sq.Select(
ActionColumnID.identifier(),
ActionColumnCreationDate.identifier(),
@@ -232,7 +233,7 @@ func prepareFlowQuery(flowType domain.FlowType) (sq.SelectBuilder, func(*sql.Row
FlowsTriggersColumnResourceOwner.identifier(),
).
From(flowsTriggersTable.name).
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID)).
LeftJoin(join(ActionColumnID, FlowsTriggersColumnActionID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Flow, error) {
flow := &Flow{
+108 -244
View File
@@ -1,6 +1,7 @@
package query
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
@@ -14,6 +15,82 @@ import (
"github.com/zitadel/zitadel/internal/domain"
)
var (
prepareFlowStmt = `SELECT projections.actions3.id,` +
` projections.actions3.creation_date,` +
` projections.actions3.change_date,` +
` projections.actions3.resource_owner,` +
` projections.actions3.action_state,` +
` projections.actions3.sequence,` +
` projections.actions3.name,` +
` projections.actions3.script,` +
` projections.actions3.allowed_to_fail,` +
` projections.actions3.timeout,` +
` projections.flow_triggers2.trigger_type,` +
` projections.flow_triggers2.trigger_sequence,` +
` projections.flow_triggers2.flow_type,` +
` projections.flow_triggers2.change_date,` +
` projections.flow_triggers2.sequence,` +
` projections.flow_triggers2.resource_owner` +
` FROM projections.flow_triggers2` +
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id AND projections.flow_triggers2.instance_id = projections.actions3.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
prepareFlowCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
// flow
"trigger_type",
"trigger_sequence",
"flow_type",
"change_date",
"sequence",
"resource_owner",
}
prepareTriggerActionStmt = `SELECT projections.actions3.id,` +
` projections.actions3.creation_date,` +
` projections.actions3.change_date,` +
` projections.actions3.resource_owner,` +
` projections.actions3.action_state,` +
` projections.actions3.sequence,` +
` projections.actions3.name,` +
` projections.actions3.script,` +
` projections.actions3.allowed_to_fail,` +
` projections.actions3.timeout` +
` FROM projections.flow_triggers2` +
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id AND projections.flow_triggers2.instance_id = projections.actions3.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
prepareTriggerActionCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
}
prepareFlowTypeStmt = `SELECT projections.flow_triggers2.flow_type` +
` FROM projections.flow_triggers2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareFlowTypeCols = []string{
"flow_type",
}
)
func Test_FlowPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -27,29 +104,12 @@ func Test_FlowPrepares(t *testing.T) {
}{
{
name: "prepareFlowQuery no result",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
},
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout,`+
` projections.flow_triggers2.trigger_type,`+
` projections.flow_triggers2.trigger_sequence,`+
` projections.flow_triggers2.flow_type,`+
` projections.flow_triggers2.change_date,`+
` projections.flow_triggers2.sequence,`+
` projections.flow_triggers2.resource_owner`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
regexp.QuoteMeta(prepareFlowStmt),
nil,
nil,
),
@@ -61,48 +121,13 @@ func Test_FlowPrepares(t *testing.T) {
},
{
name: "prepareFlowQuery one action",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
},
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout,`+
` projections.flow_triggers2.trigger_type,`+
` projections.flow_triggers2.trigger_sequence,`+
` projections.flow_triggers2.flow_type,`+
` projections.flow_triggers2.change_date,`+
` projections.flow_triggers2.sequence,`+
` projections.flow_triggers2.resource_owner`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
//flow
"trigger_type",
"trigger_sequence",
"flow_type",
"change_date",
"sequence",
"resource_owner",
},
regexp.QuoteMeta(prepareFlowStmt),
prepareFlowCols,
[][]driver.Value{
{
"action-id",
@@ -150,48 +175,13 @@ func Test_FlowPrepares(t *testing.T) {
},
{
name: "prepareFlowQuery multiple actions",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
},
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout,`+
` projections.flow_triggers2.trigger_type,`+
` projections.flow_triggers2.trigger_sequence,`+
` projections.flow_triggers2.flow_type,`+
` projections.flow_triggers2.change_date,`+
` projections.flow_triggers2.sequence,`+
` projections.flow_triggers2.resource_owner`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
//flow
"trigger_type",
"trigger_sequence",
"flow_type",
"change_date",
"sequence",
"resource_owner",
},
regexp.QuoteMeta(prepareFlowStmt),
prepareFlowCols,
[][]driver.Value{
{
"action-id-pre",
@@ -271,48 +261,13 @@ func Test_FlowPrepares(t *testing.T) {
},
{
name: "prepareFlowQuery no action",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
},
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout,`+
` projections.flow_triggers2.trigger_type,`+
` projections.flow_triggers2.trigger_sequence,`+
` projections.flow_triggers2.flow_type,`+
` projections.flow_triggers2.change_date,`+
` projections.flow_triggers2.sequence,`+
` projections.flow_triggers2.resource_owner`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
//flow
"trigger_type",
"trigger_sequence",
"flow_type",
"change_date",
"sequence",
"resource_owner",
},
regexp.QuoteMeta(prepareFlowStmt),
prepareFlowCols,
[][]driver.Value{
{
nil,
@@ -345,29 +300,12 @@ func Test_FlowPrepares(t *testing.T) {
},
{
name: "prepareFlowQuery sql err",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(domain.FlowTypeExternalAuthentication)
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Flow, error)) {
return prepareFlowQuery(ctx, db, domain.FlowTypeExternalAuthentication)
},
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout,`+
` projections.flow_triggers2.trigger_type,`+
` projections.flow_triggers2.trigger_sequence,`+
` projections.flow_triggers2.flow_type,`+
` projections.flow_triggers2.change_date,`+
` projections.flow_triggers2.sequence,`+
` projections.flow_triggers2.resource_owner`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
regexp.QuoteMeta(prepareFlowStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -384,18 +322,7 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareTriggerActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
regexp.QuoteMeta(prepareTriggerActionStmt),
nil,
nil,
),
@@ -407,30 +334,8 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareTriggerActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
},
regexp.QuoteMeta(prepareTriggerActionStmt),
prepareTriggerActionCols,
[][]driver.Value{
{
"action-id",
@@ -467,30 +372,8 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareTriggerActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"script",
"allowed_to_fail",
"timeout",
},
regexp.QuoteMeta(prepareTriggerActionStmt),
prepareTriggerActionCols,
[][]driver.Value{
{
"action-id-1",
@@ -551,18 +434,7 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareTriggerActionsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.action_state,`+
` projections.actions3.sequence,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.allowed_to_fail,`+
` projections.actions3.timeout`+
` FROM projections.flow_triggers2`+
` LEFT JOIN projections.actions3 ON projections.flow_triggers2.action_id = projections.actions3.id`),
regexp.QuoteMeta(prepareTriggerActionStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -579,8 +451,7 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareFlowTypesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
` FROM projections.flow_triggers2`),
regexp.QuoteMeta(prepareFlowTypeStmt),
nil,
nil,
),
@@ -592,11 +463,8 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareFlowTypesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
` FROM projections.flow_triggers2`),
[]string{
"flow_type",
},
regexp.QuoteMeta(prepareFlowTypeStmt),
prepareFlowTypeCols,
[][]driver.Value{
{
domain.FlowTypeExternalAuthentication,
@@ -613,11 +481,8 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareFlowTypesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
` FROM projections.flow_triggers2`),
[]string{
"flow_type",
},
regexp.QuoteMeta(prepareFlowTypeStmt),
prepareFlowTypeCols,
[][]driver.Value{
{
domain.FlowTypeExternalAuthentication,
@@ -638,8 +503,7 @@ func Test_FlowPrepares(t *testing.T) {
prepare: prepareFlowTypesQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.flow_triggers2.flow_type`+
` FROM projections.flow_triggers2`),
regexp.QuoteMeta(prepareFlowTypeStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -654,7 +518,7 @@ func Test_FlowPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+65 -120
View File
@@ -13,6 +13,60 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareActionsStmt = `SELECT projections.actions3.id,` +
` projections.actions3.creation_date,` +
` projections.actions3.change_date,` +
` projections.actions3.resource_owner,` +
` projections.actions3.sequence,` +
` projections.actions3.action_state,` +
` projections.actions3.name,` +
` projections.actions3.script,` +
` projections.actions3.timeout,` +
` projections.actions3.allowed_to_fail,` +
` COUNT(*) OVER ()` +
` FROM projections.actions3` +
` AS OF SYSTEM TIME '-1 ms'`
prepareActionsCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"action_state",
"name",
"script",
"timeout",
"allowed_to_fail",
"count",
}
prepareActionStmt = `SELECT projections.actions3.id,` +
` projections.actions3.creation_date,` +
` projections.actions3.change_date,` +
` projections.actions3.resource_owner,` +
` projections.actions3.sequence,` +
` projections.actions3.action_state,` +
` projections.actions3.name,` +
` projections.actions3.script,` +
` projections.actions3.timeout,` +
` projections.actions3.allowed_to_fail` +
` FROM projections.actions3` +
` AS OF SYSTEM TIME '-1 ms'`
prepareActionCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"action_state",
"name",
"script",
"timeout",
"allowed_to_fail",
}
)
func Test_ActionPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -29,18 +83,7 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail,`+
` COUNT(*) OVER ()`+
` FROM projections.actions3`),
regexp.QuoteMeta(prepareActionsStmt),
nil,
nil,
),
@@ -52,31 +95,8 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail,`+
` COUNT(*) OVER ()`+
` FROM projections.actions3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"action_state",
"name",
"script",
"timeout",
"allowed_to_fail",
"count",
},
regexp.QuoteMeta(prepareActionsStmt),
prepareActionsCols,
[][]driver.Value{
{
"id",
@@ -118,31 +138,8 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail,`+
` COUNT(*) OVER ()`+
` FROM projections.actions3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"action_state",
"name",
"script",
"timeout",
"allowed_to_fail",
"count",
},
regexp.QuoteMeta(prepareActionsStmt),
prepareActionsCols,
[][]driver.Value{
{
"id-1",
@@ -208,18 +205,7 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail,`+
` COUNT(*) OVER ()`+
` FROM projections.actions3`),
regexp.QuoteMeta(prepareActionsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -236,17 +222,7 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail`+
` FROM projections.actions3`),
regexp.QuoteMeta(prepareActionStmt),
nil,
nil,
),
@@ -264,29 +240,8 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail`+
` FROM projections.actions3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"action_state",
"name",
"script",
"timeout",
"allowed_to_fail",
},
regexp.QuoteMeta(prepareActionStmt),
prepareActionCols,
[]driver.Value{
"id",
testNow,
@@ -319,17 +274,7 @@ func Test_ActionPrepares(t *testing.T) {
prepare: prepareActionQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.actions3.id,`+
` projections.actions3.creation_date,`+
` projections.actions3.change_date,`+
` projections.actions3.resource_owner,`+
` projections.actions3.sequence,`+
` projections.actions3.action_state,`+
` projections.actions3.name,`+
` projections.actions3.script,`+
` projections.actions3.timeout,`+
` projections.actions3.allowed_to_fail`+
` FROM projections.actions3`),
regexp.QuoteMeta(prepareActionStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -344,7 +289,7 @@ func Test_ActionPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+22 -21
View File
@@ -10,6 +10,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -250,7 +251,7 @@ func (q *Queries) AppByProjectAndAppID(ctx context.Context, shouldTriggerBulk bo
projection.AppProjection.Trigger(ctx)
}
stmt, scan := prepareAppQuery()
stmt, scan := prepareAppQuery(ctx, q.client)
eq := sq.Eq{
AppColumnID.identifier(): appID,
AppColumnProjectID.identifier(): projectID,
@@ -272,7 +273,7 @@ func (q *Queries) AppByID(ctx context.Context, appID string, withOwnerRemoved bo
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAppQuery()
stmt, scan := prepareAppQuery(ctx, q.client)
eq := sq.Eq{
AppColumnID.identifier(): appID,
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -293,7 +294,7 @@ func (q *Queries) AppBySAMLEntityID(ctx context.Context, entityID string, withOw
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAppQuery()
stmt, scan := prepareAppQuery(ctx, q.client)
eq := sq.Eq{
AppSAMLConfigColumnEntityID.identifier(): entityID,
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -314,7 +315,7 @@ func (q *Queries) ProjectByClientID(ctx context.Context, appID string, withOwner
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareProjectByAppQuery()
stmt, scan := prepareProjectByAppQuery(ctx, q.client)
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[ProjectColumnOwnerRemoved.identifier()] = false
@@ -339,7 +340,7 @@ func (q *Queries) ProjectIDFromOIDCClientID(ctx context.Context, appID string, w
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareProjectIDByAppQuery()
stmt, scan := prepareProjectIDByAppQuery(ctx, q.client)
eq := sq.Eq{
AppOIDCConfigColumnClientID.identifier(): appID,
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -360,7 +361,7 @@ func (q *Queries) ProjectIDFromClientID(ctx context.Context, appID string, withO
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareProjectIDByAppQuery()
stmt, scan := prepareProjectIDByAppQuery(ctx, q.client)
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[AppColumnOwnerRemoved.identifier()] = false
@@ -386,7 +387,7 @@ func (q *Queries) ProjectByOIDCClientID(ctx context.Context, id string, withOwne
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareProjectByAppQuery()
stmt, scan := prepareProjectByAppQuery(ctx, q.client)
eq := sq.Eq{
AppOIDCConfigColumnClientID.identifier(): id,
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -407,7 +408,7 @@ func (q *Queries) AppByOIDCClientID(ctx context.Context, clientID string, withOw
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAppQuery()
stmt, scan := prepareAppQuery(ctx, q.client)
eq := sq.Eq{
AppOIDCConfigColumnClientID.identifier(): clientID,
AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -428,7 +429,7 @@ func (q *Queries) AppByClientID(ctx context.Context, clientID string, withOwnerR
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAppQuery()
stmt, scan := prepareAppQuery(ctx, q.client)
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[AppColumnOwnerRemoved.identifier()] = false
@@ -452,7 +453,7 @@ func (q *Queries) SearchApps(ctx context.Context, queries *AppSearchQueries, wit
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareAppsQuery()
query, scan := prepareAppsQuery(ctx, q.client)
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[AppColumnOwnerRemoved.identifier()] = false
@@ -478,7 +479,7 @@ func (q *Queries) SearchClientIDs(ctx context.Context, queries *AppSearchQueries
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareClientIDsQuery()
query, scan := prepareClientIDsQuery(ctx, q.client)
eq := sq.Eq{AppColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[AppColumnOwnerRemoved.identifier()] = false
@@ -503,7 +504,7 @@ func NewAppProjectIDSearchQuery(id string) (SearchQuery, error) {
return NewTextQuery(AppColumnProjectID, id, TextEquals)
}
func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
func prepareAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
return sq.Select(
AppColumnID.identifier(),
AppColumnName.identifier(),
@@ -542,7 +543,7 @@ func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
).From(appsTable.identifier()).
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*App, error) {
app := new(App)
@@ -604,13 +605,13 @@ func prepareAppQuery() (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
}
}
func prepareProjectIDByAppQuery() (sq.SelectBuilder, func(*sql.Row) (projectID string, err error)) {
func prepareProjectIDByAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (projectID string, err error)) {
return sq.Select(
AppColumnProjectID.identifier(),
).From(appsTable.identifier()).
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (projectID string, err error) {
err = row.Scan(
&projectID,
@@ -627,7 +628,7 @@ func prepareProjectIDByAppQuery() (sq.SelectBuilder, func(*sql.Row) (projectID s
}
}
func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
func prepareProjectByAppQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
return sq.Select(
ProjectColumnID.identifier(),
ProjectColumnCreationDate.identifier(),
@@ -644,7 +645,7 @@ func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, err
Join(join(AppColumnProjectID, ProjectColumnID)).
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Project, error) {
p := new(Project)
@@ -671,7 +672,7 @@ func prepareProjectByAppQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, err
}
}
func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
func prepareAppsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
return sq.Select(
AppColumnID.identifier(),
AppColumnName.identifier(),
@@ -711,7 +712,7 @@ func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
).From(appsTable.identifier()).
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppSAMLConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(row *sql.Rows) (*Apps, error) {
apps := &Apps{Apps: []*App{}}
@@ -777,13 +778,13 @@ func prepareAppsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Apps, error)) {
}
}
func prepareClientIDsQuery() (sq.SelectBuilder, func(*sql.Rows) ([]string, error)) {
func prepareClientIDsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) ([]string, error)) {
return sq.Select(
AppAPIConfigColumnClientID.identifier(),
AppOIDCConfigColumnClientID.identifier(),
).From(appsTable.identifier()).
LeftJoin(join(AppAPIConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID)).
LeftJoin(join(AppOIDCConfigColumnAppID, AppColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(rows *sql.Rows) ([]string, error) {
ids := database.StringArray{}
+15 -10
View File
@@ -52,7 +52,8 @@ var (
` FROM projections.apps4` +
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedAppsQuery = regexp.QuoteMeta(`SELECT projections.apps4.id,` +
` projections.apps4.name,` +
` projections.apps4.project_id,` +
@@ -91,17 +92,20 @@ var (
` FROM projections.apps4` +
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedAppIDsQuery = regexp.QuoteMeta(`SELECT projections.apps4_api_configs.client_id,` +
` projections.apps4_oidc_configs.client_id` +
` FROM projections.apps4` +
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id`)
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedProjectIDByAppQuery = regexp.QuoteMeta(`SELECT projections.apps4.project_id` +
` FROM projections.apps4` +
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedProjectByAppQuery = regexp.QuoteMeta(`SELECT projections.projects3.id,` +
` projections.projects3.creation_date,` +
` projections.projects3.change_date,` +
@@ -117,7 +121,8 @@ var (
` JOIN projections.apps4 ON projections.projects3.id = projections.apps4.project_id AND projections.projects3.instance_id = projections.apps4.instance_id` +
` LEFT JOIN projections.apps4_api_configs ON projections.apps4.id = projections.apps4_api_configs.app_id AND projections.apps4.instance_id = projections.apps4_api_configs.instance_id` +
` LEFT JOIN projections.apps4_oidc_configs ON projections.apps4.id = projections.apps4_oidc_configs.app_id AND projections.apps4.instance_id = projections.apps4_oidc_configs.instance_id` +
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id`)
` LEFT JOIN projections.apps4_saml_configs ON projections.apps4.id = projections.apps4_saml_configs.app_id AND projections.apps4.instance_id = projections.apps4_saml_configs.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
appCols = database.StringArray{
"id",
@@ -1009,7 +1014,7 @@ func Test_AppsPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -1628,7 +1633,7 @@ func Test_AppPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -1714,7 +1719,7 @@ func Test_AppIDsPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -1780,7 +1785,7 @@ func Test_ProjectIDByAppPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -1978,7 +1983,7 @@ func Test_ProjectByAppPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+17 -12
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -129,7 +130,7 @@ func (q *Queries) SearchAuthNKeys(ctx context.Context, queries *AuthNKeySearchQu
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareAuthNKeysQuery()
query, scan := prepareAuthNKeysQuery(ctx, q.client)
query = queries.toQuery(query)
eq := sq.Eq{
AuthNKeyColumnEnabled.identifier(): true,
@@ -159,7 +160,7 @@ func (q *Queries) SearchAuthNKeysData(ctx context.Context, queries *AuthNKeySear
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareAuthNKeysDataQuery()
query, scan := prepareAuthNKeysDataQuery(ctx, q.client)
query = queries.toQuery(query)
eq := sq.Eq{
AuthNKeyColumnEnabled.identifier(): true,
@@ -193,7 +194,7 @@ func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, i
projection.AuthNKeyProjection.Trigger(ctx)
}
query, scan := prepareAuthNKeyQuery()
query, scan := prepareAuthNKeyQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -218,7 +219,7 @@ func (q *Queries) GetAuthNKeyPublicKeyByIDAndIdentifier(ctx context.Context, id
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAuthNKeyPublicKeyQuery()
stmt, scan := prepareAuthNKeyPublicKeyQuery(ctx, q.client)
eq := sq.And{
sq.Eq{
AuthNKeyColumnID.identifier(): id,
@@ -265,7 +266,7 @@ func NewAuthNKeyObjectIDQuery(id string) (SearchQuery, error) {
return NewTextQuery(AuthNKeyColumnObjectID, id, TextEquals)
}
func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys, error)) {
func prepareAuthNKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys, error)) {
return sq.Select(
AuthNKeyColumnID.identifier(),
AuthNKeyColumnCreationDate.identifier(),
@@ -275,7 +276,8 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
AuthNKeyColumnExpiration.identifier(),
AuthNKeyColumnType.identifier(),
countColumn.identifier(),
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*AuthNKeys, error) {
authNKeys := make([]*AuthNKey, 0)
var count uint64
@@ -310,7 +312,7 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
}
}
func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, error)) {
func prepareAuthNKeyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, error)) {
return sq.Select(
AuthNKeyColumnID.identifier(),
AuthNKeyColumnCreationDate.identifier(),
@@ -319,7 +321,8 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er
AuthNKeyColumnSequence.identifier(),
AuthNKeyColumnExpiration.identifier(),
AuthNKeyColumnType.identifier(),
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*AuthNKey, error) {
authNKey := new(AuthNKey)
err := row.Scan(
@@ -341,10 +344,11 @@ func prepareAuthNKeyQuery() (sq.SelectBuilder, func(row *sql.Row) (*AuthNKey, er
}
}
func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]byte, error)) {
func prepareAuthNKeyPublicKeyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(row *sql.Row) ([]byte, error)) {
return sq.Select(
AuthNKeyColumnPublicKey.identifier(),
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) ([]byte, error) {
var publicKey []byte
err := row.Scan(
@@ -360,7 +364,7 @@ func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]by
}
}
func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
func prepareAuthNKeysDataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
return sq.Select(
AuthNKeyColumnID.identifier(),
AuthNKeyColumnCreationDate.identifier(),
@@ -372,7 +376,8 @@ func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthN
AuthNKeyColumnIdentifier.identifier(),
AuthNKeyColumnPublicKey.identifier(),
countColumn.identifier(),
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(authNKeyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*AuthNKeysData, error) {
authNKeys := make([]*AuthNKeyData, 0)
var count uint64
+95 -167
View File
@@ -12,6 +12,80 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareAuthNKeysStmt = `SELECT projections.authn_keys2.id,` +
` projections.authn_keys2.creation_date,` +
` projections.authn_keys2.change_date,` +
` projections.authn_keys2.resource_owner,` +
` projections.authn_keys2.sequence,` +
` projections.authn_keys2.expiration,` +
` projections.authn_keys2.type,` +
` COUNT(*) OVER ()` +
` FROM projections.authn_keys2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareAuthNKeysCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"count",
}
prepareAuthNKeysDataStmt = `SELECT projections.authn_keys2.id,` +
` projections.authn_keys2.creation_date,` +
` projections.authn_keys2.change_date,` +
` projections.authn_keys2.resource_owner,` +
` projections.authn_keys2.sequence,` +
` projections.authn_keys2.expiration,` +
` projections.authn_keys2.type,` +
` projections.authn_keys2.identifier,` +
` projections.authn_keys2.public_key,` +
` COUNT(*) OVER ()` +
` FROM projections.authn_keys2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareAuthNKeysDataCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"identifier",
"public_key",
"count",
}
prepareAuthNKeyStmt = `SELECT projections.authn_keys2.id,` +
` projections.authn_keys2.creation_date,` +
` projections.authn_keys2.change_date,` +
` projections.authn_keys2.resource_owner,` +
` projections.authn_keys2.sequence,` +
` projections.authn_keys2.expiration,` +
` projections.authn_keys2.type` +
` FROM projections.authn_keys2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareAuthNKeyCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
}
prepareAuthNKeyPublicKeyStmt = `SELECT projections.authn_keys2.public_key` +
` FROM projections.authn_keys2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareAuthNKeyPublicKeyCols = []string{
"public_key",
}
)
func Test_AuthNKeyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,15 +102,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeysStmt),
nil,
nil,
),
@@ -48,25 +114,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"count",
},
regexp.QuoteMeta(prepareAuthNKeysStmt),
prepareAuthNKeysCols,
[][]driver.Value{
{
"id",
@@ -102,25 +151,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"count",
},
regexp.QuoteMeta(prepareAuthNKeysStmt),
prepareAuthNKeysCols,
[][]driver.Value{
{
"id-1",
@@ -174,15 +206,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeysStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -199,17 +223,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` projections.authn_keys2.identifier,`+
` projections.authn_keys2.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
nil,
nil,
),
@@ -221,29 +235,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` projections.authn_keys2.identifier,`+
` projections.authn_keys2.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"identifier",
"public_key",
"count",
},
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
prepareAuthNKeysDataCols,
[][]driver.Value{
{
"id",
@@ -283,29 +276,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` projections.authn_keys2.identifier,`+
` projections.authn_keys2.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
"identifier",
"public_key",
"count",
},
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
prepareAuthNKeysDataCols,
[][]driver.Value{
{
"id-1",
@@ -367,17 +339,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type,`+
` projections.authn_keys2.identifier,`+
` projections.authn_keys2.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeysDataStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -394,14 +356,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeyStmt),
nil,
nil,
),
@@ -419,23 +374,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type`+
` FROM projections.authn_keys2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"expiration",
"type",
},
regexp.QuoteMeta(prepareAuthNKeyStmt),
prepareAuthNKeyCols,
[]driver.Value{
"id",
testNow,
@@ -462,14 +402,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.authn_keys2.id,`+
` projections.authn_keys2.creation_date,`+
` projections.authn_keys2.change_date,`+
` projections.authn_keys2.resource_owner,`+
` projections.authn_keys2.sequence,`+
` projections.authn_keys2.expiration,`+
` projections.authn_keys2.type`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -486,8 +419,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyPublicKeyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
nil,
nil,
),
@@ -505,11 +437,8 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyPublicKeyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
` FROM projections.authn_keys2`),
[]string{
"public_key",
},
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
prepareAuthNKeyPublicKeyCols,
[]driver.Value{
[]byte("publicKey"),
},
@@ -522,8 +451,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
prepare: prepareAuthNKeyPublicKeyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.authn_keys2.public_key`+
` FROM projections.authn_keys2`),
regexp.QuoteMeta(prepareAuthNKeyPublicKeyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -538,7 +466,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+4 -3
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -69,7 +70,7 @@ func (q *Queries) ActiveCertificates(ctx context.Context, t time.Time, usage dom
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareCertificateQuery()
query, scan := prepareCertificateQuery(ctx, q.client)
if t.IsZero() {
t = time.Now()
}
@@ -102,7 +103,7 @@ func (q *Queries) ActiveCertificates(ctx context.Context, t time.Time, usage dom
return keys, nil
}
func prepareCertificateQuery() (sq.SelectBuilder, func(*sql.Rows) (*Certificates, error)) {
func prepareCertificateQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Certificates, error)) {
return sq.Select(
KeyColID.identifier(),
KeyColCreationDate.identifier(),
@@ -117,7 +118,7 @@ func prepareCertificateQuery() (sq.SelectBuilder, func(*sql.Rows) (*Certificates
countColumn.identifier(),
).From(keyTable.identifier()).
LeftJoin(join(CertificateColID, KeyColID)).
LeftJoin(join(KeyPrivateColID, KeyColID)).
LeftJoin(join(KeyPrivateColID, KeyColID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Certificates, error) {
certificates := make([]Certificate, 0)
+36 -56
View File
@@ -13,6 +13,37 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareCertificateStmt = `SELECT projections.keys4.id,` +
` projections.keys4.creation_date,` +
` projections.keys4.change_date,` +
` projections.keys4.sequence,` +
` projections.keys4.resource_owner,` +
` projections.keys4.algorithm,` +
` projections.keys4.use,` +
` projections.keys4_certificate.expiry,` +
` projections.keys4_certificate.certificate,` +
` projections.keys4_private.key,` +
` COUNT(*) OVER ()` +
` FROM projections.keys4` +
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id` +
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
prepareCertificateCols = []string{
"id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"algorithm",
"use",
"expiry",
"certificate",
"key",
"count",
}
)
func Test_CertificatePrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -29,20 +60,7 @@ func Test_CertificatePrepares(t *testing.T) {
prepare: prepareCertificateQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_certificate.expiry,`+
` projections.keys4_certificate.certificate,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
regexp.QuoteMeta(prepareCertificateStmt),
nil,
nil,
),
@@ -60,33 +78,8 @@ func Test_CertificatePrepares(t *testing.T) {
prepare: prepareCertificateQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_certificate.expiry,`+
` projections.keys4_certificate.certificate,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
[]string{
"id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"algorithm",
"use",
"expiry",
"certificate",
"key",
"count",
},
regexp.QuoteMeta(prepareCertificateStmt),
prepareCertificateCols,
[][]driver.Value{
{
"key-id",
@@ -135,20 +128,7 @@ func Test_CertificatePrepares(t *testing.T) {
prepare: prepareCertificateQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_certificate.expiry,`+
` projections.keys4_certificate.certificate,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_certificate ON projections.keys4.id = projections.keys4_certificate.id AND projections.keys4.instance_id = projections.keys4_certificate.instance_id`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id`),
regexp.QuoteMeta(prepareCertificateStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -163,7 +143,7 @@ func Test_CertificatePrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+1 -1
View File
@@ -93,7 +93,7 @@ func (q *Queries) UserChanges(ctx context.Context, userID string, lastSequence u
}
func (q *Queries) changes(ctx context.Context, query func(query *eventstore.SearchQuery), lastSequence uint64, limit uint64, sortAscending bool, auditLogRetention time.Duration) (*Changes, error) {
builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit)
builder := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).Limit(limit).AllowTimeTravel()
if !sortAscending {
builder.OrderDesc()
}
+8 -6
View File
@@ -10,6 +10,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -59,7 +60,7 @@ func (q *Queries) SearchCurrentSequences(ctx context.Context, queries *CurrentSe
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareCurrentSequencesQuery()
query, scan := prepareCurrentSequencesQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-MmFef", "Errors.Query.InvalidRequest")
@@ -76,7 +77,7 @@ func (q *Queries) latestSequence(ctx context.Context, projections ...table) (_ *
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLatestSequence()
query, scan := prepareLatestSequence(ctx, q.client)
or := make(sq.Or, len(projections))
for i, projection := range projections {
or[i] = sq.Eq{CurrentSequenceColProjectionName.identifier(): projection.name}
@@ -201,11 +202,12 @@ func reset(tx *sql.Tx, tables []string, projectionName string) error {
return nil
}
func prepareLatestSequence() (sq.SelectBuilder, func(*sql.Row) (*LatestSequence, error)) {
func prepareLatestSequence(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LatestSequence, error)) {
return sq.Select(
CurrentSequenceColCurrentSequence.identifier(),
CurrentSequenceColTimestamp.identifier()).
From(currentSequencesTable.identifier()).PlaceholderFormat(sq.Dollar),
From(currentSequencesTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*LatestSequence, error) {
seq := new(LatestSequence)
err := row.Scan(
@@ -219,13 +221,13 @@ func prepareLatestSequence() (sq.SelectBuilder, func(*sql.Row) (*LatestSequence,
}
}
func prepareCurrentSequencesQuery() (sq.SelectBuilder, func(*sql.Rows) (*CurrentSequences, error)) {
func prepareCurrentSequencesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*CurrentSequences, error)) {
return sq.Select(
"max("+CurrentSequenceColCurrentSequence.identifier()+") as "+CurrentSequenceColCurrentSequence.name,
"max("+CurrentSequenceColTimestamp.identifier()+") as "+CurrentSequenceColTimestamp.name,
CurrentSequenceColProjectionName.identifier(),
countColumn.identifier()).
From(currentSequencesTable.identifier()).
From(currentSequencesTable.identifier() + db.Timetravel(call.Took(ctx))).
GroupBy(CurrentSequenceColProjectionName.identifier()).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*CurrentSequences, error) {
+24 -37
View File
@@ -9,6 +9,23 @@ import (
"testing"
)
var (
currentSequenceStmt = `SELECT max(projections.current_sequences.current_sequence) as current_sequence,` +
` max(projections.current_sequences.timestamp) as timestamp,` +
` projections.current_sequences.projection_name,` +
` COUNT(*) OVER ()` +
` FROM projections.current_sequences` +
" AS OF SYSTEM TIME '-1 ms' " +
` GROUP BY projections.current_sequences.projection_name`
currentSequenceCols = []string{
"current_sequence",
"timestamp",
"projection_name",
"count",
}
)
func Test_CurrentSequencesPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -25,12 +42,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
prepare: prepareCurrentSequencesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
` max(projections.current_sequences.timestamp) as timestamp,`+
` projections.current_sequences.projection_name,`+
` COUNT(*) OVER ()`+
` FROM projections.current_sequences`+
` GROUP BY projections.current_sequences.projection_name`),
regexp.QuoteMeta(currentSequenceStmt),
nil,
nil,
),
@@ -42,18 +54,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
prepare: prepareCurrentSequencesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
` max(projections.current_sequences.timestamp) as timestamp,`+
` projections.current_sequences.projection_name,`+
` COUNT(*) OVER ()`+
` FROM projections.current_sequences`+
` GROUP BY projections.current_sequences.projection_name`),
[]string{
"current_sequence",
"timestamp",
"projection_name",
"count",
},
regexp.QuoteMeta(currentSequenceStmt),
currentSequenceCols,
[][]driver.Value{
{
uint64(20211108),
@@ -81,18 +83,8 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
prepare: prepareCurrentSequencesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
` max(projections.current_sequences.timestamp) as timestamp,`+
` projections.current_sequences.projection_name,`+
` COUNT(*) OVER ()`+
` FROM projections.current_sequences`+
` GROUP BY projections.current_sequences.projection_name`),
[]string{
"current_sequence",
"timestamp",
"projection_name",
"count",
},
regexp.QuoteMeta(currentSequenceStmt),
currentSequenceCols,
[][]driver.Value{
{
uint64(20211108),
@@ -130,12 +122,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
prepare: prepareCurrentSequencesQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT max(projections.current_sequences.current_sequence) as current_sequence,`+
` max(projections.current_sequences.timestamp) as timestamp,`+
` projections.current_sequences.projection_name,`+
` COUNT(*) OVER ()`+
` FROM projections.current_sequences`+
` GROUP BY projections.current_sequences.projection_name`),
regexp.QuoteMeta(currentSequenceStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -150,7 +137,7 @@ func Test_CurrentSequencesPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -13,6 +13,7 @@ import (
"sigs.k8s.io/yaml"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
@@ -88,7 +89,7 @@ func (q *Queries) CustomTextList(ctx context.Context, aggregateID, template, lan
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareCustomTextsQuery()
stmt, scan := prepareCustomTextsQuery(ctx, q.client)
eq := sq.Eq{
CustomTextColAggregateID.identifier(): aggregateID,
CustomTextColTemplate.identifier(): template,
@@ -119,7 +120,7 @@ func (q *Queries) CustomTextListByTemplate(ctx context.Context, aggregateID, tem
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareCustomTextsQuery()
stmt, scan := prepareCustomTextsQuery(ctx, q.client)
eq := sq.Eq{
CustomTextColAggregateID.identifier(): aggregateID,
CustomTextColTemplate.identifier(): template,
@@ -228,7 +229,7 @@ func (q *Queries) readLoginTranslationFile(ctx context.Context, lang string) ([]
return contents, nil
}
func prepareCustomTextsQuery() (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts, error)) {
func prepareCustomTextsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts, error)) {
return sq.Select(
CustomTextColAggregateID.identifier(),
CustomTextColSequence.identifier(),
@@ -239,7 +240,8 @@ func prepareCustomTextsQuery() (sq.SelectBuilder, func(*sql.Rows) (*CustomTexts,
CustomTextColKey.identifier(),
CustomTextColText.identifier(),
countColumn.identifier()).
From(customTextTable.identifier()).PlaceholderFormat(sq.Dollar),
From(customTextTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*CustomTexts, error) {
customTexts := make([]*CustomText, 0)
var count uint64
+32 -63
View File
@@ -13,6 +13,31 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareCustomTextsStmt = `SELECT projections.custom_texts2.aggregate_id,` +
` projections.custom_texts2.sequence,` +
` projections.custom_texts2.creation_date,` +
` projections.custom_texts2.change_date,` +
` projections.custom_texts2.language,` +
` projections.custom_texts2.template,` +
` projections.custom_texts2.key,` +
` projections.custom_texts2.text,` +
` COUNT(*) OVER ()` +
` FROM projections.custom_texts2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareCustomTextsCols = []string{
"aggregate_id",
"sequence",
"creation_date",
"change_date",
"language",
"template",
"key",
"text",
"count",
}
)
func Test_CustomTextPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -29,16 +54,7 @@ func Test_CustomTextPrepares(t *testing.T) {
prepare: prepareCustomTextsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
` projections.custom_texts2.sequence,`+
` projections.custom_texts2.creation_date,`+
` projections.custom_texts2.change_date,`+
` projections.custom_texts2.language,`+
` projections.custom_texts2.template,`+
` projections.custom_texts2.key,`+
` projections.custom_texts2.text,`+
` COUNT(*) OVER ()`+
` FROM projections.custom_texts2`),
regexp.QuoteMeta(prepareCustomTextsStmt),
nil,
nil,
),
@@ -56,27 +72,8 @@ func Test_CustomTextPrepares(t *testing.T) {
prepare: prepareCustomTextsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
` projections.custom_texts2.sequence,`+
` projections.custom_texts2.creation_date,`+
` projections.custom_texts2.change_date,`+
` projections.custom_texts2.language,`+
` projections.custom_texts2.template,`+
` projections.custom_texts2.key,`+
` projections.custom_texts2.text,`+
` COUNT(*) OVER ()`+
` FROM projections.custom_texts2`),
[]string{
"aggregate_id",
"sequence",
"creation_date",
"change_date",
"language",
"template",
"key",
"text",
"count",
},
regexp.QuoteMeta(prepareCustomTextsStmt),
prepareCustomTextsCols,
[][]driver.Value{
{
"agg-id",
@@ -114,27 +111,8 @@ func Test_CustomTextPrepares(t *testing.T) {
prepare: prepareCustomTextsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
` projections.custom_texts2.sequence,`+
` projections.custom_texts2.creation_date,`+
` projections.custom_texts2.change_date,`+
` projections.custom_texts2.language,`+
` projections.custom_texts2.template,`+
` projections.custom_texts2.key,`+
` projections.custom_texts2.text,`+
` COUNT(*) OVER ()`+
` FROM projections.custom_texts2`),
[]string{
"aggregate_id",
"sequence",
"creation_date",
"change_date",
"language",
"template",
"key",
"text",
"count",
},
regexp.QuoteMeta(prepareCustomTextsStmt),
prepareCustomTextsCols,
[][]driver.Value{
{
"agg-id",
@@ -192,16 +170,7 @@ func Test_CustomTextPrepares(t *testing.T) {
prepare: prepareCustomTextsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.custom_texts2.aggregate_id,`+
` projections.custom_texts2.sequence,`+
` projections.custom_texts2.creation_date,`+
` projections.custom_texts2.change_date,`+
` projections.custom_texts2.language,`+
` projections.custom_texts2.template,`+
` projections.custom_texts2.key,`+
` projections.custom_texts2.text,`+
` COUNT(*) OVER ()`+
` FROM projections.custom_texts2`),
regexp.QuoteMeta(prepareCustomTextsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -216,7 +185,7 @@ func Test_CustomTextPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -112,7 +113,7 @@ func (q *Queries) DomainPolicyByOrg(ctx context.Context, shouldTriggerBulk bool,
}
}
stmt, scan := prepareDomainPolicyQuery()
stmt, scan := prepareDomainPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(eq).OrderBy(DomainPolicyColIsDefault.identifier()).
Limit(1).ToSql()
if err != nil {
@@ -127,7 +128,7 @@ func (q *Queries) DefaultDomainPolicy(ctx context.Context) (_ *DomainPolicy, err
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareDomainPolicyQuery()
stmt, scan := prepareDomainPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
DomainPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
DomainPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -142,7 +143,7 @@ func (q *Queries) DefaultDomainPolicy(ctx context.Context) (_ *DomainPolicy, err
return scan(row)
}
func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy, error)) {
func prepareDomainPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy, error)) {
return sq.Select(
DomainPolicyColID.identifier(),
DomainPolicyColSequence.identifier(),
@@ -155,7 +156,8 @@ func prepareDomainPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*DomainPolicy
DomainPolicyColIsDefault.identifier(),
DomainPolicyColState.identifier(),
).
From(domainPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
From(domainPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*DomainPolicy, error) {
policy := new(DomainPolicy)
err := row.Scan(
+32 -46
View File
@@ -12,6 +12,33 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareDomainPolicyStmt = `SELECT projections.domain_policies2.id,` +
` projections.domain_policies2.sequence,` +
` projections.domain_policies2.creation_date,` +
` projections.domain_policies2.change_date,` +
` projections.domain_policies2.resource_owner,` +
` projections.domain_policies2.user_login_must_be_domain,` +
` projections.domain_policies2.validate_org_domains,` +
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,` +
` projections.domain_policies2.is_default,` +
` projections.domain_policies2.state` +
` FROM projections.domain_policies2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareDomainPolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"user_login_must_be_domain",
"validate_org_domains",
"smtp_sender_address_matches_instance_domain",
"is_default",
"state",
}
)
func Test_DomainPolicyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,17 +55,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
prepare: prepareDomainPolicyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
` projections.domain_policies2.sequence,`+
` projections.domain_policies2.creation_date,`+
` projections.domain_policies2.change_date,`+
` projections.domain_policies2.resource_owner,`+
` projections.domain_policies2.user_login_must_be_domain,`+
` projections.domain_policies2.validate_org_domains,`+
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
` projections.domain_policies2.is_default,`+
` projections.domain_policies2.state`+
` FROM projections.domain_policies2`),
regexp.QuoteMeta(prepareDomainPolicyStmt),
nil,
nil,
),
@@ -56,29 +73,8 @@ func Test_DomainPolicyPrepares(t *testing.T) {
prepare: prepareDomainPolicyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
` projections.domain_policies2.sequence,`+
` projections.domain_policies2.creation_date,`+
` projections.domain_policies2.change_date,`+
` projections.domain_policies2.resource_owner,`+
` projections.domain_policies2.user_login_must_be_domain,`+
` projections.domain_policies2.validate_org_domains,`+
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
` projections.domain_policies2.is_default,`+
` projections.domain_policies2.state`+
` FROM projections.domain_policies2`),
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"user_login_must_be_domain",
"validate_org_domains",
"smtp_sender_address_matches_instance_domain",
"is_default",
"state",
},
regexp.QuoteMeta(prepareDomainPolicyStmt),
prepareDomainPolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -111,17 +107,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
prepare: prepareDomainPolicyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.domain_policies2.id,`+
` projections.domain_policies2.sequence,`+
` projections.domain_policies2.creation_date,`+
` projections.domain_policies2.change_date,`+
` projections.domain_policies2.resource_owner,`+
` projections.domain_policies2.user_login_must_be_domain,`+
` projections.domain_policies2.validate_org_domains,`+
` projections.domain_policies2.smtp_sender_address_matches_instance_domain,`+
` projections.domain_policies2.is_default,`+
` projections.domain_policies2.state`+
` FROM projections.domain_policies2`),
regexp.QuoteMeta(prepareDomainPolicyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -136,7 +122,7 @@ func Test_DomainPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ type EventEditor struct {
func (q *Queries) SearchEvents(ctx context.Context, query *eventstore.SearchQueryBuilder) (_ []*Event, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
events, err := q.eventstore.Filter(ctx, query)
events, err := q.eventstore.Filter(ctx, query.AllowTimeTravel())
if err != nil {
return nil, err
}
+5 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
)
@@ -70,7 +71,7 @@ type FailedEventSearchQueries struct {
}
func (q *Queries) SearchFailedEvents(ctx context.Context, queries *FailedEventSearchQueries) (failedEvents *FailedEvents, err error) {
query, scan := prepareFailedEventsQuery()
query, scan := prepareFailedEventsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-n8rjJ", "Errors.Query.InvalidRequest")
@@ -123,7 +124,7 @@ func (q *FailedEventSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil
return query
}
func prepareFailedEventsQuery() (sq.SelectBuilder, func(*sql.Rows) (*FailedEvents, error)) {
func prepareFailedEventsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*FailedEvents, error)) {
return sq.Select(
FailedEventsColumnProjectionName.identifier(),
FailedEventsColumnFailedSequence.identifier(),
@@ -131,7 +132,8 @@ func prepareFailedEventsQuery() (sq.SelectBuilder, func(*sql.Rows) (*FailedEvent
FailedEventsColumnLastFailed.identifier(),
FailedEventsColumnError.identifier(),
countColumn.identifier()).
From(failedEventsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(failedEventsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*FailedEvents, error) {
failedEvents := make([]*FailedEvent, 0)
var count uint64
+27 -45
View File
@@ -9,6 +9,26 @@ import (
"testing"
)
var (
prepareFailedEventsStmt = `SELECT projections.failed_events.projection_name,` +
` projections.failed_events.failed_sequence,` +
` projections.failed_events.failure_count,` +
` projections.failed_events.last_failed,` +
` projections.failed_events.error,` +
` COUNT(*) OVER ()` +
` FROM projections.failed_events` +
` AS OF SYSTEM TIME '-1 ms'`
prepareFailedEventsCols = []string{
"projection_name",
"failed_sequence",
"failure_count",
"last_failed",
"error",
"count",
}
)
func Test_FailedEventsPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -25,13 +45,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
prepare: prepareFailedEventsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
` projections.failed_events.failed_sequence,`+
` projections.failed_events.failure_count,`+
` projections.failed_events.last_failed,`+
` projections.failed_events.error,`+
` COUNT(*) OVER ()`+
` FROM projections.failed_events`),
regexp.QuoteMeta(prepareFailedEventsStmt),
nil,
nil,
),
@@ -43,21 +57,8 @@ func Test_FailedEventsPrepares(t *testing.T) {
prepare: prepareFailedEventsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
` projections.failed_events.failed_sequence,`+
` projections.failed_events.failure_count,`+
` projections.failed_events.last_failed,`+
` projections.failed_events.error,`+
` COUNT(*) OVER ()`+
` FROM projections.failed_events`),
[]string{
"projection_name",
"failed_sequence",
"failure_count",
"last_failed",
"error",
"count",
},
regexp.QuoteMeta(prepareFailedEventsStmt),
prepareFailedEventsCols,
[][]driver.Value{
{
"projection-name",
@@ -89,21 +90,8 @@ func Test_FailedEventsPrepares(t *testing.T) {
prepare: prepareFailedEventsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
` projections.failed_events.failed_sequence,`+
` projections.failed_events.failure_count,`+
` projections.failed_events.last_failed,`+
` projections.failed_events.error,`+
` COUNT(*) OVER ()`+
` FROM projections.failed_events`),
[]string{
"projection_name",
"failed_sequence",
"failure_count",
"last_failed",
"error",
"count",
},
regexp.QuoteMeta(prepareFailedEventsStmt),
prepareFailedEventsCols,
[][]driver.Value{
{
"projection-name",
@@ -148,13 +136,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
prepare: prepareFailedEventsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.failed_events.projection_name,`+
` projections.failed_events.failed_sequence,`+
` projections.failed_events.failure_count,`+
` projections.failed_events.last_failed,`+
` projections.failed_events.error,`+
` COUNT(*) OVER ()`+
` FROM projections.failed_events`),
regexp.QuoteMeta(prepareFailedEventsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -169,7 +151,7 @@ func Test_FailedEventsPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+4 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -78,7 +79,7 @@ func (q *Queries) IAMMembers(ctx context.Context, queries *IAMMembersQuery, with
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareInstanceMembersQuery()
query, scan := prepareInstanceMembersQuery(ctx, q.client)
eq := sq.Eq{InstanceMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addIamMemberWithoutOwnerRemoved(eq)
@@ -106,7 +107,7 @@ func (q *Queries) IAMMembers(ctx context.Context, queries *IAMMembersQuery, with
return members, err
}
func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
func prepareInstanceMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
return sq.Select(
InstanceMemberCreationDate.identifier(),
InstanceMemberChangeDate.identifier(),
@@ -125,7 +126,7 @@ func prepareInstanceMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members,
).From(instanceMemberTable.identifier()).
LeftJoin(join(HumanUserIDCol, InstanceMemberUserID)).
LeftJoin(join(MachineUserIDCol, InstanceMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, InstanceMemberUserID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
+2 -1
View File
@@ -34,6 +34,7 @@ var (
"ON members.user_id = projections.users8_machines.user_id AND members.instance_id = projections.users8_machines.instance_id " +
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id AND members.instance_id = projections.login_names2.instance_id " +
"AS OF SYSTEM TIME '-1 ms' " +
"WHERE projections.login_names2.is_primary = $1")
instanceMembersColumns = []string{
"creation_date",
@@ -271,7 +272,7 @@ func Test_IAMMemberPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
@@ -209,7 +210,7 @@ func (q *Queries) IDPByIDAndResourceOwner(ctx context.Context, shouldTriggerBulk
sq.Eq{IDPResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
},
}
stmt, scan := prepareIDPByIDQuery()
stmt, scan := prepareIDPByIDQuery(ctx, q.client)
query, args, err := stmt.Where(where).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-0gocI", "Errors.Query.SQLStatement")
@@ -224,7 +225,7 @@ func (q *Queries) IDPs(ctx context.Context, queries *IDPSearchQueries, withOwner
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareIDPsQuery()
query, scan := prepareIDPsQuery(ctx, q.client)
eq := sq.Eq{
IDPInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
}
@@ -285,7 +286,7 @@ func (q *IDPSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
return query
}
func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
func prepareIDPByIDQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
return sq.Select(
IDPIDCol.identifier(),
IDPResourceOwnerCol.identifier(),
@@ -313,7 +314,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
JWTIDPColEndpoint.identifier(),
).From(idpTable.identifier()).
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
LeftJoin(join(JWTIDPColIDPID, IDPIDCol)).
LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*IDP, error) {
idp := new(IDP)
@@ -393,7 +394,7 @@ func prepareIDPByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDP, error)) {
}
}
func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
func prepareIDPsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
return sq.Select(
IDPIDCol.identifier(),
IDPResourceOwnerCol.identifier(),
@@ -422,7 +423,7 @@ func prepareIDPsQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPs, error)) {
countColumn.identifier(),
).From(idpTable.identifier()).
LeftJoin(join(OIDCIDPColIDPID, IDPIDCol)).
LeftJoin(join(JWTIDPColIDPID, IDPIDCol)).
LeftJoin(join(JWTIDPColIDPID, IDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPs, error) {
idps := make([]*IDP, 0)
+5 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -84,7 +85,7 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareIDPLoginPolicyLinksQuery()
query, scan := prepareIDPLoginPolicyLinksQuery(ctx, q.client)
eq := sq.Eq{
IDPLoginPolicyLinkResourceOwnerCol.identifier(): resourceOwner,
IDPLoginPolicyLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -109,14 +110,15 @@ func (q *Queries) IDPLoginPolicyLinks(ctx context.Context, resourceOwner string,
return idps, err
}
func prepareIDPLoginPolicyLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
func prepareIDPLoginPolicyLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPLoginPolicyLinks, error)) {
return sq.Select(
IDPLoginPolicyLinkIDPIDCol.identifier(),
IDPNameCol.identifier(),
IDPTypeCol.identifier(),
countColumn.identifier()).
From(idpLoginPolicyLinkTable.identifier()).
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol)).PlaceholderFormat(sq.Dollar),
LeftJoin(join(IDPIDCol, IDPLoginPolicyLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPLoginPolicyLinks, error) {
links := make([]*IDPLoginPolicyLink, 0)
var count uint64
+3 -2
View File
@@ -17,7 +17,8 @@ var (
` projections.idps3.type,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_login_policy_links4` +
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id`)
` LEFT JOIN projections.idps3 ON projections.idp_login_policy_links4.idp_id = projections.idps3.id AND projections.idp_login_policy_links4.instance_id = projections.idps3.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
loginPolicyIDPLinksCols = []string{
"idp_id",
"name",
@@ -115,7 +116,7 @@ func Test_IDPLoginPolicyLinkPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+7 -6
View File
@@ -10,6 +10,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
@@ -409,7 +410,7 @@ func (q *Queries) IDPTemplateByIDAndResourceOwner(ctx context.Context, shouldTri
sq.Eq{IDPTemplateResourceOwnerCol.identifier(): authz.GetInstance(ctx).InstanceID()},
},
}
stmt, scan := prepareIDPTemplateByIDQuery()
stmt, scan := prepareIDPTemplateByIDQuery(ctx, q.client)
query, args, err := stmt.Where(where).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-SFAew", "Errors.Query.SQLStatement")
@@ -424,7 +425,7 @@ func (q *Queries) IDPTemplates(ctx context.Context, queries *IDPTemplateSearchQu
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareIDPTemplatesQuery()
query, scan := prepareIDPTemplatesQuery(ctx, q.client)
eq := sq.Eq{
IDPTemplateInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
}
@@ -485,7 +486,7 @@ func (q *IDPTemplateSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil
return query
}
func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTemplate, error)) {
func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*IDPTemplate, error)) {
return sq.Select(
IDPTemplateIDCol.identifier(),
IDPTemplateResourceOwnerCol.identifier(),
@@ -553,7 +554,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*IDPTemplate, error) {
idpTemplate := new(IDPTemplate)
@@ -750,7 +751,7 @@ func prepareIDPTemplateByIDQuery() (sq.SelectBuilder, func(*sql.Row) (*IDPTempla
}
}
func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplates, error)) {
func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplates, error)) {
return sq.Select(
IDPTemplateIDCol.identifier(),
IDPTemplateResourceOwnerCol.identifier(),
@@ -819,7 +820,7 @@ func prepareIDPTemplatesQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPTemplate
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
LeftJoin(join(GoogleIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol)).
LeftJoin(join(LDAPIDCol, IDPTemplateIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPTemplates, error) {
templates := make([]*IDPTemplate, 0)
+5 -3
View File
@@ -81,7 +81,8 @@ var (
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id`
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
idpTemplateCols = []string{
"id",
"resource_owner",
@@ -212,7 +213,8 @@ var (
` LEFT JOIN projections.idp_templates2_oidc ON projections.idp_templates2.id = projections.idp_templates2_oidc.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_oidc.instance_id` +
` LEFT JOIN projections.idp_templates2_jwt ON projections.idp_templates2.id = projections.idp_templates2_jwt.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_jwt.instance_id` +
` LEFT JOIN projections.idp_templates2_google ON projections.idp_templates2.id = projections.idp_templates2_google.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_google.instance_id` +
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id`
` LEFT JOIN projections.idp_templates2_ldap ON projections.idp_templates2.id = projections.idp_templates2_ldap.idp_id AND projections.idp_templates2.instance_id = projections.idp_templates2_ldap.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
idpTemplatesCols = []string{
"id",
"resource_owner",
@@ -1628,7 +1630,7 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+1 -1
View File
@@ -733,7 +733,7 @@ func Test_IDPPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+5 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -92,7 +93,7 @@ func (q *Queries) IDPUserLinks(ctx context.Context, queries *IDPUserLinksSearchQ
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareIDPUserLinksQuery()
query, scan := prepareIDPUserLinksQuery(ctx, q.client)
eq := sq.Eq{IDPUserLinkInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[IDPUserLinkOwnerRemovedCol.identifier()] = false
@@ -126,7 +127,7 @@ func NewIDPUserLinksResourceOwnerSearchQuery(value string) (SearchQuery, error)
return NewTextQuery(IDPUserLinkResourceOwnerCol, value, TextEquals)
}
func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
func prepareIDPUserLinksQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLinks, error)) {
return sq.Select(
IDPUserLinkIDPIDCol.identifier(),
IDPUserLinkUserIDCol.identifier(),
@@ -137,7 +138,8 @@ func prepareIDPUserLinksQuery() (sq.SelectBuilder, func(*sql.Rows) (*IDPUserLink
IDPUserLinkResourceOwnerCol.identifier(),
countColumn.identifier()).
From(idpUserLinkTable.identifier()).
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol)).PlaceholderFormat(sq.Dollar),
LeftJoin(join(IDPIDCol, IDPUserLinkIDPIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*IDPUserLinks, error) {
idps := make([]*IDPUserLink, 0)
var count uint64
+3 -2
View File
@@ -21,7 +21,8 @@ var (
` projections.idp_user_links3.resource_owner,` +
` COUNT(*) OVER ()` +
` FROM projections.idp_user_links3` +
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id`)
` LEFT JOIN projections.idps3 ON projections.idp_user_links3.idp_id = projections.idps3.id AND projections.idp_user_links3.instance_id = projections.idps3.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
idpUserLinksCols = []string{
"idp_id",
"user_id",
@@ -139,7 +140,7 @@ func Test_IDPUserLinkPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+13 -11
View File
@@ -11,6 +11,7 @@ import (
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -159,7 +160,7 @@ func (q *Queries) SearchInstances(ctx context.Context, queries *InstanceSearchQu
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
filter, query, scan := prepareInstancesQuery()
filter, query, scan := prepareInstancesQuery(ctx, q.client)
stmt, args, err := query(queries.toQuery(filter)).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-M9fow", "Errors.Query.SQLStatement")
@@ -184,7 +185,7 @@ func (q *Queries) Instance(ctx context.Context, shouldTriggerBulk bool) (_ *Inst
projection.InstanceProjection.Trigger(ctx)
}
stmt, scan := prepareInstanceDomainQuery(authz.GetInstance(ctx).RequestedDomain())
stmt, scan := prepareInstanceDomainQuery(ctx, q.client, authz.GetInstance(ctx).RequestedDomain())
query, args, err := stmt.Where(sq.Eq{
InstanceColumnID.identifier(): authz.GetInstance(ctx).InstanceID(),
}).ToSql()
@@ -203,7 +204,7 @@ func (q *Queries) InstanceByHost(ctx context.Context, host string) (_ authz.Inst
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareAuthzInstanceQuery(host)
stmt, scan := prepareAuthzInstanceQuery(ctx, q.client, host)
host = strings.Split(host, ":")[0] //remove possible port
query, args, err := stmt.Where(sq.Eq{
InstanceDomainDomainCol.identifier(): host,
@@ -231,7 +232,7 @@ func (q *Queries) GetDefaultLanguage(ctx context.Context) language.Tag {
return instance.DefaultLanguage()
}
func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
func prepareInstanceQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
return sq.Select(
InstanceColumnID.identifier(),
InstanceColumnCreationDate.identifier(),
@@ -243,7 +244,8 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta
InstanceColumnConsoleAppID.identifier(),
InstanceColumnDefaultLanguage.identifier(),
).
From(instanceTable.identifier()).PlaceholderFormat(sq.Dollar),
From(instanceTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Instance, error) {
instance := &Instance{host: host}
lang := ""
@@ -269,7 +271,7 @@ func prepareInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Row) (*Insta
}
}
func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
func prepareInstancesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(sq.SelectBuilder) sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
instanceFilterTable := instanceTable.setAlias(InstancesFilterTableAlias)
instanceFilterIDColumn := InstanceColumnID.setTable(instanceFilterTable)
instanceFilterCountColumn := InstancesFilterTableAlias + ".count"
@@ -298,7 +300,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.Select
InstanceDomainSequenceCol.identifier(),
).FromSelect(builder, InstancesFilterTableAlias).
LeftJoin(join(InstanceColumnID, instanceFilterIDColumn)).
LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn)).
LeftJoin(join(InstanceDomainInstanceIDCol, instanceFilterIDColumn) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar)
},
func(rows *sql.Rows) (*Instances, error) {
@@ -373,7 +375,7 @@ func prepareInstancesQuery() (sq.SelectBuilder, func(sq.SelectBuilder) sq.Select
}
}
func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
func prepareInstanceDomainQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
return sq.Select(
InstanceColumnID.identifier(),
InstanceColumnCreationDate.identifier(),
@@ -393,7 +395,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows)
InstanceDomainSequenceCol.identifier(),
).
From(instanceTable.identifier()).
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)).
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Instance, error) {
instance := &Instance{
@@ -455,7 +457,7 @@ func prepareInstanceDomainQuery(host string) (sq.SelectBuilder, func(*sql.Rows)
}
}
func prepareAuthzInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
func prepareAuthzInstanceQuery(ctx context.Context, db prepareDatabase, host string) (sq.SelectBuilder, func(*sql.Rows) (*Instance, error)) {
return sq.Select(
InstanceColumnID.identifier(),
InstanceColumnCreationDate.identifier(),
@@ -478,7 +480,7 @@ func prepareAuthzInstanceQuery(host string) (sq.SelectBuilder, func(*sql.Rows) (
).
From(instanceTable.identifier()).
LeftJoin(join(InstanceDomainInstanceIDCol, InstanceColumnID)).
LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID)).
LeftJoin(join(SecurityPolicyColumnInstanceID, InstanceColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Instance, error) {
instance := &Instance{
+6 -4
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -61,7 +62,7 @@ func (q *Queries) SearchInstanceDomains(ctx context.Context, queries *InstanceDo
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareInstanceDomainsQuery()
query, scan := prepareInstanceDomainsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).
Where(sq.Eq{
InstanceDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -77,7 +78,7 @@ func (q *Queries) SearchInstanceDomainsGlobal(ctx context.Context, queries *Inst
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareInstanceDomainsQuery()
query, scan := prepareInstanceDomainsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-IHhLR", "Errors.Query.SQLStatement")
@@ -99,7 +100,7 @@ func (q *Queries) queryInstanceDomains(ctx context.Context, stmt string, scan fu
return domains, err
}
func prepareInstanceDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*InstanceDomains, error)) {
func prepareInstanceDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*InstanceDomains, error)) {
return sq.Select(
InstanceDomainCreationDateCol.identifier(),
InstanceDomainChangeDateCol.identifier(),
@@ -109,7 +110,8 @@ func prepareInstanceDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Instance
InstanceDomainIsGeneratedCol.identifier(),
InstanceDomainIsPrimaryCol.identifier(),
countColumn.identifier(),
).From(instanceDomainsTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(instanceDomainsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*InstanceDomains, error) {
domains := make([]*InstanceDomain, 0)
var count uint64
+30 -57
View File
@@ -9,6 +9,29 @@ import (
"testing"
)
var (
prepareInstanceDomainsStmt = `SELECT projections.instance_domains.creation_date,` +
` projections.instance_domains.change_date,` +
` projections.instance_domains.sequence,` +
` projections.instance_domains.domain,` +
` projections.instance_domains.instance_id,` +
` projections.instance_domains.is_generated,` +
` projections.instance_domains.is_primary,` +
` COUNT(*) OVER ()` +
` FROM projections.instance_domains` +
` AS OF SYSTEM TIME '-1 ms'`
prepareInstanceDomainsCols = []string{
"creation_date",
"change_date",
"sequence",
"domain",
"instance_id",
"is_generated",
"is_primary",
"count",
}
)
func Test_InstanceDomainPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -25,15 +48,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
prepare: prepareInstanceDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
` projections.instance_domains.change_date,`+
` projections.instance_domains.sequence,`+
` projections.instance_domains.domain,`+
` projections.instance_domains.instance_id,`+
` projections.instance_domains.is_generated,`+
` projections.instance_domains.is_primary,`+
` COUNT(*) OVER ()`+
` FROM projections.instance_domains`),
regexp.QuoteMeta(prepareInstanceDomainsStmt),
nil,
nil,
),
@@ -45,25 +60,8 @@ func Test_InstanceDomainPrepares(t *testing.T) {
prepare: prepareInstanceDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
` projections.instance_domains.change_date,`+
` projections.instance_domains.sequence,`+
` projections.instance_domains.domain,`+
` projections.instance_domains.instance_id,`+
` projections.instance_domains.is_generated,`+
` projections.instance_domains.is_primary,`+
` COUNT(*) OVER ()`+
` FROM projections.instance_domains`),
[]string{
"creation_date",
"change_date",
"sequence",
"domain",
"instance_id",
"is_generated",
"is_primary",
"count",
},
regexp.QuoteMeta(prepareInstanceDomainsStmt),
prepareInstanceDomainsCols,
[][]driver.Value{
{
testNow,
@@ -99,25 +97,8 @@ func Test_InstanceDomainPrepares(t *testing.T) {
prepare: prepareInstanceDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
` projections.instance_domains.change_date,`+
` projections.instance_domains.sequence,`+
` projections.instance_domains.domain,`+
` projections.instance_domains.instance_id,`+
` projections.instance_domains.is_generated,`+
` projections.instance_domains.is_primary,`+
` COUNT(*) OVER ()`+
` FROM projections.instance_domains`),
[]string{
"creation_date",
"change_date",
"sequence",
"domain",
"instance_id",
"is_generated",
"is_primary",
"count",
},
regexp.QuoteMeta(prepareInstanceDomainsStmt),
prepareInstanceDomainsCols,
[][]driver.Value{
{
testNow,
@@ -171,15 +152,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
prepare: prepareInstanceDomainsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.instance_domains.creation_date,`+
` projections.instance_domains.change_date,`+
` projections.instance_domains.sequence,`+
` projections.instance_domains.domain,`+
` projections.instance_domains.instance_id,`+
` projections.instance_domains.is_generated,`+
` projections.instance_domains.is_primary,`+
` COUNT(*) OVER ()`+
` FROM projections.instance_domains`),
regexp.QuoteMeta(prepareInstanceDomainsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -194,7 +167,7 @@ func Test_InstanceDomainPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+29 -27
View File
@@ -1,10 +1,12 @@
package query
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"regexp"
"testing"
@@ -24,7 +26,8 @@ var (
` projections.instances.console_client_id,` +
` projections.instances.console_app_id,` +
` projections.instances.default_language` +
` FROM projections.instances`
` FROM projections.instances` +
` AS OF SYSTEM TIME '-1 ms'`
instanceCols = []string{
"id",
"creation_date",
@@ -54,7 +57,8 @@ var (
` projections.instance_domains.sequence` +
` FROM (SELECT projections.instances.id, COUNT(*) OVER () FROM projections.instances) AS f` +
` LEFT JOIN projections.instances ON f.id = projections.instances.id` +
` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id`
` LEFT JOIN projections.instance_domains ON f.id = projections.instance_domains.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
instancesCols = []string{
"count",
"id",
@@ -82,16 +86,16 @@ func Test_InstancePrepares(t *testing.T) {
err checkErr
}
tests := []struct {
name string
prepare interface{}
want want
object interface{}
name string
prepare interface{}
additionalArgs []reflect.Value
want want
object interface{}
}{
{
name: "prepareInstanceQuery no result",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
return prepareInstanceQuery("")
},
name: "prepareInstanceQuery no result",
additionalArgs: []reflect.Value{reflect.ValueOf("")},
prepare: prepareInstanceQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(instanceQuery),
@@ -108,10 +112,9 @@ func Test_InstancePrepares(t *testing.T) {
object: (*Instance)(nil),
},
{
name: "prepareInstanceQuery found",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
return prepareInstanceQuery("")
},
name: "prepareInstanceQuery found",
additionalArgs: []reflect.Value{reflect.ValueOf("")},
prepare: prepareInstanceQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(instanceQuery),
@@ -142,10 +145,9 @@ func Test_InstancePrepares(t *testing.T) {
},
},
{
name: "prepareInstanceQuery sql err",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*Instance, error)) {
return prepareInstanceQuery("")
},
name: "prepareInstanceQuery sql err",
additionalArgs: []reflect.Value{reflect.ValueOf("")},
prepare: prepareInstanceQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(instanceQuery),
@@ -162,8 +164,8 @@ func Test_InstancePrepares(t *testing.T) {
},
{
name: "prepareInstancesQuery no result",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery()
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery(ctx, db)
return query(filter), scan
},
want: want{
@@ -177,8 +179,8 @@ func Test_InstancePrepares(t *testing.T) {
},
{
name: "prepareInstancesQuery one result",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery()
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery(ctx, db)
return query(filter), scan
},
want: want{
@@ -241,8 +243,8 @@ func Test_InstancePrepares(t *testing.T) {
},
{
name: "prepareInstancesQuery multiple results",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery()
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery(ctx, db)
return query(filter), scan
},
want: want{
@@ -374,8 +376,8 @@ func Test_InstancePrepares(t *testing.T) {
},
{
name: "prepareInstancesQuery sql err",
prepare: func() (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery()
prepare: func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Instances, error)) {
filter, query, scan := prepareInstancesQuery(ctx, db)
return query(filter), scan
},
want: want{
@@ -395,7 +397,7 @@ func Test_InstancePrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, append(defaultPrepareArgs, tt.additionalArgs...)...)
})
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -180,7 +181,7 @@ func (q *Queries) ActivePublicKeys(ctx context.Context, t time.Time) (_ *PublicK
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := preparePublicKeysQuery()
query, scan := preparePublicKeysQuery(ctx, q.client)
if t.IsZero() {
t = time.Now()
}
@@ -212,7 +213,7 @@ func (q *Queries) ActivePrivateSigningKey(ctx context.Context, t time.Time) (_ *
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := preparePrivateKeysQuery()
stmt, scan := preparePrivateKeysQuery(ctx, q.client)
if t.IsZero() {
t = time.Now()
}
@@ -243,7 +244,7 @@ func (q *Queries) ActivePrivateSigningKey(ctx context.Context, t time.Time) (_ *
return keys, nil
}
func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, error)) {
func preparePublicKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, error)) {
return sq.Select(
KeyColID.identifier(),
KeyColCreationDate.identifier(),
@@ -256,7 +257,7 @@ func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, e
KeyPublicColKey.identifier(),
countColumn.identifier(),
).From(keyTable.identifier()).
LeftJoin(join(KeyPublicColID, KeyColID)).
LeftJoin(join(KeyPublicColID, KeyColID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*PublicKeys, error) {
keys := make([]PublicKey, 0)
@@ -299,7 +300,7 @@ func preparePublicKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PublicKeys, e
}
}
func preparePrivateKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys, error)) {
func preparePrivateKeysQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys, error)) {
return sq.Select(
KeyColID.identifier(),
KeyColCreationDate.identifier(),
@@ -312,7 +313,7 @@ func preparePrivateKeysQuery() (sq.SelectBuilder, func(*sql.Rows) (*PrivateKeys,
KeyPrivateColKey.identifier(),
countColumn.identifier(),
).From(keyTable.identifier()).
LeftJoin(join(KeyPrivateColID, KeyColID)).
LeftJoin(join(KeyPrivateColID, KeyColID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*PrivateKeys, error) {
keys := make([]PrivateKey, 0)
+51 -97
View File
@@ -15,6 +15,48 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
preparePublicKeysStmt = `SELECT projections.keys4.id,` +
` projections.keys4.creation_date,` +
` projections.keys4.change_date,` +
` projections.keys4.sequence,` +
` projections.keys4.resource_owner,` +
` projections.keys4.algorithm,` +
` projections.keys4.use,` +
` projections.keys4_public.expiry,` +
` projections.keys4_public.key,` +
` COUNT(*) OVER ()` +
` FROM projections.keys4` +
` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id AND projections.keys4.instance_id = projections.keys4_public.instance_id` +
` AS OF SYSTEM TIME '-1 ms' `
preparePublicKeysCols = []string{
"id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"algorithm",
"use",
"expiry",
"key",
"count",
}
preparePrivateKeysStmt = `SELECT projections.keys4.id,` +
` projections.keys4.creation_date,` +
` projections.keys4.change_date,` +
` projections.keys4.sequence,` +
` projections.keys4.resource_owner,` +
` projections.keys4.algorithm,` +
` projections.keys4.use,` +
` projections.keys4_private.expiry,` +
` projections.keys4_private.key,` +
` COUNT(*) OVER ()` +
` FROM projections.keys4` +
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id AND projections.keys4.instance_id = projections.keys4_private.instance_id` +
` AS OF SYSTEM TIME '-1 ms' `
)
func Test_KeyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -31,18 +73,7 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePublicKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_public.expiry,`+
` projections.keys4_public.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`),
regexp.QuoteMeta(preparePublicKeysStmt),
nil,
nil,
),
@@ -60,30 +91,8 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePublicKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_public.expiry,`+
` projections.keys4_public.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`),
[]string{
"id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"algorithm",
"use",
"expiry",
"key",
"count",
},
regexp.QuoteMeta(preparePublicKeysStmt),
preparePublicKeysCols,
[][]driver.Value{
{
"key-id",
@@ -128,18 +137,7 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePublicKeysQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_public.expiry,`+
` projections.keys4_public.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_public ON projections.keys4.id = projections.keys4_public.id`),
regexp.QuoteMeta(preparePublicKeysStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -156,18 +154,7 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePrivateKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_private.expiry,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`),
regexp.QuoteMeta(preparePrivateKeysStmt),
nil,
nil,
),
@@ -185,30 +172,8 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePrivateKeysQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_private.expiry,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`),
[]string{
"id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"algorithm",
"use",
"expiry",
"key",
"count",
},
regexp.QuoteMeta(preparePrivateKeysStmt),
preparePublicKeysCols,
[][]driver.Value{
{
"key-id",
@@ -255,18 +220,7 @@ func Test_KeyPrepares(t *testing.T) {
prepare: preparePrivateKeysQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.keys4.id,`+
` projections.keys4.creation_date,`+
` projections.keys4.change_date,`+
` projections.keys4.sequence,`+
` projections.keys4.resource_owner,`+
` projections.keys4.algorithm,`+
` projections.keys4.use,`+
` projections.keys4_private.expiry,`+
` projections.keys4_private.key,`+
` COUNT(*) OVER ()`+
` FROM projections.keys4`+
` LEFT JOIN projections.keys4_private ON projections.keys4.id = projections.keys4_private.id`),
regexp.QuoteMeta(preparePrivateKeysStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -281,7 +235,7 @@ func Test_KeyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+8 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -45,7 +46,7 @@ func (q *Queries) ActiveLabelPolicyByOrg(ctx context.Context, orgID string, with
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareLabelPolicyQuery()
stmt, scan := prepareLabelPolicyQuery(ctx, q.client)
eq := sq.Eq{
LabelPolicyColState.identifier(): domain.LabelPolicyStateActive,
LabelPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -75,7 +76,7 @@ func (q *Queries) PreviewLabelPolicyByOrg(ctx context.Context, orgID string) (_
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareLabelPolicyQuery()
stmt, scan := prepareLabelPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
sq.Or{
@@ -105,7 +106,7 @@ func (q *Queries) DefaultActiveLabelPolicy(ctx context.Context) (_ *LabelPolicy,
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareLabelPolicyQuery()
stmt, scan := prepareLabelPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
LabelPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
LabelPolicyColState.identifier(): domain.LabelPolicyStateActive,
@@ -125,7 +126,7 @@ func (q *Queries) DefaultPreviewLabelPolicy(ctx context.Context) (_ *LabelPolicy
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareLabelPolicyQuery()
stmt, scan := prepareLabelPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
LabelPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
LabelPolicyColState.identifier(): domain.LabelPolicyStatePreview,
@@ -223,7 +224,7 @@ var (
}
)
func prepareLabelPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, error)) {
func prepareLabelPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy, error)) {
return sq.Select(
LabelPolicyColCreationDate.identifier(),
LabelPolicyColChangeDate.identifier(),
@@ -252,7 +253,8 @@ func prepareLabelPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LabelPolicy,
LabelPolicyColDarkLogoURL.identifier(),
LabelPolicyColDarkIconURL.identifier(),
).
From(labelPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
From(labelPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*LabelPolicy, error) {
policy := new(LabelPolicy)
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -94,7 +95,7 @@ func (q *Queries) LockoutPolicyByOrg(ctx context.Context, shouldTriggerBulk bool
eq[LockoutPolicyOwnerRemoved.identifier()] = false
}
stmt, scan := prepareLockoutPolicyQuery()
stmt, scan := prepareLockoutPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
eq,
@@ -117,7 +118,7 @@ func (q *Queries) DefaultLockoutPolicy(ctx context.Context) (_ *LockoutPolicy, e
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareLockoutPolicyQuery()
stmt, scan := prepareLockoutPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
LockoutColID.identifier(): authz.GetInstance(ctx).InstanceID(),
LockoutColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -132,7 +133,7 @@ func (q *Queries) DefaultLockoutPolicy(ctx context.Context) (_ *LockoutPolicy, e
return scan(row)
}
func prepareLockoutPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LockoutPolicy, error)) {
func prepareLockoutPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*LockoutPolicy, error)) {
return sq.Select(
LockoutColID.identifier(),
LockoutColSequence.identifier(),
@@ -144,7 +145,8 @@ func prepareLockoutPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*LockoutPoli
LockoutColIsDefault.identifier(),
LockoutColState.identifier(),
).
From(lockoutTable.identifier()).PlaceholderFormat(sq.Dollar),
From(lockoutTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*LockoutPolicy, error) {
policy := new(LockoutPolicy)
err := row.Scan(
+31 -42
View File
@@ -12,6 +12,32 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareLockoutPolicyStmt = `SELECT projections.lockout_policies2.id,` +
` projections.lockout_policies2.sequence,` +
` projections.lockout_policies2.creation_date,` +
` projections.lockout_policies2.change_date,` +
` projections.lockout_policies2.resource_owner,` +
` projections.lockout_policies2.show_failure,` +
` projections.lockout_policies2.max_password_attempts,` +
` projections.lockout_policies2.is_default,` +
` projections.lockout_policies2.state` +
` FROM projections.lockout_policies2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareLockoutPolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"show_failure",
"max_password_attempts",
"is_default",
"state",
}
)
func Test_LockoutPolicyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,16 +54,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) {
prepare: prepareLockoutPolicyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+
` projections.lockout_policies2.sequence,`+
` projections.lockout_policies2.creation_date,`+
` projections.lockout_policies2.change_date,`+
` projections.lockout_policies2.resource_owner,`+
` projections.lockout_policies2.show_failure,`+
` projections.lockout_policies2.max_password_attempts,`+
` projections.lockout_policies2.is_default,`+
` projections.lockout_policies2.state`+
` FROM projections.lockout_policies2`),
regexp.QuoteMeta(prepareLockoutPolicyStmt),
nil,
nil,
),
@@ -55,27 +72,8 @@ func Test_LockoutPolicyPrepares(t *testing.T) {
prepare: prepareLockoutPolicyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+
` projections.lockout_policies2.sequence,`+
` projections.lockout_policies2.creation_date,`+
` projections.lockout_policies2.change_date,`+
` projections.lockout_policies2.resource_owner,`+
` projections.lockout_policies2.show_failure,`+
` projections.lockout_policies2.max_password_attempts,`+
` projections.lockout_policies2.is_default,`+
` projections.lockout_policies2.state`+
` FROM projections.lockout_policies2`),
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"show_failure",
"max_password_attempts",
"is_default",
"state",
},
regexp.QuoteMeta(prepareLockoutPolicyStmt),
prepareLockoutPolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -106,16 +104,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) {
prepare: prepareLockoutPolicyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.lockout_policies2.id,`+
` projections.lockout_policies2.sequence,`+
` projections.lockout_policies2.creation_date,`+
` projections.lockout_policies2.change_date,`+
` projections.lockout_policies2.resource_owner,`+
` projections.lockout_policies2.show_failure,`+
` projections.lockout_policies2.max_password_attempts,`+
` projections.lockout_policies2.is_default,`+
` projections.lockout_policies2.state`+
` FROM projections.lockout_policies2`),
regexp.QuoteMeta(prepareLockoutPolicyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -130,7 +119,7 @@ func Test_LockoutPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+15 -12
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -172,7 +173,7 @@ func (q *Queries) LoginPolicyByID(ctx context.Context, shouldTriggerBulk bool, o
eq[LoginPolicyColumnOwnerRemoved.identifier()] = false
}
query, scan := prepareLoginPolicyQuery()
query, scan := prepareLoginPolicyQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.And{
eq,
@@ -212,7 +213,7 @@ func (q *Queries) DefaultLoginPolicy(ctx context.Context) (_ *LoginPolicy, err e
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLoginPolicyQuery()
query, scan := prepareLoginPolicyQuery(ctx, q.client)
stmt, args, err := query.Where(sq.Eq{
LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(),
LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -232,7 +233,7 @@ func (q *Queries) SecondFactorsByOrg(ctx context.Context, orgID string) (_ *Seco
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLoginPolicy2FAsQuery()
query, scan := prepareLoginPolicy2FAsQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.And{
sq.Eq{
@@ -266,7 +267,7 @@ func (q *Queries) DefaultSecondFactors(ctx context.Context) (_ *SecondFactors, e
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLoginPolicy2FAsQuery()
query, scan := prepareLoginPolicy2FAsQuery(ctx, q.client)
stmt, args, err := query.Where(sq.Eq{
LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(),
LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -288,7 +289,7 @@ func (q *Queries) MultiFactorsByOrg(ctx context.Context, orgID string) (_ *Multi
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLoginPolicyMFAsQuery()
query, scan := prepareLoginPolicyMFAsQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.And{
sq.Eq{
@@ -322,7 +323,7 @@ func (q *Queries) DefaultMultiFactors(ctx context.Context) (_ *MultiFactors, err
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareLoginPolicyMFAsQuery()
query, scan := prepareLoginPolicyMFAsQuery(ctx, q.client)
stmt, args, err := query.Where(sq.Eq{
LoginPolicyColumnOrgID.identifier(): authz.GetInstance(ctx).InstanceID(),
LoginPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -340,7 +341,7 @@ func (q *Queries) DefaultMultiFactors(ctx context.Context) (_ *MultiFactors, err
return factors, err
}
func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, error)) {
func prepareLoginPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy, error)) {
return sq.Select(
LoginPolicyColumnOrgID.identifier(),
LoginPolicyColumnCreationDate.identifier(),
@@ -365,7 +366,7 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
LoginPolicyColumnMFAInitSkipLifetime.identifier(),
LoginPolicyColumnSecondFactorCheckLifetime.identifier(),
LoginPolicyColumnMultiFactorCheckLifetime.identifier(),
).From(loginPolicyTable.identifier()).
).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*LoginPolicy, error) {
p := new(LoginPolicy)
@@ -408,10 +409,11 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
}
}
func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFactors, error)) {
func prepareLoginPolicy2FAsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecondFactors, error)) {
return sq.Select(
LoginPolicyColumnSecondFactors.identifier(),
).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*SecondFactors, error) {
p := new(SecondFactors)
err := row.Scan(
@@ -429,10 +431,11 @@ func prepareLoginPolicy2FAsQuery() (sq.SelectBuilder, func(*sql.Row) (*SecondFac
}
}
func prepareLoginPolicyMFAsQuery() (sq.SelectBuilder, func(*sql.Row) (*MultiFactors, error)) {
func prepareLoginPolicyMFAsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MultiFactors, error)) {
return sq.Select(
LoginPolicyColumnMultiFactors.identifier(),
).From(loginPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(loginPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*MultiFactors, error) {
p := new(MultiFactors)
err := row.Scan(
+31 -36
View File
@@ -38,7 +38,8 @@ var (
` projections.login_policies4.mfa_init_skip_lifetime,` +
` projections.login_policies4.second_factor_check_lifetime,` +
` projections.login_policies4.multi_factor_check_lifetime` +
` FROM projections.login_policies4`
` FROM projections.login_policies4` +
` AS OF SYSTEM TIME '-1 ms'`
loginPolicyCols = []string{
"aggregate_id",
"creation_date",
@@ -64,6 +65,20 @@ var (
"second_factor_check_lifetime",
"multi_factor_check_lifetime",
}
prepareLoginPolicy2FAsStmt = `SELECT projections.login_policies4.second_factors` +
` FROM projections.login_policies4` +
` AS OF SYSTEM TIME '-1 ms'`
prepareLoginPolicy2FAsCols = []string{
"second_factors",
}
prepareLoginPolicyMFAsStmt = `SELECT projections.login_policies4.multi_factors` +
` FROM projections.login_policies4` +
` AS OF SYSTEM TIME '-1 ms'`
prepareLoginPolicyMFAsCols = []string{
"multi_factors",
}
)
func Test_LoginPolicyPrepares(t *testing.T) {
@@ -177,11 +192,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicy2FAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+
` FROM projections.login_policies4`),
[]string{
"second_factors",
},
regexp.QuoteMeta(prepareLoginPolicy2FAsStmt),
prepareLoginPolicy2FAsCols,
nil,
),
err: func(err error) (error, bool) {
@@ -198,11 +210,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicy2FAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+
` FROM projections.login_policies4`),
[]string{
"second_factors",
},
regexp.QuoteMeta(prepareLoginPolicy2FAsStmt),
prepareLoginPolicy2FAsCols,
[]driver.Value{
database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP},
},
@@ -220,11 +229,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicy2FAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+
` FROM projections.login_policies4`),
[]string{
"second_factors",
},
regexp.QuoteMeta(prepareLoginPolicy2FAsStmt),
prepareLoginPolicy2FAsCols,
[]driver.Value{
database.EnumArray[domain.SecondFactorType]{},
},
@@ -237,8 +243,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicy2FAsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.login_policies4.second_factors`+
` FROM projections.login_policies4`),
regexp.QuoteMeta(prepareLoginPolicy2FAsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -255,11 +260,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicyMFAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+
` FROM projections.login_policies4`),
[]string{
"multi_factors",
},
regexp.QuoteMeta(prepareLoginPolicyMFAsStmt),
prepareLoginPolicyMFAsCols,
nil,
),
err: func(err error) (error, bool) {
@@ -276,11 +278,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicyMFAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+
` FROM projections.login_policies4`),
[]string{
"multi_factors",
},
regexp.QuoteMeta(prepareLoginPolicyMFAsStmt),
prepareLoginPolicyMFAsCols,
[]driver.Value{
database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN},
},
@@ -298,11 +297,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicyMFAsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+
` FROM projections.login_policies4`),
[]string{
"multi_factors",
},
regexp.QuoteMeta(prepareLoginPolicyMFAsStmt),
prepareLoginPolicyMFAsCols,
[]driver.Value{
database.EnumArray[domain.MultiFactorType]{},
},
@@ -315,8 +311,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
prepare: prepareLoginPolicyMFAsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.login_policies4.multi_factors`+
` FROM projections.login_policies4`),
regexp.QuoteMeta(prepareLoginPolicyMFAsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -331,7 +326,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -73,7 +74,7 @@ func (q *Queries) MailTemplateByOrg(ctx context.Context, orgID string, withOwner
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareMailTemplateQuery()
stmt, scan := prepareMailTemplateQuery(ctx, q.client)
eq := sq.Eq{MailTemplateColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[MailTemplateColOwnerRemoved.identifier()] = false
@@ -100,7 +101,7 @@ func (q *Queries) DefaultMailTemplate(ctx context.Context) (_ *MailTemplate, err
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareMailTemplateQuery()
stmt, scan := prepareMailTemplateQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
MailTemplateColAggregateID.identifier(): authz.GetInstance(ctx).InstanceID(),
MailTemplateColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -115,7 +116,7 @@ func (q *Queries) DefaultMailTemplate(ctx context.Context) (_ *MailTemplate, err
return scan(row)
}
func prepareMailTemplateQuery() (sq.SelectBuilder, func(*sql.Row) (*MailTemplate, error)) {
func prepareMailTemplateQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MailTemplate, error)) {
return sq.Select(
MailTemplateColAggregateID.identifier(),
MailTemplateColSequence.identifier(),
@@ -125,7 +126,8 @@ func prepareMailTemplateQuery() (sq.SelectBuilder, func(*sql.Row) (*MailTemplate
MailTemplateColIsDefault.identifier(),
MailTemplateColState.identifier(),
).
From(mailTemplateTable.identifier()).PlaceholderFormat(sq.Dollar),
From(mailTemplateTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*MailTemplate, error) {
policy := new(MailTemplate)
err := row.Scan(
+6 -4
View File
@@ -16,6 +16,7 @@ import (
"sigs.k8s.io/yaml"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -127,7 +128,7 @@ func (q *Queries) DefaultMessageText(ctx context.Context) (_ *MessageText, err e
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareMessageTextQuery()
stmt, scan := prepareMessageTextQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
MessageTextColAggregateID.identifier(): authz.GetInstance(ctx).InstanceID(),
MessageTextColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -160,7 +161,7 @@ func (q *Queries) CustomMessageTextByTypeAndLanguage(ctx context.Context, aggreg
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareMessageTextQuery()
stmt, scan := prepareMessageTextQuery(ctx, q.client)
eq := sq.Eq{
MessageTextColLanguage.identifier(): language,
MessageTextColType.identifier(): messageType,
@@ -240,7 +241,7 @@ func (q *Queries) readNotificationTextMessages(ctx context.Context, language str
return contents, nil
}
func prepareMessageTextQuery() (sq.SelectBuilder, func(*sql.Row) (*MessageText, error)) {
func prepareMessageTextQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*MessageText, error)) {
return sq.Select(
MessageTextColAggregateID.identifier(),
MessageTextColSequence.identifier(),
@@ -257,7 +258,8 @@ func prepareMessageTextQuery() (sq.SelectBuilder, func(*sql.Row) (*MessageText,
MessageTextColButtonText.identifier(),
MessageTextColFooter.identifier(),
).
From(messageTextTable.identifier()).PlaceholderFormat(sq.Dollar),
From(messageTextTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*MessageText, error) {
msg := new(MessageText)
lang := ""
+40 -62
View File
@@ -14,6 +14,41 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareMessageTextStmt = `SELECT projections.message_texts2.aggregate_id,` +
` projections.message_texts2.sequence,` +
` projections.message_texts2.creation_date,` +
` projections.message_texts2.change_date,` +
` projections.message_texts2.state,` +
` projections.message_texts2.type,` +
` projections.message_texts2.language,` +
` projections.message_texts2.title,` +
` projections.message_texts2.pre_header,` +
` projections.message_texts2.subject,` +
` projections.message_texts2.greeting,` +
` projections.message_texts2.text,` +
` projections.message_texts2.button_text,` +
` projections.message_texts2.footer_text` +
` FROM projections.message_texts2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareMessgeTextCols = []string{
"aggregate_id",
"sequence",
"creation_date",
"change_date",
"state",
"type",
"language",
"title",
"pre_header",
"subject",
"greeting",
"text",
"button_text",
"footer_text",
}
)
func Test_MessageTextPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -30,21 +65,7 @@ func Test_MessageTextPrepares(t *testing.T) {
prepare: prepareMessageTextQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+
` projections.message_texts2.sequence,`+
` projections.message_texts2.creation_date,`+
` projections.message_texts2.change_date,`+
` projections.message_texts2.state,`+
` projections.message_texts2.type,`+
` projections.message_texts2.language,`+
` projections.message_texts2.title,`+
` projections.message_texts2.pre_header,`+
` projections.message_texts2.subject,`+
` projections.message_texts2.greeting,`+
` projections.message_texts2.text,`+
` projections.message_texts2.button_text,`+
` projections.message_texts2.footer_text`+
` FROM projections.message_texts2`),
regexp.QuoteMeta(prepareMessageTextStmt),
nil,
nil,
),
@@ -62,37 +83,8 @@ func Test_MessageTextPrepares(t *testing.T) {
prepare: prepareMessageTextQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+
` projections.message_texts2.sequence,`+
` projections.message_texts2.creation_date,`+
` projections.message_texts2.change_date,`+
` projections.message_texts2.state,`+
` projections.message_texts2.type,`+
` projections.message_texts2.language,`+
` projections.message_texts2.title,`+
` projections.message_texts2.pre_header,`+
` projections.message_texts2.subject,`+
` projections.message_texts2.greeting,`+
` projections.message_texts2.text,`+
` projections.message_texts2.button_text,`+
` projections.message_texts2.footer_text`+
` FROM projections.message_texts2`),
[]string{
"aggregate_id",
"sequence",
"creation_date",
"change_date",
"state",
"type",
"language",
"title",
"pre_header",
"subject",
"greeting",
"text",
"button_text",
"footer_text",
},
regexp.QuoteMeta(prepareMessageTextStmt),
prepareMessgeTextCols,
[]driver.Value{
"agg-id",
uint64(20211109),
@@ -133,21 +125,7 @@ func Test_MessageTextPrepares(t *testing.T) {
prepare: prepareMessageTextQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.message_texts2.aggregate_id,`+
` projections.message_texts2.sequence,`+
` projections.message_texts2.creation_date,`+
` projections.message_texts2.change_date,`+
` projections.message_texts2.state,`+
` projections.message_texts2.type,`+
` projections.message_texts2.language,`+
` projections.message_texts2.title,`+
` projections.message_texts2.pre_header,`+
` projections.message_texts2.subject,`+
` projections.message_texts2.greeting,`+
` projections.message_texts2.text,`+
` projections.message_texts2.button_text,`+
` projections.message_texts2.footer_text`+
` FROM projections.message_texts2`),
regexp.QuoteMeta(prepareMessageTextStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -162,7 +140,7 @@ func Test_MessageTextPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -88,7 +89,7 @@ func (q *Queries) NotificationPolicyByOrg(ctx context.Context, shouldTriggerBulk
if !withOwnerRemoved {
eq[NotificationPolicyColOwnerRemoved.identifier()] = false
}
stmt, scan := prepareNotificationPolicyQuery()
stmt, scan := prepareNotificationPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
eq,
@@ -116,7 +117,7 @@ func (q *Queries) DefaultNotificationPolicy(ctx context.Context, shouldTriggerBu
}
}
stmt, scan := prepareNotificationPolicyQuery()
stmt, scan := prepareNotificationPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
NotificationPolicyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
NotificationPolicyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -131,7 +132,7 @@ func (q *Queries) DefaultNotificationPolicy(ctx context.Context, shouldTriggerBu
return scan(row)
}
func prepareNotificationPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*NotificationPolicy, error)) {
func prepareNotificationPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*NotificationPolicy, error)) {
return sq.Select(
NotificationPolicyColID.identifier(),
NotificationPolicyColSequence.identifier(),
@@ -142,7 +143,8 @@ func prepareNotificationPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*Notifi
NotificationPolicyColIsDefault.identifier(),
NotificationPolicyColState.identifier(),
).
From(notificationPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
From(notificationPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*NotificationPolicy, error) {
policy := new(NotificationPolicy)
err := row.Scan(
+24 -20
View File
@@ -12,15 +12,28 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var notificationPolicyStmt = regexp.QuoteMeta(`SELECT projections.notification_policies.id,` +
` projections.notification_policies.sequence,` +
` projections.notification_policies.creation_date,` +
` projections.notification_policies.change_date,` +
` projections.notification_policies.resource_owner,` +
` projections.notification_policies.password_change,` +
` projections.notification_policies.is_default,` +
` projections.notification_policies.state` +
` FROM projections.notification_policies`)
var (
notificationPolicyStmt = regexp.QuoteMeta(`SELECT projections.notification_policies.id,` +
` projections.notification_policies.sequence,` +
` projections.notification_policies.creation_date,` +
` projections.notification_policies.change_date,` +
` projections.notification_policies.resource_owner,` +
` projections.notification_policies.password_change,` +
` projections.notification_policies.is_default,` +
` projections.notification_policies.state` +
` FROM projections.notification_policies` +
` AS OF SYSTEM TIME '-1 ms'`)
notificationPolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"password_change",
"is_default",
"state",
}
)
func Test_NotificationPolicyPrepares(t *testing.T) {
type want struct {
@@ -57,16 +70,7 @@ func Test_NotificationPolicyPrepares(t *testing.T) {
want: want{
sqlExpectations: mockQuery(
notificationPolicyStmt,
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"password_change",
"is_default",
"state",
},
notificationPolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -110,7 +114,7 @@ func Test_NotificationPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+5 -3
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -73,7 +74,7 @@ func (q *Queries) NotificationProviderByIDAndType(ctx context.Context, aggID str
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareDebugNotificationProviderQuery()
query, scan := prepareDebugNotificationProviderQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.And{
sq.Eq{NotificationProviderColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()},
@@ -93,7 +94,7 @@ func (q *Queries) NotificationProviderByIDAndType(ctx context.Context, aggID str
return scan(row)
}
func prepareDebugNotificationProviderQuery() (sq.SelectBuilder, func(*sql.Row) (*DebugNotificationProvider, error)) {
func prepareDebugNotificationProviderQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*DebugNotificationProvider, error)) {
return sq.Select(
NotificationProviderColumnAggID.identifier(),
NotificationProviderColumnCreationDate.identifier(),
@@ -103,7 +104,8 @@ func prepareDebugNotificationProviderQuery() (sq.SelectBuilder, func(*sql.Row) (
NotificationProviderColumnState.identifier(),
NotificationProviderColumnType.identifier(),
NotificationProviderColumnCompact.identifier(),
).From(notificationProviderTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(notificationProviderTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*DebugNotificationProvider, error) {
p := new(DebugNotificationProvider)
err := row.Scan(
+28 -38
View File
@@ -12,6 +12,29 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareNotificationProviderStmt = `SELECT projections.notification_providers.aggregate_id,` +
` projections.notification_providers.creation_date,` +
` projections.notification_providers.change_date,` +
` projections.notification_providers.sequence,` +
` projections.notification_providers.resource_owner,` +
` projections.notification_providers.state,` +
` projections.notification_providers.provider_type,` +
` projections.notification_providers.compact` +
` FROM projections.notification_providers` +
` AS OF SYSTEM TIME '-1 ms'`
prepareNotificationProviderCols = []string{
"aggregate_id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"state",
"provider_type",
"compact",
}
)
func Test_NotificationProviderPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,15 +51,7 @@ func Test_NotificationProviderPrepares(t *testing.T) {
prepare: prepareDebugNotificationProviderQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+
` projections.notification_providers.creation_date,`+
` projections.notification_providers.change_date,`+
` projections.notification_providers.sequence,`+
` projections.notification_providers.resource_owner,`+
` projections.notification_providers.state,`+
` projections.notification_providers.provider_type,`+
` projections.notification_providers.compact`+
` FROM projections.notification_providers`),
regexp.QuoteMeta(prepareNotificationProviderStmt),
nil,
nil,
),
@@ -54,25 +69,8 @@ func Test_NotificationProviderPrepares(t *testing.T) {
prepare: prepareDebugNotificationProviderQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+
` projections.notification_providers.creation_date,`+
` projections.notification_providers.change_date,`+
` projections.notification_providers.sequence,`+
` projections.notification_providers.resource_owner,`+
` projections.notification_providers.state,`+
` projections.notification_providers.provider_type,`+
` projections.notification_providers.compact`+
` FROM projections.notification_providers`),
[]string{
"aggregate_id",
"creation_date",
"change_date",
"sequence",
"resource_owner",
"state",
"provider_type",
"compact",
},
regexp.QuoteMeta(prepareNotificationProviderStmt),
prepareNotificationProviderCols,
[]driver.Value{
"agg-id",
testNow,
@@ -101,15 +99,7 @@ func Test_NotificationProviderPrepares(t *testing.T) {
prepare: prepareDebugNotificationProviderQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.notification_providers.aggregate_id,`+
` projections.notification_providers.creation_date,`+
` projections.notification_providers.change_date,`+
` projections.notification_providers.sequence,`+
` projections.notification_providers.resource_owner,`+
` projections.notification_providers.state,`+
` projections.notification_providers.provider_type,`+
` projections.notification_providers.compact`+
` FROM projections.notification_providers`),
regexp.QuoteMeta(prepareNotificationProviderStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -124,7 +114,7 @@ func Test_NotificationProviderPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+5 -3
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -78,7 +79,7 @@ func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) (
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareOIDCSettingsQuery()
stmt, scan := prepareOIDCSettingsQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
OIDCSettingsColumnAggregateID.identifier(): aggregateID,
OIDCSettingsColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -91,7 +92,7 @@ func (q *Queries) OIDCSettingsByAggID(ctx context.Context, aggregateID string) (
return scan(row)
}
func prepareOIDCSettingsQuery() (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings, error)) {
func prepareOIDCSettingsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings, error)) {
return sq.Select(
OIDCSettingsColumnAggregateID.identifier(),
OIDCSettingsColumnCreationDate.identifier(),
@@ -102,7 +103,8 @@ func prepareOIDCSettingsQuery() (sq.SelectBuilder, func(*sql.Row) (*OIDCSettings
OIDCSettingsColumnIdTokenLifetime.identifier(),
OIDCSettingsColumnRefreshTokenIdleExpiration.identifier(),
OIDCSettingsColumnRefreshTokenExpiration.identifier()).
From(oidcSettingsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(oidcSettingsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*OIDCSettings, error) {
oidcSettings := new(OIDCSettings)
err := row.Scan(
+30 -42
View File
@@ -12,6 +12,31 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareOIDCSettingsStmt = `SELECT projections.oidc_settings2.aggregate_id,` +
` projections.oidc_settings2.creation_date,` +
` projections.oidc_settings2.change_date,` +
` projections.oidc_settings2.resource_owner,` +
` projections.oidc_settings2.sequence,` +
` projections.oidc_settings2.access_token_lifetime,` +
` projections.oidc_settings2.id_token_lifetime,` +
` projections.oidc_settings2.refresh_token_idle_expiration,` +
` projections.oidc_settings2.refresh_token_expiration` +
` FROM projections.oidc_settings2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareOIDCSettingsCols = []string{
"aggregate_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"access_token_lifetime",
"id_token_lifetime",
"refresh_token_idle_expiration",
"refresh_token_expiration",
}
)
func Test_OIDCConfigsPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,16 +53,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) {
prepare: prepareOIDCSettingsQuery,
want: want{
sqlExpectations: mockQueries(
`SELECT projections.oidc_settings2.aggregate_id,`+
` projections.oidc_settings2.creation_date,`+
` projections.oidc_settings2.change_date,`+
` projections.oidc_settings2.resource_owner,`+
` projections.oidc_settings2.sequence,`+
` projections.oidc_settings2.access_token_lifetime,`+
` projections.oidc_settings2.id_token_lifetime,`+
` projections.oidc_settings2.refresh_token_idle_expiration,`+
` projections.oidc_settings2.refresh_token_expiration`+
` FROM projections.oidc_settings`,
prepareOIDCSettingsStmt,
nil,
nil,
),
@@ -55,27 +71,8 @@ func Test_OIDCConfigsPrepares(t *testing.T) {
prepare: prepareOIDCSettingsQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.oidc_settings2.aggregate_id,`+
` projections.oidc_settings2.creation_date,`+
` projections.oidc_settings2.change_date,`+
` projections.oidc_settings2.resource_owner,`+
` projections.oidc_settings2.sequence,`+
` projections.oidc_settings2.access_token_lifetime,`+
` projections.oidc_settings2.id_token_lifetime,`+
` projections.oidc_settings2.refresh_token_idle_expiration,`+
` projections.oidc_settings2.refresh_token_expiration`+
` FROM projections.oidc_settings`),
[]string{
"aggregate_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"access_token_lifetime",
"id_token_lifetime",
"refresh_token_idle_expiration",
"refresh_token_expiration",
},
regexp.QuoteMeta(prepareOIDCSettingsStmt),
prepareOIDCSettingsCols,
[]driver.Value{
"agg-id",
testNow,
@@ -106,16 +103,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) {
prepare: prepareOIDCSettingsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.oidc_settings2.aggregate_id,`+
` projections.oidc_settings2.creation_date,`+
` projections.oidc_settings2.change_date,`+
` projections.oidc_settings2.resource_owner,`+
` projections.oidc_settings2.sequence,`+
` projections.oidc_settings2.access_token_lifetime,`+
` projections.oidc_settings2.id_token_lifetime,`+
` projections.oidc_settings2.refresh_token_idle_expiration,`+
` projections.oidc_settings2.refresh_token_expiration`+
` FROM projections.oidc_settings`),
regexp.QuoteMeta(prepareOIDCSettingsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -130,7 +118,7 @@ func Test_OIDCConfigsPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+49 -46
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
domain_pkg "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -96,7 +97,7 @@ func (q *Queries) OrgByID(ctx context.Context, shouldTriggerBulk bool, id string
projection.OrgProjection.Trigger(ctx)
}
stmt, scan := prepareOrgQuery()
stmt, scan := prepareOrgQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
OrgColumnID.identifier(): id,
OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -113,7 +114,7 @@ func (q *Queries) OrgByPrimaryDomain(ctx context.Context, domain string) (_ *Org
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareOrgQuery()
stmt, scan := prepareOrgQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
OrgColumnDomain.identifier(): domain,
OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -130,7 +131,7 @@ func (q *Queries) OrgByVerifiedDomain(ctx context.Context, domain string) (_ *Or
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareOrgWithDomainsQuery()
stmt, scan := prepareOrgWithDomainsQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
OrgDomainDomainCol.identifier(): domain,
OrgDomainIsVerifiedCol.identifier(): true,
@@ -151,7 +152,7 @@ func (q *Queries) IsOrgUnique(ctx context.Context, name, domain string) (isUniqu
if name == "" && domain == "" {
return false, errors.ThrowInvalidArgument(nil, "QUERY-DGqfd", "Errors.Query.InvalidRequest")
}
query, scan := prepareOrgUniqueQuery()
query, scan := prepareOrgUniqueQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.And{
sq.Eq{
@@ -190,7 +191,7 @@ func (q *Queries) SearchOrgs(ctx context.Context, queries *OrgSearchQueries) (or
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareOrgsQuery()
query, scan := prepareOrgsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).
Where(sq.Eq{
OrgColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -231,7 +232,7 @@ func NewOrgIDsSearchQuery(ids ...string) (SearchQuery, error) {
return NewListQuery(OrgColumnID, list, ListIn)
}
func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) {
func prepareOrgsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) {
return sq.Select(
OrgColumnID.identifier(),
OrgColumnCreationDate.identifier(),
@@ -242,7 +243,8 @@ func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) {
OrgColumnName.identifier(),
OrgColumnDomain.identifier(),
countColumn.identifier()).
From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(orgsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Orgs, error) {
orgs := make([]*Org, 0)
var count uint64
@@ -278,7 +280,7 @@ func prepareOrgsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Orgs, error)) {
}
}
func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
func prepareOrgQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
return sq.Select(
OrgColumnID.identifier(),
OrgColumnCreationDate.identifier(),
@@ -289,42 +291,7 @@ func prepareOrgQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
OrgColumnName.identifier(),
OrgColumnDomain.identifier(),
).
From(orgsTable.identifier()).PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Org, error) {
o := new(Org)
err := row.Scan(
&o.ID,
&o.CreationDate,
&o.ChangeDate,
&o.ResourceOwner,
&o.State,
&o.Sequence,
&o.Name,
&o.Domain,
)
if err != nil {
if errs.Is(err, sql.ErrNoRows) {
return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound")
}
return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal")
}
return o, nil
}
}
func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
return sq.Select(
OrgColumnID.identifier(),
OrgColumnCreationDate.identifier(),
OrgColumnChangeDate.identifier(),
OrgColumnResourceOwner.identifier(),
OrgColumnState.identifier(),
OrgColumnSequence.identifier(),
OrgColumnName.identifier(),
OrgColumnDomain.identifier(),
).
From(orgsTable.identifier()).
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)).
From(orgsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Org, error) {
o := new(Org)
@@ -348,10 +315,46 @@ func prepareOrgWithDomainsQuery() (sq.SelectBuilder, func(*sql.Row) (*Org, error
}
}
func prepareOrgUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
func prepareOrgWithDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Org, error)) {
return sq.Select(
OrgColumnID.identifier(),
OrgColumnCreationDate.identifier(),
OrgColumnChangeDate.identifier(),
OrgColumnResourceOwner.identifier(),
OrgColumnState.identifier(),
OrgColumnSequence.identifier(),
OrgColumnName.identifier(),
OrgColumnDomain.identifier(),
).
From(orgsTable.identifier()).
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Org, error) {
o := new(Org)
err := row.Scan(
&o.ID,
&o.CreationDate,
&o.ChangeDate,
&o.ResourceOwner,
&o.State,
&o.Sequence,
&o.Name,
&o.Domain,
)
if err != nil {
if errs.Is(err, sql.ErrNoRows) {
return nil, errors.ThrowNotFound(err, "QUERY-iTTGJ", "Errors.Org.NotFound")
}
return nil, errors.ThrowInternal(err, "QUERY-pWS5H", "Errors.Internal")
}
return o, nil
}
}
func prepareOrgUniqueQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
return sq.Select(uniqueColumn.identifier()).
From(orgsTable.identifier()).
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID)).
LeftJoin(join(OrgDomainOrgIDCol, OrgColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (isUnique bool, err error) {
err = row.Scan(&isUnique)
+5 -3
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -59,7 +60,7 @@ func (q *Queries) SearchOrgDomains(ctx context.Context, queries *OrgDomainSearch
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareDomainsQuery()
query, scan := prepareDomainsQuery(ctx, q.client)
eq := sq.Eq{OrgDomainInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[OrgDomainOwnerRemovedCol.identifier()] = false
@@ -81,7 +82,7 @@ func (q *Queries) SearchOrgDomains(ctx context.Context, queries *OrgDomainSearch
return domains, err
}
func prepareDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Domains, error)) {
func prepareDomainsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Domains, error)) {
return sq.Select(
OrgDomainCreationDateCol.identifier(),
OrgDomainChangeDateCol.identifier(),
@@ -92,7 +93,8 @@ func prepareDomainsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Domains, error))
OrgDomainIsPrimaryCol.identifier(),
OrgDomainValidationTypeCol.identifier(),
countColumn.identifier(),
).From(orgDomainsTable.identifier()).PlaceholderFormat(sq.Dollar),
).From(orgDomainsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Domains, error) {
domains := make([]*Domain, 0)
var count uint64
+32 -63
View File
@@ -11,6 +11,31 @@ import (
"github.com/zitadel/zitadel/internal/domain"
)
var (
prepareOrgDomainsStmt = `SELECT projections.org_domains2.creation_date,` +
` projections.org_domains2.change_date,` +
` projections.org_domains2.sequence,` +
` projections.org_domains2.domain,` +
` projections.org_domains2.org_id,` +
` projections.org_domains2.is_verified,` +
` projections.org_domains2.is_primary,` +
` projections.org_domains2.validation_type,` +
` COUNT(*) OVER ()` +
` FROM projections.org_domains2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareOrgDomainsCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
}
)
func Test_OrgDomainPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -27,16 +52,7 @@ func Test_OrgDomainPrepares(t *testing.T) {
prepare: prepareDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+
` projections.org_domains2.change_date,`+
` projections.org_domains2.sequence,`+
` projections.org_domains2.domain,`+
` projections.org_domains2.org_id,`+
` projections.org_domains2.is_verified,`+
` projections.org_domains2.is_primary,`+
` projections.org_domains2.validation_type,`+
` COUNT(*) OVER ()`+
` FROM projections.org_domains2`),
regexp.QuoteMeta(prepareOrgDomainsStmt),
nil,
nil,
),
@@ -48,27 +64,8 @@ func Test_OrgDomainPrepares(t *testing.T) {
prepare: prepareDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+
` projections.org_domains2.change_date,`+
` projections.org_domains2.sequence,`+
` projections.org_domains2.domain,`+
` projections.org_domains2.org_id,`+
` projections.org_domains2.is_verified,`+
` projections.org_domains2.is_primary,`+
` projections.org_domains2.validation_type,`+
` COUNT(*) OVER ()`+
` FROM projections.org_domains2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
},
regexp.QuoteMeta(prepareOrgDomainsStmt),
prepareOrgDomainsCols,
[][]driver.Value{
{
testNow,
@@ -106,27 +103,8 @@ func Test_OrgDomainPrepares(t *testing.T) {
prepare: prepareDomainsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+
` projections.org_domains2.change_date,`+
` projections.org_domains2.sequence,`+
` projections.org_domains2.domain,`+
` projections.org_domains2.org_id,`+
` projections.org_domains2.is_verified,`+
` projections.org_domains2.is_primary,`+
` projections.org_domains2.validation_type,`+
` COUNT(*) OVER ()`+
` FROM projections.org_domains2`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
},
regexp.QuoteMeta(prepareOrgDomainsStmt),
prepareOrgDomainsCols,
[][]driver.Value{
{
testNow,
@@ -184,16 +162,7 @@ func Test_OrgDomainPrepares(t *testing.T) {
prepare: prepareDomainsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.org_domains2.creation_date,`+
` projections.org_domains2.change_date,`+
` projections.org_domains2.sequence,`+
` projections.org_domains2.domain,`+
` projections.org_domains2.org_id,`+
` projections.org_domains2.is_verified,`+
` projections.org_domains2.is_primary,`+
` projections.org_domains2.validation_type,`+
` COUNT(*) OVER ()`+
` FROM projections.org_domains2`),
regexp.QuoteMeta(prepareOrgDomainsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -208,7 +177,7 @@ func Test_OrgDomainPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+4 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -80,7 +81,7 @@ func (q *Queries) OrgMembers(ctx context.Context, queries *OrgMembersQuery, with
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareOrgMembersQuery()
query, scan := prepareOrgMembersQuery(ctx, q.client)
eq := sq.Eq{OrgMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addOrgMemberWithoutOwnerRemoved(eq)
@@ -108,7 +109,7 @@ func (q *Queries) OrgMembers(ctx context.Context, queries *OrgMembersQuery, with
return members, err
}
func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
func prepareOrgMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
return sq.Select(
OrgMemberCreationDate.identifier(),
OrgMemberChangeDate.identifier(),
@@ -127,7 +128,7 @@ func prepareOrgMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, erro
).From(orgMemberTable.identifier()).
LeftJoin(join(HumanUserIDCol, OrgMemberUserID)).
LeftJoin(join(MachineUserIDCol, OrgMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, OrgMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, OrgMemberUserID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
+2 -1
View File
@@ -37,6 +37,7 @@ var (
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id " +
"AND members.instance_id = projections.login_names2.instance_id " +
"AS OF SYSTEM TIME '-1 ms' " +
"WHERE projections.login_names2.is_primary = $1")
orgMembersColumns = []string{
"creation_date",
@@ -274,7 +275,7 @@ func Test_OrgMemberPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -84,7 +85,7 @@ func (q *Queries) GetOrgMetadataByKey(ctx context.Context, shouldTriggerBulk boo
projection.OrgMetadataProjection.Trigger(ctx)
}
query, scan := prepareOrgMetadataQuery()
query, scan := prepareOrgMetadataQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -119,7 +120,7 @@ func (q *Queries) SearchOrgMetadata(ctx context.Context, shouldTriggerBulk bool,
if !withOwnerRemoved {
eq[OrgMetadataOwnerRemovedCol.identifier()] = false
}
query, scan := prepareOrgMetadataListQuery()
query, scan := prepareOrgMetadataListQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-Egbld", "Errors.Query.SQLStatment")
@@ -162,7 +163,7 @@ func NewOrgMetadataKeySearchQuery(value string, comparison TextComparison) (Sear
return NewTextQuery(OrgMetadataKeyCol, value, comparison)
}
func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, error)) {
func prepareOrgMetadataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata, error)) {
return sq.Select(
OrgMetadataCreationDateCol.identifier(),
OrgMetadataChangeDateCol.identifier(),
@@ -171,7 +172,7 @@ func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata,
OrgMetadataKeyCol.identifier(),
OrgMetadataValueCol.identifier(),
).
From(orgMetadataTable.identifier()).
From(orgMetadataTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*OrgMetadata, error) {
m := new(OrgMetadata)
@@ -194,7 +195,7 @@ func prepareOrgMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*OrgMetadata,
}
}
func prepareOrgMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*OrgMetadataList, error)) {
func prepareOrgMetadataListQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*OrgMetadataList, error)) {
return sq.Select(
OrgMetadataCreationDateCol.identifier(),
OrgMetadataChangeDateCol.identifier(),
@@ -203,7 +204,7 @@ func prepareOrgMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*OrgMetad
OrgMetadataKeyCol.identifier(),
OrgMetadataValueCol.identifier(),
countColumn.identifier()).
From(orgMetadataTable.identifier()).
From(orgMetadataTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*OrgMetadataList, error) {
metadata := make([]*OrgMetadata, 0)
+5 -3
View File
@@ -18,7 +18,8 @@ var (
` projections.org_metadata2.sequence,` +
` projections.org_metadata2.key,` +
` projections.org_metadata2.value` +
` FROM projections.org_metadata2`
` FROM projections.org_metadata2` +
` AS OF SYSTEM TIME '-1 ms'`
orgMetadataCols = []string{
"creation_date",
"change_date",
@@ -34,7 +35,8 @@ var (
` projections.org_metadata2.key,` +
` projections.org_metadata2.value,` +
` COUNT(*) OVER ()` +
` FROM projections.org_metadata2`
` FROM projections.org_metadata2` +
` AS OF SYSTEM TIME '-1 ms'`
orgMetadataListCols = []string{
"creation_date",
"change_date",
@@ -242,7 +244,7 @@ func Test_OrgMetadataPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+73 -111
View File
@@ -11,13 +11,66 @@ import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
)
var (
orgUniqueQuery = "SELECT COUNT(*) = 0 FROM projections.orgs LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id WHERE (projections.org_domains2.is_verified = $1 AND projections.orgs.instance_id = $2 AND (projections.org_domains2.domain ILIKE $3 OR projections.orgs.name ILIKE $4) AND projections.orgs.org_state <> $5)"
orgUniqueQuery = "SELECT COUNT(*) = 0 FROM projections.orgs LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id AS OF SYSTEM TIME '-1 ms' WHERE (projections.org_domains2.is_verified = $1 AND projections.orgs.instance_id = $2 AND (projections.org_domains2.domain ILIKE $3 OR projections.orgs.name ILIKE $4) AND projections.orgs.org_state <> $5)"
orgUniqueCols = []string{"is_unique"}
prepareOrgsQueryStmt = `SELECT projections.orgs.id,` +
` projections.orgs.creation_date,` +
` projections.orgs.change_date,` +
` projections.orgs.resource_owner,` +
` projections.orgs.org_state,` +
` projections.orgs.sequence,` +
` projections.orgs.name,` +
` projections.orgs.primary_domain,` +
` COUNT(*) OVER ()` +
` FROM projections.orgs` +
` AS OF SYSTEM TIME '-1 ms' `
prepareOrgsQueryCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
}
prepareOrgQueryStmt = `SELECT projections.orgs.id,` +
` projections.orgs.creation_date,` +
` projections.orgs.change_date,` +
` projections.orgs.resource_owner,` +
` projections.orgs.org_state,` +
` projections.orgs.sequence,` +
` projections.orgs.name,` +
` projections.orgs.primary_domain` +
` FROM projections.orgs` +
` AS OF SYSTEM TIME '-1 ms' `
prepareOrgQueryCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
}
prepareOrgUniqueStmt = `SELECT COUNT(*) = 0` +
` FROM projections.orgs` +
` LEFT JOIN projections.org_domains2 ON projections.orgs.id = projections.org_domains2.org_id AND projections.orgs.instance_id = projections.org_domains2.instance_id` +
` AS OF SYSTEM TIME '-1 ms' `
prepareOrgUniqueCols = []string{
"count",
}
)
func Test_OrgPrepares(t *testing.T) {
@@ -36,16 +89,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain,`+
` COUNT(*) OVER ()`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgsQueryStmt),
nil,
nil,
),
@@ -57,27 +101,8 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain,`+
` COUNT(*) OVER ()`+
` FROM projections.orgs`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
},
regexp.QuoteMeta(prepareOrgsQueryStmt),
prepareOrgsQueryCols,
[][]driver.Value{
{
"id",
@@ -115,27 +140,8 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain,`+
` COUNT(*) OVER ()`+
` FROM projections.orgs`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
"count",
},
regexp.QuoteMeta(prepareOrgsQueryStmt),
prepareOrgsQueryCols,
[][]driver.Value{
{
"id-1",
@@ -193,16 +199,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain,`+
` COUNT(*) OVER ()`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgsQueryStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -219,15 +216,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgQueryStmt),
nil,
nil,
),
@@ -245,25 +234,8 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain`+
` FROM projections.orgs`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"org_state",
"sequence",
"name",
"primary_domain",
},
regexp.QuoteMeta(prepareOrgQueryStmt),
prepareOrgQueryCols,
[]driver.Value{
"id",
testNow,
@@ -292,15 +264,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.orgs.id,`+
` projections.orgs.creation_date,`+
` projections.orgs.change_date,`+
` projections.orgs.resource_owner,`+
` projections.orgs.org_state,`+
` projections.orgs.sequence,`+
` projections.orgs.name,`+
` projections.orgs.primary_domain`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgQueryStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -317,8 +281,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgUniqueQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT COUNT(*) = 0`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgUniqueStmt),
nil,
nil,
),
@@ -336,11 +299,8 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgUniqueQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT COUNT(*) = 0`+
` FROM projections.orgs`),
[]string{
"count",
},
regexp.QuoteMeta(prepareOrgUniqueStmt),
prepareOrgUniqueCols,
[]driver.Value{
1,
},
@@ -353,8 +313,7 @@ func Test_OrgPrepares(t *testing.T) {
prepare: prepareOrgUniqueQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT COUNT(*) = 0`+
` FROM projections.orgs`),
regexp.QuoteMeta(prepareOrgUniqueStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -369,7 +328,7 @@ func Test_OrgPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -456,7 +415,10 @@ func TestQueries_IsOrgUnique(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
q := &Queries{
client: client,
client: &database.DB{
DB: client,
Database: new(prepareDB),
},
}
gotIsUnique, err := q.IsOrgUnique(context.Background(), tt.args.name, tt.args.domain)
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -91,7 +92,7 @@ func (q *Queries) PasswordAgePolicyByOrg(ctx context.Context, shouldTriggerBulk
if !withOwnerRemoved {
eq[PasswordAgeColOwnerRemoved.identifier()] = false
}
stmt, scan := preparePasswordAgePolicyQuery()
stmt, scan := preparePasswordAgePolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
eq,
@@ -118,7 +119,7 @@ func (q *Queries) DefaultPasswordAgePolicy(ctx context.Context, shouldTriggerBul
projection.PasswordAgeProjection.Trigger(ctx)
}
stmt, scan := preparePasswordAgePolicyQuery()
stmt, scan := preparePasswordAgePolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
PasswordAgeColID.identifier(): authz.GetInstance(ctx).InstanceID(),
}).
@@ -132,7 +133,7 @@ func (q *Queries) DefaultPasswordAgePolicy(ctx context.Context, shouldTriggerBul
return scan(row)
}
func preparePasswordAgePolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PasswordAgePolicy, error)) {
func preparePasswordAgePolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PasswordAgePolicy, error)) {
return sq.Select(
PasswordAgeColID.identifier(),
PasswordAgeColSequence.identifier(),
@@ -144,7 +145,8 @@ func preparePasswordAgePolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*Passwor
PasswordAgeColIsDefault.identifier(),
PasswordAgeColState.identifier(),
).
From(passwordAgeTable.identifier()).PlaceholderFormat(sq.Dollar),
From(passwordAgeTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*PasswordAgePolicy, error) {
policy := new(PasswordAgePolicy)
err := row.Scan(
+30 -42
View File
@@ -12,6 +12,31 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
preparePasswordAgePolicyStmt = `SELECT projections.password_age_policies2.id,` +
` projections.password_age_policies2.sequence,` +
` projections.password_age_policies2.creation_date,` +
` projections.password_age_policies2.change_date,` +
` projections.password_age_policies2.resource_owner,` +
` projections.password_age_policies2.expire_warn_days,` +
` projections.password_age_policies2.max_age_days,` +
` projections.password_age_policies2.is_default,` +
` projections.password_age_policies2.state` +
` FROM projections.password_age_policies2` +
` AS OF SYSTEM TIME '-1 ms'`
preparePasswordAgePolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"expire_warn_days",
"max_age_days",
"is_default",
"state",
}
)
func Test_PasswordAgePolicyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,16 +53,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) {
prepare: preparePasswordAgePolicyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+
` projections.password_age_policies2.sequence,`+
` projections.password_age_policies2.creation_date,`+
` projections.password_age_policies2.change_date,`+
` projections.password_age_policies2.resource_owner,`+
` projections.password_age_policies2.expire_warn_days,`+
` projections.password_age_policies2.max_age_days,`+
` projections.password_age_policies2.is_default,`+
` projections.password_age_policies2.state`+
` FROM projections.password_age_policies2`),
regexp.QuoteMeta(preparePasswordAgePolicyStmt),
nil,
nil,
),
@@ -55,27 +71,8 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) {
prepare: preparePasswordAgePolicyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+
` projections.password_age_policies2.sequence,`+
` projections.password_age_policies2.creation_date,`+
` projections.password_age_policies2.change_date,`+
` projections.password_age_policies2.resource_owner,`+
` projections.password_age_policies2.expire_warn_days,`+
` projections.password_age_policies2.max_age_days,`+
` projections.password_age_policies2.is_default,`+
` projections.password_age_policies2.state`+
` FROM projections.password_age_policies2`),
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"expire_warn_days",
"max_age_days",
"is_default",
"state",
},
regexp.QuoteMeta(preparePasswordAgePolicyStmt),
preparePasswordAgePolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -106,16 +103,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) {
prepare: preparePasswordAgePolicyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.password_age_policies2.id,`+
` projections.password_age_policies2.sequence,`+
` projections.password_age_policies2.creation_date,`+
` projections.password_age_policies2.change_date,`+
` projections.password_age_policies2.resource_owner,`+
` projections.password_age_policies2.expire_warn_days,`+
` projections.password_age_policies2.max_age_days,`+
` projections.password_age_policies2.is_default,`+
` projections.password_age_policies2.state`+
` FROM projections.password_age_policies2`),
regexp.QuoteMeta(preparePasswordAgePolicyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -130,7 +118,7 @@ func Test_PasswordAgePolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -43,7 +44,7 @@ func (q *Queries) PasswordComplexityPolicyByOrg(ctx context.Context, shouldTrigg
if !withOwnerRemoved {
eq[PasswordComplexityColOwnerRemoved.identifier()] = false
}
stmt, scan := preparePasswordComplexityPolicyQuery()
stmt, scan := preparePasswordComplexityPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
eq,
@@ -70,7 +71,7 @@ func (q *Queries) DefaultPasswordComplexityPolicy(ctx context.Context, shouldTri
projection.PasswordComplexityProjection.Trigger(ctx)
}
stmt, scan := preparePasswordComplexityPolicyQuery()
stmt, scan := preparePasswordComplexityPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
PasswordComplexityColID.identifier(): authz.GetInstance(ctx).InstanceID(),
PasswordComplexityColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -148,7 +149,7 @@ var (
}
)
func preparePasswordComplexityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PasswordComplexityPolicy, error)) {
func preparePasswordComplexityPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PasswordComplexityPolicy, error)) {
return sq.Select(
PasswordComplexityColID.identifier(),
PasswordComplexityColSequence.identifier(),
@@ -163,7 +164,8 @@ func preparePasswordComplexityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*
PasswordComplexityColIsDefault.identifier(),
PasswordComplexityColState.identifier(),
).
From(passwordComplexityTable.identifier()).PlaceholderFormat(sq.Dollar),
From(passwordComplexityTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*PasswordComplexityPolicy, error) {
policy := new(PasswordComplexityPolicy)
err := row.Scan(
@@ -12,6 +12,37 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
preparePasswordComplexityPolicyStmt = `SELECT projections.password_complexity_policies2.id,` +
` projections.password_complexity_policies2.sequence,` +
` projections.password_complexity_policies2.creation_date,` +
` projections.password_complexity_policies2.change_date,` +
` projections.password_complexity_policies2.resource_owner,` +
` projections.password_complexity_policies2.min_length,` +
` projections.password_complexity_policies2.has_lowercase,` +
` projections.password_complexity_policies2.has_uppercase,` +
` projections.password_complexity_policies2.has_number,` +
` projections.password_complexity_policies2.has_symbol,` +
` projections.password_complexity_policies2.is_default,` +
` projections.password_complexity_policies2.state` +
` FROM projections.password_complexity_policies2` +
` AS OF SYSTEM TIME '-1 ms'`
preparePasswordComplexityPolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"min_length",
"has_lowercase",
"has_uppercase",
"has_number",
"has_symbol",
"is_default",
"state",
}
)
func Test_PasswordComplexityPolicyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,19 +59,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) {
prepare: preparePasswordComplexityPolicyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+
` projections.password_complexity_policies2.sequence,`+
` projections.password_complexity_policies2.creation_date,`+
` projections.password_complexity_policies2.change_date,`+
` projections.password_complexity_policies2.resource_owner,`+
` projections.password_complexity_policies2.min_length,`+
` projections.password_complexity_policies2.has_lowercase,`+
` projections.password_complexity_policies2.has_uppercase,`+
` projections.password_complexity_policies2.has_number,`+
` projections.password_complexity_policies2.has_symbol,`+
` projections.password_complexity_policies2.is_default,`+
` projections.password_complexity_policies2.state`+
` FROM projections.password_complexity_policies2`),
regexp.QuoteMeta(preparePasswordComplexityPolicyStmt),
nil,
nil,
),
@@ -58,33 +77,8 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) {
prepare: preparePasswordComplexityPolicyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+
` projections.password_complexity_policies2.sequence,`+
` projections.password_complexity_policies2.creation_date,`+
` projections.password_complexity_policies2.change_date,`+
` projections.password_complexity_policies2.resource_owner,`+
` projections.password_complexity_policies2.min_length,`+
` projections.password_complexity_policies2.has_lowercase,`+
` projections.password_complexity_policies2.has_uppercase,`+
` projections.password_complexity_policies2.has_number,`+
` projections.password_complexity_policies2.has_symbol,`+
` projections.password_complexity_policies2.is_default,`+
` projections.password_complexity_policies2.state`+
` FROM projections.password_complexity_policies2`),
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"min_length",
"has_lowercase",
"has_uppercase",
"has_number",
"has_symbol",
"is_default",
"state",
},
regexp.QuoteMeta(preparePasswordComplexityPolicyStmt),
preparePasswordComplexityPolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -121,19 +115,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) {
prepare: preparePasswordComplexityPolicyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.password_complexity_policies2.id,`+
` projections.password_complexity_policies2.sequence,`+
` projections.password_complexity_policies2.creation_date,`+
` projections.password_complexity_policies2.change_date,`+
` projections.password_complexity_policies2.resource_owner,`+
` projections.password_complexity_policies2.min_length,`+
` projections.password_complexity_policies2.has_lowercase,`+
` projections.password_complexity_policies2.has_uppercase,`+
` projections.password_complexity_policies2.has_number,`+
` projections.password_complexity_policies2.has_symbol,`+
` projections.password_complexity_policies2.is_default,`+
` projections.password_complexity_policies2.state`+
` FROM projections.password_complexity_policies2`),
regexp.QuoteMeta(preparePasswordComplexityPolicyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -148,7 +130,7 @@ func Test_PasswordComplexityPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+23 -10
View File
@@ -1,6 +1,7 @@
package query
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
@@ -19,14 +20,14 @@ var (
testNow = time.Now()
)
//assertPrepare checks if the prepare func executes the correct sql query and returns the correct object
//prepareFunc must be of type
// assertPrepare checks if the prepare func executes the correct sql query and returns the correct object
// prepareFunc must be of type
// func() (sq.SelectBuilder, func(*sql.Rows) (*struct, error))
// or
// func() (sq.SelectBuilder, func(*sql.Row) (*struct, error))
//expectedObject represents the return value of scan
//sqlExpectation represents the query executed on the database
func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr) bool {
// expectedObject represents the return value of scan
// sqlExpectation represents the query executed on the database
func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExpectation sqlExpectation, isErr checkErr, prepareArgs ...reflect.Value) bool {
t.Helper()
client, mock, err := sqlmock.New()
@@ -36,7 +37,7 @@ func assertPrepare(t *testing.T, prepareFunc, expectedObject interface{}, sqlExp
mock = sqlExpectation(mock)
builder, scan, err := execPrepare(prepareFunc)
builder, scan, err := execPrepare(prepareFunc, prepareArgs)
if err != nil {
t.Error(err)
return false
@@ -177,12 +178,12 @@ func validateScan(scanType reflect.Type) error {
return nil
}
func execPrepare(prepare interface{}) (builder sq.SelectBuilder, scan interface{}, err error) {
func execPrepare(prepare interface{}, args []reflect.Value) (builder sq.SelectBuilder, scan interface{}, err error) {
prepareVal := reflect.ValueOf(prepare)
if err := validatePrepare(prepareVal.Type()); err != nil {
return sq.SelectBuilder{}, nil, err
}
res := prepareVal.Call([]reflect.Value{})
res := prepareVal.Call(args)
return res[0].Interface().(sq.SelectBuilder), res[1].Interface(), nil
}
@@ -191,7 +192,7 @@ func validatePrepare(prepareType reflect.Type) error {
if prepareType.Kind() != reflect.Func {
return errors.New("prepare is not a function")
}
if prepareType.NumIn() != 0 {
if prepareType.NumIn() < 2 {
return fmt.Errorf("prepare: invalid number of inputs: want: 0 got %d", prepareType.NumIn())
}
if prepareType.NumOut() != 2 {
@@ -297,7 +298,7 @@ func TestValidatePrepare(t *testing.T) {
},
{
name: "correct",
t: reflect.TypeOf(func() (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) {
t: reflect.TypeOf(func(context.Context, prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (interface{}, error)) {
log.Fatal("should not be executed")
return sq.SelectBuilder{}, nil
}),
@@ -313,3 +314,15 @@ func TestValidatePrepare(t *testing.T) {
})
}
}
type prepareDB struct{}
func (_ *prepareDB) Timetravel(time.Duration) string { return " AS OF SYSTEM TIME '-1 ms' " }
var defaultPrepareArgs = []reflect.Value{reflect.ValueOf(context.Background()), reflect.ValueOf(new(prepareDB))}
func (*prepareDB) DatabaseName() string { return "db" }
func (*prepareDB) Username() string { return "user" }
func (*prepareDB) Type() string { return "type" }
+6 -4
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -96,7 +97,7 @@ func (q *Queries) PrivacyPolicyByOrg(ctx context.Context, shouldTriggerBulk bool
if !withOwnerRemoved {
eq[PrivacyColOwnerRemoved.identifier()] = false
}
stmt, scan := preparePrivacyPolicyQuery()
stmt, scan := preparePrivacyPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(
sq.And{
eq,
@@ -122,7 +123,7 @@ func (q *Queries) DefaultPrivacyPolicy(ctx context.Context, shouldTriggerBulk bo
projection.PrivacyPolicyProjection.Trigger(ctx)
}
stmt, scan := preparePrivacyPolicyQuery()
stmt, scan := preparePrivacyPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
PrivacyColID.identifier(): authz.GetInstance(ctx).InstanceID(),
PrivacyColInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -137,7 +138,7 @@ func (q *Queries) DefaultPrivacyPolicy(ctx context.Context, shouldTriggerBulk bo
return scan(row)
}
func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPolicy, error)) {
func preparePrivacyPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PrivacyPolicy, error)) {
return sq.Select(
PrivacyColID.identifier(),
PrivacyColSequence.identifier(),
@@ -150,7 +151,8 @@ func preparePrivacyPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*PrivacyPoli
PrivacyColIsDefault.identifier(),
PrivacyColState.identifier(),
).
From(privacyTable.identifier()).PlaceholderFormat(sq.Dollar),
From(privacyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*PrivacyPolicy, error) {
policy := new(PrivacyPolicy)
err := row.Scan(
+32 -46
View File
@@ -12,6 +12,33 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
preparePrivacyPolicyStmt = `SELECT projections.privacy_policies2.id,` +
` projections.privacy_policies2.sequence,` +
` projections.privacy_policies2.creation_date,` +
` projections.privacy_policies2.change_date,` +
` projections.privacy_policies2.resource_owner,` +
` projections.privacy_policies2.privacy_link,` +
` projections.privacy_policies2.tos_link,` +
` projections.privacy_policies2.help_link,` +
` projections.privacy_policies2.is_default,` +
` projections.privacy_policies2.state` +
` FROM projections.privacy_policies2` +
` AS OF SYSTEM TIME '-1 ms'`
preparePrivacyPolicyCols = []string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"privacy_link",
"tos_link",
"help_link",
"is_default",
"state",
}
)
func Test_PrivacyPolicyPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,17 +55,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
prepare: preparePrivacyPolicyQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+
` projections.privacy_policies2.sequence,`+
` projections.privacy_policies2.creation_date,`+
` projections.privacy_policies2.change_date,`+
` projections.privacy_policies2.resource_owner,`+
` projections.privacy_policies2.privacy_link,`+
` projections.privacy_policies2.tos_link,`+
` projections.privacy_policies2.help_link,`+
` projections.privacy_policies2.is_default,`+
` projections.privacy_policies2.state`+
` FROM projections.privacy_policies2`),
regexp.QuoteMeta(preparePrivacyPolicyStmt),
nil,
nil,
),
@@ -56,29 +73,8 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
prepare: preparePrivacyPolicyQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+
` projections.privacy_policies2.sequence,`+
` projections.privacy_policies2.creation_date,`+
` projections.privacy_policies2.change_date,`+
` projections.privacy_policies2.resource_owner,`+
` projections.privacy_policies2.privacy_link,`+
` projections.privacy_policies2.tos_link,`+
` projections.privacy_policies2.help_link,`+
` projections.privacy_policies2.is_default,`+
` projections.privacy_policies2.state`+
` FROM projections.privacy_policies2`),
[]string{
"id",
"sequence",
"creation_date",
"change_date",
"resource_owner",
"privacy_link",
"tos_link",
"help_link",
"is_default",
"state",
},
regexp.QuoteMeta(preparePrivacyPolicyStmt),
preparePrivacyPolicyCols,
[]driver.Value{
"pol-id",
uint64(20211109),
@@ -111,17 +107,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
prepare: preparePrivacyPolicyQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.privacy_policies2.id,`+
` projections.privacy_policies2.sequence,`+
` projections.privacy_policies2.creation_date,`+
` projections.privacy_policies2.change_date,`+
` projections.privacy_policies2.resource_owner,`+
` projections.privacy_policies2.privacy_link,`+
` projections.privacy_policies2.tos_link,`+
` projections.privacy_policies2.help_link,`+
` projections.privacy_policies2.is_default,`+
` projections.privacy_policies2.state`+
` FROM projections.privacy_policies2`),
regexp.QuoteMeta(preparePrivacyPolicyStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -136,7 +122,7 @@ func Test_PrivacyPolicyPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+9 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -107,7 +108,7 @@ func (q *Queries) ProjectByID(ctx context.Context, shouldTriggerBulk bool, id st
projection.ProjectProjection.Trigger(ctx)
}
stmt, scan := prepareProjectQuery()
stmt, scan := prepareProjectQuery(ctx, q.client)
eq := sq.Eq{
ProjectColumnID.identifier(): id,
ProjectColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -128,7 +129,7 @@ func (q *Queries) SearchProjects(ctx context.Context, queries *ProjectSearchQuer
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareProjectsQuery()
query, scan := prepareProjectsQuery(ctx, q.client)
eq := sq.Eq{ProjectColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[ProjectColumnOwnerRemoved.identifier()] = false
@@ -195,7 +196,7 @@ func (q *ProjectSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder
return query
}
func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
func prepareProjectQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Project, error)) {
return sq.Select(
ProjectColumnID.identifier(),
ProjectColumnCreationDate.identifier(),
@@ -208,7 +209,8 @@ func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error))
ProjectColumnProjectRoleCheck.identifier(),
ProjectColumnHasProjectCheck.identifier(),
ProjectColumnPrivateLabelingSetting.identifier()).
From(projectsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(projectsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Project, error) {
p := new(Project)
err := row.Scan(
@@ -234,7 +236,7 @@ func prepareProjectQuery() (sq.SelectBuilder, func(*sql.Row) (*Project, error))
}
}
func prepareProjectsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Projects, error)) {
func prepareProjectsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Projects, error)) {
return sq.Select(
ProjectColumnID.identifier(),
ProjectColumnCreationDate.identifier(),
@@ -248,7 +250,8 @@ func prepareProjectsQuery() (sq.SelectBuilder, func(*sql.Rows) (*Projects, error
ProjectColumnHasProjectCheck.identifier(),
ProjectColumnPrivateLabelingSetting.identifier(),
countColumn.identifier()).
From(projectsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(projectsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Projects, error) {
projects := make([]*Project, 0)
var count uint64
+12 -9
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -118,7 +119,7 @@ func (q *Queries) ProjectGrantByID(ctx context.Context, shouldTriggerBulk bool,
projection.ProjectGrantProjection.Trigger(ctx)
}
stmt, scan := prepareProjectGrantQuery()
stmt, scan := prepareProjectGrantQuery(ctx, q.client)
eq := sq.Eq{
ProjectGrantColumnGrantID.identifier(): id,
ProjectGrantColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -140,7 +141,7 @@ func (q *Queries) ProjectGrantByIDAndGrantedOrg(ctx context.Context, id, granted
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareProjectGrantQuery()
stmt, scan := prepareProjectGrantQuery(ctx, q.client)
eq := sq.Eq{
ProjectGrantColumnGrantID.identifier(): id,
ProjectGrantColumnGrantedOrgID.identifier(): grantedOrg,
@@ -163,7 +164,7 @@ func (q *Queries) SearchProjectGrants(ctx context.Context, queries *ProjectGrant
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareProjectGrantsQuery()
query, scan := prepareProjectGrantsQuery(ctx, q.client)
eq := sq.Eq{
ProjectGrantColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
}
@@ -272,7 +273,7 @@ func (q *ProjectGrantSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBui
return query
}
func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant, error)) {
func prepareProjectGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant, error)) {
resourceOwnerOrgTable := orgsTable.setAlias(ProjectGrantResourceOwnerTableAlias)
resourceOwnerIDColumn := OrgColumnID.setTable(resourceOwnerOrgTable)
grantedOrgTable := orgsTable.setAlias(ProjectGrantGrantedOrgTableAlias)
@@ -290,10 +291,11 @@ func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant
ProjectGrantColumnGrantedOrgName.identifier(),
ProjectGrantColumnGrantedRoleKeys.identifier(),
ProjectGrantColumnResourceOwnerName.identifier()).
From(projectGrantsTable.identifier()).PlaceholderFormat(sq.Dollar).
From(projectGrantsTable.identifier()).
PlaceholderFormat(sq.Dollar).
LeftJoin(join(ProjectColumnID, ProjectGrantColumnProjectID)).
LeftJoin(join(resourceOwnerIDColumn, ProjectGrantColumnResourceOwner)).
LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID)),
LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID) + db.Timetravel(call.Took(ctx))),
func(row *sql.Row) (*ProjectGrant, error) {
grant := new(ProjectGrant)
var (
@@ -330,7 +332,7 @@ func prepareProjectGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*ProjectGrant
}
}
func prepareProjectGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectGrants, error)) {
func prepareProjectGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*ProjectGrants, error)) {
resourceOwnerOrgTable := orgsTable.setAlias(ProjectGrantResourceOwnerTableAlias)
resourceOwnerIDColumn := OrgColumnID.setTable(resourceOwnerOrgTable)
grantedOrgTable := orgsTable.setAlias(ProjectGrantGrantedOrgTableAlias)
@@ -349,10 +351,11 @@ func prepareProjectGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectGra
ProjectGrantColumnGrantedRoleKeys.identifier(),
ProjectGrantColumnResourceOwnerName.identifier(),
countColumn.identifier()).
From(projectGrantsTable.identifier()).PlaceholderFormat(sq.Dollar).
From(projectGrantsTable.identifier()).
PlaceholderFormat(sq.Dollar).
LeftJoin(join(ProjectColumnID, ProjectGrantColumnProjectID)).
LeftJoin(join(resourceOwnerIDColumn, ProjectGrantColumnResourceOwner)).
LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID)),
LeftJoin(join(grantedOrgIDColumn, ProjectGrantColumnGrantedOrgID) + db.Timetravel(call.Took(ctx))),
func(rows *sql.Rows) (*ProjectGrants, error) {
projects := make([]*ProjectGrant, 0)
var (
+4 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
)
@@ -94,7 +95,7 @@ func addProjectGrantMemberWithoutOwnerRemoved(eq map[string]interface{}) {
}
func (q *Queries) ProjectGrantMembers(ctx context.Context, queries *ProjectGrantMembersQuery, withOwnerRemoved bool) (*Members, error) {
query, scan := prepareProjectGrantMembersQuery()
query, scan := prepareProjectGrantMembersQuery(ctx, q.client)
eq := sq.Eq{ProjectGrantMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addProjectGrantMemberWithoutOwnerRemoved(eq)
@@ -122,7 +123,7 @@ func (q *Queries) ProjectGrantMembers(ctx context.Context, queries *ProjectGrant
return members, err
}
func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
func prepareProjectGrantMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
return sq.Select(
ProjectGrantMemberCreationDate.identifier(),
ProjectGrantMemberChangeDate.identifier(),
@@ -142,7 +143,7 @@ func prepareProjectGrantMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Memb
LeftJoin(join(HumanUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(MachineUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, ProjectGrantMemberUserID)).
LeftJoin(join(ProjectGrantColumnGrantID, ProjectGrantMemberGrantID)).
LeftJoin(join(ProjectGrantColumnGrantID, ProjectGrantMemberGrantID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
+2 -1
View File
@@ -40,6 +40,7 @@ var (
"LEFT JOIN projections.project_grants3 " +
"ON members.grant_id = projections.project_grants3.grant_id " +
"AND members.instance_id = projections.project_grants3.instance_id " +
`AS OF SYSTEM TIME '-1 ms' ` +
"WHERE projections.login_names2.is_primary = $1")
projectGrantMembersColumns = []string{
"creation_date",
@@ -277,7 +278,7 @@ func Test_ProjectGrantMemberPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+5 -3
View File
@@ -30,7 +30,8 @@ var (
` FROM projections.project_grants3 ` +
` LEFT JOIN projections.projects3 ON projections.project_grants3.project_id = projections.projects3.id AND projections.project_grants3.instance_id = projections.projects3.instance_id ` +
` LEFT JOIN projections.orgs AS r ON projections.project_grants3.resource_owner = r.id AND projections.project_grants3.instance_id = r.instance_id` +
` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id`
` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
projectGrantsCols = []string{
"project_id",
"grant_id",
@@ -61,7 +62,8 @@ var (
` FROM projections.project_grants3 ` +
` LEFT JOIN projections.projects3 ON projections.project_grants3.project_id = projections.projects3.id AND projections.project_grants3.instance_id = projections.projects3.instance_id ` +
` LEFT JOIN projections.orgs AS r ON projections.project_grants3.resource_owner = r.id AND projections.project_grants3.instance_id = r.instance_id` +
` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id`
` LEFT JOIN projections.orgs AS o ON projections.project_grants3.granted_org_id = o.id AND projections.project_grants3.instance_id = o.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
projectGrantCols = []string{
"project_id",
"grant_id",
@@ -571,7 +573,7 @@ func Test_ProjectGrantPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+4 -3
View File
@@ -7,6 +7,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -80,7 +81,7 @@ func (q *Queries) ProjectMembers(ctx context.Context, queries *ProjectMembersQue
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareProjectMembersQuery()
query, scan := prepareProjectMembersQuery(ctx, q.client)
eq := sq.Eq{ProjectMemberInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addProjectMemberWithoutOwnerRemoved(eq)
@@ -108,7 +109,7 @@ func (q *Queries) ProjectMembers(ctx context.Context, queries *ProjectMembersQue
return members, err
}
func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
func prepareProjectMembersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Members, error)) {
return sq.Select(
ProjectMemberCreationDate.identifier(),
ProjectMemberChangeDate.identifier(),
@@ -127,7 +128,7 @@ func prepareProjectMembersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Members,
).From(projectMemberTable.identifier()).
LeftJoin(join(HumanUserIDCol, ProjectMemberUserID)).
LeftJoin(join(MachineUserIDCol, ProjectMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, ProjectMemberUserID)).
LeftJoin(join(LoginNameUserIDCol, ProjectMemberUserID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
+2 -1
View File
@@ -37,6 +37,7 @@ var (
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id " +
"AND members.instance_id = projections.login_names2.instance_id " +
`AS OF SYSTEM TIME '-1 ms' ` +
"WHERE projections.login_names2.is_primary = $1")
projectMembersColumns = []string{
"creation_date",
@@ -274,7 +275,7 @@ func Test_ProjectMemberPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+6 -4
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -95,7 +96,7 @@ func (q *Queries) SearchProjectRoles(ctx context.Context, shouldTriggerBulk bool
eq[ProjectRoleColumnOwnerRemoved.identifier()] = false
}
query, scan := prepareProjectRolesQuery()
query, scan := prepareProjectRolesQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-3N9ff", "Errors.Query.InvalidRequest")
@@ -131,7 +132,7 @@ func (q *Queries) SearchGrantedProjectRoles(ctx context.Context, grantID, grante
eq[ProjectRoleColumnOwnerRemoved.identifier()] = false
}
query, scan := prepareProjectRolesQuery()
query, scan := prepareProjectRolesQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-3N9ff", "Errors.Query.InvalidRequest")
@@ -212,7 +213,7 @@ func (q *ProjectRoleSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuil
return query
}
func prepareProjectRolesQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectRoles, error)) {
func prepareProjectRolesQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*ProjectRoles, error)) {
return sq.Select(
ProjectRoleColumnProjectID.identifier(),
ProjectRoleColumnCreationDate.identifier(),
@@ -223,7 +224,8 @@ func prepareProjectRolesQuery() (sq.SelectBuilder, func(*sql.Rows) (*ProjectRole
ProjectRoleColumnDisplayName.identifier(),
ProjectRoleColumnGroupName.identifier(),
countColumn.identifier()).
From(projectRolesTable.identifier()).PlaceholderFormat(sq.Dollar),
From(projectRolesTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*ProjectRoles, error) {
projects := make([]*ProjectRole, 0)
var count uint64
+32 -63
View File
@@ -9,6 +9,31 @@ import (
"testing"
)
var (
prepareProjectRolesStmt = `SELECT projections.project_roles3.project_id,` +
` projections.project_roles3.creation_date,` +
` projections.project_roles3.change_date,` +
` projections.project_roles3.resource_owner,` +
` projections.project_roles3.sequence,` +
` projections.project_roles3.role_key,` +
` projections.project_roles3.display_name,` +
` projections.project_roles3.group_name,` +
` COUNT(*) OVER ()` +
` FROM projections.project_roles3` +
` AS OF SYSTEM TIME '-1 ms'`
prepareProjectRolesCols = []string{
"project_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"role_key",
"display_name",
"group_name",
"count",
}
)
func Test_ProjectRolePrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -25,16 +50,7 @@ func Test_ProjectRolePrepares(t *testing.T) {
prepare: prepareProjectRolesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+
` projections.project_roles3.creation_date,`+
` projections.project_roles3.change_date,`+
` projections.project_roles3.resource_owner,`+
` projections.project_roles3.sequence,`+
` projections.project_roles3.role_key,`+
` projections.project_roles3.display_name,`+
` projections.project_roles3.group_name,`+
` COUNT(*) OVER ()`+
` FROM projections.project_roles3`),
regexp.QuoteMeta(prepareProjectRolesStmt),
nil,
nil,
),
@@ -46,27 +62,8 @@ func Test_ProjectRolePrepares(t *testing.T) {
prepare: prepareProjectRolesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+
` projections.project_roles3.creation_date,`+
` projections.project_roles3.change_date,`+
` projections.project_roles3.resource_owner,`+
` projections.project_roles3.sequence,`+
` projections.project_roles3.role_key,`+
` projections.project_roles3.display_name,`+
` projections.project_roles3.group_name,`+
` COUNT(*) OVER ()`+
` FROM projections.project_roles3`),
[]string{
"project_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"role_key",
"display_name",
"group_name",
"count",
},
regexp.QuoteMeta(prepareProjectRolesStmt),
prepareProjectRolesCols,
[][]driver.Value{
{
"project-id",
@@ -104,27 +101,8 @@ func Test_ProjectRolePrepares(t *testing.T) {
prepare: prepareProjectRolesQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+
` projections.project_roles3.creation_date,`+
` projections.project_roles3.change_date,`+
` projections.project_roles3.resource_owner,`+
` projections.project_roles3.sequence,`+
` projections.project_roles3.role_key,`+
` projections.project_roles3.display_name,`+
` projections.project_roles3.group_name,`+
` COUNT(*) OVER ()`+
` FROM projections.project_roles3`),
[]string{
"project_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"role_key",
"display_name",
"group_name",
"count",
},
regexp.QuoteMeta(prepareProjectRolesStmt),
prepareProjectRolesCols,
[][]driver.Value{
{
"project-id",
@@ -182,16 +160,7 @@ func Test_ProjectRolePrepares(t *testing.T) {
prepare: prepareProjectRolesQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.project_roles3.project_id,`+
` projections.project_roles3.creation_date,`+
` projections.project_roles3.change_date,`+
` projections.project_roles3.resource_owner,`+
` projections.project_roles3.sequence,`+
` projections.project_roles3.role_key,`+
` projections.project_roles3.display_name,`+
` projections.project_roles3.group_name,`+
` COUNT(*) OVER ()`+
` FROM projections.project_roles3`),
regexp.QuoteMeta(prepareProjectRolesStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -206,7 +175,7 @@ func Test_ProjectRolePrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+67 -130
View File
@@ -26,6 +26,62 @@ var (
"has_project_check",
"private_labeling_setting",
}
prepareProjectsStmt = `SELECT projections.projects3.id,` +
` projections.projects3.creation_date,` +
` projections.projects3.change_date,` +
` projections.projects3.resource_owner,` +
` projections.projects3.state,` +
` projections.projects3.sequence,` +
` projections.projects3.name,` +
` projections.projects3.project_role_assertion,` +
` projections.projects3.project_role_check,` +
` projections.projects3.has_project_check,` +
` projections.projects3.private_labeling_setting,` +
` COUNT(*) OVER ()` +
` FROM projections.projects3` +
` AS OF SYSTEM TIME '-1 ms'`
prepareProjectsCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"project_role_assertion",
"project_role_check",
"has_project_check",
"private_labeling_setting",
"count",
}
prepareProjectStmt = `SELECT projections.projects3.id,` +
` projections.projects3.creation_date,` +
` projections.projects3.change_date,` +
` projections.projects3.resource_owner,` +
` projections.projects3.state,` +
` projections.projects3.sequence,` +
` projections.projects3.name,` +
` projections.projects3.project_role_assertion,` +
` projections.projects3.project_role_check,` +
` projections.projects3.has_project_check,` +
` projections.projects3.private_labeling_setting` +
` FROM projections.projects3` +
` AS OF SYSTEM TIME '-1 ms'`
prepareProjectCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"project_role_assertion",
"project_role_check",
"has_project_check",
"private_labeling_setting",
}
)
func Test_ProjectPrepares(t *testing.T) {
@@ -44,19 +100,7 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting,`+
` COUNT(*) OVER ()`+
` FROM projections.projects3`),
regexp.QuoteMeta(prepareProjectsStmt),
nil,
nil,
),
@@ -68,33 +112,8 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting,`+
` COUNT(*) OVER ()`+
` FROM projections.projects3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"project_role_assertion",
"project_role_check",
"has_project_check",
"private_labeling_setting",
"count",
},
regexp.QuoteMeta(prepareProjectsStmt),
prepareProjectsCols,
[][]driver.Value{
{
"id",
@@ -138,33 +157,8 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting,`+
` COUNT(*) OVER ()`+
` FROM projections.projects3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"project_role_assertion",
"project_role_check",
"has_project_check",
"private_labeling_setting",
"count",
},
regexp.QuoteMeta(prepareProjectsStmt),
prepareProjectsCols,
[][]driver.Value{
{
"id-1",
@@ -234,19 +228,7 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting,`+
` COUNT(*) OVER ()`+
` FROM projections.projects3`),
regexp.QuoteMeta(prepareProjectsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -263,18 +245,7 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectQuery,
want: want{
sqlExpectations: mockQueries(
`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting`+
` FROM projections.projects3`,
prepareProjectStmt,
nil,
nil,
),
@@ -292,31 +263,8 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting`+
` FROM projections.projects3`),
[]string{
"id",
"creation_date",
"change_date",
"resource_owner",
"state",
"sequence",
"name",
"project_role_assertion",
"project_role_check",
"has_project_check",
"private_labeling_setting",
},
regexp.QuoteMeta(prepareProjectStmt),
prepareProjectCols,
[]driver.Value{
"id",
testNow,
@@ -351,18 +299,7 @@ func Test_ProjectPrepares(t *testing.T) {
prepare: prepareProjectQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.projects3.id,`+
` projections.projects3.creation_date,`+
` projections.projects3.change_date,`+
` projections.projects3.resource_owner,`+
` projections.projects3.state,`+
` projections.projects3.sequence,`+
` projections.projects3.name,`+
` projections.projects3.project_role_assertion,`+
` projections.projects3.project_role_check,`+
` projections.projects3.has_project_check,`+
` projections.projects3.private_labeling_setting`+
` FROM projections.projects3`),
regexp.QuoteMeta(prepareProjectStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -377,7 +314,7 @@ func Test_ProjectPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+2 -2
View File
@@ -2,9 +2,9 @@ package projection
import (
"context"
"database/sql"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/handler"
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
@@ -74,7 +74,7 @@ var (
projections []projection
)
func Create(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, config Config, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm) error {
func Create(ctx context.Context, sqlClient *database.DB, es *eventstore.Eventstore, config Config, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm) error {
projectionConfig = crdb.StatementHandlerConfig{
ProjectionHandlerConfig: handler.ProjectionHandlerConfig{
HandlerConfig: handler.HandlerConfig{
+8 -3
View File
@@ -2,10 +2,10 @@ package query
import (
"context"
"database/sql"
"fmt"
"net/http"
"sync"
"time"
"github.com/rakyll/statik/fs"
"golang.org/x/text/language"
@@ -13,6 +13,7 @@ import (
"github.com/zitadel/zitadel/internal/api/authz"
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -27,7 +28,7 @@ import (
type Queries struct {
eventstore *eventstore.Eventstore
client *sql.DB
client *database.DB
idpConfigEncryption crypto.EncryptionAlgorithm
@@ -42,7 +43,7 @@ type Queries struct {
multifactors domain.MultifactorConfigs
}
func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *sql.DB, projections projection.Config, defaults sd.SystemDefaults, idpConfigEncryption, otpEncryption, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm, zitadelRoles []authz.RoleMapping) (repo *Queries, err error) {
func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *database.DB, projections projection.Config, defaults sd.SystemDefaults, idpConfigEncryption, otpEncryption, keyEncryptionAlgorithm crypto.EncryptionAlgorithm, certEncryptionAlgorithm crypto.EncryptionAlgorithm, zitadelRoles []authz.RoleMapping) (repo *Queries, err error) {
statikLoginFS, err := fs.NewWithNamespace("login")
if err != nil {
return nil, fmt.Errorf("unable to start login statik dir")
@@ -91,3 +92,7 @@ func StartQueries(ctx context.Context, es *eventstore.Eventstore, sqlClient *sql
func (q *Queries) Health(ctx context.Context) error {
return q.client.Ping()
}
type prepareDatabase interface {
Timetravel(d time.Duration) string
}
+55
View File
@@ -0,0 +1,55 @@
package query
import (
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/quota"
)
type quotaReadModel struct {
eventstore.ReadModel
unit quota.Unit
active bool
config *quota.AddedEvent
}
// newQuotaReadModel aggregateId is filled by reducing unit matching events
func newQuotaReadModel(instanceId, resourceOwner string, unit quota.Unit) *quotaReadModel {
return &quotaReadModel{
ReadModel: eventstore.ReadModel{
InstanceID: instanceId,
ResourceOwner: resourceOwner,
},
unit: unit,
}
}
func (rm *quotaReadModel) Query() *eventstore.SearchQueryBuilder {
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(rm.ResourceOwner).
AllowTimeTravel().
AddQuery().
InstanceID(rm.InstanceID).
AggregateTypes(quota.AggregateType).
EventTypes(
quota.AddedEventType,
quota.RemovedEventType,
).EventData(map[string]interface{}{"unit": rm.unit})
return query.Builder()
}
func (rm *quotaReadModel) Reduce() error {
for _, event := range rm.Events {
switch e := event.(type) {
case *quota.AddedEvent:
rm.AggregateID = e.Aggregate().ID
rm.active = true
rm.config = e
case *quota.RemovedEvent:
rm.AggregateID = e.Aggregate().ID
rm.active = false
rm.config = nil
}
}
return rm.ReadModel.Reduce()
}
+59
View File
@@ -0,0 +1,59 @@
package query
import (
"context"
"math"
"time"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/quota"
)
func (q *Queries) GetDueQuotaNotifications(ctx context.Context, config *quota.AddedEvent, periodStart time.Time, usedAbs uint64) ([]*quota.NotifiedEvent, error) {
if len(config.Notifications) == 0 {
return nil, nil
}
aggregate := config.Aggregate()
wm, err := q.getQuotaNotificationsReadModel(ctx, aggregate, periodStart)
if err != nil {
return nil, err
}
usedRel := uint16(math.Floor(float64(usedAbs*100) / float64(config.Amount)))
var dueNotifications []*quota.NotifiedEvent
for _, notification := range config.Notifications {
if notification.Percent > usedRel {
continue
}
threshold := notification.Percent
if notification.Repeat {
threshold = uint16(math.Min(1, math.Floor(float64(usedRel)/float64(notification.Percent)))) * notification.Percent
}
if wm.latestNotifiedThresholds[notification.ID] < threshold {
dueNotifications = append(
dueNotifications,
quota.NewNotifiedEvent(
ctx,
&aggregate,
config.Unit,
notification.ID,
notification.CallURL,
periodStart,
threshold,
usedAbs,
),
)
}
}
return dueNotifications, nil
}
func (q *Queries) getQuotaNotificationsReadModel(ctx context.Context, aggregate eventstore.Aggregate, periodStart time.Time) (*quotaNotificationsReadModel, error) {
wm := newQuotaNotificationsReadModel(aggregate.ID, aggregate.InstanceID, aggregate.ResourceOwner, periodStart)
return wm, q.eventstore.FilterToQueryReducer(ctx, wm)
}
@@ -0,0 +1,46 @@
package query
import (
"time"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/quota"
)
type quotaNotificationsReadModel struct {
eventstore.ReadModel
periodStart time.Time
latestNotifiedThresholds map[string]uint16
}
func newQuotaNotificationsReadModel(aggregateId, instanceId, resourceOwner string, periodStart time.Time) *quotaNotificationsReadModel {
return &quotaNotificationsReadModel{
ReadModel: eventstore.ReadModel{
AggregateID: aggregateId,
InstanceID: instanceId,
ResourceOwner: resourceOwner,
},
periodStart: periodStart,
latestNotifiedThresholds: make(map[string]uint16),
}
}
func (rm *quotaNotificationsReadModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(rm.ResourceOwner).
AllowTimeTravel().
AddQuery().
InstanceID(rm.InstanceID).
AggregateTypes(quota.AggregateType).
AggregateIDs(rm.AggregateID).
CreationDateAfter(rm.periodStart).
EventTypes(quota.NotifiedEventType).Builder()
}
func (rm *quotaNotificationsReadModel) Reduce() error {
for _, event := range rm.Events {
e := event.(*quota.NotifiedEvent)
rm.latestNotifiedThresholds[e.ID] = e.Threshold
}
return rm.ReadModel.Reduce()
}
+30
View File
@@ -0,0 +1,30 @@
package query
import (
"context"
"time"
"github.com/zitadel/zitadel/internal/repository/quota"
)
func (q *Queries) GetCurrentQuotaPeriod(ctx context.Context, instanceID string, unit quota.Unit) (*quota.AddedEvent, time.Time, error) {
rm, err := q.getQuotaReadModel(ctx, instanceID, instanceID, unit)
if err != nil || !rm.active {
return nil, time.Time{}, err
}
return rm.config, pushPeriodStart(rm.config.From, rm.config.ResetInterval, time.Now()), nil
}
func pushPeriodStart(from time.Time, interval time.Duration, now time.Time) time.Time {
next := from.Add(interval)
if next.After(now) {
return from
}
return pushPeriodStart(next, interval, now)
}
func (q *Queries) getQuotaReadModel(ctx context.Context, instanceId, resourceOwner string, unit quota.Unit) (*quotaReadModel, error) {
rm := newQuotaReadModel(instanceId, resourceOwner, unit)
return rm, q.eventstore.FilterToQueryReducer(ctx, rm)
}
+72 -140
View File
@@ -13,6 +13,67 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareSecretGeneratorStmt = `SELECT projections.secret_generators2.aggregate_id,` +
` projections.secret_generators2.generator_type,` +
` projections.secret_generators2.creation_date,` +
` projections.secret_generators2.change_date,` +
` projections.secret_generators2.resource_owner,` +
` projections.secret_generators2.sequence,` +
` projections.secret_generators2.length,` +
` projections.secret_generators2.expiry,` +
` projections.secret_generators2.include_lower_letters,` +
` projections.secret_generators2.include_upper_letters,` +
` projections.secret_generators2.include_digits,` +
` projections.secret_generators2.include_symbols` +
` FROM projections.secret_generators2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareSecretGeneratorCols = []string{
"aggregate_id",
"generator_type",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"length",
"expiry",
"include_lower_letters",
"include_upper_letters",
"include_digits",
"include_symbols",
}
prepareSecretGeneratorsStmt = `SELECT projections.secret_generators2.aggregate_id,` +
` projections.secret_generators2.generator_type,` +
` projections.secret_generators2.creation_date,` +
` projections.secret_generators2.change_date,` +
` projections.secret_generators2.resource_owner,` +
` projections.secret_generators2.sequence,` +
` projections.secret_generators2.length,` +
` projections.secret_generators2.expiry,` +
` projections.secret_generators2.include_lower_letters,` +
` projections.secret_generators2.include_upper_letters,` +
` projections.secret_generators2.include_digits,` +
` projections.secret_generators2.include_symbols,` +
` COUNT(*) OVER ()` +
` FROM projections.secret_generators2` +
` AS OF SYSTEM TIME '-1 ms'`
prepareSecretGeneratorsCols = []string{
"aggregate_id",
"generator_type",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"length",
"expiry",
"include_lower_letters",
"include_upper_letters",
"include_digits",
"include_symbols",
"count",
}
)
func Test_SecretGeneratorsPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -29,20 +90,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols,`+
` COUNT(*) OVER ()`+
` FROM projections.secret_generators2`),
regexp.QuoteMeta(prepareSecretGeneratorsStmt),
nil,
nil,
),
@@ -54,35 +102,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols,`+
` COUNT(*) OVER ()`+
` FROM projections.secret_generators2`),
[]string{
"aggregate_id",
"generator_type",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"length",
"expiry",
"include_lower_letters",
"include_upper_letters",
"include_digits",
"include_symbols",
"count",
},
regexp.QuoteMeta(prepareSecretGeneratorsStmt),
prepareSecretGeneratorsCols,
[][]driver.Value{
{
"agg-id",
@@ -128,35 +149,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols,`+
` COUNT(*) OVER ()`+
` FROM projections.secret_generators2`),
[]string{
"aggregate_id",
"generator_type",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"length",
"expiry",
"include_lower_letters",
"include_upper_letters",
"include_digits",
"include_symbols",
"count",
},
regexp.QuoteMeta(prepareSecretGeneratorsStmt),
prepareSecretGeneratorsCols,
[][]driver.Value{
{
"agg-id",
@@ -230,20 +224,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols,`+
` COUNT(*) OVER ()`+
` FROM projections.secret_generators2`),
regexp.QuoteMeta(prepareSecretGeneratorsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -260,19 +241,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorQuery,
want: want{
sqlExpectations: mockQueries(
`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols`+
` FROM projections.secret_generators2`,
prepareSecretGeneratorStmt,
nil,
nil,
),
@@ -290,33 +259,8 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols`+
` FROM projections.secret_generators2`),
[]string{
"aggregate_id",
"generator_type",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"length",
"expiry",
"include_lower_letters",
"include_upper_letters",
"include_digits",
"include_symbols",
},
regexp.QuoteMeta(prepareSecretGeneratorStmt),
prepareSecretGeneratorCols,
[]driver.Value{
"agg-id",
domain.SecretGeneratorTypeInitCode,
@@ -353,19 +297,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
prepare: prepareSecretGeneratorQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.secret_generators2.aggregate_id,`+
` projections.secret_generators2.generator_type,`+
` projections.secret_generators2.creation_date,`+
` projections.secret_generators2.change_date,`+
` projections.secret_generators2.resource_owner,`+
` projections.secret_generators2.sequence,`+
` projections.secret_generators2.length,`+
` projections.secret_generators2.expiry,`+
` projections.secret_generators2.include_lower_letters,`+
` projections.secret_generators2.include_upper_letters,`+
` projections.secret_generators2.include_digits,`+
` projections.secret_generators2.include_symbols`+
` FROM projections.secret_generators2`),
regexp.QuoteMeta(prepareSecretGeneratorStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -380,7 +312,7 @@ func Test_SecretGeneratorsPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+9 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -137,7 +138,7 @@ func (q *Queries) SecretGeneratorByType(ctx context.Context, generatorType domai
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareSecretGeneratorQuery()
stmt, scan := prepareSecretGeneratorQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
SecretGeneratorColumnGeneratorType.identifier(): generatorType,
SecretGeneratorColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -154,7 +155,7 @@ func (q *Queries) SearchSecretGenerators(ctx context.Context, queries *SecretGen
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareSecretGeneratorsQuery()
query, scan := prepareSecretGeneratorsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).
Where(sq.Eq{
SecretGeneratorColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -187,7 +188,7 @@ func NewSecretGeneratorTypeSearchQuery(value int32) (SearchQuery, error) {
return NewNumberQuery(SecretGeneratorColumnGeneratorType, value, NumberEquals)
}
func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGenerator, error)) {
func prepareSecretGeneratorQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecretGenerator, error)) {
return sq.Select(
SecretGeneratorColumnAggregateID.identifier(),
SecretGeneratorColumnGeneratorType.identifier(),
@@ -201,7 +202,8 @@ func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGen
SecretGeneratorColumnIncludeUpperLetters.identifier(),
SecretGeneratorColumnIncludeDigits.identifier(),
SecretGeneratorColumnIncludeSymbols.identifier()).
From(secretGeneratorsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(secretGeneratorsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*SecretGenerator, error) {
secretGenerator := new(SecretGenerator)
err := row.Scan(
@@ -228,7 +230,7 @@ func prepareSecretGeneratorQuery() (sq.SelectBuilder, func(*sql.Row) (*SecretGen
}
}
func prepareSecretGeneratorsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SecretGenerators, error)) {
func prepareSecretGeneratorsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*SecretGenerators, error)) {
return sq.Select(
SecretGeneratorColumnAggregateID.identifier(),
SecretGeneratorColumnGeneratorType.identifier(),
@@ -243,7 +245,8 @@ func prepareSecretGeneratorsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SecretG
SecretGeneratorColumnIncludeDigits.identifier(),
SecretGeneratorColumnIncludeSymbols.identifier(),
countColumn.identifier()).
From(secretGeneratorsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(secretGeneratorsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*SecretGenerators, error) {
secretGenerators := make([]*SecretGenerator, 0)
var count uint64
+5 -3
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -57,7 +58,7 @@ type SecurityPolicy struct {
}
func (q *Queries) SecurityPolicy(ctx context.Context) (*SecurityPolicy, error) {
stmt, scan := prepareSecurityPolicyQuery()
stmt, scan := prepareSecurityPolicyQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
SecurityPolicyColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
}).ToSql()
@@ -69,7 +70,7 @@ func (q *Queries) SecurityPolicy(ctx context.Context) (*SecurityPolicy, error) {
return scan(row)
}
func prepareSecurityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*SecurityPolicy, error)) {
func prepareSecurityPolicyQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SecurityPolicy, error)) {
return sq.Select(
SecurityPolicyColumnInstanceID.identifier(),
SecurityPolicyColumnCreationDate.identifier(),
@@ -78,7 +79,8 @@ func prepareSecurityPolicyQuery() (sq.SelectBuilder, func(*sql.Row) (*SecurityPo
SecurityPolicyColumnSequence.identifier(),
SecurityPolicyColumnEnabled.identifier(),
SecurityPolicyColumnAllowedOrigins.identifier()).
From(securityPolicyTable.identifier()).PlaceholderFormat(sq.Dollar),
From(securityPolicyTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*SecurityPolicy, error) {
securityPolicy := new(SecurityPolicy)
err := row.Scan(
+8 -7
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -118,7 +119,7 @@ func (q *Queries) SMSProviderConfigByID(ctx context.Context, id string) (_ *SMSC
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareSMSConfigQuery()
query, scan := prepareSMSConfigQuery(ctx, q.client)
stmt, args, err := query.Where(
sq.Eq{
SMSConfigColumnID.identifier(): id,
@@ -137,7 +138,7 @@ func (q *Queries) SMSProviderConfig(ctx context.Context, queries ...SearchQuery)
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareSMSConfigQuery()
query, scan := prepareSMSConfigQuery(ctx, q.client)
for _, searchQuery := range queries {
query = searchQuery.toQuery(query)
}
@@ -158,7 +159,7 @@ func (q *Queries) SearchSMSConfigs(ctx context.Context, queries *SMSConfigsSearc
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareSMSConfigsQuery()
query, scan := prepareSMSConfigsQuery(ctx, q.client)
stmt, args, err := queries.toQuery(query).
Where(sq.Eq{
SMSConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -183,7 +184,7 @@ func NewSMSProviderStateQuery(state domain.SMSConfigState) (SearchQuery, error)
return NewNumberQuery(SMSConfigColumnState, state, NumberEquals)
}
func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, error)) {
func prepareSMSConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, error)) {
return sq.Select(
SMSConfigColumnID.identifier(),
SMSConfigColumnAggregateID.identifier(),
@@ -198,7 +199,7 @@ func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, erro
SMSTwilioConfigColumnToken.identifier(),
SMSTwilioConfigColumnSenderNumber.identifier(),
).From(smsConfigsTable.identifier()).
LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID)).
LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(row *sql.Row) (*SMSConfig, error) {
config := new(SMSConfig)
@@ -234,7 +235,7 @@ func prepareSMSConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMSConfig, erro
}
}
func prepareSMSConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, error)) {
func prepareSMSConfigsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, error)) {
return sq.Select(
SMSConfigColumnID.identifier(),
SMSConfigColumnAggregateID.identifier(),
@@ -250,7 +251,7 @@ func prepareSMSConfigsQuery() (sq.SelectBuilder, func(*sql.Rows) (*SMSConfigs, e
SMSTwilioConfigColumnSenderNumber.identifier(),
countColumn.identifier(),
).From(smsConfigsTable.identifier()).
LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID)).
LeftJoin(join(SMSTwilioConfigColumnSMSID, SMSConfigColumnID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar), func(row *sql.Rows) (*SMSConfigs, error) {
configs := &SMSConfigs{Configs: []*SMSConfig{}}
+6 -4
View File
@@ -28,7 +28,8 @@ var (
` projections.sms_configs2_twilio.token,` +
` projections.sms_configs2_twilio.sender_number` +
` FROM projections.sms_configs2` +
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id`)
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedSMSConfigsQuery = regexp.QuoteMeta(`SELECT projections.sms_configs2.id,` +
` projections.sms_configs2.aggregate_id,` +
` projections.sms_configs2.creation_date,` +
@@ -44,7 +45,8 @@ var (
` projections.sms_configs2_twilio.sender_number,` +
` COUNT(*) OVER ()` +
` FROM projections.sms_configs2` +
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id`)
` LEFT JOIN projections.sms_configs2_twilio ON projections.sms_configs2.id = projections.sms_configs2_twilio.sms_id AND projections.sms_configs2.instance_id = projections.sms_configs2_twilio.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
smsConfigCols = []string{
"id",
@@ -228,7 +230,7 @@ func Test_SMSConfigssPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
@@ -320,7 +322,7 @@ func Test_SMSConfigPrepare(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+5 -3
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -94,7 +95,7 @@ func (q *Queries) SMTPConfigByAggregateID(ctx context.Context, aggregateID strin
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
stmt, scan := prepareSMTPConfigQuery()
stmt, scan := prepareSMTPConfigQuery(ctx, q.client)
query, args, err := stmt.Where(sq.Eq{
SMTPConfigColumnAggregateID.identifier(): aggregateID,
SMTPConfigColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -107,7 +108,7 @@ func (q *Queries) SMTPConfigByAggregateID(ctx context.Context, aggregateID strin
return scan(row)
}
func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, error)) {
func prepareSMTPConfigQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, error)) {
password := new(crypto.CryptoValue)
return sq.Select(
@@ -122,7 +123,8 @@ func prepareSMTPConfigQuery() (sq.SelectBuilder, func(*sql.Row) (*SMTPConfig, er
SMTPConfigColumnSMTPHost.identifier(),
SMTPConfigColumnSMTPUser.identifier(),
SMTPConfigColumnSMTPPassword.identifier()).
From(smtpConfigsTable.identifier()).PlaceholderFormat(sq.Dollar),
From(smtpConfigsTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*SMTPConfig, error) {
config := new(SMTPConfig)
err := row.Scan(
+34 -50
View File
@@ -12,6 +12,35 @@ import (
errs "github.com/zitadel/zitadel/internal/errors"
)
var (
prepareSMTPConfigStmt = `SELECT projections.smtp_configs.aggregate_id,` +
` projections.smtp_configs.creation_date,` +
` projections.smtp_configs.change_date,` +
` projections.smtp_configs.resource_owner,` +
` projections.smtp_configs.sequence,` +
` projections.smtp_configs.tls,` +
` projections.smtp_configs.sender_address,` +
` projections.smtp_configs.sender_name,` +
` projections.smtp_configs.host,` +
` projections.smtp_configs.username,` +
` projections.smtp_configs.password` +
` FROM projections.smtp_configs` +
` AS OF SYSTEM TIME '-1 ms'`
prepareSMTPConfigCols = []string{
"aggregate_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"tls",
"sender_address",
"sender_name",
"smtp_host",
"smtp_user",
"smtp_password",
}
)
func Test_SMTPConfigsPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -28,18 +57,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
prepare: prepareSMTPConfigQuery,
want: want{
sqlExpectations: mockQueries(
`SELECT projections.smtp_configs.aggregate_id,`+
` projections.smtp_configs.creation_date,`+
` projections.smtp_configs.change_date,`+
` projections.smtp_configs.resource_owner,`+
` projections.smtp_configs.sequence,`+
` projections.smtp_configs.tls,`+
` projections.smtp_configs.sender_address,`+
` projections.smtp_configs.sender_name,`+
` projections.smtp_configs.host,`+
` projections.smtp_configs.username,`+
` projections.smtp_configs.password`+
` FROM projections.smtp_configs`,
prepareSMTPConfigStmt,
nil,
nil,
),
@@ -57,31 +75,8 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
prepare: prepareSMTPConfigQuery,
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(`SELECT projections.smtp_configs.aggregate_id,`+
` projections.smtp_configs.creation_date,`+
` projections.smtp_configs.change_date,`+
` projections.smtp_configs.resource_owner,`+
` projections.smtp_configs.sequence,`+
` projections.smtp_configs.tls,`+
` projections.smtp_configs.sender_address,`+
` projections.smtp_configs.sender_name,`+
` projections.smtp_configs.host,`+
` projections.smtp_configs.username,`+
` projections.smtp_configs.password`+
` FROM projections.smtp_configs`),
[]string{
"aggregate_id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"tls",
"sender_address",
"sender_name",
"smtp_host",
"smtp_user",
"smtp_password",
},
regexp.QuoteMeta(prepareSMTPConfigStmt),
prepareSMTPConfigCols,
[]driver.Value{
"agg-id",
testNow,
@@ -116,18 +111,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
prepare: prepareSMTPConfigQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.smtp_configs.aggregate_id,`+
` projections.smtp_configs.creation_date,`+
` projections.smtp_configs.change_date,`+
` projections.smtp_configs.resource_owner,`+
` projections.smtp_configs.sequence,`+
` projections.smtp_configs.tls,`+
` projections.smtp_configs.sender_address,`+
` projections.smtp_configs.sender_name,`+
` projections.smtp_configs.host,`+
` projections.smtp_configs.username,`+
` projections.smtp_configs.password`+
` FROM projections.smtp_configs`),
regexp.QuoteMeta(prepareSMTPConfigStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -142,7 +126,7 @@ func Test_SMTPConfigsPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+24 -23
View File
@@ -11,6 +11,7 @@ import (
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -341,7 +342,7 @@ func (q *Queries) GetUserByID(ctx context.Context, shouldTriggerBulk bool, userI
projection.LoginNameProjection.Trigger(ctx)
}
query, scan := prepareUserQuery()
query, scan := prepareUserQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -370,7 +371,7 @@ func (q *Queries) GetUser(ctx context.Context, shouldTriggerBulk bool, withOwner
projection.LoginNameProjection.Trigger(ctx)
}
query, scan := prepareUserQuery()
query, scan := prepareUserQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -393,7 +394,7 @@ func (q *Queries) GetHumanProfile(ctx context.Context, userID string, withOwnerR
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareProfileQuery()
query, scan := prepareProfileQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -417,7 +418,7 @@ func (q *Queries) GetHumanEmail(ctx context.Context, userID string, withOwnerRem
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareEmailQuery()
query, scan := prepareEmailQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -441,7 +442,7 @@ func (q *Queries) GetHumanPhone(ctx context.Context, userID string, withOwnerRem
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := preparePhoneQuery()
query, scan := preparePhoneQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -470,7 +471,7 @@ func (q *Queries) GetNotifyUserByID(ctx context.Context, shouldTriggered bool, u
projection.LoginNameProjection.Trigger(ctx)
}
query, scan := prepareNotifyUserQuery()
query, scan := prepareNotifyUserQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -499,7 +500,7 @@ func (q *Queries) GetNotifyUser(ctx context.Context, shouldTriggered bool, withO
projection.LoginNameProjection.Trigger(ctx)
}
query, scan := prepareNotifyUserQuery()
query, scan := prepareNotifyUserQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -522,7 +523,7 @@ func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, w
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareUsersQuery()
query, scan := prepareUsersQuery(ctx, q.client)
eq := sq.Eq{UserInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addUserWithoutOwnerRemoved(eq)
@@ -549,7 +550,7 @@ func (q *Queries) IsUserUnique(ctx context.Context, username, email, resourceOwn
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareUserUniqueQuery()
query, scan := prepareUserUniqueQuery(ctx, q.client)
queries := make([]SearchQuery, 0, 3)
if username != "" {
usernameQuery, err := NewUserUsernameSearchQuery(username, TextEquals)
@@ -722,7 +723,7 @@ func preparePreferredLoginNamesQuery() (string, []interface{}, error) {
).ToSql()
}
func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
func prepareUserQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery()
if err != nil {
return sq.SelectBuilder{}, nil
@@ -770,7 +771,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
loginNamesArgs...).
LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+
userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(),
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)),
preferredLoginNameArgs...).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*User, error) {
@@ -863,7 +864,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
}
}
func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) {
func prepareProfileQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Profile, error)) {
return sq.Select(
UserIDCol.identifier(),
UserCreationDateCol.identifier(),
@@ -879,7 +880,7 @@ func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error))
HumanGenderCol.identifier(),
HumanAvatarURLCol.identifier()).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Profile, error) {
p := new(Profile)
@@ -929,7 +930,7 @@ func prepareProfileQuery() (sq.SelectBuilder, func(*sql.Row) (*Profile, error))
}
}
func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) {
func prepareEmailQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Email, error)) {
return sq.Select(
UserIDCol.identifier(),
UserCreationDateCol.identifier(),
@@ -940,7 +941,7 @@ func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) {
HumanEmailCol.identifier(),
HumanIsEmailVerifiedCol.identifier()).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Email, error) {
e := new(Email)
@@ -976,7 +977,7 @@ func prepareEmailQuery() (sq.SelectBuilder, func(*sql.Row) (*Email, error)) {
}
}
func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) {
func preparePhoneQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) {
return sq.Select(
UserIDCol.identifier(),
UserCreationDateCol.identifier(),
@@ -987,7 +988,7 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) {
HumanPhoneCol.identifier(),
HumanIsPhoneVerifiedCol.identifier()).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*Phone, error) {
e := new(Phone)
@@ -1023,7 +1024,7 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) {
}
}
func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
func prepareNotifyUserQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery()
if err != nil {
return sq.SelectBuilder{}, nil
@@ -1068,7 +1069,7 @@ func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, er
loginNamesArgs...).
LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+
userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(),
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)),
preferredLoginNameArgs...).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*NotifyUser, error) {
@@ -1155,7 +1156,7 @@ func prepareNotifyUserQuery() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, er
}
}
func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
func prepareUserUniqueQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
return sq.Select(
UserIDCol.identifier(),
UserStateCol.identifier(),
@@ -1164,7 +1165,7 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
HumanEmailCol.identifier(),
HumanIsEmailVerifiedCol.identifier()).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
LeftJoin(join(HumanUserIDCol, UserIDCol) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (bool, error) {
userID := sql.NullString{}
@@ -1192,7 +1193,7 @@ func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
}
}
func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
loginNamesQuery, loginNamesArgs, err := prepareLoginNamesQuery()
if err != nil {
return sq.SelectBuilder{}, nil
@@ -1239,7 +1240,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
loginNamesArgs...).
LeftJoin("("+preferredLoginNameQuery+") AS "+userPreferredLoginNameTable.alias+" ON "+
userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier()+" AND "+
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier(),
userPreferredLoginNameInstanceIDCol.identifier()+" = "+UserInstanceIDCol.identifier()+db.Timetravel(call.Took(ctx)),
preferredLoginNameArgs...).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*Users, error) {
+5 -3
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -91,7 +92,7 @@ func (q *Queries) SearchUserAuthMethods(ctx context.Context, queries *UserAuthMe
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareUserAuthMethodsQuery()
query, scan := prepareUserAuthMethodsQuery(ctx, q.client)
eq := sq.Eq{UserAuthMethodColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
eq[UserAuthMethodColumnOwnerRemoved.identifier()] = false
@@ -203,7 +204,7 @@ func (q *UserAuthMethodSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectB
return query
}
func prepareUserAuthMethodsQuery() (sq.SelectBuilder, func(*sql.Rows) (*AuthMethods, error)) {
func prepareUserAuthMethodsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*AuthMethods, error)) {
return sq.Select(
UserAuthMethodColumnTokenID.identifier(),
UserAuthMethodColumnCreationDate.identifier(),
@@ -215,7 +216,8 @@ func prepareUserAuthMethodsQuery() (sq.SelectBuilder, func(*sql.Rows) (*AuthMeth
UserAuthMethodColumnState.identifier(),
UserAuthMethodColumnMethodType.identifier(),
countColumn.identifier()).
From(userAuthMethodTable.identifier()).PlaceholderFormat(sq.Dollar),
From(userAuthMethodTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*AuthMethods, error) {
userAuthMethods := make([]*AuthMethod, 0)
var count uint64
+34 -69
View File
@@ -11,6 +11,33 @@ import (
"github.com/zitadel/zitadel/internal/domain"
)
var (
prepareUserAuthMethodsStmt = `SELECT projections.user_auth_methods4.token_id,` +
` projections.user_auth_methods4.creation_date,` +
` projections.user_auth_methods4.change_date,` +
` projections.user_auth_methods4.resource_owner,` +
` projections.user_auth_methods4.user_id,` +
` projections.user_auth_methods4.sequence,` +
` projections.user_auth_methods4.name,` +
` projections.user_auth_methods4.state,` +
` projections.user_auth_methods4.method_type,` +
` COUNT(*) OVER ()` +
` FROM projections.user_auth_methods4` +
` AS OF SYSTEM TIME '-1 ms'`
prepareUserAuthMethodsCols = []string{
"token_id",
"creation_date",
"change_date",
"resource_owner",
"user_id",
"sequence",
"name",
"state",
"method_type",
"count",
}
)
func Test_UserAuthMethodPrepares(t *testing.T) {
type want struct {
sqlExpectations sqlExpectation
@@ -27,17 +54,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) {
prepare: prepareUserAuthMethodsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+
` projections.user_auth_methods4.creation_date,`+
` projections.user_auth_methods4.change_date,`+
` projections.user_auth_methods4.resource_owner,`+
` projections.user_auth_methods4.user_id,`+
` projections.user_auth_methods4.sequence,`+
` projections.user_auth_methods4.name,`+
` projections.user_auth_methods4.state,`+
` projections.user_auth_methods4.method_type,`+
` COUNT(*) OVER ()`+
` FROM projections.user_auth_methods4`),
regexp.QuoteMeta(prepareUserAuthMethodsStmt),
nil,
nil,
),
@@ -49,29 +66,8 @@ func Test_UserAuthMethodPrepares(t *testing.T) {
prepare: prepareUserAuthMethodsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+
` projections.user_auth_methods4.creation_date,`+
` projections.user_auth_methods4.change_date,`+
` projections.user_auth_methods4.resource_owner,`+
` projections.user_auth_methods4.user_id,`+
` projections.user_auth_methods4.sequence,`+
` projections.user_auth_methods4.name,`+
` projections.user_auth_methods4.state,`+
` projections.user_auth_methods4.method_type,`+
` COUNT(*) OVER ()`+
` FROM projections.user_auth_methods4`),
[]string{
"token_id",
"creation_date",
"change_date",
"resource_owner",
"user_id",
"sequence",
"name",
"state",
"method_type",
"count",
},
regexp.QuoteMeta(prepareUserAuthMethodsStmt),
prepareUserAuthMethodsCols,
[][]driver.Value{
{
"token_id",
@@ -111,29 +107,8 @@ func Test_UserAuthMethodPrepares(t *testing.T) {
prepare: prepareUserAuthMethodsQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+
` projections.user_auth_methods4.creation_date,`+
` projections.user_auth_methods4.change_date,`+
` projections.user_auth_methods4.resource_owner,`+
` projections.user_auth_methods4.user_id,`+
` projections.user_auth_methods4.sequence,`+
` projections.user_auth_methods4.name,`+
` projections.user_auth_methods4.state,`+
` projections.user_auth_methods4.method_type,`+
` COUNT(*) OVER ()`+
` FROM projections.user_auth_methods4`),
[]string{
"token_id",
"creation_date",
"change_date",
"resource_owner",
"user_id",
"sequence",
"name",
"state",
"method_type",
"count",
},
regexp.QuoteMeta(prepareUserAuthMethodsStmt),
prepareUserAuthMethodsCols,
[][]driver.Value{
{
"token_id",
@@ -195,17 +170,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) {
prepare: prepareUserAuthMethodsQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.user_auth_methods4.token_id,`+
` projections.user_auth_methods4.creation_date,`+
` projections.user_auth_methods4.change_date,`+
` projections.user_auth_methods4.resource_owner,`+
` projections.user_auth_methods4.user_id,`+
` projections.user_auth_methods4.sequence,`+
` projections.user_auth_methods4.name,`+
` projections.user_auth_methods4.state,`+
` projections.user_auth_methods4.method_type,`+
` COUNT(*) OVER ()`+
` FROM projections.user_auth_methods4`),
regexp.QuoteMeta(prepareUserAuthMethodsStmt),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
@@ -220,7 +185,7 @@ func Test_UserAuthMethodPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
@@ -225,7 +226,7 @@ func (q *Queries) UserGrant(ctx context.Context, shouldTriggerBulk bool, withOwn
projection.UserGrantProjection.Trigger(ctx)
}
query, scan := prepareUserGrantQuery()
query, scan := prepareUserGrantQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -246,7 +247,7 @@ func (q *Queries) UserGrants(ctx context.Context, queries *UserGrantsQueries, wi
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := prepareUserGrantsQuery()
query, scan := prepareUserGrantsQuery(ctx, q.client)
eq := sq.Eq{UserGrantInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
if !withOwnerRemoved {
addUserGrantWithoutOwnerRemoved(eq)
@@ -274,7 +275,7 @@ func (q *Queries) UserGrants(ctx context.Context, queries *UserGrantsQueries, wi
return grants, nil
}
func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, error)) {
func prepareUserGrantQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*UserGrant, error)) {
return sq.Select(
UserGrantID.identifier(),
UserGrantCreationDate.identifier(),
@@ -307,7 +308,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
@@ -382,7 +383,7 @@ func prepareUserGrantQuery() (sq.SelectBuilder, func(*sql.Row) (*UserGrant, erro
}
}
func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, error)) {
func prepareUserGrantsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, error)) {
return sq.Select(
UserGrantID.identifier(),
UserGrantCreationDate.identifier(),
@@ -417,7 +418,7 @@ func prepareUserGrantsQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserGrants, e
LeftJoin(join(HumanUserIDCol, UserGrantUserID)).
LeftJoin(join(OrgColumnID, UserGrantResourceOwner)).
LeftJoin(join(ProjectColumnID, UserGrantProjectID)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID)).
LeftJoin(join(LoginNameUserIDCol, UserGrantUserID) + db.Timetravel(call.Took(ctx))).
Where(
sq.Eq{LoginNameIsPrimaryCol.identifier(): true},
).PlaceholderFormat(sq.Dollar),
+3 -1
View File
@@ -43,6 +43,7 @@ var (
" LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" +
" LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" +
" LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names2.is_primary = $1")
userGrantCols = []string{
"id",
@@ -98,6 +99,7 @@ var (
" LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" +
" LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" +
" LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names2.is_primary = $1")
userGrantsCols = append(
userGrantCols,
@@ -923,7 +925,7 @@ func Test_UserGrantPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+4 -3
View File
@@ -8,6 +8,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -108,7 +109,7 @@ func (q *Queries) Memberships(ctx context.Context, queries *MembershipSearchQuer
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, queryArgs, scan := prepareMembershipsQuery(withOwnerRemoved)
query, queryArgs, scan := prepareMembershipsQuery(ctx, q.client, withOwnerRemoved)
eq := sq.Eq{membershipInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
if err != nil {
@@ -221,7 +222,7 @@ func getMembershipFromQuery(withOwnerRemoved bool) (string, []interface{}) {
args
}
func prepareMembershipsQuery(withOwnerRemoved bool) (sq.SelectBuilder, []interface{}, func(*sql.Rows) (*Memberships, error)) {
func prepareMembershipsQuery(ctx context.Context, db prepareDatabase, withOwnerRemoved bool) (sq.SelectBuilder, []interface{}, func(*sql.Rows) (*Memberships, error)) {
query, args := getMembershipFromQuery(withOwnerRemoved)
return sq.Select(
membershipUserID.identifier(),
@@ -241,7 +242,7 @@ func prepareMembershipsQuery(withOwnerRemoved bool) (sq.SelectBuilder, []interfa
).From(query).
LeftJoin(join(ProjectColumnID, membershipProjectID)).
LeftJoin(join(OrgColumnID, membershipOrgID)).
LeftJoin(join(ProjectGrantColumnGrantID, membershipGrantID)).
LeftJoin(join(ProjectGrantColumnGrantID, membershipGrantID) + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
args,
func(rows *sql.Rows) (*Memberships, error) {
+7 -5
View File
@@ -1,6 +1,7 @@
package query
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
@@ -88,7 +89,8 @@ var (
") AS memberships" +
" LEFT JOIN projections.projects3 ON memberships.project_id = projections.projects3.id AND memberships.instance_id = projections.projects3.instance_id" +
" LEFT JOIN projections.orgs ON memberships.org_id = projections.orgs.id AND memberships.instance_id = projections.orgs.instance_id" +
" LEFT JOIN projections.project_grants3 ON memberships.grant_id = projections.project_grants3.grant_id AND memberships.instance_id = projections.project_grants3.instance_id")
" LEFT JOIN projections.project_grants3 ON memberships.grant_id = projections.project_grants3.grant_id AND memberships.instance_id = projections.project_grants3.instance_id" +
` AS OF SYSTEM TIME '-1 ms'`)
membershipCols = []string{
"user_id",
"roles",
@@ -447,14 +449,14 @@ func Test_MembershipPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
func prepareMembershipWrapper(withOwnerRemoved bool) func() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) {
builder, _, fun := prepareMembershipsQuery(withOwnerRemoved)
return func() (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) {
func prepareMembershipWrapper(withOwnerRemoved bool) func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) {
return func(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*Memberships, error)) {
builder, _, fun := prepareMembershipsQuery(ctx, db, withOwnerRemoved)
return builder, fun
}
}
+7 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
@@ -84,7 +85,7 @@ func (q *Queries) GetUserMetadataByKey(ctx context.Context, shouldTriggerBulk bo
projection.UserMetadataProjection.Trigger(ctx)
}
query, scan := prepareUserMetadataQuery()
query, scan := prepareUserMetadataQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -113,7 +114,7 @@ func (q *Queries) SearchUserMetadata(ctx context.Context, shouldTriggerBulk bool
projection.UserMetadataProjection.Trigger(ctx)
}
query, scan := prepareUserMetadataListQuery()
query, scan := prepareUserMetadataListQuery(ctx, q.client)
eq := sq.Eq{
UserMetadataUserIDCol.identifier(): userID,
UserMetadataInstanceIDCol.identifier(): authz.GetInstance(ctx).InstanceID(),
@@ -163,7 +164,7 @@ func NewUserMetadataKeySearchQuery(value string, comparison TextComparison) (Sea
return NewTextQuery(UserMetadataKeyCol, value, comparison)
}
func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata, error)) {
func prepareUserMetadataQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*UserMetadata, error)) {
return sq.Select(
UserMetadataCreationDateCol.identifier(),
UserMetadataChangeDateCol.identifier(),
@@ -172,7 +173,7 @@ func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata
UserMetadataKeyCol.identifier(),
UserMetadataValueCol.identifier(),
).
From(userMetadataTable.identifier()).
From(userMetadataTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*UserMetadata, error) {
m := new(UserMetadata)
@@ -195,7 +196,7 @@ func prepareUserMetadataQuery() (sq.SelectBuilder, func(*sql.Row) (*UserMetadata
}
}
func prepareUserMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserMetadataList, error)) {
func prepareUserMetadataListQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*UserMetadataList, error)) {
return sq.Select(
UserMetadataCreationDateCol.identifier(),
UserMetadataChangeDateCol.identifier(),
@@ -204,7 +205,7 @@ func prepareUserMetadataListQuery() (sq.SelectBuilder, func(*sql.Rows) (*UserMet
UserMetadataKeyCol.identifier(),
UserMetadataValueCol.identifier(),
countColumn.identifier()).
From(userMetadataTable.identifier()).
From(userMetadataTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*UserMetadataList, error) {
metadata := make([]*UserMetadata, 0)
+3 -2
View File
@@ -18,7 +18,8 @@ var (
` projections.user_metadata4.sequence,` +
` projections.user_metadata4.key,` +
` projections.user_metadata4.value` +
` FROM projections.user_metadata4`
` FROM projections.user_metadata4` +
` AS OF SYSTEM TIME '-1 ms'`
userMetadataCols = []string{
"creation_date",
"change_date",
@@ -242,7 +243,7 @@ func Test_UserMetadataPrepares(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err, defaultPrepareArgs...)
})
}
}
+17 -13
View File
@@ -18,7 +18,7 @@ func (q *Queries) GetHumanOTPSecret(ctx context.Context, userID, resourceowner s
if userID == "" {
return "", errors.ThrowPreconditionFailed(nil, "QUERY-8N9ds", "Errors.User.UserIDMissing")
}
existingOTP, err := q.otpWriteModelByID(ctx, userID, resourceowner)
existingOTP, err := q.otpReadModelByID(ctx, userID, resourceowner)
if err != nil {
return "", err
}
@@ -29,35 +29,39 @@ func (q *Queries) GetHumanOTPSecret(ctx context.Context, userID, resourceowner s
return crypto.DecryptString(existingOTP.Secret, q.multifactors.OTP.CryptoMFA)
}
func (q *Queries) otpWriteModelByID(ctx context.Context, userID, resourceOwner string) (writeModel *HumanOTPWriteModel, err error) {
func (q *Queries) otpReadModelByID(ctx context.Context, userID, resourceOwner string) (readModel *HumanOTPReadModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewHumanOTPWriteModel(userID, resourceOwner)
err = q.eventstore.FilterToQueryReducer(ctx, writeModel)
readModel = NewHumanOTPReadModel(userID, resourceOwner)
err = q.eventstore.FilterToQueryReducer(ctx, readModel)
if err != nil {
return nil, err
}
return writeModel, nil
return readModel, nil
}
type HumanOTPWriteModel struct {
eventstore.WriteModel
type HumanOTPReadModel struct {
*eventstore.ReadModel
State domain.MFAState
Secret *crypto.CryptoValue
}
func NewHumanOTPWriteModel(userID, resourceOwner string) *HumanOTPWriteModel {
return &HumanOTPWriteModel{
WriteModel: eventstore.WriteModel{
func (rm *HumanOTPReadModel) AppendEvents(events ...eventstore.Event) {
rm.ReadModel.AppendEvents(events...)
}
func NewHumanOTPReadModel(userID, resourceOwner string) *HumanOTPReadModel {
return &HumanOTPReadModel{
ReadModel: &eventstore.ReadModel{
AggregateID: userID,
ResourceOwner: resourceOwner,
},
}
}
func (wm *HumanOTPWriteModel) Reduce() error {
func (wm *HumanOTPReadModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *user.HumanOTPAddedEvent:
@@ -71,10 +75,10 @@ func (wm *HumanOTPWriteModel) Reduce() error {
wm.State = domain.MFAStateRemoved
}
}
return wm.WriteModel.Reduce()
return wm.ReadModel.Reduce()
}
func (wm *HumanOTPWriteModel) Query() *eventstore.SearchQueryBuilder {
func (wm *HumanOTPReadModel) Query() *eventstore.SearchQueryBuilder {
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
AddQuery().
AggregateTypes(user.AggregateType).
+18 -13
View File
@@ -12,8 +12,8 @@ import (
"github.com/zitadel/zitadel/internal/telemetry/tracing"
)
type HumanPasswordWriteModel struct {
eventstore.WriteModel
type HumanPasswordReadModel struct {
*eventstore.ReadModel
Secret *crypto.CryptoValue
SecretChangeRequired bool
@@ -33,7 +33,7 @@ func (q *Queries) GetHumanPassword(ctx context.Context, orgID, userID string) (p
if userID == "" {
return nil, "", errors.ThrowInvalidArgument(nil, "QUERY-4Mfsf", "Errors.User.UserIDMissing")
}
existingPassword, err := q.passwordWriteModel(ctx, userID, orgID)
existingPassword, err := q.passwordReadModel(ctx, userID, orgID)
if err != nil {
return nil, "", errors.ThrowInternal(nil, "QUERY-p1k1n2i", "Errors.User.NotFound")
}
@@ -48,28 +48,32 @@ func (q *Queries) GetHumanPassword(ctx context.Context, orgID, userID string) (p
return nil, "", nil
}
func (q *Queries) passwordWriteModel(ctx context.Context, userID, resourceOwner string) (writeModel *HumanPasswordWriteModel, err error) {
func (q *Queries) passwordReadModel(ctx context.Context, userID, resourceOwner string) (readModel *HumanPasswordReadModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewHumanPasswordWriteModel(userID, resourceOwner)
err = q.eventstore.FilterToQueryReducer(ctx, writeModel)
readModel = NewHumanPasswordReadModel(userID, resourceOwner)
err = q.eventstore.FilterToQueryReducer(ctx, readModel)
if err != nil {
return nil, err
}
return writeModel, nil
return readModel, nil
}
func NewHumanPasswordWriteModel(userID, resourceOwner string) *HumanPasswordWriteModel {
return &HumanPasswordWriteModel{
WriteModel: eventstore.WriteModel{
func NewHumanPasswordReadModel(userID, resourceOwner string) *HumanPasswordReadModel {
return &HumanPasswordReadModel{
ReadModel: &eventstore.ReadModel{
AggregateID: userID,
ResourceOwner: resourceOwner,
},
}
}
func (wm *HumanPasswordWriteModel) Reduce() error {
func (rm *HumanPasswordReadModel) AppendEvents(events ...eventstore.Event) {
rm.ReadModel.AppendEvents(events...)
}
func (wm *HumanPasswordReadModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *user.HumanAddedEvent:
@@ -107,11 +111,12 @@ func (wm *HumanPasswordWriteModel) Reduce() error {
wm.UserState = domain.UserStateDeleted
}
}
return wm.WriteModel.Reduce()
return wm.ReadModel.Reduce()
}
func (wm *HumanPasswordWriteModel) Query() *eventstore.SearchQueryBuilder {
func (wm *HumanPasswordReadModel) Query() *eventstore.SearchQueryBuilder {
query := eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
AllowTimeTravel().
AddQuery().
AggregateTypes(user.AggregateType).
AggregateIDs(wm.AggregateID).
+9 -6
View File
@@ -9,6 +9,7 @@ import (
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
@@ -92,7 +93,7 @@ func (q *Queries) PersonalAccessTokenByID(ctx context.Context, shouldTriggerBulk
projection.PersonalAccessTokenProjection.Trigger(ctx)
}
query, scan := preparePersonalAccessTokenQuery()
query, scan := preparePersonalAccessTokenQuery(ctx, q.client)
for _, q := range queries {
query = q.toQuery(query)
}
@@ -116,7 +117,7 @@ func (q *Queries) SearchPersonalAccessTokens(ctx context.Context, queries *Perso
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
query, scan := preparePersonalAccessTokensQuery()
query, scan := preparePersonalAccessTokensQuery(ctx, q.client)
eq := sq.Eq{
PersonalAccessTokenColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID(),
}
@@ -165,7 +166,7 @@ func (q *PersonalAccessTokenSearchQueries) toQuery(query sq.SelectBuilder) sq.Se
return query
}
func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*PersonalAccessToken, error)) {
func preparePersonalAccessTokenQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Row) (*PersonalAccessToken, error)) {
return sq.Select(
PersonalAccessTokenColumnID.identifier(),
PersonalAccessTokenColumnCreationDate.identifier(),
@@ -175,7 +176,8 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso
PersonalAccessTokenColumnUserID.identifier(),
PersonalAccessTokenColumnExpiration.identifier(),
PersonalAccessTokenColumnScopes.identifier()).
From(personalAccessTokensTable.identifier()).PlaceholderFormat(sq.Dollar),
From(personalAccessTokensTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*PersonalAccessToken, error) {
p := new(PersonalAccessToken)
err := row.Scan(
@@ -198,7 +200,7 @@ func preparePersonalAccessTokenQuery() (sq.SelectBuilder, func(*sql.Row) (*Perso
}
}
func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*PersonalAccessTokens, error)) {
func preparePersonalAccessTokensQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder, func(*sql.Rows) (*PersonalAccessTokens, error)) {
return sq.Select(
PersonalAccessTokenColumnID.identifier(),
PersonalAccessTokenColumnCreationDate.identifier(),
@@ -209,7 +211,8 @@ func preparePersonalAccessTokensQuery() (sq.SelectBuilder, func(*sql.Rows) (*Per
PersonalAccessTokenColumnExpiration.identifier(),
PersonalAccessTokenColumnScopes.identifier(),
countColumn.identifier()).
From(personalAccessTokensTable.identifier()).PlaceholderFormat(sq.Dollar),
From(personalAccessTokensTable.identifier() + db.Timetravel(call.Took(ctx))).
PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*PersonalAccessTokens, error) {
personalAccessTokens := make([]*PersonalAccessToken, 0)
var count uint64

Some files were not shown because too many files have changed in this diff Show More