From 8afc391e97c495e60eaeb44049559f58fae3663b Mon Sep 17 00:00:00 2001 From: = Date: Mon, 20 Oct 2025 00:40:27 +0530 Subject: [PATCH] feat: billing fixes --- backend/src/ee/routes/v1/index.ts | 2 +- .../src/ee/services/license/license-dal.ts | 33 ++++++++++-- .../ee/services/license/license-service.ts | 50 +++++++++---------- backend/src/server/routes/index.ts | 1 - backend/src/server/routes/v1/index.ts | 2 +- .../src/services/identity/identity-org-dal.ts | 2 +- .../src/services/identity/identity-service.ts | 9 +++- .../membership-identity-service.ts | 2 +- .../org/org-membership-identity-factory.ts | 2 +- .../org/org-membership-user-factory.ts | 2 +- backend/src/services/org/org-dal.ts | 22 +++++++- .../service-token/service-token-service.ts | 2 +- .../hooks/api/orgIdentityMembership/index.tsx | 6 ++- frontend/src/hooks/api/organization/index.ts | 2 +- .../src/hooks/api/organization/queries.tsx | 4 +- .../components/NavBar/Navbar.tsx | 2 +- .../NavBar/NewSubOrganizationForm.tsx | 2 +- .../IdentitySection/IdentityLinkForm.tsx | 2 +- .../IdentitySection/IdentityModal.tsx | 2 +- .../IdentitySection/IdentitySection.tsx | 2 +- .../components/OrgTabGroup/OrgTabGroup.tsx | 2 +- frontend/src/pages/organization/layout.tsx | 2 +- 22 files changed, 103 insertions(+), 52 deletions(-) diff --git a/backend/src/ee/routes/v1/index.ts b/backend/src/ee/routes/v1/index.ts index 8d4671e50..31847b503 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -48,9 +48,9 @@ import { registerSshCertRouter } from "./ssh-certificate-router"; import { registerSshCertificateTemplateRouter } from "./ssh-certificate-template-router"; import { registerSshHostGroupRouter } from "./ssh-host-group-router"; import { registerSshHostRouter } from "./ssh-host-router"; +import { registerSubOrgRouter } from "./sub-org-router"; import { registerTrustedIpRouter } from "./trusted-ip-router"; import { registerUserAdditionalPrivilegeRouter } from "./user-additional-privilege-router"; -import { registerSubOrgRouter } from "./sub-org-router"; export const registerV1EERoutes = async (server: FastifyZodProvider) => { // org role starts with organization diff --git a/backend/src/ee/services/license/license-dal.ts b/backend/src/ee/services/license/license-dal.ts index a2bd7ec51..853f3a994 100644 --- a/backend/src/ee/services/license/license-dal.ts +++ b/backend/src/ee/services/license/license-dal.ts @@ -10,6 +10,7 @@ export const licenseDALFactory = (db: TDbClient) => { const countOfOrgMembers = async (orgId: string | null, tx?: Knex) => { try { const doc = await (tx || db.replicaNode())(TableName.Membership) + .join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`) .where({ status: OrgMembershipStatus.Accepted, scope: AccessScope.Organization }) .andWhere((bd) => { if (orgId) { @@ -18,6 +19,7 @@ export const licenseDALFactory = (db: TDbClient) => { }) .join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`) .where(`${TableName.Users}.isGhost`, false) + .whereNull(`${TableName.Organization}.rootOrgId`) .count(); return Number(doc?.[0]?.count ?? 0); } catch (error) { @@ -25,10 +27,31 @@ export const licenseDALFactory = (db: TDbClient) => { } }; + const countOfOrgIdentities = async (orgId: string | null, tx?: Knex) => { + try { + // count org identities + const identityDoc = await (tx || db.replicaNode())(TableName.Identity) + .join(TableName.Organization, `${TableName.Identity}.orgId`, `${TableName.Organization}.id`) + .where((bd) => { + if (orgId) { + void bd.where(`${TableName.Organization}.rootOrgId`, orgId).orWhere(`${TableName.Organization}.id`, orgId); + } + }) + .count(); + + const identityCount = Number(identityDoc?.[0].count); + + return identityCount; + } catch (error) { + throw new DatabaseError({ error, name: "Count of Org Users + Identities" }); + } + }; + const countOrgUsersAndIdentities = async (orgId: string | null, tx?: Knex) => { try { // count org users const userDoc = await (tx || db.replicaNode())(TableName.Membership) + .join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.Membership}.scopeOrgId`) .where({ status: OrgMembershipStatus.Accepted, scope: AccessScope.Organization }) .whereNotNull(`${TableName.Membership}.actorUserId`) .andWhere((bd) => { @@ -38,17 +61,17 @@ export const licenseDALFactory = (db: TDbClient) => { }) .join(TableName.Users, `${TableName.Membership}.actorUserId`, `${TableName.Users}.id`) .where(`${TableName.Users}.isGhost`, false) + .whereNull(`${TableName.Organization}.rootOrgId`) .count(); const userCount = Number(userDoc?.[0].count); // count org identities - const identityDoc = await (tx || db.replicaNode())(TableName.Membership) - .where({ scope: AccessScope.Organization }) - .whereNotNull(`${TableName.Membership}.actorIdentityId`) + const identityDoc = await (tx || db.replicaNode())(TableName.Identity) + .join(TableName.Organization, `${TableName.Identity}.orgId`, `${TableName.Organization}.id`) .where((bd) => { if (orgId) { - void bd.where(`${TableName.Membership}.scopeOrgId`, orgId); + void bd.where(`${TableName.Organization}.rootOrgId`, orgId).orWhere(`${TableName.Organization}.id`, orgId); } }) .count(); @@ -61,5 +84,5 @@ export const licenseDALFactory = (db: TDbClient) => { } }; - return { countOfOrgMembers, countOrgUsersAndIdentities }; + return { countOfOrgMembers, countOrgUsersAndIdentities, countOfOrgIdentities }; }; diff --git a/backend/src/ee/services/license/license-service.ts b/backend/src/ee/services/license/license-service.ts index 8fc4987f4..835c80dd5 100644 --- a/backend/src/ee/services/license/license-service.ts +++ b/backend/src/ee/services/license/license-service.ts @@ -15,7 +15,6 @@ import { getConfig } from "@app/lib/config/env"; import { verifyOfflineLicense } from "@app/lib/crypto"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; -import { TIdentityOrgDALFactory } from "@app/services/identity/identity-org-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal"; @@ -46,11 +45,10 @@ import { } from "./license-types"; type TLicenseServiceFactoryDep = { - orgDAL: Pick; + orgDAL: Pick; permissionService: Pick; licenseDAL: TLicenseDALFactory; keyStore: Pick; - identityOrgMembershipDAL: TIdentityOrgDALFactory; projectDAL: TProjectDALFactory; }; @@ -67,7 +65,6 @@ export const licenseServiceFactory = ({ permissionService, licenseDAL, keyStore, - identityOrgMembershipDAL, projectDAL }: TLicenseServiceFactoryDep) => { let isValidLicense = false; @@ -200,19 +197,21 @@ export const licenseServiceFactory = ({ return JSON.parse(cachedPlan) as TFeatureSet; } - const org = await orgDAL.findOrgById(orgId); + const org = await orgDAL.findRootOrgDetails(orgId); if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); + const rootOrgId = org.id; + const { data: { currentPlan } } = await licenseServerCloudApi.request.get<{ currentPlan: TFeatureSet }>( `/api/license-server/v1/customers/${org.customerId}/cloud-plan` ); - const workspacesUsed = await projectDAL.countOfOrgProjects(orgId); + const workspacesUsed = await projectDAL.countOfOrgProjects(rootOrgId); currentPlan.workspacesUsed = workspacesUsed; - const membersUsed = await licenseDAL.countOfOrgMembers(orgId); + const membersUsed = await licenseDAL.countOfOrgMembers(rootOrgId); currentPlan.membersUsed = membersUsed; - const identityUsed = await licenseDAL.countOrgUsersAndIdentities(orgId); + const identityUsed = await licenseDAL.countOrgUsersAndIdentities(rootOrgId); currentPlan.identitiesUsed = identityUsed; if (currentPlan.identityLimit && currentPlan.identityLimit !== identityUsed) { @@ -285,10 +284,10 @@ export const licenseServiceFactory = ({ }; const updateSubscriptionOrgMemberCount = async (orgId: string, tx?: Knex) => { - const org = await orgDAL.findOrgById(orgId); + const org = await orgDAL.findRootOrgDetails(orgId); if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); - const rootOrgId = org.rootOrgId || org.id; + const rootOrgId = org.id; if (instanceType === InstanceType.Cloud) { const quantity = await licenseDAL.countOfOrgMembers(rootOrgId, tx); const quantityIdentities = await licenseDAL.countOrgUsersAndIdentities(rootOrgId, tx); @@ -381,7 +380,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -420,7 +419,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: "Organization not found" @@ -473,7 +472,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -539,7 +538,7 @@ export const licenseServiceFactory = ({ const getUsageMetrics = async (orgId: string) => { const [orgMembersUsed, identityUsed, projectCount] = await Promise.all([ orgDAL.countAllOrgMembers(orgId), - identityOrgMembershipDAL.countAllOrgIdentities({ scopeOrgId: orgId }), + licenseDAL.countOfOrgIdentities(orgId), projectDAL.countOfOrgProjects(orgId) ]); @@ -563,7 +562,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -607,7 +606,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -642,7 +641,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -669,7 +668,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -706,7 +705,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -745,7 +744,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -781,7 +780,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -809,7 +808,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -840,7 +839,7 @@ export const licenseServiceFactory = ({ OrgPermissionSubjects.Billing ); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -864,7 +863,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -888,7 +887,7 @@ export const licenseServiceFactory = ({ }); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionBillingActions.Read, OrgPermissionSubjects.Billing); - const organization = await orgDAL.findOrgById(orgId); + const organization = await orgDAL.findById(orgId); if (!organization) { throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` @@ -933,7 +932,6 @@ export const licenseServiceFactory = ({ getLicenseId, invalidateGetPlan, updateSubscriptionOrgMemberCount, - refreshPlan, getOrgPlan, getOrgPlansTableByBillCycle, startOrgTrial, diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index fa5cd7a11..ddc757e6f 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -561,7 +561,6 @@ export const registerRoutes = async ( orgDAL, licenseDAL, keyStore, - identityOrgMembershipDAL, projectDAL }); diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index 307b922d3..710bf4240 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -32,6 +32,7 @@ import { registerIdentityKubernetesRouter } from "./identity-kubernetes-auth-rou import { registerIdentityLdapAuthRouter } from "./identity-ldap-auth-router"; import { registerIdentityOciAuthRouter } from "./identity-oci-auth-router"; import { registerIdentityOidcAuthRouter } from "./identity-oidc-auth-router"; +import { registerOrgIdentityMembershipRouter } from "./identity-org-membership-router"; import { registerIdentityProjectRouter } from "./identity-project-router"; import { registerIdentityRouter } from "./identity-router"; import { registerIdentityTlsCertAuthRouter } from "./identity-tls-cert-auth-router"; @@ -65,7 +66,6 @@ import { registerUserEngagementRouter } from "./user-engagement-router"; import { registerUserRouter } from "./user-router"; import { registerWebhookRouter } from "./webhook-router"; import { registerWorkflowIntegrationRouter } from "./workflow-integration-router"; -import { registerOrgIdentityMembershipRouter } from "./identity-org-membership-router"; export const registerV1Routes = async (server: FastifyZodProvider) => { await server.register(registerSsoRouter, { prefix: "/sso" }); diff --git a/backend/src/services/identity/identity-org-dal.ts b/backend/src/services/identity/identity-org-dal.ts index 3d1004608..04c384843 100644 --- a/backend/src/services/identity/identity-org-dal.ts +++ b/backend/src/services/identity/identity-org-dal.ts @@ -654,7 +654,7 @@ export const identityOrgDALFactory = (db: TDbClient) => { tx?: Knex ) => { try { - const query = (tx || db.replicaNode())(TableName.Membership) + const query = (tx || db.replicaNode())(TableName.Identity) .where(`${TableName.Membership}.scope`, AccessScope.Organization) .whereNotNull(`${TableName.Membership}.actorIdentityId`) .where(filter) diff --git a/backend/src/services/identity/identity-service.ts b/backend/src/services/identity/identity-service.ts index 2183ec826..f2caeb053 100644 --- a/backend/src/services/identity/identity-service.ts +++ b/backend/src/services/identity/identity-service.ts @@ -12,6 +12,7 @@ import { TKeyStoreFactory } from "@app/keystore/keystore"; import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal"; +import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; import { TMembershipIdentityDALFactory } from "../membership-identity/membership-identity-dal"; import { TOrgDALFactory } from "../org/org-dal"; @@ -28,7 +29,6 @@ import { TSearchOrgIdentitiesByOrgIdDTO, TUpdateIdentityDTO } from "./identity-types"; -import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal"; type TIdentityServiceFactoryDep = { identityDAL: TIdentityDALFactory; @@ -347,6 +347,13 @@ export const identityServiceFactory = ({ } await membershipIdentityDAL.transaction(async (tx) => { + await identityMetadataDAL.delete( + { + identityId: id, + orgId: actorOrgId + }, + tx + ); const identityProjectMembership = await membershipIdentityDAL.find( { actorIdentityId: id, diff --git a/backend/src/services/membership-identity/membership-identity-service.ts b/backend/src/services/membership-identity/membership-identity-service.ts index c1bb9cbbc..16292ea82 100644 --- a/backend/src/services/membership-identity/membership-identity-service.ts +++ b/backend/src/services/membership-identity/membership-identity-service.ts @@ -6,6 +6,7 @@ import { ms } from "@app/lib/ms"; import { SearchResourceOperators } from "@app/lib/search-resource/search"; import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal"; +import { TIdentityDALFactory } from "../identity/identity-dal"; import { TMembershipRoleDALFactory } from "../membership/membership-role-dal"; import { TOrgDALFactory } from "../org/org-dal"; import { TRoleDALFactory } from "../role/role-dal"; @@ -20,7 +21,6 @@ import { import { newNamespaceMembershipIdentityFactory } from "./namespace/namespace-membership-identity-factory"; import { newOrgMembershipIdentityFactory } from "./org/org-membership-identity-factory"; import { newProjectMembershipIdentityFactory } from "./project/project-membership-identity-factory"; -import { TIdentityDALFactory } from "../identity/identity-dal"; type TMembershipIdentityServiceFactoryDep = { membershipIdentityDAL: TMembershipIdentityDALFactory; diff --git a/backend/src/services/membership-identity/org/org-membership-identity-factory.ts b/backend/src/services/membership-identity/org/org-membership-identity-factory.ts index caffc984e..1ad77dfbd 100644 --- a/backend/src/services/membership-identity/org/org-membership-identity-factory.ts +++ b/backend/src/services/membership-identity/org/org-membership-identity-factory.ts @@ -8,11 +8,11 @@ import { } from "@app/ee/services/permission/permission-fns"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { BadRequestError, InternalServerError, PermissionBoundaryError } from "@app/lib/errors"; +import { TIdentityDALFactory } from "@app/services/identity/identity-dal"; import { TOrgDALFactory } from "@app/services/org/org-dal"; import { isCustomOrgRole } from "@app/services/org/org-role-fns"; import { TMembershipIdentityScopeFactory } from "../membership-identity-types"; -import { TIdentityDALFactory } from "@app/services/identity/identity-dal"; type TOrgMembershipIdentityScopeFactoryDep = { permissionService: Pick; diff --git a/backend/src/services/membership-user/org/org-membership-user-factory.ts b/backend/src/services/membership-user/org/org-membership-user-factory.ts index 761a1397d..ca867286a 100644 --- a/backend/src/services/membership-user/org/org-membership-user-factory.ts +++ b/backend/src/services/membership-user/org/org-membership-user-factory.ts @@ -15,8 +15,8 @@ import { isCustomOrgRole } from "@app/services/org/org-role-fns"; import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service"; import { TUserDALFactory } from "@app/services/user/user-dal"; -import { TMembershipUserScopeFactory } from "../membership-user-types"; import { TMembershipUserDALFactory } from "../membership-user-dal"; +import { TMembershipUserScopeFactory } from "../membership-user-types"; type TOrgMembershipUserScopeFactoryDep = { permissionService: Pick; diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index fd1a361f0..ff625875a 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -705,6 +705,25 @@ export const orgDALFactory = (db: TDbClient) => { } }; + const findRootOrgDetails = async (orgId: string): Promise => { + try { + const org = await db + .replicaNode()(TableName.Organization) + .select(selectAllTableCols(TableName.Organization)) + .where( + "id", + db(TableName.Organization) + .select(db.raw(`CASE WHEN "rootOrgId" IS NULL THEN id ELSE "rootOrgId" END`)) + .where("id", orgId) + ) + .first(); + + return org; + } catch (error) { + throw new DatabaseError({ error, name: "FindRootOrgDetails" }); + } + }; + return withTransaction(db, { ...orgOrm, findOrgByProjectId, @@ -728,6 +747,7 @@ export const orgDALFactory = (db: TDbClient) => { deleteMembershipById, deleteMembershipsById, updateMembership, - findIdentityOrganization + findIdentityOrganization, + findRootOrgDetails }); }; diff --git a/backend/src/services/service-token/service-token-service.ts b/backend/src/services/service-token/service-token-service.ts index 8b50e9970..081b99208 100644 --- a/backend/src/services/service-token/service-token-service.ts +++ b/backend/src/services/service-token/service-token-service.ts @@ -14,6 +14,7 @@ import { logger } from "@app/lib/logger"; import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue"; import { ActorType } from "../auth/auth-type"; +import { TOrgDALFactory } from "../org/org-dal"; import { TProjectDALFactory } from "../project/project-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service"; @@ -25,7 +26,6 @@ import { TGetServiceTokenInfoDTO, TProjectServiceTokensDTO } from "./service-token-types"; -import { TOrgDALFactory } from "../org/org-dal"; type TServiceTokenServiceFactoryDep = { serviceTokenDAL: TServiceTokenDALFactory; diff --git a/frontend/src/hooks/api/orgIdentityMembership/index.tsx b/frontend/src/hooks/api/orgIdentityMembership/index.tsx index 61d572e30..a28824501 100644 --- a/frontend/src/hooks/api/orgIdentityMembership/index.tsx +++ b/frontend/src/hooks/api/orgIdentityMembership/index.tsx @@ -1,2 +1,6 @@ export { useCreateOrgIdentityMembership, useDeleteOrgIdentityMembership } from "./mutation"; -export type { TCreateOrgIdentityMembershipDTO, TDeleteOrgIdentityMembershipDTO, TOrgIdentityMembership } from "./types"; +export type { + TCreateOrgIdentityMembershipDTO, + TDeleteOrgIdentityMembershipDTO, + TOrgIdentityMembership +} from "./types"; diff --git a/frontend/src/hooks/api/organization/index.ts b/frontend/src/hooks/api/organization/index.ts index 5f2be9b76..7c283691e 100644 --- a/frontend/src/hooks/api/organization/index.ts +++ b/frontend/src/hooks/api/organization/index.ts @@ -1,12 +1,12 @@ export { useAddOrgPmtMethod, - useGetAvailableOrgIdentities, useAddOrgTaxId, useCreateCustomerPortalSession, useCreateOrg, useDeleteOrgById, useDeleteOrgPmtMethod, useDeleteOrgTaxId, + useGetAvailableOrgIdentities, useGetIdentityMembershipOrgs, useGetOrganizationGroups, useGetOrganizations, diff --git a/frontend/src/hooks/api/organization/queries.tsx b/frontend/src/hooks/api/organization/queries.tsx index d76b8a54b..36c0fd1fb 100644 --- a/frontend/src/hooks/api/organization/queries.tsx +++ b/frontend/src/hooks/api/organization/queries.tsx @@ -582,7 +582,7 @@ export const useGetAvailableOrgIdentities = (enabled = true) => queryKey: organizationKeys.getAvailableIdentities(), queryFn: async () => { const { data } = await apiRequest.get<{ identities: { name: string; id: string }[] }>( - `/api/v1/organization/identities/available` + "/api/v1/organization/identities/available" ); return data.identities; @@ -596,7 +596,7 @@ export const useGetAvailableOrgUsers = (enabled = true) => queryFn: async () => { const { data } = await apiRequest.get<{ users: { username: string; id: string; firstName: string; lastName: string }[]; - }>(`/api/v1/organization/users/available`); + }>("/api/v1/organization/users/available"); return data.users; }, diff --git a/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx b/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx index ffaf5b068..3b48e7763 100644 --- a/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/NavBar/Navbar.tsx @@ -58,8 +58,8 @@ import { AuthMethod } from "@app/hooks/api/users/types"; import { navigateUserToOrg } from "@app/pages/auth/LoginPage/Login.utils"; import { ServerAdminsPanel } from "../ServerAdminsPanel/ServerAdminsPanel"; -import { NotificationDropdown } from "./NotificationDropdown"; import { NewSubOrganizationForm } from "./NewSubOrganizationForm"; +import { NotificationDropdown } from "./NotificationDropdown"; const getPlan = (subscription: SubscriptionPlan) => { if (subscription.groups) return "Enterprise"; diff --git a/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx b/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx index 81946de8d..c05c5abaa 100644 --- a/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx @@ -4,8 +4,8 @@ import { z } from "zod"; import { createNotification } from "@app/components/notifications"; import { Button, FormControl, Input } from "@app/components/v2"; -import { GenericResourceNameSchema } from "@app/lib/schemas"; import { useCreateSubOrganization } from "@app/hooks/api"; +import { GenericResourceNameSchema } from "@app/lib/schemas"; type ContentProps = { onClose: () => void; diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLinkForm.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLinkForm.tsx index 96ad3eba4..b0977437b 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLinkForm.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityLinkForm.tsx @@ -105,7 +105,7 @@ export const IdentityLinkForm = ({ onClose }: Props) => { placeholder="Select role..." getOptionValue={(option) => option.slug} getOptionLabel={(option) => option.name} - menuPortalTarget={document.body} + // menuPortalTarget={document.body} /> )} diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal.tsx index 6b4d5c232..dacbba428 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal.tsx @@ -53,7 +53,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => { const orgId = currentOrg?.id || ""; const { data: roles } = useGetOrgRoles(orgId); - const isOrgIdentity = orgId === popUp?.identity?.data?.orgId; + const isOrgIdentity = popUp?.identity?.data ? orgId === popUp?.identity?.data?.orgId : true; const { mutateAsync: createMutateAsync } = useCreateIdentity(); const { mutateAsync: updateMutateAsync } = useUpdateIdentity(); diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx index 6627f87ce..2f0551966 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx @@ -24,11 +24,11 @@ import { usePopUp } from "@app/hooks/usePopUp"; import { IdentityAuthTemplateModal } from "./IdentityAuthTemplateModal"; import { IdentityAuthTemplatesTable } from "./IdentityAuthTemplatesTable"; +import { IdentityLinkForm } from "./IdentityLinkForm"; import { IdentityModal } from "./IdentityModal"; import { IdentityTable } from "./IdentityTable"; import { IdentityTokenAuthTokenModal } from "./IdentityTokenAuthTokenModal"; import { MachineAuthTemplateUsagesModal } from "./MachineAuthTemplateUsagesModal"; -import { IdentityLinkForm } from "./IdentityLinkForm"; export const IdentitySection = withPermission( () => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx index f5b0f5a0c..ceb3d6565 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgTabGroup/OrgTabGroup.tsx @@ -3,6 +3,7 @@ import { useSearch } from "@tanstack/react-router"; import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; import { ROUTE_PATHS } from "@app/const/routes"; +import { useOrganization } from "@app/context"; import { AuditLogStreamsTab } from "../AuditLogStreamTab"; import { ExternalMigrationsTab } from "../ExternalMigrationsTab"; @@ -14,7 +15,6 @@ import { OrgSecurityTab } from "../OrgSecurityTab"; import { OrgSsoTab } from "../OrgSsoTab"; import { OrgWorkflowIntegrationTab } from "../OrgWorkflowIntegrationTab"; import { ProjectTemplatesTab } from "../ProjectTemplatesTab"; -import { useOrganization } from "@app/context"; export const OrgTabGroup = () => { const search = useSearch({ diff --git a/frontend/src/pages/organization/layout.tsx b/frontend/src/pages/organization/layout.tsx index 233b490b3..0caf8286c 100644 --- a/frontend/src/pages/organization/layout.tsx +++ b/frontend/src/pages/organization/layout.tsx @@ -1,7 +1,7 @@ import { createFileRoute, retainSearchParams } from "@tanstack/react-router"; +import { z } from "zod"; import { OrganizationLayout } from "@app/layouts/OrganizationLayout"; -import { z } from "zod"; export const Route = createFileRoute("/_authenticate/_inject-org-details/_org-layout")({ component: OrganizationLayout,