feat: switched to root org id pattern

This commit is contained in:
=
2025-10-20 18:58:13 +05:30
parent 6fca30f2cb
commit 545ea4e27c
20 changed files with 114 additions and 52 deletions
@@ -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 {
@@ -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;
@@ -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 };
@@ -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 };
};
+7 -7
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`)
+4 -4
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) {
@@ -298,7 +298,6 @@ export const projectServiceFactory = ({
projectTemplate = await projectTemplateService.findProjectTemplateByName(template, {
id: actorId,
orgId: organization.id,
parentOrgId: organization.id,
type: actor,
authMethod: actorAuthMethod
});
@@ -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 () => {