feat: user grants command side (#1191)

* fix: user grant command side

* fix: user grant command side

* fix: user grant command side check permissions

* fix: unique constraint on user grants

* fix: add usergrant

* fix: add usergrant

* fix: add usergrant

* fix: user grant remove

* Update internal/v2/command/auth_checks.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/v2/command/auth_checks.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/v2/command/project.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* Update internal/v2/command/user_grant.go

Co-authored-by: Livio Amstutz <livio.a@gmail.com>

* fix: project events

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Fabi 2021-01-22 13:31:52 +01:00 committed by GitHub
parent 28bfe72930
commit dfcb96d6a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 890 additions and 277 deletions

View File

@ -97,6 +97,7 @@ func startZitadel(configPaths []string) {
logging.Log("MAIN-FaF2r").OnError(err).Fatal("cannot read config")
ctx := context.Background()
//TODO: new eventstore config for command sie
es, err := es_int.Start(conf.Admin.Eventstore)
if err != nil {
return

View File

@ -2,7 +2,6 @@ package management
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"github.com/caos/zitadel/internal/api/authz"
@ -28,42 +27,36 @@ func (s *Server) UserGrantByID(ctx context.Context, request *management.UserGran
}
func (s *Server) CreateUserGrant(ctx context.Context, in *management.UserGrantCreate) (*management.UserGrant, error) {
user, err := s.usergrant.AddUserGrant(ctx, userGrantCreateToModel(in))
user, err := s.command.AddUserGrant(ctx, userGrantCreateToDomain(in), authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return usergrantFromModel(user), nil
return userGrantFromDomain(user), nil
}
func (s *Server) UpdateUserGrant(ctx context.Context, in *management.UserGrantUpdate) (*management.UserGrant, error) {
user, err := s.usergrant.ChangeUserGrant(ctx, userGrantUpdateToModel(in))
user, err := s.command.ChangeUserGrant(ctx, userGrantUpdateToDomain(in), authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return usergrantFromModel(user), nil
return userGrantFromDomain(user), nil
}
func (s *Server) DeactivateUserGrant(ctx context.Context, in *management.UserGrantID) (*management.UserGrant, error) {
user, err := s.usergrant.DeactivateUserGrant(ctx, in.Id)
if err != nil {
return nil, err
}
return usergrantFromModel(user), nil
func (s *Server) DeactivateUserGrant(ctx context.Context, in *management.UserGrantID) (*empty.Empty, error) {
err := s.command.DeactivateUserGrant(ctx, in.Id, authz.GetCtxData(ctx).OrgID)
return &empty.Empty{}, err
}
func (s *Server) ReactivateUserGrant(ctx context.Context, in *management.UserGrantID) (*management.UserGrant, error) {
user, err := s.usergrant.ReactivateUserGrant(ctx, in.Id)
if err != nil {
return nil, err
}
return usergrantFromModel(user), nil
func (s *Server) ReactivateUserGrant(ctx context.Context, in *management.UserGrantID) (*empty.Empty, error) {
err := s.command.ReactivateUserGrant(ctx, in.Id, authz.GetCtxData(ctx).OrgID)
return &empty.Empty{}, err
}
func (s *Server) RemoveUserGrant(ctx context.Context, in *management.UserGrantID) (*empty.Empty, error) {
err := s.usergrant.RemoveUserGrant(ctx, in.Id)
err := s.command.RemoveUserGrant(ctx, in.Id, authz.GetCtxData(ctx).OrgID)
return &empty.Empty{}, err
}
func (s *Server) BulkRemoveUserGrant(ctx context.Context, in *management.UserGrantRemoveBulk) (*empty.Empty, error) {
err := s.usergrant.BulkRemoveUserGrant(ctx, userGrantRemoveBulkToModel(in)...)
err := s.command.BulkRemoveUserGrant(ctx, userGrantRemoveBulkToModel(in), authz.GetCtxData(ctx).OrgID)
return &empty.Empty{}, err
}

View File

@ -2,44 +2,39 @@ package management
import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/golang/protobuf/ptypes"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/caos/zitadel/internal/eventstore/models"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
"github.com/caos/zitadel/pkg/grpc/management"
)
func usergrantFromModel(grant *grant_model.UserGrant) *management.UserGrant {
creationDate, err := ptypes.TimestampProto(grant.CreationDate)
logging.Log("GRPC-ki9ds").OnError(err).Debug("unable to parse timestamp")
changeDate, err := ptypes.TimestampProto(grant.ChangeDate)
logging.Log("GRPC-sl9ew").OnError(err).Debug("unable to parse timestamp")
func userGrantFromDomain(grant *domain.UserGrant) *management.UserGrant {
return &management.UserGrant{
Id: grant.AggregateID,
UserId: grant.UserID,
State: usergrantStateFromModel(grant.State),
CreationDate: creationDate,
ChangeDate: changeDate,
Sequence: grant.Sequence,
ProjectId: grant.ProjectID,
RoleKeys: grant.RoleKeys,
Id: grant.AggregateID,
UserId: grant.UserID,
State: usergrantStateFromDomain(grant.State),
ChangeDate: timestamppb.New(grant.ChangeDate),
Sequence: grant.Sequence,
ProjectId: grant.ProjectID,
RoleKeys: grant.RoleKeys,
}
}
func userGrantCreateToModel(u *management.UserGrantCreate) *grant_model.UserGrant {
return &grant_model.UserGrant{
ObjectRoot: models.ObjectRoot{AggregateID: u.UserId},
UserID: u.UserId,
ProjectID: u.ProjectId,
RoleKeys: u.RoleKeys,
GrantID: u.GrantId,
func userGrantCreateToDomain(u *management.UserGrantCreate) *domain.UserGrant {
return &domain.UserGrant{
ObjectRoot: models.ObjectRoot{AggregateID: u.UserId},
UserID: u.UserId,
ProjectID: u.ProjectId,
RoleKeys: u.RoleKeys,
ProjectGrantID: u.GrantId,
}
}
func userGrantUpdateToModel(u *management.UserGrantUpdate) *grant_model.UserGrant {
return &grant_model.UserGrant{
func userGrantUpdateToDomain(u *management.UserGrantUpdate) *domain.UserGrant {
return &domain.UserGrant{
ObjectRoot: models.ObjectRoot{AggregateID: u.Id},
RoleKeys: u.RoleKeys,
}
@ -171,3 +166,14 @@ func usergrantStateFromModel(state grant_model.UserGrantState) management.UserGr
return management.UserGrantState_USERGRANTSTATE_UNSPECIFIED
}
}
func usergrantStateFromDomain(state domain.UserGrantState) management.UserGrantState {
switch state {
case domain.UserGrantStateActive:
return management.UserGrantState_USERGRANTSTATE_ACTIVE
case domain.UserGrantStateInactive:
return management.UserGrantState_USERGRANTSTATE_INACTIVE
default:
return management.UserGrantState_USERGRANTSTATE_UNSPECIFIED
}
}

View File

@ -5,7 +5,6 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
caos_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
global_model "github.com/caos/zitadel/internal/model"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
@ -28,92 +27,6 @@ func (repo *UserGrantRepo) UserGrantByID(ctx context.Context, grantID string) (*
return model.UserGrantToModel(grant), nil
}
func (repo *UserGrantRepo) AddUserGrant(ctx context.Context, grant *grant_model.UserGrant) (*grant_model.UserGrant, error) {
err := checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return nil, err
}
return repo.UserGrantEvents.AddUserGrant(ctx, grant)
}
func (repo *UserGrantRepo) ChangeUserGrant(ctx context.Context, grant *grant_model.UserGrant) (*grant_model.UserGrant, error) {
err := checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return nil, err
}
return repo.UserGrantEvents.ChangeUserGrant(ctx, grant)
}
func (repo *UserGrantRepo) DeactivateUserGrant(ctx context.Context, grantID string) (*grant_model.UserGrant, error) {
grant, err := repo.UserGrantByID(ctx, grantID)
if err != nil {
return nil, err
}
err = checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return nil, err
}
return repo.UserGrantEvents.DeactivateUserGrant(ctx, grantID)
}
func (repo *UserGrantRepo) ReactivateUserGrant(ctx context.Context, grantID string) (*grant_model.UserGrant, error) {
grant, err := repo.UserGrantByID(ctx, grantID)
if err != nil {
return nil, err
}
err = checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return nil, err
}
return repo.UserGrantEvents.ReactivateUserGrant(ctx, grantID)
}
func (repo *UserGrantRepo) RemoveUserGrant(ctx context.Context, grantID string) error {
grant, err := repo.UserGrantByID(ctx, grantID)
if err != nil {
return err
}
err = checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return err
}
return repo.UserGrantEvents.RemoveUserGrant(ctx, grantID)
}
func (repo *UserGrantRepo) BulkAddUserGrant(ctx context.Context, grants ...*grant_model.UserGrant) error {
for _, grant := range grants {
err := checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return err
}
}
return repo.UserGrantEvents.AddUserGrants(ctx, grants...)
}
func (repo *UserGrantRepo) BulkChangeUserGrant(ctx context.Context, grants ...*grant_model.UserGrant) error {
for _, grant := range grants {
err := checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return err
}
}
return repo.UserGrantEvents.ChangeUserGrants(ctx, grants...)
}
func (repo *UserGrantRepo) BulkRemoveUserGrant(ctx context.Context, grantIDs ...string) error {
for _, grantID := range grantIDs {
grant, err := repo.UserGrantByID(ctx, grantID)
if err != nil {
return err
}
err = checkExplicitPermission(ctx, grant.GrantID, grant.ProjectID)
if err != nil {
return err
}
}
return repo.UserGrantEvents.RemoveUserGrants(ctx, grantIDs...)
}
func (repo *UserGrantRepo) SearchUserGrants(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.UserGrantSearchResponse, error) {
request.EnsureLimit(repo.SearchLimit)
sequence, sequenceErr := repo.View.GetLatestUserGrantSequence("")
@ -189,34 +102,3 @@ func checkContainsPermID(ids []string, query *grant_model.UserGrantSearchQuery,
}
return nil
}
func checkExplicitPermission(ctx context.Context, grantID, projectID string) error {
permissions := authz.GetRequestPermissionsFromCtx(ctx)
if authz.HasGlobalPermission(permissions) {
return nil
}
ids := authz.GetAllPermissionCtxIDs(permissions)
containsID := false
if grantID != "" {
containsID = listContainsID(ids, grantID)
if containsID {
return nil
}
}
containsID = listContainsID(ids, projectID)
if !containsID {
return caos_errors.ThrowPermissionDenied(nil, "EVENT-Shu7e", "Errors.UserGrant.NoPermissionForProject")
}
return nil
}
func listContainsID(ids []string, id string) bool {
containsID := false
for _, i := range ids {
if i == id {
containsID = true
break
}
}
return containsID
}

View File

@ -7,14 +7,5 @@ import (
type UserGrantRepository interface {
UserGrantByID(ctx context.Context, grantID string) (*model.UserGrantView, error)
AddUserGrant(ctx context.Context, grant *model.UserGrant) (*model.UserGrant, error)
ChangeUserGrant(ctx context.Context, grant *model.UserGrant) (*model.UserGrant, error)
DeactivateUserGrant(ctx context.Context, grantID string) (*model.UserGrant, error)
ReactivateUserGrant(ctx context.Context, grantID string) (*model.UserGrant, error)
RemoveUserGrant(ctx context.Context, grantID string) error
SearchUserGrants(ctx context.Context, request *model.UserGrantSearchRequest) (*model.UserGrantSearchResponse, error)
BulkAddUserGrant(ctx context.Context, grant ...*model.UserGrant) error
BulkChangeUserGrant(ctx context.Context, grant ...*model.UserGrant) error
BulkRemoveUserGrant(ctx context.Context, grantIDs ...string) error
}

View File

@ -170,7 +170,7 @@ func GetMockManipulateProjectWithSAMLApp(ctrl *gomock.Controller) *ProjectEvents
func GetMockManipulateProjectWithGrant(ctrl *gomock.Controller) *ProjectEventstore {
data, _ := json.Marshal(model.Project{Name: "Name"})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
events := []*es_models.Event{
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectGrantAdded, Data: grantData},
@ -186,7 +186,7 @@ func GetMockManipulateProjectWithGrantExistingRole(ctrl *gomock.Controller) *Pro
data, _ := json.Marshal(model.Project{Name: "Name"})
roleData, _ := json.Marshal(model.ProjectRole{Key: "Key", DisplayName: "DisplayName", Group: "Group"})
roleData2, _ := json.Marshal(model.ProjectRole{Key: "KeyChanged", DisplayName: "DisplayName", Group: "Group"})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
events := []*es_models.Event{
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectRoleAdded, Data: roleData},
@ -202,8 +202,8 @@ func GetMockManipulateProjectWithGrantExistingRole(ctrl *gomock.Controller) *Pro
func GetMockManipulateProjectWithGrantMember(ctrl *gomock.Controller) *ProjectEventstore {
data, _ := json.Marshal(model.Project{Name: "Name"})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
memberData, _ := json.Marshal(model.ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}})
memberData, _ := json.Marshal(model.ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}})
events := []*es_models.Event{
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: data},
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectGrantAdded, Data: grantData},
@ -254,7 +254,7 @@ func GetMockProjectAppsByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
func GetMockProjectGrantByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
projectData, _ := json.Marshal(model.Project{Name: "Name"})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantID", RoleKeys: []string{"Key"}})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "ProjectGrantID", RoleKeys: []string{"Key"}})
events := []*es_models.Event{
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: projectData},
@ -267,8 +267,8 @@ func GetMockProjectGrantByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
func GetMockProjectGrantMemberByIDsOK(ctrl *gomock.Controller) *ProjectEventstore {
projectData, _ := json.Marshal(model.Project{Name: "Name"})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantID", RoleKeys: []string{"Key"}})
memberData, _ := json.Marshal(model.ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}})
grantData, _ := json.Marshal(model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "ProjectGrantID", RoleKeys: []string{"Key"}})
memberData, _ := json.Marshal(model.ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}})
events := []*es_models.Event{
&es_models.Event{AggregateID: "ID", Sequence: 1, Type: model.ProjectAdded, Data: projectData},

View File

@ -1950,11 +1950,11 @@ func TestProjectGrantByID(t *testing.T) {
name: "get grant",
args: args{
es: GetMockProjectGrantByIDsOK(ctrl),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "GrantID"},
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "ProjectGrantID"},
},
res: res{
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"Key"},
},
@ -1964,7 +1964,7 @@ func TestProjectGrantByID(t *testing.T) {
name: "no events for project",
args: args{
es: GetMockProjectByIDNoEvents(ctrl),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "GrantID"},
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "ProjectGrantID"},
},
res: res{
wantErr: true,
@ -2024,14 +2024,14 @@ func TestAddProjectGrant(t *testing.T) {
es: GetMockManipulateProjectWithRole(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"Key"},
},
},
res: res{
result: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"Key"},
},
@ -2043,7 +2043,7 @@ func TestAddProjectGrant(t *testing.T) {
es: GetMockManipulateProject(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2057,7 +2057,7 @@ func TestAddProjectGrant(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
},
},
@ -2072,7 +2072,7 @@ func TestAddProjectGrant(t *testing.T) {
es: GetMockManipulateProject(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"Key"},
},
@ -2088,7 +2088,7 @@ func TestAddProjectGrant(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"Key"},
},
@ -2135,7 +2135,7 @@ func TestRemoveProjectGrant(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
},
@ -2157,7 +2157,7 @@ func TestRemoveProjectGrant(t *testing.T) {
es: GetMockManipulateProject(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2171,7 +2171,7 @@ func TestRemoveProjectGrant(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2217,12 +2217,12 @@ func TestDeactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
result: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
State: model.ProjectGrantStateInactive,
},
},
@ -2245,7 +2245,7 @@ func TestDeactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProject(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2259,7 +2259,7 @@ func TestDeactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2311,12 +2311,12 @@ func TestReactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
result: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
State: model.ProjectGrantStateActive,
},
},
@ -2339,7 +2339,7 @@ func TestReactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProject(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2353,7 +2353,7 @@ func TestReactivateProjectGrant(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
grant: &model.ProjectGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
},
},
res: res{
@ -2402,17 +2402,17 @@ func TestProjectGrantMemberByIDs(t *testing.T) {
name: "projectgrant member from events, ok",
args: args{
es: GetMockProjectGrantMemberByIDsOK(ctrl),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "GrantID", UserID: "UserID"},
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "ProjectGrantID", UserID: "UserID"},
},
res: res{
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}},
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}},
},
},
{
name: "no project events",
args: args{
es: GetMockProjectByIDNoEvents(ctrl),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "GrantID", UserID: "UserID"},
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1}, GrantID: "ProjectGrantID", UserID: "UserID"},
},
res: res{
wantErr: true,
@ -2475,14 +2475,14 @@ func TestAddProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrantExistingRole(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
},
res: res{
result: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2508,7 +2508,7 @@ func TestAddProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2524,7 +2524,7 @@ func TestAddProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrantMember(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2543,7 +2543,7 @@ func TestAddProjectGrantMember(t *testing.T) {
t.Errorf("result has no id")
}
if !tt.res.wantErr && result.GrantID != tt.res.result.GrantID {
t.Errorf("got wrong result GrantID: expected: %v, actual: %v ", tt.res.result.GrantID, result.GrantID)
t.Errorf("got wrong result ProjectGrantID: expected: %v, actual: %v ", tt.res.result.GrantID, result.GrantID)
}
if tt.res.wantErr && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
@ -2575,14 +2575,14 @@ func TestChangeProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrantMember(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"RoleChanged"},
},
},
res: res{
result: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"RoleChanged"},
},
@ -2608,7 +2608,7 @@ func TestChangeProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2624,7 +2624,7 @@ func TestChangeProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2643,7 +2643,7 @@ func TestChangeProjectGrantMember(t *testing.T) {
t.Errorf("result has no id")
}
if !tt.res.wantErr && result.GrantID != tt.res.result.GrantID {
t.Errorf("got wrong result GrantID: expected: %v, actual: %v ", tt.res.result.GrantID, result.GrantID)
t.Errorf("got wrong result ProjectGrantID: expected: %v, actual: %v ", tt.res.result.GrantID, result.GrantID)
}
if tt.res.wantErr && !tt.res.errFunc(err) {
t.Errorf("got wrong err: %v ", err)
@ -2674,7 +2674,7 @@ func TestRemoveProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrantMember(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"RoleChanged"},
},
@ -2700,7 +2700,7 @@ func TestRemoveProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectNoEvents(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},
@ -2716,7 +2716,7 @@ func TestRemoveProjectGrantMember(t *testing.T) {
es: GetMockManipulateProjectWithGrant(ctrl),
ctx: authz.NewMockContext("orgID", "userID"),
member: &model.ProjectGrantMember{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID", Sequence: 1},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
UserID: "UserID",
Roles: []string{"Role"},
},

View File

@ -21,17 +21,17 @@ func TestAppendAddGrantMemberEvent(t *testing.T) {
name: "append add grant member",
args: args{
project: &Project{Grants: []*ProjectGrant{
&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
member: &ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}},
&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}},
event: &es_models.Event{},
},
result: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
},
}
@ -69,21 +69,21 @@ func TestAppendChangeGrantMemberEvent(t *testing.T) {
project: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
member: &ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
event: &es_models.Event{},
},
result: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}}}},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}}}}},
},
},
}
@ -120,12 +120,12 @@ func TestAppendRemoveGrantMemberEvent(t *testing.T) {
project: &Project{
Grants: []*ProjectGrant{
&ProjectGrant{
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "OrgID",
RoleKeys: []string{"Key"},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
Members: []*ProjectGrantMember{&ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Role"}}}}},
},
member: &ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
member: &ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"RoleChanged"}},
event: &es_models.Event{},
},
},

