...

Source file src/edge-infra.dev/pkg/sds/emergencyaccess/rules/server/banner_rules_test.go

Documentation: edge-infra.dev/pkg/sds/emergencyaccess/rules/server

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  
    13  	rulesengine "edge-infra.dev/pkg/sds/emergencyaccess/rules"
    14  )
    15  
    16  // testing helper type
    17  type helper interface {
    18  	Helper()
    19  }
    20  
    21  type StringAssertionFunc func(t assert.TestingT, actual string, msgAndArgs ...interface{}) bool
    22  
    23  func JSONEq(expected string) StringAssertionFunc {
    24  	return func(t assert.TestingT, actual string, msgAndArgs ...interface{}) bool {
    25  		if help, ok := t.(helper); ok {
    26  			help.Helper()
    27  		}
    28  
    29  		return assert.JSONEq(t, expected, actual, msgAndArgs...)
    30  	}
    31  }
    32  
    33  func StringEqual(expected string) StringAssertionFunc {
    34  	return func(t assert.TestingT, actual string, msgAndArgs ...interface{}) bool {
    35  		if help, ok := t.(helper); ok {
    36  			help.Helper()
    37  		}
    38  
    39  		return assert.Equal(t, expected, actual, msgAndArgs...)
    40  	}
    41  }
    42  
    43  func JSONEmpty() StringAssertionFunc {
    44  	return func(t assert.TestingT, actual string, msgAndArgs ...interface{}) bool {
    45  		if help, ok := t.(helper); ok {
    46  			help.Helper()
    47  		}
    48  
    49  		return assert.Empty(t, actual, msgAndArgs...)
    50  	}
    51  }
    52  
    53  type GetAllBannerRulesMock struct {
    54  	RulesEngine
    55  
    56  	AllOut []rulesengine.ReadBannerRule
    57  	AllErr error
    58  }
    59  
    60  func (mc GetAllBannerRulesMock) ReadRulesForAllBanners(_ context.Context) ([]rulesengine.ReadBannerRule, error) {
    61  	return mc.AllOut, mc.AllErr
    62  }
    63  
    64  func TestGetAllRulesForAllBanners(t *testing.T) {
    65  	t.Parallel()
    66  
    67  	tests := map[string]struct {
    68  		rengOut   []rulesengine.ReadBannerRule
    69  		rengErr   error
    70  		expStatus int
    71  		expOut    string
    72  	}{
    73  		"error return": {
    74  			rengOut:   nil,
    75  			rengErr:   fmt.Errorf("an error"),
    76  			expStatus: http.StatusInternalServerError,
    77  			expOut:    "",
    78  		},
    79  		"Rules Returned": {
    80  			expStatus: http.StatusOK,
    81  			expOut: `[{
    82  				"command": {
    83  					"id": "abcd",
    84  					"name": "ls"
    85  				},
    86  				"banners": [{
    87  					"banner": {
    88  						"id": "efgh",
    89  						"name": "banner"
    90  					},
    91  					"privileges": [{
    92  						"id": "ijkl",
    93  						"name": "read"
    94  					}]
    95  				}]
    96  				}]`,
    97  			rengErr: nil,
    98  			rengOut: []rulesengine.ReadBannerRule{
    99  				{
   100  					Command: rulesengine.Command{Name: "ls", ID: "abcd"},
   101  					Banners: []rulesengine.BannerPrivOverrides{
   102  						{
   103  							Banner: rulesengine.Banner{BannerName: "banner", BannerID: "efgh"},
   104  							Privileges: []rulesengine.Privilege{
   105  								{Name: "read", ID: "ijkl"},
   106  							},
   107  						},
   108  					},
   109  				},
   110  			},
   111  		},
   112  	}
   113  
   114  	for name, tc := range tests {
   115  		tc := tc
   116  		t.Run(name, func(t *testing.T) {
   117  			t.Parallel()
   118  
   119  			log := newLogger()
   120  
   121  			ruleseng := GetAllBannerRulesMock{
   122  				AllOut: tc.rengOut,
   123  				AllErr: tc.rengErr,
   124  			}
   125  
   126  			r := httptest.NewRecorder()
   127  			_, ginEngine := getTestGinContext(r)
   128  			_, err := New(ginEngine, &ruleseng, log)
   129  			assert.NoError(t, err)
   130  
   131  			req, err := http.NewRequest(http.MethodGet, "/admin/rules/banner/commands", nil)
   132  			assert.NoError(t, err)
   133  
   134  			ginEngine.ServeHTTP(r, req)
   135  
   136  			assert.Equal(t, tc.expStatus, r.Result().StatusCode)
   137  
   138  			if tc.expOut != "" {
   139  				assert.JSONEq(t, tc.expOut, r.Body.String())
   140  			} else {
   141  				assert.Empty(t, r.Body.String())
   142  			}
   143  		})
   144  	}
   145  }
   146  
   147  type getBannerMock struct {
   148  	RulesEngine
   149  
   150  	bannerName string
   151  
   152  	retRules []rulesengine.Rule
   153  	retErr   error
   154  }
   155  
   156  func (mc *getBannerMock) ReadRulesForBanner(_ context.Context, bannerName string) ([]rulesengine.Rule, error) {
   157  	mc.bannerName = bannerName
   158  
   159  	return mc.retRules, mc.retErr
   160  }
   161  
   162  func TestReadAllRulesInBanner(t *testing.T) {
   163  	t.Parallel()
   164  
   165  	tests := map[string]struct {
   166  		url string
   167  
   168  		// Values rulesengine should return
   169  		retRules []rulesengine.Rule
   170  		retErr   error
   171  
   172  		// value rulesengine should be called with
   173  		expBanner string
   174  
   175  		// Expected http response
   176  		expStatusCode int
   177  		expOutput     StringAssertionFunc
   178  	}{
   179  		"Empty list return": {
   180  			url:           "/admin/rules/banner/commands?bannerName=myBanner",
   181  			expBanner:     "myBanner",
   182  			retRules:      []rulesengine.Rule{},
   183  			retErr:        nil,
   184  			expStatusCode: http.StatusOK,
   185  			expOutput:     JSONEq("null"),
   186  		},
   187  		"Nil return": {
   188  			url:           "/admin/rules/banner/commands?bannerName=myBanner",
   189  			expBanner:     "myBanner",
   190  			retRules:      nil,
   191  			retErr:        nil,
   192  			expStatusCode: http.StatusOK,
   193  			expOutput:     JSONEq("null"),
   194  		},
   195  		"Error return": {
   196  			url:           "/admin/rules/banner/commands?bannerName=aBanner",
   197  			expBanner:     "aBanner",
   198  			retRules:      []rulesengine.Rule{},
   199  			retErr:        fmt.Errorf("an error"),
   200  			expStatusCode: http.StatusInternalServerError,
   201  			expOutput:     JSONEmpty(),
   202  		},
   203  		"Ok return": {
   204  			url:           "/admin/rules/banner/commands?bannerName=myBanner",
   205  			expBanner:     "myBanner",
   206  			retRules:      []rulesengine.Rule{{Command: rulesengine.Command{Name: "ls", ID: "efgh"}, Privileges: []rulesengine.Privilege{{Name: "read", ID: "abcd"}}}},
   207  			retErr:        nil,
   208  			expStatusCode: http.StatusOK,
   209  			expOutput: JSONEq(`[{
   210  				"command": {
   211  					"name": "ls",
   212  					"id": "efgh"
   213  				},
   214  				"privileges": [{
   215  					"name": "read",
   216  					"id": "abcd"
   217  				}]
   218  			}]`),
   219  		},
   220  		"Missing Banner Name": {
   221  			url:           "/admin/rules/banner/commands?bannerName=",
   222  			expBanner:     "",
   223  			retRules:      []rulesengine.Rule{{Command: rulesengine.Command{Name: "ls", ID: "efgh"}, Privileges: []rulesengine.Privilege{{Name: "read", ID: "abcd"}}}},
   224  			retErr:        nil,
   225  			expStatusCode: http.StatusBadRequest,
   226  			expOutput:     JSONEmpty(),
   227  		},
   228  	}
   229  
   230  	for name, tc := range tests {
   231  		tc := tc
   232  		t.Run(name, func(t *testing.T) {
   233  			t.Parallel()
   234  
   235  			log := newLogger()
   236  
   237  			ruleseng := getBannerMock{
   238  				retRules: tc.retRules,
   239  				retErr:   tc.retErr,
   240  			}
   241  
   242  			r := httptest.NewRecorder()
   243  			_, ginEngine := getTestGinContext(r)
   244  			_, err := New(ginEngine, &ruleseng, log)
   245  			assert.NoError(t, err)
   246  
   247  			req, err := http.NewRequest(http.MethodGet, tc.url, nil)
   248  			assert.NoError(t, err)
   249  
   250  			ginEngine.ServeHTTP(r, req)
   251  
   252  			assert.Equal(t, tc.expStatusCode, r.Result().StatusCode)
   253  
   254  			tc.expOutput(t, r.Body.String())
   255  		})
   256  	}
   257  }
   258  
   259  func TestDeleteRuleErrors(t *testing.T) {
   260  	t.Parallel()
   261  
   262  	tests := map[string]struct {
   263  		url string
   264  
   265  		expStatus int
   266  		expOut    StringAssertionFunc
   267  	}{
   268  		"Delete Rule called without a bannerName": {
   269  			url: "/admin/rules/banner/commands/rm/privileges/basic?bannerName=",
   270  
   271  			expStatus: http.StatusBadRequest,
   272  			expOut:    JSONEmpty(),
   273  		},
   274  		"Delete Rule called without a query parameter": {
   275  			url: "/admin/rules/banner/commands/rm/privileges/basic",
   276  
   277  			expStatus: http.StatusBadRequest,
   278  			expOut:    JSONEmpty(),
   279  		},
   280  		"Delete Rule called without a command": {
   281  			url: "/admin/rules/banner/commands//privileges/basic?bannerName=myBanner",
   282  
   283  			expStatus: http.StatusBadRequest,
   284  			expOut:    JSONEmpty(),
   285  		},
   286  	}
   287  
   288  	// Create mock with no implementation to ensure server panics (returns 500)
   289  	// if rulesengine is called
   290  	deleteMock := struct {
   291  		RulesEngine
   292  	}{}
   293  
   294  	for name, tc := range tests {
   295  		tc := tc
   296  		t.Run(name, func(t *testing.T) {
   297  			t.Parallel()
   298  
   299  			log := newLogger()
   300  
   301  			r := httptest.NewRecorder()
   302  			_, ginEngine := getTestGinContext(r)
   303  			_, err := New(ginEngine, deleteMock, log)
   304  			assert.NoError(t, err)
   305  
   306  			req, err := http.NewRequest(
   307  				http.MethodDelete,
   308  				tc.url,
   309  				nil,
   310  			)
   311  			assert.NoError(t, err)
   312  
   313  			ginEngine.ServeHTTP(r, req)
   314  
   315  			assert.Equal(t, tc.expStatus, r.Result().StatusCode)
   316  
   317  			tc.expOut(t, r.Body.String())
   318  		})
   319  	}
   320  }
   321  
   322  type postBannerRulesMock struct {
   323  	RulesEngine
   324  
   325  	dataRet rulesengine.AddRuleResult
   326  	errRet  error
   327  
   328  	callCount  int
   329  	bannerName string
   330  	rules      rulesengine.WriteRules
   331  }
   332  
   333  func (pr *postBannerRulesMock) AddBannerRules(_ context.Context, bannerName string, rules rulesengine.WriteRules) (rulesengine.AddRuleResult, error) {
   334  	pr.callCount = pr.callCount + 1
   335  
   336  	pr.bannerName = bannerName
   337  	pr.rules = rules
   338  
   339  	return pr.dataRet, pr.errRet
   340  }
   341  
   342  func TestPostRulesInBanner(t *testing.T) {
   343  	t.Parallel()
   344  
   345  	tests := map[string]struct {
   346  		url     string
   347  		reqBody string
   348  
   349  		mockDataRet rulesengine.AddRuleResult
   350  		mockErrRet  error
   351  
   352  		expMockCalledCount int
   353  		expCalledBanner    string
   354  		expCalledRules     rulesengine.WriteRules
   355  
   356  		expCode int
   357  		expOut  string
   358  	}{
   359  		"Ok": {
   360  			url: "/admin/rules/banner/commands?bannerName=myBanner",
   361  			reqBody: `[
   362  				{"command": "ls", "privileges": ["read","write"]},
   363  				{"command": "cat", "privileges": ["read","write"]}
   364  			]`,
   365  
   366  			expMockCalledCount: 1,
   367  			expCalledBanner:    "myBanner",
   368  			expCalledRules: rulesengine.WriteRules{
   369  				{Command: "ls", Privileges: []string{"read", "write"}},
   370  				{Command: "cat", Privileges: []string{"read", "write"}},
   371  			},
   372  
   373  			expCode: http.StatusOK,
   374  			expOut:  ``,
   375  		},
   376  		"Invalid JSON": {
   377  			url:     "/admin/rules/banner/commands?bannerName=myBanner",
   378  			reqBody: `[{"comm`,
   379  
   380  			expMockCalledCount: 0,
   381  
   382  			expCode: http.StatusBadRequest,
   383  			expOut:  ``,
   384  		},
   385  		"Invalid payload": {
   386  			url:     "/admin/rules/banner/commands?bannerName=myBanner",
   387  			reqBody: `[{"command": "", "privileges": ["read"]}]`,
   388  
   389  			expMockCalledCount: 0,
   390  
   391  			expCode: http.StatusBadRequest,
   392  			expOut:  ``,
   393  		},
   394  		"Rulesengine Error": {
   395  			url: "/admin/rules/banner/commands?bannerName=aBanner",
   396  			reqBody: `[
   397  				{"command": "ls", "privileges": ["read","write"]},
   398  				{"command": "cat", "privileges": ["read","write"]}
   399  			]`,
   400  
   401  			mockDataRet: rulesengine.AddRuleResult{},
   402  			mockErrRet:  fmt.Errorf("an error occurred"),
   403  
   404  			expMockCalledCount: 1,
   405  			expCalledBanner:    "aBanner",
   406  			expCalledRules: rulesengine.WriteRules{
   407  				{Command: "ls", Privileges: []string{"read", "write"}},
   408  				{Command: "cat", Privileges: []string{"read", "write"}},
   409  			},
   410  
   411  			expCode: http.StatusInternalServerError,
   412  			expOut:  ``,
   413  		},
   414  		"Rulesengine Conflict": {
   415  			url: "/admin/rules/banner/commands?bannerName=myBanner",
   416  			reqBody: `[
   417  				{"command": "ls", "privileges": ["read","write"]},
   418  				{"command": "cat", "privileges": ["read","write"]}
   419  			]`,
   420  
   421  			mockDataRet: rulesengine.AddRuleResult{Errors: []rulesengine.Error{
   422  				{Banner: "myBanner", Type: rulesengine.UnknownBanner},
   423  				{Command: "ls", Type: rulesengine.UnknownCommand},
   424  			}},
   425  			mockErrRet: nil,
   426  
   427  			expMockCalledCount: 1,
   428  			expCalledBanner:    "myBanner",
   429  			expCalledRules: rulesengine.WriteRules{
   430  				{Command: "ls", Privileges: []string{"read", "write"}},
   431  				{Command: "cat", Privileges: []string{"read", "write"}},
   432  			},
   433  
   434  			expCode: http.StatusNotFound,
   435  			expOut: `{
   436  				"errors": [
   437  					{"banner": "myBanner", "type":"Unknown Banner"},
   438  					{"command":"ls","type":"Unknown Command"}
   439  				]
   440  			}`,
   441  		},
   442  		"Post with Missing Banner": {
   443  			url: "/admin/rules/banner/commands?bannerName=",
   444  			reqBody: `[
   445  				{"command": "ls", "privileges": ["read","write"]},
   446  				{"command": "cat", "privileges": ["read","write"]}
   447  			]`,
   448  
   449  			expMockCalledCount: 0,
   450  
   451  			expCode: http.StatusBadRequest,
   452  			expOut:  ``,
   453  		},
   454  		"Post with Missing Query string": {
   455  			url: "/admin/rules/banner/commands",
   456  			reqBody: `[
   457  				{"command": "ls", "privileges": ["read","write"]},
   458  				{"command": "cat", "privileges": ["read","write"]}
   459  			]`,
   460  
   461  			expMockCalledCount: 0,
   462  
   463  			expCode: http.StatusBadRequest,
   464  			expOut:  ``,
   465  		},
   466  	}
   467  
   468  	for name, tc := range tests {
   469  		tc := tc
   470  		t.Run(name, func(t *testing.T) {
   471  			t.Parallel()
   472  
   473  			ruleseng := postBannerRulesMock{
   474  				dataRet: tc.mockDataRet,
   475  				errRet:  tc.mockErrRet,
   476  			}
   477  
   478  			log := newLogger()
   479  
   480  			r := httptest.NewRecorder()
   481  			_, ginEngine := getTestGinContext(r)
   482  			_, err := New(ginEngine, &ruleseng, log)
   483  			assert.NoError(t, err)
   484  
   485  			req, err := http.NewRequest(http.MethodPost, tc.url, strings.NewReader(tc.reqBody))
   486  			assert.NoError(t, err)
   487  
   488  			ginEngine.ServeHTTP(r, req)
   489  
   490  			assert.Equal(t, tc.expCode, r.Result().StatusCode)
   491  
   492  			assert.Equal(t, tc.expMockCalledCount, ruleseng.callCount)
   493  			assert.Equal(t, tc.expCalledBanner, ruleseng.bannerName)
   494  			assert.Equal(t, tc.expCalledRules, ruleseng.rules)
   495  
   496  			if tc.expOut == "" {
   497  				assert.Empty(t, r.Body.String())
   498  			} else {
   499  				assert.JSONEq(t, tc.expOut, r.Body.String())
   500  			}
   501  		})
   502  	}
   503  }
   504  
   505  type getRulesForSpecificCommandForAllBannersMock struct {
   506  	RulesEngine
   507  
   508  	Out rulesengine.ReadBannerRule
   509  	Err error
   510  
   511  	commandName string
   512  }
   513  
   514  func (m *getRulesForSpecificCommandForAllBannersMock) ReadBannerRulesForCommand(_ context.Context, commandName string) (rulesengine.ReadBannerRule, error) {
   515  	m.commandName = commandName
   516  	return m.Out, m.Err
   517  }
   518  
   519  func TestGetRulesForSpecificCommandForAllBanners(t *testing.T) {
   520  	t.Parallel()
   521  
   522  	tests := map[string]struct {
   523  		commandName string
   524  
   525  		rengOut rulesengine.ReadBannerRule
   526  		rengErr error
   527  
   528  		expStatus int
   529  		expOut    StringAssertionFunc
   530  	}{
   531  		"Standard": {
   532  			commandName: "ls",
   533  
   534  			rengOut: rulesengine.ReadBannerRule{
   535  				Command: rulesengine.Command{Name: "ls", ID: "a"},
   536  				Banners: []rulesengine.BannerPrivOverrides{
   537  					{
   538  						Banner: rulesengine.Banner{BannerName: "myBanner", BannerID: "b"},
   539  						Privileges: []rulesengine.Privilege{
   540  							{Name: "ea-read", ID: "c"},
   541  						},
   542  					},
   543  				},
   544  			},
   545  			rengErr: nil,
   546  
   547  			expStatus: http.StatusOK,
   548  			expOut: JSONEq(`{
   549  				"command": {"name": "ls", "id": "a"},
   550  				"banners": [
   551  					{
   552  						"banner": {"name": "myBanner", "id": "b"},
   553  						"privileges": [
   554  							{"name":"ea-read","id":"c"}
   555  						]
   556  					}
   557  				]
   558  			}`),
   559  		},
   560  		"Error Return": {
   561  			commandName: "cat",
   562  			rengOut:     rulesengine.ReadBannerRule{},
   563  			rengErr:     fmt.Errorf("an error"),
   564  			expStatus:   http.StatusInternalServerError,
   565  			expOut:      JSONEmpty(),
   566  		},
   567  		"Empty Return": {
   568  			commandName: "cat",
   569  			rengOut:     rulesengine.ReadBannerRule{},
   570  			rengErr:     nil,
   571  			expStatus:   http.StatusOK,
   572  			expOut:      JSONEq(`null`),
   573  		},
   574  	}
   575  
   576  	for name, tc := range tests {
   577  		tc := tc
   578  		t.Run(name, func(t *testing.T) {
   579  			t.Parallel()
   580  
   581  			log := newLogger()
   582  
   583  			ruleseng := getRulesForSpecificCommandForAllBannersMock{
   584  				Out: tc.rengOut,
   585  				Err: tc.rengErr,
   586  			}
   587  
   588  			r := httptest.NewRecorder()
   589  			_, ginEngine := getTestGinContext(r)
   590  			_, err := New(ginEngine, &ruleseng, log)
   591  			assert.NoError(t, err)
   592  
   593  			req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/admin/rules/banner/commands/%s", tc.commandName), nil)
   594  			assert.NoError(t, err)
   595  
   596  			ginEngine.ServeHTTP(r, req)
   597  
   598  			assert.Equal(t, tc.expStatus, r.Result().StatusCode)
   599  
   600  			assert.Equal(t, tc.commandName, ruleseng.commandName)
   601  
   602  			tc.expOut(t, r.Body.String())
   603  		})
   604  	}
   605  }
   606  
   607  type getRulesForSpecificCommandForBannerMock struct {
   608  	RulesEngine
   609  
   610  	Out rulesengine.Rule
   611  	Err error
   612  
   613  	bannerName  string
   614  	commandName string
   615  }
   616  
   617  func (m *getRulesForSpecificCommandForBannerMock) ReadBannerRulesForCommandAndBanner(_ context.Context, bannerName string, commandName string) (rulesengine.Rule, error) {
   618  	m.bannerName = bannerName
   619  	m.commandName = commandName
   620  	return m.Out, m.Err
   621  }
   622  
   623  func TestReadAllRulesInBannerForCommand(t *testing.T) {
   624  	t.Parallel()
   625  
   626  	tests := map[string]struct {
   627  		bannerName  string
   628  		commandName string
   629  
   630  		expBannerName  StringAssertionFunc
   631  		expCommandName StringAssertionFunc
   632  
   633  		rengOut rulesengine.Rule
   634  		rengErr error
   635  
   636  		expStatus int
   637  		expOut    StringAssertionFunc
   638  	}{
   639  		"No Banner": {
   640  			bannerName:     "",
   641  			commandName:    "ls",
   642  			expBannerName:  JSONEmpty(),
   643  			expCommandName: JSONEmpty(),
   644  			rengOut:        rulesengine.Rule{},
   645  			rengErr:        nil,
   646  			expStatus:      http.StatusBadRequest,
   647  			expOut:         JSONEmpty(),
   648  		},
   649  
   650  		"Standard": {
   651  			bannerName:  "myBanner2",
   652  			commandName: "ls",
   653  
   654  			rengOut: rulesengine.Rule{
   655  				Command: rulesengine.Command{Name: "ls", ID: "a"},
   656  				Privileges: []rulesengine.Privilege{
   657  					{Name: "ea-read", ID: "c"},
   658  				},
   659  			},
   660  			rengErr: nil,
   661  
   662  			expStatus: http.StatusOK,
   663  			expOut: JSONEq(`{
   664  				"command": {"name": "ls", "id": "a"},
   665  				"privileges": [
   666  					{"name":"ea-read","id":"c"}
   667  				]
   668  			}`),
   669  		},
   670  		"Error Return": {
   671  			bannerName:  "myBanner",
   672  			commandName: "cat",
   673  			rengOut:     rulesengine.Rule{},
   674  			rengErr:     fmt.Errorf("an error"),
   675  			expStatus:   http.StatusInternalServerError,
   676  			expOut:      JSONEmpty(),
   677  		},
   678  		"Empty Return": {
   679  			bannerName:  "myBanner",
   680  			commandName: "cat",
   681  			rengOut:     rulesengine.Rule{},
   682  			rengErr:     nil,
   683  			expStatus:   http.StatusOK,
   684  			expOut:      JSONEq(`null`),
   685  		},
   686  	}
   687  
   688  	for name, tc := range tests {
   689  		tc := tc
   690  		t.Run(name, func(t *testing.T) {
   691  			t.Parallel()
   692  
   693  			log := newLogger()
   694  
   695  			ruleseng := getRulesForSpecificCommandForBannerMock{
   696  				Out: tc.rengOut,
   697  				Err: tc.rengErr,
   698  			}
   699  
   700  			r := httptest.NewRecorder()
   701  			_, ginEngine := getTestGinContext(r)
   702  			_, err := New(ginEngine, &ruleseng, log)
   703  			assert.NoError(t, err)
   704  
   705  			req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/admin/rules/banner/commands/%s?bannerName=%s", tc.commandName, tc.bannerName), nil)
   706  			assert.NoError(t, err)
   707  
   708  			ginEngine.ServeHTTP(r, req)
   709  
   710  			assert.Equal(t, tc.expStatus, r.Result().StatusCode)
   711  
   712  			if tc.expBannerName != nil {
   713  				tc.expBannerName(t, ruleseng.bannerName)
   714  			} else {
   715  				assert.Equal(t, tc.bannerName, ruleseng.bannerName)
   716  			}
   717  			if tc.expCommandName != nil {
   718  				tc.expCommandName(t, ruleseng.commandName)
   719  			} else {
   720  				assert.Equal(t, tc.commandName, ruleseng.commandName)
   721  			}
   722  
   723  			tc.expOut(t, r.Body.String())
   724  		})
   725  	}
   726  }
   727  
   728  type deleteBannerMock struct {
   729  	RulesEngine
   730  
   731  	banner, command, privilege string
   732  
   733  	retDelete rulesengine.DeleteResult
   734  	retErr    error
   735  }
   736  
   737  func (mc *deleteBannerMock) DeletePrivilegeFromBannerRule(_ context.Context, bannerName string, commandName string, privilegeName string) (rulesengine.DeleteResult, error) {
   738  	mc.banner = bannerName
   739  	mc.command = commandName
   740  	mc.privilege = privilegeName
   741  
   742  	return mc.retDelete, mc.retErr
   743  }
   744  
   745  func TestDeletePrivilegeFromBannerRule(t *testing.T) {
   746  	t.Parallel()
   747  
   748  	tests := map[string]struct {
   749  		banner    string
   750  		command   string
   751  		privilege string
   752  
   753  		retRes rulesengine.DeleteResult
   754  		retErr error
   755  
   756  		expStatus int
   757  		expOut    StringAssertionFunc
   758  	}{
   759  		"Delete rule Success": {
   760  			banner:    "myBanner",
   761  			command:   "ls",
   762  			privilege: "read",
   763  
   764  			retRes: rulesengine.DeleteResult{RowsAffected: 1},
   765  			retErr: nil,
   766  
   767  			expStatus: http.StatusOK,
   768  			expOut:    JSONEmpty(),
   769  		},
   770  		"Delete rule No Change With Errors": {
   771  			banner:    "myBanner",
   772  			command:   "ls",
   773  			privilege: "read",
   774  
   775  			retRes: rulesengine.DeleteResult{RowsAffected: 0, Errors: []rulesengine.Error{{Type: rulesengine.UnknownBanner, Banner: "myBanner"}}},
   776  			retErr: nil,
   777  
   778  			expStatus: http.StatusNotFound,
   779  			expOut:    JSONEq(`{"errors":[{"type":"Unknown Banner","banner":"myBanner"}]}`),
   780  		},
   781  		// TODO Is this test required/expected?
   782  		"Delete rule With Conflicts": {
   783  			banner:    "myBanner",
   784  			command:   "ls",
   785  			privilege: "read",
   786  
   787  			retRes: rulesengine.DeleteResult{RowsAffected: 0, Errors: []rulesengine.Error{{Type: rulesengine.Conflict, Banner: "myBanner"}}},
   788  			retErr: nil,
   789  
   790  			expStatus: http.StatusNotFound,
   791  			expOut:    JSONEq(`{"errors":[{"type":"Conflict","banner":"myBanner"}]}`),
   792  		},
   793  		"Delete rule application error": {
   794  			banner:    "myBanner",
   795  			command:   "ls",
   796  			privilege: "read",
   797  
   798  			retRes: rulesengine.DeleteResult{RowsAffected: 1},
   799  			retErr: fmt.Errorf("an error"),
   800  
   801  			expStatus: http.StatusInternalServerError,
   802  			expOut:    JSONEmpty(),
   803  		},
   804  	}
   805  
   806  	for name, tc := range tests {
   807  		tc := tc
   808  		t.Run(name, func(t *testing.T) {
   809  			t.Parallel()
   810  
   811  			log := newLogger()
   812  			ruleseng := deleteBannerMock{
   813  				retDelete: tc.retRes,
   814  				retErr:    tc.retErr,
   815  			}
   816  
   817  			r := httptest.NewRecorder()
   818  			_, ginEngine := getTestGinContext(r)
   819  			_, err := New(ginEngine, &ruleseng, log)
   820  			assert.NoError(t, err)
   821  
   822  			req, err := http.NewRequest(
   823  				http.MethodDelete,
   824  				"/admin/rules/banner/commands/"+tc.command+"/privileges/"+tc.privilege+"?bannerName="+tc.banner,
   825  				nil,
   826  			)
   827  			assert.NoError(t, err)
   828  
   829  			ginEngine.ServeHTTP(r, req)
   830  
   831  			assert.Equal(t, tc.expStatus, r.Result().StatusCode)
   832  
   833  			tc.expOut(t, r.Body.String())
   834  
   835  			assert.Equal(t, tc.banner, ruleseng.banner)
   836  			assert.Equal(t, tc.command, ruleseng.command)
   837  			assert.Equal(t, tc.privilege, ruleseng.privilege)
   838  		})
   839  	}
   840  }
   841  

View as plain text