From ce37b1f59bbe88e1766bd8a2b7ec73ec088c4d2e Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sun, 5 Dec 2021 19:40:37 +0000
Subject: [PATCH] Add tests for some resource-related operations

---
 integrationtest/errors_test.go    |  45 ++++++++
 integrationtest/resources_test.go | 171 ++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+)
 create mode 100644 integrationtest/resources_test.go

diff --git a/integrationtest/errors_test.go b/integrationtest/errors_test.go
index 3d43f095..e485805e 100644
--- a/integrationtest/errors_test.go
+++ b/integrationtest/errors_test.go
@@ -54,6 +54,51 @@ func TestIntegration_Error_GetUser(t *testing.T) {
 
 }
 
+func TestIntegration_Error_GetResource(t *testing.T) {
+	stop, _, c := startService(t)
+	defer stop()
+
+	testdata := []struct {
+		authUser        string
+		authGroup       string
+		resourceID      string
+		expectedErrCode int
+	}{
+		{"uno@investici.org", "", "cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com", http.StatusForbidden},
+		{testAdminUser, testAdminGroup, "cn=not-existing.com,uid=uno@investici.org,ou=People,dc=example,dc=com", http.StatusNotFound},
+		{testAdminUser, testAdminGroup, "badly,formatted,DN", http.StatusInternalServerError},
+	}
+
+	for _, td := range testdata {
+		var groups []string
+		if td.authGroup != "" {
+			groups = append(groups, td.authGroup)
+		}
+		err := c.request("/api/resource/get", &as.GetResourceRequest{
+			AdminResourceRequestBase: as.AdminResourceRequestBase{
+				ResourceRequestBase: as.ResourceRequestBase{
+					RequestBase: as.RequestBase{
+						SSO: c.ssoTicket(td.authUser, groups...),
+					},
+					ResourceID: as.ResourceID(td.resourceID),
+				},
+			},
+		}, nil)
+		if err == nil {
+			t.Errorf("oops, request as %s succeeded unexpectedly", td.authUser)
+			continue
+		}
+		var httpErr *httpError
+		if !errors.As(err, &httpErr) {
+			t.Errorf("oops, request as %s returned unexpected error: %v", td.authUser, err)
+			continue
+		}
+		if httpErr.code != td.expectedErrCode {
+			t.Errorf("request as %s returned error code %d, expected %d", td.authUser, httpErr.code, td.expectedErrCode)
+		}
+	}
+}
+
 func TestIntegration_Error_Validation(t *testing.T) {
 	stop, _, c := startService(t)
 	defer stop()
diff --git a/integrationtest/resources_test.go b/integrationtest/resources_test.go
new file mode 100644
index 00000000..d70876e8
--- /dev/null
+++ b/integrationtest/resources_test.go
@@ -0,0 +1,171 @@
+package integrationtest
+
+import (
+	"encoding/json"
+	"errors"
+	"testing"
+
+	as "git.autistici.org/ai3/accountserver"
+)
+
+func TestIntegration_GetResource_Auth(t *testing.T) {
+	stop, _, c := startService(t)
+	defer stop()
+
+	rid := "cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com"
+	testdata := []struct {
+		authUser   string
+		authGroup  string
+		resourceID string
+		expectedOk bool
+	}{
+		{"uno@investici.org", "users", rid, false},
+		{testAdminUser, testAdminGroup, rid, true},
+	}
+
+	for _, td := range testdata {
+		var groups []string
+		if td.authGroup != "" {
+			groups = append(groups, td.authGroup)
+		}
+
+		err := c.request("/api/resource/get", &as.GetResourceRequest{
+			AdminResourceRequestBase: as.AdminResourceRequestBase{
+				ResourceRequestBase: as.ResourceRequestBase{
+					RequestBase: as.RequestBase{
+						SSO: c.ssoTicket(td.authUser, groups...),
+					},
+					ResourceID: as.ResourceID(td.resourceID),
+				},
+			},
+		}, nil)
+		if td.expectedOk && err != nil {
+			t.Errorf("access error for user %s: expected ok, got error: %v", td.authUser, err)
+		} else if !td.expectedOk && err == nil {
+			t.Errorf("access error for user %s: expected error, got ok", td.authUser)
+		}
+	}
+}
+
+func TestIntegration_SetResourceStatus(t *testing.T) {
+	stop, _, c := startService(t)
+	defer stop()
+
+	rid := "cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com"
+	err := c.request("/api/resource/set_status", &as.SetResourceStatusRequest{
+		AdminResourceRequestBase: as.AdminResourceRequestBase{
+			ResourceRequestBase: as.ResourceRequestBase{
+				RequestBase: as.RequestBase{
+					SSO: c.ssoTicket(testAdminUser, testAdminGroup),
+				},
+				ResourceID: as.ResourceID(rid),
+			},
+		},
+		Status: as.ResourceStatusInactive,
+	}, nil)
+	if err != nil {
+		t.Fatalf("SetResourceStatus(): %v", err)
+	}
+}
+
+func TestIntegration_AdminUpdateResource(t *testing.T) {
+	stop, _, c := startService(t)
+	defer stop()
+
+	rid := "cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com"
+
+	getResource := func() *as.Resource {
+		var rsrc as.GetResourceResponse
+		err := c.request("/api/resource/get", &as.GetResourceRequest{
+			AdminResourceRequestBase: as.AdminResourceRequestBase{
+				ResourceRequestBase: as.ResourceRequestBase{
+					RequestBase: as.RequestBase{
+						SSO: c.ssoTicket(testAdminUser, testAdminGroup),
+					},
+					ResourceID: as.ResourceID(rid),
+				},
+			},
+		}, &rsrc)
+		if err != nil {
+			t.Fatalf("GetResource(): %v", err)
+		}
+		return rsrc.Resource
+	}
+
+	rsrc := getResource()
+	if rsrc.Website == nil {
+		t.Fatalf("resource has empty Website object: %+v", *rsrc)
+	}
+	rsrc.Website.AcceptMail = false
+
+	err := c.request("/api/resource/update", &as.AdminUpdateResourceRequest{
+		AdminResourceRequestBase: as.AdminResourceRequestBase{
+			ResourceRequestBase: as.ResourceRequestBase{
+				RequestBase: as.RequestBase{
+					SSO: c.ssoTicket(testAdminUser, testAdminGroup),
+				},
+				ResourceID: as.ResourceID(rid),
+			},
+		},
+		Resource: rsrc,
+	}, nil)
+	if err != nil {
+		t.Fatalf("AdminUpdateResource(): %v", err)
+	}
+
+	rsrc = getResource()
+	if rsrc.Website.AcceptMail {
+		t.Fatal("AdminUpdateResource() did not update the acceptMail field")
+	}
+}
+
+func TestIntegration_AdminUpdateResource_FailValidation(t *testing.T) {
+	stop, _, c := startService(t)
+	defer stop()
+
+	rid := "cn=example.com,uid=uno@investici.org,ou=People,dc=example,dc=com"
+
+	var resp as.GetResourceResponse
+	err := c.request("/api/resource/get", &as.GetResourceRequest{
+		AdminResourceRequestBase: as.AdminResourceRequestBase{
+			ResourceRequestBase: as.ResourceRequestBase{
+				RequestBase: as.RequestBase{
+					SSO: c.ssoTicket(testAdminUser, testAdminGroup),
+				},
+				ResourceID: as.ResourceID(rid),
+			},
+		},
+	}, &resp)
+	if err != nil {
+		t.Fatalf("GetResource(): %v", err)
+	}
+
+	rsrc := resp.Resource
+	rsrc.Website.UID = 42999
+
+	err = c.request("/api/resource/update", &as.AdminUpdateResourceRequest{
+		AdminResourceRequestBase: as.AdminResourceRequestBase{
+			ResourceRequestBase: as.ResourceRequestBase{
+				RequestBase: as.RequestBase{
+					SSO: c.ssoTicket(testAdminUser, testAdminGroup),
+				},
+				ResourceID: as.ResourceID(rid),
+			},
+		},
+		Resource: rsrc,
+	}, nil)
+	if err == nil {
+		t.Fatal("AdminUpdateResource() accepted faulty update")
+	}
+	var httpErr *httpError
+	if !errors.As(err, &httpErr) {
+		t.Fatalf("AdminUpdateResource() did not return a structured error: %v", err)
+	}
+	var fields map[string][]string
+	if err := json.Unmarshal(httpErr.data, &fields); err != nil {
+		t.Fatalf("error unmarshaling JSON error: %v", err)
+	}
+	if values, ok := fields["website.uid"]; !ok || len(values) != 1 {
+		t.Fatalf("error does not contain details for the 'website.uid' field: %+v", fields)
+	}
+}
-- 
GitLab