0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-12-01 04:12:23 +01:00
posthog/ee/api/test/test_organization.py

207 lines
11 KiB
Python
Raw Normal View History

Project-based permissioning framework (#5976) * Refactor `AvailableFeature` from strings to an enum everywhere * Fix circular dependency and type * Add "Per-project access" feature flag, premium feature, and organization switch * Rename `OrganizationMembershipLevel` to `OrganizationAccessLevel` * Create `ExplicitTeamMembership` model * Show whether projects are restricted in the project switcher * Update organizations API code * Fix migrations * Move organization tests that require EE to `ee` * Revert `OrganizationMembershipLevel` rename * Fix organization tests * Update migration * Fix schema and add Members to Project Settings * Build out test memberships API with security tests * Update `TeamMembers` and `teamMembersLogic` * Move "Per-project access" description to tooltip * Add moar tests * Fix Project Members list logic * Add additional membership checks * Update migrations * Fix typing * Adjust explicit team memberships API similarly * Fix typo * Unify `ExplicitTeamMemberSerializer` * Remove old changes to `membersLogic` usage * Use `effective_membership_level` on `TeamBasicSerializer` * Clean up organization update tests * Explicitly disallow enabling per-project access for free * Fix circular import * Remove `id` from `UserSerializer` * Fix typing * Try to fix import * Fix fatal typing * Add more tests * Update permissioning.ts * Add clarifying comment to migration * Fix import * minor clarifications * Revert `TopNavigation` changes * Make new access control entirely project-based * Update migrations * Add `project_based_permissioning` to `TeamBasicSerializer` * Update test_team.py * Fix Access Control restriction tooltip * adjust copy & UI a bit * Address feedback on field comment * "Privacy settings" to "Access Control" * Ignore mypy * Rename `Team` field `project_based_permissioning` to `access_control` * Update migrations Co-authored-by: Paolo D'Amico <paolodamico@users.noreply.github.com>
2021-09-22 18:29:59 +02:00
import datetime as dt
import random
Project-based permissioning framework (#5976) * Refactor `AvailableFeature` from strings to an enum everywhere * Fix circular dependency and type * Add "Per-project access" feature flag, premium feature, and organization switch * Rename `OrganizationMembershipLevel` to `OrganizationAccessLevel` * Create `ExplicitTeamMembership` model * Show whether projects are restricted in the project switcher * Update organizations API code * Fix migrations * Move organization tests that require EE to `ee` * Revert `OrganizationMembershipLevel` rename * Fix organization tests * Update migration * Fix schema and add Members to Project Settings * Build out test memberships API with security tests * Update `TeamMembers` and `teamMembersLogic` * Move "Per-project access" description to tooltip * Add moar tests * Fix Project Members list logic * Add additional membership checks * Update migrations * Fix typing * Adjust explicit team memberships API similarly * Fix typo * Unify `ExplicitTeamMemberSerializer` * Remove old changes to `membersLogic` usage * Use `effective_membership_level` on `TeamBasicSerializer` * Clean up organization update tests * Explicitly disallow enabling per-project access for free * Fix circular import * Remove `id` from `UserSerializer` * Fix typing * Try to fix import * Fix fatal typing * Add more tests * Update permissioning.ts * Add clarifying comment to migration * Fix import * minor clarifications * Revert `TopNavigation` changes * Make new access control entirely project-based * Update migrations * Add `project_based_permissioning` to `TeamBasicSerializer` * Update test_team.py * Fix Access Control restriction tooltip * adjust copy & UI a bit * Address feedback on field comment * "Privacy settings" to "Access Control" * Ignore mypy * Rename `Team` field `project_based_permissioning` to `access_control` * Update migrations Co-authored-by: Paolo D'Amico <paolodamico@users.noreply.github.com>
2021-09-22 18:29:59 +02:00
from unittest.mock import Mock, patch
from freezegun.api import freeze_time
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
from rest_framework import status
from ee.api.test.base import APILicensedTest
Project-based permissioning framework (#5976) * Refactor `AvailableFeature` from strings to an enum everywhere * Fix circular dependency and type * Add "Per-project access" feature flag, premium feature, and organization switch * Rename `OrganizationMembershipLevel` to `OrganizationAccessLevel` * Create `ExplicitTeamMembership` model * Show whether projects are restricted in the project switcher * Update organizations API code * Fix migrations * Move organization tests that require EE to `ee` * Revert `OrganizationMembershipLevel` rename * Fix organization tests * Update migration * Fix schema and add Members to Project Settings * Build out test memberships API with security tests * Update `TeamMembers` and `teamMembersLogic` * Move "Per-project access" description to tooltip * Add moar tests * Fix Project Members list logic * Add additional membership checks * Update migrations * Fix typing * Adjust explicit team memberships API similarly * Fix typo * Unify `ExplicitTeamMemberSerializer` * Remove old changes to `membersLogic` usage * Use `effective_membership_level` on `TeamBasicSerializer` * Clean up organization update tests * Explicitly disallow enabling per-project access for free * Fix circular import * Remove `id` from `UserSerializer` * Fix typing * Try to fix import * Fix fatal typing * Add more tests * Update permissioning.ts * Add clarifying comment to migration * Fix import * minor clarifications * Revert `TopNavigation` changes * Make new access control entirely project-based * Update migrations * Add `project_based_permissioning` to `TeamBasicSerializer` * Update test_team.py * Fix Access Control restriction tooltip * adjust copy & UI a bit * Address feedback on field comment * "Privacy settings" to "Access Control" * Ignore mypy * Rename `Team` field `project_based_permissioning` to `access_control` * Update migrations Co-authored-by: Paolo D'Amico <paolodamico@users.noreply.github.com>
2021-09-22 18:29:59 +02:00
from ee.models.license import License
from posthog.celery import sync_all_organization_available_features
from posthog.models import Team, User
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
from posthog.models.organization import Organization, OrganizationMembership
class TestOrganizationEnterpriseAPI(APILicensedTest):
def test_create_organization(self):
response = self.client.post("/api/organizations/", {"name": "Test"})
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Organization.objects.count(), 2)
response_data = response.json()
self.assertEqual(response_data.get("name"), "Test")
self.assertEqual(OrganizationMembership.objects.filter(organization_id=response_data.get("id")).count(), 1)
self.assertEqual(
OrganizationMembership.objects.get(organization_id=response_data.get("id"), user=self.user).level,
OrganizationMembership.Level.OWNER,
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
)
def test_create_two_similarly_named_organizations(self):
random.seed(0)
response = self.client.post("/api/organizations/", {"name": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"})
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertDictContainsSubset(
{
"name": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"slug": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
},
response.json(),
)
response = self.client.post(
"/api/organizations/", {"name": "#XXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX"}
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertDictContainsSubset(
{
"name": "#XXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX",
"slug": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-yWAc",
},
response.json(),
)
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
def test_delete_second_managed_organization(self):
organization, _, team = Organization.objects.bootstrap(self.user, name="X")
self.assertTrue(Organization.objects.filter(id=organization.id).exists())
self.assertTrue(Team.objects.filter(id=team.id).exists())
response = self.client.delete(f"/api/organizations/{organization.id}")
self.assertEqual(response.status_code, 204)
self.assertFalse(Organization.objects.filter(id=organization.id).exists())
self.assertFalse(Team.objects.filter(id=team.id).exists())
def test_delete_last_organization(self):
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
org_id = self.organization.id
self.assertTrue(Organization.objects.filter(id=org_id).exists())
2021-04-01 04:00:58 +02:00
self.organization_membership.level = OrganizationMembership.Level.OWNER
self.organization_membership.save()
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
response = self.client.delete(f"/api/organizations/{org_id}")
self.assertEqual(response.status_code, 204, "Did not successfully delete last organization on the instance")
self.assertFalse(Organization.objects.filter(id=org_id).exists())
self.assertFalse(Organization.objects.exists())
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
response_bis = self.client.delete(f"/api/organizations/{org_id}")
self.assertEqual(response_bis.status_code, 404, "Did not return a 404 on trying to delete a nonexistent org")
def test_no_delete_organization_not_owning(self):
for level in (OrganizationMembership.Level.MEMBER, OrganizationMembership.Level.ADMIN):
self.organization_membership.level = level
self.organization_membership.save()
response = self.client.delete(f"/api/organizations/{self.organization.id}")
potential_err_message = f"Somehow managed to delete the org as a level {level} (which is not owner)"
self.assertEqual(
response.json(),
{
"attr": None,
"detail": "Your organization access level is insufficient.",
"code": "permission_denied",
"type": "authentication_error",
},
potential_err_message,
)
self.assertEqual(response.status_code, 403, potential_err_message)
self.assertTrue(self.organization.name, self.CONFIG_ORGANIZATION_NAME)
def test_delete_organization_owning(self):
self.organization_membership.level = OrganizationMembership.Level.OWNER
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
self.organization_membership.save()
membership_ids = OrganizationMembership.objects.filter(organization=self.organization).values_list(
"id", flat=True
Organization<>Team<>User structure (closes #1540) (#1562) * Backend changes to implement #1461 * Added the missing migration files * Fixes Typecheck errors * Refactor request.user.team_set.get() to use request.user.team * Updated user patch method to change current_team on team id instead of name * Merged migration file * Changes team property to return first item in queryset * Fixes failing tests * Changed User api to return the ids of the teams they are currently part of * Frontend for changing teams * Update and simplify migrations * Improve team and user buttons * Make team changing backend more logical * Improve current_team mechanics * Update test_team.py * Fix Team.objects.create_with_data * Update migration * Update tests * Make setup_review more convenient * Add Organization and OrganizationMembership * Replace is_admin with level * Extend API * Update team.py * Improve modeling * Improve handling of new mechanics * Add proper migration * Remove _ensure_organization_and_team * Update 0084_org_team_user.py * Improve user, org and team creation * Make MembershipLevel more flexible for the future * Add member deletion * Fix naive datetime warnings * Update setup_review.py * Update API route * Make PersonalAPIKey changes * Update models and migrations, fix typing * Fix typing * Use MAC-less UUID v1 instead of v4 for better performance * Add abstract UUIDModel * Update utils.py * Update utils.py * Fix multi/unicast bit * Update APIs, frontend and tests * Update pull_request_template.md * Fix comment * Fix migration error * Compress migrations * Updates with minimal renaming * More updates * Make further updates * Update test_team_user.py * Fix issues * Add migration * Satisfy mypy * Remove Signup redirect on logged in * Use uuid1_macless in Person * Fix typing * Update tests * Update /api/team/signup to /api/organization/signup * Fix mypy issues and update tests The remaining failures are actually missing functionality (TDD applied), so filling these in. * Update 0086_org_live * Make small improvements * Implement permissions * Remove now unneccesary membership check * Update setup_dev.py * Make small frontend improvements * Add drf-nested-routers as requirement * Remove unused import * Implemented nested routes * Remove cruft * Add relevant org/proj/user name to headings * Fix imports * Update migration * Replace unreliable drf-nested-routers with drf-extensions * Improve unset team handling * Make org and team creation proper * Update migration * Fix migration * Update TopContent * Update command palette for new sidebar structure * Remove deprecated demo data deletion * Assume that each org has a project and fix typing * Require paid plan for multiple orgs and projects * Make HogFlix demo a separate team * Update migration * Slightly improve style * Adjust page layout bottom padding * Make user dropdown nicer * Fix base app tests * Satisfy mypy * Fix test_leave_organization * Improve wording * Possibly fix import * Remove misplaced None check * Enhance org and teams APIs and add tests * Fix /api/projects for particular Team * Improve invites and demo data * Address feedback * Put everything related to billing on Organization * Fix minor issues * Simplify invitation creation * Update team model * Make orgs and projects premium only on self-hosted * Improve testing * Update migration * Remove extra License import * Fix minor issues * Fix Django tests * Fix Cypress * Fix yarn build * Fix TeamSignupViewset * Fix posthog-production incompatibility * Remove extraneous insight endpoint registration * Adjust tests for posthog-production * Simplify invitations and fix email validation * Address all feedback * Satisfy mypy * Update migration * Fix constraint removal in migration * Update tests * Fix test creation edge case * Run posthog-production CI tests against this branch and teams-live * Ensure that js_posthog_api_key is always passed * Fix preflight check pre-login * Update cypress tests * Update instanceStatus.js * Bring ee tets up to par * Bring actions-ux-201012 back * Cypress retry in cypress.json * Revert "Run posthog-production CI tests against this branch and teams-live" This reverts commit d79cb844d823d767b060122af32bd74163593d7a. Co-authored-by: anna <ms.annaphilips@gmail.com> Co-authored-by: Anna Philips <aphilips@matmacorp.com>
2020-10-22 10:58:32 +02:00
)
response = self.client.delete(f"/api/organizations/{self.organization.id}")
potential_err_message = f"Somehow did not delete the org as the owner"
self.assertEqual(response.status_code, 204, potential_err_message)
self.assertFalse(Organization.objects.filter(id=self.organization.id).exists(), potential_err_message)
self.assertFalse(OrganizationMembership.objects.filter(id__in=membership_ids).exists())
self.assertTrue(User.objects.filter(id=self.user.pk).exists())
def test_no_delete_organization_not_belonging_to(self):
for level in OrganizationMembership.Level:
self.organization_membership.level = level
self.organization_membership.save()
organization = Organization.objects.create(name="Some Other Org")
response = self.client.delete(f"/api/organizations/{organization.id}")
potential_err_message = f"Somehow managed to delete someone else's org as a level {level} in own org"
self.assertEqual(
response.json(),
{"attr": None, "detail": "Not found.", "code": "not_found", "type": "invalid_request"},
potential_err_message,
)
self.assertEqual(response.status_code, 404, potential_err_message)
self.assertTrue(Organization.objects.filter(id=organization.id).exists(), potential_err_message)
def test_update_org(self):
for level in OrganizationMembership.Level:
self.organization_membership.level = level
self.organization_membership.save()
response_rename = self.client.patch(f"/api/organizations/{self.organization.id}", {"name": "Woof"})
response_email = self.client.patch(
f"/api/organizations/{self.organization.id}", {"is_member_join_email_enabled": False}
)
self.organization.refresh_from_db()
expected_response = {
"attr": None,
"detail": "Your organization access level is insufficient.",
"code": "permission_denied",
"type": "authentication_error",
}
if level < OrganizationMembership.Level.ADMIN:
potential_err_message = f"Somehow managed to update the org as a level {level} (which is below admin)"
self.assertEqual(
response_rename.json(), expected_response, potential_err_message,
)
self.assertEqual(response_rename.status_code, 403, potential_err_message)
self.assertTrue(self.organization.name, self.CONFIG_ORGANIZATION_NAME)
self.assertEqual(
response_email.json(), expected_response, potential_err_message,
)
self.assertEqual(response_email.status_code, 403, potential_err_message)
else:
potential_err_message = f"Somehow did not update the org as a level {level} (which is at least admin)"
self.assertEqual(response_rename.status_code, 200, potential_err_message)
self.assertEqual(response_email.status_code, 200, potential_err_message)
self.assertTrue(self.organization.name, "Woof")
def test_no_update_organization_not_belonging_to(self):
for level in OrganizationMembership.Level:
self.organization_membership.level = level
self.organization_membership.save()
organization = Organization.objects.create(name="Meow")
response = self.client.patch(f"/api/organizations/{organization.id}", {"name": "Mooooooooo"})
potential_err_message = f"Somehow managed to update someone else's org as a level {level} in own org"
self.assertEqual(
response.json(),
{"attr": None, "detail": "Not found.", "code": "not_found", "type": "invalid_request"},
potential_err_message,
)
self.assertEqual(response.status_code, 404, potential_err_message)
organization.refresh_from_db()
self.assertTrue(organization.name, "Meow")
Project-based permissioning framework (#5976) * Refactor `AvailableFeature` from strings to an enum everywhere * Fix circular dependency and type * Add "Per-project access" feature flag, premium feature, and organization switch * Rename `OrganizationMembershipLevel` to `OrganizationAccessLevel` * Create `ExplicitTeamMembership` model * Show whether projects are restricted in the project switcher * Update organizations API code * Fix migrations * Move organization tests that require EE to `ee` * Revert `OrganizationMembershipLevel` rename * Fix organization tests * Update migration * Fix schema and add Members to Project Settings * Build out test memberships API with security tests * Update `TeamMembers` and `teamMembersLogic` * Move "Per-project access" description to tooltip * Add moar tests * Fix Project Members list logic * Add additional membership checks * Update migrations * Fix typing * Adjust explicit team memberships API similarly * Fix typo * Unify `ExplicitTeamMemberSerializer` * Remove old changes to `membersLogic` usage * Use `effective_membership_level` on `TeamBasicSerializer` * Clean up organization update tests * Explicitly disallow enabling per-project access for free * Fix circular import * Remove `id` from `UserSerializer` * Fix typing * Try to fix import * Fix fatal typing * Add more tests * Update permissioning.ts * Add clarifying comment to migration * Fix import * minor clarifications * Revert `TopNavigation` changes * Make new access control entirely project-based * Update migrations * Add `project_based_permissioning` to `TeamBasicSerializer` * Update test_team.py * Fix Access Control restriction tooltip * adjust copy & UI a bit * Address feedback on field comment * "Privacy settings" to "Access Control" * Ignore mypy * Rename `Team` field `project_based_permissioning` to `access_control` * Update migrations Co-authored-by: Paolo D'Amico <paolodamico@users.noreply.github.com>
2021-09-22 18:29:59 +02:00
@patch("posthog.models.organization.License.PLANS", {"enterprise": ["whatever"]})
@patch("ee.models.license.requests.post")
def test_feature_available_self_hosted_has_license(self, patch_post):
with self.settings(MULTI_TENANCY=False):
mock = Mock()
mock.json.return_value = {"plan": "enterprise", "valid_until": dt.datetime.now() + dt.timedelta(days=1)}
patch_post.return_value = mock
License.objects.create(key="key")
# Still only old, empty available_features field value known
self.assertFalse(self.organization.is_feature_available("whatever"))
self.assertFalse(self.organization.is_feature_available("feature-doesnt-exist"))
# New available_features field value that was updated in DB on license creation is known after refresh
self.organization.refresh_from_db()
self.assertTrue(self.organization.is_feature_available("whatever"))
self.assertFalse(self.organization.is_feature_available("feature-doesnt-exist"))
@patch("posthog.models.organization.License.PLANS", {"enterprise": ["whatever"]})
def test_feature_available_self_hosted_no_license(self):
self.assertFalse(self.organization.is_feature_available("whatever"))
self.assertFalse(self.organization.is_feature_available("feature-doesnt-exist"))
@patch("posthog.models.organization.License.PLANS", {"enterprise": ["whatever"]})
@patch("ee.models.license.requests.post")
def test_feature_available_self_hosted_license_expired(self, patch_post):
with freeze_time("2070-01-01T12:00:00.000Z"): # LicensedTestMixin enterprise license expires in 2038
sync_all_organization_available_features() # This is normally ran every hour
self.organization.refresh_from_db()
self.assertFalse(self.organization.is_feature_available("whatever"))