feat: added token based communications

This commit is contained in:
Akhil Mohan
2024-01-27 12:38:23 +05:30
parent daa94db874
commit 20fb99f042
65 changed files with 699 additions and 360 deletions
@@ -25,7 +25,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretSnapshots = await server.services.snapshot.listSnapshots({
actor: req.permission.type,
@@ -54,7 +54,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const count = await server.services.snapshot.projectSecretSnapshotCount({
actor: req.permission.type,
@@ -107,7 +107,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const auditLogs = await server.services.auditLog.listProjectAuditLogs({
actorId: req.permission.id,
@@ -30,7 +30,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretSnapshot = await server.services.snapshot.getSnapshotData({
actor: req.permission.type,
@@ -54,7 +54,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretSnapshot = await server.services.snapshot.rollbackSnapshot({
actor: req.permission.type,
@@ -0,0 +1,6 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
export type TLicenseDalFactory = ReturnType<typeof licenseDalFactory>;
export const licenseDalFactory = (db: TDbClient) => ({ });
@@ -0,0 +1,34 @@
import axios from "axios";
import { getConfig } from "@app/lib/config/env";
import { TLicenseDalFactory } from "./license-dal";
type TLicenseServiceFactoryDep = {
licenseDal: TLicenseDalFactory;
};
export type TLicenseServiceFactory = ReturnType<typeof licenseServiceFactory>;
export const licenseServiceFactory = ({ licenseDal }: TLicenseServiceFactoryDep) => {
const appCfg = getConfig();
const licenceApi = axios.create({
baseURL: appCfg.LICENCE_SERVER_URL
});
const generateOrgCustomerId = async (orgName: string, email: string) => {
const {
data: { customerId }
} = await licenceApi.post("/api/license-server/v1/customers", { email, name: orgName });
return customerId;
};
const removeOrgCustomer = async (customerId: string) => {
await licenceApi.delete(`/api/license-server/v1/customers/${customerId}`);
};
return {
generateOrgCustomerId,
removeOrgCustomer
};
};
@@ -1,12 +1,13 @@
import { createMongoAbility, MongoAbility, RawRuleOf } from "@casl/ability";
import { PackRule, unpackRules } from "@casl/ability/extra";
import { OrgMembershipRole, ProjectMembershipRole } from "@app/db/schemas";
import { OrgMembershipRole, ProjectMembershipRole, ServiceTokenScopes } from "@app/db/schemas";
import { conditionsMatcher } from "@app/lib/casl";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type";
import { TOrgRoleDalFactory } from "@app/services/org/org-role-dal";
import { TProjectRoleDalFactory } from "@app/services/project-role/project-role-dal";
import { TServiceTokenDalFactory } from "@app/services/service-token/service-token-dal";
import {
orgAdminPermissions,
@@ -16,6 +17,7 @@ import {
} from "./org-permission";
import { TPermissionDalFactory } from "./permission-dal";
import {
buildServiceTokenProjectPermission,
projectAdminPermissions,
projectMemberPermissions,
projectNoAccessPermissions,
@@ -25,6 +27,7 @@ import {
type TPermissionServiceFactoryDep = {
orgRoleDal: Pick<TOrgRoleDalFactory, "findOne">;
projectRoleDal: Pick<TProjectRoleDalFactory, "findOne">;
serviceTokenDal: Pick<TServiceTokenDalFactory, "findById">;
permissionDal: TPermissionDalFactory;
};
@@ -33,7 +36,8 @@ export type TPermissionServiceFactory = ReturnType<typeof permissionServiceFacto
export const permissionServiceFactory = ({
permissionDal,
orgRoleDal,
projectRoleDal
projectRoleDal,
serviceTokenDal
}: TPermissionServiceFactoryDep) => {
const buildOrgPermission = (role: string, permission?: unknown) => {
switch (role) {
@@ -157,10 +161,25 @@ export const permissionServiceFactory = ({
};
};
const getServiceTokenProjectPermission = async (serviceTokenId: string, projectId: string) => {
const serviceToken = await serviceTokenDal.findById(serviceTokenId);
if (serviceToken.projectId !== projectId)
throw new UnauthorizedError({
message: "Failed to find service authorization for given project"
});
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
return {
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
member: undefined
};
};
const getProjectPermission = async (type: ActorType, id: string, projectId: string) => {
switch (type) {
case ActorType.USER:
return getUserProjectPermission(id, projectId);
case ActorType.SERVICE:
return getServiceTokenProjectPermission(id, projectId);
case ActorType.IDENTITY:
return getIdentityProjectPermission(id, projectId);
default:
@@ -230,6 +230,33 @@ const buildNoAccessProjectPermission = () => {
return build({ conditionsMatcher });
};
export const buildServiceTokenProjectPermission = (
scopes: Array<{ secretPath: string; environment: string }>,
permission: string[]
) => {
const canWrite = permission.includes("write");
const canRead = permission.includes("read");
const { can, build } = new AbilityBuilder<MongoAbility<ProjectPermissionSet>>(createMongoAbility);
scopes.forEach(({ secretPath, environment }) => {
if (canWrite) {
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Secrets, { secretPath, environment });
can(ProjectPermissionActions.Create, ProjectPermissionSub.Secrets, {
secretPath,
environment
});
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Secrets, {
secretPath,
environment
});
}
if (canRead) {
can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets, { secretPath, environment });
}
});
return build({ conditionsMatcher });
};
export const projectNoAccessPermissions = buildNoAccessProjectPermission();
/**