Example #1
0
class Team(models.Model):
    """
    Team model.

    Team is can be formed by one or more Users.
    Each User can be a member of multiple Teams.
    Each Team is linked to exactly one Account.
    """

    account = models.ForeignKey(
        Account,
        on_delete=models.CASCADE,
        help_text="Account to which the Team is linked to. Each Team can be linked to only one account.",
        related_name="teams",
    )

    name = models.TextField(blank=False, null=False, help_text="Name of the team")

    description = models.TextField(blank=True, null=True, help_text="Team description")

    members = models.ManyToManyField(
        "auth.User",
        help_text="Team members. Each User can be a member of multiple Teams.",
    )

    def __str__(self) -> str:
        return self.name
Example #2
0
class ProductExtension(models.Model):
    """Add extra properties to a `Product` since we don't have control of that model."""

    product = models.OneToOneField(
        djstripe.models.Product, on_delete=models.PROTECT, related_name="extension"
    )
    allowances = models.TextField(
        help_text="Allowances granted in JSON format."
    )  # Another contender for JSONField
    tag_line = models.TextField(help_text="A short tag line for the product.")
    is_purchasable = models.BooleanField(
        null=False,
        default=True,
        help_text="Can this Produce be purchased, False means only can be bought with "
        "a coupon.",
    )
Example #3
0
class AccountRole(models.Model):
    """Roles linked to the Account, depending on their `AccountPermissionType`."""

    name = models.TextField(
        null=False,
        blank=False,
        help_text="The name of the account role e.g 'Account admin'",
    )

    permissions = models.ManyToManyField(
        AccountPermission,
        related_name="roles",
        help_text="One or more account permissions that the role has e.g `ADMINISTER`.",
    )

    def permissions_text(self) -> typing.Set[str]:
        return {permission.type for permission in self.permissions.all()}

    def permissions_types(self) -> typing.Set[AccountPermissionType]:
        return set(map(lambda p: AccountPermissionType(p), self.permissions_text()))

    @classmethod
    def roles_with_permission(cls, permission_type: AccountPermissionType) -> QuerySet:
        """Query for a list of `AccountRoles` that have the given permission_type `AccountPermissionType`."""
        # TODO: This is a good candidate for a long cache
        permission = AccountPermission.objects.get(type=permission_type.value)
        return cls.objects.filter(permissions=permission)

    def __str__(self) -> str:
        return self.name
Example #4
0
class AccountPermission(models.Model):
    """
    Model implementing `AccountPermissionType`s.

    It is necessary to have this as a database model because an
    `AccountRole` can have multiple permissions.
    """

    type = models.TextField(
        null=False,
        blank=False,
        choices=AccountPermissionType.as_choices(),
        unique=True,
        help_text="An account permission type.",
    )

    def __str__(self) -> str:
        return self.type
Example #5
0
class Account(models.Model):
    """
    Account model.

    Accounts are the entity against which resource usage is metered.
    Every user has their own personal account.
    Users can create additional accounts.
    """

    name = models.SlugField(
        null=False,
        blank=False,
        unique=True,
        help_text="Name of the account. Must be unique.",
    )

    logo = models.ImageField(
        null=True,
        blank=True,
        help_text="Logo for the account. Please use an image that is 100 x 100 px or smaller.",
    )

    theme = models.TextField(
        null=True,
        blank=True,
        help_text="The name of the theme to use as the default when generating content for this account."
        # In the future this may be a path to a Thema compatible theme hosted on the Hub or elsewhere.
        # Because of that, it is not a ChoiceField based on the list of names in `assets.thema.themes`.
    )

    hosts = models.TextField(
        null=True,
        blank=True,
        help_text="A space separated list of valid hosts for the account."
        "Used for setting Content Security Policy headers when serving content for this account.",
    )

    def save(self, *args, **kwargs) -> None:
        self.name = clean_slug(self.name, SlugType.ACCOUNT)

        super(Account, self).save(*args, **kwargs)

    def get_administrators(self) -> typing.Iterable[User]:
        """Return users who have administrative permissions on the account."""
        ownership_roles: typing.Set[
            AccountUserRole
        ] = set()  # cache the roles that have ownership perms
        users: typing.Set[AbstractUser] = set()

        for user_role in self.user_roles.all():
            user_has_role = False

            if user_role.role.pk in ownership_roles:
                user_has_role = True
            elif AccountPermissionType.ADMINISTER in user_role.role.permissions_types():
                ownership_roles.add(user_role.role.pk)
                user_has_role = True

            if user_has_role:
                users.add(user_role.user)

        return users

    def __str__(self) -> str:
        return self.name

    @property
    def plan(self) -> typing.Union[djstripe.models.Plan, dict]:
        subscription = self.subscriptions.filter(subscription__status="active").first()

        if subscription is None:
            from accounts.static_product_config import FREE_PLAN

            return FREE_PLAN

        return subscription.subscription.plan