mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-12 19:03:40 +00:00
fix: memberships (#633)
* feat: add iam members to memberships * fix: search project grants * fix: rename
This commit is contained in:
parent
568fa82d10
commit
f05c5bae24
@ -2,6 +2,7 @@ package management
|
||||
|
||||
import (
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/model"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/models"
|
||||
@ -47,12 +48,15 @@ func projectGrantMemberChangeToModel(member *management.ProjectGrantMemberChange
|
||||
}
|
||||
}
|
||||
|
||||
func projectGrantMemberSearchRequestsToModel(role *management.ProjectGrantMemberSearchRequest) *proj_model.ProjectGrantMemberSearchRequest {
|
||||
return &proj_model.ProjectGrantMemberSearchRequest{
|
||||
Offset: role.Offset,
|
||||
Limit: role.Limit,
|
||||
Queries: projectGrantMemberSearchQueriesToModel(role.Queries),
|
||||
func projectGrantMemberSearchRequestsToModel(memberSearch *management.ProjectGrantMemberSearchRequest) *proj_model.ProjectGrantMemberSearchRequest {
|
||||
request := &proj_model.ProjectGrantMemberSearchRequest{
|
||||
Offset: memberSearch.Offset,
|
||||
Limit: memberSearch.Limit,
|
||||
Queries: projectGrantMemberSearchQueriesToModel(memberSearch.Queries),
|
||||
}
|
||||
request.Queries = append(request.Queries, &proj_model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyProjectID, Method: model.SearchMethodEquals, Value: memberSearch.ProjectId})
|
||||
request.Queries = append(request.Queries, &proj_model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyGrantID, Method: model.SearchMethodEquals, Value: memberSearch.GrantId})
|
||||
return request
|
||||
}
|
||||
|
||||
func projectGrantMemberSearchQueriesToModel(queries []*management.ProjectGrantMemberSearchQuery) []*proj_model.ProjectGrantMemberSearchQuery {
|
||||
|
@ -2,7 +2,6 @@ package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
@ -198,7 +197,6 @@ func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*m
|
||||
|
||||
func (s *Server) SearchUserMemberships(ctx context.Context, in *management.UserMembershipSearchRequest) (*management.UserMembershipSearchResponse, error) {
|
||||
request := userMembershipSearchRequestsToModel(in)
|
||||
request.AppendResourceOwnerQuery(authz.GetCtxData(ctx).OrgID)
|
||||
request.AppendUserIDQuery(in.UserId)
|
||||
response, err := s.user.SearchUserMemberships(ctx, request)
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,7 @@ package eventstore
|
||||
const (
|
||||
projectReadPerm = "project.read"
|
||||
orgMemberReadPerm = "org.member.read"
|
||||
iamMemberReadPerm = "iam.member.read"
|
||||
projectMemberReadPerm = "project.member.read"
|
||||
projectGrantMemberReadPerm = "project.member.read"
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/view/repository"
|
||||
@ -18,11 +19,12 @@ import (
|
||||
)
|
||||
|
||||
type UserRepo struct {
|
||||
SearchLimit uint64
|
||||
UserEvents *usr_event.UserEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
OrgEvents *org_event.OrgEventstore
|
||||
View *view.View
|
||||
SearchLimit uint64
|
||||
UserEvents *usr_event.UserEventstore
|
||||
PolicyEvents *policy_event.PolicyEventstore
|
||||
OrgEvents *org_event.OrgEventstore
|
||||
View *view.View
|
||||
SystemDefaults systemdefaults.SystemDefaults
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*usr_model.UserView, error) {
|
||||
@ -220,6 +222,7 @@ func (repo *UserRepo) ChangeAddress(ctx context.Context, address *usr_model.Addr
|
||||
|
||||
func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_model.UserMembershipSearchRequest) (*usr_model.UserMembershipSearchResponse, error) {
|
||||
request.EnsureLimit(repo.SearchLimit)
|
||||
request.AppendResourceOwnerAndIamQuery(authz.GetCtxData(ctx).OrgID, repo.SystemDefaults.IamID)
|
||||
sequence, err := repo.View.GetLatestUserMembershipSequence()
|
||||
logging.Log("EVENT-Dn7sf").OnError(err).Warn("could not read latest user sequence")
|
||||
|
||||
@ -235,7 +238,7 @@ func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_mo
|
||||
result = &usr_model.UserMembershipSearchResponse{
|
||||
Offset: request.Offset,
|
||||
Limit: request.Limit,
|
||||
TotalResult: uint64(count),
|
||||
TotalResult: count,
|
||||
Result: model.UserMembershipsToModel(memberships),
|
||||
}
|
||||
if err == nil {
|
||||
@ -247,13 +250,16 @@ func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_mo
|
||||
|
||||
func handleSearchUserMembershipsPermissions(ctx context.Context, request *usr_model.UserMembershipSearchRequest, sequence *repository.CurrentSequence) *usr_model.UserMembershipSearchResponse {
|
||||
permissions := authz.GetAllPermissionsFromCtx(ctx)
|
||||
iamPerm := authz.HasGlobalExplicitPermission(permissions, iamMemberReadPerm)
|
||||
orgPerm := authz.HasGlobalExplicitPermission(permissions, orgMemberReadPerm)
|
||||
projectPerm := authz.HasGlobalExplicitPermission(permissions, projectMemberReadPerm)
|
||||
projectGrantPerm := authz.HasGlobalExplicitPermission(permissions, projectGrantMemberReadPerm)
|
||||
if orgPerm && projectPerm && projectGrantPerm {
|
||||
if iamPerm && orgPerm && projectPerm && projectGrantPerm {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !iamPerm {
|
||||
request.Queries = append(request.Queries, &usr_model.UserMembershipSearchQuery{Key: usr_model.UserMembershipSearchKeyMemberType, Method: global_model.SearchMethodNotEquals, Value: usr_model.MemberTypeIam})
|
||||
}
|
||||
if !orgPerm {
|
||||
request.Queries = append(request.Queries, &usr_model.UserMembershipSearchQuery{Key: usr_model.UserMembershipSearchKeyMemberType, Method: global_model.SearchMethodNotEquals, Value: usr_model.MemberTypeOrganisation})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ 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"
|
||||
@ -37,12 +38,14 @@ func (m *UserMembership) EventQuery() (*models.SearchQuery, error) {
|
||||
return nil, err
|
||||
}
|
||||
return es_models.NewSearchQuery().
|
||||
AggregateTypeFilter(org_es_model.OrgAggregate, proj_es_model.ProjectAggregate).
|
||||
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:
|
||||
@ -51,6 +54,36 @@ func (m *UserMembership) Reduce(event *models.Event) (err error) {
|
||||
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
|
||||
}
|
||||
|
||||
func (m *UserMembership) processOrg(event *models.Event) (err error) {
|
||||
member := new(usr_es_model.UserMembershipView)
|
||||
err = member.AppendEvent(event)
|
||||
|
@ -97,7 +97,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
|
||||
spooler: spool,
|
||||
OrgRepository: eventstore.OrgRepository{conf.SearchLimit, org, user, view, roles},
|
||||
ProjectRepo: eventstore.ProjectRepo{es, conf.SearchLimit, project, usergrant, user, view, roles},
|
||||
UserRepo: eventstore.UserRepo{conf.SearchLimit, user, policy, org, view},
|
||||
UserRepo: eventstore.UserRepo{conf.SearchLimit, user, policy, org, view, systemDefaults},
|
||||
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view},
|
||||
PolicyRepo: eventstore.PolicyRepo{policy},
|
||||
IamRepository: eventstore.IamRepository{iam},
|
||||
|
@ -10,22 +10,22 @@ import (
|
||||
)
|
||||
|
||||
func ProjectGrantMemberByIDs(db *gorm.DB, table, grantID, userID string) (*model.ProjectGrantMemberView, error) {
|
||||
role := new(model.ProjectGrantMemberView)
|
||||
grant := new(model.ProjectGrantMemberView)
|
||||
|
||||
grantIDQuery := model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyGrantID, Value: grantID, Method: global_model.SearchMethodEquals}
|
||||
userIDQuery := model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyUserID, Value: userID, Method: global_model.SearchMethodEquals}
|
||||
query := repository.PrepareGetByQuery(table, grantIDQuery, userIDQuery)
|
||||
err := query(db, role)
|
||||
err := query(db, grant)
|
||||
if caos_errs.IsNotFound(err) {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "VIEW-Sgr32", "Errors.Project.MemberNotExisting")
|
||||
}
|
||||
return role, err
|
||||
return grant, err
|
||||
}
|
||||
|
||||
func ProjectGrantMembersByProjectID(db *gorm.DB, table, projectID string) ([]*model.ProjectGrantMemberView, error) {
|
||||
members := make([]*model.ProjectGrantMemberView, 0)
|
||||
queries := []*proj_model.ProjectGrantMemberSearchQuery{
|
||||
&proj_model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyProjectID, Value: projectID, Method: global_model.SearchMethodEquals},
|
||||
{Key: proj_model.ProjectGrantMemberSearchKeyProjectID, Value: projectID, Method: global_model.SearchMethodEquals},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.ProjectGrantMemberSearchRequest{Queries: queries})
|
||||
_, err := query(db, &members)
|
||||
@ -48,7 +48,7 @@ func SearchProjectGrantMembers(db *gorm.DB, table string, req *proj_model.Projec
|
||||
func ProjectGrantMembersByUserID(db *gorm.DB, table, userID string) ([]*model.ProjectGrantMemberView, error) {
|
||||
members := make([]*model.ProjectGrantMemberView, 0)
|
||||
queries := []*proj_model.ProjectGrantMemberSearchQuery{
|
||||
&proj_model.ProjectGrantMemberSearchQuery{Key: proj_model.ProjectGrantMemberSearchKeyUserID, Value: userID, Method: global_model.SearchMethodEquals},
|
||||
{Key: proj_model.ProjectGrantMemberSearchKeyUserID, Value: userID, Method: global_model.SearchMethodEquals},
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.ProjectGrantMemberSearchRequest{Queries: queries})
|
||||
_, err := query(db, &members)
|
||||
@ -64,11 +64,11 @@ func PutProjectGrantMember(db *gorm.DB, table string, role *model.ProjectGrantMe
|
||||
}
|
||||
|
||||
func DeleteProjectGrantMember(db *gorm.DB, table, grantID, userID string) error {
|
||||
role, err := ProjectGrantMemberByIDs(db, table, grantID, userID)
|
||||
grant, err := ProjectGrantMemberByIDs(db, table, grantID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
delete := repository.PrepareDeleteByObject(table, role)
|
||||
delete := repository.PrepareDeleteByObject(table, grant)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ const (
|
||||
MemberTypeOrganisation
|
||||
MemberTypeProject
|
||||
MemberTypeProjectGrant
|
||||
MemberTypeIam
|
||||
)
|
||||
|
||||
type UserMembershipSearchRequest struct {
|
||||
@ -79,8 +80,8 @@ func (r *UserMembershipSearchRequest) GetSearchQuery(key UserMembershipSearchKey
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) AppendResourceOwnerQuery(orgID string) {
|
||||
r.Queries = append(r.Queries, &UserMembershipSearchQuery{Key: UserMembershipSearchKeyResourceOwner, Method: model.SearchMethodEquals, Value: orgID})
|
||||
func (r *UserMembershipSearchRequest) AppendResourceOwnerAndIamQuery(orgID, iamID string) {
|
||||
r.Queries = append(r.Queries, &UserMembershipSearchQuery{Key: UserMembershipSearchKeyResourceOwner, Method: model.SearchMethodIsOneOf, Value: []string{orgID, iamID}})
|
||||
}
|
||||
|
||||
func (r *UserMembershipSearchRequest) AppendUserIDQuery(userID string) {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/caos/logging"
|
||||
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"
|
||||
@ -77,6 +78,11 @@ func (u *UserMembershipView) AppendEvent(event *models.Event) (err error) {
|
||||
u.Sequence = event.Sequence
|
||||
|
||||
switch event.Type {
|
||||
case iam_es_model.IamMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeIam)
|
||||
err = u.setIamMemberData(event)
|
||||
case iam_es_model.IamMemberChanged:
|
||||
err = u.setIamMemberData(event)
|
||||
case org_es_model.OrgMemberAdded:
|
||||
u.setRootData(event, model.MemberTypeOrganisation)
|
||||
err = u.setOrgMemberData(event)
|
||||
@ -104,6 +110,17 @@ func (u *UserMembershipView) setRootData(event *models.Event, memberType model.M
|
||||
u.MemberType = int32(memberType)
|
||||
}
|
||||
|
||||
func (u *UserMembershipView) setIamMemberData(event *models.Event) error {
|
||||
member := new(iam_es_model.IamMember)
|
||||
if err := json.Unmarshal(event.Data, member); err != nil {
|
||||
logging.Log("MODEL-Ec9sf").WithError(err).Error("could not unmarshal event data")
|
||||
return caos_errs.ThrowInternal(nil, "MODEL-6jhsw", "could not unmarshal data")
|
||||
}
|
||||
u.UserID = member.UserID
|
||||
u.Roles = member.Roles
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UserMembershipView) setOrgMemberData(event *models.Event) error {
|
||||
member := new(org_es_model.OrgMember)
|
||||
if err := json.Unmarshal(event.Data, member); err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user