fix(git_server): make sure auth/repo resolvers take memerships/visibility into account
+ 36
- 10
app/services/gitServer/authorizationResolver.ts
@@ -3,6 +3,7 @@ import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
 import { GitServer } from "@ethicdevs/fastify-git-server";
 // app
 import { GitServerServiceDeps } from "./types";
+import { ResourceVisibility } from "@prisma/client";
 
 const makeAuthorizationResolver: ServiceMethodFactory<
   GitServerServiceDeps,

...
@@ -26,6 +27,7 @@ const makeAuthorizationResolver: ServiceMethodFactory<
     const org = await request.prisma.organization.findUnique({
       include: {
         owner: true,
+        memberships: true,
       },
       where: {
         slug: orgSlug,

...
@@ -49,8 +51,18 @@ const makeAuthorizationResolver: ServiceMethodFactory<
       return false;
     }
 
-    // for now only allow owner to push to its own repo (no members in model yet)
-    return org.ownerId === user.id && hashedPassword === user.hashedPassword;
+    if (
+      repo.visibility === ResourceVisibility.PUBLIC ||
+      repo.visibility === ResourceVisibility.UNLISTED
+    ) {
+      return true;
+    } else {
+      return !!(
+        (org.ownerId === user.id ||
+          org.memberships.find((m) => m.id === user.id)) &&
+        hashedPassword === user.hashedPassword
+      );
+    }
   };
 };
 

app/services/gitServer/repositoryResolver.ts
@@ -6,6 +6,7 @@ import { GitServer } from "@ethicdevs/fastify-git-server";
 // app
 import type { GitServerServiceDeps } from "./types";
 import { Env } from "../../env";
+import { ResourceVisibility } from "@prisma/client";
 
 const makeRepositoryResolver: ServiceMethodFactory<
   GitServerServiceDeps,

...
@@ -48,10 +49,20 @@ const makeRepositoryResolver: ServiceMethodFactory<
       join(Env.GIT_REPOSITORIES_ROOT, org.slug, repo.slug)
     );
 
-    return {
-      authMode: GitServer.AuthMode.ALWAYS,
-      gitRepositoryDir,
-    };
+    if (
+      repo.visibility === ResourceVisibility.PUBLIC ||
+      repo.visibility === ResourceVisibility.UNLISTED
+    ) {
+      return {
+        authMode: GitServer.AuthMode.PUSH_ONLY,
+        gitRepositoryDir,
+      };
+    } else {
+      return {
+        authMode: GitServer.AuthMode.ALWAYS,
+        gitRepositoryDir,
+      };
+    }
   };
 };
 

app/services/repository/getRepositoryHTTPCloneUrl.ts
@@ -1,7 +1,7 @@
 // 1st-party
 import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
 // generated via script[generate:prisma]
-import type { Repository } from "@prisma/client";
+import { Repository, ResourceVisibility } from "@prisma/client";
 // app
 import { Env } from "../../env";
 import { getEnv } from "../../utils/server";

...
@@ -27,11 +27,14 @@ const makeGetRepositoryHTTPCloneUrl: ServiceMethodFactory<
       );
     }
 
-    const authCredentials = `${parentOrg.slug}:secret`;
+    const authCredentials =
+      repo.visibility === ResourceVisibility.PRIVATE
+        ? `${parentOrg.slug}:secret@`
+        : "";
     const baseUrl =
       env === "development"
-        ? `${Env.DEPLOYMENT_SCHEME}://${authCredentials}@${Env.DEPLOYMENT_DOMAIN}:${Env.PORT}`
-        : `${Env.DEPLOYMENT_SCHEME}://${authCredentials}@${Env.DEPLOYMENT_DOMAIN}`;
+        ? `${Env.DEPLOYMENT_SCHEME}://${authCredentials}${Env.DEPLOYMENT_DOMAIN}:${Env.PORT}`
+        : `${Env.DEPLOYMENT_SCHEME}://${authCredentials}${Env.DEPLOYMENT_DOMAIN}`;
 
     return `${baseUrl}/${parentOrg.slug}/${repo.slug}.git`;
   };