mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 00:26:40 +00:00
Continue user aliases
This commit is contained in:
@@ -99,6 +99,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
async (req, profile, cb) => {
|
async (req, profile, cb) => {
|
||||||
try {
|
try {
|
||||||
|
console.log("saml login profile: ", profile);
|
||||||
if (!profile) throw new BadRequestError({ message: "Missing profile" });
|
if (!profile) throw new BadRequestError({ message: "Missing profile" });
|
||||||
const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved
|
const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved
|
||||||
|
|
||||||
@@ -107,6 +108,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { isUserCompleted, providerAuthToken } = await server.services.saml.samlLogin({
|
const { isUserCompleted, providerAuthToken } = await server.services.saml.samlLogin({
|
||||||
|
externalId: profile.nameID,
|
||||||
username: profile.nameID ?? email,
|
username: profile.nameID ?? email,
|
||||||
email,
|
email,
|
||||||
firstName: profile.firstName as string,
|
firstName: profile.firstName as string,
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
import { OrgMembershipRole, OrgMembershipStatus, SecretKeyEncoding, TLdapConfigsUpdate } from "@app/db/schemas";
|
import {
|
||||||
|
OrgMembershipRole,
|
||||||
|
OrgMembershipStatus,
|
||||||
|
SecretKeyEncoding,
|
||||||
|
TableName,
|
||||||
|
TLdapConfigsUpdate
|
||||||
|
} 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";
|
||||||
@@ -25,6 +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 { 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";
|
||||||
@@ -388,7 +395,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
let userAlias = await userAliasDAL.findOne({
|
let userAlias = await userAliasDAL.findOne({
|
||||||
externalId,
|
externalId,
|
||||||
orgId,
|
orgId,
|
||||||
aliasType: AuthMethod.LDAP
|
aliasType: UserAliasType.LDAP
|
||||||
});
|
});
|
||||||
|
|
||||||
const organization = await orgDAL.findOrgById(orgId);
|
const organization = await orgDAL.findOrgById(orgId);
|
||||||
@@ -396,7 +403,13 @@ export const ldapConfigServiceFactory = ({
|
|||||||
|
|
||||||
if (userAlias) {
|
if (userAlias) {
|
||||||
await userDAL.transaction(async (tx) => {
|
await userDAL.transaction(async (tx) => {
|
||||||
const [orgMembership] = await orgDAL.findMembership({ userId: userAlias.userId }, { tx });
|
const [orgMembership] = await orgDAL.findMembership(
|
||||||
|
{
|
||||||
|
userId: userAlias.userId,
|
||||||
|
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
||||||
|
},
|
||||||
|
{ tx }
|
||||||
|
);
|
||||||
if (!orgMembership) {
|
if (!orgMembership) {
|
||||||
await orgDAL.createMembership(
|
await orgDAL.createMembership(
|
||||||
{
|
{
|
||||||
@@ -426,7 +439,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
email: emails[0],
|
email: emails[0],
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
authMethods: [AuthMethod.LDAP],
|
authMethods: [AuthMethod.LDAP], // should this be empty?
|
||||||
isGhost: false
|
isGhost: false
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
@@ -435,7 +448,7 @@ export const ldapConfigServiceFactory = ({
|
|||||||
{
|
{
|
||||||
userId: newUser.id,
|
userId: newUser.id,
|
||||||
username,
|
username,
|
||||||
aliasType: AuthMethod.LDAP,
|
aliasType: UserAliasType.LDAP,
|
||||||
externalId,
|
externalId,
|
||||||
emails,
|
emails,
|
||||||
orgId
|
orgId
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import {
|
|||||||
SecretKeyEncoding,
|
SecretKeyEncoding,
|
||||||
TableName,
|
TableName,
|
||||||
TSamlConfigs,
|
TSamlConfigs,
|
||||||
TSamlConfigsUpdate
|
TSamlConfigsUpdate,
|
||||||
|
TUsers
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import {
|
import {
|
||||||
@@ -19,11 +20,13 @@ import {
|
|||||||
infisicalSymmetricEncypt
|
infisicalSymmetricEncypt
|
||||||
} from "@app/lib/crypto/encryption";
|
} from "@app/lib/crypto/encryption";
|
||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||||
import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal";
|
import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal";
|
||||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
import { TOrgDALFactory } from "@app/services/org/org-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 { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
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";
|
||||||
@@ -33,7 +36,7 @@ import { TCreateSamlCfgDTO, TGetSamlCfgDTO, TSamlLoginDTO, TUpdateSamlCfgDTO } f
|
|||||||
|
|
||||||
type TSamlConfigServiceFactoryDep = {
|
type TSamlConfigServiceFactoryDep = {
|
||||||
samlConfigDAL: TSamlConfigDALFactory;
|
samlConfigDAL: TSamlConfigDALFactory;
|
||||||
userDAL: Pick<TUserDALFactory, "create" | "findOne" | "transaction" | "updateById">;
|
userDAL: Pick<TUserDALFactory, "create" | "findOne" | "transaction" | "updateById" | "findById">;
|
||||||
userAliasDAL: Pick<TUserAliasDALFactory, "create" | "findOne">;
|
userAliasDAL: Pick<TUserAliasDALFactory, "create" | "findOne">;
|
||||||
orgDAL: Pick<
|
orgDAL: Pick<
|
||||||
TOrgDALFactory,
|
TOrgDALFactory,
|
||||||
@@ -51,6 +54,7 @@ export const samlConfigServiceFactory = ({
|
|||||||
orgBotDAL,
|
orgBotDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
|
userAliasDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
licenseService
|
licenseService
|
||||||
}: TSamlConfigServiceFactoryDep) => {
|
}: TSamlConfigServiceFactoryDep) => {
|
||||||
@@ -307,7 +311,8 @@ export const samlConfigServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const samlLogin = async ({
|
const samlLogin = async ({
|
||||||
username,
|
externalId,
|
||||||
|
username, // what to do about this?
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
@@ -315,22 +320,36 @@ export const samlConfigServiceFactory = ({
|
|||||||
orgId,
|
orgId,
|
||||||
relayState
|
relayState
|
||||||
}: TSamlLoginDTO) => {
|
}: TSamlLoginDTO) => {
|
||||||
|
console.log("samlLogin args: ", {
|
||||||
|
externalId,
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
authProvider,
|
||||||
|
orgId,
|
||||||
|
relayState
|
||||||
|
});
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
let user = await userDAL.findOne({ username });
|
const userAlias = await userAliasDAL.findOne({
|
||||||
|
externalId,
|
||||||
|
orgId,
|
||||||
|
aliasType: UserAliasType.SAML
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("found userAlias: ", userAlias);
|
||||||
|
|
||||||
const organization = await orgDAL.findOrgById(orgId);
|
const organization = await orgDAL.findOrgById(orgId);
|
||||||
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
if (!organization) throw new BadRequestError({ message: "Org not found" });
|
||||||
|
|
||||||
// TODO(dangtony98): remove this after aliases update
|
let user: TUsers;
|
||||||
if (authProvider === AuthMethod.KEYCLOAK_SAML && appCfg.LICENSE_SERVER_KEY) {
|
if (userAlias) {
|
||||||
throw new BadRequestError({ message: "Keycloak SAML is not yet available on Infisical Cloud" });
|
console.log("samlLogin A");
|
||||||
}
|
user = await userDAL.transaction(async (tx) => {
|
||||||
|
const foundUser = await userDAL.findById(userAlias.userId, tx);
|
||||||
if (user) {
|
|
||||||
await userDAL.transaction(async (tx) => {
|
|
||||||
const [orgMembership] = await orgDAL.findMembership(
|
const [orgMembership] = await orgDAL.findMembership(
|
||||||
{
|
{
|
||||||
userId: user.id,
|
userId: foundUser.id,
|
||||||
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
|
||||||
},
|
},
|
||||||
{ tx }
|
{ tx }
|
||||||
@@ -338,11 +357,10 @@ export const samlConfigServiceFactory = ({
|
|||||||
if (!orgMembership) {
|
if (!orgMembership) {
|
||||||
await orgDAL.createMembership(
|
await orgDAL.createMembership(
|
||||||
{
|
{
|
||||||
userId: user.id,
|
userId: userAlias.userId,
|
||||||
orgId,
|
orgId,
|
||||||
inviteEmail: email,
|
|
||||||
role: OrgMembershipRole.Member,
|
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
|
status: foundUser.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
|
tx
|
||||||
);
|
);
|
||||||
@@ -356,30 +374,53 @@ export const samlConfigServiceFactory = ({
|
|||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return foundUser;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
console.log("samlLogin B");
|
||||||
user = await userDAL.transaction(async (tx) => {
|
user = await userDAL.transaction(async (tx) => {
|
||||||
|
const uniqueUsername = await normalizeUsername(username, userDAL);
|
||||||
const newUser = await userDAL.create(
|
const newUser = await userDAL.create(
|
||||||
{
|
{
|
||||||
username,
|
username: uniqueUsername,
|
||||||
email,
|
email,
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
authMethods: [AuthMethod.EMAIL],
|
authMethods: [],
|
||||||
isGhost: false
|
isGhost: false
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
await orgDAL.createMembership({
|
await userAliasDAL.create(
|
||||||
inviteEmail: email,
|
{
|
||||||
orgId,
|
userId: newUser.id,
|
||||||
role: OrgMembershipRole.Member,
|
username,
|
||||||
status: OrgMembershipStatus.Invited
|
aliasType: UserAliasType.SAML,
|
||||||
});
|
externalId,
|
||||||
|
emails: email ? [email] : [],
|
||||||
|
orgId
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
|
||||||
|
await orgDAL.createMembership(
|
||||||
|
// note: this creates a duplicate membership atm
|
||||||
|
{
|
||||||
|
userId: newUser.id,
|
||||||
|
orgId,
|
||||||
|
role: OrgMembershipRole.Member,
|
||||||
|
status: OrgMembershipStatus.Invited
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
|
||||||
return newUser;
|
return newUser;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
console.log("samlLogin C");
|
||||||
|
|
||||||
const isUserCompleted = Boolean(user.isAccepted);
|
const isUserCompleted = Boolean(user.isAccepted);
|
||||||
const providerAuthToken = jwt.sign(
|
const providerAuthToken = jwt.sign(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export type TGetSamlCfgDTO =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TSamlLoginDTO = {
|
export type TSamlLoginDTO = {
|
||||||
|
externalId: string;
|
||||||
username: string;
|
username: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ export const registerRoutes = async (
|
|||||||
orgBotDAL,
|
orgBotDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
|
userAliasDAL,
|
||||||
samlConfigDAL,
|
samlConfigDAL,
|
||||||
licenseService
|
licenseService
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export enum UserAliasType {
|
||||||
|
LDAP = "ldap",
|
||||||
|
SAML = "saml"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user