mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-08 18:37:39 +00:00
feat(changes): add editor (#273)
* fix(changes): add editor to change mapper * fix(eventstore): only add latest sequence if greater 0 to query * sort order in request for changes * fix(changes): map editor for org, app and project
This commit is contained in:
parent
62b654ea18
commit
d947bb1247
@ -48,6 +48,9 @@ func (q *SearchQuery) EventTypesFilter(types ...EventType) *SearchQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *SearchQuery) LatestSequenceFilter(sequence uint64) *SearchQuery {
|
func (q *SearchQuery) LatestSequenceFilter(sequence uint64) *SearchQuery {
|
||||||
|
if sequence == 0 {
|
||||||
|
return q
|
||||||
|
}
|
||||||
sortOrder := Operation_Greater
|
sortOrder := Operation_Greater
|
||||||
if q.Desc {
|
if q.Desc {
|
||||||
sortOrder = Operation_Less
|
sortOrder = Operation_Less
|
||||||
|
@ -2,10 +2,11 @@ package eventstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/auth"
|
"github.com/caos/zitadel/internal/api/auth"
|
||||||
global_model "github.com/caos/zitadel/internal/model"
|
global_model "github.com/caos/zitadel/internal/model"
|
||||||
"github.com/caos/zitadel/internal/org/repository/view/model"
|
"github.com/caos/zitadel/internal/org/repository/view/model"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
mgmt_view "github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
||||||
@ -77,8 +78,8 @@ func (repo *OrgRepository) RemoveMyOrgDomain(ctx context.Context, domain string)
|
|||||||
return repo.OrgEventstore.RemoveOrgDomain(ctx, d)
|
return repo.OrgEventstore.RemoveOrgDomain(ctx, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*org_model.OrgChanges, error) {
|
func (repo *OrgRepository) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) {
|
||||||
changes, err := repo.OrgEventstore.OrgChanges(ctx, id, lastSequence, limit)
|
changes, err := repo.OrgEventstore.OrgChanges(ctx, id, lastSequence, limit, sortAscending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package eventstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||||
"github.com/caos/zitadel/internal/eventstore/models"
|
"github.com/caos/zitadel/internal/eventstore/models"
|
||||||
@ -10,7 +12,6 @@ import (
|
|||||||
es_proj_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
|
es_proj_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
|
||||||
usr_grant_model "github.com/caos/zitadel/internal/usergrant/model"
|
usr_grant_model "github.com/caos/zitadel/internal/usergrant/model"
|
||||||
usr_grant_event "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing"
|
usr_grant_event "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/auth"
|
"github.com/caos/zitadel/internal/api/auth"
|
||||||
global_model "github.com/caos/zitadel/internal/model"
|
global_model "github.com/caos/zitadel/internal/model"
|
||||||
@ -184,8 +185,8 @@ func (repo *ProjectRepo) SearchProjectRoles(ctx context.Context, request *proj_m
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*proj_model.ProjectChanges, error) {
|
func (repo *ProjectRepo) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ProjectChanges, error) {
|
||||||
changes, err := repo.ProjectEvents.ProjectChanges(ctx, id, lastSequence, limit)
|
changes, err := repo.ProjectEvents.ProjectChanges(ctx, id, lastSequence, limit, sortAscending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -235,8 +236,8 @@ func (repo *ProjectRepo) SearchApplications(ctx context.Context, request *proj_m
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, id string, appId string, lastSequence uint64, limit uint64) (*proj_model.ApplicationChanges, error) {
|
func (repo *ProjectRepo) ApplicationChanges(ctx context.Context, id string, appId string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ApplicationChanges, error) {
|
||||||
changes, err := repo.ProjectEvents.ApplicationChanges(ctx, id, appId, lastSequence, limit)
|
changes, err := repo.ProjectEvents.ApplicationChanges(ctx, id, appId, lastSequence, limit, sortAscending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package eventstore
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/auth"
|
"github.com/caos/zitadel/internal/api/auth"
|
||||||
@ -98,8 +99,8 @@ func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSe
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*usr_model.UserChanges, error) {
|
func (repo *UserRepo) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
|
||||||
changes, err := repo.UserEvents.UserChanges(ctx, id, lastSequence, limit)
|
changes, err := repo.UserEvents.UserChanges(ctx, id, lastSequence, limit, sortAscending)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ type OrgRepository interface {
|
|||||||
UpdateOrg(ctx context.Context, org *org_model.Org) (*org_model.Org, error)
|
UpdateOrg(ctx context.Context, org *org_model.Org) (*org_model.Org, error)
|
||||||
DeactivateOrg(ctx context.Context, id string) (*org_model.Org, error)
|
DeactivateOrg(ctx context.Context, id string) (*org_model.Org, error)
|
||||||
ReactivateOrg(ctx context.Context, id string) (*org_model.Org, error)
|
ReactivateOrg(ctx context.Context, id string) (*org_model.Org, error)
|
||||||
OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*org_model.OrgChanges, error)
|
OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error)
|
||||||
|
|
||||||
SearchMyOrgDomains(ctx context.Context, request *org_model.OrgDomainSearchRequest) (*org_model.OrgDomainSearchResponse, error)
|
SearchMyOrgDomains(ctx context.Context, request *org_model.OrgDomainSearchRequest) (*org_model.OrgDomainSearchResponse, error)
|
||||||
AddMyOrgDomain(ctx context.Context, domain *org_model.OrgDomain) (*org_model.OrgDomain, error)
|
AddMyOrgDomain(ctx context.Context, domain *org_model.OrgDomain) (*org_model.OrgDomain, error)
|
||||||
|
@ -27,7 +27,7 @@ type ProjectRepository interface {
|
|||||||
ChangeProjectRole(ctx context.Context, role *model.ProjectRole) (*model.ProjectRole, error)
|
ChangeProjectRole(ctx context.Context, role *model.ProjectRole) (*model.ProjectRole, error)
|
||||||
RemoveProjectRole(ctx context.Context, projectID, key string) error
|
RemoveProjectRole(ctx context.Context, projectID, key string) error
|
||||||
SearchProjectRoles(ctx context.Context, request *model.ProjectRoleSearchRequest) (*model.ProjectRoleSearchResponse, error)
|
SearchProjectRoles(ctx context.Context, request *model.ProjectRoleSearchRequest) (*model.ProjectRoleSearchResponse, error)
|
||||||
ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*model.ProjectChanges, error)
|
ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*model.ProjectChanges, error)
|
||||||
BulkAddProjectRole(ctx context.Context, role []*model.ProjectRole) error
|
BulkAddProjectRole(ctx context.Context, role []*model.ProjectRole) error
|
||||||
|
|
||||||
ApplicationByID(ctx context.Context, appID string) (*model.ApplicationView, error)
|
ApplicationByID(ctx context.Context, appID string) (*model.ApplicationView, error)
|
||||||
@ -39,7 +39,7 @@ type ProjectRepository interface {
|
|||||||
ChangeOIDCConfig(ctx context.Context, config *model.OIDCConfig) (*model.OIDCConfig, error)
|
ChangeOIDCConfig(ctx context.Context, config *model.OIDCConfig) (*model.OIDCConfig, error)
|
||||||
ChangeOIDConfigSecret(ctx context.Context, projectID, appID string) (*model.OIDCConfig, error)
|
ChangeOIDConfigSecret(ctx context.Context, projectID, appID string) (*model.OIDCConfig, error)
|
||||||
SearchApplications(ctx context.Context, request *model.ApplicationSearchRequest) (*model.ApplicationSearchResponse, error)
|
SearchApplications(ctx context.Context, request *model.ApplicationSearchRequest) (*model.ApplicationSearchResponse, error)
|
||||||
ApplicationChanges(ctx context.Context, id string, secId string, lastSequence uint64, limit uint64) (*model.ApplicationChanges, error)
|
ApplicationChanges(ctx context.Context, id string, secId string, lastSequence uint64, limit uint64, sortAscending bool) (*model.ApplicationChanges, error)
|
||||||
|
|
||||||
ProjectGrantByID(ctx context.Context, grantID string) (*model.ProjectGrantView, error)
|
ProjectGrantByID(ctx context.Context, grantID string) (*model.ProjectGrantView, error)
|
||||||
AddProjectGrant(ctx context.Context, grant *model.ProjectGrant) (*model.ProjectGrant, error)
|
AddProjectGrant(ctx context.Context, grant *model.ProjectGrant) (*model.ProjectGrant, error)
|
||||||
|
@ -15,7 +15,7 @@ type UserRepository interface {
|
|||||||
LockUser(ctx context.Context, id string) (*model.User, error)
|
LockUser(ctx context.Context, id string) (*model.User, error)
|
||||||
UnlockUser(ctx context.Context, id string) (*model.User, error)
|
UnlockUser(ctx context.Context, id string) (*model.User, error)
|
||||||
SearchUsers(ctx context.Context, request *model.UserSearchRequest) (*model.UserSearchResponse, error)
|
SearchUsers(ctx context.Context, request *model.UserSearchRequest) (*model.UserSearchResponse, error)
|
||||||
UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*model.UserChanges, error)
|
UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)
|
||||||
GetGlobalUserByEmail(ctx context.Context, email string) (*model.UserView, error)
|
GetGlobalUserByEmail(ctx context.Context, email string) (*model.UserView, error)
|
||||||
IsUserUnique(ctx context.Context, userName, email string) (bool, error)
|
IsUserUnique(ctx context.Context, userName, email string) (bool, error)
|
||||||
UserMfas(ctx context.Context, userID string) ([]*model.MultiFactor, error)
|
UserMfas(ctx context.Context, userID string) ([]*model.MultiFactor, error)
|
||||||
|
@ -3,9 +3,10 @@ package eventsourcing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/eventstore"
|
"github.com/caos/zitadel/internal/eventstore"
|
||||||
@ -194,8 +195,8 @@ func (es *OrgEventstore) RemoveOrgDomain(ctx context.Context, domain *org_model.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *OrgEventstore) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*org_model.OrgChanges, error) {
|
func (es *OrgEventstore) OrgChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*org_model.OrgChanges, error) {
|
||||||
query := ChangesQuery(id, lastSequence)
|
query := ChangesQuery(id, lastSequence, limit, sortAscending)
|
||||||
|
|
||||||
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -240,11 +241,17 @@ func (es *OrgEventstore) OrgChanges(ctx context.Context, id string, lastSequence
|
|||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChangesQuery(orgID string, latestSequence uint64) *es_models.SearchQuery {
|
func ChangesQuery(orgID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
|
||||||
query := es_models.NewSearchQuery().
|
query := es_models.NewSearchQuery().
|
||||||
AggregateTypeFilter(model.OrgAggregate).
|
AggregateTypeFilter(model.OrgAggregate)
|
||||||
LatestSequenceFilter(latestSequence).
|
|
||||||
AggregateIDFilter(orgID)
|
if !sortAscending {
|
||||||
|
query.OrderDesc() //TODO: configure from param
|
||||||
|
}
|
||||||
|
|
||||||
|
query.LatestSequenceFilter(latestSequence).
|
||||||
|
AggregateIDFilter(orgID).
|
||||||
|
SetLimit(limit)
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1077,7 @@ func TestChangesOrg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result, err := tt.args.es.OrgChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit)
|
result, err := tt.args.es.OrgChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit, false)
|
||||||
|
|
||||||
org := &model.Org{}
|
org := &model.Org{}
|
||||||
if result != nil && len(result.Changes) > 0 {
|
if result != nil && len(result.Changes) > 0 {
|
||||||
|
@ -32,7 +32,7 @@ func TestPasswordComplexityPolicyQuery(t *testing.T) {
|
|||||||
sequence: 0,
|
sequence: 0,
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
filterLen: 3,
|
filterLen: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -360,8 +360,8 @@ func (es *ProjectEventstore) RemoveProjectRole(ctx context.Context, role *proj_m
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *ProjectEventstore) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*proj_model.ProjectChanges, error) {
|
func (es *ProjectEventstore) ProjectChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ProjectChanges, error) {
|
||||||
query := ChangesQuery(id, lastSequence)
|
query := ChangesQuery(id, lastSequence, limit, sortAscending)
|
||||||
|
|
||||||
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -416,11 +416,16 @@ func (es *ProjectEventstore) ProjectChanges(ctx context.Context, id string, last
|
|||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChangesQuery(projID string, latestSequence uint64) *es_models.SearchQuery {
|
func ChangesQuery(projID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
|
||||||
query := es_models.NewSearchQuery().
|
query := es_models.NewSearchQuery().
|
||||||
AggregateTypeFilter(model.ProjectAggregate).
|
AggregateTypeFilter(model.ProjectAggregate)
|
||||||
LatestSequenceFilter(latestSequence).
|
if !sortAscending {
|
||||||
AggregateIDFilter(projID)
|
query.OrderDesc()
|
||||||
|
}
|
||||||
|
|
||||||
|
query.LatestSequenceFilter(latestSequence).
|
||||||
|
AggregateIDFilter(projID).
|
||||||
|
SetLimit(limit)
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,8 +538,8 @@ func (es *ProjectEventstore) RemoveApplication(ctx context.Context, app *proj_mo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *ProjectEventstore) ApplicationChanges(ctx context.Context, id string, secId string, lastSequence uint64, limit uint64) (*proj_model.ApplicationChanges, error) {
|
func (es *ProjectEventstore) ApplicationChanges(ctx context.Context, id string, secId string, lastSequence uint64, limit uint64, sortAscending bool) (*proj_model.ApplicationChanges, error) {
|
||||||
query := ChangesQuery(id, lastSequence)
|
query := ChangesQuery(id, lastSequence, limit, sortAscending)
|
||||||
|
|
||||||
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2624,7 +2624,7 @@ func TestChangesProject(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result, err := tt.args.es.ProjectChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit)
|
result, err := tt.args.es.ProjectChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit, false)
|
||||||
|
|
||||||
project := &model.Project{}
|
project := &model.Project{}
|
||||||
if result != nil && len(result.Changes) > 0 {
|
if result != nil && len(result.Changes) > 0 {
|
||||||
@ -2694,7 +2694,7 @@ func TestChangesApplication(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result, err := tt.args.es.ApplicationChanges(nil, tt.args.id, tt.args.secId, tt.args.lastSequence, tt.args.limit)
|
result, err := tt.args.es.ApplicationChanges(nil, tt.args.id, tt.args.secId, tt.args.lastSequence, tt.args.limit, false)
|
||||||
|
|
||||||
app := &model.Application{}
|
app := &model.Application{}
|
||||||
if result != nil && len(result.Changes) > 0 {
|
if result != nil && len(result.Changes) > 0 {
|
||||||
|
@ -83,7 +83,7 @@ func templatesAuth_method_mappingGoTmpl() (*asset, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1585815980, 0)}
|
info := bindataFileInfo{name: "templates/auth_method_mapping.go.tmpl", size: 1013, mode: os.FileMode(420), modTime: time.Unix(1587570988, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
@ -182,7 +182,6 @@ type bintree struct {
|
|||||||
Func func() (*asset, error)
|
Func func() (*asset, error)
|
||||||
Children map[string]*bintree
|
Children map[string]*bintree
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"templates": &bintree{nil, map[string]*bintree{
|
"templates": &bintree{nil, map[string]*bintree{
|
||||||
"auth_method_mapping.go.tmpl": &bintree{templatesAuth_method_mappingGoTmpl, map[string]*bintree{}},
|
"auth_method_mapping.go.tmpl": &bintree{templatesAuth_method_mappingGoTmpl, map[string]*bintree{}},
|
||||||
@ -235,3 +234,4 @@ func _filePath(dir, name string) string {
|
|||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,8 +279,8 @@ func (es *UserEventstore) UnlockUser(ctx context.Context, id string) (*usr_model
|
|||||||
return model.UserToModel(repoExisting), nil
|
return model.UserToModel(repoExisting), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *UserEventstore) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64) (*usr_model.UserChanges, error) {
|
func (es *UserEventstore) UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*usr_model.UserChanges, error) {
|
||||||
query := ChangesQuery(id, lastSequence)
|
query := ChangesQuery(id, lastSequence, limit, sortAscending)
|
||||||
|
|
||||||
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
events, err := es.Eventstore.FilterEvents(context.Background(), query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -325,11 +325,16 @@ func (es *UserEventstore) UserChanges(ctx context.Context, id string, lastSequen
|
|||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChangesQuery(userID string, latestSequence uint64) *es_models.SearchQuery {
|
func ChangesQuery(userID string, latestSequence, limit uint64, sortAscending bool) *es_models.SearchQuery {
|
||||||
query := es_models.NewSearchQuery().
|
query := es_models.NewSearchQuery().
|
||||||
AggregateTypeFilter(model.UserAggregate).
|
AggregateTypeFilter(model.UserAggregate)
|
||||||
LatestSequenceFilter(latestSequence).
|
if !sortAscending {
|
||||||
AggregateIDFilter(userID)
|
query.OrderDesc() //TODO: configure from param
|
||||||
|
}
|
||||||
|
|
||||||
|
query.LatestSequenceFilter(latestSequence).
|
||||||
|
AggregateIDFilter(userID).
|
||||||
|
SetLimit(limit)
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,13 @@ package eventsourcing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
|
||||||
policy_model "github.com/caos/zitadel/internal/policy/model"
|
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
org_model "github.com/caos/zitadel/internal/org/model"
|
||||||
|
policy_model "github.com/caos/zitadel/internal/policy/model"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/auth"
|
"github.com/caos/zitadel/internal/api/auth"
|
||||||
@ -3310,7 +3311,7 @@ func TestChangesUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result, err := tt.args.es.UserChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit)
|
result, err := tt.args.es.UserChanges(nil, tt.args.id, tt.args.lastSequence, tt.args.limit, false)
|
||||||
|
|
||||||
user := &model.Profile{}
|
user := &model.Profile{}
|
||||||
if result != nil && len(result.Changes) > 0 {
|
if result != nil && len(result.Changes) > 0 {
|
||||||
|
@ -73,7 +73,7 @@ func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, in *Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ApplicationChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
func (s *Server) ApplicationChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
||||||
response, err := s.project.ApplicationChanges(ctx, changesRequest.Id, changesRequest.SecId, 0, 0)
|
response, err := s.project.ApplicationChanges(ctx, changesRequest.Id, changesRequest.SecId, changesRequest.SequenceOffset, changesRequest.Limit, changesRequest.Asc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -337,6 +337,7 @@ func appChangesToMgtAPI(changes *proj_model.ApplicationChanges) (_ []*Change) {
|
|||||||
ChangeDate: change.ChangeDate,
|
ChangeDate: change.ChangeDate,
|
||||||
EventType: change.EventType,
|
EventType: change.EventType,
|
||||||
Sequence: change.Sequence,
|
Sequence: change.Sequence,
|
||||||
|
Editor: change.Modifier,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -481,6 +481,13 @@
|
|||||||
"required": false,
|
"required": false,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uint64"
|
"format": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "asc",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"format": "boolean"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1231,6 +1238,13 @@
|
|||||||
"required": false,
|
"required": false,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uint64"
|
"format": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "asc",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"format": "boolean"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1276,6 +1290,13 @@
|
|||||||
"required": false,
|
"required": false,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uint64"
|
"format": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "asc",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"format": "boolean"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -2961,6 +2982,13 @@
|
|||||||
"required": false,
|
"required": false,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uint64"
|
"format": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "asc",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"format": "boolean"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -3520,7 +3548,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "A successful response.",
|
"description": "A successful response.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/protobufStruct"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3531,19 +3559,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"protobufListValue": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"values": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/protobufValue"
|
|
||||||
},
|
|
||||||
"description": "Repeated field of dynamically typed values."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "`ListValue` is a wrapper around a repeated field of values.\n\nThe JSON representation for `ListValue` is JSON array."
|
|
||||||
},
|
|
||||||
"protobufNullValue": {
|
"protobufNullValue": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
@ -3552,51 +3567,6 @@
|
|||||||
"default": "NULL_VALUE",
|
"default": "NULL_VALUE",
|
||||||
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
"description": "`NullValue` is a singleton enumeration to represent the null value for the\n`Value` type union.\n\n The JSON representation for `NullValue` is JSON `null`.\n\n - NULL_VALUE: Null value."
|
||||||
},
|
},
|
||||||
"protobufStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"fields": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"$ref": "#/definitions/protobufValue"
|
|
||||||
},
|
|
||||||
"description": "Unordered map of dynamically typed values."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "`Struct` represents a structured data value, consisting of fields\nwhich map to dynamically typed values. In some languages, `Struct`\nmight be supported by a native representation. For example, in\nscripting languages like JS a struct is represented as an\nobject. The details of that representation are described together\nwith the proto support for the language.\n\nThe JSON representation for `Struct` is JSON object."
|
|
||||||
},
|
|
||||||
"protobufValue": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"null_value": {
|
|
||||||
"$ref": "#/definitions/protobufNullValue",
|
|
||||||
"description": "Represents a null value."
|
|
||||||
},
|
|
||||||
"number_value": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double",
|
|
||||||
"description": "Represents a double value."
|
|
||||||
},
|
|
||||||
"string_value": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Represents a string value."
|
|
||||||
},
|
|
||||||
"bool_value": {
|
|
||||||
"type": "boolean",
|
|
||||||
"format": "boolean",
|
|
||||||
"description": "Represents a boolean value."
|
|
||||||
},
|
|
||||||
"struct_value": {
|
|
||||||
"$ref": "#/definitions/protobufStruct",
|
|
||||||
"description": "Represents a structured value."
|
|
||||||
},
|
|
||||||
"list_value": {
|
|
||||||
"$ref": "#/definitions/protobufListValue",
|
|
||||||
"description": "Represents a repeated `Value`."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "`Value` represents a dynamically typed value which can be either\nnull, a number, a string, a boolean, a recursive struct value, or a\nlist of values. A producer of value is expected to set one of that\nvariants, absence of any variant indicates an error.\n\nThe JSON representation for `Value` is JSON value."
|
|
||||||
},
|
|
||||||
"v1AddOrgDomainRequest": {
|
"v1AddOrgDomainRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -3796,7 +3766,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/protobufStruct"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@ package grpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/auth"
|
"github.com/caos/zitadel/internal/api/auth"
|
||||||
"github.com/golang/protobuf/ptypes/empty"
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
)
|
)
|
||||||
@ -60,7 +61,7 @@ func (s *Server) RemoveMyOrgDomain(ctx context.Context, in *RemoveOrgDomainReque
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) OrgChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
func (s *Server) OrgChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
||||||
response, err := s.org.OrgChanges(ctx, changesRequest.Id, 0, 0)
|
response, err := s.org.OrgChanges(ctx, changesRequest.Id, changesRequest.SequenceOffset, changesRequest.Limit, changesRequest.Asc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,7 @@ func orgChangesToMgtAPI(changes *org_model.OrgChanges) (_ []*Change) {
|
|||||||
EventType: change.EventType,
|
EventType: change.EventType,
|
||||||
Sequence: change.Sequence,
|
Sequence: change.Sequence,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Editor: change.Modifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func (s *Server) SearchProjectRoles(ctx context.Context, in *ProjectRoleSearchRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ProjectChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
func (s *Server) ProjectChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
||||||
response, err := s.project.ProjectChanges(ctx, changesRequest.Id, 0, 0)
|
response, err := s.project.ProjectChanges(ctx, changesRequest.Id, changesRequest.SequenceOffset, changesRequest.Limit, changesRequest.Asc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -289,6 +289,7 @@ func projectChangesToMgtAPI(changes *proj_model.ProjectChanges) (_ []*Change) {
|
|||||||
ChangeDate: change.ChangeDate,
|
ChangeDate: change.ChangeDate,
|
||||||
EventType: change.EventType,
|
EventType: change.EventType,
|
||||||
Sequence: change.Sequence,
|
Sequence: change.Sequence,
|
||||||
|
Editor: change.Modifier,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func (s *Server) SearchUsers(ctx context.Context, in *UserSearchRequest) (*UserS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) UserChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
func (s *Server) UserChanges(ctx context.Context, changesRequest *ChangeRequest) (*Changes, error) {
|
||||||
response, err := s.user.UserChanges(ctx, changesRequest.Id, 0, 0)
|
response, err := s.user.UserChanges(ctx, changesRequest.Id, changesRequest.SequenceOffset, changesRequest.Limit, changesRequest.Asc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -504,6 +504,7 @@ func userChangesToMgtAPI(changes *usr_model.UserChanges) (_ []*Change) {
|
|||||||
EventType: change.EventType,
|
EventType: change.EventType,
|
||||||
Sequence: change.Sequence,
|
Sequence: change.Sequence,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Editor: change.Modifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1361,6 +1361,7 @@ message ChangeRequest {
|
|||||||
string sec_id = 2;
|
string sec_id = 2;
|
||||||
uint64 limit= 3;
|
uint64 limit= 3;
|
||||||
uint64 sequence_offset = 4;
|
uint64 sequence_offset = 4;
|
||||||
|
bool asc = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Changes {
|
message Changes {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user