View File

@ -22,10 +22,10 @@ func TestAppendAddGrantEvent(t *testing.T) {
name: "append add grant event",
args: args{
project: &Project{},
role: &ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}},
role: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
},
}
for _, tt := range tests {
@ -59,11 +59,11 @@ func TestAppendChangeGrantEvent(t *testing.T) {
{
name: "append change grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}},
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}}}},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"KeyChanged"}}}},
},
}
for _, tt := range tests {
@ -97,8 +97,8 @@ func TestAppendRemoveGrantEvent(t *testing.T) {
{
name: "append remove role event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "GrantID"},
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrant{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
},
result: &Project{Grants: []*ProjectGrant{}},
@ -133,22 +133,22 @@ func TestAppendGrantStateEvent(t *testing.T) {
{
name: "append deactivate grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "GrantID"},
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.ProjectGrantStateInactive,
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateInactive)}}},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateInactive)}}},
},
{
name: "append reactivate grant event",
args: args{
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "GrantID"},
project: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}}}},
grant: &ProjectGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.ProjectGrantStateActive,
},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateActive)}}},
result: &Project{Grants: []*ProjectGrant{&ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"Key"}, State: int32(model.ProjectGrantStateActive)}}},
},
}
for _, tt := range tests {

View File

@ -908,10 +908,10 @@ func TestProjectRoleRemovedAggregate(t *testing.T) {
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
Name: "ProjectName",
State: int32(proj_model.ProjectStateActive),
Grants: []*model.ProjectGrant{{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"ROLE"}}},
Grants: []*model.ProjectGrant{{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{"ROLE"}}},
},
newProject: &model.ProjectRole{ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"}, Key: "Key"},
grants: []*model.ProjectGrant{{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "GrantID", GrantedOrgID: "OrgID", RoleKeys: []string{}}},
grants: []*model.ProjectGrant{{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "ProjectGrantID", GrantedOrgID: "OrgID", RoleKeys: []string{}}},
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
@ -1611,7 +1611,7 @@ func TestProjectGrantAddedAggregate(t *testing.T) {
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existingProject: &model.Project{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, Name: "ProjectName", State: int32(proj_model.ProjectStateActive)},
newProject: &model.ProjectGrant{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "GrantID", GrantedOrgID: "OrgID"},
newProject: &model.ProjectGrant{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "ProjectGrantID", GrantedOrgID: "OrgID"},
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{
@ -1696,11 +1696,11 @@ func TestProjectGrantChangedAggregate(t *testing.T) {
Name: "ProjectName",
State: int32(proj_model.ProjectStateActive),
Grants: []*model.ProjectGrant{
{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}},
{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: []string{"Key"}},
}},
newProject: &model.ProjectGrant{
ObjectRoot: models.ObjectRoot{AggregateID: "ID"},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"KeyChanged"},
},
@ -1787,11 +1787,11 @@ func TestProjectGrantRemovedAggregate(t *testing.T) {
Name: "ProjectName",
State: int32(proj_model.ProjectStateActive),
Grants: []*model.ProjectGrant{
{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID"},
{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID"},
}},
newProject: &model.ProjectGrant{
ObjectRoot: models.ObjectRoot{AggregateID: "ID"},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"KeyChanged"},
},
@ -1878,11 +1878,11 @@ func TestProjectGrantDeactivatedAggregate(t *testing.T) {
Name: "ProjectName",
State: int32(proj_model.ProjectStateActive),
Grants: []*model.ProjectGrant{
{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID"},
{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID"},
}},
newProject: &model.ProjectGrant{
ObjectRoot: models.ObjectRoot{AggregateID: "ID"},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"KeyChanged"},
},
@ -1969,11 +1969,11 @@ func TestProjectGrantReactivatedAggregate(t *testing.T) {
Name: "ProjectName",
State: int32(proj_model.ProjectStateInactive),
Grants: []*model.ProjectGrant{
{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID"},
{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID"},
}},
newProject: &model.ProjectGrant{
ObjectRoot: models.ObjectRoot{AggregateID: "ID"},
GrantID: "GrantID",
GrantID: "ProjectGrantID",
GrantedOrgID: "GrantedOrgID",
RoleKeys: []string{"KeyChanged"},
},
@ -2056,7 +2056,7 @@ func TestProjectGrantMemberAddedAggregate(t *testing.T) {
args: args{
ctx: authz.NewMockContext("orgID", "userID"),
existingProject: &model.Project{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, Name: "ProjectName", State: int32(proj_model.ProjectStateActive)},
newProject: &model.ProjectGrantMember{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "GrantID", UserID: "UserID", Roles: []string{"Roles"}},
newProject: &model.ProjectGrantMember{ObjectRoot: models.ObjectRoot{AggregateID: "ID"}, GrantID: "ProjectGrantID", UserID: "UserID", Roles: []string{"Roles"}},
aggCreator: models.NewAggregateCreator("Test"),
},
res: res{

View File

@ -27,18 +27,18 @@ func TestGrantedProjectMemberAppendEvent(t *testing.T) {
{
name: "append added member event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantMemberAdded, ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "GrantID", UserID: "UserID", Roles: pq.StringArray{"Role"}})},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantMemberAdded, ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", UserID: "UserID", Roles: pq.StringArray{"Role"}})},
member: &ProjectGrantMemberView{},
},
result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "GrantID", Roles: pq.StringArray{"Role"}},
result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"Role"}},
},
{
name: "append changed member event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantMemberAdded, ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "GrantID", Roles: pq.StringArray{"RoleChanged"}})},
member: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "GrantID", Roles: pq.StringArray{"Role"}},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantMemberAdded, ResourceOwner: "OrgID", Data: mockProjectGrantMemberData(&es_model.ProjectGrantMember{GrantID: "ProjectGrantID", Roles: pq.StringArray{"RoleChanged"}})},
member: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"Role"}},
},
result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "GrantID", Roles: pq.StringArray{"RoleChanged"}},
result: &ProjectGrantMemberView{ProjectID: "AggregateID", UserID: "UserID", GrantID: "ProjectGrantID", Roles: pq.StringArray{"RoleChanged"}},
},
}
for _, tt := range tests {
@ -51,7 +51,7 @@ func TestGrantedProjectMemberAppendEvent(t *testing.T) {
t.Errorf("got wrong result userID: expected: %v, actual: %v ", tt.result.UserID, tt.args.member.UserID)
}
if tt.args.member.GrantID != tt.result.GrantID {
t.Errorf("got wrong result GrantID: expected: %v, actual: %v ", tt.result.GrantID, tt.args.member.GrantID)
t.Errorf("got wrong result ProjectGrantID: expected: %v, actual: %v ", tt.result.GrantID, tt.args.member.GrantID)
}
if !reflect.DeepEqual(tt.args.member.Roles, tt.result.Roles) {
t.Errorf("got wrong result Roles: expected: %v, actual: %v ", tt.result.Roles, tt.args.member.Roles)

View File

@ -33,7 +33,7 @@ func TestProjectGrantAppendEvent(t *testing.T) {
{
name: "append added project grant event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantAdded, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "GrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: pq.StringArray{"Role"}})},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantAdded, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", GrantedOrgID: "GrantedOrgID", RoleKeys: pq.StringArray{"Role"}})},
project: &ProjectGrantView{},
},
result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}},
@ -41,7 +41,7 @@ func TestProjectGrantAppendEvent(t *testing.T) {
{
name: "append change project grant event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantChanged, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "GrantID", RoleKeys: pq.StringArray{"RoleChanged"}})},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantChanged, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID", RoleKeys: pq.StringArray{"RoleChanged"}})},
project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}},
},
result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"RoleChanged"}},
@ -49,7 +49,7 @@ func TestProjectGrantAppendEvent(t *testing.T) {
{
name: "append deactivate project grant event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantDeactivated, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "GrantID"})},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantDeactivated, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID"})},
project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}},
},
result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: pq.StringArray{"Role"}},
@ -57,7 +57,7 @@ func TestProjectGrantAppendEvent(t *testing.T) {
{
name: "append reactivate project grant event",
args: args{
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantReactivated, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "GrantID"})},
event: &es_models.Event{AggregateID: "AggregateID", Sequence: 1, Type: es_model.ProjectGrantReactivated, ResourceOwner: "OrgID", Data: mockProjectGrantData(&es_model.ProjectGrant{GrantID: "ProjectGrantID"})},
project: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateInactive), GrantedRoleKeys: pq.StringArray{"Role"}},
},
result: &ProjectGrantView{ProjectID: "AggregateID", ResourceOwner: "OrgID", OrgID: "GrantedOrgID", State: int32(model.ProjectStateActive), GrantedRoleKeys: pq.StringArray{"Role"}},

