mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 19:14:23 +00:00
aed7010508
* fix: improve scheduling * build pre-release * fix: locker * fix: user handler and print stack in case of panic in reducer * chore: remove sentry * fix: improve handler projection and implement tests * more tests * fix: race condition in tests * Update internal/eventstore/repository/sql/query.go Co-authored-by: Silvan <silvan.reusser@gmail.com> * fix: implemented suggested changes * fix: lock statement Co-authored-by: Silvan <silvan.reusser@gmail.com>
294 lines
7.3 KiB
Go
294 lines
7.3 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/zitadel/logging"
|
|
|
|
"github.com/zitadel/zitadel/internal/errors"
|
|
)
|
|
|
|
type SearchQueryFactory struct {
|
|
columns Columns
|
|
limit uint64
|
|
desc bool
|
|
queries []*query
|
|
}
|
|
|
|
type query struct {
|
|
desc bool
|
|
aggregateTypes []AggregateType
|
|
aggregateIDs []string
|
|
sequenceFrom uint64
|
|
sequenceTo uint64
|
|
eventTypes []EventType
|
|
resourceOwner string
|
|
instanceID string
|
|
ignoredInstanceIDs []string
|
|
creationDate time.Time
|
|
factory *SearchQueryFactory
|
|
}
|
|
|
|
type searchQuery struct {
|
|
Columns Columns
|
|
Limit uint64
|
|
Desc bool
|
|
Filters [][]*Filter
|
|
}
|
|
|
|
type Columns int32
|
|
|
|
const (
|
|
Columns_Event = iota
|
|
Columns_Max_Sequence
|
|
Columns_InstanceIDs
|
|
//insert new columns-types before this columnsCount because count is needed for validation
|
|
columnsCount
|
|
)
|
|
|
|
//FactoryFromSearchQuery is deprecated because it's for migration purposes. use NewSearchQueryFactory
|
|
func FactoryFromSearchQuery(q *SearchQuery) *SearchQueryFactory {
|
|
factory := &SearchQueryFactory{
|
|
columns: q.Columns,
|
|
desc: q.Desc,
|
|
limit: q.Limit,
|
|
queries: make([]*query, len(q.Queries)),
|
|
}
|
|
|
|
for i, qq := range q.Queries {
|
|
factory.queries[i] = &query{factory: factory}
|
|
for _, filter := range qq.Filters {
|
|
switch filter.field {
|
|
case Field_AggregateType:
|
|
factory.queries[i] = factory.queries[i].aggregateTypesMig(filter.value.([]AggregateType)...)
|
|
case Field_AggregateID:
|
|
if aggregateID, ok := filter.value.(string); ok {
|
|
factory.queries[i] = factory.queries[i].AggregateIDs(aggregateID)
|
|
} else if aggregateIDs, ok := filter.value.([]string); ok {
|
|
factory.queries[i] = factory.queries[i].AggregateIDs(aggregateIDs...)
|
|
}
|
|
case Field_LatestSequence:
|
|
if filter.operation == Operation_Greater {
|
|
factory.queries[i] = factory.queries[i].SequenceGreater(filter.value.(uint64))
|
|
} else {
|
|
factory.queries[i] = factory.queries[i].SequenceLess(filter.value.(uint64))
|
|
}
|
|
case Field_ResourceOwner:
|
|
factory.queries[i] = factory.queries[i].ResourceOwner(filter.value.(string))
|
|
case Field_InstanceID:
|
|
if filter.operation == Operation_Equals {
|
|
factory.queries[i] = factory.queries[i].InstanceID(filter.value.(string))
|
|
} else if filter.operation == Operation_NotIn {
|
|
factory.queries[i] = factory.queries[i].IgnoredInstanceIDs(filter.value.([]string)...)
|
|
}
|
|
case Field_EventType:
|
|
factory.queries[i] = factory.queries[i].EventTypes(filter.value.([]EventType)...)
|
|
case Field_EditorService, Field_EditorUser:
|
|
logging.WithFields("value", filter.value).Panic("field not converted to factory")
|
|
case Field_CreationDate:
|
|
factory.queries[i] = factory.queries[i].CreationDateNewer(filter.value.(time.Time))
|
|
}
|
|
}
|
|
}
|
|
|
|
return factory
|
|
}
|
|
|
|
func NewSearchQueryFactory() *SearchQueryFactory {
|
|
return &SearchQueryFactory{}
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) Columns(columns Columns) *SearchQueryFactory {
|
|
factory.columns = columns
|
|
return factory
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) Limit(limit uint64) *SearchQueryFactory {
|
|
factory.limit = limit
|
|
return factory
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) OrderDesc() *SearchQueryFactory {
|
|
factory.desc = true
|
|
return factory
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) OrderAsc() *SearchQueryFactory {
|
|
factory.desc = false
|
|
return factory
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) AddQuery() *query {
|
|
q := &query{factory: factory}
|
|
factory.queries = append(factory.queries, q)
|
|
return q
|
|
}
|
|
|
|
func (q *query) Factory() *SearchQueryFactory {
|
|
return q.factory
|
|
}
|
|
|
|
func (q *query) SequenceGreater(sequence uint64) *query {
|
|
q.sequenceFrom = sequence
|
|
return q
|
|
}
|
|
|
|
func (q *query) SequenceLess(sequence uint64) *query {
|
|
q.sequenceTo = sequence
|
|
return q
|
|
}
|
|
|
|
func (q *query) AggregateTypes(types ...AggregateType) *query {
|
|
q.aggregateTypes = types
|
|
return q
|
|
}
|
|
|
|
func (q *query) AggregateIDs(ids ...string) *query {
|
|
q.aggregateIDs = ids
|
|
return q
|
|
}
|
|
|
|
func (q *query) aggregateTypesMig(types ...AggregateType) *query {
|
|
q.aggregateTypes = types
|
|
return q
|
|
}
|
|
|
|
func (q *query) EventTypes(types ...EventType) *query {
|
|
q.eventTypes = types
|
|
return q
|
|
}
|
|
|
|
func (q *query) ResourceOwner(resourceOwner string) *query {
|
|
q.resourceOwner = resourceOwner
|
|
return q
|
|
}
|
|
|
|
func (q *query) InstanceID(instanceID string) *query {
|
|
q.instanceID = instanceID
|
|
return q
|
|
}
|
|
|
|
func (q *query) IgnoredInstanceIDs(instanceIDs ...string) *query {
|
|
q.ignoredInstanceIDs = instanceIDs
|
|
return q
|
|
}
|
|
|
|
func (q *query) CreationDateNewer(time time.Time) *query {
|
|
q.creationDate = time
|
|
return q
|
|
}
|
|
|
|
func (factory *SearchQueryFactory) Build() (*searchQuery, error) {
|
|
if factory == nil ||
|
|
len(factory.queries) < 1 ||
|
|
(factory.columns < 0 || factory.columns >= columnsCount) {
|
|
return nil, errors.ThrowPreconditionFailed(nil, "MODEL-tGAD3", "factory invalid")
|
|
}
|
|
filters := make([][]*Filter, len(factory.queries))
|
|
|
|
for i, query := range factory.queries {
|
|
for _, f := range []func() *Filter{
|
|
query.aggregateTypeFilter,
|
|
query.aggregateIDFilter,
|
|
query.sequenceFromFilter,
|
|
query.sequenceToFilter,
|
|
query.eventTypeFilter,
|
|
query.resourceOwnerFilter,
|
|
query.instanceIDFilter,
|
|
query.ignoredInstanceIDsFilter,
|
|
query.creationDateNewerFilter,
|
|
} {
|
|
if filter := f(); filter != nil {
|
|
filters[i] = append(filters[i], filter)
|
|
}
|
|
}
|
|
}
|
|
|
|
return &searchQuery{
|
|
Columns: factory.columns,
|
|
Limit: factory.limit,
|
|
Desc: factory.desc,
|
|
Filters: filters,
|
|
}, nil
|
|
}
|
|
|
|
func (q *query) aggregateIDFilter() *Filter {
|
|
if len(q.aggregateIDs) < 1 {
|
|
return nil
|
|
}
|
|
if len(q.aggregateIDs) == 1 {
|
|
return NewFilter(Field_AggregateID, q.aggregateIDs[0], Operation_Equals)
|
|
}
|
|
return NewFilter(Field_AggregateID, q.aggregateIDs, Operation_In)
|
|
}
|
|
|
|
func (q *query) eventTypeFilter() *Filter {
|
|
if len(q.eventTypes) < 1 {
|
|
return nil
|
|
}
|
|
if len(q.eventTypes) == 1 {
|
|
return NewFilter(Field_EventType, q.eventTypes[0], Operation_Equals)
|
|
}
|
|
return NewFilter(Field_EventType, q.eventTypes, Operation_In)
|
|
}
|
|
|
|
func (q *query) aggregateTypeFilter() *Filter {
|
|
if len(q.aggregateTypes) < 1 {
|
|
return nil
|
|
}
|
|
if len(q.aggregateTypes) == 1 {
|
|
return NewFilter(Field_AggregateType, q.aggregateTypes[0], Operation_Equals)
|
|
}
|
|
return NewFilter(Field_AggregateType, q.aggregateTypes, Operation_In)
|
|
}
|
|
|
|
func (q *query) sequenceFromFilter() *Filter {
|
|
if q.sequenceFrom == 0 {
|
|
return nil
|
|
}
|
|
sortOrder := Operation_Greater
|
|
if q.factory.desc {
|
|
sortOrder = Operation_Less
|
|
}
|
|
return NewFilter(Field_LatestSequence, q.sequenceFrom, sortOrder)
|
|
}
|
|
|
|
func (q *query) sequenceToFilter() *Filter {
|
|
if q.sequenceTo == 0 {
|
|
return nil
|
|
}
|
|
sortOrder := Operation_Less
|
|
if q.factory.desc {
|
|
sortOrder = Operation_Greater
|
|
}
|
|
return NewFilter(Field_LatestSequence, q.sequenceTo, sortOrder)
|
|
}
|
|
|
|
func (q *query) resourceOwnerFilter() *Filter {
|
|
if q.resourceOwner == "" {
|
|
return nil
|
|
}
|
|
return NewFilter(Field_ResourceOwner, q.resourceOwner, Operation_Equals)
|
|
}
|
|
|
|
func (q *query) instanceIDFilter() *Filter {
|
|
if q.instanceID == "" {
|
|
return nil
|
|
}
|
|
return NewFilter(Field_InstanceID, q.instanceID, Operation_Equals)
|
|
}
|
|
|
|
func (q *query) ignoredInstanceIDsFilter() *Filter {
|
|
if len(q.ignoredInstanceIDs) == 0 {
|
|
return nil
|
|
}
|
|
return NewFilter(Field_InstanceID, q.ignoredInstanceIDs, Operation_NotIn)
|
|
}
|
|
|
|
func (q *query) creationDateNewerFilter() *Filter {
|
|
if q.creationDate.IsZero() {
|
|
return nil
|
|
}
|
|
return NewFilter(Field_CreationDate, q.creationDate, Operation_Greater)
|
|
}
|