TestGitHubRoutes_RoleGating exercises the router-level middleware split introduced in MUL-2413: GET installations runs under RequireWorkspaceMemberFromURL while connect / delete remain behind RequireWorkspaceRoleFromURL(owner, admin). The handler-level tests above inject a member into context direct
(t *testing.T)
| 1891 | // itself — a future routing change that accidentally moved one of the |
| 1892 | // admin-only routes into the member group would slip past them. |
| 1893 | func TestGitHubRoutes_RoleGating(t *testing.T) { |
| 1894 | if testHandler == nil { |
| 1895 | t.Skip("handler test fixture not initialized (no DB?)") |
| 1896 | } |
| 1897 | ctx := context.Background() |
| 1898 | |
| 1899 | const slug = "github-routes-role-gating" |
| 1900 | _, _ = testPool.Exec(ctx, `DELETE FROM workspace WHERE slug = $1`, slug) |
| 1901 | |
| 1902 | var wsID string |
| 1903 | if err := testPool.QueryRow(ctx, ` |
| 1904 | INSERT INTO workspace (name, slug, description, issue_prefix) |
| 1905 | VALUES ($1, $2, $3, $4) |
| 1906 | RETURNING id |
| 1907 | `, "GitHub Routes Role Gating", slug, "github routes role gating", "GRG").Scan(&wsID); err != nil { |
| 1908 | t.Fatalf("create workspace: %v", err) |
| 1909 | } |
| 1910 | |
| 1911 | // Three workspace members + one outsider. We attach the requesting user |
| 1912 | // via the X-User-ID header so the middleware reads them off the auth |
| 1913 | // boundary just like a real request. |
| 1914 | mkUser := func(t *testing.T, label string) string { |
| 1915 | t.Helper() |
| 1916 | var id string |
| 1917 | email := fmt.Sprintf("github-routes-%s-%s@multica.ai", slug, label) |
| 1918 | if err := testPool.QueryRow(ctx, ` |
| 1919 | INSERT INTO "user" (name, email) VALUES ($1, $2) RETURNING id |
| 1920 | `, "GHR "+label, email).Scan(&id); err != nil { |
| 1921 | t.Fatalf("create user %s: %v", label, err) |
| 1922 | } |
| 1923 | return id |
| 1924 | } |
| 1925 | adminUserID := mkUser(t, "admin") |
| 1926 | memberUserID := mkUser(t, "member") |
| 1927 | outsiderUserID := mkUser(t, "outsider") |
| 1928 | |
| 1929 | for _, m := range []struct { |
| 1930 | userID, role string |
| 1931 | }{ |
| 1932 | {adminUserID, "admin"}, |
| 1933 | {memberUserID, "member"}, |
| 1934 | } { |
| 1935 | if _, err := testPool.Exec(ctx, ` |
| 1936 | INSERT INTO member (workspace_id, user_id, role) VALUES ($1, $2, $3) |
| 1937 | `, wsID, m.userID, m.role); err != nil { |
| 1938 | t.Fatalf("insert member (%s): %v", m.role, err) |
| 1939 | } |
| 1940 | } |
| 1941 | |
| 1942 | const installationID int64 = 90909090 |
| 1943 | createdInst, err := testHandler.Queries.CreateGitHubInstallation(ctx, db.CreateGitHubInstallationParams{ |
| 1944 | WorkspaceID: parseUUID(wsID), |
| 1945 | InstallationID: installationID, |
| 1946 | AccountLogin: "routes-acct", |
| 1947 | AccountType: "User", |
| 1948 | }) |
| 1949 | if err != nil { |
| 1950 | t.Fatalf("CreateGitHubInstallation: %v", err) |
nothing calls this directly
no test coverage detected