View File

@ -248,8 +248,10 @@ Errors:
Policy:
AlreadyExists: Policy existiert bereits
UserGrant:
AlreadyExists: Benutzer Berechtigung existiert bereits
NotFound: Benutzer Berechtigung konnte nicht gefunden werden
Invalid: Benutzer Berechtigung ist ungültig
NotChanged: Benutzer Berechtigung wurde nicht verändert
IDMissing: Id fehlt
NotActive: Benutzer Berechtigung ist nicht aktiv
NotInactive: Benutzer Berechtigung ist nicht deaktiviert

View File

@ -245,8 +245,10 @@ Errors:
Policy:
AlreadyExists: Policy already exists
UserGrant:
AlreadyExists: User grant already exists
NotFound: User grant not found
Invalid: User grant is invalid
NotChanged: User grant has not been changed
IDMissing: Id missing
NotActive: User grant is not active
NotInactive: User grant is not deactivated

View File

@ -23,7 +23,7 @@ func TestAppendGrantStateEvent(t *testing.T) {
name: "append deactivate grant event",
args: args{
grant: &UserGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID"}, UserID: "UserID", ProjectID: "ProjectID", RoleKeys: []string{"Key"}},
grantID: &UserGrantID{GrantID: "GrantID"},
grantID: &UserGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.UserGrantStateInactive,
},
@ -33,7 +33,7 @@ func TestAppendGrantStateEvent(t *testing.T) {
name: "append reactivate grant event",
args: args{
grant: &UserGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID"}, UserID: "UserID", ProjectID: "ProjectID", RoleKeys: []string{"Key"}},
grantID: &UserGrantID{GrantID: "GrantID"},
grantID: &UserGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.UserGrantStateActive,
},
@ -43,7 +43,7 @@ func TestAppendGrantStateEvent(t *testing.T) {
name: "append remove grant event",
args: args{
grant: &UserGrant{ObjectRoot: es_models.ObjectRoot{AggregateID: "ID"}, UserID: "UserID", ProjectID: "ProjectID", RoleKeys: []string{"Key"}},
grantID: &UserGrantID{GrantID: "GrantID"},
grantID: &UserGrantID{GrantID: "ProjectGrantID"},
event: &es_models.Event{},
state: model.UserGrantStateRemoved,
},

View File

@ -0,0 +1,31 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/api/authz"
caos_errors "github.com/caos/zitadel/internal/errors"
)
func checkExplicitProjectPermission(ctx context.Context, grantID, projectID string) error {
permissions := authz.GetRequestPermissionsFromCtx(ctx)
if authz.HasGlobalPermission(permissions) {
return nil
}
ids := authz.GetAllPermissionCtxIDs(permissions)
if grantID != "" && listContainsID(ids, grantID) {
return nil
}
if listContainsID(ids, projectID) {
return nil
}
return caos_errors.ThrowPermissionDenied(nil, "EVENT-Shu7e", "Errors.UserGrant.NoPermissionForProject")
}
func listContainsID(ids []string, id string) bool {
for _, i := range ids {
if i == id {
return true
}
}
return false
}

View File

@ -12,7 +12,9 @@ import (
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/org"
proj_repo "github.com/caos/zitadel/internal/v2/repository/project"
usr_repo "github.com/caos/zitadel/internal/v2/repository/user"
usr_grant_repo "github.com/caos/zitadel/internal/v2/repository/usergrant"
webauthn_helper "github.com/caos/zitadel/internal/webauthn"
)
@ -53,6 +55,8 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
iam_repo.RegisterEventMappers(repo.eventstore)
org.RegisterEventMappers(repo.eventstore)
usr_repo.RegisterEventMappers(repo.eventstore)
usr_grant_repo.RegisterEventMappers(repo.eventstore)
proj_repo.RegisterEventMappers(repo.eventstore)
//TODO: simplify!!!!
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)

View File

@ -54,6 +54,17 @@ func (r *CommandSide) getProjectByID(ctx context.Context, projectID, resourceOwn
return projectWriteModelToProject(projectWriteModel), nil
}
func (r *CommandSide) checkProjectExists(ctx context.Context, projectID, resourceOwner string) error {
projectWriteModel, err := r.getProjectWriteModelByID(ctx, projectID, resourceOwner)
if err != nil {
return err
}
if projectWriteModel.State == domain.ProjectStateUnspecified || projectWriteModel.State == domain.ProjectStateRemoved {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0fs", "Errors.Project.NotFound")
}
return nil
}
func (r *CommandSide) getProjectWriteModelByID(ctx context.Context, projectID, resourceOwner string) (*ProjectWriteModel, error) {
projectWriteModel := NewProjectWriteModel(projectID, resourceOwner)
err := r.eventstore.FilterToQueryReducer(ctx, projectWriteModel)

View File

@ -26,12 +26,6 @@ func NewProjectWriteModel(projectID string, resourceOwner string) *ProjectWriteM
func (wm *ProjectWriteModel) AppendEvents(events ...eventstore.EventReader) {
wm.WriteModel.AppendEvents(events...)
for _, event := range events {
switch e := event.(type) {
case *project.ProjectAddedEvent:
wm.WriteModel.AppendEvents(e)
}
}
}
func (wm *ProjectWriteModel) Reduce() error {

View File

@ -0,0 +1,236 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/usergrant"
"reflect"
)
func (r *CommandSide) AddUserGrant(ctx context.Context, usergrant *domain.UserGrant, resourceOwner string) (_ *domain.UserGrant, err error) {
userGrantAgg, addedUserGrant, err := r.addUserGrant(ctx, usergrant, resourceOwner)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedUserGrant, userGrantAgg)
if err != nil {
return nil, err
}
return userGrantWriteModelToUserGrant(addedUserGrant), nil
}
func (r *CommandSide) addUserGrant(ctx context.Context, userGrant *domain.UserGrant, resourceOwner string) (_ *usergrant.Aggregate, _ *UserGrantWriteModel, err error) {
err = checkExplicitProjectPermission(ctx, userGrant.ProjectGrantID, userGrant.ProjectID)
if err != nil {
return nil, nil, err
}
if !userGrant.IsValid() {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0fs", "Errors.UserGrant.Invalid")
}
exists, err := r.checkUserExists(ctx, userGrant.UserID, resourceOwner)
if err != nil {
return nil, nil, err
}
if !exists {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0fs", "Errors.User.NotFound")
}
err = r.checkProjectExists(ctx, userGrant.ProjectID, resourceOwner)
if err != nil {
return nil, nil, err
}
userGrant.AggregateID, err = r.idGenerator.Next()
if err != nil {
return nil, nil, err
}
addedUserGrant := NewUserGrantWriteModel(userGrant.AggregateID, resourceOwner)
userGrantAgg := UserGrantAggregateFromWriteModel(&addedUserGrant.WriteModel)
userGrantAgg.PushEvents(
usergrant.NewUserGrantAddedEvent(
ctx,
resourceOwner,
userGrant.UserID,
userGrant.ProjectID,
userGrant.ProjectGrantID,
userGrant.RoleKeys,
),
)
return userGrantAgg, addedUserGrant, nil
}
func (r *CommandSide) ChangeUserGrant(ctx context.Context, userGrant *domain.UserGrant, resourceOwner string) (_ *domain.UserGrant, err error) {
userGrantAgg, addedUserGrant, err := r.changeUserGrant(ctx, userGrant, resourceOwner, false)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedUserGrant, userGrantAgg)
if err != nil {
return nil, err
}
return userGrantWriteModelToUserGrant(addedUserGrant), nil
}
func (r *CommandSide) changeUserGrant(ctx context.Context, userGrant *domain.UserGrant, resourceOwner string, cascade bool) (_ *usergrant.Aggregate, _ *UserGrantWriteModel, err error) {
err = checkExplicitProjectPermission(ctx, userGrant.ProjectGrantID, userGrant.ProjectID)
if err != nil {
return nil, nil, err
}
if userGrant.IsValid() {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M0sd", "Errors.UserGrant.Invalid")
}
existingUserGrant, err := r.userGrantWriteModelByID(ctx, userGrant.AggregateID, userGrant.ResourceOwner)
if err != nil {
return nil, nil, err
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.UserGrant.NotFound")
}
if reflect.DeepEqual(existingUserGrant.RoleKeys, userGrant.RoleKeys) {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Rs8fy", "Errors.UserGrant.NotChanged")
}
changedUserGrant := NewUserGrantWriteModel(userGrant.AggregateID, resourceOwner)
userGrantAgg := UserGrantAggregateFromWriteModel(&changedUserGrant.WriteModel)
if !cascade {
userGrantAgg.PushEvents(
usergrant.NewUserGrantChangedEvent(ctx, userGrant.RoleKeys),
)
} else {
userGrantAgg.PushEvents(
usergrant.NewUserGrantCascadeChangedEvent(ctx, userGrant.RoleKeys),
)
}
return userGrantAgg, changedUserGrant, nil
}
func (r *CommandSide) DeactivateUserGrant(ctx context.Context, grantID, resourceOwner string) (err error) {
if grantID == "" || resourceOwner == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-M0dsf", "Errors.UserGrant.IDMissing")
}
existingUserGrant, err := r.userGrantWriteModelByID(ctx, grantID, resourceOwner)
if err != nil {
return err
}
err = checkExplicitProjectPermission(ctx, existingUserGrant.ProjectGrantID, existingUserGrant.ProjectID)
if err != nil {
return err
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.UserGrant.NotFound")
}
if existingUserGrant.State != domain.UserGrantStateActive {
return caos_errs.ThrowNotFound(nil, "COMMAND-1S9gx", "Errors.UserGrant.NotActive")
}
deactivateUserGrant := NewUserGrantWriteModel(grantID, resourceOwner)
userGrantAgg := UserGrantAggregateFromWriteModel(&deactivateUserGrant.WriteModel)
userGrantAgg.PushEvents(
usergrant.NewUserGrantDeactivatedEvent(ctx),
)
return r.eventstore.PushAggregate(ctx, deactivateUserGrant, userGrantAgg)
}
func (r *CommandSide) ReactivateUserGrant(ctx context.Context, grantID, resourceOwner string) (err error) {
if grantID == "" || resourceOwner == "" {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Qxy8v", "Errors.UserGrant.IDMissing")
}
existingUserGrant, err := r.userGrantWriteModelByID(ctx, grantID, resourceOwner)
if err != nil {
return err
}
err = checkExplicitProjectPermission(ctx, existingUserGrant.ProjectGrantID, existingUserGrant.ProjectID)
if err != nil {
return err
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return caos_errs.ThrowNotFound(nil, "COMMAND-Lp0gs", "Errors.UserGrant.NotFound")
}
if existingUserGrant.State != domain.UserGrantStateInactive {
return caos_errs.ThrowNotFound(nil, "COMMAND-1ML0v", "Errors.UserGrant.NotInactive")
}
deactivateUserGrant := NewUserGrantWriteModel(grantID, resourceOwner)
userGrantAgg := UserGrantAggregateFromWriteModel(&deactivateUserGrant.WriteModel)
userGrantAgg.PushEvents(
usergrant.NewUserGrantReactivatedEvent(ctx),
)
return r.eventstore.PushAggregate(ctx, deactivateUserGrant, userGrantAgg)
}
func (r *CommandSide) RemoveUserGrant(ctx context.Context, grantID, resourceOwner string) (err error) {
userGrantAgg, removeUserGrant, err := r.removeUserGrant(ctx, grantID, resourceOwner, false)
if err != nil {
return nil
}
return r.eventstore.PushAggregate(ctx, removeUserGrant, userGrantAgg)
}
func (r *CommandSide) BulkRemoveUserGrant(ctx context.Context, grantIDs []string, resourceOwner string) (err error) {
aggregates := make([]eventstore.Aggregater, len(grantIDs))
for i, grantID := range grantIDs {
userGrantAgg, _, err := r.removeUserGrant(ctx, grantID, resourceOwner, false)
if err != nil {
return nil
}
aggregates[i] = userGrantAgg
}
_, err = r.eventstore.PushAggregates(ctx, aggregates...)
return err
}
func (r *CommandSide) removeUserGrant(ctx context.Context, grantID, resourceOwner string, cascade bool) (_ *usergrant.Aggregate, _ *UserGrantWriteModel, err error) {
if grantID == "" || resourceOwner == "" {
return nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-J9sc5", "Errors.UserGrant.IDMissing")
}
existingUserGrant, err := r.userGrantWriteModelByID(ctx, grantID, resourceOwner)
if err != nil {
return nil, nil, err
}
err = checkExplicitProjectPermission(ctx, existingUserGrant.ProjectGrantID, existingUserGrant.ProjectID)
if err != nil {
return nil, nil, err
}
if existingUserGrant.State == domain.UserGrantStateUnspecified || existingUserGrant.State == domain.UserGrantStateRemoved {
return nil, nil, caos_errs.ThrowNotFound(nil, "COMMAND-1My0t", "Errors.UserGrant.NotFound")
}
//TODO: Remove Uniqueness
removeUserGrant := NewUserGrantWriteModel(grantID, resourceOwner)
userGrantAgg := UserGrantAggregateFromWriteModel(&removeUserGrant.WriteModel)
if !cascade {
userGrantAgg.PushEvents(
usergrant.NewUserGrantRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID),
)
} else {
userGrantAgg.PushEvents(
usergrant.NewUserGrantCascadeRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID),
)
}
return userGrantAgg, removeUserGrant, nil
}
func (r *CommandSide) userGrantWriteModelByID(ctx context.Context, userGrantID, resourceOwner string) (writeModel *UserGrantWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewUserGrantWriteModel(userGrantID, resourceOwner)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,14 @@
package command
import "github.com/caos/zitadel/internal/v2/domain"
func userGrantWriteModelToUserGrant(writeModel *UserGrantWriteModel) *domain.UserGrant {
return &domain.UserGrant{
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel),
UserID: writeModel.UserID,
ProjectID: writeModel.ProjectID,
ProjectGrantID: writeModel.ProjectGrantID,
RoleKeys: writeModel.RoleKeys,
State: writeModel.State,
}
}

