import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
import { GitServer } from "@ethicdevs/fastify-git-server";
import { GitServerServiceDeps } from "./types";
import { ResourceVisibility } from "@prisma/client";
const makeAuthorizationResolver: ServiceMethodFactory<
GitServerServiceDeps,
[string, GitServer.AuthCredentials],
PromiseLike<boolean>
> = ({ cryptoService, request }) => {
return async (repoPath, { username, password }) => {
const [orgSlug, repoSlugUnsafe] = repoPath.split("/");
const isPubKeyAuth = repoSlugUnsafe.endsWith(".pub");
const repoSlug = repoSlugUnsafe.replace(/\.(git|pub)$/, "");
console.log("AuthorizationResolver called with:", {
repoPath,
username,
isPubKeyAuth,
});
const user = await request.prisma.user.findUnique({
where: {
username,
},
});
if (user == null) {
return false;
}
const org = await request.prisma.organization.findUnique({
include: {
owner: true,
memberships: true,
},
where: {
slug: orgSlug,
},
});
if (org == null) {
return false;
}
const repo = await request.prisma.repository.findFirst({
where: {
slug: repoSlug,
organization: {
slug: orgSlug,
},
},
});
if (repo == null) {
return false;
}
const repoOrgOwnerIsReqUser = org.ownerId === user.id;
const repoMembershipsHasReqUser =
org.memberships.find((m) => m.id === user.id) != null;
if (repo.visibility === ResourceVisibility.PUBLIC) {
return true;
} else {
if (
repoOrgOwnerIsReqUser === false &&
repoMembershipsHasReqUser === false
) {
return false;
}
if (isPubKeyAuth) {
const matchingPk = await request.prisma.userSSHKey.findFirst({
where: {
key: password,
revoked: false,
},
include: {
user: true,
},
});
return (
matchingPk != null &&
matchingPk.user.id === user.id &&
matchingPk.user.username === username
);
} else {
const hashedPassword = cryptoService.computeHash(password);
return hashedPassword === user.hashedPassword;
}
}
};
};
export default makeAuthorizationResolver;