mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Continue moving SCIM userId refs to orgMembershipId
This commit is contained in:
@@ -2,4 +2,5 @@
|
|||||||
frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx:generic-api-key:206
|
frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/IdentityRbacSection.tsx:generic-api-key:206
|
||||||
frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:304
|
frontend/src/views/Project/MembersPage/components/IdentityTab/components/IdentityRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:304
|
||||||
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/MemberRbacSection.tsx:generic-api-key:206
|
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/MemberRbacSection.tsx:generic-api-key:206
|
||||||
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:292
|
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:292
|
||||||
|
docs/self-hosting/configuration/envars.mdx:generic-api-key:106
|
||||||
|
|||||||
@@ -152,8 +152,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log("GET /Users req.query: ", req.query);
|
||||||
const users = await req.server.services.scim.listScimUsers({
|
const users = await req.server.services.scim.listScimUsers({
|
||||||
offset: req.query.startIndex,
|
startIndex: req.query.startIndex,
|
||||||
limit: req.query.count,
|
limit: req.query.count,
|
||||||
filter: req.query.filter,
|
filter: req.query.filter,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -163,11 +164,11 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/Users/:userId",
|
url: "/Users/:orgMembershipId",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
userId: z.string().trim()
|
orgMembershipId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
201: z.object({
|
201: z.object({
|
||||||
@@ -192,8 +193,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`GET /Users/${req.params.orgMembershipId}`);
|
||||||
const user = await req.server.services.scim.getScimUser({
|
const user = await req.server.services.scim.getScimUser({
|
||||||
userId: req.params.userId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
});
|
});
|
||||||
return user;
|
return user;
|
||||||
@@ -246,6 +248,8 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log("POST /Users req.body: ", req.body);
|
||||||
|
|
||||||
const primaryEmail = req.body.emails?.find((email) => email.primary)?.value;
|
const primaryEmail = req.body.emails?.find((email) => email.primary)?.value;
|
||||||
|
|
||||||
const user = await req.server.services.scim.createScimUser({
|
const user = await req.server.services.scim.createScimUser({
|
||||||
@@ -261,11 +265,11 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/Users/:userId",
|
url: "/Users/:orgMembershipId",
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
userId: z.string().trim()
|
orgMembershipId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({})
|
200: z.object({})
|
||||||
@@ -273,8 +277,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`DELETE /Users/${req.params.orgMembershipId}`);
|
||||||
const user = await req.server.services.scim.deleteScimUser({
|
const user = await req.server.services.scim.deleteScimUser({
|
||||||
userId: req.params.userId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -319,6 +324,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log("POST /Groups req.body: ", req.body);
|
||||||
const group = await req.server.services.scim.createScimGroup({
|
const group = await req.server.services.scim.createScimGroup({
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
...req.body
|
...req.body
|
||||||
@@ -359,6 +365,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log("GET /Groups req.query: ", req.query);
|
||||||
const groups = await req.server.services.scim.listScimGroups({
|
const groups = await req.server.services.scim.listScimGroups({
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
offset: req.query.startIndex,
|
offset: req.query.startIndex,
|
||||||
@@ -395,6 +402,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`GET /Groups/${req.params.groupId}`);
|
||||||
const group = await req.server.services.scim.getScimGroup({
|
const group = await req.server.services.scim.getScimGroup({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -440,6 +448,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`PUT /Groups/${req.params.groupId} req.body: `, req.body);
|
||||||
const group = await req.server.services.scim.updateScimGroupNamePut({
|
const group = await req.server.services.scim.updateScimGroupNamePut({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
@@ -501,6 +510,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`PATCH /Groups/${req.params.groupId} req.body: `, req.body);
|
||||||
const group = await req.server.services.scim.updateScimGroupNamePatch({
|
const group = await req.server.services.scim.updateScimGroupNamePatch({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
@@ -524,6 +534,7 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`DELETE /Groups/${req.params.groupId}`);
|
||||||
const group = await req.server.services.scim.deleteScimGroup({
|
const group = await req.server.services.scim.deleteScimGroup({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -534,11 +545,11 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/Users/:userId",
|
url: "/Users/:orgMembershipId",
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
userId: z.string().trim()
|
orgMembershipId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
schemas: z.array(z.string()),
|
schemas: z.array(z.string()),
|
||||||
@@ -574,8 +585,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
|
console.log(`PUT /Users/${req.params.orgMembershipId} req.body: `, req.body);
|
||||||
const user = await req.server.services.scim.replaceScimUser({
|
const user = await req.server.services.scim.replaceScimUser({
|
||||||
userId: req.params.userId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
active: req.body.active
|
active: req.body.active
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal
|
|||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
import { normalizeUsername } from "@app/services/user/user-fns";
|
import { normalizeUsername } from "@app/services/user/user-fns";
|
||||||
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
||||||
import { TUserAliasType } from "@app/services/user-alias/user-alias-types";
|
import { UserAliasType } from "@app/services/user-alias/user-alias-types";
|
||||||
|
|
||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
@@ -395,7 +395,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
let userAlias = await userAliasDAL.findOne({
|
let userAlias = await userAliasDAL.findOne({
|
||||||
externalId,
|
externalId,
|
||||||
orgId,
|
orgId,
|
||||||
aliasType: TUserAliasType.LDAP
|
aliasType: UserAliasType.LDAP
|
||||||
});
|
});
|
||||||
|
|
||||||
const organization = await orgDAL.findOrgById(orgId);
|
const organization = await orgDAL.findOrgById(orgId);
|
||||||
@@ -449,7 +449,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
{
|
{
|
||||||
userId: newUser.id,
|
userId: newUser.id,
|
||||||
username,
|
username,
|
||||||
aliasType: TUserAliasType.LDAP,
|
aliasType: UserAliasType.LDAP,
|
||||||
externalId,
|
externalId,
|
||||||
emails,
|
emails,
|
||||||
orgId
|
orgId
|
||||||
@@ -564,7 +564,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
organizationId: organization.id,
|
organizationId: organization.id,
|
||||||
organizationSlug: organization.slug,
|
organizationSlug: organization.slug,
|
||||||
authMethod: AuthMethod.LDAP,
|
authMethod: AuthMethod.LDAP,
|
||||||
authType: TUserAliasType.LDAP,
|
authType: UserAliasType.LDAP,
|
||||||
isUserCompleted,
|
isUserCompleted,
|
||||||
...(relayState
|
...(relayState
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ export const getDefaultOnPremFeatures = () => {
|
|||||||
customAlerts: false,
|
customAlerts: false,
|
||||||
auditLogs: false,
|
auditLogs: false,
|
||||||
auditLogsRetentionDays: 0,
|
auditLogsRetentionDays: 0,
|
||||||
samlSSO: true,
|
samlSSO: false,
|
||||||
scim: true,
|
scim: false,
|
||||||
ldap: false,
|
ldap: false,
|
||||||
groups: false,
|
groups: false,
|
||||||
status: null,
|
status: null,
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
customAlerts: false,
|
customAlerts: false,
|
||||||
auditLogs: false,
|
auditLogs: false,
|
||||||
auditLogsRetentionDays: 0,
|
auditLogsRetentionDays: 0,
|
||||||
samlSSO: true,
|
samlSSO: false,
|
||||||
scim: true,
|
scim: false,
|
||||||
ldap: true,
|
ldap: false,
|
||||||
groups: true,
|
groups: false,
|
||||||
status: null,
|
status: null,
|
||||||
trial_end: null,
|
trial_end: null,
|
||||||
has_used_trial: true,
|
has_used_trial: true,
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export type TFeatureSet = {
|
|||||||
customAlerts: false;
|
customAlerts: false;
|
||||||
auditLogs: false;
|
auditLogs: false;
|
||||||
auditLogsRetentionDays: 0;
|
auditLogsRetentionDays: 0;
|
||||||
samlSSO: true;
|
samlSSO: false;
|
||||||
scim: true;
|
scim: false;
|
||||||
ldap: false;
|
ldap: false;
|
||||||
groups: false;
|
groups: false;
|
||||||
status: null;
|
status: null;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membe
|
|||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
import { normalizeUsername } from "@app/services/user/user-fns";
|
import { normalizeUsername } from "@app/services/user/user-fns";
|
||||||
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
||||||
import { TUserAliasType } from "@app/services/user-alias/user-alias-types";
|
import { UserAliasType } from "@app/services/user-alias/user-alias-types";
|
||||||
|
|
||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
@@ -326,7 +326,7 @@ export const samlConfigServiceFactory = ({
|
|||||||
const userAlias = await userAliasDAL.findOne({
|
const userAlias = await userAliasDAL.findOne({
|
||||||
externalId,
|
externalId,
|
||||||
orgId,
|
orgId,
|
||||||
aliasType: TUserAliasType.SAML
|
aliasType: UserAliasType.SAML
|
||||||
});
|
});
|
||||||
|
|
||||||
const organization = await orgDAL.findOrgById(orgId);
|
const organization = await orgDAL.findOrgById(orgId);
|
||||||
@@ -385,7 +385,7 @@ export const samlConfigServiceFactory = ({
|
|||||||
await userAliasDAL.create(
|
await userAliasDAL.create(
|
||||||
{
|
{
|
||||||
userId: newUser.id,
|
userId: newUser.id,
|
||||||
aliasType: TUserAliasType.SAML,
|
aliasType: UserAliasType.SAML,
|
||||||
externalId,
|
externalId,
|
||||||
emails: email ? [email] : [],
|
emails: email ? [email] : [],
|
||||||
orgId
|
orgId
|
||||||
@@ -421,7 +421,7 @@ export const samlConfigServiceFactory = ({
|
|||||||
organizationId: organization.id,
|
organizationId: organization.id,
|
||||||
organizationSlug: organization.slug,
|
organizationSlug: organization.slug,
|
||||||
authMethod: authProvider,
|
authMethod: authProvider,
|
||||||
authType: TUserAliasType.SAML,
|
authType: UserAliasType.SAML,
|
||||||
isUserCompleted,
|
isUserCompleted,
|
||||||
...(relayState
|
...(relayState
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -2,31 +2,31 @@ import { TListScimGroups, TListScimUsers, TScimGroup, TScimUser } from "./scim-t
|
|||||||
|
|
||||||
export const buildScimUserList = ({
|
export const buildScimUserList = ({
|
||||||
scimUsers,
|
scimUsers,
|
||||||
offset,
|
startIndex,
|
||||||
limit
|
limit
|
||||||
}: {
|
}: {
|
||||||
scimUsers: TScimUser[];
|
scimUsers: TScimUser[];
|
||||||
offset: number;
|
startIndex: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
}): TListScimUsers => {
|
}): TListScimUsers => {
|
||||||
return {
|
return {
|
||||||
Resources: scimUsers,
|
Resources: scimUsers,
|
||||||
itemsPerPage: limit,
|
itemsPerPage: limit,
|
||||||
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
|
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
|
||||||
startIndex: offset,
|
startIndex,
|
||||||
totalResults: scimUsers.length
|
totalResults: scimUsers.length
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const buildScimUser = ({
|
export const buildScimUser = ({
|
||||||
userId,
|
orgMembershipId,
|
||||||
username,
|
username,
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
active
|
active
|
||||||
}: {
|
}: {
|
||||||
userId: string;
|
orgMembershipId: string;
|
||||||
username: string;
|
username: string;
|
||||||
email?: string | null;
|
email?: string | null;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
@@ -35,7 +35,7 @@ export const buildScimUser = ({
|
|||||||
}): TScimUser => {
|
}): TScimUser => {
|
||||||
const scimUser = {
|
const scimUser = {
|
||||||
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||||
id: userId,
|
id: orgMembershipId,
|
||||||
userName: username,
|
userName: username,
|
||||||
displayName: `${firstName} ${lastName}`,
|
displayName: `${firstName} ${lastName}`,
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
import slugify from "@sindresorhus/slugify";
|
import slugify from "@sindresorhus/slugify";
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
import { OrgMembershipRole, OrgMembershipStatus, TableName, TGroups } from "@app/db/schemas";
|
import { OrgMembershipRole, OrgMembershipStatus, TableName, TGroups, TOrgMemberships, TUsers } from "@app/db/schemas";
|
||||||
import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
|
import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
|
||||||
import { addUsersToGroupByUserIds, removeUsersFromGroupByUserIds } from "@app/ee/services/group/group-fns";
|
import { addUsersToGroupByUserIds, removeUsersFromGroupByUserIds } from "@app/ee/services/group/group-fns";
|
||||||
import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
||||||
@@ -11,16 +11,20 @@ import { getConfig } from "@app/lib/config/env";
|
|||||||
import { BadRequestError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { TOrgPermission } from "@app/lib/types";
|
import { TOrgPermission } from "@app/lib/types";
|
||||||
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||||
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
||||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||||
import { deleteOrgMembership } from "@app/services/org/org-fns";
|
import { deleteOrgMembership } from "@app/services/org/org-fns";
|
||||||
|
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
||||||
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
|
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
|
||||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||||
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
|
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
|
import { normalizeUsername } from "@app/services/user/user-fns";
|
||||||
|
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
||||||
|
import { UserAliasType } from "@app/services/user-alias/user-alias-types";
|
||||||
|
|
||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
@@ -47,11 +51,16 @@ import {
|
|||||||
|
|
||||||
type TScimServiceFactoryDep = {
|
type TScimServiceFactoryDep = {
|
||||||
scimDAL: Pick<TScimDALFactory, "create" | "find" | "findById" | "deleteById">;
|
scimDAL: Pick<TScimDALFactory, "create" | "find" | "findById" | "deleteById">;
|
||||||
userDAL: Pick<TUserDALFactory, "find" | "findOne" | "create" | "transaction" | "findUserEncKeyByUserIdsBatch">;
|
userDAL: Pick<
|
||||||
|
TUserDALFactory,
|
||||||
|
"find" | "findOne" | "create" | "transaction" | "findUserEncKeyByUserIdsBatch" | "findById"
|
||||||
|
>;
|
||||||
|
userAliasDAL: TUserAliasDALFactory; // TODO: pick
|
||||||
orgDAL: Pick<
|
orgDAL: Pick<
|
||||||
TOrgDALFactory,
|
TOrgDALFactory,
|
||||||
"createMembership" | "findById" | "findMembership" | "deleteMembershipById" | "transaction"
|
"createMembership" | "findById" | "findMembership" | "deleteMembershipById" | "transaction" | "updateMembershipById"
|
||||||
>;
|
>;
|
||||||
|
orgMembershipDAL: TOrgMembershipDALFactory; // TODO: Pick
|
||||||
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">;
|
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">;
|
||||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
||||||
groupDAL: Pick<
|
groupDAL: Pick<
|
||||||
@@ -64,7 +73,7 @@ type TScimServiceFactoryDep = {
|
|||||||
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
|
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
|
||||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
smtpService: TSmtpService;
|
smtpService: Pick<TSmtpService, "sendMail">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TScimServiceFactory = ReturnType<typeof scimServiceFactory>;
|
export type TScimServiceFactory = ReturnType<typeof scimServiceFactory>;
|
||||||
@@ -75,7 +84,9 @@ export const scimServiceFactory = ({
|
|||||||
licenseService,
|
licenseService,
|
||||||
scimDAL,
|
scimDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
|
userAliasDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
|
orgMembershipDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
projectMembershipDAL,
|
projectMembershipDAL,
|
||||||
groupDAL,
|
groupDAL,
|
||||||
@@ -162,8 +173,13 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// SCIM server endpoints
|
// SCIM server endpoints
|
||||||
const listScimUsers = async ({ offset, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => {
|
const listScimUsers = async ({ startIndex, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => {
|
||||||
console.log("listScimUsers"); // done
|
console.log("listScimUsers args: ", {
|
||||||
|
startIndex,
|
||||||
|
limit,
|
||||||
|
filter,
|
||||||
|
orgId
|
||||||
|
}); // done
|
||||||
const org = await orgDAL.findById(orgId);
|
const org = await orgDAL.findById(orgId);
|
||||||
|
|
||||||
if (!org.scimEnabled)
|
if (!org.scimEnabled)
|
||||||
@@ -181,11 +197,11 @@ export const scimServiceFactory = ({
|
|||||||
attributeName = "email";
|
attributeName = "email";
|
||||||
}
|
}
|
||||||
|
|
||||||
return { [attributeName]: parsedValue };
|
return { [attributeName]: parsedValue.replace(/"/g, "") };
|
||||||
};
|
};
|
||||||
|
|
||||||
const findOpts = {
|
const findOpts = {
|
||||||
...(offset && { offset }),
|
...(startIndex && { offset: startIndex - 1 }),
|
||||||
...(limit && { limit })
|
...(limit && { limit })
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -197,11 +213,9 @@ export const scimServiceFactory = ({
|
|||||||
findOpts
|
findOpts
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("orgDAL.findMembership users: ", users);
|
|
||||||
|
|
||||||
const scimUsers = users.map(({ id, username, firstName, lastName, email }) =>
|
const scimUsers = users.map(({ id, username, firstName, lastName, email }) =>
|
||||||
buildScimUser({
|
buildScimUser({
|
||||||
userId: id ?? "",
|
orgMembershipId: id ?? "",
|
||||||
username,
|
username,
|
||||||
firstName: firstName ?? "",
|
firstName: firstName ?? "",
|
||||||
lastName: lastName ?? "",
|
lastName: lastName ?? "",
|
||||||
@@ -212,17 +226,20 @@ export const scimServiceFactory = ({
|
|||||||
|
|
||||||
return buildScimUserList({
|
return buildScimUserList({
|
||||||
scimUsers,
|
scimUsers,
|
||||||
offset,
|
startIndex,
|
||||||
limit
|
limit
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getScimUser = async ({ userId, orgId }: TGetScimUserDTO) => {
|
const getScimUser = async ({ orgMembershipId, orgId }: TGetScimUserDTO) => {
|
||||||
console.log("getScimUser"); // done
|
console.log("getScimUser args: ", {
|
||||||
|
orgMembershipId,
|
||||||
|
orgId
|
||||||
|
}); // done
|
||||||
const [membership] = await orgDAL
|
const [membership] = await orgDAL
|
||||||
.findMembership({
|
.findMembership({
|
||||||
userId,
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
throw new ScimRequestError({
|
throw new ScimRequestError({
|
||||||
@@ -246,7 +263,7 @@ export const scimServiceFactory = ({
|
|||||||
console.log("getScimUser membership: ", membership);
|
console.log("getScimUser membership: ", membership);
|
||||||
|
|
||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
userId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.username,
|
username: membership.username,
|
||||||
email: membership.email ?? "",
|
email: membership.email ?? "",
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName as string,
|
||||||
@@ -256,7 +273,14 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
|
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
|
||||||
console.log("createScimUser"); // TODO: update implementation to always create a new user and be based on orgMembershipId
|
// do we get external ID or not?
|
||||||
|
console.log("createScimUser args: ", {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
orgId
|
||||||
|
});
|
||||||
const org = await orgDAL.findById(orgId);
|
const org = await orgDAL.findById(orgId);
|
||||||
|
|
||||||
if (!org)
|
if (!org)
|
||||||
@@ -271,67 +295,85 @@ export const scimServiceFactory = ({
|
|||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
||||||
let user = await userDAL.findOne({
|
const appCfg = getConfig();
|
||||||
username
|
|
||||||
|
const userAlias = await userAliasDAL.findOne({
|
||||||
|
externalId: username,
|
||||||
|
orgId,
|
||||||
|
aliasType: UserAliasType.SAML
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user) {
|
const { user: createdUser, orgMembership: createdOrgMembership } = await userDAL.transaction(async (tx) => {
|
||||||
await userDAL.transaction(async (tx) => {
|
let user: TUsers;
|
||||||
const [orgMembership] = await orgDAL.findMembership(
|
let orgMembership: TOrgMemberships;
|
||||||
|
if (userAlias) {
|
||||||
|
user = await userDAL.findById(userAlias.userId, tx);
|
||||||
|
orgMembership = await orgMembershipDAL.findOne(
|
||||||
{
|
{
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
orgId
|
||||||
},
|
|
||||||
{ tx }
|
|
||||||
);
|
|
||||||
if (orgMembership)
|
|
||||||
throw new ScimRequestError({
|
|
||||||
detail: "User already exists in the database",
|
|
||||||
status: 409
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!orgMembership) {
|
|
||||||
await orgDAL.createMembership(
|
|
||||||
{
|
|
||||||
userId: user.id,
|
|
||||||
orgId,
|
|
||||||
inviteEmail: email,
|
|
||||||
role: OrgMembershipRole.Member,
|
|
||||||
status: OrgMembershipStatus.Invited
|
|
||||||
},
|
|
||||||
tx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
user = await userDAL.transaction(async (tx) => {
|
|
||||||
const newUser = await userDAL.create(
|
|
||||||
{
|
|
||||||
username,
|
|
||||||
email,
|
|
||||||
firstName,
|
|
||||||
lastName,
|
|
||||||
authMethods: [AuthMethod.EMAIL],
|
|
||||||
isGhost: false
|
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
|
||||||
await orgDAL.createMembership(
|
if (!orgMembership) {
|
||||||
|
orgMembership = await orgMembershipDAL.create(
|
||||||
|
{
|
||||||
|
userId: userAlias.userId,
|
||||||
|
inviteEmail: email,
|
||||||
|
orgId,
|
||||||
|
role: OrgMembershipRole.Member,
|
||||||
|
status: user.isAccepted ? OrgMembershipStatus.Accepted : OrgMembershipStatus.Invited // if user is fully completed, then set status to accepted, otherwise set it to invited so we can update it later
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
} else if (orgMembership.status === OrgMembershipStatus.Invited && user.isAccepted) {
|
||||||
|
orgMembership = await orgMembershipDAL.updateById(
|
||||||
|
orgMembership.id,
|
||||||
|
{
|
||||||
|
status: OrgMembershipStatus.Accepted
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const uniqueUsername = await normalizeUsername(username, userDAL);
|
||||||
|
user = await userDAL.create(
|
||||||
{
|
{
|
||||||
|
username: uniqueUsername,
|
||||||
|
email,
|
||||||
|
isEmailVerified: appCfg.TRUST_SAML_EMAILS,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
authMethods: [],
|
||||||
|
isGhost: false
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
await userAliasDAL.create(
|
||||||
|
{
|
||||||
|
userId: user.id,
|
||||||
|
aliasType: UserAliasType.SAML,
|
||||||
|
externalId: username,
|
||||||
|
emails: email ? [email] : [],
|
||||||
|
orgId
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
orgMembership = await orgMembershipDAL.create(
|
||||||
|
{
|
||||||
|
userId: user.id,
|
||||||
inviteEmail: email,
|
inviteEmail: email,
|
||||||
orgId,
|
orgId,
|
||||||
userId: newUser.id,
|
|
||||||
role: OrgMembershipRole.Member,
|
role: OrgMembershipRole.Member,
|
||||||
status: OrgMembershipStatus.Invited
|
status: OrgMembershipStatus.Invited
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
return newUser;
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const appCfg = getConfig();
|
return { user, orgMembership };
|
||||||
|
});
|
||||||
|
|
||||||
if (email) {
|
if (email) {
|
||||||
await smtpService.sendMail({
|
await smtpService.sendMail({
|
||||||
@@ -346,11 +388,11 @@ export const scimServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
userId: user.id,
|
orgMembershipId: createdOrgMembership.id,
|
||||||
username: user.username,
|
username: createdUser.username,
|
||||||
firstName: user.firstName as string,
|
firstName: createdUser.firstName as string,
|
||||||
lastName: user.lastName as string,
|
lastName: createdUser.lastName as string,
|
||||||
email: user.email ?? "",
|
email: createdUser.email ?? "",
|
||||||
active: true
|
active: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -406,7 +448,7 @@ export const scimServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
userId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.username,
|
username: membership.username,
|
||||||
email: membership.email,
|
email: membership.email,
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName as string,
|
||||||
@@ -415,12 +457,16 @@ export const scimServiceFactory = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const replaceScimUser = async ({ userId, active, orgId }: TReplaceScimUserDTO) => {
|
const replaceScimUser = async ({ orgMembershipId, active, orgId }: TReplaceScimUserDTO) => {
|
||||||
console.log("replaceScimUser"); // done
|
console.log("replaceScimUser args: ", {
|
||||||
|
orgMembershipId,
|
||||||
|
orgId,
|
||||||
|
active
|
||||||
|
}); // done
|
||||||
const [membership] = await orgDAL
|
const [membership] = await orgDAL
|
||||||
.findMembership({
|
.findMembership({
|
||||||
userId,
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
throw new ScimRequestError({
|
throw new ScimRequestError({
|
||||||
@@ -453,7 +499,7 @@ export const scimServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
userId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.username,
|
username: membership.username,
|
||||||
email: membership.email,
|
email: membership.email,
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName as string,
|
||||||
@@ -462,19 +508,15 @@ export const scimServiceFactory = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteScimUser = async ({ userId, orgId }: TDeleteScimUserDTO) => {
|
const deleteScimUser = async ({ orgMembershipId, orgId }: TDeleteScimUserDTO) => {
|
||||||
console.log("deleteScimUser"); // done
|
console.log("deleteScimUser args: ", {
|
||||||
const [membership] = await orgDAL
|
orgMembershipId,
|
||||||
.findMembership({
|
orgId
|
||||||
userId,
|
}); // done
|
||||||
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
const [membership] = await orgDAL.findMembership({
|
||||||
})
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
.catch(() => {
|
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
||||||
throw new ScimRequestError({
|
});
|
||||||
detail: "User not found",
|
|
||||||
status: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!membership)
|
if (!membership)
|
||||||
throw new ScimRequestError({
|
throw new ScimRequestError({
|
||||||
@@ -593,12 +635,19 @@ export const scimServiceFactory = ({
|
|||||||
return { group, newMembers: [] };
|
return { group, newMembers: [] };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const orgMemberships = await orgDAL.findMembership({
|
||||||
|
orgId,
|
||||||
|
$in: {
|
||||||
|
userId: newGroup.newMembers.map((member) => member.id)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return buildScimGroup({
|
return buildScimGroup({
|
||||||
groupId: newGroup.group.id,
|
groupId: newGroup.group.id,
|
||||||
name: newGroup.group.name,
|
name: newGroup.group.name,
|
||||||
members: newGroup.newMembers.map((member) => ({
|
members: orgMemberships.map(({ id, firstName, lastName }) => ({
|
||||||
value: member.id,
|
value: id,
|
||||||
display: `${member.firstName} ${member.lastName}`
|
display: `${firstName} ${lastName}`
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -627,15 +676,20 @@ export const scimServiceFactory = ({
|
|||||||
groupId: group.id
|
groupId: group.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const orgMemberships = await orgDAL.findMembership({
|
||||||
|
orgId,
|
||||||
|
$in: {
|
||||||
|
userId: users.filter((user) => user.isPartOfGroup).map((user) => user.id)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return buildScimGroup({
|
return buildScimGroup({
|
||||||
groupId: group.id,
|
groupId: group.id,
|
||||||
name: group.name,
|
name: group.name,
|
||||||
members: users
|
members: orgMemberships.map(({ id, firstName, lastName }) => ({
|
||||||
.filter((user) => user.isPartOfGroup)
|
value: id,
|
||||||
.map((user) => ({
|
display: `${firstName} ${lastName}`
|
||||||
value: user.id,
|
}))
|
||||||
display: `${user.firstName} ${user.lastName}`
|
|
||||||
}))
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export type TDeleteScimTokenDTO = {
|
|||||||
// SCIM server endpoint types
|
// SCIM server endpoint types
|
||||||
|
|
||||||
export type TListScimUsersDTO = {
|
export type TListScimUsersDTO = {
|
||||||
offset: number;
|
startIndex: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
filter?: string;
|
filter?: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
@@ -27,7 +27,7 @@ export type TListScimUsers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TGetScimUserDTO = {
|
export type TGetScimUserDTO = {
|
||||||
userId: string;
|
orgMembershipId: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,13 +54,13 @@ export type TUpdateScimUserDTO = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TReplaceScimUserDTO = {
|
export type TReplaceScimUserDTO = {
|
||||||
userId: string;
|
orgMembershipId: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TDeleteScimUserDTO = {
|
export type TDeleteScimUserDTO = {
|
||||||
userId: string;
|
orgMembershipId: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -292,7 +292,9 @@ export const registerRoutes = async (
|
|||||||
licenseService,
|
licenseService,
|
||||||
scimDAL,
|
scimDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
|
userAliasDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
|
orgMembershipDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
projectMembershipDAL,
|
projectMembershipDAL,
|
||||||
groupDAL,
|
groupDAL,
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ export const deleteOrgMembership = async ({
|
|||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: delete associated aliases
|
||||||
|
|
||||||
return orgMembership;
|
return orgMembership;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export enum TUserAliasType {
|
export enum UserAliasType {
|
||||||
LDAP = "ldap",
|
LDAP = "ldap",
|
||||||
SAML = "saml"
|
SAML = "saml"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user