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,19 @@
|
|
|
1
|
+
from django.core.management.base import BaseCommand
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
class Command(BaseCommand):
|
|
5
|
+
help = "Run kcli commands from the Django CLI."
|
|
6
|
+
|
|
7
|
+
def run_from_argv(self, argv):
|
|
8
|
+
# Remove the management command name ("kcli") from argv
|
|
9
|
+
kcli_args = argv[2:]
|
|
10
|
+
try:
|
|
11
|
+
from kcli.__main__ import app
|
|
12
|
+
# Call the Typer app with the forwarded arguments
|
|
13
|
+
app(prog_name="karrio cli", args=kcli_args)
|
|
14
|
+
except SystemExit as e:
|
|
15
|
+
# Typer uses SystemExit for normal CLI exit, so suppress traceback
|
|
16
|
+
sys.exit(e.code)
|
|
17
|
+
except ImportError:
|
|
18
|
+
self.stderr.write(self.style.ERROR("Could not import kcli CLI app."))
|
|
19
|
+
sys.exit(1)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from django.core.management.base import BaseCommand
|
|
2
|
+
from oauth2_provider.models import Application
|
|
3
|
+
from django.contrib.auth import get_user_model
|
|
4
|
+
|
|
5
|
+
User = get_user_model()
|
|
6
|
+
|
|
7
|
+
class Command(BaseCommand):
|
|
8
|
+
help = 'Creates an OAuth2 client application'
|
|
9
|
+
|
|
10
|
+
def add_arguments(self, parser):
|
|
11
|
+
parser.add_argument('--name', required=True)
|
|
12
|
+
parser.add_argument('--client_id', required=True)
|
|
13
|
+
parser.add_argument('--client_secret', required=True)
|
|
14
|
+
parser.add_argument('--redirect_uri', required=True)
|
|
15
|
+
parser.add_argument('--user_email', required=True)
|
|
16
|
+
|
|
17
|
+
def handle(self, *args, **options):
|
|
18
|
+
try:
|
|
19
|
+
user = User.objects.get(email=options['user_email'])
|
|
20
|
+
except User.DoesNotExist:
|
|
21
|
+
self.stdout.write(self.style.ERROR(f"User with email {options['user_email']} does not exist"))
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
# Check if application with this client_id already exists
|
|
25
|
+
app, created = Application.objects.update_or_create(
|
|
26
|
+
client_id=options['client_id'],
|
|
27
|
+
defaults={
|
|
28
|
+
'name': options['name'],
|
|
29
|
+
'user': user,
|
|
30
|
+
'client_type': Application.CLIENT_CONFIDENTIAL,
|
|
31
|
+
'authorization_grant_type': Application.GRANT_AUTHORIZATION_CODE,
|
|
32
|
+
'client_secret': options['client_secret'],
|
|
33
|
+
'redirect_uris': options['redirect_uri'],
|
|
34
|
+
'skip_authorization': True,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if created:
|
|
39
|
+
self.stdout.write(self.style.SUCCESS(f"Successfully created OAuth2 application: {options['name']}"))
|
|
40
|
+
else:
|
|
41
|
+
self.stdout.write(self.style.SUCCESS(f"Successfully updated OAuth2 application: {options['name']}"))
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import threading
|
|
3
|
+
from django.db.models import Q
|
|
4
|
+
from django.http import HttpResponse
|
|
5
|
+
from karrio.core.utils import Tracer
|
|
6
|
+
from karrio.server.conf import settings
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CreatorAccess:
|
|
10
|
+
def __call__(self, context, key: str = "created_by", **kwargs) -> Q:
|
|
11
|
+
user_key = f"{key}_id"
|
|
12
|
+
user = getattr(context, "user", None)
|
|
13
|
+
|
|
14
|
+
return Q(**{user_key: getattr(user, "id", None)})
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class WideAccess:
|
|
18
|
+
def __call__(self, *args, **kwargs) -> Q:
|
|
19
|
+
return Q()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UserToken:
|
|
23
|
+
def __call__(self, context, **kwargs) -> dict:
|
|
24
|
+
return dict(user=getattr(context, "user", context))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SessionContext:
|
|
28
|
+
_threadmap: dict = {}
|
|
29
|
+
|
|
30
|
+
def __init__(self, get_response):
|
|
31
|
+
self.get_response = get_response
|
|
32
|
+
# One-time configuration and initialization.
|
|
33
|
+
|
|
34
|
+
def __call__(self, request):
|
|
35
|
+
# Code to be executed for each request before
|
|
36
|
+
# the view (and later middleware) are called.
|
|
37
|
+
request.tracer = Tracer()
|
|
38
|
+
self._threadmap[threading.get_ident()] = request
|
|
39
|
+
|
|
40
|
+
response = self.get_response(request)
|
|
41
|
+
|
|
42
|
+
# Code to be executed for each request/response after
|
|
43
|
+
# the view is called.
|
|
44
|
+
try:
|
|
45
|
+
self._save_tracing_records(request, schema=settings.schema)
|
|
46
|
+
del self._threadmap[threading.get_ident()]
|
|
47
|
+
except KeyError:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
return response
|
|
51
|
+
|
|
52
|
+
def _save_tracing_records(self, request, schema: str = None):
|
|
53
|
+
from karrio.server.tracing.utils import save_tracing_records
|
|
54
|
+
|
|
55
|
+
save_tracing_records(request, schema=schema)
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def get_current_request(cls):
|
|
59
|
+
return cls._threadmap.get(threading.get_ident())
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class NonHtmlDebugToolbarMiddleware:
|
|
63
|
+
"""
|
|
64
|
+
The Django Debug Toolbar usually only works for views that return HTML.
|
|
65
|
+
This middleware wraps any non-HTML response in HTML if the request
|
|
66
|
+
has a 'debug' query parameter (e.g. http://localhost/foo?debug)
|
|
67
|
+
Special handling for json (pretty printing) and
|
|
68
|
+
binary data (only show data length)
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, get_response):
|
|
72
|
+
self.get_response = get_response
|
|
73
|
+
|
|
74
|
+
def __call__(self, request):
|
|
75
|
+
response = self.get_response(request)
|
|
76
|
+
|
|
77
|
+
if request.GET.get("debug") == "":
|
|
78
|
+
if response["Content-Type"] == "application/octet-stream":
|
|
79
|
+
new_content = (
|
|
80
|
+
"<html><body>Binary Data, "
|
|
81
|
+
"Length: {}</body></html>".format(len(response.content))
|
|
82
|
+
)
|
|
83
|
+
response = HttpResponse(new_content)
|
|
84
|
+
elif response["Content-Type"] != "text/html":
|
|
85
|
+
content = response.content
|
|
86
|
+
try:
|
|
87
|
+
json_ = json.loads(content)
|
|
88
|
+
content = json.dumps(json_, sort_keys=True, indent=2)
|
|
89
|
+
except ValueError:
|
|
90
|
+
pass
|
|
91
|
+
response = HttpResponse(
|
|
92
|
+
"<html><body><pre>{}" "</pre></body></html>".format(content)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return response
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by Django 3.2.3 on 2021-05-18 10:53
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
import karrio.server.core.models.base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
initial = True
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
('rest_framework_tracking', '0011_auto_20201117_2016'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.CreateModel(
|
|
17
|
+
name='APILog',
|
|
18
|
+
fields=[
|
|
19
|
+
],
|
|
20
|
+
options={
|
|
21
|
+
'ordering': ['-requested_at'],
|
|
22
|
+
'proxy': True,
|
|
23
|
+
'indexes': [],
|
|
24
|
+
'constraints': [],
|
|
25
|
+
},
|
|
26
|
+
bases=('rest_framework_tracking.apirequestlog', karrio.server.core.models.base.ControlledAccessModel),
|
|
27
|
+
),
|
|
28
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Generated by Django 3.2.13 on 2022-07-18 12:05
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
import karrio.server.core.utils as utils
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def forwards_func(apps, schema_editor):
|
|
9
|
+
db_alias = schema_editor.connection.alias
|
|
10
|
+
APILog = apps.get_model("core", "APILog")
|
|
11
|
+
APILogIndex = apps.get_model("core", "APILogIndex")
|
|
12
|
+
logs = APILog.objects.using(db_alias).filter(response__isnull=False).iterator()
|
|
13
|
+
|
|
14
|
+
for log in logs:
|
|
15
|
+
response = utils.failsafe(
|
|
16
|
+
lambda: utils.DP.to_dict(utils.DP.to_dict(log.response))
|
|
17
|
+
)
|
|
18
|
+
entity_id = utils.failsafe(lambda: response["id"])
|
|
19
|
+
|
|
20
|
+
if entity_id is not None:
|
|
21
|
+
_index = APILogIndex(
|
|
22
|
+
apirequestlog_ptr=log,
|
|
23
|
+
entity_id=entity_id,
|
|
24
|
+
)
|
|
25
|
+
_index.save_base(raw=True)
|
|
26
|
+
|
|
27
|
+
if isinstance(response, dict):
|
|
28
|
+
log.response = utils.DP.jsonify(response)
|
|
29
|
+
log.save()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def reverse_func(apps, schema_editor):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Migration(migrations.Migration):
|
|
37
|
+
dependencies = [
|
|
38
|
+
("rest_framework_tracking", "0011_auto_20201117_2016"),
|
|
39
|
+
("core", "0001_initial"),
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
operations = [
|
|
43
|
+
migrations.CreateModel(
|
|
44
|
+
name="APILogIndex",
|
|
45
|
+
fields=[
|
|
46
|
+
(
|
|
47
|
+
"apirequestlog_ptr",
|
|
48
|
+
models.OneToOneField(
|
|
49
|
+
auto_created=True,
|
|
50
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
51
|
+
parent_link=True,
|
|
52
|
+
primary_key=True,
|
|
53
|
+
serialize=False,
|
|
54
|
+
to="rest_framework_tracking.apirequestlog",
|
|
55
|
+
),
|
|
56
|
+
),
|
|
57
|
+
(
|
|
58
|
+
"entity_id",
|
|
59
|
+
models.CharField(db_index=True, max_length=50, null=True),
|
|
60
|
+
),
|
|
61
|
+
],
|
|
62
|
+
options={
|
|
63
|
+
"verbose_name": "API Request Log",
|
|
64
|
+
"abstract": False,
|
|
65
|
+
},
|
|
66
|
+
bases=("core.apilog",),
|
|
67
|
+
),
|
|
68
|
+
migrations.RunPython(forwards_func, reverse_func),
|
|
69
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Generated by Django 4.1.4 on 2022-12-17 11:46
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import karrio.server.core.utils as utils
|
|
5
|
+
import karrio.lib as lib
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def forwards_func(apps, schema_editor):
|
|
9
|
+
db_alias = schema_editor.connection.alias
|
|
10
|
+
APILog = apps.get_model("core", "APILog")
|
|
11
|
+
APILogIndex = apps.get_model("core", "APILogIndex")
|
|
12
|
+
logs = (
|
|
13
|
+
APILog.objects.using(db_alias)
|
|
14
|
+
.filter(models.Q(response__icontains="test_mode"))
|
|
15
|
+
.iterator()
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
for log in logs:
|
|
19
|
+
response = utils.failsafe(lambda: lib.to_dict(lib.to_dict(log.response)))
|
|
20
|
+
entity_id = utils.failsafe(lambda: response["id"])
|
|
21
|
+
test_mode = utils.failsafe(lambda: response["test_mode"])
|
|
22
|
+
|
|
23
|
+
if test_mode is None and '"test_mode": true' in log.response:
|
|
24
|
+
test_mode = True
|
|
25
|
+
if test_mode is None and '"test_mode": false' in log.response:
|
|
26
|
+
test_mode = False
|
|
27
|
+
|
|
28
|
+
if test_mode is not None and hasattr(log, "apilogindex"):
|
|
29
|
+
log.apilogindex.test_mode = test_mode
|
|
30
|
+
log.apilogindex.save()
|
|
31
|
+
|
|
32
|
+
if hasattr(log, "apilogindex") is False:
|
|
33
|
+
_index = APILogIndex(
|
|
34
|
+
apirequestlog_ptr=log,
|
|
35
|
+
entity_id=entity_id,
|
|
36
|
+
test_mode=test_mode,
|
|
37
|
+
)
|
|
38
|
+
_index.save_base(raw=True)
|
|
39
|
+
|
|
40
|
+
log.response = utils.DP.jsonify(response)
|
|
41
|
+
log.save()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def reverse_func(apps, schema_editor):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Migration(migrations.Migration):
|
|
49
|
+
dependencies = [
|
|
50
|
+
("core", "0002_apilogindex"),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
operations = [
|
|
54
|
+
migrations.AddField(
|
|
55
|
+
model_name="apilogindex",
|
|
56
|
+
name="test_mode",
|
|
57
|
+
field=models.BooleanField(
|
|
58
|
+
default=True, help_text="execution context", null=True
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
migrations.RunPython(forwards_func, reverse_func),
|
|
62
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Generated by Django 4.2.8 on 2024-01-13 22:41
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
import functools
|
|
7
|
+
import karrio.server.core.models.base
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Migration(migrations.Migration):
|
|
11
|
+
dependencies = [
|
|
12
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
13
|
+
("core", "0003_apilogindex_test_mode"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.CreateModel(
|
|
18
|
+
name="Metafield",
|
|
19
|
+
fields=[
|
|
20
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
21
|
+
("updated_at", models.DateTimeField(auto_now=True)),
|
|
22
|
+
(
|
|
23
|
+
"id",
|
|
24
|
+
models.CharField(
|
|
25
|
+
default=functools.partial(
|
|
26
|
+
karrio.server.core.models.base.uuid,
|
|
27
|
+
*(),
|
|
28
|
+
**{"prefix": "metaf_"}
|
|
29
|
+
),
|
|
30
|
+
editable=False,
|
|
31
|
+
max_length=50,
|
|
32
|
+
primary_key=True,
|
|
33
|
+
serialize=False,
|
|
34
|
+
),
|
|
35
|
+
),
|
|
36
|
+
(
|
|
37
|
+
"key",
|
|
38
|
+
models.CharField(db_index=True, max_length=50, verbose_name="name"),
|
|
39
|
+
),
|
|
40
|
+
("value", models.CharField(blank=True, max_length=250, null=True)),
|
|
41
|
+
(
|
|
42
|
+
"type",
|
|
43
|
+
models.CharField(
|
|
44
|
+
choices=[
|
|
45
|
+
("text", "text"),
|
|
46
|
+
("number", "number"),
|
|
47
|
+
("boolean", "boolean"),
|
|
48
|
+
],
|
|
49
|
+
db_index=True,
|
|
50
|
+
default="text",
|
|
51
|
+
max_length=50,
|
|
52
|
+
verbose_name="type",
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
("is_required", models.BooleanField(default=False)),
|
|
56
|
+
(
|
|
57
|
+
"created_by",
|
|
58
|
+
models.ForeignKey(
|
|
59
|
+
blank=True,
|
|
60
|
+
editable=False,
|
|
61
|
+
null=True,
|
|
62
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
63
|
+
to=settings.AUTH_USER_MODEL,
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
],
|
|
67
|
+
options={
|
|
68
|
+
"verbose_name": "Metafield",
|
|
69
|
+
"verbose_name_plural": "Metafields",
|
|
70
|
+
"db_table": "metafield",
|
|
71
|
+
},
|
|
72
|
+
bases=(karrio.server.core.models.base.ControlledAccessModel, models.Model),
|
|
73
|
+
),
|
|
74
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Generated by Django 5.2.3 on 2025-06-19 05:27
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('core', '0004_metafield'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='metafield',
|
|
15
|
+
name='type',
|
|
16
|
+
field=models.CharField(choices=[('text', 'text'), ('number', 'number'), ('boolean', 'boolean'), ('json', 'json'), ('date', 'date'), ('date_time', 'date_time'), ('password', 'password')], db_index=True, default='text', max_length=50, verbose_name='type'),
|
|
17
|
+
),
|
|
18
|
+
migrations.AlterField(
|
|
19
|
+
model_name='metafield',
|
|
20
|
+
name='value',
|
|
21
|
+
field=models.JSONField(blank=True, null=True),
|
|
22
|
+
),
|
|
23
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import yaml
|
|
3
|
+
import typing
|
|
4
|
+
import functools
|
|
5
|
+
|
|
6
|
+
import karrio.lib as lib
|
|
7
|
+
from karrio.server.core.models.base import (
|
|
8
|
+
ControlledAccessModel,
|
|
9
|
+
get_access_filter,
|
|
10
|
+
register_model,
|
|
11
|
+
uuid,
|
|
12
|
+
MetafieldType,
|
|
13
|
+
METAFIELD_TYPE,
|
|
14
|
+
)
|
|
15
|
+
from karrio.server.core.models.third_party import (
|
|
16
|
+
APILog,
|
|
17
|
+
APILogIndex,
|
|
18
|
+
)
|
|
19
|
+
from karrio.server.core.models.metafield import (
|
|
20
|
+
Metafield,
|
|
21
|
+
)
|
|
22
|
+
from karrio.server.core.models.entity import Entity, OwnedEntity
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _identity(value: typing.Any):
|
|
26
|
+
return value
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def field_default(value: typing.Any) -> typing.Callable:
|
|
30
|
+
return functools.partial(_identity, value=value)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def metafields_to_dict(metafields: typing.List[Metafield]) -> dict:
|
|
34
|
+
_values = {}
|
|
35
|
+
|
|
36
|
+
for _ in metafields:
|
|
37
|
+
# Skip metafields with None or empty values
|
|
38
|
+
if _.value is None or _.value == "":
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
if _.type == "number":
|
|
42
|
+
_values.update({_.key: lib.failsafe(lambda: ast.literal_eval(_.value))})
|
|
43
|
+
elif _.type == "boolean":
|
|
44
|
+
_values.update({_.key: lib.failsafe(lambda: bool(yaml.safe_load(_.value)))})
|
|
45
|
+
else:
|
|
46
|
+
_values.update({_.key: _.value})
|
|
47
|
+
|
|
48
|
+
return _values
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import pydoc
|
|
2
|
+
import typing
|
|
3
|
+
import functools
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
from django.db import models
|
|
6
|
+
from django.conf import settings
|
|
7
|
+
|
|
8
|
+
import karrio.lib as lib
|
|
9
|
+
|
|
10
|
+
T = typing.TypeVar("T")
|
|
11
|
+
MODEL_TRANSFORMERS = getattr(settings, "MODEL_TRANSFORMERS", [])
|
|
12
|
+
ACCESS_METHOD = getattr(
|
|
13
|
+
settings,
|
|
14
|
+
"KARRIO_ENTITY_ACCESS_METHOD",
|
|
15
|
+
"karrio.server.core.middleware.WideAccess",
|
|
16
|
+
)
|
|
17
|
+
get_access_filter = pydoc.locate(ACCESS_METHOD)()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def uuid(prefix: str = None):
|
|
21
|
+
return f'{prefix or ""}{uuid4().hex}'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ControlledAccessModel:
|
|
25
|
+
@classmethod
|
|
26
|
+
def access_by(cls: models.Model, context, manager: str = "objects"):
|
|
27
|
+
test_mode = (
|
|
28
|
+
context.get("test_mode")
|
|
29
|
+
if isinstance(context, dict)
|
|
30
|
+
else getattr(context, "test_mode", None)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if hasattr(cls, "created_by"):
|
|
34
|
+
key = "created_by"
|
|
35
|
+
elif hasattr(cls, "actor"):
|
|
36
|
+
key = "actor"
|
|
37
|
+
else:
|
|
38
|
+
key = "user"
|
|
39
|
+
|
|
40
|
+
query = get_access_filter(context, key)
|
|
41
|
+
|
|
42
|
+
if hasattr(cls, "test_mode") and test_mode is not None:
|
|
43
|
+
query = query & models.Q(
|
|
44
|
+
models.Q(test_mode=context.test_mode) | models.Q(test_mode__isnull=True)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
queryset = getattr(cls, manager, cls.objects)
|
|
48
|
+
|
|
49
|
+
return queryset.filter(query)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def register_model(model: T) -> T:
|
|
53
|
+
transform = lambda model, transformer: (
|
|
54
|
+
model if transformer is None else pydoc.locate(transformer)(model)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return functools.reduce(transform, MODEL_TRANSFORMERS, model)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MetafieldType(lib.StrEnum):
|
|
61
|
+
text = "text"
|
|
62
|
+
number = "number"
|
|
63
|
+
boolean = "boolean"
|
|
64
|
+
json = "json"
|
|
65
|
+
date = "date"
|
|
66
|
+
date_time = "date_time"
|
|
67
|
+
password = "password"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
METAFIELD_TYPE = [(c.name, c.name) for c in list(MetafieldType)]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from karrio.server.core.models.base import uuid, ControlledAccessModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Entity(models.Model):
|
|
7
|
+
class Meta:
|
|
8
|
+
abstract = True
|
|
9
|
+
|
|
10
|
+
id = models.CharField(max_length=50, primary_key=True, default=uuid, editable=False)
|
|
11
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
12
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
13
|
+
|
|
14
|
+
def __str__(self):
|
|
15
|
+
return self.id
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OwnedEntity(ControlledAccessModel, Entity):
|
|
19
|
+
class Meta:
|
|
20
|
+
abstract = True
|
|
21
|
+
|
|
22
|
+
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|