feat(Tenants, Memberships): PRWLR-4719 Add memberships endpoints and security changes (#44)

* feat(SimpleJWT): PRWLR-4717 add djangorestframework-simplejwt dep

* feat(SimpleJWT): PRWLR-4717 add basic configuration and env variables

* feat(Users): PRWLR-4717 add model and security constraints

* feat(Users): PRWLR-4717 add serializers

* feat(Users): PRWLR-4717 add views

* test(Conftest): PRWLR-4717 add user and authenticated client fixtures

* fix(Unit tests): PRWLR-4717 add automated authentication to all unit tests

* fix(Authentication): PRWLR-4717 add authentication class and update tests

* test(Users): PRWLR-4717 add unit tests

* test(Users): PRWLR-4717 add integration tests

* chore(Schema): PRWLR-4717 update API schema

* fix(User): PRWLR-4717 fix password validation

* feat(Validators): PRWLR-4717 add MaxLength password validator

* fix(User): PRWLR-4717 update User model to delete admin fields

* chore(Serializers): PRWLR-4717 add docstrings and update serializers

* chore(Fixtures): PRWLR-4717 add dev user

* feat(Memberships): PRWLR-4719 add membership.Roles postgres enums

* feat(Memberships): PRWLR-4719 add model

* feat(Tenants): PRWLR-4719 add owner membership when creating a new one

* chore(Users): PRWLR-4717 raise DRF NotFound instead of returning response

* chore(Deps): PRWLR-4719 add drf-nested-routers

* feat(Memberships): PRWLR-4719 add serializers, urls and views

* feat(Tenants): PRWLR-4719 add RLS based on memberships

* chore(Views): PRWLR-4719 unify tenant related views dispatch methods

* test(Tenants): PRWLR-4719 add membership to test user when creating tenants

* test(Users): PRWLR-4719 add name field to model

* chore(Deps): PRWLR-4719 add drf-nested-routers

* feat(Memberships): PRWLR-4719 separate membership endpoints

* feat(Memberships): PRWLR-4719 add filters

* test(Memberships): PRWLR-4719 add unit tests

* test(Tenants): PRWLR-4719 add membership unit tests

* chore(API): PRWLR-4719 update spec

* chore(API): PRWLR-4719 update Django dev fixtures

* test(Memberships): PRWLR-4719 add more unit tests

* chore(Memberships): PRWLR-4719 move /memberships to /users/me/

* feat(Users, Tenants, Memberships): PRWLR-4719 update responses and routes

* feat(Memberships): PRWLR-4719 adjust tenant membership view results under membership role

* chore(Scans): PRWLR-4719 rename django fixture
This commit is contained in:
Víctor Fernández Poyatos authored and GitHub committed 2024-09-25 13:12:15 +02:00
1 parent 4a881fd2fd
commit 4c83351b26
19 files changed
+1195 -46

No files matched your search

+43 -2
View File
@@ -15,6 +15,7 @@ from psqlextra.types import PostgresPartitioningMethod
from uuid6 import uuid7
from api.db_utils import (
MemberRoleEnumField,
enum_to_choices,
ProviderEnumField,
StateEnumField,
@@ -27,6 +28,9 @@ from api.db_utils import (
from api.exceptions import ModelValidationError
from api.rls import (
RowLevelSecurityProtectedModel,
)
from api.rls import (
Tenant,
RowLevelSecurityConstraint,
BaseSecurityConstraint,
)
@@ -39,7 +43,7 @@ class StatusChoices(models.TextChoices):
"""
This list is based on the finding status in the Prowler CLI.
However it adds another state, MUTED, which is not in the CLI.
However, it adds another state, MUTED, which is not in the CLI.
"""
FAIL = "FAIL", _("Fail")
@@ -59,6 +63,7 @@ class StateChoices(models.TextChoices):
class User(AbstractBaseUser):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(max_length=150, validators=[MinLengthValidator(3)])
username = models.CharField(
max_length=150, unique=True, validators=[UnicodeUsernameValidator()]
)
@@ -67,7 +72,7 @@ class User(AbstractBaseUser):
date_joined = models.DateTimeField(auto_now_add=True, editable=False)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
REQUIRED_FIELDS = ["name", "email"]
objects = CustomUserManager()
@@ -82,6 +87,42 @@ class User(AbstractBaseUser):
]
class Membership(models.Model):
class RoleChoices(models.TextChoices):
OWNER = "owner", _("Owner")
MEMBER = "member", _("Member")
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="memberships",
related_query_name="membership",
)
tenant = models.ForeignKey(
Tenant,
on_delete=models.CASCADE,
related_name="memberships",
related_query_name="membership",
)
role = MemberRoleEnumField(choices=RoleChoices.choices, default=RoleChoices.MEMBER)
date_joined = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "memberships"
constraints = [
models.UniqueConstraint(
fields=("user", "tenant"),
name="unique_resources_by_membership",
),
BaseSecurityConstraint(
name="statements_on_%(class)s",
statements=["SELECT", "INSERT", "UPDATE", "DELETE"],
),
]
class Provider(RowLevelSecurityProtectedModel):
class ProviderChoices(models.TextChoices):
AWS = "aws", _("AWS")