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:
Silvan
2022-11-30 17:01:17 +01:00
committed by GitHub
parent 21a4e73bb6
commit f3e6f3b23b
304 changed files with 7293 additions and 3286 deletions

View File

@@ -2,7 +2,9 @@ package projection
import (
"context"
"fmt"
"strings"
sq "github.com/Masterminds/squirrel"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
@@ -15,76 +17,160 @@ import (
)
const (
LoginNameProjectionTable = "projections.login_names"
LoginNameTableAlias = "login_names2"
LoginNameProjectionTable = "projections." + LoginNameTableAlias
LoginNameUserProjectionTable = LoginNameProjectionTable + "_" + loginNameUserSuffix
LoginNamePolicyProjectionTable = LoginNameProjectionTable + "_" + loginNamePolicySuffix
LoginNameDomainProjectionTable = LoginNameProjectionTable + "_" + loginNameDomainSuffix
LoginNameCol = "login_name"
LoginNameCol = "login_name"
LoginNameUserCol = "user_id"
LoginNameIsPrimaryCol = "is_primary"
LoginNameInstanceIDCol = "instance_id"
LoginNameOwnerRemovedUserCol = "user_owner_removed"
LoginNameOwnerRemovedPolicyCol = "policy_owner_removed"
LoginNameOwnerRemovedDomainCol = "domain_owner_removed"
usersAlias = "users"
policyCustomAlias = "policy_custom"
policyDefaultAlias = "policy_default"
policyUsersAlias = "policy_users"
domainsAlias = "domains"
domainAlias = "domain"
loginNameUserSuffix = "users"
LoginNameUserIDCol = "id"
LoginNameUserUserNameCol = "user_name"
LoginNameUserResourceOwnerCol = "resource_owner"
LoginNameUserInstanceIDCol = "instance_id"
LoginNameUserOwnerRemovedCol = "owner_removed"
loginNameDomainSuffix = "domains"
LoginNameDomainNameCol = "name"
LoginNameDomainIsPrimaryCol = "is_primary"
LoginNameDomainResourceOwnerCol = "resource_owner"
LoginNameDomainInstanceIDCol = "instance_id"
LoginNameDomainOwnerRemovedCol = "owner_removed"
loginNamePolicySuffix = "policies"
LoginNamePoliciesMustBeDomainCol = "must_be_domain"
LoginNamePoliciesIsDefaultCol = "is_default"
LoginNamePoliciesResourceOwnerCol = "resource_owner"
LoginNamePoliciesInstanceIDCol = "instance_id"
LoginNamePoliciesOwnerRemovedCol = "owner_removed"
)
var (
viewStmt = fmt.Sprintf("SELECT"+
" user_id"+
" , (CASE WHEN %[1]s THEN CONCAT(%[2]s, '@', domain) ELSE %[2]s END) AS login_name"+
" , COALESCE(%[3]s, true) AS %[3]s"+
" , %[4]s"+
" FROM ("+
" SELECT"+
" policy_users.user_id"+
" , policy_users.%[2]s"+
" , policy_users.%[5]s"+
" , policy_users.%[4]s"+
" , policy_users.%[1]s"+
" , domains.%[6]s AS domain"+
" , domains.%[3]s"+
" FROM ("+
" SELECT"+
" users.id as user_id"+
" , users.%[2]s"+
" , users.%[4]s"+
" , users.%[5]s"+
" , COALESCE(policy_custom.%[1]s, policy_default.%[1]s) AS %[1]s"+
" FROM %[7]s users"+
" LEFT JOIN %[8]s policy_custom on policy_custom.%[9]s = users.%[5]s AND policy_custom.%[10]s = users.%[4]s"+
" LEFT JOIN %[8]s policy_default on policy_default.%[11]s = true AND policy_default.%[10]s = users.%[4]s) policy_users"+
" LEFT JOIN %[12]s domains ON policy_users.%[1]s AND policy_users.%[5]s = domains.%[13]s AND policy_users.%[10]s = domains.%[14]s"+
") AS login_names;",
LoginNamePoliciesMustBeDomainCol,
LoginNameUserUserNameCol,
LoginNameDomainIsPrimaryCol,
LoginNameUserInstanceIDCol,
LoginNameUserResourceOwnerCol,
LoginNameDomainNameCol,
LoginNameUserProjectionTable,
LoginNamePolicyProjectionTable,
LoginNamePoliciesResourceOwnerCol,
LoginNamePoliciesInstanceIDCol,
LoginNamePoliciesIsDefaultCol,
LoginNameDomainProjectionTable,
LoginNameDomainResourceOwnerCol,
LoginNameDomainInstanceIDCol,
)
policyUsers = sq.Select(
alias(
col(usersAlias, LoginNameUserIDCol),
LoginNameUserCol,
),
col(usersAlias, LoginNameUserUserNameCol),
col(usersAlias, LoginNameUserInstanceIDCol),
col(usersAlias, LoginNameUserResourceOwnerCol),
alias(
coalesce(col(policyCustomAlias, LoginNamePoliciesMustBeDomainCol), col(policyDefaultAlias, LoginNamePoliciesMustBeDomainCol)),
LoginNamePoliciesMustBeDomainCol,
),
alias(col(usersAlias, LoginNameUserOwnerRemovedCol),
LoginNameOwnerRemovedUserCol),
alias(coalesce(col(policyCustomAlias, LoginNamePoliciesOwnerRemovedCol), "false"),
LoginNameOwnerRemovedPolicyCol),
).From(alias(LoginNameUserProjectionTable, usersAlias)).
LeftJoin(
leftJoin(LoginNamePolicyProjectionTable, policyCustomAlias,
eq(col(policyCustomAlias, LoginNamePoliciesResourceOwnerCol), col(usersAlias, LoginNameUserResourceOwnerCol)),
eq(col(policyCustomAlias, LoginNamePoliciesInstanceIDCol), col(usersAlias, LoginNameUserInstanceIDCol)),
),
).
LeftJoin(
leftJoin(LoginNamePolicyProjectionTable, policyDefaultAlias,
eq(col(policyDefaultAlias, LoginNamePoliciesIsDefaultCol), "true"),
eq(col(policyDefaultAlias, LoginNamePoliciesInstanceIDCol), col(usersAlias, LoginNameUserInstanceIDCol)),
),
)
loginNamesTable = sq.Select(
col(policyUsersAlias, LoginNameUserCol),
col(policyUsersAlias, LoginNameUserUserNameCol),
col(policyUsersAlias, LoginNameUserResourceOwnerCol),
alias(col(policyUsersAlias, LoginNameUserInstanceIDCol),
LoginNameInstanceIDCol),
col(policyUsersAlias, LoginNamePoliciesMustBeDomainCol),
alias(col(domainsAlias, LoginNameDomainNameCol),
domainAlias),
col(domainsAlias, LoginNameDomainIsPrimaryCol),
col(policyUsersAlias, LoginNameOwnerRemovedUserCol),
col(policyUsersAlias, LoginNameOwnerRemovedPolicyCol),
alias(coalesce(col(domainsAlias, LoginNameDomainOwnerRemovedCol), "false"),
LoginNameOwnerRemovedDomainCol),
).FromSelect(policyUsers, policyUsersAlias).
LeftJoin(
leftJoin(LoginNameDomainProjectionTable, domainsAlias,
col(policyUsersAlias, LoginNamePoliciesMustBeDomainCol),
eq(col(policyUsersAlias, LoginNameUserResourceOwnerCol), col(domainsAlias, LoginNameDomainResourceOwnerCol)),
eq(col(policyUsersAlias, LoginNamePoliciesInstanceIDCol), col(domainsAlias, LoginNameDomainInstanceIDCol)),
),
)
viewStmt, _ = sq.Select(
LoginNameUserCol,
alias(
whenThenElse(
LoginNamePoliciesMustBeDomainCol,
concat(LoginNameUserUserNameCol, "'@'", domainAlias),
LoginNameUserUserNameCol),
LoginNameCol),
alias(coalesce(LoginNameDomainIsPrimaryCol, "true"),
LoginNameIsPrimaryCol),
LoginNameInstanceIDCol,
LoginNameOwnerRemovedUserCol,
LoginNameOwnerRemovedPolicyCol,
LoginNameOwnerRemovedDomainCol,
).FromSelect(loginNamesTable, LoginNameTableAlias).MustSql()
)
func col(table, name string) string {
return table + "." + name
}
func alias(col, alias string) string {
return col + " AS " + alias
}
func coalesce(values ...string) string {
str := "COALESCE("
for i, value := range values {
if i > 0 {
str += ", "
}
str += value
}
str += ")"
return str
}
func eq(first, second string) string {
return first + " = " + second
}
func leftJoin(table, alias, on string, and ...string) string {
st := table + " " + alias + " ON " + on
for _, a := range and {
st += " AND " + a
}
return st
}
func concat(strs ...string) string {
return "CONCAT(" + strings.Join(strs, ", ") + ")"
}
func whenThenElse(when, then, el string) string {
return "(CASE WHEN " + when + " THEN " + then + " ELSE " + el + " END)"
}
type loginNameProjection struct {
crdb.StatementHandler
}
@@ -100,29 +186,35 @@ func newLoginNameProjection(ctx context.Context, config crdb.StatementHandlerCon
crdb.NewColumn(LoginNameUserUserNameCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameUserResourceOwnerCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameUserInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameUserOwnerRemovedCol, crdb.ColumnTypeBool, crdb.Default(false)),
},
crdb.NewPrimaryKey(LoginNameUserInstanceIDCol, LoginNameUserIDCol),
loginNameUserSuffix,
crdb.WithIndex(crdb.NewIndex("ro_idx", []string{LoginNameUserResourceOwnerCol})),
crdb.WithIndex(crdb.NewIndex("resource_owner", []string{LoginNameUserResourceOwnerCol})),
crdb.WithIndex(crdb.NewIndex("owner_removed", []string{LoginNameUserOwnerRemovedCol})),
),
crdb.NewSuffixedTable([]*crdb.Column{
crdb.NewColumn(LoginNameDomainNameCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameDomainIsPrimaryCol, crdb.ColumnTypeBool, crdb.Default(false)),
crdb.NewColumn(LoginNameDomainResourceOwnerCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameDomainInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNameDomainOwnerRemovedCol, crdb.ColumnTypeBool, crdb.Default(false)),
},
crdb.NewPrimaryKey(LoginNameDomainInstanceIDCol, LoginNameDomainResourceOwnerCol, LoginNameDomainNameCol),
loginNameDomainSuffix,
crdb.WithIndex(crdb.NewIndex("owner_removed", []string{LoginNameDomainOwnerRemovedCol})),
),
crdb.NewSuffixedTable([]*crdb.Column{
crdb.NewColumn(LoginNamePoliciesMustBeDomainCol, crdb.ColumnTypeBool),
crdb.NewColumn(LoginNamePoliciesIsDefaultCol, crdb.ColumnTypeBool),
crdb.NewColumn(LoginNamePoliciesResourceOwnerCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNamePoliciesInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(LoginNamePoliciesOwnerRemovedCol, crdb.ColumnTypeBool, crdb.Default(false)),
},
crdb.NewPrimaryKey(LoginNamePoliciesInstanceIDCol, LoginNamePoliciesResourceOwnerCol),
loginNamePolicySuffix,
crdb.WithIndex(crdb.NewIndex("is_default_idx", []string{LoginNamePoliciesResourceOwnerCol, LoginNamePoliciesIsDefaultCol})),
crdb.WithIndex(crdb.NewIndex("is_default", []string{LoginNamePoliciesResourceOwnerCol, LoginNamePoliciesIsDefaultCol})),
crdb.WithIndex(crdb.NewIndex("owner_removed", []string{LoginNamePoliciesOwnerRemovedCol})),
),
)
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
@@ -198,6 +290,10 @@ func (p *loginNameProjection) reducers() []handler.AggregateReducer {
Event: org.OrgDomainVerifiedEventType,
Reduce: p.reduceDomainVerified,
},
{
Event: org.OrgRemovedEventType,
Reduce: p.reduceOwnerRemoved,
},
},
},
{
@@ -469,3 +565,44 @@ func (p *loginNameProjection) reduceInstanceRemoved(event eventstore.Event) (*ha
),
), nil
}
func (p *loginNameProjection) reduceOwnerRemoved(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*org.OrgRemovedEvent)
if !ok {
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-px02mo", "reduce.wrong.event.type %s", org.OrgRemovedEventType)
}
return crdb.NewMultiStatement(
event,
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(LoginNameDomainOwnerRemovedCol, true),
},
[]handler.Condition{
handler.NewCond(LoginNameDomainInstanceIDCol, e.Aggregate().InstanceID),
handler.NewCond(LoginNameDomainResourceOwnerCol, e.Aggregate().ID),
},
crdb.WithTableSuffix(loginNameDomainSuffix),
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(LoginNamePoliciesOwnerRemovedCol, true),
},
[]handler.Condition{
handler.NewCond(LoginNamePoliciesInstanceIDCol, e.Aggregate().InstanceID),
handler.NewCond(LoginNamePoliciesResourceOwnerCol, e.Aggregate().ID),
},
crdb.WithTableSuffix(loginNamePolicySuffix),
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(LoginNameUserOwnerRemovedCol, true),
},
[]handler.Condition{
handler.NewCond(LoginNameUserInstanceIDCol, e.Aggregate().InstanceID),
handler.NewCond(LoginNameUserResourceOwnerCol, e.Aggregate().ID),
},
crdb.WithTableSuffix(loginNameUserSuffix),
),
), nil
}