Skip to content

Commit

Permalink
(enhance) Token with label and permissions and add user permission co…
Browse files Browse the repository at this point in the history
…mputation based on context and authentication method
  • Loading branch information
danh91 committed Dec 8, 2023
1 parent e823715 commit 469c372
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 1 deletion.
3 changes: 2 additions & 1 deletion modules/core/karrio/server/user/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ class TokenAdmin(admin.ModelAdmin):
list_display = (
"key",
"user",
"label",
*(["organization"] if settings.MULTI_ORGANIZATIONS else []),
"test_mode",
"created",
)
fields = ("user", "test_mode")
fields = ("user", "label", "test_mode")
ordering = ("-created",)

def get_queryset(self, request):
Expand Down
21 changes: 21 additions & 0 deletions modules/core/karrio/server/user/migrations/0005_token_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.0 on 2023-12-08 05:41

import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("user", "0004_group"),
]

operations = [
migrations.AddField(
model_name="token",
name="label",
field=models.CharField(
default=django.utils.timezone.now, max_length=50, verbose_name="label"
),
preserve_default=False,
),
]
41 changes: 41 additions & 0 deletions modules/core/karrio/server/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.conf import settings
from django.contrib.auth import models as auth
from rest_framework.authtoken import models as authtoken
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _

from karrio.server.core.models import (
Expand Down Expand Up @@ -68,9 +69,14 @@ def delete(self, *args, **kwargs):
def object_type(self):
return "user"

@property
def permissions(self):
return [_.name for _ in self.groups.all()]


@register_model
class Token(authtoken.Token, ControlledAccessModel):
label = models.CharField(_("label"), max_length=50)
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="tokens"
)
Expand All @@ -96,6 +102,41 @@ def organization(self):
def object_type(self):
return "token"

@property
def permissions(self):
import karrio.server.conf as conf
import karrio.server.iam.models as iam

_permissions = []
if iam.ContextPermission.objects.filter(object_pk=self.pk).exists():
_permissions = (
iam.ContextPermission.objects.get(
object_pk=self.pk,
content_type=ContentType.objects.get_for_model(Token),
)
.groups.all()
.values_list("name", flat=True)
)

if (
not any(_permissions)
and conf.settings.MULTI_ORGANIZATIONS
and self.org.exists()
):
org_user = self.org.first().organization_users.filter(user_id=self.user_id)
_permissions = (
iam.ContextPermission.objects.get(
object_pk=org_user.first().pk,
content_type=ContentType.objects.get_for_model(org_user.first()),
)
.groups.all()
.values_list("name", flat=True)
if org_user.exists()
else []
)

return _permissions if any(_permissions) else self.user.permissions


@register_model
class Group(auth.Group):
Expand Down
33 changes: 33 additions & 0 deletions modules/graph/karrio/server/graph/schemas/base/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from django.forms.models import model_to_dict
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
from django.contrib.contenttypes.models import ContentType

import karrio.lib as lib
import karrio.server.iam.models as iam
import karrio.server.core.models as core
import karrio.server.graph.utils as utils
import karrio.server.graph.models as graph
Expand All @@ -31,6 +33,32 @@ class UserType:
date_joined: datetime.datetime
is_superuser: typing.Optional[bool] = strawberry.UNSET
last_login: typing.Optional[datetime.datetime] = strawberry.UNSET
permissions: typing.Optional[typing.List[str]] = strawberry.UNSET

@strawberry.field
def permissions(self: User, info) -> typing.Optional[typing.List[str]]:
# Return permissions from token if exists
if hasattr(getattr(info.context.request, "token", None), "permissions"):
return info.context.request.token.permissions

# Return permissions from org user if multiple orgs context
if hasattr(info.context.request, "org"):
org_user = info.context.request.org.organization_users.filter(
user_id=self.id
)
return (
iam.ContextPermission.objects.get(
object_pk=org_user.first().pk,
content_type=ContentType.objects.get_for_model(org_user.first()),
)
.groups.all()
.values_list("name", flat=True)
if org_user.exists()
else []
)

# Return permissions from user
return info.context.request.user.permissions

@staticmethod
@utils.authentication_required
Expand Down Expand Up @@ -159,9 +187,14 @@ def resolve_list(
@strawberry.type
class TokenType:
object_type: str
label: str
key: str
created: datetime.datetime

@strawberry.field
def permissions(self: "Token", info) -> typing.Optional[typing.List[str]]:
return self.permissions

@staticmethod
@utils.authentication_required
def resolve(info, org_id: typing.Optional[str] = strawberry.UNSET) -> "TokenType":
Expand Down

0 comments on commit 469c372

Please sign in to comment.