Skip to content

Commit

Permalink
feat(environments): Add new environments endpoint and move /projects …
Browse files Browse the repository at this point in the history
…to Project (#24154)

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Twixes and github-actions[bot] authored Sep 11, 2024
1 parent b2e8300 commit f2522de
Show file tree
Hide file tree
Showing 41 changed files with 3,495 additions and 1,880 deletions.
3 changes: 2 additions & 1 deletion .storybook/app-context.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { MOCK_DEFAULT_TEAM } from 'lib/api.mock'
import { MOCK_DEFAULT_TEAM, MOCK_DEFAULT_PROJECT } from 'lib/api.mock'
import { AppContext } from '~/types'

export const getStorybookAppContext = (): AppContext => ({
anonymous: false,
// Ideally we wouldn't set `current_team` here, the same way we don't set `current_user`, but unfortunately
// as of March 2024, a bunch of logics make the assumption that this is set, via `AppConfig`
current_team: MOCK_DEFAULT_TEAM,
current_project: MOCK_DEFAULT_PROJECT,
current_user: undefined as any, // `undefined` triggers a fetch and lets us mock the data
default_event_name: '$pageview',
persisted_feature_flags: [],
Expand Down
1 change: 1 addition & 0 deletions ee/api/test/test_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ def mock_implementation(url: str, headers: Any = None, params: Any = None) -> Ma
# Create a demo project
self.organization_membership.level = OrganizationMembership.Level.ADMIN
self.organization_membership.save()
self.assertEqual(Team.objects.count(), 1)
response = self.client.post("/api/projects/", {"name": "Test", "is_demo": True})
self.assertEqual(response.status_code, 201)
self.assertEqual(Team.objects.count(), 3)
Expand Down
2 changes: 1 addition & 1 deletion ee/api/test/test_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_create_organization(self):
OrganizationMembership.Level.OWNER,
)

@patch("secrets.choice", return_value="Y")
@patch("posthog.models.utils.generate_random_short_suffix", return_value="YYYY")
def test_create_two_similarly_named_organizations(self, mock_choice):
response = self.client.post(
"/api/organizations/",
Expand Down
48 changes: 48 additions & 0 deletions ee/api/test/test_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from ee.api.test.test_team import team_enterprise_api_test_factory
from posthog.api.test.test_team import EnvironmentToProjectRewriteClient
from posthog.models.organization import Organization, OrganizationMembership
from posthog.models.project import Project
from posthog.models.team.team import Team


class TestProjectEnterpriseAPI(team_enterprise_api_test_factory()):
"""
We inherit from TestTeamEnterpriseAPI, as previously /api/projects/ referred to the Team model, which used to mean "project".
Now as Team means "environment" and Project is separate, we must ensure backward compatibility of /api/projects/.
At the same time, this class is where we can continue adding `Project`-specific API tests.
"""

client_class = EnvironmentToProjectRewriteClient

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
self.organization_membership.save()

current_org, _, _ = Organization.objects.bootstrap(self.user, name="other_org")
other_org = self.organization # Bootstrapping above sets it to the current org
assert Team.objects.count() == 2
assert Project.objects.count() == 2

assert current_org.id == self.user.current_organization_id
response = self.client.post(f"/api/organizations/{current_org.id}/projects/", {"name": "Via current org"})
self.assertEqual(response.status_code, 201)
assert response.json()["organization"] == str(current_org.id)
assert Team.objects.count() == 3
assert Project.objects.count() == 3

assert other_org.id != self.user.current_organization_id
response = self.client.post(f"/api/organizations/{other_org.id}/projects/", {"name": "Via path org"})
self.assertEqual(response.status_code, 201, msg=response.json())
assert response.json()["organization"] == str(other_org.id)
assert Team.objects.count() == 4
assert Project.objects.count() == 4

def test_user_cannot_create_project_in_org_without_access(self):
_, _, _ = Organization.objects.bootstrap(self.user, name="other_org")
other_org = self.organization # Bootstrapping above sets it to the current org

assert other_org.id != self.user.current_organization_id
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.")
Loading

0 comments on commit f2522de

Please sign in to comment.