View File

@ -0,0 +1,74 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/usergrant"
)
type UserGrantWriteModel struct {
eventstore.WriteModel
UserID string
ProjectID string
ProjectGrantID string
RoleKeys []string
State domain.UserGrantState
}
func NewUserGrantWriteModel(userGrantID string, resourceOwner string) *UserGrantWriteModel {
return &UserGrantWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: userGrantID,
ResourceOwner: resourceOwner,
},
}
}
func (wm *UserGrantWriteModel) AppendEvents(events ...eventstore.EventReader) {
wm.WriteModel.AppendEvents(events...)
}
func (wm *UserGrantWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *usergrant.UserGrantAddedEvent:
wm.UserID = e.UserID
wm.ProjectID = e.ProjectID
wm.ProjectGrantID = e.ProjectGrantID
wm.RoleKeys = e.RoleKeys
wm.State = domain.UserGrantStateActive
case *usergrant.UserGrantChangedEvent:
wm.RoleKeys = e.RoleKeys
case *usergrant.UserGrantCascadeChangedEvent:
wm.RoleKeys = e.RoleKeys
case *usergrant.UserGrantDeactivatedEvent:
if wm.State == domain.UserGrantStateRemoved {
continue
}
wm.State = domain.UserGrantStateInactive
case *usergrant.UserGrantReactivatedEvent:
if wm.State == domain.UserGrantStateRemoved {
continue
}
wm.State = domain.UserGrantStateActive
case *usergrant.UserGrantRemovedEvent:
wm.State = domain.UserGrantStateRemoved
case *usergrant.UserGrantCascadeRemovedEvent:
wm.State = domain.UserGrantStateRemoved
}
}
return nil
}
func (wm *UserGrantWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, usergrant.AggregateType).
AggregateIDs(wm.AggregateID).
ResourceOwner(wm.ResourceOwner)
}
func UserGrantAggregateFromWriteModel(wm *eventstore.WriteModel) *usergrant.Aggregate {
return &usergrant.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, usergrant.AggregateType, usergrant.AggregateVersion),
}
}

