Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite committed Oct 27, 2023
2 parents 37bd438 + 79b5e90 commit c52404a
Show file tree
Hide file tree
Showing 1,254 changed files with 49,856 additions and 42,886 deletions.
20 changes: 18 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ module.exports = {
react: {
version: 'detect',
},
'import/resolver': {
node: {
paths: ['eslint-rules'], // Add the directory containing your custom rules
extensions: ['.js', '.jsx', '.ts', '.tsx'], // Ensure ESLint resolves both JS and TS files
},
},
},
extends: [
'eslint:recommended',
Expand All @@ -37,7 +43,7 @@ module.exports = {
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['prettier', 'react', 'cypress', '@typescript-eslint', 'no-only-tests', 'jest', 'compat'],
plugins: ['prettier', 'react', 'cypress', '@typescript-eslint', 'no-only-tests', 'jest', 'compat', 'posthog'],
rules: {
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-debugger': 'error',
Expand Down Expand Up @@ -91,7 +97,7 @@ module.exports = {
],
},
],
'react/forbid-elements': [
'posthog/warn-elements': [
1,
{
forbid: [
Expand Down Expand Up @@ -236,6 +242,16 @@ module.exports = {
'@typescript-eslint/no-var-requires': 'off',
},
},
{
files: 'eslint-rules/**/*',
extends: ['eslint:recommended'],
rules: {
'@typescript-eslint/no-var-requires': 'off',
},
env: {
node: true,
},
},
],
reportUnusedDisableDirectives: true,
}
14 changes: 10 additions & 4 deletions .github/actions/build-n-cache-image/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ inputs:
actions-id-token-request-url:
required: true
description: "ACTIONS_ID_TOKEN_REQUEST_URL, issued by GitHub when permission 'id-token' is set to 'write'"
load:
save:
required: false
default: 'false'
description: Whether to load the image into local Docker after building it
description: Whether to save the image in the Depot ephemeral registry after building it

outputs:
tag:
description: The tag of the image that was built
value: ${{ steps.emit.outputs.tag }}
build-id:
description: The ID of the build
value: ${{ steps.build.outputs.build-id }}
unit-build-id:
description: The ID of the unit build
value: ${{ steps.build-unit.outputs.build-id }}

runs:
using: 'composite'
Expand All @@ -30,10 +36,10 @@ runs:
uses: depot/build-push-action@v1
with:
buildx-fallback: false # buildx is so slow it's better to just fail
load: ${{ inputs.load }}
tags: ${{ steps.emit.outputs.tag }}
platforms: linux/amd64,linux/arm64
build-args: COMMIT_HASH=${{ github.sha }}
save: ${{ inputs.save }}
env:
ACTIONS_ID_TOKEN_REQUEST_URL: ${{ inputs.actions-id-token-request-url }}

Expand All @@ -42,10 +48,10 @@ runs:
uses: depot/build-push-action@v1
with:
buildx-fallback: false # buildx is so slow it's better to just fail
load: ${{ inputs.load }}
file: production-unit.Dockerfile
tags: ${{ steps.emit.outputs.tag }}
platforms: linux/amd64
build-args: COMMIT_HASH=${{ github.sha }}
save: ${{ inputs.save }}
env:
ACTIONS_ID_TOKEN_REQUEST_URL: ${{ inputs.actions-id-token-request-url }}
31 changes: 20 additions & 11 deletions .github/workflows/ci-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,21 @@ jobs:
permissions:
contents: read
id-token: write # allow issuing OIDC tokens for this workflow run
outputs:
tag: ${{ steps.build.outputs.tag }}
build-id: ${{ steps.build.outputs.build-id }}
unit-build-id: ${{ steps.build.outputs.unit-build-id }}
steps:
- name: Checkout
if: needs.changes.outputs.shouldTriggerCypress == 'true'
uses: actions/checkout@v3
- name: Get Docker image cached in Depot
- name: Build the Docker image with Depot
if: needs.changes.outputs.shouldTriggerCypress == 'true'
# Build the container image in preparation for the E2E tests
uses: ./.github/actions/build-n-cache-image
id: build
with:
save: true
actions-id-token-request-url: ${{ env.ACTIONS_ID_TOKEN_REQUEST_URL }}

cypress:
Expand Down Expand Up @@ -157,17 +163,20 @@ jobs:
if: needs.changes.outputs.shouldTriggerCypress == 'true'
run: ./bin/check_kafka_clickhouse_up

- name: Install Depot CLI
if: needs.changes.outputs.shouldTriggerCypress == 'true'
uses: depot/setup-action@v1

- name: Get Docker image cached in Depot
if: needs.changes.outputs.shouldTriggerCypress == 'true'
# We don't actually build the image here, because we use Depot, which acts as our cross-workflow cache.
# The build is first initiated in container-images-ci.yml, so by the time this runs, some layers already
# are cached, and the in-flight builds overall are deduplicated. According to Depot folks, this applies
# even if the builds _start_ concurrently! In short, only one build per commit push is ever executed.
uses: ./.github/actions/build-n-cache-image
id: docker-build
uses: depot/pull-action@v1
with:
actions-id-token-request-url: ${{ env.ACTIONS_ID_TOKEN_REQUEST_URL }}
load: true
# Use the production.Dockerfile image:
# build-id: ${{ needs.container.outputs.build-id }}
# Use the production-unit.Dockerfile image:
build-id: ${{ needs.container.outputs.unit-build-id }}
tags: |
${{ needs.container.outputs.tag }}
- name: Write .env # This step intentionally has no if, so that GH always considers the action as having run
run: |
Expand Down Expand Up @@ -199,8 +208,8 @@ jobs:
run: |
mkdir -p /tmp/logs
echo "Starting PostHog using the container image ${{ steps.docker-build.outputs.tag }}"
DOCKER_RUN="docker run --rm --network host --add-host kafka:127.0.0.1 --env-file .env ${{ steps.docker-build.outputs.tag }}"
echo "Starting PostHog using the container image ${{ needs.container.outputs.tag }}"
DOCKER_RUN="docker run --rm --network host --add-host kafka:127.0.0.1 --env-file .env ${{ needs.container.outputs.tag }}"
$DOCKER_RUN ./bin/migrate
$DOCKER_RUN python manage.py setup_dev
Expand Down
20 changes: 0 additions & 20 deletions .storybook/decorators/with3000.tsx

This file was deleted.

8 changes: 4 additions & 4 deletions .storybook/decorators/withFeatureFlags.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useFeatureFlags } from '~/mocks/browser'
import type { DecoratorFn } from '@storybook/react'
import { setFeatureFlags } from '~/mocks/browser'
import type { Decorator } from '@storybook/react'

/** Global story decorator that allows setting feature flags.
*
Expand All @@ -13,9 +13,9 @@ import type { DecoratorFn } from '@storybook/react'
* } as ComponentMeta<typeof MyComponent>
* ```
*/
export const withFeatureFlags: DecoratorFn = (Story, { parameters }) => {
export const withFeatureFlags: Decorator = (Story, { parameters }) => {
if (parameters.featureFlags) {
useFeatureFlags(parameters.featureFlags)
setFeatureFlags(parameters.featureFlags)
}

return <Story />
Expand Down
4 changes: 2 additions & 2 deletions .storybook/decorators/withKea/withKea.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { DecoratorFn } from '@storybook/react'
import type { Decorator } from '@storybook/react'
import { useAvailableFeatures } from '~/mocks/features'

import { KeaStory } from './kea-story'

export const withKea: DecoratorFn = (Story) => {
export const withKea: Decorator = (Story) => {
// Reset enabled enterprise features. Overwrite this line within your stories.
useAvailableFeatures([])
return (
Expand Down
4 changes: 2 additions & 2 deletions .storybook/decorators/withMockDate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DecoratorFn } from '@storybook/react'
import type { Decorator } from '@storybook/react'
import MockDate from 'mockdate'

/** Global story decorator that allows mocking of dates.
Expand All @@ -13,7 +13,7 @@ import MockDate from 'mockdate'
* } as ComponentMeta<typeof MyComponent>
* ```
*/
export const withMockDate: DecoratorFn = (Story, { parameters }) => {
export const withMockDate: Decorator = (Story, { parameters }) => {
if (parameters.mockDate) {
MockDate.set(parameters.mockDate)
} else {
Expand Down
4 changes: 2 additions & 2 deletions .storybook/decorators/withSnapshotsDisabled.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { DecoratorFn } from '@storybook/react'
import { Decorator } from '@storybook/react'
import { inStorybookTestRunner } from 'lib/utils'

/** Workaround for https://github.com/storybookjs/test-runner/issues/74 */
// TODO: Smoke-test all the stories by removing this decorator, once all the stories pass
export const withSnapshotsDisabled: DecoratorFn = (Story, { parameters }) => {
export const withSnapshotsDisabled: Decorator = (Story, { parameters }) => {
if (parameters?.testOptions?.skip && inStorybookTestRunner()) {
return <>Disabled for Test Runner</>
}
Expand Down
44 changes: 44 additions & 0 deletions .storybook/decorators/withTheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { Decorator } from '@storybook/react'

import { FEATURE_FLAGS } from 'lib/constants'

/** Global story decorator that is used by the theming control to
* switch between themes.
*/
export const withTheme: Decorator = (Story, context) => {
const theme = context.globals.theme

// set the body class
const actualClassState = document.body.classList.contains('posthog-3000')
const desiredClassState = theme !== 'legacy'

if (actualClassState !== desiredClassState) {
if (desiredClassState) {
document.body.classList.add('posthog-3000')
} else {
document.body.classList.remove('posthog-3000')
}
}

// set the feature flag
const actualFeatureFlagState = window.POSTHOG_APP_CONTEXT!.persisted_feature_flags?.includes(
FEATURE_FLAGS.POSTHOG_3000
)
const desiredFeatureFlagState = theme !== 'legacy'

if (actualFeatureFlagState !== desiredFeatureFlagState) {
const currentFlags = window.POSTHOG_APP_CONTEXT!.persisted_feature_flags || []
if (desiredFeatureFlagState) {
window.POSTHOG_APP_CONTEXT!.persisted_feature_flags = [...currentFlags, FEATURE_FLAGS.POSTHOG_3000]
} else {
window.POSTHOG_APP_CONTEXT!.persisted_feature_flags = currentFlags.filter(
(f) => f !== FEATURE_FLAGS.POSTHOG_3000
)
}
}

// set the theme
document.body.setAttribute('theme', theme === 'dark' ? 'dark' : 'light')

return <Story />
}
19 changes: 19 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { withMockDate } from './decorators/withMockDate'
import { defaultMocks } from '~/mocks/handlers'
import { withSnapshotsDisabled } from './decorators/withSnapshotsDisabled'
import { withFeatureFlags } from './decorators/withFeatureFlags'
import { withTheme } from './decorators/withTheme'

const setupMsw = () => {
// Make sure the msw worker is started
Expand Down Expand Up @@ -86,6 +87,8 @@ export const decorators: Meta['decorators'] = [
withMockDate,
// Allow us to easily set feature flags in stories.
withFeatureFlags,
// Set theme from global context
withTheme,
]

const preview: Preview = {
Expand All @@ -110,6 +113,22 @@ const preview: Preview = {
),
},
},
globalTypes: {
theme: {
description: '',
defaultValue: 'legacy',
toolbar: {
title: 'Theme',
items: [
{ value: 'legacy', icon: 'faceneutral', title: 'Legacy' },
{ value: 'light', icon: 'sun', title: 'Light' },
{ value: 'dark', icon: 'moon', title: 'Dark' },
],
// change the title based on the selected value
dynamicTitle: true,
},
},
},
}

export default preview
25 changes: 19 additions & 6 deletions ee/api/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

@api_view(["GET"])
def saml_metadata_view(request, *args, **kwargs):

if (
not request.user.organization_memberships.get(organization=request.user.organization).level
>= OrganizationMembership.Level.ADMIN
Expand All @@ -46,7 +45,6 @@ class MultitenantSAMLAuth(SAMLAuth):
"""

def get_idp(self, organization_domain_or_id: Union["OrganizationDomain", str]):

try:
organization_domain = (
organization_domain_or_id
Expand All @@ -57,7 +55,10 @@ def get_idp(self, organization_domain_or_id: Union["OrganizationDomain", str]):
raise AuthFailed("saml", "Authentication request is invalid. Invalid RelayState.")

if not organization_domain.organization.is_feature_available(AvailableFeature.SAML):
raise AuthFailed("saml", "Your organization does not have the required license to use SAML.")
raise AuthFailed(
"saml",
"Your organization does not have the required license to use SAML.",
)

return SAMLIdentityProvider(
str(organization_domain.id),
Expand Down Expand Up @@ -88,7 +89,12 @@ def auth_url(self):
# name, since we multiple IdPs share the same auth_complete URL.
return auth.login(return_to=str(instance.id))

def _get_attr(self, response_attributes: Dict[str, Any], attribute_names: List[str], optional: bool = False) -> str:
def _get_attr(
self,
response_attributes: Dict[str, Any],
attribute_names: List[str],
optional: bool = False,
) -> str:
"""
Fetches a specific attribute from the SAML response, attempting with multiple different attribute names.
We attempt multiple attribute names to make it easier for admins to configure SAML (less configuration to set).
Expand All @@ -114,7 +120,9 @@ def get_user_details(self, response):
attributes = response["attributes"]
return {
"fullname": self._get_attr(
attributes, ["full_name", "FULL_NAME", "fullName", OID_COMMON_NAME], optional=True
attributes,
["full_name", "FULL_NAME", "fullName", OID_COMMON_NAME],
optional=True,
),
"first_name": self._get_attr(
attributes,
Expand All @@ -140,7 +148,12 @@ def get_user_details(self, response):
),
"email": self._get_attr(
attributes,
["email", "EMAIL", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", OID_MAIL],
[
"email",
"EMAIL",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
OID_MAIL,
],
),
}

Expand Down
Loading

0 comments on commit c52404a

Please sign in to comment.