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  }