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
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
169 retRules []rulesengine.Rule
170 retErr error
171
172
173 expBanner string
174
175
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
289
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
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