karrio-server-core 2025.5rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of karrio-server-core might be problematic. Click here for more details.
- karrio/server/conf.py +54 -0
- karrio/server/core/__init__.py +3 -0
- karrio/server/core/admin.py +1 -0
- karrio/server/core/apps.py +10 -0
- karrio/server/core/authentication.py +313 -0
- karrio/server/core/context_processors.py +12 -0
- karrio/server/core/datatypes.py +369 -0
- karrio/server/core/dataunits.py +156 -0
- karrio/server/core/exceptions.py +200 -0
- karrio/server/core/fields.py +12 -0
- karrio/server/core/filters.py +823 -0
- karrio/server/core/gateway.py +720 -0
- karrio/server/core/management/commands/cli.py +19 -0
- karrio/server/core/management/commands/create_oauth_client.py +41 -0
- karrio/server/core/middleware.py +95 -0
- karrio/server/core/migrations/0001_initial.py +28 -0
- karrio/server/core/migrations/0002_apilogindex.py +69 -0
- karrio/server/core/migrations/0003_apilogindex_test_mode.py +62 -0
- karrio/server/core/migrations/0004_metafield.py +74 -0
- karrio/server/core/migrations/0005_alter_metafield_type_alter_metafield_value.py +23 -0
- karrio/server/core/migrations/__init__.py +0 -0
- karrio/server/core/models/__init__.py +48 -0
- karrio/server/core/models/base.py +70 -0
- karrio/server/core/models/entity.py +22 -0
- karrio/server/core/models/metafield.py +144 -0
- karrio/server/core/models/third_party.py +21 -0
- karrio/server/core/oauth_validators.py +171 -0
- karrio/server/core/permissions.py +37 -0
- karrio/server/core/renderers.py +11 -0
- karrio/server/core/router.py +3 -0
- karrio/server/core/serializers.py +1898 -0
- karrio/server/core/signals.py +57 -0
- karrio/server/core/tests.py +98 -0
- karrio/server/core/urls.py +12 -0
- karrio/server/core/utils.py +479 -0
- karrio/server/core/validators.py +416 -0
- karrio/server/core/views/__init__.py +2 -0
- karrio/server/core/views/api.py +133 -0
- karrio/server/core/views/metadata.py +44 -0
- karrio/server/core/views/oauth.py +74 -0
- karrio/server/core/views/references.py +82 -0
- karrio/server/core/views/schema.py +310 -0
- karrio/server/filters/__init__.py +2 -0
- karrio/server/filters/abstract.py +26 -0
- karrio/server/iam/__init__.py +0 -0
- karrio/server/iam/admin.py +3 -0
- karrio/server/iam/apps.py +21 -0
- karrio/server/iam/migrations/0001_initial.py +33 -0
- karrio/server/iam/migrations/__init__.py +0 -0
- karrio/server/iam/models.py +48 -0
- karrio/server/iam/permissions.py +134 -0
- karrio/server/iam/serializers.py +39 -0
- karrio/server/iam/signals.py +20 -0
- karrio/server/iam/tests.py +3 -0
- karrio/server/iam/views.py +3 -0
- karrio/server/openapi.py +75 -0
- karrio/server/providers/__init__.py +1 -0
- karrio/server/providers/admin.py +364 -0
- karrio/server/providers/apps.py +10 -0
- karrio/server/providers/extension/__init__.py +1 -0
- karrio/server/providers/extension/models/__init__.py +1 -0
- karrio/server/providers/extension/models/allied_express.py +22 -0
- karrio/server/providers/extension/models/allied_express_local.py +22 -0
- karrio/server/providers/extension/models/amazon_shipping.py +27 -0
- karrio/server/providers/extension/models/aramex.py +25 -0
- karrio/server/providers/extension/models/asendia_us.py +21 -0
- karrio/server/providers/extension/models/australiapost.py +20 -0
- karrio/server/providers/extension/models/boxknight.py +19 -0
- karrio/server/providers/extension/models/bpost.py +21 -0
- karrio/server/providers/extension/models/canadapost.py +21 -0
- karrio/server/providers/extension/models/canpar.py +19 -0
- karrio/server/providers/extension/models/chronopost.py +22 -0
- karrio/server/providers/extension/models/colissimo.py +22 -0
- karrio/server/providers/extension/models/dhl_express.py +23 -0
- karrio/server/providers/extension/models/dhl_parcel_de.py +25 -0
- karrio/server/providers/extension/models/dhl_poland.py +22 -0
- karrio/server/providers/extension/models/dhl_universal.py +19 -0
- karrio/server/providers/extension/models/dicom.py +20 -0
- karrio/server/providers/extension/models/dpd.py +37 -0
- karrio/server/providers/extension/models/dpdhl.py +26 -0
- karrio/server/providers/extension/models/easypost.py +20 -0
- karrio/server/providers/extension/models/eshipper.py +21 -0
- karrio/server/providers/extension/models/fedex.py +25 -0
- karrio/server/providers/extension/models/fedex_ws.py +24 -0
- karrio/server/providers/extension/models/freightcom.py +21 -0
- karrio/server/providers/extension/models/generic.py +35 -0
- karrio/server/providers/extension/models/geodis.py +22 -0
- karrio/server/providers/extension/models/hay_post.py +22 -0
- karrio/server/providers/extension/models/laposte.py +19 -0
- karrio/server/providers/extension/models/locate2u.py +22 -0
- karrio/server/providers/extension/models/nationex.py +22 -0
- karrio/server/providers/extension/models/purolator.py +21 -0
- karrio/server/providers/extension/models/roadie.py +18 -0
- karrio/server/providers/extension/models/royalmail.py +19 -0
- karrio/server/providers/extension/models/sendle.py +22 -0
- karrio/server/providers/extension/models/tge.py +63 -0
- karrio/server/providers/extension/models/tnt.py +23 -0
- karrio/server/providers/extension/models/ups.py +23 -0
- karrio/server/providers/extension/models/usps.py +23 -0
- karrio/server/providers/extension/models/usps_international.py +23 -0
- karrio/server/providers/extension/models/usps_wt.py +24 -0
- karrio/server/providers/extension/models/usps_wt_international.py +24 -0
- karrio/server/providers/extension/models/zoom2u.py +23 -0
- karrio/server/providers/migrations/0001_initial.py +140 -0
- karrio/server/providers/migrations/0002_carrier_active.py +18 -0
- karrio/server/providers/migrations/0003_auto_20201230_0820.py +24 -0
- karrio/server/providers/migrations/0004_auto_20210212_0554.py +178 -0
- karrio/server/providers/migrations/0005_auto_20210212_0555.py +18 -0
- karrio/server/providers/migrations/0006_australiapostsettings.py +29 -0
- karrio/server/providers/migrations/0007_auto_20210213_0206.py +21 -0
- karrio/server/providers/migrations/0008_auto_20210214_0409.py +30 -0
- karrio/server/providers/migrations/0009_auto_20210308_0302.py +18 -0
- karrio/server/providers/migrations/0010_auto_20210409_0852.py +32 -0
- karrio/server/providers/migrations/0011_auto_20210409_0853.py +21 -0
- karrio/server/providers/migrations/0012_alter_carrier_options.py +17 -0
- karrio/server/providers/migrations/0013_tntsettings.py +30 -0
- karrio/server/providers/migrations/0014_auto_20210612_1608.py +46 -0
- karrio/server/providers/migrations/0015_auto_20210615_1601.py +28 -0
- karrio/server/providers/migrations/0016_alter_purolatorsettings_user_token.py +18 -0
- karrio/server/providers/migrations/0017_auto_20210805_0359.py +1293 -0
- karrio/server/providers/migrations/0018_alter_fedexsettings_user_key.py +18 -0
- karrio/server/providers/migrations/0019_dhlpolandsettings_servicelevel.py +65 -0
- karrio/server/providers/migrations/0020_genericsettings_labeltemplate.py +52 -0
- karrio/server/providers/migrations/0021_auto_20211231_2353.py +40 -0
- karrio/server/providers/migrations/0022_carrier_metadata.py +18 -0
- karrio/server/providers/migrations/0023_auto_20220124_1916.py +27 -0
- karrio/server/providers/migrations/0024_alter_genericsettings_custom_carrier_name.py +19 -0
- karrio/server/providers/migrations/0025_alter_servicelevel_service_code.py +19 -0
- karrio/server/providers/migrations/0026_auto_20220208_0132.py +59 -0
- karrio/server/providers/migrations/0027_auto_20220304_1340.py +29 -0
- karrio/server/providers/migrations/0028_auto_20220323_1500.py +33 -0
- karrio/server/providers/migrations/0029_easypostsettings.py +27 -0
- karrio/server/providers/migrations/0030_amazonmwssettings.py +29 -0
- karrio/server/providers/migrations/0031_delete_amazonmwssettings.py +18 -0
- karrio/server/providers/migrations/0032_alter_carrier_test.py +18 -0
- karrio/server/providers/migrations/0033_auto_20220708_1350.py +22 -0
- karrio/server/providers/migrations/0034_amazonmwssettings_dpdhlsettings.py +47 -0
- karrio/server/providers/migrations/0035_alter_carrier_capabilities.py +43 -0
- karrio/server/providers/migrations/0036_upsfreightsettings.py +31 -0
- karrio/server/providers/migrations/0037_chronopostsettings.py +29 -0
- karrio/server/providers/migrations/0038_alter_genericsettings_label_template.py +19 -0
- karrio/server/providers/migrations/0039_auto_20220906_0612.py +23 -0
- karrio/server/providers/migrations/0040_dpdhlsettings_services.py +18 -0
- karrio/server/providers/migrations/0041_auto_20221105_0705.py +38 -0
- karrio/server/providers/migrations/0042_auto_20221215_1642.py +23 -0
- karrio/server/providers/migrations/0043_alter_genericsettings_account_number_and_more.py +39 -0
- karrio/server/providers/migrations/0044_carrier_carrier_capabilities.py +64 -0
- karrio/server/providers/migrations/0045_alter_carrier_active_alter_carrier_carrier_id.py +31 -0
- karrio/server/providers/migrations/0046_remove_dpdhlsettings_signature_and_more.py +41 -0
- karrio/server/providers/migrations/0047_dpdsettings.py +286 -0
- karrio/server/providers/migrations/0048_servicelevel_min_weight_servicelevel_transit_days_and_more.py +64 -0
- karrio/server/providers/migrations/0049_boxknightsettings_geodissettings_lapostesettings_and_more.py +156 -0
- karrio/server/providers/migrations/0050_carrier_is_system_alter_carrier_metadata_and_more.py +106 -0
- karrio/server/providers/migrations/0051_rename_username_upssettings_client_id_and_more.py +31 -0
- karrio/server/providers/migrations/0052_alter_upssettings_account_number_and_more.py +20 -0
- karrio/server/providers/migrations/0053_locate2usettings.py +281 -0
- karrio/server/providers/migrations/0054_zoom2usettings.py +280 -0
- karrio/server/providers/migrations/0055_rename_amazonmwssettings_amazonshippingsettings_and_more.py +44 -0
- karrio/server/providers/migrations/0056_asendiaussettings_geodissettings_code_client_and_more.py +75 -0
- karrio/server/providers/migrations/0057_alter_servicelevel_weight_unit_belgianpostsettings.py +51 -0
- karrio/server/providers/migrations/0058_alliedexpresssettings.py +38 -0
- karrio/server/providers/migrations/0059_ratesheet.py +81 -0
- karrio/server/providers/migrations/0060_belgianpostsettings_rate_sheet_and_more.py +73 -0
- karrio/server/providers/migrations/0061_alliedexpresssettings_service_type.py +17 -0
- karrio/server/providers/migrations/0062_sendlesettings_account_country_code.py +257 -0
- karrio/server/providers/migrations/0063_servicelevel_metadata.py +25 -0
- karrio/server/providers/migrations/0064_alliedexpresslocalsettings.py +43 -0
- karrio/server/providers/migrations/0065_servicelevel_carrier_service_code_and_more.py +66 -0
- karrio/server/providers/migrations/0066_rename_fedexsettings_fedexwssettings_and_more.py +28 -0
- karrio/server/providers/migrations/0067_fedexsettings.py +283 -0
- karrio/server/providers/migrations/0068_fedexsettings_track_api_key_and_more.py +38 -0
- karrio/server/providers/migrations/0069_alter_canadapostsettings_contract_id_and_more.py +23 -0
- karrio/server/providers/migrations/0070_tgesettings_alter_carrier_capabilities.py +65 -0
- karrio/server/providers/migrations/0071_alter_tgesettings_my_toll_token.py +18 -0
- karrio/server/providers/migrations/0072_rename_eshippersettings_eshipperxmlsettings_and_more.py +28 -0
- karrio/server/providers/migrations/0073_delete_eshipperxmlsettings.py +41 -0
- karrio/server/providers/migrations/0074_eshippersettings.py +38 -0
- karrio/server/providers/migrations/0075_haypostsettings.py +40 -0
- karrio/server/providers/migrations/0076_rename_customer_registration_id_uspsinternationalsettings_account_number_and_more.py +125 -0
- karrio/server/providers/migrations/0077_uspswtinternationalsettings_uspswtsettings_and_more.py +165 -0
- karrio/server/providers/migrations/0078_auto_20240813_1552.py +120 -0
- karrio/server/providers/migrations/0079_alter_carrier_options_alter_ratesheet_created_by.py +31 -0
- karrio/server/providers/migrations/0080_alter_aramexsettings_account_country_code_and_more.py +3025 -0
- karrio/server/providers/migrations/0081_remove_alliedexpresssettings_carrier_ptr_and_more.py +338 -0
- karrio/server/providers/migrations/__init__.py +0 -0
- karrio/server/providers/models/__init__.py +17 -0
- karrio/server/providers/models/carrier.py +309 -0
- karrio/server/providers/models/config.py +30 -0
- karrio/server/providers/models/service.py +62 -0
- karrio/server/providers/models/sheet.py +60 -0
- karrio/server/providers/models/template.py +39 -0
- karrio/server/providers/models/utils.py +58 -0
- karrio/server/providers/router.py +3 -0
- karrio/server/providers/serializers/__init__.py +3 -0
- karrio/server/providers/serializers/base.py +277 -0
- karrio/server/providers/signals.py +27 -0
- karrio/server/providers/tests.py +3 -0
- karrio/server/providers/urls.py +11 -0
- karrio/server/providers/views/__init__.py +0 -0
- karrio/server/providers/views/carriers.py +269 -0
- karrio/server/providers/views/connections.py +176 -0
- karrio/server/samples.py +352 -0
- karrio/server/serializers/__init__.py +2 -0
- karrio/server/serializers/abstract.py +506 -0
- karrio/server/tracing/__init__.py +0 -0
- karrio/server/tracing/admin.py +63 -0
- karrio/server/tracing/apps.py +8 -0
- karrio/server/tracing/migrations/0001_initial.py +41 -0
- karrio/server/tracing/migrations/0002_auto_20220710_1307.py +22 -0
- karrio/server/tracing/migrations/0003_auto_20221105_0317.py +43 -0
- karrio/server/tracing/migrations/0004_tracingrecord_carrier_account_idx.py +24 -0
- karrio/server/tracing/migrations/0005_optimise_tracingrecord_request_log_idx.py +25 -0
- karrio/server/tracing/migrations/0006_alter_tracingrecord_options_and_more.py +49 -0
- karrio/server/tracing/migrations/__init__.py +0 -0
- karrio/server/tracing/models.py +80 -0
- karrio/server/tracing/tests.py +3 -0
- karrio/server/tracing/utils.py +112 -0
- karrio/server/user/__init__.py +0 -0
- karrio/server/user/admin.py +96 -0
- karrio/server/user/apps.py +7 -0
- karrio/server/user/forms.py +35 -0
- karrio/server/user/migrations/0001_initial.py +41 -0
- karrio/server/user/migrations/0002_token.py +29 -0
- karrio/server/user/migrations/0003_token_test_mode.py +20 -0
- karrio/server/user/migrations/0004_group.py +26 -0
- karrio/server/user/migrations/0005_token_label.py +21 -0
- karrio/server/user/migrations/0006_workspaceconfig.py +63 -0
- karrio/server/user/migrations/__init__.py +0 -0
- karrio/server/user/models.py +203 -0
- karrio/server/user/serializers.py +46 -0
- karrio/server/user/templates/registration/login.html +108 -0
- karrio/server/user/templates/registration/registration_confirm_email.html +10 -0
- karrio/server/user/templates/registration/registration_confirm_email.txt +3 -0
- karrio/server/user/tests.py +3 -0
- karrio/server/user/urls.py +10 -0
- karrio/server/user/utils.py +60 -0
- karrio/server/user/views.py +9 -0
- karrio_server_core-2025.5rc1.dist-info/METADATA +32 -0
- karrio_server_core-2025.5rc1.dist-info/RECORD +241 -0
- karrio_server_core-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_server_core-2025.5rc1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import yaml # type: ignore
|
|
2
|
+
from rest_framework import status
|
|
3
|
+
from rest_framework.decorators import api_view, renderer_classes, permission_classes
|
|
4
|
+
from rest_framework.permissions import AllowAny
|
|
5
|
+
from rest_framework.response import Response
|
|
6
|
+
from rest_framework.request import Request
|
|
7
|
+
from rest_framework.renderers import JSONRenderer
|
|
8
|
+
from django.urls import path
|
|
9
|
+
from django.conf import settings
|
|
10
|
+
|
|
11
|
+
from karrio.server.conf import FEATURE_FLAGS
|
|
12
|
+
from karrio.server.core.router import router
|
|
13
|
+
import karrio.server.core.dataunits as dataunits
|
|
14
|
+
import karrio.server.openapi as openapi
|
|
15
|
+
|
|
16
|
+
ENDPOINT_ID = "&&" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
|
17
|
+
BASE_PATH = getattr(settings, "BASE_PATH", "")
|
|
18
|
+
References = openapi.OpenApiResponse(
|
|
19
|
+
openapi.OpenApiTypes.OBJECT,
|
|
20
|
+
examples=[
|
|
21
|
+
openapi.OpenApiExample(
|
|
22
|
+
name="References",
|
|
23
|
+
value={
|
|
24
|
+
"VERSION": "",
|
|
25
|
+
"APP_NAME": "",
|
|
26
|
+
"APP_WEBSITE": "",
|
|
27
|
+
"HOST": "",
|
|
28
|
+
"ADMIN": "",
|
|
29
|
+
"OPENAPI": "",
|
|
30
|
+
"GRAPHQL": "",
|
|
31
|
+
**{flag: True for flag in FEATURE_FLAGS},
|
|
32
|
+
"ADDRESS_AUTO_COMPLETE": {},
|
|
33
|
+
"countries": {},
|
|
34
|
+
"currencies": {},
|
|
35
|
+
"carriers": {},
|
|
36
|
+
"customs_content_type": {},
|
|
37
|
+
"incoterms": {},
|
|
38
|
+
"states": {},
|
|
39
|
+
"services": {},
|
|
40
|
+
"connection_configs": {},
|
|
41
|
+
"service_names": {},
|
|
42
|
+
"options": {},
|
|
43
|
+
"option_names": {},
|
|
44
|
+
"package_presets": {},
|
|
45
|
+
"packaging_types": {},
|
|
46
|
+
"payment_types": {},
|
|
47
|
+
"carrier_capabilities": {},
|
|
48
|
+
"service_levels": {},
|
|
49
|
+
"integration_status": {},
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@openapi.extend_schema(
|
|
57
|
+
auth=[],
|
|
58
|
+
methods=["get"],
|
|
59
|
+
tags=["API"],
|
|
60
|
+
operation_id=f"{ENDPOINT_ID}data",
|
|
61
|
+
summary="Data References",
|
|
62
|
+
responses={200: References},
|
|
63
|
+
)
|
|
64
|
+
@api_view(["GET"])
|
|
65
|
+
@permission_classes([AllowAny])
|
|
66
|
+
@renderer_classes([JSONRenderer])
|
|
67
|
+
def references(request: Request):
|
|
68
|
+
try:
|
|
69
|
+
reduced = bool(yaml.safe_load(request.query_params.get("reduced", "true")))
|
|
70
|
+
|
|
71
|
+
return Response(
|
|
72
|
+
dataunits.contextual_reference(reduced=reduced),
|
|
73
|
+
status=status.HTTP_200_OK,
|
|
74
|
+
)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
import logging
|
|
77
|
+
|
|
78
|
+
logging.exception(e)
|
|
79
|
+
raise e
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
router.urls.append(path("references", references))
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import jinja2
|
|
2
|
+
import django.conf as django
|
|
3
|
+
import drf_spectacular.views as views
|
|
4
|
+
import rest_framework.response as response
|
|
5
|
+
|
|
6
|
+
import django.urls as urls
|
|
7
|
+
import karrio.server.conf as conf
|
|
8
|
+
import karrio.server.core.dataunits as dataunits
|
|
9
|
+
|
|
10
|
+
VERSION = getattr(django.settings, "VERSION", "")
|
|
11
|
+
non_null = lambda items: [i for i in items if i is not None]
|
|
12
|
+
RedocView = views.SpectacularRedocView.as_view(
|
|
13
|
+
url_name="shipping-openapi",
|
|
14
|
+
template_name="openapi/openapi.html",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ShippingOpenAPIView(views.SpectacularAPIView):
|
|
19
|
+
def _get_schema_response(self, request):
|
|
20
|
+
version = (
|
|
21
|
+
self.api_version or request.version or self._get_version_parameter(request)
|
|
22
|
+
)
|
|
23
|
+
generator = self.generator_class(
|
|
24
|
+
urlconf=self.urlconf, api_version=version, patterns=self.patterns
|
|
25
|
+
)
|
|
26
|
+
data = generator.get_schema(request=request, public=self.serve_public)
|
|
27
|
+
|
|
28
|
+
data["tags"] = render_tags(request, conf.settings.APP_NAME)
|
|
29
|
+
data["components"]["securitySchemes"] = {
|
|
30
|
+
k: v
|
|
31
|
+
for k, v in data["components"]["securitySchemes"].items()
|
|
32
|
+
if k in ["JWT", "OAuth2", "Token", "TokenBasic"]
|
|
33
|
+
}
|
|
34
|
+
data["info"] = dict(
|
|
35
|
+
description=render_schema_description(conf.settings.APP_NAME),
|
|
36
|
+
title=f"{conf.settings.APP_NAME} API",
|
|
37
|
+
version=conf.settings.VERSION,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
return response.Response(
|
|
41
|
+
data=data,
|
|
42
|
+
headers={
|
|
43
|
+
"Content-Disposition": f'inline; filename="{self._get_filename(request, version)}"'
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
urlpatterns = [
|
|
49
|
+
urls.path(
|
|
50
|
+
django.settings.OPEN_API_PATH,
|
|
51
|
+
RedocView,
|
|
52
|
+
name="schema-rapi",
|
|
53
|
+
),
|
|
54
|
+
urls.path(
|
|
55
|
+
"shipping-openapi",
|
|
56
|
+
ShippingOpenAPIView.as_view(),
|
|
57
|
+
name="shipping-openapi",
|
|
58
|
+
),
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def render_schema_description(APP_NAME):
|
|
63
|
+
return f"""
|
|
64
|
+
{APP_NAME} is a multi-carrier shipping API that simplifies the integration of logistics carrier services.
|
|
65
|
+
|
|
66
|
+
The {APP_NAME} API is organized around REST. Our API has predictable resource-oriented URLs, accepts JSON-encoded
|
|
67
|
+
request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
|
|
68
|
+
|
|
69
|
+
The {APP_NAME} API differs for every account as we release new versions.
|
|
70
|
+
These docs are customized to your version of the API.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## Versioning
|
|
74
|
+
|
|
75
|
+
When backwards-incompatible changes are made to the API, a new, dated version is released.
|
|
76
|
+
The current version is `{VERSION}`.
|
|
77
|
+
|
|
78
|
+
Read our API changelog to learn more about backwards compatibility.
|
|
79
|
+
|
|
80
|
+
As a precaution, use API versioning to check a new API version before committing to an upgrade.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## Environments
|
|
84
|
+
|
|
85
|
+
The {APP_NAME} API offer the possibility to create and retrieve certain objects in `test_mode`.
|
|
86
|
+
In development, it is therefore possible to add carrier connections, get live rates,
|
|
87
|
+
buy labels, create trackers and schedule pickups in `test_mode`.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
## Pagination
|
|
91
|
+
|
|
92
|
+
All top-level API resources have support for bulk fetches via "list" API methods. For instance, you can list addresses,
|
|
93
|
+
list shipments, and list trackers. These list API methods share a common structure, taking at least these
|
|
94
|
+
two parameters: limit, and offset.
|
|
95
|
+
|
|
96
|
+
{APP_NAME} utilizes offset-based pagination via the offset and limit parameters.
|
|
97
|
+
Both parameters take a number as value (see below) and return objects in reverse chronological order.
|
|
98
|
+
The offset parameter returns objects listed after an index.
|
|
99
|
+
The limit parameter take a limit on the number of objects to be returned from 1 to 100.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{{
|
|
104
|
+
"count": 100,
|
|
105
|
+
"next": "/v1/shipments?limit=25&offset=50",
|
|
106
|
+
"previous": "/v1/shipments?limit=25&offset=25",
|
|
107
|
+
"results": [
|
|
108
|
+
{{ ... }},
|
|
109
|
+
]
|
|
110
|
+
}}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Metadata
|
|
114
|
+
|
|
115
|
+
Updateable {APP_NAME} objects—including Shipment and Order have a metadata parameter.
|
|
116
|
+
You can use this parameter to attach key-value data to these {APP_NAME} objects.
|
|
117
|
+
|
|
118
|
+
Metadata is useful for storing additional, structured information on an object.
|
|
119
|
+
As an example, you could store your user's full name and corresponding unique identifier
|
|
120
|
+
from your system on a {APP_NAME} Order object.
|
|
121
|
+
|
|
122
|
+
Do not store any sensitive information as metadata.
|
|
123
|
+
|
|
124
|
+
## Authentication
|
|
125
|
+
|
|
126
|
+
API keys are used to authenticate requests. You can view and manage your API keys in the Dashboard.
|
|
127
|
+
|
|
128
|
+
Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret
|
|
129
|
+
API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
|
|
130
|
+
|
|
131
|
+
Authentication to the API is performed via HTTP Basic Auth. Provide your API token as
|
|
132
|
+
the basic auth username value. You do not need to provide a password.
|
|
133
|
+
|
|
134
|
+
```shell
|
|
135
|
+
$ curl https://instance.api.com/v1/shipments \\
|
|
136
|
+
-u key_xxxxxx:
|
|
137
|
+
# The colon prevents curl from asking for a password.
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
If you need to authenticate via bearer auth (e.g., for a cross-origin request),
|
|
141
|
+
use `-H "Authorization: Token key_xxxxxx"` instead of `-u key_xxxxxx`.
|
|
142
|
+
|
|
143
|
+
All API requests must be made over [HTTPS](http://en.wikipedia.org/wiki/HTTP_Secure).
|
|
144
|
+
API requests without authentication will also fail.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def render_reference_descriptions(request):
|
|
149
|
+
refs = dataunits.contextual_reference(request, reduced=False)
|
|
150
|
+
|
|
151
|
+
def format_preset(preset: dict):
|
|
152
|
+
vals = [
|
|
153
|
+
str(v)
|
|
154
|
+
for v in [
|
|
155
|
+
preset.get("width"),
|
|
156
|
+
preset.get("height"),
|
|
157
|
+
preset.get("length"),
|
|
158
|
+
]
|
|
159
|
+
if v is not None
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
return f'{" x ".join(vals)} {preset.get("dimension_unit").lower()}'
|
|
163
|
+
|
|
164
|
+
template = """## Carriers
|
|
165
|
+
| Carrier Name | Display Name |
|
|
166
|
+
| ------------ | ------------ |
|
|
167
|
+
{% for carrier, name in refs.get("carriers", {}).items() -%}{% if carrier != "generic" -%}
|
|
168
|
+
| {{ carrier }} | {{ name }} |
|
|
169
|
+
{% endif -%}{% endfor %}
|
|
170
|
+
---
|
|
171
|
+
## Services
|
|
172
|
+
The following service level codes can be used to reference specific rates
|
|
173
|
+
when purchasing shipping labels using single call label creation.
|
|
174
|
+
You can also find all of the possible service levels for each of your carrier
|
|
175
|
+
accounts by using [this endpoint](#operation/&&get_services).
|
|
176
|
+
{% for carrier, services in refs.get("services", {}).items() -%}{% if carrier != "generic" -%}
|
|
177
|
+
### {{ refs.get("carriers", {}).get(carrier, "") }}
|
|
178
|
+
| Code | Service Name |
|
|
179
|
+
| ------------ | ------------ |
|
|
180
|
+
{% for code, name in services.items() -%}
|
|
181
|
+
| {{ code }} | {{ name }} |
|
|
182
|
+
{% endfor %}
|
|
183
|
+
{% endif -%}{% endfor %}
|
|
184
|
+
---
|
|
185
|
+
## Parcel Templates
|
|
186
|
+
Use any of the following templates when you ship with special carrier packaging.
|
|
187
|
+
{% for carrier, presets in refs.get("package_presets", {}).items() -%}
|
|
188
|
+
### {{ refs.get("carriers", {}).get(carrier, "") }}
|
|
189
|
+
| Code | Dimensions |
|
|
190
|
+
| ------------ | ------------ |
|
|
191
|
+
{% for code, preset in presets.items() -%}
|
|
192
|
+
| {{ code }} | {{ format_preset(preset) }} |
|
|
193
|
+
{% endfor %}
|
|
194
|
+
{% endfor %}
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
return jinja2.Template(template).render(refs=refs, format_preset=format_preset)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def render_tags(request, APP_NAME):
|
|
201
|
+
return non_null(
|
|
202
|
+
[
|
|
203
|
+
{
|
|
204
|
+
"name": "API",
|
|
205
|
+
"description": """API instance metadata resources.
|
|
206
|
+
""",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "Auth",
|
|
210
|
+
"description": """API authentication resources.
|
|
211
|
+
""",
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "Carriers",
|
|
215
|
+
"description": f"""This is an object representing your {APP_NAME} carrier extension.
|
|
216
|
+
You can retrieve all supported carrier extensions available.
|
|
217
|
+
""",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"name": "Connections",
|
|
221
|
+
"description": f"""This is an object representing your {APP_NAME} carrier connections.
|
|
222
|
+
You can retrieve all carrier connections available to your account.
|
|
223
|
+
The `carrier_id` is a friendly name you assign to your connection.
|
|
224
|
+
""",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "Addresses",
|
|
228
|
+
"description": f"""This is an object representing your {APP_NAME} shipping address.
|
|
229
|
+
You can retrieve all addresses related to your {APP_NAME} account.
|
|
230
|
+
Address objects are linked to your shipment history, and can be used for recurring shipping
|
|
231
|
+
to / from the same locations.
|
|
232
|
+
""",
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "Parcels",
|
|
236
|
+
"description": f"""This is an object representing your {APP_NAME} shipping parcel.
|
|
237
|
+
Parcel objects are linked to your shipment history, and can be used for recurring shipping
|
|
238
|
+
using the same packaging.
|
|
239
|
+
""",
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"name": "Shipments",
|
|
243
|
+
"description": f"""This is an object representing your {APP_NAME} shipment.
|
|
244
|
+
A Shipment guides you through process of preparing and purchasing a label for an order.
|
|
245
|
+
A Shipment transitions through multiple statuses throughout its lifetime as the package
|
|
246
|
+
shipped makes its journey to it's destination.
|
|
247
|
+
""",
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"name": "Documents",
|
|
251
|
+
"description": f"""This is an object representing your {APP_NAME} document upload record.
|
|
252
|
+
A Document upload record keep traces of shipping trade documents uploaded to carriers
|
|
253
|
+
to fast track customs and border processing.
|
|
254
|
+
""",
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"name": "Manifests",
|
|
258
|
+
"description": f"""This is an object representing your {APP_NAME} manifest details.
|
|
259
|
+
Some carriers require manifests to be created after labels are generated.
|
|
260
|
+
A manifest is a summary of all the shipments that are being sent out.
|
|
261
|
+
""",
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"name": "Trackers",
|
|
265
|
+
"description": f"""This is an object representing your {APP_NAME} shipment tracker.
|
|
266
|
+
A shipment tracker is an object attached to a shipment by it's tracking number.
|
|
267
|
+
The tracker provide the latest tracking status and events associated with a shipment
|
|
268
|
+
""",
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"name": "Pickups",
|
|
272
|
+
"description": f"""This is an object representing your {APP_NAME} pickup booking.
|
|
273
|
+
You can retrieve all pickup booked historically for your {APP_NAME} account shipments.
|
|
274
|
+
""",
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"name": "Proxy",
|
|
278
|
+
"description": f"""In some scenarios, all we need is to send request to a carrier using the {APP_NAME} unified API.
|
|
279
|
+
The Proxy API comes handy for that as it turn {APP_NAME} into a simple middleware that converts and
|
|
280
|
+
validate your request and simply forward it to the shipping carrier server.<br/>
|
|
281
|
+
**Note:**<br/>
|
|
282
|
+
When using the proxy API, no objects are created in the {APP_NAME} system.
|
|
283
|
+
excpet API logs and tracing records for debugging purposes.
|
|
284
|
+
""",
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"name": "Orders",
|
|
288
|
+
"description": f"""This is an object representing your {APP_NAME} order.
|
|
289
|
+
You can create {APP_NAME} orders to organize your shipments and ship line items separately.
|
|
290
|
+
""",
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "Webhooks",
|
|
294
|
+
"description": f"""This is an object representing your {APP_NAME} webhook.
|
|
295
|
+
You can configure webhook endpoints via the API to be notified about events happen in your
|
|
296
|
+
{APP_NAME} account.
|
|
297
|
+
""",
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"name": "Batches",
|
|
301
|
+
"description": f"""This is an object representing your {APP_NAME} batch operation.
|
|
302
|
+
You can retrieve all batch operations historically for your {APP_NAME} account.
|
|
303
|
+
""",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"name": "Reference & Enums",
|
|
307
|
+
"description": render_reference_descriptions(request),
|
|
308
|
+
},
|
|
309
|
+
]
|
|
310
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import django_filters
|
|
2
|
+
import karrio.lib as lib
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CharInFilter(django_filters.BaseInFilter, django_filters.CharFilter):
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FilterSet(django_filters.FilterSet):
|
|
10
|
+
def __init__(self, data=None, queryset=None, *, request=None, prefix=None):
|
|
11
|
+
data = {
|
|
12
|
+
**data,
|
|
13
|
+
**{
|
|
14
|
+
key: (
|
|
15
|
+
",".join(val)
|
|
16
|
+
if self.base_filters.get(key).__class__ == CharInFilter
|
|
17
|
+
else val
|
|
18
|
+
)
|
|
19
|
+
for key, val in data.items()
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
super().__init__(data, queryset, request=request, prefix=prefix)
|
|
23
|
+
|
|
24
|
+
def to_dict(self):
|
|
25
|
+
self.form.is_valid()
|
|
26
|
+
return lib.to_dict(self.form.cleaned_data)
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class IamConfig(AppConfig):
|
|
6
|
+
name = "karrio.server.iam"
|
|
7
|
+
verbose_name = _("IAM")
|
|
8
|
+
default_auto_field = "django.db.models.BigAutoField"
|
|
9
|
+
|
|
10
|
+
def ready(self):
|
|
11
|
+
from karrio.server.core import utils
|
|
12
|
+
from karrio.server.iam import signals, permissions
|
|
13
|
+
|
|
14
|
+
@utils.skip_on_commands()
|
|
15
|
+
def _init():
|
|
16
|
+
signals.register_all()
|
|
17
|
+
|
|
18
|
+
# Setup default permission groups and apply to existing orgs on start up
|
|
19
|
+
utils.run_on_all_tenants(permissions.setup_groups)()
|
|
20
|
+
|
|
21
|
+
_init()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 3.2.14 on 2022-09-03 12:25
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
initial = True
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
('user', '0004_group'),
|
|
13
|
+
('auth', '0012_alter_user_first_name_max_length'),
|
|
14
|
+
('contenttypes', '0002_remove_content_type_name'),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name='ContextPermission',
|
|
20
|
+
fields=[
|
|
21
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
22
|
+
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
|
23
|
+
('object_pk', models.CharField(db_index=True, max_length=50, verbose_name='object pk')),
|
|
24
|
+
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype', verbose_name='content type')),
|
|
25
|
+
('groups', models.ManyToManyField(blank=True, help_text='The groups this user context belongs to. A user will get all permissions granted to each of their groups.', related_name='context', related_query_name='context', to='user.Group', verbose_name='groups')),
|
|
26
|
+
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user context.', related_name='context', related_query_name='context', to='auth.Permission', verbose_name='user context permissions')),
|
|
27
|
+
],
|
|
28
|
+
options={
|
|
29
|
+
'verbose_name': 'context permission',
|
|
30
|
+
'verbose_name_plural': 'context permission',
|
|
31
|
+
},
|
|
32
|
+
),
|
|
33
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.contrib.auth.models import PermissionsMixin, Permission
|
|
3
|
+
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
4
|
+
from django.utils.translation import gettext_lazy as _
|
|
5
|
+
|
|
6
|
+
import karrio.server.user.models as user
|
|
7
|
+
|
|
8
|
+
User = user.User
|
|
9
|
+
Group = user.Group
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ContextPermission(PermissionsMixin):
|
|
13
|
+
class Meta:
|
|
14
|
+
verbose_name = _("context permission")
|
|
15
|
+
verbose_name_plural = _("context permission")
|
|
16
|
+
|
|
17
|
+
def __str__(self) -> str:
|
|
18
|
+
return f"{self.object_pk} - {self.content_type}"
|
|
19
|
+
|
|
20
|
+
content_type = models.ForeignKey(
|
|
21
|
+
to="contenttypes.ContentType",
|
|
22
|
+
on_delete=models.CASCADE,
|
|
23
|
+
related_name="+",
|
|
24
|
+
verbose_name=_("content type"),
|
|
25
|
+
)
|
|
26
|
+
object_pk = models.CharField(
|
|
27
|
+
db_index=True, max_length=50, verbose_name=_("object pk")
|
|
28
|
+
)
|
|
29
|
+
content_object = GenericForeignKey("content_type", "object_pk")
|
|
30
|
+
groups = models.ManyToManyField(
|
|
31
|
+
Group,
|
|
32
|
+
verbose_name=_("groups"),
|
|
33
|
+
blank=True,
|
|
34
|
+
help_text=_(
|
|
35
|
+
"The groups this user context belongs to. A user will get all permissions "
|
|
36
|
+
"granted to each of their groups."
|
|
37
|
+
),
|
|
38
|
+
related_name="context",
|
|
39
|
+
related_query_name="context",
|
|
40
|
+
)
|
|
41
|
+
user_permissions = models.ManyToManyField(
|
|
42
|
+
Permission,
|
|
43
|
+
verbose_name=_("user context permissions"),
|
|
44
|
+
blank=True,
|
|
45
|
+
help_text=_("Specific permissions for this user context."),
|
|
46
|
+
related_name="context",
|
|
47
|
+
related_query_name="context",
|
|
48
|
+
)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import logging
|
|
3
|
+
from django.db import models
|
|
4
|
+
from django.contrib.auth import get_user_model
|
|
5
|
+
from django.contrib.auth.models import Permission
|
|
6
|
+
|
|
7
|
+
import karrio.server.core.utils as utils
|
|
8
|
+
import karrio.server.user.models as users
|
|
9
|
+
import karrio.server.iam.serializers as serializers
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
User = get_user_model()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@utils.skip_on_loadata
|
|
16
|
+
@utils.async_wrapper
|
|
17
|
+
@utils.tenant_aware
|
|
18
|
+
def setup_groups(**_):
|
|
19
|
+
"""This function create all standard group permissions if they don't exsist."""
|
|
20
|
+
print("> setting up permissions")
|
|
21
|
+
|
|
22
|
+
# manage_apps
|
|
23
|
+
setup_group(
|
|
24
|
+
serializers.PermissionGroup.manage_apps.name,
|
|
25
|
+
permissions=Permission.objects.filter(content_type__app_label="apps"),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# manage_carriers
|
|
29
|
+
setup_group(
|
|
30
|
+
serializers.PermissionGroup.manage_carriers.name,
|
|
31
|
+
permissions=[
|
|
32
|
+
*Permission.objects.filter(content_type__app_label="providers"),
|
|
33
|
+
*Permission.objects.filter(
|
|
34
|
+
models.Q(content_type__app_label="orgs")
|
|
35
|
+
& models.Q(name__icontains="carrier")
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
override=True,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# manage_orders
|
|
42
|
+
setup_group(
|
|
43
|
+
serializers.PermissionGroup.manage_orders.name,
|
|
44
|
+
permissions=Permission.objects.filter(content_type__app_label="orders"),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# manage_team
|
|
48
|
+
setup_group(
|
|
49
|
+
serializers.PermissionGroup.manage_team.name,
|
|
50
|
+
permissions=(
|
|
51
|
+
Permission.objects.filter(
|
|
52
|
+
content_type__app_label="orgs", name__icontains="organization"
|
|
53
|
+
).exclude(name__icontains="owner")
|
|
54
|
+
),
|
|
55
|
+
override=True,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# manage_org_owner
|
|
59
|
+
setup_group(
|
|
60
|
+
serializers.PermissionGroup.manage_org_owner.name,
|
|
61
|
+
permissions=Permission.objects.filter(
|
|
62
|
+
content_type__model="OrganizationOwner".lower()
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# manage_webhooks
|
|
67
|
+
setup_group(
|
|
68
|
+
serializers.PermissionGroup.manage_webhooks.name,
|
|
69
|
+
permissions=Permission.objects.filter(content_type__model="Webhook".lower()),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# manage_data
|
|
73
|
+
setup_group(
|
|
74
|
+
serializers.PermissionGroup.manage_data.name,
|
|
75
|
+
permissions=[
|
|
76
|
+
*Permission.objects.filter(
|
|
77
|
+
content_type__app_label__in=["data", "graph", "documents"]
|
|
78
|
+
),
|
|
79
|
+
*Permission.objects.filter(
|
|
80
|
+
content_type__app_label="audit", name__icontains="view"
|
|
81
|
+
),
|
|
82
|
+
*Permission.objects.filter(
|
|
83
|
+
content_type__app_label="rest_framework_tracking",
|
|
84
|
+
name__icontains="view",
|
|
85
|
+
),
|
|
86
|
+
],
|
|
87
|
+
override=True,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# manage_shipments
|
|
91
|
+
setup_group(
|
|
92
|
+
serializers.PermissionGroup.manage_shipments.name,
|
|
93
|
+
permissions=[
|
|
94
|
+
*Permission.objects.filter(content_type__app_label="manager"),
|
|
95
|
+
*Permission.objects.filter(
|
|
96
|
+
models.Q(content_type__app_label="orgs")
|
|
97
|
+
& (
|
|
98
|
+
models.Q(name__icontains="address")
|
|
99
|
+
| models.Q(name__icontains="parcel")
|
|
100
|
+
| models.Q(name__icontains="commodity")
|
|
101
|
+
| models.Q(name__icontains="customs")
|
|
102
|
+
| models.Q(name__icontains="pickup")
|
|
103
|
+
| models.Q(name__icontains="tracker")
|
|
104
|
+
| models.Q(name__icontains="shipment")
|
|
105
|
+
)
|
|
106
|
+
),
|
|
107
|
+
],
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# manage_system
|
|
111
|
+
setup_group(
|
|
112
|
+
serializers.PermissionGroup.manage_system.name,
|
|
113
|
+
permissions=Permission.objects.filter(
|
|
114
|
+
content_type__app_label__in=[
|
|
115
|
+
"admin",
|
|
116
|
+
"user",
|
|
117
|
+
"pricing",
|
|
118
|
+
"providers",
|
|
119
|
+
"audit",
|
|
120
|
+
"database",
|
|
121
|
+
"rest_framework_tracking",
|
|
122
|
+
]
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def setup_group(
|
|
128
|
+
name: str, permissions: typing.List[Permission], override: bool = False
|
|
129
|
+
):
|
|
130
|
+
group, created = users.Group.objects.get_or_create(name=name)
|
|
131
|
+
|
|
132
|
+
if created or override:
|
|
133
|
+
group.permissions.set(permissions)
|
|
134
|
+
group.save()
|