github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/web/interceptor/access_control_methods_test.go (about) 1 package interceptor 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 "github.com/quickfeed/quickfeed/qf/qfconnect" 9 ) 10 11 // TestAccessControlMethods checks that all QuickFeedService methods have an entry 12 // in the access control list. 13 func TestAccessControlQuickFeedServiceMethods(t *testing.T) { 14 service := reflect.TypeOf(qfconnect.UnimplementedQuickFeedServiceHandler{}) 15 serviceMethods := make(map[string]bool) 16 for i := 0; i < service.NumMethod(); i++ { 17 serviceMethods[service.Method(i).Name] = true 18 } 19 if err := checkAccessControlMethods(serviceMethods); err != nil { 20 t.Error(err) 21 } 22 } 23 24 func TestAccessControlMethodsChecker(t *testing.T) { 25 serviceMethods := map[string]bool{ 26 "GetUser": true, 27 "GetCourse": true, 28 "GetCourses": true, 29 "CreateEnrollment": true, 30 "UpdateCourseVisibility": true, 31 "UpdateUser": true, 32 "GetEnrollments": true, 33 "GetSubmissions": true, 34 "CreateGroup": true, 35 "GetGroup": true, 36 "GetAssignments": true, 37 "GetRepositories": true, 38 "UpdateGroup": true, 39 "DeleteGroup": true, 40 "GetGroupsByCourse": true, 41 "UpdateCourse": true, 42 "UpdateEnrollments": true, 43 "UpdateAssignments": true, 44 "UpdateSubmission": true, 45 "UpdateSubmissions": true, 46 "RebuildSubmissions": true, 47 "CreateBenchmark": true, 48 "UpdateBenchmark": true, 49 "DeleteBenchmark": true, 50 "CreateCriterion": true, 51 "UpdateCriterion": true, 52 "DeleteCriterion": true, 53 "CreateReview": true, 54 "UpdateReview": true, 55 "IsEmptyRepo": true, 56 "GetSubmissionsByCourse": true, 57 "GetUsers": true, 58 "GetOrganization": true, 59 "CreateCourse": true, 60 "GetSubmission": true, 61 "SubmissionStream": true, 62 } 63 if err := checkAccessControlMethods(serviceMethods); err != nil { 64 t.Error(err) 65 } 66 67 // Disable CreateCourse method in the serviceMethods map; 68 // make it appear as if it was removed from the service interface. 69 serviceMethods["CreateCourse"] = false 70 err := checkAccessControlMethods(serviceMethods) 71 expectedErr := "superfluous method(s) in access control table: [CreateCourse]" 72 if err == nil { 73 t.Errorf("Expected error: %q, got nil", expectedErr) 74 } 75 if err.Error() != expectedErr { 76 t.Errorf("Expected error: %q, got: %q", expectedErr, err.Error()) 77 } 78 79 // Add new Dummy method to the serviceMethods map; 80 // make it appear as if it was added to the service interface. 81 serviceMethods["Dummy"] = true 82 err = checkAccessControlMethods(serviceMethods) 83 expectedErr = "missing required method(s) in access control table: [Dummy]" 84 if err == nil { 85 t.Errorf("Expected error: %q, got nil", expectedErr) 86 } 87 if err.Error() != expectedErr { 88 t.Errorf("Expected error: %q, got: %q", expectedErr, err.Error()) 89 } 90 } 91 92 func has(method string) bool { 93 _, ok := accessRolesFor[method] 94 return ok 95 } 96 97 func checkAccessControlMethods(expectedMethodNames map[string]bool) error { 98 missingMethods := []string{} 99 superfluousMethods := []string{} 100 for method := range expectedMethodNames { 101 if !has(method) { 102 missingMethods = append(missingMethods, method) 103 } 104 } 105 for method := range accessRolesFor { 106 if !expectedMethodNames[method] { 107 superfluousMethods = append(superfluousMethods, method) 108 } 109 } 110 if len(missingMethods) > 0 { 111 return fmt.Errorf("missing required method(s) in access control table: %v", missingMethods) 112 } 113 if len(superfluousMethods) > 0 { 114 return fmt.Errorf("superfluous method(s) in access control table: %v", superfluousMethods) 115 } 116 return nil 117 }