Skip to content

Commit

Permalink
(fix) token permissions resolution order and ensure backward compatib…
Browse files Browse the repository at this point in the history
…ility with single token management
  • Loading branch information
danh91 committed Dec 11, 2023
1 parent d8081d3 commit fc91e47
Show file tree
Hide file tree
Showing 17 changed files with 519 additions and 140 deletions.
2 changes: 1 addition & 1 deletion apps/api/karrio/server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2023.9.3
2023.9.4
2 changes: 1 addition & 1 deletion modules/admin/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="karrio.server.admin",
version="2023.9",
version="2023.9.4",
description="Multi-carrier shipping API admin module",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
2 changes: 1 addition & 1 deletion modules/core/karrio/server/core/dataunits.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def contextual_metadata(request: Request):


def contextual_reference(request: Request = None, reduced: bool = True):
import karrio.server.core.validators as validators
import karrio.server.core.gateway as gateway
import karrio.server.core.validators as validators
import karrio.server.core.middleware as middleware

request = request or middleware.SessionContext.get_current_request()
Expand Down
42 changes: 32 additions & 10 deletions modules/core/karrio/server/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,28 @@ def object_type(self):

@property
def permissions(self):
_permissions = self.groups.all().values_list("name", flat=True)
import karrio.server.conf as conf
import karrio.server.iam.models as iam
import karrio.server.core.middleware as middleware

ctx = middleware.SessionContext.get_current_request()
_permissions = []

if conf.settings.MULTI_ORGANIZATIONS and ctx.org is not None:
org_user = ctx.org.organization_users.filter(user_id=self.pk)
_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 []
)

if not any(_permissions):
_permissions = self.groups.all().values_list("name", flat=True)

if not any(_permissions) and self.is_superuser:
return Group.objects.all().values_list("name", flat=True)
Expand Down Expand Up @@ -119,30 +140,31 @@ def permissions(self):

_permissions = []

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

