fix: memberships (#633)

* feat: add iam members to memberships

* fix: search project grants

* fix: rename
This commit is contained in:
Fabi 2020-08-25 16:08:51 +02:00 committed by GitHub
parent 568fa82d10
commit f05c5bae24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 26 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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"
)

View File

@ -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})
}

View File

@ -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)

View File

@ -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},

View File

@ -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)
}

View File

@ -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) {

View File

@ -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 {