package service_test import ( "context" "testing" "github.com/stretchr/testify/require" "go.infratographer.com/x/events" "go.infratographer.com/x/gidx" "go.equinixmetal.net/infra9-metal-bridge/internal/metal/models" "go.equinixmetal.net/infra9-metal-bridge/internal/metal/providers" "go.equinixmetal.net/infra9-metal-bridge/internal/permissions" "go.equinixmetal.net/infra9-metal-bridge/internal/service" ) func TestTouchProjectEmpty(t *testing.T) { rootTenantID := gidx.PrefixedID("tnntten-root1") roleMap := map[string][]string{ "owner": { "action1", "action2", }, } userID := gidx.PrefixedID("idntusr-2s-9kVNPJBaInlHpRs3lAMsvU_kVkLaSlD4R_RhavDw") user := &models.UserDetails{ ID: "usr1", } orgID := gidx.PrefixedID("metlorg-org1") org := &models.OrganizationDetails{ ID: "org1", } projectID := gidx.PrefixedID("metlprj-prj1") project := &models.ProjectDetails{ ID: "prj1", Organization: org, Memberships: []*models.Membership[models.ProjectDetails]{ { User: user, Roles: []string{ "owner", }, }, }, } var ( mMetal = new(providers.MockProvider) mPerms = new(permissions.MockClient) mPublisher = new(mockPublisher) ) // Relationships mMetal.On("GetProjectDetails", projectID).Return(project, nil) mPerms.On("ListResourceRelationshipsFrom", projectID).Return([]permissions.ResourceRelationship{}, nil) relateParentChangeMessage := events.ChangeMessage{ SubjectID: projectID, EventType: string(events.CreateChangeType), AdditionalSubjectIDs: []gidx.PrefixedID{ orgID, }, } mPublisher.On("PublishChange", "metalproject", relateParentChangeMessage).Return(nil) // Memberships newRoleID := gidx.PrefixedID("permrol-role1") mPerms.On("ListResourceRoles", projectID).Return(permissions.ResourceRoles{}, nil) mPerms.On("CreateRole", projectID, roleMap["owner"]).Return(newRoleID, nil) mPerms.On("AssignRole", newRoleID, userID).Return(nil) // Run scenario svc, err := service.New(mPublisher, mMetal, mPerms, service.WithRootTenant(rootTenantID.String()), service.WithRoles(roleMap), ) require.NoError(t, err) err = svc.TouchProject(context.Background(), projectID) require.NoError(t, err) require.True(t, mMetal.AssertExpectations(t), "unexpected calls to metal provider") require.True(t, mPerms.AssertExpectations(t), "unexpected calls to permissions client") require.True(t, mPublisher.AssertExpectations(t), "unexpected calls to events publisher") } func TestTouchProjectCleanup(t *testing.T) { rootTenantID := gidx.PrefixedID("tnntten-root1") roleMap := map[string][]string{ "owner": { "action1", "action2", }, "collaborator": { "action1", }, } oldUserID := gidx.PrefixedID("idntusr-2s-9kVNPJBaInlHpRs3lAMsvU_kVkLaSlD4R_RhavDw") oldOrgID := gidx.PrefixedID("metlorg-org1") userID := gidx.PrefixedID("idntusr-RnKvdujrwqm4o1dBDgfgaqeCpKFMaGeOtGnNbZky0Kg") user := &models.UserDetails{ ID: "usr2", } orgID := gidx.PrefixedID("metlorg-org2") org := &models.OrganizationDetails{ ID: "org2", } projectID := gidx.PrefixedID("metlprj-prj2") project := &models.ProjectDetails{ ID: "prj2", Organization: org, Memberships: []*models.Membership[models.ProjectDetails]{ { User: user, Roles: []string{ "owner", }, }, }, } var ( mMetal = new(providers.MockProvider) mPerms = new(permissions.MockClient) mPublisher = new(mockPublisher) ) // Relationships mMetal.On("GetProjectDetails", projectID).Return(project, nil) existingRelsFrom := []permissions.ResourceRelationship{ { Relation: string(service.RelateParent), SubjectID: oldOrgID, }, } mPerms.On("ListResourceRelationshipsFrom", projectID).Return(existingRelsFrom, nil) mPerms.On("DeleteResourceRelationship", projectID, string(service.RelateParent), oldOrgID).Return(nil) relateParentChangeMessage := events.ChangeMessage{ SubjectID: projectID, EventType: string(events.CreateChangeType), AdditionalSubjectIDs: []gidx.PrefixedID{ orgID, }, } mPublisher.On("PublishChange", "metalproject", relateParentChangeMessage).Return(nil) // Memberships oldRoleID := gidx.PrefixedID("permrol-role1") newRoleID := gidx.PrefixedID("permrol-role2") existingRoles := permissions.ResourceRoles{ { ID: oldRoleID, Actions: roleMap["collaborator"], }, } mPerms.On("ListResourceRoles", projectID).Return(existingRoles, nil) existingRoleAssignments := []gidx.PrefixedID{ oldUserID, } mPerms.On("ListRoleAssignments", oldRoleID).Return(existingRoleAssignments, nil) mPerms.On("CreateRole", projectID, roleMap["owner"]).Return(newRoleID, nil) mPerms.On("DeleteRole", oldRoleID).Return(nil) mPerms.On("AssignRole", newRoleID, userID).Return(nil) mPerms.On("UnassignRole", oldRoleID, oldUserID).Return(nil) // Run scenario svc, err := service.New(mPublisher, mMetal, mPerms, service.WithRootTenant(rootTenantID.String()), service.WithRoles(roleMap), ) require.NoError(t, err) err = svc.TouchProject(context.Background(), projectID) require.NoError(t, err) require.True(t, mMetal.AssertExpectations(t), "unexpected calls to metal provider") require.True(t, mPerms.AssertExpectations(t), "unexpected calls to permissions client") require.True(t, mPublisher.AssertExpectations(t), "unexpected calls to events publisher") } func TestTouchProjectNoChange(t *testing.T) { rootTenantID := gidx.PrefixedID("tnntten-root1") roleMap := map[string][]string{ "owner": { "action1", "action2", }, } userID := gidx.PrefixedID("idntusr-2s-9kVNPJBaInlHpRs3lAMsvU_kVkLaSlD4R_RhavDw") user := &models.UserDetails{ ID: "usr1", } orgID := gidx.PrefixedID("metlorg-org1") org := &models.OrganizationDetails{ ID: "org1", } projectID := gidx.PrefixedID("metlprj-prj1") project := &models.ProjectDetails{ ID: "prj1", Organization: org, Memberships: []*models.Membership[models.ProjectDetails]{ { User: user, Roles: []string{ "owner", }, }, }, } var ( mMetal = new(providers.MockProvider) mPerms = new(permissions.MockClient) mPublisher = new(mockPublisher) ) // Relationships mMetal.On("GetProjectDetails", projectID).Return(project, nil) existingRelsFrom := []permissions.ResourceRelationship{ { Relation: string(service.RelateParent), SubjectID: orgID, }, } mPerms.On("ListResourceRelationshipsFrom", projectID).Return(existingRelsFrom, nil) // Memberships roleID := gidx.PrefixedID("permrol-role1") existingRoles := permissions.ResourceRoles{ { ID: roleID, Actions: roleMap["owner"], }, } mPerms.On("ListResourceRoles", projectID).Return(existingRoles, nil) existingRoleAssignments := []gidx.PrefixedID{ userID, } mPerms.On("ListRoleAssignments", roleID).Return(existingRoleAssignments, nil) // Run scenario svc, err := service.New(mPublisher, mMetal, mPerms, service.WithRootTenant(rootTenantID.String()), service.WithRoles(roleMap), ) require.NoError(t, err) err = svc.TouchProject(context.Background(), projectID) require.NoError(t, err) require.True(t, mMetal.AssertExpectations(t), "unexpected calls to metal provider") require.True(t, mPerms.AssertExpectations(t), "unexpected calls to permissions client") require.True(t, mPublisher.AssertExpectations(t), "unexpected calls to events publisher") }