mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:57:33 +00:00
feat: remove org (#4148)
* feat(command): remove org * refactor: imports, unused code, error handling * reduce org removed in action * add org deletion to projections * add org removal to projections * add org removal to projections * org removed projection * lint import * projections * fix: table names in tests * fix: table names in tests * logging * add org state * fix(domain): add Owner removed to object details * feat(ListQuery): add with owner removed * fix(org-delete): add bool to functions to select with owner removed * fix(org-delete): add bools to user grants with events to determine if dependencies lost owner * fix(org-delete): add unit tests for owner removed and org removed events * fix(org-delete): add handling of org remove for grants and members * fix(org-delete): correction of unit tests for owner removed * fix(org-delete): update projections, unit tests and get functions * fix(org-delete): add change date to authnkeys and owner removed to org metadata * fix(org-delete): include owner removed for login names * fix(org-delete): some column fixes in projections and build for queries with owner removed * indexes * fix(org-delete): include review changes * fix(org-delete): change user projection name after merge * fix(org-delete): include review changes for project grant where no project owner is necessary * fix(org-delete): include auth and adminapi tables with owner removed information * fix(org-delete): cleanup username and orgdomain uniqueconstraints when org is removed * fix(org-delete): add permissions for org.remove * remove unnecessary unique constraints * fix column order in primary keys * fix(org-delete): include review changes * fix(org-delete): add owner removed indexes and chang setup step to create tables * fix(org-delete): move PK order of instance_id and change added user_grant from review * fix(org-delete): no params for prepareUserQuery * change to step 6 * merge main * fix(org-delete): OldUserName rename to private * fix linting * cleanup * fix: remove org test * create prerelease * chore: delete org-delete as prerelease Co-authored-by: Stefan Benz <stefan@caos.ch> Co-authored-by: Livio Spring <livio.a@gmail.com> Co-authored-by: Fabi <38692350+hifabienne@users.noreply.github.com> Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package projection
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
@@ -10,25 +11,33 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/project"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/repository/usergrant"
|
||||
)
|
||||
|
||||
const (
|
||||
UserGrantProjectionTable = "projections.user_grants2"
|
||||
UserGrantProjectionTable = "projections.user_grants3"
|
||||
|
||||
UserGrantID = "id"
|
||||
UserGrantCreationDate = "creation_date"
|
||||
UserGrantChangeDate = "change_date"
|
||||
UserGrantSequence = "sequence"
|
||||
UserGrantState = "state"
|
||||
UserGrantResourceOwner = "resource_owner"
|
||||
UserGrantInstanceID = "instance_id"
|
||||
UserGrantUserID = "user_id"
|
||||
UserGrantProjectID = "project_id"
|
||||
UserGrantGrantID = "grant_id"
|
||||
UserGrantRoles = "roles"
|
||||
UserGrantID = "id"
|
||||
UserGrantCreationDate = "creation_date"
|
||||
UserGrantChangeDate = "change_date"
|
||||
UserGrantSequence = "sequence"
|
||||
UserGrantState = "state"
|
||||
UserGrantResourceOwner = "resource_owner"
|
||||
UserGrantInstanceID = "instance_id"
|
||||
UserGrantUserID = "user_id"
|
||||
UserGrantResourceOwnerUser = "resource_owner_user"
|
||||
UserGrantUserOwnerRemoved = "user_owner_removed"
|
||||
UserGrantProjectID = "project_id"
|
||||
UserGrantResourceOwnerProject = "resource_owner_project"
|
||||
UserGrantProjectOwnerRemoved = "project_owner_removed"
|
||||
UserGrantGrantID = "grant_id"
|
||||
UserGrantGrantedOrg = "granted_org"
|
||||
UserGrantGrantedOrgRemoved = "granted_org_removed"
|
||||
UserGrantRoles = "roles"
|
||||
UserGrantOwnerRemoved = "owner_removed"
|
||||
)
|
||||
|
||||
type userGrantProjection struct {
|
||||
@@ -49,13 +58,24 @@ func newUserGrantProjection(ctx context.Context, config crdb.StatementHandlerCon
|
||||
crdb.NewColumn(UserGrantResourceOwner, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantInstanceID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantUserID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantResourceOwnerUser, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantUserOwnerRemoved, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||
crdb.NewColumn(UserGrantProjectID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantResourceOwnerProject, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantProjectOwnerRemoved, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||
crdb.NewColumn(UserGrantGrantID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantGrantedOrg, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(UserGrantGrantedOrgRemoved, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||
crdb.NewColumn(UserGrantRoles, crdb.ColumnTypeTextArray, crdb.Nullable()),
|
||||
crdb.NewColumn(UserGrantOwnerRemoved, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||
},
|
||||
crdb.NewPrimaryKey(UserGrantInstanceID, UserGrantID),
|
||||
crdb.WithIndex(crdb.NewIndex("user_grant_user_idx", []string{UserGrantUserID})),
|
||||
crdb.WithIndex(crdb.NewIndex("user_grant_ro_idx", []string{UserGrantResourceOwner})),
|
||||
crdb.WithIndex(crdb.NewIndex("user_id", []string{UserGrantUserID})),
|
||||
crdb.WithIndex(crdb.NewIndex("resource_owner", []string{UserGrantResourceOwner})),
|
||||
crdb.WithIndex(crdb.NewIndex("owner_removed", []string{UserGrantOwnerRemoved})),
|
||||
crdb.WithIndex(crdb.NewIndex("user_owner_removed", []string{UserGrantUserOwnerRemoved})),
|
||||
crdb.WithIndex(crdb.NewIndex("project_owner_removed", []string{UserGrantProjectOwnerRemoved})),
|
||||
crdb.WithIndex(crdb.NewIndex("granted_org_removed", []string{UserGrantGrantedOrgRemoved})),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -132,6 +152,15 @@ func (p *userGrantProjection) reducers() []handler.AggregateReducer {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Aggregate: org.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: org.OrgRemovedEventType,
|
||||
Reduce: p.reduceOwnerRemoved,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Aggregate: instance.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
@@ -149,6 +178,27 @@ func (p *userGrantProjection) reduceAdded(event eventstore.Event) (*handler.Stat
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "PROJE-MQHVB", "reduce.wrong.event.type %s", usergrant.UserGrantAddedType)
|
||||
}
|
||||
|
||||
ctx := setUserGrantContext(e.Aggregate())
|
||||
userOwner, err := getResourceOwnerOfUser(ctx, p.Eventstore, e.Aggregate().InstanceID, e.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectOwner := ""
|
||||
grantOwner := ""
|
||||
if e.ProjectGrantID != "" {
|
||||
grantOwner, err = getGrantedOrgOfGrantedProject(ctx, p.Eventstore, e.Aggregate().InstanceID, e.ProjectID, e.ProjectGrantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
projectOwner, err = getResourceOwnerOfProject(ctx, p.Eventstore, e.Aggregate().InstanceID, e.ProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return crdb.NewCreateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
@@ -159,8 +209,11 @@ func (p *userGrantProjection) reduceAdded(event eventstore.Event) (*handler.Stat
|
||||
handler.NewCol(UserGrantChangeDate, e.CreationDate()),
|
||||
handler.NewCol(UserGrantSequence, e.Sequence()),
|
||||
handler.NewCol(UserGrantUserID, e.UserID),
|
||||
handler.NewCol(UserGrantResourceOwnerUser, userOwner),
|
||||
handler.NewCol(UserGrantProjectID, e.ProjectID),
|
||||
handler.NewCol(UserGrantResourceOwnerProject, projectOwner),
|
||||
handler.NewCol(UserGrantGrantID, e.ProjectGrantID),
|
||||
handler.NewCol(UserGrantGrantedOrg, grantOwner),
|
||||
handler.NewCol(UserGrantRoles, database.StringArray(e.RoleKeys)),
|
||||
handler.NewCol(UserGrantState, domain.UserGrantStateActive),
|
||||
},
|
||||
@@ -334,3 +387,129 @@ func (p *userGrantProjection) reduceProjectGrantChanged(event eventstore.Event)
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *userGrantProjection) reduceOwnerRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*org.OrgRemovedEvent)
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "PROJE-jpIvp", "reduce.wrong.event.type %s", org.OrgRemovedEventType)
|
||||
}
|
||||
|
||||
return crdb.NewMultiStatement(
|
||||
e,
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(UserGrantChangeDate, e.CreationDate()),
|
||||
handler.NewCol(UserGrantSequence, e.Sequence()),
|
||||
handler.NewCol(UserGrantOwnerRemoved, true),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(UserGrantInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(UserGrantResourceOwner, e.Aggregate().ID),
|
||||
},
|
||||
),
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(UserGrantChangeDate, e.CreationDate()),
|
||||
handler.NewCol(UserGrantSequence, e.Sequence()),
|
||||
handler.NewCol(UserGrantUserOwnerRemoved, true),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(UserGrantInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(UserGrantResourceOwnerUser, e.Aggregate().ID),
|
||||
},
|
||||
),
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(UserGrantChangeDate, e.CreationDate()),
|
||||
handler.NewCol(UserGrantSequence, e.Sequence()),
|
||||
handler.NewCol(UserGrantProjectOwnerRemoved, true),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(UserGrantInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(UserGrantResourceOwnerProject, e.Aggregate().ID),
|
||||
},
|
||||
),
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(UserGrantChangeDate, e.CreationDate()),
|
||||
handler.NewCol(UserGrantSequence, e.Sequence()),
|
||||
handler.NewCol(UserGrantGrantedOrgRemoved, true),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(UserGrantInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(UserGrantGrantedOrg, e.Aggregate().ID),
|
||||
},
|
||||
),
|
||||
), nil
|
||||
}
|
||||
|
||||
func getResourceOwnerOfUser(ctx context.Context, es *eventstore.Eventstore, instanceID, aggID string) (string, error) {
|
||||
events, err := es.Filter(
|
||||
ctx,
|
||||
eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
InstanceID(instanceID).
|
||||
AddQuery().
|
||||
AggregateTypes(user.AggregateType).
|
||||
AggregateIDs(aggID).
|
||||
EventTypes(user.HumanRegisteredType, user.HumanAddedType, user.MachineAddedEventType).
|
||||
Builder(),
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(events) != 1 {
|
||||
return "", errors.ThrowNotFound(nil, "PROJ-0I92sp", "Errors.User.NotFound")
|
||||
}
|
||||
return events[0].Aggregate().ResourceOwner, nil
|
||||
}
|
||||
|
||||
func getResourceOwnerOfProject(ctx context.Context, es *eventstore.Eventstore, instanceID, aggID string) (string, error) {
|
||||
events, err := es.Filter(
|
||||
ctx,
|
||||
eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
InstanceID(instanceID).
|
||||
AddQuery().
|
||||
AggregateTypes(project.AggregateType).
|
||||
AggregateIDs(aggID).
|
||||
EventTypes(project.ProjectAddedType).
|
||||
Builder(),
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(events) != 1 {
|
||||
return "", errors.ThrowNotFound(nil, "PROJ-0I91sp", "Errors.Project.NotFound")
|
||||
}
|
||||
return events[0].Aggregate().ResourceOwner, nil
|
||||
}
|
||||
|
||||
func getGrantedOrgOfGrantedProject(ctx context.Context, es *eventstore.Eventstore, instanceID, projectID, grantID string) (string, error) {
|
||||
events, err := es.Filter(
|
||||
ctx,
|
||||
eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
InstanceID(instanceID).
|
||||
AddQuery().
|
||||
AggregateTypes(project.AggregateType).
|
||||
AggregateIDs(projectID).
|
||||
EventTypes(project.GrantAddedType).
|
||||
EventData(map[string]interface{}{
|
||||
"grantId": grantID,
|
||||
}).
|
||||
Builder(),
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(events) != 1 {
|
||||
return "", errors.ThrowNotFound(nil, "PROJ-MoaSpw", "Errors.Grant.NotFound")
|
||||
}
|
||||
grantAddedEvent, ok := events[0].(*project.GrantAddedEvent)
|
||||
if !ok {
|
||||
return "", errors.ThrowNotFound(nil, "PROJ-P0s2o0", "Errors.Grant.NotFound")
|
||||
}
|
||||
return grantAddedEvent.GrantedOrgID, nil
|
||||
}
|
||||
|
||||
func setUserGrantContext(event eventstore.Aggregate) context.Context {
|
||||
return authz.WithInstanceID(context.Background(), event.InstanceID)
|
||||
}
|
||||
|
Reference in New Issue
Block a user