View File

@ -0,0 +1,26 @@
package domain
import es_models "github.com/caos/zitadel/internal/eventstore/models"
type UserGrant struct {
es_models.ObjectRoot
State UserGrantState
UserID string
ProjectID string
ProjectGrantID string
RoleKeys []string
}
type UserGrantState int32
const (
UserGrantStateUnspecified UserGrantState = iota
UserGrantStateActive
UserGrantStateInactive
UserGrantStateRemoved
)
func (u *UserGrant) IsValid() bool {
return u.ProjectID != "" && u.UserID != ""
}

View File

@ -0,0 +1,9 @@
package project
import (
"github.com/caos/zitadel/internal/eventstore/v2"
)
func RegisterEventMappers(es *eventstore.Eventstore) {
es.RegisterFilterEventMapper(ProjectAddedType, ProjectAddedEventMapper)
}

View File

@ -12,7 +12,7 @@ import (
const (
uniqueProjectnameTable = "project_names"
projectEventTypePrefix = eventstore.EventType("project.")
ProjectAdded = projectEventTypePrefix + "added"
ProjectAddedType = projectEventTypePrefix + "added"
ProjectChanged = projectEventTypePrefix + "changed"
ProjectDeactivated = projectEventTypePrefix + "deactivated"
ProjectReactivated = projectEventTypePrefix + "reactivated"
@ -52,7 +52,7 @@ func NewProjectAddedEvent(ctx context.Context, name, resourceOwner string) *Proj
return &ProjectAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx,
ProjectAdded,
ProjectAddedType,
resourceOwner,
),
Name: name,

View File

@ -0,0 +1,14 @@
package usergrant
import (
"github.com/caos/zitadel/internal/eventstore/v2"
)
const (
AggregateType = "usergrant"
AggregateVersion = "v1"
)
type Aggregate struct {
eventstore.Aggregate
}

View File

@ -0,0 +1,15 @@
package usergrant
import (
"github.com/caos/zitadel/internal/eventstore/v2"
)
func RegisterEventMappers(es *eventstore.Eventstore) {
es.RegisterFilterEventMapper(UserGrantAddedType, UserGrantAddedEventMapper).
RegisterFilterEventMapper(UserGrantChangedType, UserGrantChangedEventMapper).
RegisterFilterEventMapper(UserGrantCascadeChangedType, UserGrantCascadeChangedEventMapper).
RegisterFilterEventMapper(UserGrantRemovedType, UserGrantRemovedEventMapper).
RegisterFilterEventMapper(UserGrantCascadeRemovedType, UserGrantCascadeRemovedEventMapper).
RegisterFilterEventMapper(UserGrantDeactivatedType, UserGrantDeactivatedEventMapper).
RegisterFilterEventMapper(UserGrantReactivatedType, UserGrantReactivatedEventMapper)
}

View File

@ -0,0 +1,307 @@
package usergrant
import (
"context"
"encoding/json"
"fmt"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
)
const (
uniqueUserGrant = "user_grant"
userGrantEventTypePrefix = eventstore.EventType("user.grant")
UserGrantAddedType = userGrantEventTypePrefix + "added"
UserGrantChangedType = userGrantEventTypePrefix + "changed"
UserGrantCascadeChangedType = userGrantEventTypePrefix + "cascade.changed"
UserGrantRemovedType = userGrantEventTypePrefix + "removed"
UserGrantCascadeRemovedType = userGrantEventTypePrefix + "cascade.removed"
UserGrantDeactivatedType = userGrantEventTypePrefix + "deactivated"
UserGrantReactivatedType = userGrantEventTypePrefix + "reactivated"
)
func NewAddUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint(
uniqueUserGrant,
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID),
"Errors.UserGrant.AlreadyExists")
}
func NewRemoveUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint(
uniqueUserGrant,
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID))
}
type UserGrantAddedEvent struct {
eventstore.BaseEvent `json:"-"`
UserID string `json:"userId,omitempty"`
ProjectID string `json:"projectId,omitempty"`
ProjectGrantID string `json:"grantId,omitempty"`
RoleKeys []string `json:"roleKeys,omitempty"`
}
func (e *UserGrantAddedEvent) Data() interface{} {
return e
}
func (e *UserGrantAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewAddUserGrantUniqueConstraint(e.ResourceOwner(), e.UserID, e.ProjectID)}
}
func NewUserGrantAddedEvent(
ctx context.Context,
resourceOwner,
userID,
projectID,
projectGrantID string,
roleKeys []string) *UserGrantAddedEvent {
return &UserGrantAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx,
UserGrantAddedType,
resourceOwner,
),
UserID: userID,
ProjectID: projectID,
ProjectGrantID: projectGrantID,
RoleKeys: roleKeys,
}
}
func UserGrantAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantAddedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-2M9fs", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantChangedEvent struct {
eventstore.BaseEvent `json:"-"`
RoleKeys []string `json:"roleKeys,omitempty"`
}
func (e *UserGrantChangedEvent) Data() interface{} {
return e
}
func (e *UserGrantChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewUserGrantChangedEvent(
ctx context.Context,
roleKeys []string) *UserGrantChangedEvent {
return &UserGrantChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserGrantChangedType,
),
RoleKeys: roleKeys,
}
}
func UserGrantChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-4M0sd", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantCascadeChangedEvent struct {
eventstore.BaseEvent `json:"-"`
RoleKeys []string `json:"roleKeys,omitempty"`
}
func (e *UserGrantCascadeChangedEvent) Data() interface{} {
return e
}
func (e *UserGrantCascadeChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewUserGrantCascadeChangedEvent(
ctx context.Context,
roleKeys []string) *UserGrantCascadeChangedEvent {
return &UserGrantCascadeChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserGrantCascadeChangedType,
),
RoleKeys: roleKeys,
}
}
func UserGrantCascadeChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-Gs9df", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
userID string
projectID string
}
func (e *UserGrantRemovedEvent) Data() interface{} {
return e
}
func (e *UserGrantRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID)}
}
func NewUserGrantRemovedEvent(ctx context.Context, resourceOwner, userID, projectID string) *UserGrantRemovedEvent {
return &UserGrantRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx,
UserGrantRemovedType,
resourceOwner,
),
userID: userID,
projectID: projectID,
}
}
func UserGrantRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-M0sdf", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantCascadeRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
userID string
projectID string
}
func (e *UserGrantCascadeRemovedEvent) Data() interface{} {
return e
}
func (e *UserGrantCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID)}
}
func NewUserGrantCascadeRemovedEvent(ctx context.Context, resourceOwner, userID, projectID string) *UserGrantRemovedEvent {
return &UserGrantRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx,
UserGrantRemovedType,
resourceOwner,
),
userID: userID,
projectID: projectID,
}
}
func UserGrantCascadeRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-E7urs", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantDeactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *UserGrantDeactivatedEvent) Data() interface{} {
return e
}
func (e *UserGrantDeactivatedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewUserGrantDeactivatedEvent(ctx context.Context) *UserGrantDeactivatedEvent {
return &UserGrantDeactivatedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserGrantDeactivatedType,
),
}
}
func UserGrantDeactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantDeactivatedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-pL0ds", "unable to unmarshal user grant")
}
return e, nil
}
type UserGrantReactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *UserGrantReactivatedEvent) Data() interface{} {
return e
}
func (e *UserGrantReactivatedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewUserGrantReactivatedEvent(ctx context.Context) *UserGrantReactivatedEvent {
return &UserGrantReactivatedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UserGrantReactivatedType,
),
}
}
func UserGrantReactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &UserGrantReactivatedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, e)
if err != nil {
return nil, errors.ThrowInternal(err, "UGRANT-M0sdf", "unable to unmarshal user grant")
}
return e, nil
}

