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

99 lines
3.3 KiB
Python
Raw Normal View History

from typing import Any, List, Optional, cast
import requests
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models.signals import post_save
from django.dispatch.dispatcher import receiver
from django.utils import timezone
from rest_framework import exceptions, status
from posthog.celery import sync_all_organization_available_features
from posthog.constants import AvailableFeature
class LicenseError(exceptions.APIException):
"""
Exception raised for licensing errors.
"""
default_type = "license_error"
default_code = "license_error"
status_code = status.HTTP_400_BAD_REQUEST
default_detail = "There was a problem with your current license."
def __init__(self, code, detail):
self.code = code
self.detail = exceptions._get_error_details(detail, code)
class LicenseManager(models.Manager):
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 create(self, *args: Any, **kwargs: Any) -> "License":
validate = requests.post("https://license.posthog.com/licenses/activate", data={"key": kwargs["key"]})
resp = validate.json()
if not validate.ok:
raise LicenseError(resp["code"], resp["detail"])
kwargs["valid_until"] = resp["valid_until"]
kwargs["plan"] = resp["plan"]
kwargs["max_users"] = resp.get("max_users", 0)
return cast(License, super().create(*args, **kwargs))
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 first_valid(self) -> Optional["License"]:
return cast(Optional[License], (self.filter(valid_until__gte=timezone.now()).first()))
class License(models.Model):
objects: LicenseManager = LicenseManager()
Personal API keys and Zapier integration (#1281) * Add missing migration * Add generate_random_token() model util * Move PublicTokenAuthentication to utils * Make use of generate_random_token * Add User.personal_access_token field * Add PersonalAccessTokenAuthentication * Fix PublicTokenAuthentication * Fix migration and auth import * Add personal_access_token to user API * Update Setup.js * Support trailing slash in API * Improve PAT auth quality * Add django-rest-hooks requirement * Update settings.py for rest_hooks * Fix django-rest-hooks requirement * Bring back API routes with no double trailing slash * Rename posthog.api.team to team_user * Add API TODO * Ad PAT auth with X-PAT HTTP header * Replace User.personal_access_token with PersonalAPIKey model * Fix PersonalAPIKey max_lengths * Describe posthog.models.utils.generate_random_token better * Add personal_api_key to API * Add authenticate_header to PersonalAPIKeyAuthentication * Add hook API endpoint * Use django.utils.timezone in place of datetime.datetime * Add Personal API Keys to Setup * Sort personal_api_keys in ORM * Add Action.on_perform() * Remove requirements.txt comment * Add a * Add REST hook tasks * Optimize PersonalAPIKeyAuthentication query * Add a trailing slash version of /e endpoint * Add team field to PersonalAPIKey model * Add personal API key support to capture endpoint, get_cached_from_token * Reject personal API keys from inactive users * Add extra_properties_json field to /capture * Improve PAK auth header regex * Use custom hook model * Deliver hooks * Handle action.on_perform * Consolidate userLogic in userLogic.tsx * Update PersonalAPIKeys.js * Make PersonalAPIKey foreign keys read-only * Update requirements/dev.txt * Make PersonalAPIKeys TSX * Fix conflict * Fix migration * Fix minor mishaps * Update and fix tests * Use CharField of random 32 bits as hook.id * Fix conflicting migrations * Fix ValidationError in HookSerializer.validate_event * Use query param in /api/event/actions ID filtering * Rename endpoint `hook` to `hooks` * Satisfy mypy * Add tests * Use DRF serialization in action_defined and annotation_created triggers * Update migration leafs * Make mypy ignore rest_hooks * Update Django signal receiver names * Update TS dependencies * Revert "Update TS dependencies" This reverts commit 7fc26fefcdc16e630e1c8fd2c510fd323d97169f. * Add field user to Hook model * Update migration leafs * Fix circular import * Fix some code * Install git before running pip install in Dockerfiles * Improve personal API keys UI * Satisfy mypy * Reword key label placeholder * Add personal API key support to /api/user/* Unfortunately these endpoints are still limited by CSRF protections at the moment, so not accessible outside PostHog itself. * Improve PersonalAPIKeyAuthentication and add CsrfOrKeyViewMiddleware * Run collectstatic before test * Don't install dev dependencies in CI * Update dependency installation order in CI * Fix bug and describe PersonalAPIKeyAuthentication * Fix CI issues * Fix typing issues * Fix more typing issues * Use /api/personal_api_keys to list keys * Move REST hooks (and therefore Zapier) to ee/ * Refactor personal API logic with kea-loaders * Add "More about API authentication in PostHog docs." * Update PersonalAPIKeys.tsx * Use TestMixin * Fix "Authentication" that should've been "Authorization" * Add option to skip self.client.force_login in API tests * Include team_id and user_id in personal API key serialization * Update test_hooks.py * Add personal API key tests * Remove leftover * Make ee.settings override posthog.settings * Don't directly import from models * Remove unused imports * Fix mypy issues * Fix HOOK_DELIVERER * Use decorator for /api/user PAK auth * Don't fire REST hook if user doesn't have "zapier" feature * Import Optional * Reword to "premium Zapier" * Make mypy happy * Fix test_delete_personal_api_key * Fix misclick * Fix and test /capture with personal API key * Make mypy happy * Remove extra_properties_json * Resolve migrations * Remove apt-utils * Optimize and test PAK user.is_active filtering * Replace DEBUG true with 1 * Remove unused instance_id * Improve typing * Fix deletion toast * Refactor CopyToClipboard and use it in PAKs * Use toast.success * Update migrations * Fix migration * Fix migrations * Complete merge Co-authored-by: Tim Glaser <tim@glsr.nl>
2020-08-26 10:34:57 +02:00
created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True)
plan: models.CharField = models.CharField(max_length=200)
valid_until: models.DateTimeField = models.DateTimeField()
key: models.CharField = models.CharField(max_length=200)
max_users: models.IntegerField = models.IntegerField(default=None, null=True) # None = no restriction
2021-10-14 14:13:37 +02:00
SCALE_PLAN = "scale"
SCALE_FEATURES = [
AvailableFeature.ZAPIER,
AvailableFeature.ORGANIZATIONS_PROJECTS,
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
AvailableFeature.PROJECT_BASED_PERMISSIONING,
AvailableFeature.GOOGLE_LOGIN,
AvailableFeature.DASHBOARD_COLLABORATION,
AvailableFeature.INGESTION_TAXONOMY,
2021-10-14 14:13:37 +02:00
]
ENTERPRISE_PLAN = "enterprise"
ENTERPRISE_FEATURES = SCALE_FEATURES + [
AvailableFeature.SAML,
]
PLANS = {SCALE_PLAN: SCALE_FEATURES, ENTERPRISE_PLAN: ENTERPRISE_FEATURES}
@property
def available_features(self) -> List[AvailableFeature]:
return self.PLANS.get(self.plan, [])
def get_licensed_users_available() -> Optional[int]:
"""
Returns the number of user slots available that can be created based on the instance's current license.
Not relevant for cloud users.
`None` means unlimited users.
"""
license = License.objects.first_valid()
from posthog.models import OrganizationInvite
if license:
if license.max_users is None:
return None
users_left = license.max_users - get_user_model().objects.count() - OrganizationInvite.objects.count()
return max(users_left, 0)
return None
@receiver(post_save, sender=License)
def license_saved(sender, instance, created, raw, using, **kwargs):
sync_all_organization_available_features()