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

wip: support test_ api key #4206

Merged
merged 36 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c9c910d
wip: support test_ api key
buwilliams May 3, 2021
180d2e0
Merge branch 'master' into multiple-environments
buwilliams May 4, 2021
4c83268
Renamed test_environment property to
buwilliams May 4, 2021
55f7eff
Added Prod/Test switch to determine which environment to show data for
buwilliams May 4, 2021
3bc0a0e
moved environment toggle behind feature flag
buwilliams May 4, 2021
744f536
corrected key name to standard $ names
buwilliams May 4, 2021
faaaf78
Moved hidden filters to PropertyKeyInfo for improved clarity
buwilliams May 4, 2021
87018fc
fix typing
paolodamico May 5, 2021
b4bee83
proposed UI
paolodamico May 5, 2021
ba0a6b1
Renamed to ; Changed to a string and added environment const types:…
buwilliams May 5, 2021
1e3a56a
Added filter for test environments so that when it's enabled all test…
buwilliams May 5, 2021
3750ca3
Remove component if feature flag for test-environment is enabled
buwilliams May 5, 2021
8ed947e
Merge branch 'master' into multiple-environments
buwilliams May 5, 2021
642b730
adjust style of tooltip
paolodamico May 6, 2021
672c50c
adjust UI based on @corywatilo's input
paolodamico May 6, 2021
ac00cca
implemented toggle functionality
buwilliams May 6, 2021
0d70406
Made Environments an enum for clarity
buwilliams May 7, 2021
1de0325
Moved environment constants to constants.py for consistency
buwilliams May 7, 2021
0268bed
Moved Environments into constants for consistency
buwilliams May 7, 2021
6f1f168
Using parameter destructuring for better syntax
buwilliams May 7, 2021
b7e91e8
Make sure type is set as a string
buwilliams May 7, 2021
cf146f7
Merge branch 'master' into multiple-environments
buwilliams May 7, 2021
db993cc
Removed test filters
buwilliams May 8, 2021
ed0caa7
Created _clean_token to ensure test_ is removed from all the places
buwilliams May 10, 2021
6da97ab
Bug fixes for adding filter property so that it work properly
buwilliams May 10, 2021
37a0274
Merge branch 'master' into multiple-environments
buwilliams May 10, 2021
f5ef025
Show test account filter
buwilliams May 10, 2021
a552d34
ensure token isn't None so that mypy checks pass
buwilliams May 10, 2021
bd129c6
Corrected css selector syntax
buwilliams May 11, 2021
32b0970
Merge branch 'master' into multiple-environments
buwilliams May 11, 2021
616cbd3
removed quote since it's not needed
buwilliams May 11, 2021
faf89fe
Corrected cypress test by excluding featureFlag usage on shared dashb…
buwilliams May 11, 2021
9c47d35
Fixed test
May 13, 2021
d67d4ac
merged master
May 13, 2021
f5cb467
corrected syntax style issues
buwilliams May 13, 2021
84dead5
merged master and fixed conflicts
buwilliams May 21, 2021
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
23 changes: 20 additions & 3 deletions frontend/src/layout/navigation/TopNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { userLogic } from 'scenes/userLogic'
import { Badge } from 'lib/components/Badge'
import { ChangelogModal } from '~/layout/ChangelogModal'
import { router } from 'kea-router'
import { Button, Card, Dropdown, Tooltip } from 'antd'
import { Button, Card, Dropdown, Radio, Tooltip } from 'antd'
import {
ProjectOutlined,
DownOutlined,
Expand All @@ -33,6 +33,7 @@ import { CreateInviteModalWithButton } from 'scenes/organization/Settings/Create
import MD5 from 'crypto-js/md5'
import { preflightLogic } from 'scenes/PreflightCheck/logic'
import { billingLogic } from 'scenes/billing/billingLogic'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'

export interface ProfilePictureProps {
name?: string
Expand Down Expand Up @@ -78,16 +79,17 @@ export function TopNavigation(): JSX.Element {
const { menuCollapsed, systemStatus, updateAvailable, changelogModalOpen, inviteMembersModalOpen } = useValues(
navigationLogic
)
const { user } = useValues(userLogic)
const { user, productionEnvironment } = useValues(userLogic)
const { preflight } = useValues(preflightLogic)
const { billing } = useValues(billingLogic)
const { logout, updateCurrentTeam, updateCurrentOrganization } = useActions(userLogic)
const { logout, updateCurrentTeam, updateCurrentOrganization, setProductionEnvironment } = useActions(userLogic)
const { showUpgradeModal } = useActions(sceneLogic)
const { sceneConfig } = useValues(sceneLogic)
const { push } = router.actions
const { showPalette } = useActions(commandPaletteLogic)
const [projectModalShown, setProjectModalShown] = useState(false) // TODO: Move to Kea (using useState for backwards-compatibility with TopSelectors.tsx)
const [organizationModalShown, setOrganizationModalShown] = useState(false) // TODO: Same as above
const { featureFlags } = useValues(featureFlagLogic)

const whoAmIDropdown = (
<div className="navigation-top-dropdown whoami-dropdown">
Expand Down Expand Up @@ -306,6 +308,21 @@ export function TopNavigation(): JSX.Element {
{user?.team?.name} <DownOutlined className="ml-05" />
</div>
</Dropdown>
{featureFlags['test-environment-3149'] && (
<div style={{ marginLeft: '1rem' }}>
<Radio.Group
value={productionEnvironment}
onChange={(e) => setProductionEnvironment(e.target.value)}
>
<Tooltip title="All queries use only production environment data.">
<Radio.Button value={true}>PROD</Radio.Button>
</Tooltip>
<Tooltip title="All queries use only test environment data. Add test_[apiKey] to your apiKey to mark an environment as test.">
<Radio.Button value={false}>TEST</Radio.Button>
</Tooltip>
</Radio.Group>
</div>
)}
</div>
{user && (
<div>
Expand Down
34 changes: 19 additions & 15 deletions frontend/src/lib/components/PropertyFilters/PropertyFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { CloseButton } from 'lib/components/CloseButton'
import PropertyFilterButton from './PropertyFilterButton'
import '../../../scenes/actions/Actions.scss'

import { hiddenFilters } from 'lib/components/PropertyKeyInfo'

const FilterRow = React.memo(function FilterRow({
item,
index,
Expand Down Expand Up @@ -98,21 +100,23 @@ export function PropertyFilters({
return (
<div className="mb" style={style}>
{filters?.length &&
filters.map((item, index) => {
return (
<FilterRow
key={index}
logic={logic}
item={item}
index={index}
totalCount={filters.length - 1} // empty state
filters={filters}
pageKey={pageKey}
showConditionBadge={showConditionBadge}
popoverPlacement={popoverPlacement}
/>
)
})}
filters
.filter((item) => !hiddenFilters.includes(item.key))
.map((item, index) => {
return (
<FilterRow
key={index}
logic={logic}
item={item}
index={index}
totalCount={filters.length - 1} // empty state
filters={filters}
pageKey={pageKey}
showConditionBadge={showConditionBadge}
popoverPlacement={popoverPlacement}
/>
)
})}
</div>
)
}
2 changes: 2 additions & 0 deletions frontend/src/lib/components/PropertyKeyInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ export const keyMapping: KeyMappingInterface = {
},
}

export const hiddenFilters: Array<string> = ['$test_environment']

interface PropertyKeyInfoInterface {
value: string
type?: 'event' | 'element'
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/scenes/userLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const userLogic = kea<userLogicType<UserType, UpdateUserPayload>>({
loadUser: (resetOnFailure?: boolean) => ({ resetOnFailure }),
updateCurrentTeam: (teamId: number, destination?: string) => ({ teamId, destination }),
updateCurrentOrganization: (organizationId: string, destination?: string) => ({ organizationId, destination }),
setProductionEnvironment: (isProduction: boolean) => ({ isProduction }),
logout: true,
}),
reducers: {
Expand All @@ -40,6 +41,12 @@ export const userLogic = kea<userLogicType<UserType, UpdateUserPayload>>({
setUserLoading: (_, { loading }) => loading,
},
],
productionEnvironment: [
true,
{
setProductionEnvironment: (_, payload) => payload.isProduction,
},
],
},
selectors: ({ selectors }) => ({
demoOnlyProject: [
Expand Down
8 changes: 8 additions & 0 deletions posthog/api/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ def get_event(request):
),
)

# Support test_[apiKey] for users with multiple environments
is_test_environment = token.startswith("test_")
token = token[5:] if is_test_environment else token

team = Team.objects.get_team_from_token(token)

if team is None:
Expand Down Expand Up @@ -236,6 +240,10 @@ def get_event(request):
if not event.get("properties"):
event["properties"] = {}

# Support test_[apiKey] for users with multiple environments
if event["properties"].get("$test_environment") is None:
event["properties"]["$test_environment"] = True if is_test_environment else False

_ensure_web_feature_flags_in_properties(event, team, distinct_id)

event_uuid = UUIDT()
Expand Down
47 changes: 42 additions & 5 deletions posthog/api/test/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def test_capture_event(self, patch_process_event_with_plugins):
{"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",},
{"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",},
],
"$test_environment": False,
},
}
now = timezone.now()
Expand All @@ -85,6 +86,40 @@ def test_capture_event(self, patch_process_event_with_plugins):
},
)

@patch("posthog.models.team.TEAM_CACHE", {})
@patch("posthog.api.capture.celery_app.send_task")
def test_test_api_key(self, patch_process_event_with_plugins):
api_token = "test_" + self.team.api_token
data: Dict[str, Any] = {
"event": "$autocapture",
"properties": {
"distinct_id": 2,
"token": api_token,
"$elements": [
{"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",},
{"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",},
],
},
}
now = timezone.now()
with freeze_time(now):
with self.assertNumQueries(2):
response = self.client.get("/e/?data=%s" % quote(self._to_json(data)), HTTP_ORIGIN="https://localhost",)
self.assertEqual(response.get("access-control-allow-origin"), "https://localhost")
arguments = self._to_arguments(patch_process_event_with_plugins)
arguments.pop("now") # can't compare fakedate
arguments.pop("sent_at") # can't compare fakedate
self.assertDictEqual(
arguments,
{
"distinct_id": "2",
"ip": "127.0.0.1",
"site_url": "http://testserver",
"data": {**data, "properties": {**data["properties"], "$test_environment": True}},
"team_id": self.team.pk,
},
)

@patch("posthog.models.team.TEAM_CACHE", {})
@patch("posthog.api.capture.celery_app.send_task")
def test_personal_api_key(self, patch_process_event_with_plugins):
Expand All @@ -100,6 +135,7 @@ def test_personal_api_key(self, patch_process_event_with_plugins):
{"tag_name": "a", "nth_child": 1, "nth_of_type": 2, "attr__class": "btn btn-sm",},
{"tag_name": "div", "nth_child": 1, "nth_of_type": 2, "$el_text": "💻",},
],
"$test_environment": False,
},
}
now = timezone.now()
Expand Down Expand Up @@ -164,6 +200,7 @@ def test_personal_api_key_from_batch_request(self, patch_process_event_with_plug
"$device_type": "Desktop",
"distinct_id": "94b03e599131fd5026b",
"token": "fake token",
"$test_environment": False,
},
"timestamp": "2021-04-20T19:11:33.841Z",
},
Expand Down Expand Up @@ -326,7 +363,7 @@ def test_batch(self, patch_process_event_with_plugins):
"distinct_id": "2",
"ip": "127.0.0.1",
"site_url": "http://testserver",
"data": {**data, "properties": {}},
"data": {**data, "properties": {"$test_environment": False,}},
"team_id": self.team.pk,
},
)
Expand All @@ -336,7 +373,7 @@ def test_batch(self, patch_process_event_with_plugins):
def test_batch_gzip_header(self, patch_process_event_with_plugins):
data = {
"api_key": self.team.api_token,
"batch": [{"type": "capture", "event": "user signed up", "distinct_id": "2"}],
"batch": [{"type": "capture", "event": "user signed up", "distinct_id": "2",}],
}

response = self.client.generic(
Expand All @@ -356,7 +393,7 @@ def test_batch_gzip_header(self, patch_process_event_with_plugins):
"distinct_id": "2",
"ip": "127.0.0.1",
"site_url": "http://testserver",
"data": {**data["batch"][0], "properties": {}},
"data": {**data["batch"][0], "properties": {"$test_environment": False,}},
"team_id": self.team.pk,
},
)
Expand Down Expand Up @@ -385,7 +422,7 @@ def test_batch_gzip_param(self, patch_process_event_with_plugins):
"distinct_id": "2",
"ip": "127.0.0.1",
"site_url": "http://testserver",
"data": {**data["batch"][0], "properties": {}},
"data": {**data["batch"][0], "properties": {"$test_environment": False}},
"team_id": self.team.pk,
},
)
Expand Down Expand Up @@ -415,7 +452,7 @@ def test_batch_lzstring(self, patch_process_event_with_plugins):
"distinct_id": "2",
"ip": "127.0.0.1",
"site_url": "http://testserver",
"data": {**data["batch"][0], "properties": {}},
"data": {**data["batch"][0], "properties": {"$test_environment": False,}},
"team_id": self.team.pk,
},
)
Expand Down