package integration import ( "fmt" "testing" "github.com/stretchr/testify/assert" "edge-infra.dev/pkg/edge/api/graph/model" "edge-infra.dev/pkg/edge/api/services" "edge-infra.dev/pkg/edge/api/sql/plugin" "edge-infra.dev/test/f2" "edge-infra.dev/test/f2/x/postgres" ) // Seed Data used for tests. Initialised to the dev1 seed data var oiSeedData []plugin.Seed = func() []plugin.Seed { type rule struct { CommandName string PrivilegeName string } type command struct { CommandName string } type privilege struct { PrivilegeName string } type roleMapping struct { BslRole string EaPrivilege string } return []plugin.Seed{ { Name: "seed-ea-default-rules.tmpl", Priority: 5, Data: []rule{ {CommandName: "ls", PrivilegeName: "ea-read"}, {CommandName: "hostname", PrivilegeName: "ea-read"}, {CommandName: "cat", PrivilegeName: "ea-read"}, {CommandName: "dmesg", PrivilegeName: "ea-read"}, {CommandName: "base64", PrivilegeName: "ea-read"}, {CommandName: "echo", PrivilegeName: "ea-read"}, {CommandName: "head", PrivilegeName: "ea-read"}, {CommandName: "tail", PrivilegeName: "ea-read"}, {CommandName: "df", PrivilegeName: "ea-read"}, {CommandName: "du", PrivilegeName: "ea-read"}, {CommandName: "free", PrivilegeName: "ea-read"}, {CommandName: "ps", PrivilegeName: "ea-read"}, {CommandName: "pwd", PrivilegeName: "ea-read"}, {CommandName: "ping", PrivilegeName: "ea-read"}, {CommandName: "date", PrivilegeName: "ea-read"}, {CommandName: "stat", PrivilegeName: "ea-read"}, {CommandName: "grep", PrivilegeName: "ea-read"}, {CommandName: "kubectl", PrivilegeName: "ea-write"}, {CommandName: "systemctl", PrivilegeName: "ea-dev"}, {CommandName: "journalctl", PrivilegeName: "ea-dev"}, {CommandName: "rm", PrivilegeName: "ea-dev"}, {CommandName: "mv", PrivilegeName: "ea-dev"}, {CommandName: "kill", PrivilegeName: "ea-dev"}, {CommandName: "wget", PrivilegeName: "ea-dev"}, {CommandName: "curl", PrivilegeName: "ea-dev"}, {CommandName: "cp", PrivilegeName: "ea-dev"}, {CommandName: "tar", PrivilegeName: "ea-dev"}, {CommandName: "timedatectl", PrivilegeName: "ea-dev"}, }, }, { Name: "seed-ea-commands.tmpl", Priority: 4, Data: []command{ {CommandName: "ls"}, {CommandName: "hostname"}, {CommandName: "cat"}, {CommandName: "dmesg"}, {CommandName: "base64"}, {CommandName: "echo"}, {CommandName: "head"}, {CommandName: "tail"}, {CommandName: "df"}, {CommandName: "du"}, {CommandName: "free"}, {CommandName: "ps"}, {CommandName: "pwd"}, {CommandName: "ping"}, {CommandName: "curl"}, {CommandName: "kubectl"}, {CommandName: "systemctl"}, {CommandName: "journalctl"}, {CommandName: "cp"}, {CommandName: "tar"}, {CommandName: "rm"}, {CommandName: "mv"}, {CommandName: "kill"}, {CommandName: "wget"}, {CommandName: "date"}, {CommandName: "timedatectl"}, {CommandName: "stat"}, {CommandName: "grep"}, }, }, { Name: "seed-ea-privileges.tmpl", Priority: 4, Data: []privilege{ {PrivilegeName: "ea-read"}, {PrivilegeName: "ea-write"}, {PrivilegeName: "ea-dev"}, }, }, { Name: "seed-ea-oi-role-privileges.tmpl", Priority: 5, Data: []roleMapping{ {BslRole: "EDGE_L1", EaPrivilege: "ea-read"}, {BslRole: "EDGE_L2", EaPrivilege: "ea-write"}, {BslRole: "EDGE_L2", EaPrivilege: "ea-read"}, {BslRole: "EDGE_L3", EaPrivilege: "ea-write"}, {BslRole: "EDGE_L3", EaPrivilege: "ea-read"}, {BslRole: "EDGE_L4", EaPrivilege: "ea-read"}, {BslRole: "EDGE_L4", EaPrivilege: "ea-write"}, {BslRole: "EDGE_L4", EaPrivilege: "ea-dev"}, }, }, } }() func TestOiRoleMappings(t *testing.T) { var oiService services.OperatorInterventionService feat := f2.NewFeature("Oi Role Mappings"). Setup("Load Data", postgres.WithData(oiSeedData)). Setup("Create service", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService = services.NewOperatorInterventionService(db) return ctx }). Test("Get All Role Mappings", func(ctx f2.Context, t *testing.T) f2.Context { roleMappings, err := oiService.RoleMappings(ctx, nil) assert.NoError(t, err) var expectedRoleMappings = []*model.OiRoleMapping{ {Role: model.RoleEdgeL1, Privileges: []*model.Privilege{ {Name: "ea-read"}, }}, {Role: model.RoleEdgeL2, Privileges: []*model.Privilege{ {Name: "ea-write"}, {Name: "ea-read"}, }}, {Role: model.RoleEdgeL3, Privileges: []*model.Privilege{ {Name: "ea-write"}, {Name: "ea-read"}, }}, {Role: model.RoleEdgeL4, Privileges: []*model.Privilege{ {Name: "ea-read"}, {Name: "ea-write"}, {Name: "ea-dev"}, }}, } assert.Equal(t, expectedRoleMappings, roleMappings) return ctx }). Test("Get 1 Role Mapping", func(ctx f2.Context, t *testing.T) f2.Context { roleMappings, err := oiService.RoleMappings(ctx, []string{"EDGE_L2"}) assert.NoError(t, err) var expectedRoleMappings = []*model.OiRoleMapping{ {Role: model.RoleEdgeL2, Privileges: []*model.Privilege{ {Name: "ea-read"}, {Name: "ea-write"}, }}, } assert.Equal(t, expectedRoleMappings, roleMappings) return ctx }). Feature() f.Test(t, feat) } func TestDeleteOperatorInterventionRoleMapping(t *testing.T) { var oiService services.OperatorInterventionService // annoying var invalidEdgeRole = "INVALID_EDGE_ROLE" var invalidPrivilege = "unknownprivilege" var eaRead = "ea-read" var edgeOrgAdmin = "EDGE_L4" // Run table tests sequentially to verify behaviour of missing role mappings var tests = []struct { oirole string privName string resp *model.DeleteOperatorInterventionResponse }{ { // Should successfully delete oirole: edgeOrgAdmin, privName: eaRead, resp: &model.DeleteOperatorInterventionResponse{}, }, { // Same role and privilege should return error on second attempt oirole: edgeOrgAdmin, privName: eaRead, resp: &model.DeleteOperatorInterventionResponse{Errors: []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownRoleMapping, Privilege: &eaRead, Role: &edgeOrgAdmin, }, }}, }, { // Invalid Edge Role or missing privilege does not return an // UNKNOWN_ROLE or UNKNOWN_PRIVILEGE error, it only ever returns // UnknownRoleMapping oirole: "INVALID_EDGE_ROLE", privName: "unknownprivilege", resp: &model.DeleteOperatorInterventionResponse{Errors: []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownRoleMapping, Privilege: &invalidPrivilege, Role: &invalidEdgeRole, }, }}, }, } featureBuilder := f2.NewFeature("DeleteOIRoleMapping"). Setup("Load Data", postgres.WithData(oiSeedData)). Setup("Create Service", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService = services.NewOperatorInterventionService(db) return ctx }) for idx, tc := range tests { featureBuilder. Test(fmt.Sprintf("Test %d", idx), func(ctx f2.Context, t *testing.T) f2.Context { out, err := oiService.DeleteRoleMapping(ctx, model.DeleteOperatorInterventionMappingInput{ Privilege: &model.OperatorInterventionPrivilegeInput{Name: tc.privName}, Role: tc.oirole, }) assert.NoError(t, err) assert.Equal(t, tc.resp, out) return ctx }) } f.Test(t, featureBuilder.Feature()) } func TestAddOiRoleMappings(t *testing.T) { var oiService services.OperatorInterventionService roleMappingInput := []*model.UpdateOperatorInterventionRoleMappingInput{ { Role: "EDGE_L3", Privileges: []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, {Name: "ea-write"}, }, }, { Role: "EDGE_L4", Privileges: []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, }, }, } verifyRoles := func(ctx f2.Context, t *testing.T) f2.Context { out, err := oiService.RoleMappings(ctx, nil) assert.NoError(t, err) exp := []*model.OiRoleMapping{ {Role: model.RoleEdgeL3, Privileges: []*model.Privilege{ {Name: "ea-read"}, {Name: "ea-write"}, }}, {Role: model.RoleEdgeL4, Privileges: []*model.Privilege{ {Name: "ea-read"}, }}, } assert.Equal(t, exp, out) return ctx } feat := f2.NewFeature("Add Oi Role Mappings"). Setup("Add Privileges", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() privs := []any{"ea-read", "ea-write", "ea-dev"} _, err := db.ExecContext(ctx, `INSERT INTO ea_rules_privileges (name) VALUES ($1), ($2), ($3)`, privs...) assert.NoError(t, err) return ctx }). Setup("Create Service", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService = services.NewOperatorInterventionService(db) return ctx }). Test("Add new Role Mappings", func(ctx f2.Context, t *testing.T) f2.Context { roleMappings, err := oiService.UpdateRoleMappings(ctx, roleMappingInput) assert.NoError(t, err) assert.Empty(t, roleMappings.Errors) for _, errResp := range roleMappings.Errors { // This test isn't strictly necessary due to the Empty check // above, however it's useful to have full details printed out // when debugging assert.Zero(t, errResp) } return ctx }). Test("Verify DB Contents", verifyRoles). Test("Insert Duplicates", func(ctx f2.Context, t *testing.T) f2.Context { roleMappings, err := oiService.UpdateRoleMappings(ctx, roleMappingInput) assert.NoError(t, err) assert.Empty(t, roleMappings.Errors) for _, errResp := range roleMappings.Errors { // This test isn't strictly necessary due to the Empty check // above, however it's useful to have full details printed out // when debugging assert.Zero(t, errResp) } return ctx }). Test("Verify DB Contents on duplicates", verifyRoles). Test("Insert empty", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) roleMappings, err := oiService.UpdateRoleMappings(ctx, []*model.UpdateOperatorInterventionRoleMappingInput{}) assert.NoError(t, err) assert.Empty(t, roleMappings.Errors) for _, errResp := range roleMappings.Errors { // This test isn't strictly necessary due to the Empty check // above, however it's useful to have full details printed out // when debugging assert.Zero(t, errResp) } return ctx }). Test("Verify DB Contents on Empty insert", verifyRoles). Test("Insert invalid values", func(ctx f2.Context, t *testing.T) f2.Context { roleMappings, err := oiService.UpdateRoleMappings(ctx, []*model.UpdateOperatorInterventionRoleMappingInput{ { Role: "Invalid_Role", Privileges: []*model.OperatorInterventionPrivilegeInput{{Name: "ea-read"}}, }, { Role: "EDGE_L4", Privileges: []*model.OperatorInterventionPrivilegeInput{{Name: "invalid_privilege"}}, }, }, ) assert.NoError(t, err) var invalidRole = "Invalid_Role" var invalidPrivilege = "invalid_privilege" expRoleMappings := model.UpdateOperatorInterventionRoleMappingResponse{ Errors: []*model.OperatorInterventionErrorResponse{ {Type: model.OperatorInterventionErrorTypeUnknownRole, Role: &invalidRole}, {Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: &invalidPrivilege}, }, } assert.Equal(t, expRoleMappings.Errors, roleMappings.Errors) return ctx }). Feature() f.Test(t, feat) } func TestReadOperatorInterventionCommands(t *testing.T) { feat := f2.NewFeature("Read OI Commands"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Read a Command", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{{Name: "ls"}} result, err := oiService.ReadCommands(ctx, payload) assert.NoError(t, err) assert.Len(t, result, 1) assert.Equal(t, "ls", result[0].Name) return ctx }). Test("Read Multiple Commands", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{{Name: "ls"}, {Name: "echo"}, {Name: "cat"}} result, err := oiService.ReadCommands(ctx, payload) assert.NoError(t, err) assert.Len(t, result, 3) for _, command := range payload { assert.Contains(t, result, &model.Command{Name: command.Name}) } return ctx }). Test("Read All Commands", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) result, err := oiService.ReadCommands(ctx, nil) assert.NoError(t, err) assert.Greater(t, len(result), 0) return ctx }). Test("No Command Found", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{{Name: "nonexistant-command"}} result, err := oiService.ReadCommands(ctx, payload) assert.NoError(t, err) assert.Len(t, result, 0) return ctx }). Test("Some Commands Found", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) //names := []string{"ls", "nonexistant-command", "echo"} payload := []*model.OperatorInterventionCommandInput{ {Name: "ls"}, {Name: "nonexistant-command"}, {Name: "echo"}, } result, err := oiService.ReadCommands(ctx, payload) assert.NoError(t, err) assert.Len(t, result, 2) assert.Contains(t, result, &model.Command{Name: payload[0].Name}) assert.Contains(t, result, &model.Command{Name: payload[2].Name}) assert.NotContains(t, result, &model.Command{Name: payload[1].Name}) return ctx }). Feature() f.Test(t, feat) } //nolint:dupl func TestOperatorInterventionCreateCommands(t *testing.T) { feat := f2.NewFeature("Create OI Commands"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Add One Command", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{ {Name: "a-command-that-is-not-in-yet"}, } response, err := oiService.CreateCommands(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Add Multiple Commands", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{ {Name: "a-command-that-is-not-in-yet-1"}, {Name: "a-command-that-is-not-in-yet-2"}, {Name: "a-command-that-is-not-in-yet-3"}, } response, err := oiService.CreateCommands(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Conflicts", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) conflictCommand1 := "ls" conflictCommand2 := "echo" payload := []*model.OperatorInterventionCommandInput{ {Name: conflictCommand1}, {Name: "a-command-that-is-definitely-not-in-yet"}, {Name: conflictCommand2}, } response, err := oiService.CreateCommands(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Feature() f.Test(t, feat) } //nolint:dupl func TestDeleteOperatorInterventionCommand(t *testing.T) { feat := f2.NewFeature("Create OI Commands"). Setup("Load Data", postgres.WithData(oiSeedData)). Setup("Add Command To Be Deleted In Test", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{ {Name: "a-command-that-is-not-in-yet"}, } response, err := oiService.CreateCommands(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Delete Command", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := model.OperatorInterventionCommandInput{ Name: "a-command-that-is-not-in-yet", } response, err := oiService.DeleteCommand(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Fail to Delete Non-Existing Command", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) command := "a-command-that-was-never-there" payload := model.OperatorInterventionCommandInput{ Name: command, } response, err := oiService.DeleteCommand(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, command, *response.Errors[0].Command) assert.Equal(t, model.OperatorInterventionErrorTypeUnknownCommand, response.Errors[0].Type) return ctx }). Test("Fail to Delete Command with an active rule", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) command := "ls" payload := model.OperatorInterventionCommandInput{ Name: command, } response, err := oiService.DeleteCommand(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, command, *response.Errors[0].Command) assert.Equal(t, model.OperatorInterventionErrorTypeConflict, response.Errors[0].Type) return ctx }). Feature() f.Test(t, feat) } //nolint:dupl func TestDeleteOperatorInterventionPrivilege(t *testing.T) { feat := f2.NewFeature("Delete OI Privileges"). Setup("Load Data", postgres.WithData(oiSeedData)). Setup("Add Privilege to be used in delete tests", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionPrivilegeInput{ {Name: "test-priv"}, } response, err := oiService.CreatePrivileges(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Delete Privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := model.OperatorInterventionPrivilegeInput{ Name: "test-priv", } response, err := oiService.DeletePrivilege(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Fail to Delete Non-Existing Privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) privilege := "a-privilege-that-was-never-there" payload := model.OperatorInterventionPrivilegeInput{ Name: privilege, } response, err := oiService.DeletePrivilege(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, privilege, *response.Errors[0].Privilege) assert.Equal(t, model.OperatorInterventionErrorTypeUnknownPrivilege, response.Errors[0].Type) return ctx }). Test("Fail to Delete Privilege with an active rule", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) privilege := "ea-read" payload := model.OperatorInterventionPrivilegeInput{ Name: privilege, } response, err := oiService.DeletePrivilege(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, privilege, *response.Errors[0].Privilege) assert.Equal(t, model.OperatorInterventionErrorTypeConflict, response.Errors[0].Type) return ctx }). Feature() f.Test(t, feat) } func TestOperatorInterventionReadPrivilege(t *testing.T) { const ( privilegeName = "ea-read" ) feat := f2.NewFeature("Read Privilege"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Read one privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) privileges, err := oiService.ReadPrivileges(ctx, []*model.OperatorInterventionPrivilegeInput{ {Name: privilegeName}, }) assert.NoError(t, err) assert.Len(t, privileges, 1) assert.Equal(t, privilegeName, privileges[0].Name) return ctx }). Test("Read multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) //privileges, err := oiService.ReadPrivileges(ctx, []string{"ea-read", "ea-write"}) privileges, err := oiService.ReadPrivileges(ctx, []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, {Name: "ea-write"}, }) assert.NoError(t, err) assert.Len(t, privileges, 2) returnedPrivileges := []string{privileges[0].Name, privileges[1].Name} assert.EqualValues(t, []string{privilegeName, "ea-write"}, returnedPrivileges) return ctx }). Feature() f.Test(t, feat) } //nolint:dupl func TestOperatorInterventionCreatePrivileges(t *testing.T) { feat := f2.NewFeature("Create Privileges"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Create single privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionPrivilegeInput{ {Name: "test-priv"}, } response, err := oiService.CreatePrivileges(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Create multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionPrivilegeInput{ {Name: "test-priv-1"}, {Name: "test-priv-2"}, {Name: "test-priv-3"}, } response, err := oiService.CreatePrivileges(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Create conflicting privileges", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, {Name: "ea-write"}, } response, err := oiService.CreatePrivileges(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Feature() f.Test(t, feat) } func TestDeleteOperatorInterventionRules(t *testing.T) { feat := f2.NewFeature("Delete OI Rules"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Delete Rule", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := model.DeleteOperatorInterventionRuleInput{ Privilege: "ea-read", Command: "ls", } response, err := oiService.DeleteRule(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Fail to Delete Rule with non-existing command", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) command := "non-existent-command" payload := model.DeleteOperatorInterventionRuleInput{ Command: command, Privilege: "ea-read", } response, err := oiService.DeleteRule(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownCommand, Command: &command, }, }, response.Errors) return ctx }). Test("Fail to Delete Rule with non-existing privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) privilege := "non-existent-privilege" payload := model.DeleteOperatorInterventionRuleInput{ Command: "ls", Privilege: privilege, } response, err := oiService.DeleteRule(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: &privilege, }, }, response.Errors) return ctx }). Test("Fail to Delete Rule with non-existing command and privilege", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) command := "a-non-existent-command" privilege := "a-non-existent-privilege" payload := model.DeleteOperatorInterventionRuleInput{ Command: command, Privilege: privilege, } response, err := oiService.DeleteRule(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownCommand, Command: &command, }, { Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: &privilege, }, }, response.Errors) return ctx }). Test("Fail to delete non-existing rule", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := model.DeleteOperatorInterventionRuleInput{ Command: "ls", Privilege: "ea-read", } response, err := oiService.DeleteRule(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownRule, Privilege: func() *string { s := "ea-read"; return &s }(), Command: func() *string { s := "ls"; return &s }(), }, }, response.Errors) return ctx }). Feature() f.Test(t, feat) } func TestUpdateOperatorInterventionRules(t *testing.T) { feat := f2.NewFeature("Create OI Rules"). Setup("Add Commands", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, {Name: "testCommand2"}, {Name: "testCommand3"}, } response, err := oiService.CreateCommands(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Setup("Add Privileges", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) payload := []*model.OperatorInterventionPrivilegeInput{ {Name: "testPriv1"}, {Name: "testPriv2"}, {Name: "testPriv3"}, } response, err := oiService.CreatePrivileges(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) return ctx }). Test("Create Rule", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{{ //{Commands: []string{"testCommand1"}, Privilege: "testPriv1"}, Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) assertRulesInDB(ctx, t, []*model.Rule{ { Commands: []*model.Command{ {Name: "testCommand1"}}, Privilege: &model.Privilege{ Name: "testPriv1", }, }, }) return ctx }). Test("Conflicting Rule", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) assertRulesInDB(ctx, t, []*model.Rule{ { Commands: []*model.Command{ {Name: "testCommand1"}}, Privilege: &model.Privilege{ Name: "testPriv1", }, }, }) return ctx }). Test("Create Rule with multiple commands", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ { // Commands: []string{ // "testCommand2", // "testCommand3", // }, // Privilege: "testPriv1" Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand2"}, {Name: "testCommand3"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) assertRulesInDB(ctx, t, []*model.Rule{ { Commands: []*model.Command{ {Name: "testCommand1"}, {Name: "testCommand2"}, //new {Name: "testCommand3"}, //new }, Privilege: &model.Privilege{ Name: "testPriv1", }, }, }) return ctx }). Test("Create Rule with multiple privileges", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv2"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv3"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) assertRulesInDB(ctx, t, []*model.Rule{ { Commands: []*model.Command{ {Name: "testCommand1"}, {Name: "testCommand2"}, {Name: "testCommand3"}, }, Privilege: &model.Privilege{ Name: "testPriv1", }, }, { //new Commands: []*model.Command{ {Name: "testCommand1"}, }, Privilege: &model.Privilege{ Name: "testPriv2", }, }, { //new Commands: []*model.Command{ {Name: "testCommand1"}, }, Privilege: &model.Privilege{ Name: "testPriv3", }, }, }) return ctx }). Test("Fail to create rule with non-existing command", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "non-existent-command"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownCommand, Command: func() *string { s := "non-existent-command"; return &s }(), }, }, response.Errors) return ctx }). Test("Fail to create rule with non-existing privilege", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "non-existent-privilege"}, Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.NotEmpty(t, response) assert.Equal(t, []*model.OperatorInterventionErrorResponse{ { Type: model.OperatorInterventionErrorTypeUnknownPrivilege, Privilege: func() *string { s := "non-existent-privilege"; return &s }(), }, }, response.Errors) return ctx }). Test("Create rule despite conflicting rule", func(ctx f2.Context, t *testing.T) f2.Context { payload := []*model.UpdateOperatorInterventionRuleInput{ // {Commands: []string{"testCommand1"}, Privilege: "testPriv1"}, // already present // {Commands: []string{"testCommand2"}, Privilege: "testPriv2"}, // new { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv1"}, //already present Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand1"}, }, }, { Privilege: &model.OperatorInterventionPrivilegeInput{Name: "testPriv2"}, //new Commands: []*model.OperatorInterventionCommandInput{ {Name: "testCommand2"}, }, }, } db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) response, err := oiService.UpdateRules(ctx, payload) assert.NoError(t, err) assert.Empty(t, response) assertRulesInDB(ctx, t, []*model.Rule{ { Commands: []*model.Command{ {Name: "testCommand1"}, {Name: "testCommand2"}, {Name: "testCommand3"}, }, Privilege: &model.Privilege{ Name: "testPriv1", }, }, { Commands: []*model.Command{ {Name: "testCommand1"}, {Name: "testCommand2"}, //new }, Privilege: &model.Privilege{ Name: "testPriv2", }, }, { Commands: []*model.Command{ {Name: "testCommand1"}, }, Privilege: &model.Privilege{ Name: "testPriv3", }, }, }) return ctx }). Feature() f.Test(t, feat) } func assertRulesInDB(ctx f2.Context, t *testing.T, expectedRules []*model.Rule) { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) rules, err := oiService.ReadRules(ctx, nil) assert.NoError(t, err) assert.ElementsMatch(t, expectedRules, rules) } func TestReadOperatorInterventionRules(t *testing.T) { feat := f2.NewFeature("Read OI Rules"). Setup("Load Data", postgres.WithData(oiSeedData)). Test("Read all rules", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) rules, err := oiService.ReadRules(ctx, nil) assert.NoError(t, err) assert.Greater(t, len(rules), 0) return ctx }). Test("Read one rule", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) rules, err := oiService.ReadRules(ctx, []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, }) assert.NoError(t, err) assert.Len(t, rules, 1) assert.Equal(t, "ea-read", rules[0].Privilege.Name) return ctx }). Test("Read multiple rules", func(ctx f2.Context, t *testing.T) f2.Context { db := postgres.FromContextT(ctx, t).DB() oiService := services.NewOperatorInterventionService(db) rules, err := oiService.ReadRules(ctx, []*model.OperatorInterventionPrivilegeInput{ {Name: "ea-read"}, {Name: "ea-write"}, }) assert.NoError(t, err) assert.Len(t, rules, 2) return ctx }). Feature() f.Test(t, feat) }