mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 02:54:20 +00:00
fix: permissions (#698)
* get my zitadel permissions from memberships (not grants) * change SearchMyProjectOrgs to user user_membership
This commit is contained in:
parent
a2aabe577a
commit
cca92874ab
@ -2,6 +2,7 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
@ -11,6 +12,8 @@ import (
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_view_model "github.com/caos/zitadel/internal/org/repository/view/model"
|
||||
user_model "github.com/caos/zitadel/internal/user/model"
|
||||
user_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
grant_model "github.com/caos/zitadel/internal/usergrant/model"
|
||||
"github.com/caos/zitadel/internal/usergrant/repository/view/model"
|
||||
)
|
||||
@ -63,6 +66,7 @@ func (repo *UserGrantRepo) SearchMyProjectOrgs(ctx context.Context, request *gra
|
||||
if isAdmin {
|
||||
return repo.SearchAdminOrgs(request)
|
||||
}
|
||||
return repo.searchZitadelOrgs(ctxData, request)
|
||||
}
|
||||
request.Queries = append(request.Queries, &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyProjectID, Method: global_model.SearchMethodEquals, Value: ctxData.ProjectID})
|
||||
|
||||
@ -73,35 +77,48 @@ func (repo *UserGrantRepo) SearchMyProjectOrgs(ctx context.Context, request *gra
|
||||
if len(grants.Result) > 0 {
|
||||
return grantRespToOrgResp(grants), nil
|
||||
}
|
||||
user, err := repo.View.UserByID(ctxData.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return repo.userOrg(ctxData)
|
||||
}
|
||||
|
||||
func membershipsToOrgResp(memberships []*user_view_model.UserMembershipView, count uint64) *grant_model.ProjectOrgSearchResponse {
|
||||
orgs := make([]*grant_model.Org, 0, len(memberships))
|
||||
for _, m := range memberships {
|
||||
if !containsOrg(orgs, m.ResourceOwner) {
|
||||
orgs = append(orgs, &grant_model.Org{OrgID: m.ResourceOwner, OrgName: m.ResourceOwnerName})
|
||||
}
|
||||
}
|
||||
org, err := repo.View.OrgByID(user.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &grant_model.ProjectOrgSearchResponse{
|
||||
TotalResult: count,
|
||||
Result: orgs,
|
||||
}
|
||||
return &grant_model.ProjectOrgSearchResponse{Result: []*grant_model.Org{&grant_model.Org{
|
||||
OrgID: org.ID,
|
||||
OrgName: org.Name,
|
||||
}}}, nil
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) SearchMyZitadelPermissions(ctx context.Context) ([]string, error) {
|
||||
grant, err := repo.AuthZRepo.ResolveGrants(ctx)
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
memberships, count, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{
|
||||
Queries: []*user_model.UserMembershipSearchQuery{
|
||||
{
|
||||
Key: user_model.UserMembershipSearchKeyUserID,
|
||||
Method: global_model.SearchMethodEquals,
|
||||
Value: ctxData.UserID,
|
||||
},
|
||||
{
|
||||
Key: user_model.UserMembershipSearchKeyResourceOwner,
|
||||
Method: global_model.SearchMethodEquals,
|
||||
Value: ctxData.OrgID,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if grant == nil {
|
||||
if count == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
permissions := &grant_model.Permissions{Permissions: []string{}}
|
||||
for _, role := range grant.Roles {
|
||||
roleName, ctxID := authz.SplitPermission(role)
|
||||
for _, mapping := range repo.Auth.RolePermissionMappings {
|
||||
if mapping.Role == roleName {
|
||||
permissions.AppendPermissions(ctxID, mapping.Permissions...)
|
||||
}
|
||||
for _, membership := range memberships {
|
||||
for _, role := range membership.Roles {
|
||||
permissions = repo.mapRoleToPermission(permissions, membership, role)
|
||||
}
|
||||
}
|
||||
return permissions.Permissions, nil
|
||||
@ -159,6 +176,56 @@ func (repo *UserGrantRepo) UserGrantsByProjectAndUserID(projectID, userID string
|
||||
return model.UserGrantsToModel(grants), nil
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) userOrg(ctxData authz.CtxData) (*grant_model.ProjectOrgSearchResponse, error) {
|
||||
user, err := repo.View.UserByID(ctxData.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
org, err := repo.View.OrgByID(user.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &grant_model.ProjectOrgSearchResponse{Result: []*grant_model.Org{&grant_model.Org{
|
||||
OrgID: org.ID,
|
||||
OrgName: org.Name,
|
||||
}}}, nil
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) searchZitadelOrgs(ctxData authz.CtxData, request *grant_model.UserGrantSearchRequest) (*grant_model.ProjectOrgSearchResponse, error) {
|
||||
memberships, count, err := repo.View.SearchUserMemberships(&user_model.UserMembershipSearchRequest{
|
||||
Offset: request.Offset,
|
||||
Limit: request.Limit,
|
||||
Asc: request.Asc,
|
||||
Queries: []*user_model.UserMembershipSearchQuery{
|
||||
{
|
||||
Key: user_model.UserMembershipSearchKeyUserID,
|
||||
Method: global_model.SearchMethodEquals,
|
||||
Value: ctxData.UserID,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(memberships) > 0 {
|
||||
return membershipsToOrgResp(memberships, count), nil
|
||||
}
|
||||
return repo.userOrg(ctxData)
|
||||
}
|
||||
|
||||
func (repo *UserGrantRepo) mapRoleToPermission(permissions *grant_model.Permissions, membership *user_view_model.UserMembershipView, role string) *grant_model.Permissions {
|
||||
for _, mapping := range repo.Auth.RolePermissionMappings {
|
||||
if mapping.Role == role {
|
||||
ctxID := ""
|
||||
if membership.MemberType == int32(user_model.MemberTypeProject) || membership.MemberType == int32(user_model.MemberTypeProjectGrant) {
|
||||
ctxID = membership.ObjectID
|
||||
}
|
||||
permissions.AppendPermissions(ctxID, mapping.Permissions...)
|
||||
}
|
||||
}
|
||||
return permissions
|
||||
}
|
||||
|
||||
func grantRespToOrgResp(grants *grant_model.UserGrantSearchResponse) *grant_model.ProjectOrgSearchResponse {
|
||||
resp := &grant_model.ProjectOrgSearchResponse{
|
||||
TotalResult: grants.TotalResult,
|
||||
@ -207,3 +274,12 @@ func addIamAdminRoles(orgRoles, iamAdminRoles []string) []string {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func containsOrg(orgs []*grant_model.Org, resourceOwner string) bool {
|
||||
for _, org := range orgs {
|
||||
if org.OrgID == resourceOwner {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, ev
|
||||
return []query.Handler{
|
||||
&User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, orgEvents: repos.OrgEvents},
|
||||
&UserSession{handler: handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount}, userEvents: repos.UserEvents},
|
||||
&UserMembership{handler: handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount}, orgEvents: repos.OrgEvents, projectEvents: repos.ProjectEvents},
|
||||
&Token{handler: handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount}, ProjectEvents: repos.ProjectEvents},
|
||||
&Key{handler: handler{view, bulkLimit, configs.cycleDuration("Key"), errorCount}},
|
||||
&Application{handler: handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount}},
|
||||
|
@ -260,10 +260,20 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st
|
||||
proj_es_model.ProjectGrantMemberRemoved:
|
||||
|
||||
grant, err := u.view.UserGrantByIDs(event.ResourceOwner, u.iamProjectID, userID)
|
||||
if err != nil {
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return u.view.DeleteUserGrant(grant.ID, event.Sequence)
|
||||
if errors.IsNotFound(err) {
|
||||
return u.view.ProcessedUserGrantSequence(event.Sequence)
|
||||
}
|
||||
if roleSuffix != "" {
|
||||
roleKeys = suffixRoles(roleSuffix, roleKeys)
|
||||
}
|
||||
if grant.RoleKeys == nil {
|
||||
return u.view.ProcessedUserGrantSequence(event.Sequence)
|
||||
}
|
||||
grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil)
|
||||
return u.view.PutUserGrant(grant, event.Sequence)
|
||||
default:
|
||||
return u.view.ProcessedUserGrantSequence(event.Sequence)
|
||||
}
|
||||
|
@ -0,0 +1,216 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
org_model "github.com/caos/zitadel/internal/org/model"
|
||||
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/caos/zitadel/internal/eventstore/spooler"
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
||||
usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
type UserMembership struct {
|
||||
handler
|
||||
orgEvents *org_event.OrgEventstore
|
||||
projectEvents *proj_event.ProjectEventstore
|
||||
}
|
||||
|
||||
const (
|
||||
userMembershipTable = "auth.user_memberships"
|
||||
)
|
||||
|
||||
func (m *UserMembership) ViewModel() string {
|
||||
return userMembershipTable
|
||||
}
|
||||
|
||||
func (m *UserMembership) EventQuery() (*models.SearchQuery, error) {
|
||||
sequence, err := m.view.GetLatestUserMembershipSequence()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate).
|
||||
LatestSequenceFilter(sequence.CurrentSequence), nil
|
||||
}
|
||||
|
||||
func (m *UserMembership) Reduce(event *models.Event) (err error) {
|
||||
switch event.AggregateType {
|
||||
case iam_es_model.IAMAggregate:
|
||||
err = m.processIam(event)
|
||||
case org_es_model.OrgAggregate:
|
||||
err = m.processOrg(event)
|
||||
case proj_es_model.ProjectAggregate:
|
||||
err = m.processProject(event)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *UserMembership) processIam(event *models.Event) (err error) {
|
||||
member := new(usr_es_model.UserMembershipView)
|
||||
err = member.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch event.Type {
|
||||
case iam_es_model.IAMMemberAdded:
|
||||
m.fillIamDisplayName(member)
|
||||
case iam_es_model.IAMMemberChanged:
|
||||
member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = member.AppendEvent(event)
|
||||
case iam_es_model.IAMMemberRemoved:
|
||||
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence)
|
||||
default:
|
||||
return m.view.ProcessedUserMembershipSequence(event.Sequence)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutUserMembership(member, event.Sequence)
|
||||
}
|
||||
|
||||
func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) {
|
||||
member.DisplayName = member.AggregateID
|
||||
member.ResourceOwnerName = member.ResourceOwner
|
||||
}
|
||||
|
||||
func (m *UserMembership) processOrg(event *models.Event) (err error) {
|
||||
member := new(usr_es_model.UserMembershipView)
|
||||
err = member.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch event.Type {
|
||||
case org_es_model.OrgMemberAdded:
|
||||
err = m.fillOrgName(member)
|
||||
case org_es_model.OrgMemberChanged:
|
||||
member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = member.AppendEvent(event)
|
||||
case org_es_model.OrgMemberRemoved:
|
||||
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence)
|
||||
case org_es_model.OrgChanged:
|
||||
err = m.updateOrgName(event)
|
||||
default:
|
||||
return m.view.ProcessedUserMembershipSequence(event.Sequence)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutUserMembership(member, event.Sequence)
|
||||
}
|
||||
|
||||
func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) {
|
||||
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(member.ResourceOwner))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
member.ResourceOwnerName = org.Name
|
||||
if member.AggregateID == org.AggregateID {
|
||||
member.DisplayName = org.Name
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UserMembership) updateOrgName(event *models.Event) error {
|
||||
org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.AggregateID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
memberships, err := m.view.UserMembershipsByResourceOwner(event.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, membership := range memberships {
|
||||
membership.ResourceOwnerName = org.Name
|
||||
if membership.AggregateID == event.AggregateID {
|
||||
membership.DisplayName = org.Name
|
||||
}
|
||||
}
|
||||
return m.view.BulkPutUserMemberships(memberships, event.Sequence)
|
||||
}
|
||||
|
||||
func (m *UserMembership) processProject(event *models.Event) (err error) {
|
||||
member := new(usr_es_model.UserMembershipView)
|
||||
err = member.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch event.Type {
|
||||
case proj_es_model.ProjectMemberAdded, proj_es_model.ProjectGrantMemberAdded:
|
||||
err = m.fillProjectDisplayName(member)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.fillOrgName(member)
|
||||
case proj_es_model.ProjectMemberChanged:
|
||||
member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = member.AppendEvent(event)
|
||||
case proj_es_model.ProjectMemberRemoved:
|
||||
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence)
|
||||
case proj_es_model.ProjectGrantMemberChanged:
|
||||
member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = member.AppendEvent(event)
|
||||
case proj_es_model.ProjectGrantMemberRemoved:
|
||||
return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence)
|
||||
case proj_es_model.ProjectChanged:
|
||||
err = m.updateProjectDisplayName(event)
|
||||
default:
|
||||
return m.view.ProcessedUserMembershipSequence(event.Sequence)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.view.PutUserMembership(member, event.Sequence)
|
||||
}
|
||||
|
||||
func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) {
|
||||
project, err := m.projectEvents.ProjectByID(context.Background(), member.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
member.DisplayName = project.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UserMembership) updateProjectDisplayName(event *models.Event) error {
|
||||
project, err := m.projectEvents.ProjectByID(context.Background(), event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
memberships, err := m.view.UserMembershipsByAggregateID(event.AggregateID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, membership := range memberships {
|
||||
membership.DisplayName = project.Name
|
||||
}
|
||||
return m.view.BulkPutUserMemberships(memberships, event.Sequence)
|
||||
}
|
||||
|
||||
func (m *UserMembership) OnError(event *models.Event, err error) error {
|
||||
logging.LogWithFields("SPOOL-Ms3fj", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgmember handler")
|
||||
return spooler.HandleError(event, err, m.view.GetLatestUserMembershipFailedEvent, m.view.ProcessedUserMembershipFailedEvent, m.view.ProcessedUserMembershipSequence, m.errorCountUntilSkip)
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
||||
"github.com/caos/zitadel/internal/user/repository/view"
|
||||
"github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
userMembershipTable = "auth.user_memberships"
|
||||
)
|
||||
|
||||
func (v *View) UserMembershipByIDs(userID, aggregateID, objectID string, memberType usr_model.MemberType) (*model.UserMembershipView, error) {
|
||||
return view.UserMembershipByIDs(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType)
|
||||
}
|
||||
|
||||
func (v *View) UserMembershipsByAggregateID(aggregateID string) ([]*model.UserMembershipView, error) {
|
||||
return view.UserMembershipsByAggregateID(v.Db, userMembershipTable, aggregateID)
|
||||
}
|
||||
|
||||
func (v *View) UserMembershipsByResourceOwner(resourceOwner string) ([]*model.UserMembershipView, error) {
|
||||
return view.UserMembershipsByResourceOwner(v.Db, userMembershipTable, resourceOwner)
|
||||
}
|
||||
|
||||
func (v *View) SearchUserMemberships(request *usr_model.UserMembershipSearchRequest) ([]*model.UserMembershipView, uint64, error) {
|
||||
return view.SearchUserMemberships(v.Db, userMembershipTable, request)
|
||||
}
|
||||
|
||||
func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64) error {
|
||||
err := view.PutUserMembership(v.Db, userMembershipTable, membership)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedUserMembershipSequence(sequence)
|
||||
}
|
||||
|
||||
func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64) error {
|
||||
err := view.PutUserMemberships(v.Db, userTable, memberships...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return v.ProcessedUserMembershipSequence(sequence)
|
||||
}
|
||||
|
||||
func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64) error {
|
||||
err := view.DeleteUserMembership(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return v.ProcessedUserMembershipSequence(eventSequence)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestUserMembershipSequence() (*repository.CurrentSequence, error) {
|
||||
return v.latestSequence(userMembershipTable)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedUserMembershipSequence(eventSequence uint64) error {
|
||||
return v.saveCurrentSequence(userMembershipTable, eventSequence)
|
||||
}
|
||||
|
||||
func (v *View) GetLatestUserMembershipFailedEvent(sequence uint64) (*repository.FailedEvent, error) {
|
||||
return v.latestFailedEvent(userMembershipTable, sequence)
|
||||
}
|
||||
|
||||
func (v *View) ProcessedUserMembershipFailedEvent(failedEvent *repository.FailedEvent) error {
|
||||
return v.saveFailedEvent(failedEvent)
|
||||
}
|
@ -13,12 +13,13 @@ type UserMembershipView struct {
|
||||
//ObjectID differs from aggregate id if obejct is sub of an aggregate
|
||||
ObjectID string
|
||||
|
||||
Roles []string
|
||||
DisplayName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
Roles []string
|
||||
DisplayName string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
ResourceOwnerName string
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
type MemberType int32
|
||||
|
@ -5,13 +5,14 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/lib/pq"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
|
||||
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
|
||||
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
|
||||
"github.com/caos/zitadel/internal/user/model"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,41 +29,28 @@ type UserMembershipView struct {
|
||||
AggregateID string `json:"-" gorm:"column:aggregate_id;primary_key"`
|
||||
ObjectID string `json:"-" gorm:"column:object_id;primary_key"`
|
||||
|
||||
Roles pq.StringArray `json:"-" gorm:"column:roles"`
|
||||
DisplayName string `json:"-" gorm:"column:display_name"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func UserMembershipFromModel(membership *model.UserMembershipView) *UserMembershipView {
|
||||
return &UserMembershipView{
|
||||
UserID: membership.UserID,
|
||||
MemberType: int32(membership.MemberType),
|
||||
AggregateID: membership.AggregateID,
|
||||
ObjectID: membership.ObjectID,
|
||||
Roles: membership.Roles,
|
||||
DisplayName: membership.DisplayName,
|
||||
ChangeDate: membership.ChangeDate,
|
||||
CreationDate: membership.CreationDate,
|
||||
ResourceOwner: membership.ResourceOwner,
|
||||
Sequence: membership.Sequence,
|
||||
}
|
||||
Roles pq.StringArray `json:"-" gorm:"column:roles"`
|
||||
DisplayName string `json:"-" gorm:"column:display_name"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
ResourceOwnerName string `json:"-" gorm:"column:resource_owner_name"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func UserMembershipToModel(membership *UserMembershipView) *model.UserMembershipView {
|
||||
return &model.UserMembershipView{
|
||||
UserID: membership.UserID,
|
||||
MemberType: model.MemberType(membership.MemberType),
|
||||
AggregateID: membership.AggregateID,
|
||||
ObjectID: membership.ObjectID,
|
||||
Roles: membership.Roles,
|
||||
DisplayName: membership.DisplayName,
|
||||
ChangeDate: membership.ChangeDate,
|
||||
CreationDate: membership.CreationDate,
|
||||
ResourceOwner: membership.ResourceOwner,
|
||||
Sequence: membership.Sequence,
|
||||
UserID: membership.UserID,
|
||||
MemberType: model.MemberType(membership.MemberType),
|
||||
AggregateID: membership.AggregateID,
|
||||
ObjectID: membership.ObjectID,
|
||||
Roles: membership.Roles,
|
||||
DisplayName: membership.DisplayName,
|
||||
ChangeDate: membership.ChangeDate,
|
||||
CreationDate: membership.CreationDate,
|
||||
ResourceOwner: membership.ResourceOwner,
|
||||
ResourceOwnerName: membership.ResourceOwnerName,
|
||||
Sequence: membership.Sequence,
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,22 +70,26 @@ func (u *UserMembershipView) AppendEvent(event *models.Event) (err error) {
|
||||
case iam_es_model.IAMMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeIam)
|
||||
err = u.setIamMemberData(event)
|
||||
case iam_es_model.IAMMemberChanged:
|
||||
case iam_es_model.IAMMemberChanged,
|
||||
iam_es_model.IAMMemberRemoved:
|
||||
err = u.setIamMemberData(event)
|
||||
case org_es_model.OrgMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeOrganisation)
|
||||
err = u.setOrgMemberData(event)
|
||||
case org_es_model.OrgMemberChanged:
|
||||
case org_es_model.OrgMemberChanged,
|
||||
org_es_model.OrgMemberRemoved:
|
||||
err = u.setOrgMemberData(event)
|
||||
case proj_es_model.ProjectMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeProject)
|
||||
err = u.setProjectMemberData(event)
|
||||
case proj_es_model.ProjectMemberChanged:
|
||||
case proj_es_model.ProjectMemberChanged,
|
||||
proj_es_model.ProjectMemberRemoved:
|
||||
err = u.setProjectMemberData(event)
|
||||
case proj_es_model.ProjectGrantMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeProjectGrant)
|
||||
err = u.setProjectMemberData(event)
|
||||
case proj_es_model.ProjectGrantMemberChanged:
|
||||
case proj_es_model.ProjectGrantMemberChanged,
|
||||
proj_es_model.ProjectGrantMemberRemoved:
|
||||
err = u.setProjectMemberData(event)
|
||||
}
|
||||
return err
|
||||
|
@ -35,6 +35,16 @@ func UserMembershipsByAggregateID(db *gorm.DB, table, aggregateID string) ([]*mo
|
||||
return memberships, err
|
||||
}
|
||||
|
||||
func UserMembershipsByResourceOwner(db *gorm.DB, table, resourceOwner string) ([]*model.UserMembershipView, error) {
|
||||
memberships := make([]*model.UserMembershipView, 0)
|
||||
aggregateIDQuery := &usr_model.UserMembershipSearchQuery{Key: usr_model.UserMembershipSearchKeyResourceOwner, Value: resourceOwner, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareSearchQuery(table, model.UserMembershipSearchRequest{
|
||||
Queries: []*usr_model.UserMembershipSearchQuery{aggregateIDQuery},
|
||||
})
|
||||
_, err := query(db, &memberships)
|
||||
return memberships, err
|
||||
}
|
||||
|
||||
func SearchUserMemberships(db *gorm.DB, table string, req *usr_model.UserMembershipSearchRequest) ([]*model.UserMembershipView, uint64, error) {
|
||||
users := make([]*model.UserMembershipView, 0)
|
||||
query := repository.PrepareSearchQuery(table, model.UserMembershipSearchRequest{Limit: req.Limit, Offset: req.Offset, Queries: req.Queries})
|
||||
|
18
migrations/cockroach/V1.11__usermembership.sql
Normal file
18
migrations/cockroach/V1.11__usermembership.sql
Normal file
@ -0,0 +1,18 @@
|
||||
CREATE TABLE auth.user_memberships (
|
||||
user_id TEXT,
|
||||
member_type SMALLINT,
|
||||
aggregate_id TEXT,
|
||||
object_id TEXT,
|
||||
|
||||
roles TEXT ARRAY,
|
||||
display_name TEXT,
|
||||
resource_owner TEXT,
|
||||
resource_owner_name TEXT,
|
||||
creation_date TIMESTAMPTZ,
|
||||
change_date TIMESTAMPTZ,
|
||||
sequence BIGINT,
|
||||
|
||||
PRIMARY KEY (user_id, member_type, aggregate_id, object_id)
|
||||
);
|
||||
|
||||
ALTER TABLE management.user_memberships ADD COLUMN resource_owner_name TEXT;
|
Loading…
Reference in New Issue
Block a user