View File

@ -3,3 +3,5 @@ CREATE TABLE eventstore.unique_constraints (
unique_field TEXT,
PRIMARY KEY (unique_type, unique_field)
);
GRANT DELETE ON TABLE eventstore.unique_constraints to adminapi;

View File

@ -1189,7 +1189,7 @@ service ManagementService {
};
}
rpc DeactivateUserGrant(UserGrantID) returns (UserGrant) {
rpc DeactivateUserGrant(UserGrantID) returns (google.protobuf.Empty) {
option (google.api.http) = {
put: "/users/{user_id}/grants/{id}/_deactivate"
body: "*"
@ -1200,7 +1200,7 @@ service ManagementService {
};
}
rpc ReactivateUserGrant(UserGrantID) returns (UserGrant) {
rpc ReactivateUserGrant(UserGrantID) returns (google.protobuf.Empty) {
option (google.api.http) = {
put: "/users/{user_id}/grants/{id}/_reactivate"
body: "*"
@ -2833,10 +2833,9 @@ message UserGrant {
string project_id = 4;
repeated string role_keys = 5;
UserGrantState state = 6;
google.protobuf.Timestamp creation_date = 7;
google.protobuf.Timestamp change_date = 8;
uint64 sequence = 9;
string grant_id = 10;
google.protobuf.Timestamp change_date = 7;
uint64 sequence = 8;
string grant_id = 9;
}
message UserGrantCreate {