mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-07 11:16:37 +00:00
Centralize user functions
This commit is contained in:
142
server/lib/userOrg.ts
Normal file
142
server/lib/userOrg.ts
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import {
|
||||||
|
db,
|
||||||
|
Org,
|
||||||
|
orgs,
|
||||||
|
resources,
|
||||||
|
siteResources,
|
||||||
|
sites,
|
||||||
|
Transaction,
|
||||||
|
UserOrg,
|
||||||
|
userOrgs,
|
||||||
|
userResources,
|
||||||
|
userSiteResources,
|
||||||
|
userSites
|
||||||
|
} from "@server/db";
|
||||||
|
import { eq, and, inArray, ne, exists } from "drizzle-orm";
|
||||||
|
import { usageService } from "@server/lib/billing/usageService";
|
||||||
|
import { FeatureId } from "@server/lib/billing";
|
||||||
|
|
||||||
|
export async function assignUserToOrg(
|
||||||
|
org: Org,
|
||||||
|
values: typeof userOrgs.$inferInsert,
|
||||||
|
trx: Transaction | typeof db = db
|
||||||
|
) {
|
||||||
|
const [userOrg] = await trx.insert(userOrgs).values(values).returning();
|
||||||
|
|
||||||
|
// calculate if the user is in any other of the orgs before we count it as an add to the billing org
|
||||||
|
if (org.billingOrgId) {
|
||||||
|
const otherBillingOrgs = await trx
|
||||||
|
.select()
|
||||||
|
.from(orgs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(orgs.billingOrgId, org.billingOrgId),
|
||||||
|
ne(orgs.orgId, org.orgId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const billingOrgIds = otherBillingOrgs.map((o) => o.orgId);
|
||||||
|
|
||||||
|
const orgsInBillingDomainThatTheUserIsStillIn = await trx
|
||||||
|
.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(userOrgs.userId, userOrg.userId),
|
||||||
|
inArray(userOrgs.orgId, billingOrgIds)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (orgsInBillingDomainThatTheUserIsStillIn.length === 0) {
|
||||||
|
await usageService.add(org.orgId, FeatureId.USERS, 1, trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeUserFromOrg(
|
||||||
|
org: Org,
|
||||||
|
userId: string,
|
||||||
|
trx: Transaction | typeof db = db
|
||||||
|
) {
|
||||||
|
await trx
|
||||||
|
.delete(userOrgs)
|
||||||
|
.where(and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, org.orgId)));
|
||||||
|
|
||||||
|
await trx.delete(userResources).where(
|
||||||
|
and(
|
||||||
|
eq(userResources.userId, userId),
|
||||||
|
exists(
|
||||||
|
trx
|
||||||
|
.select()
|
||||||
|
.from(resources)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(resources.resourceId, userResources.resourceId),
|
||||||
|
eq(resources.orgId, org.orgId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await trx.delete(userSiteResources).where(
|
||||||
|
and(
|
||||||
|
eq(userSiteResources.userId, userId),
|
||||||
|
exists(
|
||||||
|
trx
|
||||||
|
.select()
|
||||||
|
.from(siteResources)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(
|
||||||
|
siteResources.siteResourceId,
|
||||||
|
userSiteResources.siteResourceId
|
||||||
|
),
|
||||||
|
eq(siteResources.orgId, org.orgId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await trx.delete(userSites).where(
|
||||||
|
and(
|
||||||
|
eq(userSites.userId, userId),
|
||||||
|
exists(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(sites)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(sites.siteId, userSites.siteId),
|
||||||
|
eq(sites.orgId, org.orgId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// calculate if the user is in any other of the orgs before we count it as an remove to the billing org
|
||||||
|
if (org.billingOrgId) {
|
||||||
|
const billingOrgs = await trx
|
||||||
|
.select()
|
||||||
|
.from(orgs)
|
||||||
|
.where(eq(orgs.billingOrgId, org.billingOrgId));
|
||||||
|
|
||||||
|
const billingOrgIds = billingOrgs.map((o) => o.orgId);
|
||||||
|
|
||||||
|
const orgsInBillingDomainThatTheUserIsStillIn = await trx
|
||||||
|
.select()
|
||||||
|
.from(userOrgs)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(userOrgs.userId, userId),
|
||||||
|
inArray(userOrgs.orgId, billingOrgIds)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (orgsInBillingDomainThatTheUserIsStillIn.length === 0) {
|
||||||
|
await usageService.add(org.orgId, FeatureId.USERS, -1, trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import { build } from "@server/build";
|
|||||||
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
||||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
import { assignUserToOrg } from "@server/lib/userOrg";
|
||||||
|
|
||||||
const paramsSchema = z.strictObject({
|
const paramsSchema = z.strictObject({
|
||||||
orgId: z.string().nonempty()
|
orgId: z.string().nonempty()
|
||||||
@@ -220,15 +221,12 @@ export async function createOrgUser(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await trx
|
await assignUserToOrg(org, {
|
||||||
.insert(userOrgs)
|
orgId,
|
||||||
.values({
|
userId: existingUser.userId,
|
||||||
orgId,
|
roleId: role.roleId,
|
||||||
userId: existingUser.userId,
|
autoProvisioned: false
|
||||||
roleId: role.roleId,
|
}, trx);
|
||||||
autoProvisioned: false
|
|
||||||
})
|
|
||||||
.returning();
|
|
||||||
} else {
|
} else {
|
||||||
userId = generateId(15);
|
userId = generateId(15);
|
||||||
|
|
||||||
@@ -246,47 +244,15 @@ export async function createOrgUser(
|
|||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
await trx
|
await assignUserToOrg(org, {
|
||||||
.insert(userOrgs)
|
|
||||||
.values({
|
|
||||||
orgId,
|
orgId,
|
||||||
userId: newUser.userId,
|
userId: newUser.userId,
|
||||||
roleId: role.roleId,
|
roleId: role.roleId,
|
||||||
autoProvisioned: false
|
autoProvisioned: false
|
||||||
})
|
}, trx);
|
||||||
.returning();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await calculateUserClientsForOrgs(userId, trx);
|
await calculateUserClientsForOrgs(userId, trx);
|
||||||
|
|
||||||
// calculate if the user is in any other of the orgs before we count it as an add to the billing org
|
|
||||||
if (org.billingOrgId) {
|
|
||||||
const otherBillingOrgs = await trx
|
|
||||||
.select()
|
|
||||||
.from(orgs)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(orgs.billingOrgId, org.billingOrgId),
|
|
||||||
ne(orgs.orgId, orgId)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const billingOrgIds = otherBillingOrgs.map((o) => o.orgId);
|
|
||||||
|
|
||||||
const orgsInBillingDomainThatTheUserIsStillIn = await trx
|
|
||||||
.select()
|
|
||||||
.from(userOrgs)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(userOrgs.userId, userId),
|
|
||||||
inArray(userOrgs.orgId, billingOrgIds)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (orgsInBillingDomainThatTheUserIsStillIn.length === 0) {
|
|
||||||
await usageService.add(orgId, FeatureId.USERS, 1, trx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return next(
|
return next(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { FeatureId } from "@server/lib/billing";
|
|||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { UserType } from "@server/types/UserTypes";
|
import { UserType } from "@server/types/UserTypes";
|
||||||
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
import { calculateUserClientsForOrgs } from "@server/lib/calculateUserClientsForOrgs";
|
||||||
|
import { removeUserFromOrg } from "@server/lib/userOrg";
|
||||||
|
|
||||||
const removeUserSchema = z.strictObject({
|
const removeUserSchema = z.strictObject({
|
||||||
userId: z.string(),
|
userId: z.string(),
|
||||||
@@ -89,68 +90,7 @@ export async function removeUserOrg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await db.transaction(async (trx) => {
|
await db.transaction(async (trx) => {
|
||||||
await trx
|
await removeUserFromOrg(org, userId, trx);
|
||||||
.delete(userOrgs)
|
|
||||||
.where(
|
|
||||||
and(eq(userOrgs.userId, userId), eq(userOrgs.orgId, orgId))
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.delete(userResources).where(
|
|
||||||
and(
|
|
||||||
eq(userResources.userId, userId),
|
|
||||||
exists(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(resources)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(
|
|
||||||
resources.resourceId,
|
|
||||||
userResources.resourceId
|
|
||||||
),
|
|
||||||
eq(resources.orgId, orgId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.delete(userSiteResources).where(
|
|
||||||
and(
|
|
||||||
eq(userSiteResources.userId, userId),
|
|
||||||
exists(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(siteResources)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(
|
|
||||||
siteResources.siteResourceId,
|
|
||||||
userSiteResources.siteResourceId
|
|
||||||
),
|
|
||||||
eq(siteResources.orgId, orgId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.delete(userSites).where(
|
|
||||||
and(
|
|
||||||
eq(userSites.userId, userId),
|
|
||||||
exists(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(sites)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(sites.siteId, userSites.siteId),
|
|
||||||
eq(sites.orgId, orgId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// if (build === "saas") {
|
// if (build === "saas") {
|
||||||
// const [rootUser] = await trx
|
// const [rootUser] = await trx
|
||||||
@@ -170,30 +110,6 @@ export async function removeUserOrg(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
await calculateUserClientsForOrgs(userId, trx);
|
await calculateUserClientsForOrgs(userId, trx);
|
||||||
|
|
||||||
// calculate if the user is in any other of the orgs before we count it as an remove to the billing org
|
|
||||||
if (org.billingOrgId) {
|
|
||||||
const billingOrgs = await trx
|
|
||||||
.select()
|
|
||||||
.from(orgs)
|
|
||||||
.where(eq(orgs.billingOrgId, org.billingOrgId));
|
|
||||||
|
|
||||||
const billingOrgIds = billingOrgs.map((o) => o.orgId);
|
|
||||||
|
|
||||||
const orgsInBillingDomainThatTheUserIsStillIn = await trx
|
|
||||||
.select()
|
|
||||||
.from(userOrgs)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(userOrgs.userId, userId),
|
|
||||||
inArray(userOrgs.orgId, billingOrgIds)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (orgsInBillingDomainThatTheUserIsStillIn.length === 0) {
|
|
||||||
await usageService.add(orgId, FeatureId.USERS, -1, trx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return response(res, {
|
return response(res, {
|
||||||
|
|||||||
Reference in New Issue
Block a user