Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add project path to action webhook urls #21211

Merged
merged 4 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 additions & 18 deletions plugin-server/src/worker/ingestion/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,24 @@ export const PERSON_DEFAULT_DISPLAY_NAME_PROPERTIES = [
'UserName',
]

export function getPersonLink(event: PostIngestionEvent, siteUrl: string): string {
return `${siteUrl}/person/${encodeURIComponent(event.distinctId)}`
function getProjectUrl(team: Team, siteUrl: string): string {
return `${siteUrl}/project/${team.id}`
}

function getPersonLink(team: Team, siteUrl: string, event: PostIngestionEvent): string {
return `${getProjectUrl(team, siteUrl)}/person/${encodeURIComponent(event.distinctId)}`
}

function getActionLink(team: Team, siteUrl: string, action: Action): string {
return `${getProjectUrl(team, siteUrl)}/action/${action.id}`
}

function getEventLink(team: Team, siteUrl: string, event: PostIngestionEvent): string {
return `${getProjectUrl(team, siteUrl)}/events/${encodeURIComponent(event.eventUuid)}/${encodeURIComponent(
event.timestamp
)}`
}

export function getPersonDetails(
event: PostIngestionEvent,
siteUrl: string,
Expand All @@ -119,25 +134,25 @@ export function getPersonDetails(

const display: string | undefined = (customIdentifier || event.distinctId)?.trim()

return toWebhookLink(display, getPersonLink(event, siteUrl), webhookType)
return toWebhookLink(display, getPersonLink(team, siteUrl, event), webhookType)
}

export function getActionLink(action: Action, siteUrl: string): string {
return `${siteUrl}/action/${action.id}`
}
export function getActionDetails(action: Action, siteUrl: string, webhookType: WebhookType): [string, string] {
return toWebhookLink(action.name, getActionLink(action, siteUrl), webhookType)
export function getActionDetails(
team: Team,
action: Action,
siteUrl: string,
webhookType: WebhookType
): [string, string] {
return toWebhookLink(action.name, getActionLink(team, siteUrl, action), webhookType)
}

export function getEventLink(event: PostIngestionEvent, siteUrl: string): string {
return `${siteUrl}/events/${encodeURIComponent(event.eventUuid)}/${encodeURIComponent(event.timestamp)}`
}
export function getEventDetails(
team: Team,
event: PostIngestionEvent,
siteUrl: string,
webhookType: WebhookType
): [string, string] {
return toWebhookLink(event.event, getEventLink(event, siteUrl), webhookType)
return toWebhookLink(event.event, getEventLink(team, siteUrl, event), webhookType)
}

const TOKENS_REGEX_BRACKETS_EXCLUDED = /(?<=(?<!\\)\[)(.*?)(?=(?<!\\)\])/g
Expand Down Expand Up @@ -178,7 +193,7 @@ export function getValueOfToken(
if (tokenParts.length === 1) {
;[text, markdown] = getPersonDetails(event, siteUrl, webhookType, team)
} else if (tokenParts[1] === 'link') {
markdown = text = webhookEscape(getPersonLink(event, siteUrl), webhookType)
markdown = text = webhookEscape(getPersonLink(team, siteUrl, event), webhookType)
} else if (tokenParts[1] === 'properties' && tokenParts.length > 2) {
const property = event.person_properties
? getPropertyValueByPath(event.person_properties, tokenParts.slice(2))
Expand All @@ -187,15 +202,15 @@ export function getValueOfToken(
}
} else if (tokenParts[0] === 'action') {
if (tokenParts[1] === 'name') {
;[text, markdown] = getActionDetails(action, siteUrl, webhookType)
;[text, markdown] = getActionDetails(team, action, siteUrl, webhookType)
} else if (tokenParts[1] === 'link') {
markdown = text = webhookEscape(getActionLink(action, siteUrl), webhookType)
markdown = text = webhookEscape(getActionLink(team, siteUrl, action), webhookType)
}
} else if (tokenParts[0] === 'event') {
if (tokenParts.length === 1) {
;[text, markdown] = getEventDetails(event, siteUrl, webhookType)
;[text, markdown] = getEventDetails(team, event, siteUrl, webhookType)
} else if (tokenParts[1] === 'link') {
markdown = text = webhookEscape(getEventLink(event, siteUrl), webhookType)
markdown = text = webhookEscape(getEventLink(team, siteUrl, event), webhookType)
} else if (tokenParts[1] === 'uuid') {
markdown = text = webhookEscape(event.eventUuid, webhookType)
} else if (tokenParts[1] === 'name') {
Expand Down Expand Up @@ -245,7 +260,7 @@ export function getFormattedMessage(
messageText = format(tokenizedMessage, ...values)
messageMarkdown = format(tokenizedMessage, ...markdownValues)
} catch (error) {
const [actionName, actionMarkdown] = getActionDetails(action, siteUrl, webhookType)
const [actionName, actionMarkdown] = getActionDetails(team, action, siteUrl, webhookType)
messageText = `⚠ Error: There are one or more formatting errors in the message template for action "${actionName}".`
messageMarkdown = `*⚠ Error: There are one or more formatting errors in the message template for action "${actionMarkdown}".*`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('Event Pipeline integration test', () => {
await ingestEvent(event)

const expectedPayload = {
text: '[Test Action](https://example.com/action/69) was triggered by [abc](https://example.com/person/abc)',
text: '[Test Action](https://example.com/project/2/action/69) was triggered by [abc](https://example.com/project/2/person/abc)',
}

expect(fetch).toHaveBeenCalledWith('https://webhook.example.com/', {
Expand Down
35 changes: 18 additions & 17 deletions plugin-server/tests/worker/ingestion/hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { Hook } from './../../../src/types'

describe('hooks', () => {
const team = { id: 123, person_display_name_properties: null } as Team
beforeEach(() => {
process.env.NODE_ENV = 'test'
})
Expand Down Expand Up @@ -46,7 +47,6 @@ describe('hooks', () => {
distinctId: 'WALL-E',
person_properties: { email: '[email protected]' },
} as unknown as PostIngestionEvent
const team = { person_display_name_properties: null } as Team

test('Slack', () => {
const [userDetails, userDetailsMarkdown] = getPersonDetails(
Expand All @@ -57,7 +57,7 @@ describe('hooks', () => {
)

expect(userDetails).toBe('[email protected]')
expect(userDetailsMarkdown).toBe('<http://localhost:8000/person/WALL-E|[email protected]>')
expect(userDetailsMarkdown).toBe('<http://localhost:8000/project/123/person/WALL-E|[email protected]>')
})

test('Teams', () => {
Expand All @@ -69,7 +69,7 @@ describe('hooks', () => {
)

expect(userDetails).toBe('[email protected]')
expect(userDetailsMarkdown).toBe('[[email protected]](http://localhost:8000/person/WALL-E)')
expect(userDetailsMarkdown).toBe('[[email protected]](http://localhost:8000/project/123/person/WALL-E)')
})
})

Expand All @@ -78,24 +78,26 @@ describe('hooks', () => {

test('Slack', () => {
const [actionDetails, actionDetailsMarkdown] = getActionDetails(
team,
action,
'http://localhost:8000',
WebhookType.Slack
)

expect(actionDetails).toBe('action1')
expect(actionDetailsMarkdown).toBe('<http://localhost:8000/action/1|action1>')
expect(actionDetailsMarkdown).toBe('<http://localhost:8000/project/123/action/1|action1>')
})

test('Teams', () => {
const [actionDetails, actionDetailsMarkdown] = getActionDetails(
team,
action,
'http://localhost:8000',
WebhookType.Other
)

expect(actionDetails).toBe('action1')
expect(actionDetailsMarkdown).toBe('[action1](http://localhost:8000/action/1)')
expect(actionDetailsMarkdown).toBe('[action1](http://localhost:8000/project/123/action/1)')
})
})

Expand Down Expand Up @@ -129,7 +131,6 @@ describe('hooks', () => {
person_properties: { enjoys_broccoli_on_pizza: false },
timestamp: '2021-10-31T00:44:00.000Z',
} as unknown as PostIngestionEvent
const team = { person_display_name_properties: null } as Team

test('event', () => {
const tokenUserName = ['event']
Expand All @@ -144,7 +145,9 @@ describe('hooks', () => {
)

expect(text).toBe('$pageview')
expect(markdown).toBe('[$pageview](http://localhost:8000/events/123/2021-10-31T00%3A44%3A00.000Z)')
expect(markdown).toBe(
'[$pageview](http://localhost:8000/project/123/events/123/2021-10-31T00%3A44%3A00.000Z)'
)
})

test('event UUID', () => {
Expand Down Expand Up @@ -224,7 +227,7 @@ describe('hooks', () => {
)

expect(text).toBe('WALL-E')
expect(markdown).toBe('[WALL-E](http://localhost:8000/person/WALL-E)')
expect(markdown).toBe('[WALL-E](http://localhost:8000/project/123/person/WALL-E)')
})

test('person with email', () => {
Expand All @@ -240,7 +243,7 @@ describe('hooks', () => {
)

expect(text).toBe('[email protected]')
expect(markdown).toBe('[[email protected]](http://localhost:8000/person/WALL-E)')
expect(markdown).toBe('[[email protected]](http://localhost:8000/project/123/person/WALL-E)')
})

test('person with custom name property, team-level setting ', () => {
Expand All @@ -264,7 +267,7 @@ describe('hooks', () => {
)

expect(text).toBe('Brzęczyszczykiewicz')
expect(markdown).toBe('[Brzęczyszczykiewicz](http://localhost:8000/person/fd)')
expect(markdown).toBe('[Brzęczyszczykiewicz](http://localhost:8000/project/123/person/fd)')
})

test('person prop', () => {
Expand Down Expand Up @@ -340,7 +343,7 @@ describe('hooks', () => {
)

expect(text).toBe('WALL-E')
expect(markdown).toBe('[WALL-E](http://localhost:8000/person/WALL-E)')
expect(markdown).toBe('[WALL-E](http://localhost:8000/project/123/person/WALL-E)')
})

test('user prop (actually event prop)', () => {
Expand Down Expand Up @@ -387,7 +390,7 @@ describe('hooks', () => {

expect(text).toBe('text&gt;&lt;new link')
expect(markdown).toBe(
'<http://localhost:8000/events/**%3E)/2021-10-31T00%3A44%3A00.000Z|text&gt;&lt;new link>'
'<http://localhost:8000/project/123/events/**%3E)/2021-10-31T00%3A44%3A00.000Z|text&gt;&lt;new link>'
)
})

Expand All @@ -403,7 +406,7 @@ describe('hooks', () => {

expect(text).toBe('text\\]\\(yes\\!\\), \\[new link')
expect(markdown).toBe(
'[text\\]\\(yes\\!\\), \\[new link](http://localhost:8000/events/\\*\\*\\)/2021-10-31T00%3A44%3A00.000Z)'
'[text\\]\\(yes\\!\\), \\[new link](http://localhost:8000/project/123/events/\\*\\*\\)/2021-10-31T00%3A44%3A00.000Z)'
)
})
})
Expand All @@ -413,7 +416,6 @@ describe('hooks', () => {
distinctId: '2',
properties: { $browser: 'Chrome', page_title: 'Pricing', 'with space': 'yes sir' },
} as unknown as PostIngestionEvent
const team = { person_display_name_properties: null } as Team

test('custom format', () => {
const action = {
Expand All @@ -431,7 +433,7 @@ describe('hooks', () => {
)
expect(text).toBe('2 from Chrome on Pricing page with undefined, yes sir')
expect(markdown).toBe(
'<https://localhost:8000/person/2|2> from Chrome on Pricing page with undefined, yes sir'
'<https://localhost:8000/project/123/person/2|2> from Chrome on Pricing page with undefined, yes sir'
)
})

Expand All @@ -450,7 +452,7 @@ describe('hooks', () => {
WebhookType.Slack
)
expect(text).toBe('2 did thing from browser undefined')
expect(markdown).toBe('<https://localhost:8000/person/2|2> did thing from browser undefined')
expect(markdown).toBe('<https://localhost:8000/project/123/person/2|2> did thing from browser undefined')
})
})

Expand All @@ -462,7 +464,6 @@ describe('hooks', () => {
name: 'action1',
// slack_message_format: '[user.name] did thing from browser [user.brauzer]',
} as Action
const team = { person_display_name_properties: null } as Team

beforeEach(() => {
hook = {
Expand Down
Loading