Still fetch flags when the user is not logged in.

This commit is contained in:
Sam Rose 2024-10-09 12:29:17 +01:00
parent abd7b3b84e
commit 20f55e3795
No known key found for this signature in database
2 changed files with 75 additions and 18 deletions

View File

@ -1,7 +1,8 @@
import env from "../environment"
import * as crypto from "crypto"
import * as context from "../context"
import { PostHog, PostHogOptions } from "posthog-node"
import { FeatureFlag, IdentityType, UserCtx } from "@budibase/types"
import { FeatureFlag, UserCtx } from "@budibase/types"
import tracer from "dd-trace"
import { Duration } from "../utils"
@ -224,24 +225,29 @@ export class FlagSet<V extends Flag<any>, T extends { [key: string]: V }> {
}
const identity = context.getIdentity()
tags[`identity.type`] = identity?.type
tags[`identity.tenantId`] = identity?.tenantId
tags[`identity._id`] = identity?._id
if (posthog && identity?.type === IdentityType.USER) {
let userId = identity?._id
if (!userId && ctx?.ip) {
userId = crypto.createHash("sha512").update(ctx.ip).digest("hex")
}
let tenantId = identity?.tenantId
if (!tenantId) {
tenantId = currentTenantId
}
tags[`identity.type`] = identity?.type
tags[`identity._id`] = identity?._id
tags[`tenantId`] = tenantId
tags[`userId`] = userId
if (posthog && userId) {
tags[`readFromPostHog`] = true
const personProperties: Record<string, string> = {}
if (identity.tenantId) {
personProperties.tenantId = identity.tenantId
}
const posthogFlags = await posthog.getAllFlagsAndPayloads(
identity._id,
{
const personProperties: Record<string, string> = { tenantId }
const posthogFlags = await posthog.getAllFlagsAndPayloads(userId, {
personProperties,
}
)
})
for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
if (!this.isFlagName(name)) {

View File

@ -4,6 +4,7 @@ import * as context from "../../context"
import environment, { withEnv } from "../../environment"
import nodeFetch from "node-fetch"
import nock from "nock"
import * as crypto from "crypto"
const schema = {
TEST_BOOLEAN: Flag.boolean(false),
@ -27,10 +28,14 @@ interface PostHogFlags {
featureFlagPayloads?: Record<string, string>
}
function mockPosthogFlags(flags: PostHogFlags) {
function mockPosthogFlags(
flags: PostHogFlags,
opts?: { token?: string; distinct_id?: string }
) {
const { token = "test", distinct_id = "us_1234" } = opts || {}
nock("https://us.i.posthog.com")
.post("/decide/?v=3", body => {
return body.token === "test" && body.distinct_id === "us_1234"
return body.token === token && body.distinct_id === distinct_id
})
.reply(200, flags)
.persist()
@ -214,6 +219,14 @@ describe("feature flags", () => {
lastName: "User",
}
// We need to pass in node-fetch here otherwise nock won't get used
// because posthog-node uses axios under the hood.
init({
fetch: (url, opts) => {
return nodeFetch(url, opts)
},
})
nock("https://us.i.posthog.com")
.post("/decide/?v=3", body => {
return body.token === "test" && body.distinct_id === "us_1234"
@ -230,4 +243,42 @@ describe("feature flags", () => {
}
)
})
it("should still get flags when user is logged out", async () => {
const env: Partial<typeof environment> = {
SELF_HOSTED: false,
POSTHOG_FEATURE_FLAGS_ENABLED: "true",
POSTHOG_API_HOST: "https://us.i.posthog.com",
POSTHOG_TOKEN: "test",
}
const ctx = { ip: "127.0.0.1" } as UserCtx
const hashedIp = crypto.createHash("sha512").update(ctx.ip).digest("hex")
await withEnv(env, async () => {
mockPosthogFlags(
{
featureFlags: { TEST_BOOLEAN: true },
},
{
distinct_id: hashedIp,
}
)
// We need to pass in node-fetch here otherwise nock won't get used
// because posthog-node uses axios under the hood.
init({
fetch: (url, opts) => {
return nodeFetch(url, opts)
},
})
await context.doInTenant("default", async () => {
const result = await flags.fetch(ctx)
expect(result.TEST_BOOLEAN).toBe(true)
})
shutdown()
})
})
})