if (
not any(_permissions)
and iam.ContextPermission.objects.filter(object_pk=self.pk).exists()
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=self.pk,
content_type=ContentType.objects.get_for_model(Token),
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
Expand Down
2 changes: 1 addition & 1 deletion modules/core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="karrio.server.core",
version="2023.9.3",
version="2023.9.4",
description="Multi-carrier shipping API Core module",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
1 change: 1 addition & 0 deletions modules/graph/karrio/server/graph/schemas/base/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class UpdateUserInput(utils.BaseInput):

@strawberry.input
class TokenMutationInput(utils.BaseInput):
key: str
password: typing.Optional[str] = strawberry.UNSET
refresh: typing.Optional[bool] = strawberry.UNSET

Expand Down
16 changes: 13 additions & 3 deletions modules/graph/karrio/server/graph/schemas/base/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ class TokenMutation(utils.BaseMutation):
@utils.authentication_required
@utils.authorization_required()
def mutate(
info: Info, refresh: bool = None, password: str = None
info: Info,
key: str = None,
refresh: bool = None,
password: str = None,
) -> "UserUpdateMutation":
tokens = user_models.Token.access_by(info.context.request)
tokens = user_models.Token.access_by(info.context.request).filter(key=key)

if refresh:
if len(password or "") == 0:
Expand All @@ -80,6 +83,9 @@ def mutate(
if any(tokens):
tokens.delete()

else:
return TokenMutation(token=tokens.first()) # type:ignore

token = (
TokenSerializer.map(data={}, context=info.context.request).save().instance
)
Expand All @@ -105,7 +111,11 @@ def mutate(
api_key = TokenSerializer.map(data=data, context=context).save().instance

if any(permissions):
_auth_ctx = getattr(context, "token", context.user)
_auth_ctx = (
context.token
if hasattr(getattr(info.context.request, "token", None), "permissions")
else context.user
)
_ctx_permissions = getattr(_auth_ctx, "permissions", [])
_invalid_permissions = [_ for _ in permissions if _ not in _ctx_permissions]

Expand Down
16 changes: 0 additions & 16 deletions modules/graph/karrio/server/graph/schemas/base/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,6 @@ def permissions(self: User, info) -> typing.Optional[typing.List[str]]:
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

Expand Down
6 changes: 3 additions & 3 deletions modules/graph/karrio/server/graph/tests/test_user_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def test_update_token(self):
}
""",
operation_name="mutate_token",
variables=TOKEN_MUTATION_DATA,
variables={
"data": {"refresh": True, "password": "test", "key": current_token}
},
)
response_data = response.data

Expand All @@ -67,5 +69,3 @@ def test_update_token(self):
}
}
}

TOKEN_MUTATION_DATA = {"data": {"refresh": True, "password": "test"}}
2 changes: 1 addition & 1 deletion modules/graph/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="karrio.server.graph",
version="2023.9.2",
version="2023.9.4",
description="Multi-carrier shipping API Graph module",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
2 changes: 1 addition & 1 deletion modules/pricing/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="karrio.server.pricing",
version="2023.4",
version="2023.9.4",
description="Multi-carrier shipping API Pricing panel",
long_description=long_description,
long_description_content_type="text/markdown",
Expand Down
1 change: 1 addition & 0 deletions packages/types/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6517,6 +6517,7 @@ export interface UpdateAddressTemplateInput {

// null
export interface TokenMutationInput {
key: string;
password?: string | null;
refresh?: boolean | null;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/modals/generate-api-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useAPITokenMutation } from '@karrio/hooks/api-token';
import { useAPIToken, useAPITokenMutation } from '@karrio/hooks/api-token';
import React, { useContext, useRef, useState } from 'react';
import { Notifier, Notify } from '../components/notifier';
import { NotificationType } from '@karrio/types';
Expand All @@ -12,13 +12,14 @@ export const GenerateAPIModal: React.FC<{ children?: React.ReactNode }> = ({ chi
const { loading, setLoading } = useLoader();
const password = useRef<HTMLInputElement>(null);
const { query: { data: { user } = {} } } = useUser();
const { query: { data: { token } = {} } } = useAPIToken();
const [isActive, setIsActive] = useState<boolean>(false);

const handleSubmit = async (evt: React.FormEvent<HTMLFormElement>) => {
evt.preventDefault();
try {
setLoading(true);
await mutation.updateToken.mutateAsync({ refresh: true, password: password.current?.value });
await mutation.updateToken.mutateAsync({ refresh: true, key: token!.key, password: password.current?.value });
setLoading(false);
setIsActive(false);
notify({ type: NotificationType.success, message: "New token generated successfully!" });
Expand Down
96 changes: 51 additions & 45 deletions requirements.build.txt
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
--extra-index-url https://karrio.gateway.scarf.sh/simple/
--extra-index-url https://karrio.gateway.scarf.sh/simple/?sourceBuild
Django==4.2.8

./packages/karrio
./packages/connections/generic
./packages/connections/amazon_shipping
./packages/connections/aramex
./packages/connections/australiapost
./packages/connections/boxknight
./packages/connections/canadapost
./packages/connections/canpar
./packages/connections/chronopost
./packages/connections/dhl_express
./packages/connections/dhl_poland
./packages/connections/dhl_universal
./packages/connections/dicom
./packages/connections/dpd
./packages/connections/dpdhl
./packages/connections/fedex
./packages/connections/geodis
./packages/connections/laposte
./packages/connections/nationex
./packages/connections/purolator
./packages/connections/roadie
./packages/connections/royalmail
./packages/connections/sendle
./packages/connections/tnt
./packages/connections/ups
./packages/connections/usps
./packages/connections/usps_international
# Carrier Extentions modules
-e ./modules/sdk
-e ./modules/connectors/amazon_shipping
-e ./modules/connectors/aramex
-e ./modules/connectors/asendia_us
-e ./modules/connectors/australiapost
-e ./modules/connectors/boxknight
-e ./modules/connectors/bpost
-e ./modules/connectors/canadapost
-e ./modules/connectors/canpar
-e ./modules/connectors/chronopost
-e ./modules/connectors/colissimo
-e ./modules/connectors/dhl_express
-e ./modules/connectors/dhl_poland
-e ./modules/connectors/dhl_universal
-e ./modules/connectors/dicom
-e ./modules/connectors/dpd
-e ./modules/connectors/dpdhl
-e ./modules/connectors/fedex
-e ./modules/connectors/generic
-e ./modules/connectors/geodis
-e ./modules/connectors/laposte
-e ./modules/connectors/nationex
-e ./modules/connectors/purolator
-e ./modules/connectors/roadie
-e ./modules/connectors/royalmail
-e ./modules/connectors/sendle
-e ./modules/connectors/tnt
-e ./modules/connectors/ups
-e ./modules/connectors/usps
-e ./modules/connectors/usps_international

./packages/connections/easypost
./packages/connections/eshipper
./packages/connections/freightcom
./packages/connections/locate2u
./packages/connections/zoom2u
-e ./modules/connectors/easypost
-e ./modules/connectors/eshipper
-e ./modules/connectors/freightcom
-e ./modules/connectors/locate2u
-e ./modules/connectors/zoom2u

./packages/iam
./packages/core
./apps/api
./packages/graph
./packages/apps
./packages/data
./packages/events
./packages/manager
./packages/orders
./packages/proxy
./packages/pricing
./packages/documents

# karrio server modules
-e ./modules/core
-e ./apps/api
-e ./modules/graph
-e ./modules/apps
-e ./modules/data
-e ./modules/events
-e ./modules/manager
-e ./modules/orders
-e ./modules/proxy
-e ./modules/pricing
-e ./modules/documents
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ jwcrypto==1.5.0
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.documents&subdirectory=modules/documents
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.events&subdirectory=modules/events
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.graph&subdirectory=modules/graph
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.iam&subdirectory=modules/iam
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.manager&subdirectory=modules/manager
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.orders&subdirectory=modules/orders
-e git+ssh://git@github.com/karrioapi/karrio.git@c012a19dda60427c24a34c2996bc0122ab0695ed#egg=karrio.server.pricing&subdirectory=modules/pricing
Expand Down
Loading

0 comments on commit fc91e47

Please sign in to comment.