Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into aspicer/funnel_actors
Browse files Browse the repository at this point in the history
  • Loading branch information
aspicer committed Oct 1, 2024
2 parents 9a5889a + efdc026 commit 6d5bf56
Show file tree
Hide file tree
Showing 471 changed files with 4,755 additions and 1,691 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,6 @@ jobs:
path: 'posthog-cloud-infra'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

- name: Assert user_defined_function.xml is deployed to US
run: |
cmp posthog/user_scripts/latest_user_defined_function.xml posthog-cloud-infra/ansible/us/clickhouse/config/common/user_defined_function.xml
- name: Assert user_defined_function.xml is deployed to EU
run: |
cmp posthog/user_scripts/latest_user_defined_function.xml posthog-cloud-infra/ansible/eu/clickhouse/config/common/user_defined_function.xml
check-migrations:
needs: changes
if: needs.changes.outputs.backend == 'true'
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/rust-docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ jobs:
dockerfile: ./rust/Dockerfile
- image: property-defs-rs
dockerfile: ./rust/Dockerfile
- image: error-tracking
dockerfile: ./rust/Dockerfile
runs-on: depot-ubuntu-22.04-4
permissions:
id-token: write # allow issuing OIDC tokens for this workflow run
Expand All @@ -46,6 +48,7 @@ jobs:
hook-janitor_digest: ${{ steps.digest.outputs.hook-janitor_digest }}
hook-worker_digest: ${{ steps.digest.outputs.hook-worker_digest }}
hook-migrator_digest: ${{ steps.digest.outputs.hook-migrator_digest }}
error-tracking-rs_digest: ${{ steps.digest.outputs.error-tracking-rs_digest }}

defaults:
run:
Expand Down Expand Up @@ -141,6 +144,10 @@ jobs:
values:
image:
sha: '${{ needs.build.outputs.property-defs-rs_digest }}'
# - release: error-tracking-rs - disabled until a charts in place, for now we just build
# values:
# image:
# sha: '${{ needs.build.outputs.error-tracking-rs_digest }}'
- release: hoghooks
values:
api_image:
Expand Down
122 changes: 122 additions & 0 deletions ee/api/test/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from posthog.models.organization import Organization, OrganizationMembership
from posthog.models.project import Project
from posthog.models.team.team import Team
from posthog.models.user import User
from posthog.test.base import FuzzyInt


class TestProjectEnterpriseAPI(team_enterprise_api_test_factory()):
Expand All @@ -14,6 +16,46 @@ class TestProjectEnterpriseAPI(team_enterprise_api_test_factory()):

client_class = EnvironmentToProjectRewriteClient

def test_create_team(self):
self.organization_membership.level = OrganizationMembership.Level.ADMIN
self.organization_membership.save()
self.assertEqual(Team.objects.count(), 1)
self.assertEqual(Project.objects.count(), 1)
response = self.client.post("/api/projects/@current/environments/", {"name": "Test"})
self.assertEqual(response.status_code, 201)
self.assertEqual(Team.objects.count(), 2)
self.assertEqual(Project.objects.count(), 2)
response_data = response.json()
self.assertDictContainsSubset(
{
"name": "Test",
"access_control": False,
"effective_membership_level": OrganizationMembership.Level.ADMIN,
},
response_data,
)
self.assertEqual(self.organization.teams.count(), 2)

def test_create_team_with_access_control(self):
self.organization_membership.level = OrganizationMembership.Level.ADMIN
self.organization_membership.save()
self.assertEqual(Team.objects.count(), 1)
self.assertEqual(Project.objects.count(), 1)
response = self.client.post("/api/projects/@current/environments/", {"name": "Test", "access_control": True})
self.assertEqual(response.status_code, 201)
self.assertEqual(Team.objects.count(), 2)
self.assertEqual(Project.objects.count(), 2)
response_data = response.json()
self.assertDictContainsSubset(
{
"name": "Test",
"access_control": True,
"effective_membership_level": OrganizationMembership.Level.ADMIN,
},
response_data,
)
self.assertEqual(self.organization.teams.count(), 2)

def test_user_create_project_for_org_via_url(self):
# Set both current and new org to high enough membership level
self.organization_membership.level = OrganizationMembership.Level.ADMIN
Expand Down Expand Up @@ -46,3 +88,83 @@ def test_user_cannot_create_project_in_org_without_access(self):
response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"})
self.assertEqual(response.status_code, 403, msg=response.json())
assert response.json() == self.permission_denied_response("Your organization access level is insufficient.")

def test_user_that_does_not_belong_to_an_org_cannot_create_a_projec(self):
user = User.objects.create(email="[email protected]")
self.client.force_login(user)

response = self.client.post("/api/projects/", {"name": "Test"})
self.assertEqual(response.status_code, 404, response.content)
self.assertEqual(
response.json(),
{
"type": "invalid_request",
"code": "not_found",
"detail": "You need to belong to an organization.",
"attr": None,
},
)

def test_list_projects_restricted_ones_hidden(self):
self.organization_membership.level = OrganizationMembership.Level.MEMBER
self.organization_membership.save()
Team.objects.create(
organization=self.organization,
name="Other",
access_control=True,
)

# The other team should not be returned as it's restricted for the logged-in user
projects_response = self.client.get(f"/api/environments/")

# 9 (above):
with self.assertNumQueries(FuzzyInt(10, 11)):
current_org_response = self.client.get(f"/api/organizations/{self.organization.id}/")

self.assertEqual(projects_response.status_code, 200)
self.assertEqual(
projects_response.json().get("results"),
[
{
"id": self.team.id,
"uuid": str(self.team.uuid),
"organization": str(self.organization.id),
"api_token": self.team.api_token,
"name": self.team.name,
"completed_snippet_onboarding": False,
"has_completed_onboarding_for": {"product_analytics": True},
"ingested_event": False,
"is_demo": False,
"timezone": "UTC",
"access_control": False,
}
],
)
self.assertEqual(current_org_response.status_code, 200)
self.assertEqual(
current_org_response.json().get("teams"),
[
{
"id": self.team.id,
"uuid": str(self.team.uuid),
"organization": str(self.organization.id),
"project_id": self.team.project.id, # type: ignore
"api_token": self.team.api_token,
"name": self.team.name,
"completed_snippet_onboarding": False,
"has_completed_onboarding_for": {"product_analytics": True},
"ingested_event": False,
"is_demo": False,
"timezone": "UTC",
"access_control": False,
}
],
)

def test_cannot_create_project_in_org_without_access(self):
self.organization_membership.delete()

response = self.client.post(f"/api/organizations/{self.organization.id}/projects/", {"name": "Test"})

self.assertEqual(response.status_code, 404, response.json())
self.assertEqual(response.json(), self.not_found_response("Organization not found."))
Loading

0 comments on commit 6d5bf56

Please sign in to comment.