mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 18:27:36 +00:00
Add default org and project-level no access roles
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
|||||||
} from "../../helpers/organization";
|
} from "../../helpers/organization";
|
||||||
import { addMembershipsOrg } from "../../helpers/membershipOrg";
|
import { addMembershipsOrg } from "../../helpers/membershipOrg";
|
||||||
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
import { ACCEPTED, ADMIN, CUSTOM, MEMBER } from "../../variables";
|
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS } from "../../variables";
|
||||||
import * as reqValidator from "../../validation/organization";
|
import * as reqValidator from "../../validation/organization";
|
||||||
import { validateRequest } from "../../helpers/validation";
|
import { validateRequest } from "../../helpers/validation";
|
||||||
import {
|
import {
|
||||||
@@ -153,7 +153,7 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
|
|||||||
OrgPermissionSubjects.Member
|
OrgPermissionSubjects.Member
|
||||||
);
|
);
|
||||||
|
|
||||||
const isCustomRole = ![ADMIN, MEMBER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
const orgRole = await Role.findOne({
|
const orgRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
} from "../../ee/services/ProjectRoleService";
|
} from "../../ee/services/ProjectRoleService";
|
||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
import { BadRequestError, ForbiddenRequestError, ResourceNotFoundError } from "../../utils/errors";
|
import { BadRequestError, ForbiddenRequestError, ResourceNotFoundError } from "../../utils/errors";
|
||||||
import { ADMIN, CUSTOM, MEMBER, VIEWER } from "../../variables";
|
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
|
||||||
|
|
||||||
interface V2PushSecret {
|
interface V2PushSecret {
|
||||||
type: string; // personal or shared
|
type: string; // personal or shared
|
||||||
@@ -556,7 +556,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
let customRole;
|
let customRole;
|
||||||
if (role) {
|
if (role) {
|
||||||
const isCustomRole = ![ADMIN, MEMBER, VIEWER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
customRole = await Role.findOne({
|
customRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
@@ -632,7 +632,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
let customRole;
|
let customRole;
|
||||||
if (role) {
|
if (role) {
|
||||||
const isCustomRole = ![ADMIN, MEMBER, VIEWER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
customRole = await Role.findOne({
|
customRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
adminProjectPermissions,
|
adminProjectPermissions,
|
||||||
getAuthDataProjectPermissions,
|
getAuthDataProjectPermissions,
|
||||||
memberProjectPermissions,
|
memberProjectPermissions,
|
||||||
|
noAccessProjectPermissions,
|
||||||
viewerProjectPermission
|
viewerProjectPermission
|
||||||
} from "../../services/ProjectRoleService";
|
} from "../../services/ProjectRoleService";
|
||||||
import {
|
import {
|
||||||
@@ -22,7 +23,8 @@ import {
|
|||||||
OrgPermissionSubjects,
|
OrgPermissionSubjects,
|
||||||
adminPermissions,
|
adminPermissions,
|
||||||
getUserOrgPermissions,
|
getUserOrgPermissions,
|
||||||
memberPermissions
|
memberPermissions,
|
||||||
|
noAccessPermissions
|
||||||
} from "../../services/RoleService";
|
} from "../../services/RoleService";
|
||||||
import { BadRequestError } from "../../../utils/errors";
|
import { BadRequestError } from "../../../utils/errors";
|
||||||
import { Role } from "../../models";
|
import { Role } from "../../models";
|
||||||
@@ -195,6 +197,13 @@ export const getRoles = async (req: Request, res: Response) => {
|
|||||||
description: "Complete administration access over the organization",
|
description: "Complete administration access over the organization",
|
||||||
permissions: isOrgRole ? adminPermissions.rules : adminProjectPermissions.rules
|
permissions: isOrgRole ? adminPermissions.rules : adminProjectPermissions.rules
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
_id: "no-access",
|
||||||
|
name: "No Access",
|
||||||
|
slug: "no-access",
|
||||||
|
description: "No access to any resources in the organization",
|
||||||
|
permissions: isOrgRole ? noAccessPermissions.rules : noAccessProjectPermissions.rules
|
||||||
|
},
|
||||||
{
|
{
|
||||||
_id: "member",
|
_id: "member",
|
||||||
name: isOrgRole ? "Member" : "Developer",
|
name: isOrgRole ? "Member" : "Developer",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { BadRequestError, ForbiddenRequestError, ResourceNotFoundError, Unauthor
|
|||||||
import { extractIPDetails, isValidIpOrCidr } from "../../../utils/ip";
|
import { extractIPDetails, isValidIpOrCidr } from "../../../utils/ip";
|
||||||
import { EEAuditLogService, EELicenseService } from "../../services";
|
import { EEAuditLogService, EELicenseService } from "../../services";
|
||||||
import { getAuthSecret } from "../../../config";
|
import { getAuthSecret } from "../../../config";
|
||||||
import { ADMIN, AuthTokenType, CUSTOM, MEMBER } from "../../../variables";
|
import { ADMIN, AuthTokenType, CUSTOM, MEMBER, NO_ACCESS } from "../../../variables";
|
||||||
import {
|
import {
|
||||||
OrgPermissionActions,
|
OrgPermissionActions,
|
||||||
OrgPermissionSubjects
|
OrgPermissionSubjects
|
||||||
@@ -161,7 +161,7 @@ export const createMachineIdentity = async (req: Request, res: Response) => {
|
|||||||
const organization = await Organization.findById(organizationId);
|
const organization = await Organization.findById(organizationId);
|
||||||
if (!organization) throw BadRequestError({ message: `Organization with id ${organizationId} not found` });
|
if (!organization) throw BadRequestError({ message: `Organization with id ${organizationId} not found` });
|
||||||
|
|
||||||
const isCustomRole = ![ADMIN, MEMBER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
|
||||||
|
|
||||||
let customRole;
|
let customRole;
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
@@ -298,7 +298,7 @@ export const updateMachineIdentity = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
let customRole;
|
let customRole;
|
||||||
if (role) {
|
if (role) {
|
||||||
const isCustomRole = ![ADMIN, MEMBER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
customRole = await Role.findOne({
|
customRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class EELicenseService {
|
|||||||
secretVersioning: true,
|
secretVersioning: true,
|
||||||
pitRecovery: false,
|
pitRecovery: false,
|
||||||
ipAllowlisting: false,
|
ipAllowlisting: false,
|
||||||
rbac: false,
|
rbac: true,
|
||||||
customRateLimits: false,
|
customRateLimits: false,
|
||||||
customAlerts: false,
|
customAlerts: false,
|
||||||
auditLogs: false,
|
auditLogs: false,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
Membership,
|
Membership,
|
||||||
ServiceTokenData
|
ServiceTokenData
|
||||||
} from "../../models";
|
} from "../../models";
|
||||||
import { ADMIN, CUSTOM, MEMBER, VIEWER } from "../../variables";
|
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
|
||||||
import { checkIPAgainstBlocklist } from "../../utils/ip";
|
import { checkIPAgainstBlocklist } from "../../utils/ip";
|
||||||
import { BadRequestError } from "../../utils/errors";
|
import { BadRequestError } from "../../utils/errors";
|
||||||
|
|
||||||
@@ -262,6 +262,13 @@ const buildViewerPermission = () => {
|
|||||||
|
|
||||||
export const viewerProjectPermission = buildViewerPermission();
|
export const viewerProjectPermission = buildViewerPermission();
|
||||||
|
|
||||||
|
const buildNoAccessProjectPermission = () => {
|
||||||
|
const { build } = new AbilityBuilder<MongoAbility<ProjectPermissionSet>>(createMongoAbility);
|
||||||
|
return build({ conditionsMatcher });
|
||||||
|
}
|
||||||
|
|
||||||
|
export const noAccessProjectPermissions = buildNoAccessProjectPermission();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return permissions for user/service pertaining to workspace with id [workspaceId]
|
* Return permissions for user/service pertaining to workspace with id [workspaceId]
|
||||||
*
|
*
|
||||||
@@ -275,7 +282,7 @@ export const getAuthDataProjectPermissions = async ({
|
|||||||
authData: AuthData;
|
authData: AuthData;
|
||||||
workspaceId: Types.ObjectId;
|
workspaceId: Types.ObjectId;
|
||||||
}) => {
|
}) => {
|
||||||
let role: "admin" | "member" | "viewer" | "custom";
|
let role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
let customRole;
|
let customRole;
|
||||||
|
|
||||||
switch (authData.actor.type) {
|
switch (authData.actor.type) {
|
||||||
@@ -338,6 +345,8 @@ export const getAuthDataProjectPermissions = async ({
|
|||||||
return { permission: memberProjectPermissions };
|
return { permission: memberProjectPermissions };
|
||||||
case VIEWER:
|
case VIEWER:
|
||||||
return { permission: viewerProjectPermission };
|
return { permission: viewerProjectPermission };
|
||||||
|
case NO_ACCESS:
|
||||||
|
return { permission: noAccessProjectPermissions };
|
||||||
case CUSTOM: {
|
case CUSTOM: {
|
||||||
if (!customRole) throw UnauthorizedRequestError();
|
if (!customRole) throw UnauthorizedRequestError();
|
||||||
return {
|
return {
|
||||||
@@ -353,7 +362,7 @@ export const getAuthDataProjectPermissions = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getRolePermissions = async (role: string, workspaceId: string) => {
|
export const getRolePermissions = async (role: string, workspaceId: string) => {
|
||||||
const isCustomRole = ![ADMIN, MEMBER, VIEWER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
const workspaceRole = await Role.findOne({
|
const workspaceRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
@@ -375,6 +384,8 @@ export const getRolePermissions = async (role: string, workspaceId: string) => {
|
|||||||
return memberProjectPermissions;
|
return memberProjectPermissions;
|
||||||
case VIEWER:
|
case VIEWER:
|
||||||
return viewerProjectPermission;
|
return viewerProjectPermission;
|
||||||
|
case NO_ACCESS:
|
||||||
|
return noAccessProjectPermissions;
|
||||||
default:
|
default:
|
||||||
throw BadRequestError({ message: "Role not found" });
|
throw BadRequestError({ message: "Role not found" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { AbilityBuilder, MongoAbility, RawRuleOf, createMongoAbility } from "@ca
|
|||||||
import { MembershipOrg } from "../../models";
|
import { MembershipOrg } from "../../models";
|
||||||
import { IRole, Role } from "../models";
|
import { IRole, Role } from "../models";
|
||||||
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
import { ACCEPTED, ADMIN, CUSTOM, MEMBER } from "../../variables";
|
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../../variables";
|
||||||
import { conditionsMatcher } from "./ProjectRoleService";
|
import { conditionsMatcher } from "./ProjectRoleService";
|
||||||
|
|
||||||
export enum OrgPermissionActions {
|
export enum OrgPermissionActions {
|
||||||
@@ -116,6 +116,13 @@ const buildMemberPermission = () => {
|
|||||||
|
|
||||||
export const memberPermissions = buildMemberPermission();
|
export const memberPermissions = buildMemberPermission();
|
||||||
|
|
||||||
|
const buildNoAccessPermission = () => {
|
||||||
|
const { build } = new AbilityBuilder<MongoAbility<OrgPermissionSet>>(createMongoAbility);
|
||||||
|
return build({ conditionsMatcher });
|
||||||
|
}
|
||||||
|
|
||||||
|
export const noAccessPermissions = buildNoAccessPermission();
|
||||||
|
|
||||||
export const getUserOrgPermissions = async (userId: string, orgId: string) => {
|
export const getUserOrgPermissions = async (userId: string, orgId: string) => {
|
||||||
// TODO(akhilmhdh): speed this up by pulling from cache later
|
// TODO(akhilmhdh): speed this up by pulling from cache later
|
||||||
|
|
||||||
@@ -137,6 +144,8 @@ export const getUserOrgPermissions = async (userId: string, orgId: string) => {
|
|||||||
|
|
||||||
if (membership.role === MEMBER) return { permission: memberPermissions, membership };
|
if (membership.role === MEMBER) return { permission: memberPermissions, membership };
|
||||||
|
|
||||||
|
if (membership.role === NO_ACCESS) return { permission: noAccessPermissions, membership }
|
||||||
|
|
||||||
if (membership.role === CUSTOM) {
|
if (membership.role === CUSTOM) {
|
||||||
const permission = createMongoAbility<OrgPermissionSet>(membership.customRole.permissions, {
|
const permission = createMongoAbility<OrgPermissionSet>(membership.customRole.permissions, {
|
||||||
conditionsMatcher
|
conditionsMatcher
|
||||||
@@ -148,7 +157,7 @@ export const getUserOrgPermissions = async (userId: string, orgId: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getOrgRolePermissions = async (role: string, orgId: string) => {
|
export const getOrgRolePermissions = async (role: string, orgId: string) => {
|
||||||
const isCustomRole = ![ADMIN, MEMBER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
const orgRole = await Role.findOne({
|
const orgRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
@@ -168,6 +177,8 @@ export const getOrgRolePermissions = async (role: string, orgId: string) => {
|
|||||||
return adminPermissions;
|
return adminPermissions;
|
||||||
case MEMBER:
|
case MEMBER:
|
||||||
return memberPermissions;
|
return memberPermissions;
|
||||||
|
case NO_ACCESS:
|
||||||
|
return noAccessPermissions;
|
||||||
default:
|
default:
|
||||||
throw BadRequestError({ message: "User org role not found" });
|
throw BadRequestError({ message: "User org role not found" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const validateMembership = async ({
|
|||||||
}: {
|
}: {
|
||||||
userId: Types.ObjectId | string;
|
userId: Types.ObjectId | string;
|
||||||
workspaceId: Types.ObjectId | string;
|
workspaceId: Types.ObjectId | string;
|
||||||
acceptedRoles?: Array<"admin" | "member" | "custom" | "viewer">;
|
acceptedRoles?: Array<"admin" | "member" | "custom" | "viewer" | "no-access">;
|
||||||
}) => {
|
}) => {
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: userId,
|
user: userId,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const validateMembershipOrg = async ({
|
|||||||
}: {
|
}: {
|
||||||
userId: Types.ObjectId;
|
userId: Types.ObjectId;
|
||||||
organizationId: Types.ObjectId;
|
organizationId: Types.ObjectId;
|
||||||
acceptedRoles?: Array<"owner" | "admin" | "member" | "custom">;
|
acceptedRoles?: Array<"owner" | "admin" | "member" | "custom" | "no-access">;
|
||||||
acceptedStatuses?: Array<"invited" | "accepted">;
|
acceptedStatuses?: Array<"invited" | "accepted">;
|
||||||
}) => {
|
}) => {
|
||||||
const membershipOrg = await MembershipOrg.findOne({
|
const membershipOrg = await MembershipOrg.findOne({
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER, VIEWER } from "../variables";
|
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||||
|
|
||||||
export interface IMachineMembership {
|
export interface IMachineMembership {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
machineIdentity: Types.ObjectId;
|
machineIdentity: Types.ObjectId;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
role: "admin" | "member" | "viewer" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole: Types.ObjectId;
|
customRole: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ const machineMembershipSchema = new Schema<IMachineMembership>(
|
|||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, VIEWER, CUSTOM],
|
enum: [ADMIN, MEMBER, VIEWER, CUSTOM, NO_ACCESS],
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER } from "../variables";
|
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../variables";
|
||||||
|
|
||||||
export interface IMachineMembershipOrg {
|
export interface IMachineMembershipOrg {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
machineIdentity: Types.ObjectId;
|
machineIdentity: Types.ObjectId;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
role: "admin" | "member" | "viewer" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole: Types.ObjectId;
|
customRole: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ const machineMembershipOrgSchema = new Schema<IMachineMembershipOrg>(
|
|||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, CUSTOM],
|
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER, VIEWER } from "../variables";
|
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||||
|
|
||||||
export interface IMembershipPermission {
|
export interface IMembershipPermission {
|
||||||
environmentSlug: string;
|
environmentSlug: string;
|
||||||
@@ -11,7 +11,7 @@ export interface IMembership {
|
|||||||
user: Types.ObjectId;
|
user: Types.ObjectId;
|
||||||
inviteEmail?: string;
|
inviteEmail?: string;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
role: "admin" | "member" | "viewer" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole: Types.ObjectId;
|
customRole: Types.ObjectId;
|
||||||
deniedPermissions: IMembershipPermission[];
|
deniedPermissions: IMembershipPermission[];
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ const membershipSchema = new Schema<IMembership>(
|
|||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, VIEWER, CUSTOM],
|
enum: [ADMIN, MEMBER, VIEWER, NO_ACCESS, CUSTOM],
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Document, Schema, Types, model } from "mongoose";
|
import { Document, Schema, Types, model } from "mongoose";
|
||||||
import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER } from "../variables";
|
import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER, NO_ACCESS } from "../variables";
|
||||||
|
|
||||||
export interface IMembershipOrg extends Document {
|
export interface IMembershipOrg extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
user: Types.ObjectId;
|
user: Types.ObjectId;
|
||||||
inviteEmail: string;
|
inviteEmail: string;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
role: "owner" | "admin" | "member" | "custom";
|
role: "owner" | "admin" | "member" | "no-access" | "custom";
|
||||||
customRole: Types.ObjectId;
|
customRole: Types.ObjectId;
|
||||||
status: "invited" | "accepted";
|
status: "invited" | "accepted";
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ const membershipOrgSchema = new Schema(
|
|||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, CUSTOM],
|
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export const OWNER = "owner"; // depreciated
|
|||||||
export const ADMIN = "admin";
|
export const ADMIN = "admin";
|
||||||
export const MEMBER = "member";
|
export const MEMBER = "member";
|
||||||
export const VIEWER = "viewer";
|
export const VIEWER = "viewer";
|
||||||
|
export const NO_ACCESS = "no-access";
|
||||||
export const CUSTOM = "custom";
|
export const CUSTOM = "custom";
|
||||||
|
|
||||||
// membership statuses
|
// membership statuses
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export type MachineMembershipOrg = {
|
|||||||
_id: string;
|
_id: string;
|
||||||
machineIdentity: MachineIdentity;
|
machineIdentity: MachineIdentity;
|
||||||
organization: string;
|
organization: string;
|
||||||
role: "admin" | "member" | "viewer" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole?: TRole<string>;
|
customRole?: TRole<string>;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
@@ -38,7 +38,7 @@ export type MachineMembership = {
|
|||||||
_id: string;
|
_id: string;
|
||||||
machineIdentity: MachineIdentity;
|
machineIdentity: MachineIdentity;
|
||||||
organization: string;
|
organization: string;
|
||||||
role: "admin" | "member" | "viewer" | "custom";
|
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||||
customRole?: TRole<string>;
|
customRole?: TRole<string>;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export type OrgUser = {
|
|||||||
};
|
};
|
||||||
inviteEmail: string;
|
inviteEmail: string;
|
||||||
organization: string;
|
organization: string;
|
||||||
role: "owner" | "admin" | "member" | "custom";
|
role: "owner" | "admin" | "member" | "no-access" | "custom";
|
||||||
status: "invited" | "accepted" | "verified" | "completed";
|
status: "invited" | "accepted" | "verified" | "completed";
|
||||||
deniedPermissions: any[];
|
deniedPermissions: any[];
|
||||||
customRole: string;
|
customRole: string;
|
||||||
|
|||||||
@@ -25,7 +25,14 @@ export const MembersPage = withPermission(
|
|||||||
<Tabs defaultValue={TabSections.Member}>
|
<Tabs defaultValue={TabSections.Member}>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab value={TabSections.Member}>People</Tab>
|
<Tab value={TabSections.Member}>People</Tab>
|
||||||
<Tab value={TabSections.MachineIdentities}>Machine Identities</Tab>
|
<Tab value={TabSections.MachineIdentities}>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<p>Machine Identities</p>
|
||||||
|
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
|
||||||
|
Beta
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Tab>
|
||||||
<Tab value={TabSections.Roles}>Organization Roles</Tab>
|
<Tab value={TabSections.Roles}>Organization Roles</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel value={TabSections.Member}>
|
<TabPanel value={TabSections.Member}>
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export const OrgRoleTable = ({
|
|||||||
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
||||||
{(roles as TRole<undefined>[])?.map((role) => {
|
{(roles as TRole<undefined>[])?.map((role) => {
|
||||||
const { _id: id, name, slug } = role;
|
const { _id: id, name, slug } = role;
|
||||||
const isNonMutatable = ["owner", "admin", "member"].includes(slug);
|
const isNonMutatable = ["owner", "admin", "member", "no-access"].includes(slug);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr key={`role-list-${id}`}>
|
<Tr key={`role-list-${id}`}>
|
||||||
|
|||||||
@@ -30,7 +30,14 @@ export const MembersPage = withProjectPermission(
|
|||||||
<Tabs defaultValue={TabSections.Member}>
|
<Tabs defaultValue={TabSections.Member}>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab value={TabSections.Member}>People</Tab>
|
<Tab value={TabSections.Member}>People</Tab>
|
||||||
<Tab value={TabSections.MachineIdentities}>Machine Identities</Tab>
|
<Tab value={TabSections.MachineIdentities}>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<p>Machine Identities</p>
|
||||||
|
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
|
||||||
|
Beta
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Tab>
|
||||||
<Tab value={TabSections.ServiceTokens}>Service Tokens</Tab>
|
<Tab value={TabSections.ServiceTokens}>Service Tokens</Tab>
|
||||||
<Tab value={TabSections.Roles}>Project Roles</Tab>
|
<Tab value={TabSections.Roles}>Project Roles</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
|||||||
+1
-1
@@ -188,7 +188,7 @@ export const MachineIdentityTable = ({
|
|||||||
{!isLoading && data && data?.length === 0 && (
|
{!isLoading && data && data?.length === 0 && (
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td colSpan={7}>
|
<Td colSpan={7}>
|
||||||
<EmptyState title="No machine identities have been added to this project" icon={faServer} />
|
<EmptyState title="No MIs have been added to this project" icon={faServer} />
|
||||||
</Td>
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+1
-1
@@ -101,7 +101,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
|
|||||||
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
{isRolesLoading && <TableSkeleton columns={4} innerKey="org-roles" />}
|
||||||
{(roles as TRole<string>[])?.map((role) => {
|
{(roles as TRole<string>[])?.map((role) => {
|
||||||
const { _id: id, name, slug } = role;
|
const { _id: id, name, slug } = role;
|
||||||
const isNonMutatable = ["admin", "member", "viewer"].includes(slug);
|
const isNonMutatable = ["admin", "member", "viewer", "no-access"].includes(slug);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr key={`role-list-${id}`}>
|
<Tr key={`role-list-${id}`}>
|
||||||
|
|||||||
Reference in New Issue
Block a user