From 9e2d13876c871e97949402fb1fbc83ce945549d4 Mon Sep 17 00:00:00 2001 From: Abin Simon Date: Sun, 9 Jan 2022 16:22:23 +0530 Subject: [PATCH] Group creation now also maps proper accounts --- .../pkg/internal/models/groupaccount.go | 24 +++++ components/usermgmt/pkg/service/group.go | 56 ++++++++++- components/usermgmt/pkg/service/role.go | 98 +++++++++---------- .../000014_authsrv_groupaccount.up.sql | 9 +- 4 files changed, 130 insertions(+), 57 deletions(-) create mode 100644 components/usermgmt/pkg/internal/models/groupaccount.go diff --git a/components/usermgmt/pkg/internal/models/groupaccount.go b/components/usermgmt/pkg/internal/models/groupaccount.go new file mode 100644 index 0000000..c8c5907 --- /dev/null +++ b/components/usermgmt/pkg/internal/models/groupaccount.go @@ -0,0 +1,24 @@ +package models + +import ( + "time" + + "github.com/google/uuid" + "github.com/uptrace/bun" +) + +type GroupAccount struct { + bun.BaseModel `bun:"table:authsrv_groupaccount,alias:groupaccount"` + + ID uuid.UUID `bun:"id,type:uuid,pk,default:uuid_generate_v4()"` + Name string `bun:"name,notnull"` + Description string `bun:"description,notnull"` + CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"` + ModifiedAt time.Time `bun:"modified_at,notnull,default:current_timestamp"` + Trash bool `bun:"trash,notnull"` + // OrganizationId uuid.UUID `bun:"organization_id,type:uuid"` + // PartnerId uuid.UUID `bun:"partner_id,type:uuid"` + AccountId uuid.UUID `bun:"account_id,type:uuid"` + GroupId uuid.UUID `bun:"group_id,type:uuid"` + Active bool `bun:"active,notnull"` +} diff --git a/components/usermgmt/pkg/service/group.go b/components/usermgmt/pkg/service/group.go index 59083f9..d7ebf59 100644 --- a/components/usermgmt/pkg/service/group.go +++ b/components/usermgmt/pkg/service/group.go @@ -49,13 +49,51 @@ func NewGroupService(db *bun.DB) GroupService { } } +// Update the users(account) mapped to each group +func (s *groupService) updateGroupAccountRelation(ctx context.Context, group *userv3.Group) (*userv3.Group, error) { + // TODO: use a more efficient way to update the relations + // TODO: diff and delete the old relations + groupId, _ := uuid.Parse(group.GetMetadata().GetId()) + + // TODO: add transactions + var grpaccs []models.GroupAccount + for _, account := range group.GetSpec().GetUsers() { + accountId, err := uuid.Parse(account) + if err != nil { + return nil, err + } + grp := models.GroupAccount{ + Name: group.GetMetadata().GetName(), + Description: group.GetMetadata().GetDescription(), + CreatedAt: time.Now(), + ModifiedAt: time.Now(), + Trash: false, + AccountId: accountId, + GroupId: groupId, + Active: true, + } + grpaccs = append(grpaccs, grp) + } + _, err := s.dao.Create(ctx, &grpaccs) + if err != nil { + group.Status = &v3.Status{ + ConditionType: "Create", + ConditionStatus: v3.ConditionStatus_StatusFailed, + LastUpdated: timestamppb.Now(), + } + return group, err + } + + return group, nil +} + func (s *groupService) Create(ctx context.Context, group *userv3.Group) (*userv3.Group, error) { partnerId, _ := uuid.Parse(group.GetMetadata().GetPartner()) organizationId, _ := uuid.Parse(group.GetMetadata().GetOrganization()) // TODO: find out the interaction if project key is present in the group metadata // TODO: check if a group with the same 'name' already exists and fail if so - // TODO: we should be specifying names instead of ids for partner and org + // TODO: we should be specifying names instead of ids for partner and org (at least in output) // TODO: create vs apply difference like in kubectl?? //convert v3 spec to internal models grp := models.Group{ @@ -82,7 +120,8 @@ func (s *groupService) Create(ctx context.Context, group *userv3.Group) (*userv3 if createdGroup, ok := entity.(*models.Group); ok { group.Metadata.Id = createdGroup.ID.String() group.Spec = &userv3.GroupSpec{ - Type: createdGroup.Type, + Type: createdGroup.Type, + Users: group.Spec.Users, // TODO: is this the right thing to do? } if group.Status != nil { group.Status = &v3.Status{ @@ -93,8 +132,17 @@ func (s *groupService) Create(ctx context.Context, group *userv3.Group) (*userv3 } } - return group, nil + group, err = s.updateGroupAccountRelation(ctx, group) + if err != nil { + group.Status = &v3.Status{ + ConditionType: "Create", + ConditionStatus: v3.ConditionStatus_StatusFailed, + LastUpdated: timestamppb.Now(), + } + return group, err + } + return group, nil } func (s *groupService) GetByID(ctx context.Context, id string) (*userv3.Group, error) { @@ -157,7 +205,7 @@ func (s *groupService) GetByID(ctx context.Context, id string) (*userv3.Group, e } func (s *groupService) GetByName(ctx context.Context, name string) (*userv3.Group, error) { - fmt.Println("name:", name); + fmt.Println("name:", name) group := &userv3.Group{ ApiVersion: apiVersion, diff --git a/components/usermgmt/pkg/service/role.go b/components/usermgmt/pkg/service/role.go index 83f0225..3f8b768 100644 --- a/components/usermgmt/pkg/service/role.go +++ b/components/usermgmt/pkg/service/role.go @@ -57,7 +57,7 @@ func (s *roleService) Create(ctx context.Context, role *userv3.Role) (*userv3.Ro // TODO: we should be specifying names instead of ids for partner and org // TODO: create vs apply difference like in kubectl?? //convert v3 spec to internal models - grp := models.Role{ + rle := models.Role{ Name: role.GetMetadata().GetName(), Description: role.GetMetadata().GetDescription(), CreatedAt: time.Now(), @@ -68,7 +68,7 @@ func (s *roleService) Create(ctx context.Context, role *userv3.Role) (*userv3.Ro IsGlobal: role.GetSpec().GetIsGlobal(), Scope: role.GetSpec().GetScope(), } - entity, err := s.dao.Create(ctx, &grp) + entity, err := s.dao.Create(ctx, &rle) if err != nil { role.Status = &v3.Status{ ConditionType: "Create", @@ -129,22 +129,22 @@ func (s *roleService) GetByID(ctx context.Context, id string) (*userv3.Role, err return role, err } - if grp, ok := entity.(*models.Role); ok { + if rle, ok := entity.(*models.Role); ok { labels := make(map[string]string) - labels["organization"] = grp.OrganizationId.String() + labels["organization"] = rle.OrganizationId.String() role.Metadata = &v3.Metadata{ - Name: grp.Name, - Description: grp.Description, - Id: grp.ID.String(), - Organization: grp.OrganizationId.String(), - Partner: grp.PartnerId.String(), + Name: rle.Name, + Description: rle.Description, + Id: rle.ID.String(), + Organization: rle.OrganizationId.String(), + Partner: rle.PartnerId.String(), Labels: labels, - ModifiedAt: timestamppb.New(grp.ModifiedAt), + ModifiedAt: timestamppb.New(rle.ModifiedAt), } role.Spec = &userv3.RoleSpec{ - IsGlobal: grp.IsGlobal, - Scope: grp.Scope, + IsGlobal: rle.IsGlobal, + Scope: rle.Scope, } role.Status = &v3.Status{ LastUpdated: timestamppb.Now(), @@ -180,22 +180,22 @@ func (s *roleService) GetByName(ctx context.Context, name string) (*userv3.Role, return role, err } - if grp, ok := entity.(*models.Role); ok { + if rle, ok := entity.(*models.Role); ok { labels := make(map[string]string) - labels["organization"] = grp.OrganizationId.String() + labels["organization"] = rle.OrganizationId.String() role.Metadata = &v3.Metadata{ - Name: grp.Name, - Description: grp.Description, - Id: grp.ID.String(), - Organization: grp.OrganizationId.String(), - Partner: grp.PartnerId.String(), + Name: rle.Name, + Description: rle.Description, + Id: rle.ID.String(), + Organization: rle.OrganizationId.String(), + Partner: rle.PartnerId.String(), Labels: labels, - ModifiedAt: timestamppb.New(grp.ModifiedAt), + ModifiedAt: timestamppb.New(rle.ModifiedAt), } role.Spec = &userv3.RoleSpec{ - IsGlobal: grp.IsGlobal, - Scope: grp.Scope, + IsGlobal: rle.IsGlobal, + Scope: rle.Scope, } role.Status = &v3.Status{ LastUpdated: timestamppb.Now(), @@ -224,15 +224,15 @@ func (s *roleService) Update(ctx context.Context, role *userv3.Role) (*userv3.Ro return role, err } - if grp, ok := entity.(*models.Role); ok { + if rle, ok := entity.(*models.Role); ok { //update role details - grp.Name = role.Metadata.Name - grp.Description = role.Metadata.Description - grp.IsGlobal = role.Spec.IsGlobal - grp.Scope = role.Spec.Scope - grp.ModifiedAt = time.Now() + rle.Name = role.Metadata.Name + rle.Description = role.Metadata.Description + rle.IsGlobal = role.Spec.IsGlobal + rle.Scope = role.Spec.Scope + rle.ModifiedAt = time.Now() - _, err = s.dao.Update(ctx, id, grp) + _, err = s.dao.Update(ctx, id, rle) if err != nil { role.Status = &v3.Status{ ConditionType: "Update", @@ -245,8 +245,8 @@ func (s *roleService) Update(ctx context.Context, role *userv3.Role) (*userv3.Ro //update spec and status role.Spec = &userv3.RoleSpec{ - IsGlobal: grp.IsGlobal, - Scope: grp.Scope, + IsGlobal: rle.IsGlobal, + Scope: rle.Scope, } role.Status = &v3.Status{ ConditionType: "Update", @@ -279,8 +279,8 @@ func (s *roleService) Delete(ctx context.Context, role *userv3.Role) (*userv3.Ro } return role, err } - if grp, ok := entity.(*models.Role); ok { - err = s.dao.Delete(ctx, id, grp) + if rle, ok := entity.(*models.Role); ok { + err = s.dao.Delete(ctx, id, rle) if err != nil { role.Status = &v3.Status{ ConditionType: "Delete", @@ -291,8 +291,8 @@ func (s *roleService) Delete(ctx context.Context, role *userv3.Role) (*userv3.Ro return role, err } //update v3 spec - role.Metadata.Id = grp.ID.String() - role.Metadata.Name = grp.Name + role.Metadata.Id = rle.ID.String() + role.Metadata.Name = rle.Name role.Status = &v3.Status{ ConditionType: "Delete", ConditionStatus: v3.ConditionStatus_StatusOK, @@ -322,29 +322,29 @@ func (s *roleService) List(ctx context.Context, role *userv3.Role) (*userv3.Role if err != nil { return roleList, err } - var grps []models.Role - entities, err := s.dao.List(ctx, uuid.NullUUID{UUID: partId, Valid: true}, uuid.NullUUID{UUID: orgId, Valid: true}, &grps) + var rles []models.Role + entities, err := s.dao.List(ctx, uuid.NullUUID{UUID: partId, Valid: true}, uuid.NullUUID{UUID: orgId, Valid: true}, &rles) if err != nil { return roleList, err } - if grps, ok := entities.(*[]models.Role); ok { - for _, grp := range *grps { + if rles, ok := entities.(*[]models.Role); ok { + for _, rle := range *rles { labels := make(map[string]string) - labels["organization"] = grp.OrganizationId.String() - labels["partner"] = grp.PartnerId.String() + labels["organization"] = rle.OrganizationId.String() + labels["partner"] = rle.PartnerId.String() role.Metadata = &v3.Metadata{ - Name: grp.Name, - Description: grp.Description, - Id: grp.ID.String(), - Organization: grp.OrganizationId.String(), - Partner: grp.PartnerId.String(), + Name: rle.Name, + Description: rle.Description, + Id: rle.ID.String(), + Organization: rle.OrganizationId.String(), + Partner: rle.PartnerId.String(), Labels: labels, - ModifiedAt: timestamppb.New(grp.ModifiedAt), + ModifiedAt: timestamppb.New(rle.ModifiedAt), } role.Spec = &userv3.RoleSpec{ - // IsGlobal: grp.IsGlobal, - Scope: grp.Scope, + // IsGlobal: rle.IsGlobal, + Scope: rle.Scope, } roles = append(roles, role) } diff --git a/persistence/migrations/admindb/000014_authsrv_groupaccount.up.sql b/persistence/migrations/admindb/000014_authsrv_groupaccount.up.sql index a0a7fce..ad1ecd8 100644 --- a/persistence/migrations/admindb/000014_authsrv_groupaccount.up.sql +++ b/persistence/migrations/admindb/000014_authsrv_groupaccount.up.sql @@ -22,10 +22,11 @@ CREATE INDEX authsrv_groupaccount_name_d17de056 ON authsrv_groupaccount USING bt CREATE INDEX authsrv_groupaccount_name_d17de056_like ON authsrv_groupaccount USING btree (name varchar_pattern_ops); -ALTER TABLE ONLY authsrv_groupaccount - ADD CONSTRAINT authsrv_groupaccount_account_id_041e4e98_fk_authsrv_account_id FOREIGN KEY (account_id) - REFERENCES authsrv_account(id) DEFERRABLE INITIALLY DEFERRED; +-- TODO: find a better constraint now that we have a different accounts table +-- ALTER TABLE ONLY authsrv_groupaccount +-- ADD CONSTRAINT authsrv_groupaccount_account_id_041e4e98_fk_authsrv_account_id FOREIGN KEY (account_id) +-- REFERENCES authsrv_account(id) DEFERRABLE INITIALLY DEFERRED; ALTER TABLE ONLY authsrv_groupaccount ADD CONSTRAINT authsrv_groupaccount_group_id_c67750ef_fk_authsrv_group_id FOREIGN KEY (group_id) - REFERENCES authsrv_group(id) DEFERRABLE INITIALLY DEFERRED; \ No newline at end of file + REFERENCES authsrv_group(id) DEFERRABLE INITIALLY DEFERRED;