mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
Merge branch 'dev' into audit-logs
This commit is contained in:
@@ -26,8 +26,7 @@ export const orgs = pgTable("orgs", {
|
||||
orgId: varchar("orgId").primaryKey(),
|
||||
name: varchar("name").notNull(),
|
||||
subnet: varchar("subnet"),
|
||||
createdAt: text("createdAt"),
|
||||
settings: text("settings") // JSON blob of org-specific settings
|
||||
createdAt: text("createdAt")
|
||||
});
|
||||
|
||||
export const orgDomains = pgTable("orgDomains", {
|
||||
|
||||
@@ -19,8 +19,7 @@ export const orgs = sqliteTable("orgs", {
|
||||
orgId: text("orgId").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
subnet: text("subnet"),
|
||||
createdAt: text("createdAt"),
|
||||
settings: text("settings") // JSON blob of org-specific settings
|
||||
createdAt: text("createdAt")
|
||||
});
|
||||
|
||||
export const userDomains = sqliteTable("userDomains", {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export enum AudienceIds {
|
||||
General = "",
|
||||
Subscribed = "",
|
||||
Churned = ""
|
||||
SignUps = "",
|
||||
Subscribed = "",
|
||||
Churned = "",
|
||||
Newsletter = ""
|
||||
}
|
||||
|
||||
let resend;
|
||||
@@ -12,4 +13,4 @@ export async function moveEmailToAudience(
|
||||
audienceId: AudienceIds
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,10 +200,7 @@ class TelemetryClient {
|
||||
event: "supporter_status",
|
||||
properties: {
|
||||
valid: stats.supporterStatus.valid,
|
||||
tier: stats.supporterStatus.tier,
|
||||
github_username: stats.supporterStatus.githubUsername
|
||||
? this.anon(stats.supporterStatus.githubUsername)
|
||||
: "None"
|
||||
tier: stats.supporterStatus.tier
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -217,21 +214,6 @@ class TelemetryClient {
|
||||
install_timestamp: hostMeta.createdAt
|
||||
}
|
||||
});
|
||||
|
||||
for (const email of stats.adminUsers) {
|
||||
// There should only be on admin user, but just in case
|
||||
if (email) {
|
||||
this.client.capture({
|
||||
distinctId: this.anon(email),
|
||||
event: "admin_user",
|
||||
properties: {
|
||||
host_id: hostMeta.hostMetaId,
|
||||
app_version: stats.appVersion,
|
||||
hashed_email: this.anon(email)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async collectAndSendAnalytics() {
|
||||
@@ -262,19 +244,38 @@ class TelemetryClient {
|
||||
num_clients: stats.numClients,
|
||||
num_identity_providers: stats.numIdentityProviders,
|
||||
num_sites_online: stats.numSitesOnline,
|
||||
resources: stats.resources.map((r) => ({
|
||||
name: this.anon(r.name),
|
||||
sso_enabled: r.sso,
|
||||
protocol: r.protocol,
|
||||
http_enabled: r.http
|
||||
})),
|
||||
sites: stats.sites.map((s) => ({
|
||||
site_name: this.anon(s.siteName),
|
||||
megabytes_in: s.megabytesIn,
|
||||
megabytes_out: s.megabytesOut,
|
||||
type: s.type,
|
||||
online: s.online
|
||||
})),
|
||||
num_resources_sso_enabled: stats.resources.filter(
|
||||
(r) => r.sso
|
||||
).length,
|
||||
num_resources_non_http: stats.resources.filter(
|
||||
(r) => !r.http
|
||||
).length,
|
||||
num_newt_sites: stats.sites.filter((s) => s.type === "newt")
|
||||
.length,
|
||||
num_local_sites: stats.sites.filter(
|
||||
(s) => s.type === "local"
|
||||
).length,
|
||||
num_wg_sites: stats.sites.filter(
|
||||
(s) => s.type === "wireguard"
|
||||
).length,
|
||||
avg_megabytes_in:
|
||||
stats.sites.length > 0
|
||||
? Math.round(
|
||||
stats.sites.reduce(
|
||||
(sum, s) => sum + (s.megabytesIn ?? 0),
|
||||
0
|
||||
) / stats.sites.length
|
||||
)
|
||||
: 0,
|
||||
avg_megabytes_out:
|
||||
stats.sites.length > 0
|
||||
? Math.round(
|
||||
stats.sites.reduce(
|
||||
(sum, s) => sum + (s.megabytesOut ?? 0),
|
||||
0
|
||||
) / stats.sites.length
|
||||
)
|
||||
: 0,
|
||||
num_api_keys: stats.numApiKeys,
|
||||
num_custom_roles: stats.numCustomRoles
|
||||
}
|
||||
|
||||
@@ -16,9 +16,10 @@ import privateConfig from "#private/lib/config";
|
||||
import logger from "@server/logger";
|
||||
|
||||
export enum AudienceIds {
|
||||
General = "5cfbf99b-c592-40a9-9b8a-577a4681c158",
|
||||
Subscribed = "870b43fd-387f-44de-8fc1-707335f30b20",
|
||||
Churned = "f3ae92bd-2fdb-4d77-8746-2118afd62549"
|
||||
SignUps = "5cfbf99b-c592-40a9-9b8a-577a4681c158",
|
||||
Subscribed = "870b43fd-387f-44de-8fc1-707335f30b20",
|
||||
Churned = "f3ae92bd-2fdb-4d77-8746-2118afd62549",
|
||||
Newsletter = "5500c431-191c-42f0-a5d4-8b6d445b4ea0"
|
||||
}
|
||||
|
||||
const resend = new Resend(
|
||||
|
||||
@@ -224,7 +224,7 @@ export async function signup(
|
||||
res.appendHeader("Set-Cookie", cookie);
|
||||
|
||||
if (build == "saas") {
|
||||
moveEmailToAudience(email, AudienceIds.General);
|
||||
moveEmailToAudience(email, AudienceIds.SignUps);
|
||||
}
|
||||
|
||||
if (config.getRawConfig().flags?.require_email_verification) {
|
||||
|
||||
@@ -443,14 +443,14 @@ authenticated.post(
|
||||
resource.setResourceWhitelist,
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
authenticated.post(
|
||||
`/resource/:resourceId/whitelist/add`,
|
||||
verifyApiKeyResourceAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
|
||||
resource.addEmailToResourceWhitelist
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
authenticated.post(
|
||||
`/resource/:resourceId/whitelist/remove`,
|
||||
verifyApiKeyResourceAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.setResourceWhitelist),
|
||||
|
||||
@@ -17,7 +17,7 @@ const getOrgSchema = z
|
||||
.strict();
|
||||
|
||||
export type GetOrgResponse = {
|
||||
org: Org & { settings: { } | null };
|
||||
org: Org;
|
||||
};
|
||||
|
||||
registry.registerPath({
|
||||
@@ -64,23 +64,9 @@ export async function getOrg(
|
||||
);
|
||||
}
|
||||
|
||||
// Parse settings from JSON string back to object
|
||||
let parsedSettings = null;
|
||||
if (org[0].settings) {
|
||||
try {
|
||||
parsedSettings = JSON.parse(org[0].settings);
|
||||
} catch (error) {
|
||||
// If parsing fails, keep as string for backward compatibility
|
||||
parsedSettings = org[0].settings;
|
||||
}
|
||||
}
|
||||
|
||||
return response<GetOrgResponse>(res, {
|
||||
data: {
|
||||
org: {
|
||||
...org[0],
|
||||
settings: parsedSettings
|
||||
}
|
||||
org: org[0]
|
||||
},
|
||||
success: true,
|
||||
error: false,
|
||||
|
||||
@@ -12,15 +12,13 @@ import { OpenAPITags, registry } from "@server/openApi";
|
||||
|
||||
const updateOrgParamsSchema = z
|
||||
.object({
|
||||
orgId: z.string(),
|
||||
orgId: z.string()
|
||||
})
|
||||
.strict();
|
||||
|
||||
const updateOrgBodySchema = z
|
||||
.object({
|
||||
name: z.string().min(1).max(255).optional(),
|
||||
settings: z.object({
|
||||
}).optional(),
|
||||
name: z.string().min(1).max(255).optional()
|
||||
})
|
||||
.strict()
|
||||
.refine((data) => Object.keys(data).length > 0, {
|
||||
@@ -73,13 +71,10 @@ export async function updateOrg(
|
||||
|
||||
const { orgId } = parsedParams.data;
|
||||
|
||||
const settings = parsedBody.data.settings ? JSON.stringify(parsedBody.data.settings) : undefined;
|
||||
|
||||
const updatedOrg = await db
|
||||
.update(orgs)
|
||||
.set({
|
||||
name: parsedBody.data.name,
|
||||
settings: settings
|
||||
name: parsedBody.data.name
|
||||
})
|
||||
.where(eq(orgs.orgId, orgId))
|
||||
.returning();
|
||||
|
||||
Reference in New Issue
Block a user