feat: switched to root org id pattern

This commit is contained in:
=
2025-10-19 15:23:21 +05:30
parent 6fca30f2cb
commit 545ea4e27c
20 changed files with 114 additions and 52 deletions

View File

@@ -180,6 +180,7 @@ declare module "fastify" {
id: string;
orgId: string;
parentOrgId: string;
rootOrgId: string;
};
rateLimits: RateLimitConfiguration;
// passport data

View File

@@ -6,8 +6,12 @@ export async function up(knex: Knex): Promise<void> {
const hasParentOrgId = await knex.schema.hasColumn(TableName.Organization, "parentOrgId");
if (!hasParentOrgId) {
await knex.schema.alterTable(TableName.Organization, (t) => {
// the one just above the chain
t.uuid("parentOrgId");
t.foreign("parentOrgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
// this would root organization containing various informations like billing etc
t.uuid("rootOrgId");
t.foreign("rootOrgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
});
}
@@ -22,9 +26,11 @@ export async function up(knex: Knex): Promise<void> {
export async function down(knex: Knex): Promise<void> {
const hasParentOrgId = await knex.schema.hasColumn(TableName.Organization, "parentOrgId");
if (hasParentOrgId) {
const hasRootOrgId = await knex.schema.hasColumn(TableName.Organization, "rootOrgId");
if (hasParentOrgId || hasRootOrgId) {
await knex.schema.alterTable(TableName.Organization, (t) => {
t.dropColumn("parentOrgId");
if (hasParentOrgId) t.dropColumn("parentOrgId");
if (hasRootOrgId) t.dropColumn("rootOrgId");
});
}

View File

@@ -39,7 +39,8 @@ export const OrganizationsSchema = z.object({
maxSharedSecretViewLimit: z.number().nullable().optional(),
googleSsoAuthEnforced: z.boolean().default(false),
googleSsoAuthLastUsed: z.date().nullable().optional(),
parentOrgId: z.string().uuid().nullable().optional()
parentOrgId: z.string().uuid().nullable().optional(),
rootOrgId: z.string().uuid().nullable().optional()
});
export type TOrganizations = z.infer<typeof OrganizationsSchema>;

View File

@@ -460,7 +460,7 @@ export const groupServiceFactory = ({
const { permission } = await permissionService.getOrgPermission({
actor,
actorId,
actorOrgId,
orgId: actorOrgId,
actorAuthMethod,
actorOrgId,
scope: OrganizationActionScope.Any

View File

@@ -19,7 +19,7 @@ interface TPermissionDataReturn extends TMemberships {
orgAuthEnforced?: boolean | null;
orgGoogleSsoAuthEnforced?: boolean | null;
shouldUseNewPrivilegeSystem?: boolean | null;
parentOrgId?: boolean | null;
rootOrgId?: string | null;
bypassOrgAuthEnabled?: boolean | null;
roles: {
id: string;
@@ -275,7 +275,7 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
db.ref("googleSsoAuthEnforced").withSchema(TableName.Organization).as("orgGoogleSsoAuthEnforced"),
db.ref("bypassOrgAuthEnabled").withSchema(TableName.Organization).as("bypassOrgAuthEnabled"),
db.ref("parentOrgId").withSchema(TableName.Organization).as("parentOrgId")
db.ref("rootOrgId").withSchema(TableName.Organization).as("rootOrgId")
);
const data = sqlNestRelationships({
@@ -285,7 +285,7 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
MembershipsSchema.extend({
orgAuthEnforced: z.boolean().optional().nullable(),
shouldUseNewPrivilegeSystem: z.boolean().optional().nullable(),
parentOrgId: z.string().optional().nullable(),
rootOrgId: z.string().optional().nullable(),
orgGoogleSsoAuthEnforced: z.boolean(),
bypassOrgAuthEnabled: z.boolean()
}).parse(el),

View File

@@ -209,8 +209,8 @@ export const permissionServiceFactory = ({
});
if (!permissionData?.length) throw new ForbiddenRequestError({ name: "You are not member of this organization" });
const parentOrgId = permissionData?.[0]?.parentOrgId;
const isChild = Boolean(parentOrgId);
const rootOrgId = permissionData?.[0]?.rootOrgId;
const isChild = Boolean(rootOrgId);
if (scope === OrganizationActionScope.ParentOrganization && isChild) {
throw new BadRequestError({ message: `Child organization cannot do this operation` });
} else if (scope === OrganizationActionScope.ChildOrganization && !isChild) {

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { ProjectMembershipRole, ProjectType, TProjectEnvironments } from "@app/db/schemas";
import { TProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { OrgServiceActor } from "@app/lib/types";
import { ProjectServiceActor } from "@app/lib/types";
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
export type TProjectTemplateEnvironment = Pick<TProjectEnvironments, "name" | "slug" | "position">;
@@ -31,7 +31,7 @@ export enum InfisicalProjectTemplate {
export type TProjectTemplateServiceFactory = {
listProjectTemplatesByOrg: (
actor: OrgServiceActor,
actor: ProjectServiceActor,
type?: ProjectType
) => Promise<
(
@@ -85,7 +85,7 @@ export type TProjectTemplateServiceFactory = {
>;
createProjectTemplate: (
arg: TCreateProjectTemplateDTO,
actor: OrgServiceActor
actor: ProjectServiceActor
) => Promise<{
environments: TProjectTemplateEnvironment[];
roles: {
@@ -109,7 +109,7 @@ export type TProjectTemplateServiceFactory = {
updateProjectTemplateById: (
id: string,
{ roles, environments, ...params }: TUpdateProjectTemplateDTO,
actor: OrgServiceActor
actor: ProjectServiceActor
) => Promise<{
environments: TProjectTemplateEnvironment[];
roles: {
@@ -132,7 +132,7 @@ export type TProjectTemplateServiceFactory = {
}>;
deleteProjectTemplateById: (
id: string,
actor: OrgServiceActor
actor: ProjectServiceActor
) => Promise<{
environments: TProjectTemplateEnvironment[];
roles: {
@@ -155,7 +155,7 @@ export type TProjectTemplateServiceFactory = {
}>;
findProjectTemplateById: (
id: string,
actor: OrgServiceActor
actor: ProjectServiceActor
) => Promise<{
packedRoles: TProjectTemplateRole[];
environments: TProjectTemplateEnvironment[];
@@ -179,7 +179,7 @@ export type TProjectTemplateServiceFactory = {
}>;
findProjectTemplateByName: (
name: string,
actor: OrgServiceActor
actor: ProjectServiceActor
) => Promise<{
packedRoles: TProjectTemplateRole[];
environments: TProjectTemplateEnvironment[];

View File

@@ -44,7 +44,7 @@ export const subOrgServiceFactory = ({
OrgPermissionSubjects.ChildOrganization
);
const orgLicensePlan = await licenseService.getPlan(permissionActor.parentOrgId);
const orgLicensePlan = await licenseService.getPlan(permissionActor.rootOrgId);
if (!orgLicensePlan.subOrganization) {
throw new BadRequestError({
message: "Child organization creation failed. Please upgrade your instance to Infisical's Enterprise plan."
@@ -52,7 +52,10 @@ export const subOrgServiceFactory = ({
}
const organization = await orgDAL.transaction(async (tx) => {
const org = await orgDAL.create({ name, slug: name, parentOrgId: permissionActor.orgId }, tx);
const org = await orgDAL.create(
{ name, slug: name, rootOrgId: permissionActor.orgId, parentOrgId: permissionActor.orgId },
tx
);
const membership = await membershipDAL.create(
{
scope: AccessScope.Organization,
@@ -83,7 +86,7 @@ export const subOrgServiceFactory = ({
actorId: permissionActor.id,
actor: permissionActor.type,
orgId: permissionActor.parentOrgId,
actorOrgId: permissionActor.parentOrgId,
actorOrgId: permissionActor.rootOrgId,
actorAuthMethod: permissionActor.authMethod,
scope: OrganizationActionScope.ParentOrganization
});
@@ -91,7 +94,7 @@ export const subOrgServiceFactory = ({
const organizations = await orgDAL.listSubOrganizations({
actorId: permissionActor.id,
actorType: permissionActor.type,
orgId: permissionActor.parentOrgId,
orgId: permissionActor.rootOrgId,
isAccessible: data?.isAccessible,
limit: data?.limit,
offset: data?.offset

View File

@@ -78,6 +78,7 @@ export type OrgServiceActor = {
id: string;
authMethod: ActorAuthMethod;
orgId: string;
rootOrgId: string;
parentOrgId: string;
};

View File

@@ -20,6 +20,7 @@ export type TAuthMode =
tokenVersionId: string; // the session id of token used
user: TUsers;
orgId: string;
rootOrgId: string;
parentOrgId: string;
authMethod: AuthMethod;
isMfaVerified?: boolean;
@@ -32,6 +33,7 @@ export type TAuthMode =
userId: string;
user: TUsers;
orgId: string;
rootOrgId: string;
parentOrgId: string;
token: string;
}
@@ -41,6 +43,7 @@ export type TAuthMode =
actor: ActorType.SERVICE;
serviceTokenId: string;
orgId: string;
rootOrgId: string;
parentOrgId: string;
authMethod: null;
token: string;
@@ -51,6 +54,7 @@ export type TAuthMode =
identityId: string;
identityName: string;
orgId: string;
rootOrgId: string;
parentOrgId: string;
authMethod: null;
isInstanceAdmin?: boolean;
@@ -61,6 +65,7 @@ export type TAuthMode =
actor: ActorType.SCIM_CLIENT;
scimTokenId: string;
orgId: string;
rootOrgId: string;
parentOrgId: string;
authMethod: null;
};
@@ -145,10 +150,8 @@ export const injectIdentity = fp(
switch (authMode) {
case AuthMode.JWT: {
const { user, tokenVersionId, orgId, parentOrgId } = await server.services.authToken.fnValidateJwtIdentity(
token,
subOrganizationSelector
);
const { user, tokenVersionId, orgId, rootOrgId, parentOrgId } =
await server.services.authToken.fnValidateJwtIdentity(token, subOrganizationSelector);
requestContext.set("orgId", orgId);
req.auth = {
@@ -158,6 +161,7 @@ export const injectIdentity = fp(
tokenVersionId,
actor,
orgId,
rootOrgId,
parentOrgId,
authMethod: token.authMethod,
isMfaVerified: token.isMfaVerified,
@@ -177,6 +181,7 @@ export const injectIdentity = fp(
authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
actor,
orgId: identity.orgId,
rootOrgId: identity.rootOrgId,
parentOrgId: identity.parentOrgId,
identityId: identity.identityId,
identityName: identity.name,
@@ -213,7 +218,8 @@ export const injectIdentity = fp(
req.auth = {
orgId: serviceToken.orgId,
parentOrgId: serviceToken.orgId,
rootOrgId: serviceToken.rootOrgId,
parentOrgId: serviceToken.parentOrgId,
authMode: AuthMode.SERVICE_TOKEN as const,
serviceToken,
serviceTokenId: serviceToken.id,
@@ -235,7 +241,16 @@ export const injectIdentity = fp(
if (subOrganizationSelector)
throw new BadRequestError({ message: `Service token doesn't support sub organization selector` });
req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null, parentOrgId: orgId };
req.auth = {
authMode: AuthMode.SCIM_TOKEN,
actor,
scimTokenId,
orgId,
authMethod: null,
// scim cannot be done for sub organization
rootOrgId: orgId,
parentOrgId: orgId
};
break;
}
default:

View File

@@ -15,6 +15,7 @@ export const injectPermission = fp(async (server) => {
id: req.auth.userId,
orgId: req.auth.orgId, // if the req.auth.authMode is AuthMode.API_KEY, the orgId will be "API_KEY"
authMethod: req.auth.authMethod, // if the req.auth.authMode is AuthMode.API_KEY, the authMethod will be null
rootOrgId: req.auth.rootOrgId,
parentOrgId: req.auth.parentOrgId
};
@@ -27,6 +28,7 @@ export const injectPermission = fp(async (server) => {
id: req.auth.identityId,
orgId: req.auth.orgId,
authMethod: null,
rootOrgId: req.auth.rootOrgId,
parentOrgId: req.auth.parentOrgId
};
@@ -38,7 +40,8 @@ export const injectPermission = fp(async (server) => {
type: ActorType.SERVICE,
id: req.auth.serviceTokenId,
orgId: req.auth.orgId,
parentOrgId: req.auth.orgId,
rootOrgId: req.auth.rootOrgId,
parentOrgId: req.auth.parentOrgId,
authMethod: null
};
@@ -50,7 +53,8 @@ export const injectPermission = fp(async (server) => {
type: ActorType.SCIM_CLIENT,
id: req.auth.scimTokenId,
orgId: req.auth.orgId,
parentOrgId: req.auth.orgId,
rootOrgId: req.auth.rootOrgId,
parentOrgId: req.auth.parentOrgId,
authMethod: null
};

View File

@@ -76,7 +76,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
req.permission.id,
req.params.organizationId,
req.permission.authMethod,
req.permission.parentOrgId,
req.permission.rootOrgId,
req.permission.orgId
);
return { organization };

View File

@@ -210,11 +210,12 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, membershipUserDAL, orgD
if (!user || !user.isAccepted) throw new NotFoundError({ message: `User with ID '${session.userId}' not found` });
let orgId = "";
let rootOrgId = "";
let parentOrgId = "";
if (token.organizationId) {
if (subOrganizationSelector) {
const subOrganization = await orgDAL.findOne({
parentOrgId: token.organizationId,
rootOrgId: token.organizationId,
slug: subOrganizationSelector
});
if (!subOrganization)
@@ -234,7 +235,8 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, membershipUserDAL, orgD
throw new ForbiddenRequestError({ message: "User organization membership is inactive" });
}
orgId = subOrganization.id;
parentOrgId = token.organizationId;
rootOrgId = token.organizationId;
parentOrgId = subOrganization.parentOrgId;
} else {
const orgMembership = await membershipUserDAL.findOne({
actorUserId: user.id,
@@ -251,11 +253,12 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL, membershipUserDAL, orgD
}
orgId = token.organizationId;
rootOrgId = token.organizationId;
parentOrgId = token.organizationId;
}
}
return { user, tokenVersionId: token.tokenVersionId, orgId, parentOrgId };
return { user, tokenVersionId: token.tokenVersionId, orgId, rootOrgId, parentOrgId };
};
return {

View File

@@ -258,7 +258,13 @@ export const authSignupServiceFactory = ({
let refreshTokenExpiresIn: string | number = appCfg.JWT_REFRESH_LIFETIME;
if (organizationId) {
const org = await orgService.findOrganizationById(user.id, organizationId, authMethod, organizationId);
const org = await orgService.findOrganizationById(
user.id,
organizationId,
authMethod,
organizationId,
organizationId
);
if (org && org.userTokenExpiration) {
tokenSessionExpiresIn = getMinExpiresIn(appCfg.JWT_AUTH_LIFETIME, org.userTokenExpiration);
refreshTokenExpiresIn = org.userTokenExpiration;

View File

@@ -210,10 +210,12 @@ export const identityAccessTokenServiceFactory = ({
});
}
let orgId = "";
const parentOrgId = identityAccessToken.identityScopeOrgId;
let parentOrgId = "";
const identityOrgDetails = await orgDAL.findOne({ id: identityAccessToken.identityScopeOrgId });
const rootOrgId = identityOrgDetails.rootOrgId || identityOrgDetails.id;
if (subOrganizationSelector) {
const subOrganization = await orgDAL.findOne({ parentOrgId, slug: subOrganizationSelector });
const subOrganization = await orgDAL.findOne({ rootOrgId, slug: subOrganizationSelector });
if (!subOrganizationSelector)
throw new BadRequestError({ message: `Sub organization ${subOrganizationSelector} not found` });
@@ -227,18 +229,20 @@ export const identityAccessTokenServiceFactory = ({
throw new BadRequestError({ message: "Identity does not belong to any organization" });
}
orgId = subOrganization.id;
parentOrgId = subOrganization.parentOrgId as string;
} else {
const identityOrgMembership = await membershipIdentityDAL.findOne({
scope: AccessScope.Organization,
actorIdentityId: identityAccessToken.identityId,
scopeOrgId: parentOrgId
scopeOrgId: rootOrgId
});
if (!identityOrgMembership) {
throw new BadRequestError({ message: "Identity does not belong to any organization" });
}
orgId = parentOrgId;
orgId = rootOrgId;
parentOrgId = rootOrgId;
}
let { accessTokenNumUses } = identityAccessToken;
@@ -249,7 +253,7 @@ export const identityAccessTokenServiceFactory = ({
await validateAccessTokenExp({ ...identityAccessToken, accessTokenNumUses });
await accessTokenQueue.updateIdentityAccessTokenStatus(identityAccessToken.id, Number(accessTokenNumUses) + 1);
return { ...identityAccessToken, orgId, parentOrgId };
return { ...identityAccessToken, orgId, rootOrgId, parentOrgId };
};
return { renewAccessToken, revokeAccessToken, fnValidateIdentityAccessToken };

View File

@@ -291,5 +291,13 @@ export const membershipUserDALFactory = (db: TDbClient) => {
}
};
// const listAvailableUsers = async (scopeData: AccessScopeData) => {
// try {
// const query = await db.replicaNode()(TableName.Membership).where(`${TableName.Membership}.scopeOrgId`);
// } catch (error) {
// throw new DatabaseError({ error, name: "ListAvailableUsers" });
// }
// };
return { ...orm, findUsers, getUserById };
};

View File

@@ -65,7 +65,7 @@ export const orgDALFactory = (db: TDbClient) => {
const buildBaseQuery = (orgIdSubquery: Knex.QueryBuilder) => {
return db
.replicaNode()(TableName.Organization)
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.whereIn(`${TableName.Organization}.id`, orgIdSubquery)
.leftJoin(TableName.Project, `${TableName.Organization}.id`, `${TableName.Project}.orgId`)
.leftJoin(TableName.Membership, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`)
@@ -168,7 +168,7 @@ export const orgDALFactory = (db: TDbClient) => {
// TODO(sub-org:group): check this when implement group support
const query = db
.replicaNode()(TableName.Organization)
.where(`${TableName.Organization}.parentOrgId`, dto.orgId)
.where(`${TableName.Organization}.rootOrgId`, dto.orgId)
.select(selectAllTableCols(TableName.Organization));
if (dto.isAccessible) {
@@ -196,7 +196,7 @@ export const orgDALFactory = (db: TDbClient) => {
const org = (await db
.replicaNode()(TableName.Organization)
.where({ [`${TableName.Organization}.id` as "id"]: orgId })
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.leftJoin(TableName.SamlConfig, (qb) => {
qb.on(`${TableName.SamlConfig}.orgId`, "=", `${TableName.Organization}.id`).andOn(
`${TableName.SamlConfig}.isActive`,
@@ -233,7 +233,7 @@ export const orgDALFactory = (db: TDbClient) => {
try {
const org = (await db
.replicaNode()(TableName.Organization)
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.where({ [`${TableName.Organization}.slug` as "slug"]: orgSlug })
.leftJoin(TableName.SamlConfig, (qb) => {
qb.on(`${TableName.SamlConfig}.orgId`, "=", `${TableName.Organization}.id`).andOn(
@@ -279,7 +279,7 @@ export const orgDALFactory = (db: TDbClient) => {
.whereNotNull(`${TableName.Membership}.actorUserId`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.join(TableName.Organization, `${TableName.Membership}.scopeOrgId`, `${TableName.Organization}.id`)
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.leftJoin(TableName.SamlConfig, (qb) => {
qb.on(`${TableName.SamlConfig}.orgId`, "=", `${TableName.Organization}.id`).andOn(
`${TableName.SamlConfig}.isActive`,
@@ -651,7 +651,7 @@ export const orgDALFactory = (db: TDbClient) => {
})
.join(TableName.Users, `${TableName.Users}.id`, `${TableName.Membership}.actorUserId`)
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`)
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.leftJoin(TableName.UserAliases, function joinUserAlias() {
this.on(`${TableName.UserAliases}.userId`, "=", `${TableName.Membership}.actorUserId`)
.andOn(`${TableName.UserAliases}.orgId`, "=", `${TableName.Membership}.scopeOrgId`)
@@ -690,7 +690,7 @@ export const orgDALFactory = (db: TDbClient) => {
.replicaNode()(TableName.Membership)
.where({ actorIdentityId: identityId })
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
.whereNull(`${TableName.Organization}.parentOrgId`)
.whereNull(`${TableName.Organization}.rootOrgId`)
.whereNotNull(`${TableName.Membership}.actorIdentityId`)
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
.join(TableName.Organization, `${TableName.Membership}.scopeOrgId`, `${TableName.Organization}.id`)

View File

@@ -157,7 +157,7 @@ export const orgServiceFactory = ({
userId: string,
orgId: string,
actorAuthMethod: ActorAuthMethod,
parentOrgId: string,
rootOrgId: string,
actorOrgId: string
) => {
await permissionService.getOrgPermission({
@@ -165,17 +165,17 @@ export const orgServiceFactory = ({
actorId: userId,
orgId,
actorAuthMethod,
actorOrgId: parentOrgId,
actorOrgId: rootOrgId,
scope: OrganizationActionScope.Any
});
const appCfg = getConfig();
const org = await orgDAL.findOrgById(orgId);
if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` });
const hasSubOrg = actorOrgId !== parentOrgId;
const hasSubOrg = actorOrgId !== rootOrgId;
let subOrg;
if (hasSubOrg) {
subOrg = await orgDAL.findOne({ parentOrgId, id: actorOrgId });
subOrg = await orgDAL.findOne({ rootOrgId, id: actorOrgId });
}
if (!org.userTokenExpiration) {

View File

@@ -298,7 +298,6 @@ export const projectServiceFactory = ({
projectTemplate = await projectTemplateService.findProjectTemplateByName(template, {
id: actorId,
orgId: organization.id,
parentOrgId: organization.id,
type: actor,
authMethod: actorAuthMethod
});

View File

@@ -25,10 +25,12 @@ import {
TGetServiceTokenInfoDTO,
TProjectServiceTokensDTO
} from "./service-token-types";
import { TOrgDALFactory } from "../org/org-dal";
type TServiceTokenServiceFactoryDep = {
serviceTokenDAL: TServiceTokenDALFactory;
userDAL: TUserDALFactory;
orgDAL: Pick<TOrgDALFactory, "findById">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
projectEnvDAL: Pick<TProjectEnvDALFactory, "findBySlugs">;
projectDAL: Pick<TProjectDALFactory, "findById">;
@@ -45,7 +47,8 @@ export const serviceTokenServiceFactory = ({
projectEnvDAL,
projectDAL,
accessTokenQueue,
smtpService
smtpService,
orgDAL
}: TServiceTokenServiceFactoryDep) => {
const createServiceToken = async ({
iv,
@@ -184,7 +187,15 @@ export const serviceTokenServiceFactory = ({
if (!isMatch) throw new UnauthorizedError({ message: "Invalid service token" });
await accessTokenQueue.updateServiceTokenStatus(serviceToken.id);
return { ...serviceToken, lastUsed: new Date(), orgId: project.orgId };
const serviceTokenOrgDetails = await orgDAL.findById(project.orgId);
return {
...serviceToken,
lastUsed: new Date(),
orgId: project.orgId,
parentOrgId: serviceTokenOrgDetails.parentOrgId || serviceTokenOrgDetails.id,
rootOrgId: serviceTokenOrgDetails.rootOrgId || serviceTokenOrgDetails.id
};
};
const notifyExpiringTokens = async () => {