@speckle/shared
Version:
Shared code between various Speckle JS packages
203 lines • 9.34 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureCanUseProjectWorkspacePlanFeatureFragment = exports.ensureImplicitProjectMemberWithWriteAccessFragment = exports.ensureImplicitProjectMemberWithReadAccessFragment = exports.checkIfPubliclyReadableProjectFragment = exports.ensureProjectWorkspaceAccessFragment = exports.ensureMinimumProjectRoleFragment = void 0;
const result_1 = require("true-myth/result");
const authErrors_js_1 = require("../domain/authErrors.js");
const constants_js_1 = require("../../core/constants.js");
const roles_js_1 = require("../domain/logic/roles.js");
const projects_js_1 = require("../checks/projects.js");
const workspaces_js_1 = require("./workspaces.js");
const server_js_1 = require("./server.js");
const types_js_1 = require("../domain/projects/types.js");
const workspaceRoleImplicitProjectRoleMap = (projectVisibility) => {
const isFullyPrivate = projectVisibility === types_js_1.ProjectVisibility.Private;
return {
[constants_js_1.Roles.Workspace.Admin]: constants_js_1.Roles.Stream.Owner,
[constants_js_1.Roles.Workspace.Member]: isFullyPrivate ? null : constants_js_1.Roles.Stream.Reviewer,
[constants_js_1.Roles.Workspace.Guest]: null
};
};
/**
* Ensure user has a minimum explicit or implicit project role
*/
const ensureMinimumProjectRoleFragment = (loaders) => async ({ userId, projectId, role, explicit }) => {
const requiredProjectRole = role || constants_js_1.Roles.Stream.Reviewer;
const isTestingForMinimumAccess = requiredProjectRole === constants_js_1.Roles.Stream.Reviewer;
const env = await loaders.getEnv();
const project = await loaders.getProject({ projectId });
if (!project)
return (0, result_1.err)(new authErrors_js_1.ProjectNotFoundError());
// Check for explicit project role first
const hasExplicitProjectRole = await (0, projects_js_1.hasMinimumProjectRole)(loaders)({
userId,
projectId,
role: requiredProjectRole
});
if (hasExplicitProjectRole)
return (0, result_1.ok)();
// Now check if there's an implicit one
const { workspaceId } = project;
if (env.FF_WORKSPACES_MODULE_ENABLED && !!workspaceId) {
// Check for implicit workspace project role
const userWorkspaceRole = await loaders.getWorkspaceRole({ userId, workspaceId });
if (userWorkspaceRole) {
const implicitProjectRole = explicit
? null
: workspaceRoleImplicitProjectRoleMap(project.visibility)[userWorkspaceRole];
if (implicitProjectRole) {
// Does it fit minimum?
if ((0, roles_js_1.isMinimumProjectRole)(implicitProjectRole, requiredProjectRole)) {
return (0, result_1.ok)();
}
else {
// Have some permissions, but not enough
return (0, result_1.err)(new authErrors_js_1.ProjectNotEnoughPermissionsError());
}
}
}
}
// Do we have any role at all?
const anyRoleFound = await loaders.getProjectRole({ userId, projectId });
return (0, result_1.err)(isTestingForMinimumAccess || !anyRoleFound
? new authErrors_js_1.ProjectNoAccessError()
: new authErrors_js_1.ProjectNotEnoughPermissionsError());
};
exports.ensureMinimumProjectRoleFragment = ensureMinimumProjectRoleFragment;
/**
* Ensure user has access to the project's workspace (has role & SSO session, if any), if it has one
*/
const ensureProjectWorkspaceAccessFragment = (loaders) => async ({ userId, projectId }) => {
const env = await loaders.getEnv();
const project = await loaders.getProject({ projectId });
if (!project)
return (0, result_1.err)(new authErrors_js_1.ProjectNotFoundError());
const { workspaceId } = project;
if (!workspaceId || !env.FF_WORKSPACES_MODULE_ENABLED)
return (0, result_1.ok)();
const memberWithSsoSession = await (0, workspaces_js_1.ensureWorkspaceRoleAndSessionFragment)(loaders)({
userId,
workspaceId
});
if (memberWithSsoSession.isErr) {
switch (memberWithSsoSession.error.code) {
case authErrors_js_1.WorkspaceNoAccessError.code:
return (0, result_1.err)(new authErrors_js_1.WorkspaceNoAccessError("You do not have access to this project's workspace"));
default:
return (0, result_1.err)(memberWithSsoSession.error);
}
}
return memberWithSsoSession;
};
exports.ensureProjectWorkspaceAccessFragment = ensureProjectWorkspaceAccessFragment;
/**
* Check if project is publicly readable or not
*/
const checkIfPubliclyReadableProjectFragment = (loaders) => async ({ projectId }) => {
const project = await loaders.getProject({ projectId });
if (!project)
return (0, result_1.err)(new authErrors_js_1.ProjectNotFoundError());
return (0, result_1.ok)(await (0, projects_js_1.isPubliclyReadableProject)(loaders)({ projectId }));
};
exports.checkIfPubliclyReadableProjectFragment = checkIfPubliclyReadableProjectFragment;
/**
* Ensure user has implicit/explicit project membership and read access
*/
const ensureImplicitProjectMemberWithReadAccessFragment = (loaders) => async ({ userId, projectId, role }) => {
// Ensure user is authed
const ensuredServerRole = await (0, server_js_1.ensureMinimumServerRoleFragment)(loaders)({
userId,
role: constants_js_1.Roles.Server.Guest
});
if (ensuredServerRole.isErr) {
return (0, result_1.err)(ensuredServerRole.error);
}
// Check if user has admin override enabled
const isAdminOverrideEnabled = await (0, server_js_1.checkIfAdminOverrideEnabledFragment)(loaders)({
userId
});
if (isAdminOverrideEnabled.isErr) {
return (0, result_1.err)(isAdminOverrideEnabled.error);
}
if (isAdminOverrideEnabled.value)
return (0, result_1.ok)();
// And ensure (implicit/explicit) project role
const ensuredProjectRole = await (0, exports.ensureMinimumProjectRoleFragment)(loaders)({
userId: userId,
projectId,
role
});
if (ensuredProjectRole.isErr) {
return (0, result_1.err)(ensuredProjectRole.error);
}
// No god mode, ensure workspace access
const ensuredWorkspaceAccess = await (0, exports.ensureProjectWorkspaceAccessFragment)(loaders)({
userId: userId,
projectId
});
if (ensuredWorkspaceAccess.isErr) {
return (0, result_1.err)(ensuredWorkspaceAccess.error);
}
return (0, result_1.ok)();
};
exports.ensureImplicitProjectMemberWithReadAccessFragment = ensureImplicitProjectMemberWithReadAccessFragment;
/**
* Ensure user has implicit/explicit project membership and write access
*/
const ensureImplicitProjectMemberWithWriteAccessFragment = (loaders) => async ({ userId, projectId, role }) => {
const requiredProjectRole = role || constants_js_1.Roles.Stream.Contributor;
const requiredServerRole = requiredProjectRole === constants_js_1.Roles.Stream.Owner
? constants_js_1.Roles.Server.User
: constants_js_1.Roles.Server.Guest;
// Ensure user is authed
const ensuredServerRole = await (0, server_js_1.ensureMinimumServerRoleFragment)(loaders)({
userId,
role: requiredServerRole
});
if (ensuredServerRole.isErr) {
return (0, result_1.err)(ensuredServerRole.error);
}
// And ensure (implicit/explicit) project role
const ensuredProjectRole = await (0, exports.ensureMinimumProjectRoleFragment)(loaders)({
userId: userId,
projectId,
role: requiredProjectRole
});
if (ensuredProjectRole.isErr) {
return (0, result_1.err)(ensuredProjectRole.error);
}
// Ensure workspace access
const ensuredWorkspaceAccess = await (0, exports.ensureProjectWorkspaceAccessFragment)(loaders)({
userId: userId,
projectId
});
if (ensuredWorkspaceAccess.isErr) {
return (0, result_1.err)(ensuredWorkspaceAccess.error);
}
return (0, result_1.ok)();
};
exports.ensureImplicitProjectMemberWithWriteAccessFragment = ensureImplicitProjectMemberWithWriteAccessFragment;
/**
* Ensure project is workspaced and has access to a specific plan feature
*/
const ensureCanUseProjectWorkspacePlanFeatureFragment = (loaders) => async ({ projectId, feature, allowUnworkspaced = false }) => {
const project = await loaders.getProject({ projectId });
if (!project)
return (0, result_1.err)(new authErrors_js_1.ProjectNotFoundError());
const workspaceId = project.workspaceId;
if (!workspaceId) {
if (allowUnworkspaced)
return (0, result_1.ok)();
return (0, result_1.err)(new authErrors_js_1.WorkspaceNoAccessError({
message: 'The project must be in a workspace'
}));
}
const canUseFeature = await (0, workspaces_js_1.ensureCanUseWorkspacePlanFeatureFragment)(loaders)({
workspaceId,
feature
});
if (canUseFeature.isErr)
return (0, result_1.err)(canUseFeature.error);
return (0, result_1.ok)();
};
exports.ensureCanUseProjectWorkspacePlanFeatureFragment = ensureCanUseProjectWorkspacePlanFeatureFragment;
//# sourceMappingURL=projects.js.map