karrio-server-core 2025.5__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.
Files changed (213) hide show
  1. karrio/server/conf.py +54 -0
  2. karrio/server/core/__init__.py +3 -0
  3. karrio/server/core/admin.py +1 -0
  4. karrio/server/core/apps.py +10 -0
  5. karrio/server/core/authentication.py +347 -0
  6. karrio/server/core/config.py +31 -0
  7. karrio/server/core/context_processors.py +12 -0
  8. karrio/server/core/datatypes.py +394 -0
  9. karrio/server/core/dataunits.py +187 -0
  10. karrio/server/core/exceptions.py +404 -0
  11. karrio/server/core/fields.py +12 -0
  12. karrio/server/core/filters.py +837 -0
  13. karrio/server/core/gateway.py +1011 -0
  14. karrio/server/core/logging.py +403 -0
  15. karrio/server/core/management/commands/cli.py +19 -0
  16. karrio/server/core/management/commands/create_oauth_client.py +41 -0
  17. karrio/server/core/management/commands/runserver.py +5 -0
  18. karrio/server/core/middleware.py +197 -0
  19. karrio/server/core/migrations/0001_initial.py +28 -0
  20. karrio/server/core/migrations/0002_apilogindex.py +69 -0
  21. karrio/server/core/migrations/0003_apilogindex_test_mode.py +62 -0
  22. karrio/server/core/migrations/0004_metafield.py +74 -0
  23. karrio/server/core/migrations/0005_alter_metafield_type_alter_metafield_value.py +23 -0
  24. karrio/server/core/migrations/0006_add_api_log_requested_at_index.py +22 -0
  25. karrio/server/core/migrations/__init__.py +0 -0
  26. karrio/server/core/models/__init__.py +48 -0
  27. karrio/server/core/models/base.py +103 -0
  28. karrio/server/core/models/entity.py +24 -0
  29. karrio/server/core/models/metafield.py +144 -0
  30. karrio/server/core/models/third_party.py +21 -0
  31. karrio/server/core/oauth_validators.py +170 -0
  32. karrio/server/core/permissions.py +36 -0
  33. karrio/server/core/renderers.py +11 -0
  34. karrio/server/core/router.py +3 -0
  35. karrio/server/core/serializers.py +1971 -0
  36. karrio/server/core/signals.py +55 -0
  37. karrio/server/core/telemetry.py +573 -0
  38. karrio/server/core/tests.py +99 -0
  39. karrio/server/core/tests_resource_token.py +411 -0
  40. karrio/server/core/urls.py +12 -0
  41. karrio/server/core/utils.py +1025 -0
  42. karrio/server/core/validators.py +264 -0
  43. karrio/server/core/views/__init__.py +2 -0
  44. karrio/server/core/views/api.py +133 -0
  45. karrio/server/core/views/metadata.py +44 -0
  46. karrio/server/core/views/oauth.py +75 -0
  47. karrio/server/core/views/references.py +82 -0
  48. karrio/server/core/views/schema.py +310 -0
  49. karrio/server/filters/__init__.py +2 -0
  50. karrio/server/filters/abstract.py +26 -0
  51. karrio/server/iam/__init__.py +0 -0
  52. karrio/server/iam/admin.py +3 -0
  53. karrio/server/iam/apps.py +21 -0
  54. karrio/server/iam/migrations/0001_initial.py +33 -0
  55. karrio/server/iam/migrations/__init__.py +0 -0
  56. karrio/server/iam/models.py +48 -0
  57. karrio/server/iam/permissions.py +155 -0
  58. karrio/server/iam/serializers.py +54 -0
  59. karrio/server/iam/signals.py +18 -0
  60. karrio/server/iam/tests.py +3 -0
  61. karrio/server/iam/views.py +3 -0
  62. karrio/server/openapi.py +75 -0
  63. karrio/server/providers/__init__.py +1 -0
  64. karrio/server/providers/admin.py +364 -0
  65. karrio/server/providers/apps.py +10 -0
  66. karrio/server/providers/management/commands/migrate_rate_sheets.py +101 -0
  67. karrio/server/providers/migrations/0001_initial.py +140 -0
  68. karrio/server/providers/migrations/0002_carrier_active.py +18 -0
  69. karrio/server/providers/migrations/0003_auto_20201230_0820.py +24 -0
  70. karrio/server/providers/migrations/0004_auto_20210212_0554.py +178 -0
  71. karrio/server/providers/migrations/0005_auto_20210212_0555.py +18 -0
  72. karrio/server/providers/migrations/0006_australiapostsettings.py +29 -0
  73. karrio/server/providers/migrations/0007_auto_20210213_0206.py +21 -0
  74. karrio/server/providers/migrations/0008_auto_20210214_0409.py +30 -0
  75. karrio/server/providers/migrations/0009_auto_20210308_0302.py +18 -0
  76. karrio/server/providers/migrations/0010_auto_20210409_0852.py +32 -0
  77. karrio/server/providers/migrations/0011_auto_20210409_0853.py +21 -0
  78. karrio/server/providers/migrations/0012_alter_carrier_options.py +17 -0
  79. karrio/server/providers/migrations/0013_tntsettings.py +30 -0
  80. karrio/server/providers/migrations/0014_auto_20210612_1608.py +46 -0
  81. karrio/server/providers/migrations/0015_auto_20210615_1601.py +28 -0
  82. karrio/server/providers/migrations/0016_alter_purolatorsettings_user_token.py +18 -0
  83. karrio/server/providers/migrations/0017_auto_20210805_0359.py +1293 -0
  84. karrio/server/providers/migrations/0018_alter_fedexsettings_user_key.py +18 -0
  85. karrio/server/providers/migrations/0019_dhlpolandsettings_servicelevel.py +65 -0
  86. karrio/server/providers/migrations/0020_genericsettings_labeltemplate.py +52 -0
  87. karrio/server/providers/migrations/0021_auto_20211231_2353.py +40 -0
  88. karrio/server/providers/migrations/0022_carrier_metadata.py +18 -0
  89. karrio/server/providers/migrations/0023_auto_20220124_1916.py +27 -0
  90. karrio/server/providers/migrations/0024_alter_genericsettings_custom_carrier_name.py +19 -0
  91. karrio/server/providers/migrations/0025_alter_servicelevel_service_code.py +19 -0
  92. karrio/server/providers/migrations/0026_auto_20220208_0132.py +59 -0
  93. karrio/server/providers/migrations/0027_auto_20220304_1340.py +29 -0
  94. karrio/server/providers/migrations/0028_auto_20220323_1500.py +33 -0
  95. karrio/server/providers/migrations/0029_easypostsettings.py +27 -0
  96. karrio/server/providers/migrations/0030_amazonmwssettings.py +29 -0
  97. karrio/server/providers/migrations/0031_delete_amazonmwssettings.py +18 -0
  98. karrio/server/providers/migrations/0032_alter_carrier_test.py +18 -0
  99. karrio/server/providers/migrations/0033_auto_20220708_1350.py +22 -0
  100. karrio/server/providers/migrations/0034_amazonmwssettings_dpdhlsettings.py +47 -0
  101. karrio/server/providers/migrations/0035_alter_carrier_capabilities.py +43 -0
  102. karrio/server/providers/migrations/0036_upsfreightsettings.py +31 -0
  103. karrio/server/providers/migrations/0037_chronopostsettings.py +29 -0
  104. karrio/server/providers/migrations/0038_alter_genericsettings_label_template.py +19 -0
  105. karrio/server/providers/migrations/0039_auto_20220906_0612.py +23 -0
  106. karrio/server/providers/migrations/0040_dpdhlsettings_services.py +18 -0
  107. karrio/server/providers/migrations/0041_auto_20221105_0705.py +38 -0
  108. karrio/server/providers/migrations/0042_auto_20221215_1642.py +23 -0
  109. karrio/server/providers/migrations/0043_alter_genericsettings_account_number_and_more.py +39 -0
  110. karrio/server/providers/migrations/0044_carrier_carrier_capabilities.py +64 -0
  111. karrio/server/providers/migrations/0045_alter_carrier_active_alter_carrier_carrier_id.py +31 -0
  112. karrio/server/providers/migrations/0046_remove_dpdhlsettings_signature_and_more.py +41 -0
  113. karrio/server/providers/migrations/0047_dpdsettings.py +286 -0
  114. karrio/server/providers/migrations/0048_servicelevel_min_weight_servicelevel_transit_days_and_more.py +64 -0
  115. karrio/server/providers/migrations/0049_boxknightsettings_geodissettings_lapostesettings_and_more.py +156 -0
  116. karrio/server/providers/migrations/0050_carrier_is_system_alter_carrier_metadata_and_more.py +106 -0
  117. karrio/server/providers/migrations/0051_rename_username_upssettings_client_id_and_more.py +31 -0
  118. karrio/server/providers/migrations/0052_alter_upssettings_account_number_and_more.py +20 -0
  119. karrio/server/providers/migrations/0053_locate2usettings.py +281 -0
  120. karrio/server/providers/migrations/0054_zoom2usettings.py +280 -0
  121. karrio/server/providers/migrations/0055_rename_amazonmwssettings_amazonshippingsettings_and_more.py +44 -0
  122. karrio/server/providers/migrations/0056_asendiaussettings_geodissettings_code_client_and_more.py +75 -0
  123. karrio/server/providers/migrations/0057_alter_servicelevel_weight_unit_belgianpostsettings.py +51 -0
  124. karrio/server/providers/migrations/0058_alliedexpresssettings.py +38 -0
  125. karrio/server/providers/migrations/0059_ratesheet.py +81 -0
  126. karrio/server/providers/migrations/0060_belgianpostsettings_rate_sheet_and_more.py +73 -0
  127. karrio/server/providers/migrations/0061_alliedexpresssettings_service_type.py +17 -0
  128. karrio/server/providers/migrations/0062_sendlesettings_account_country_code.py +257 -0
  129. karrio/server/providers/migrations/0063_servicelevel_metadata.py +25 -0
  130. karrio/server/providers/migrations/0064_alliedexpresslocalsettings.py +43 -0
  131. karrio/server/providers/migrations/0065_servicelevel_carrier_service_code_and_more.py +66 -0
  132. karrio/server/providers/migrations/0066_rename_fedexsettings_fedexwssettings_and_more.py +28 -0
  133. karrio/server/providers/migrations/0067_fedexsettings.py +283 -0
  134. karrio/server/providers/migrations/0068_fedexsettings_track_api_key_and_more.py +38 -0
  135. karrio/server/providers/migrations/0069_alter_canadapostsettings_contract_id_and_more.py +23 -0
  136. karrio/server/providers/migrations/0070_tgesettings_alter_carrier_capabilities.py +65 -0
  137. karrio/server/providers/migrations/0071_alter_tgesettings_my_toll_token.py +18 -0
  138. karrio/server/providers/migrations/0072_rename_eshippersettings_eshipperxmlsettings_and_more.py +28 -0
  139. karrio/server/providers/migrations/0073_delete_eshipperxmlsettings.py +41 -0
  140. karrio/server/providers/migrations/0074_eshippersettings.py +38 -0
  141. karrio/server/providers/migrations/0075_haypostsettings.py +40 -0
  142. karrio/server/providers/migrations/0076_rename_customer_registration_id_uspsinternationalsettings_account_number_and_more.py +125 -0
  143. karrio/server/providers/migrations/0077_uspswtinternationalsettings_uspswtsettings_and_more.py +165 -0
  144. karrio/server/providers/migrations/0078_auto_20240813_1552.py +120 -0
  145. karrio/server/providers/migrations/0079_alter_carrier_options_alter_ratesheet_created_by.py +31 -0
  146. karrio/server/providers/migrations/0080_alter_aramexsettings_account_country_code_and_more.py +3025 -0
  147. karrio/server/providers/migrations/0081_remove_alliedexpresssettings_carrier_ptr_and_more.py +338 -0
  148. karrio/server/providers/migrations/0082_add_zone_identifiers.py +50 -0
  149. karrio/server/providers/migrations/0083_add_optimized_rate_sheet_structure.py +33 -0
  150. karrio/server/providers/migrations/0084_alter_servicelevel_currency.py +168 -0
  151. karrio/server/providers/migrations/0085_populate_dhl_parcel_de_oauth_credentials.py +82 -0
  152. karrio/server/providers/migrations/0086_rename_dhl_parcel_de_customer_number_to_billing_number.py +71 -0
  153. karrio/server/providers/migrations/__init__.py +0 -0
  154. karrio/server/providers/models/__init__.py +16 -0
  155. karrio/server/providers/models/carrier.py +387 -0
  156. karrio/server/providers/models/config.py +30 -0
  157. karrio/server/providers/models/service.py +192 -0
  158. karrio/server/providers/models/sheet.py +287 -0
  159. karrio/server/providers/models/template.py +39 -0
  160. karrio/server/providers/models/utils.py +58 -0
  161. karrio/server/providers/router.py +3 -0
  162. karrio/server/providers/serializers/__init__.py +3 -0
  163. karrio/server/providers/serializers/base.py +538 -0
  164. karrio/server/providers/signals.py +25 -0
  165. karrio/server/providers/templates/providers/oauth_callback.html +105 -0
  166. karrio/server/providers/tests/__init__.py +5 -0
  167. karrio/server/providers/tests/test_connections.py +895 -0
  168. karrio/server/providers/urls.py +11 -0
  169. karrio/server/providers/views/__init__.py +0 -0
  170. karrio/server/providers/views/carriers.py +267 -0
  171. karrio/server/providers/views/connections.py +496 -0
  172. karrio/server/samples.py +352 -0
  173. karrio/server/serializers/__init__.py +2 -0
  174. karrio/server/serializers/abstract.py +602 -0
  175. karrio/server/tracing/__init__.py +0 -0
  176. karrio/server/tracing/admin.py +63 -0
  177. karrio/server/tracing/apps.py +8 -0
  178. karrio/server/tracing/migrations/0001_initial.py +41 -0
  179. karrio/server/tracing/migrations/0002_auto_20220710_1307.py +22 -0
  180. karrio/server/tracing/migrations/0003_auto_20221105_0317.py +43 -0
  181. karrio/server/tracing/migrations/0004_tracingrecord_carrier_account_idx.py +24 -0
  182. karrio/server/tracing/migrations/0005_optimise_tracingrecord_request_log_idx.py +25 -0
  183. karrio/server/tracing/migrations/0006_alter_tracingrecord_options_and_more.py +49 -0
  184. karrio/server/tracing/migrations/0007_tracingrecord_tracing_created_at_idx.py +19 -0
  185. karrio/server/tracing/migrations/__init__.py +0 -0
  186. karrio/server/tracing/models.py +82 -0
  187. karrio/server/tracing/tests.py +3 -0
  188. karrio/server/tracing/utils.py +109 -0
  189. karrio/server/user/__init__.py +0 -0
  190. karrio/server/user/admin.py +96 -0
  191. karrio/server/user/apps.py +7 -0
  192. karrio/server/user/forms.py +35 -0
  193. karrio/server/user/migrations/0001_initial.py +41 -0
  194. karrio/server/user/migrations/0002_token.py +29 -0
  195. karrio/server/user/migrations/0003_token_test_mode.py +20 -0
  196. karrio/server/user/migrations/0004_group.py +26 -0
  197. karrio/server/user/migrations/0005_token_label.py +21 -0
  198. karrio/server/user/migrations/0006_workspaceconfig.py +63 -0
  199. karrio/server/user/migrations/0007_user_metadata.py +25 -0
  200. karrio/server/user/migrations/__init__.py +0 -0
  201. karrio/server/user/models.py +218 -0
  202. karrio/server/user/serializers.py +47 -0
  203. karrio/server/user/templates/registration/login.html +108 -0
  204. karrio/server/user/templates/registration/registration_confirm_email.html +10 -0
  205. karrio/server/user/templates/registration/registration_confirm_email.txt +3 -0
  206. karrio/server/user/tests.py +3 -0
  207. karrio/server/user/urls.py +10 -0
  208. karrio/server/user/utils.py +60 -0
  209. karrio/server/user/views.py +9 -0
  210. karrio_server_core-2025.5.dist-info/METADATA +32 -0
  211. karrio_server_core-2025.5.dist-info/RECORD +213 -0
  212. karrio_server_core-2025.5.dist-info/WHEEL +5 -0
  213. karrio_server_core-2025.5.dist-info/top_level.txt +2 -0
@@ -0,0 +1,41 @@
1
+ # Generated by Django 3.2.13 on 2022-06-28 00:44
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.core.utils.helpers
8
+ import karrio.server.core.models.base
9
+
10
+
11
+ class Migration(migrations.Migration):
12
+
13
+ initial = True
14
+
15
+ dependencies = [
16
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17
+ ]
18
+
19
+ operations = [
20
+ migrations.CreateModel(
21
+ name='TracingRecord',
22
+ fields=[
23
+ ('created_at', models.DateTimeField(auto_now_add=True)),
24
+ ('updated_at', models.DateTimeField(auto_now=True)),
25
+ ('id', models.CharField(default=functools.partial(karrio.server.core.models.base.uuid, *(), **{'prefix': 'trace_'}), editable=False, max_length=50, primary_key=True, serialize=False)),
26
+ ('key', models.CharField(max_length=50)),
27
+ ('record', models.JSONField(default=functools.partial(karrio.core.utils.helpers.identity, *(), **{'value': {}}), help_text='Record data')),
28
+ ('timestamp', models.FloatField()),
29
+ ('meta', models.JSONField(blank=True, default=functools.partial(karrio.core.utils.helpers.identity, *(), **{'value': {}}), help_text='Readonly Context metadata use for filtering and premission check', null=True)),
30
+ ('test_mode', models.BooleanField()),
31
+ ('created_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
32
+ ],
33
+ options={
34
+ 'verbose_name': 'Tracing Record',
35
+ 'verbose_name_plural': 'Tracing Records',
36
+ 'db_table': 'tracing-record',
37
+ 'ordering': ['-created_at'],
38
+ },
39
+ bases=(karrio.server.core.models.base.ControlledAccessModel, models.Model),
40
+ ),
41
+ ]
@@ -0,0 +1,22 @@
1
+ # Generated by Django 3.2.13 on 2022-07-10 13:07
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.fields.json
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('tracing', '0001_initial'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddIndex(
15
+ model_name='tracingrecord',
16
+ index=models.Index(django.db.models.fields.json.KeyTextTransform('object_id', 'meta'), condition=models.Q(('meta__object_id__isnull', False)), name='trace_object_idx'),
17
+ ),
18
+ migrations.AddIndex(
19
+ model_name='tracingrecord',
20
+ index=models.Index(django.db.models.fields.json.KeyTextTransform('request_log_id', 'meta'), condition=models.Q(('meta__request_log_id__isnull', False)), name='request_log_idx'),
21
+ ),
22
+ ]
@@ -0,0 +1,43 @@
1
+ # Generated by Django 3.2.16 on 2022-11-05 03:17
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ def forwards_func(apps, schema_editor):
7
+ db_alias = schema_editor.connection.alias
8
+ TracingRecord = apps.get_model("tracing", "TracingRecord")
9
+
10
+ duplicates = TracingRecord.objects.using(db_alias)\
11
+ .values('meta__request_log_id')\
12
+ .annotate(count=models.Count('id'))\
13
+ .values('meta__request_log_id')\
14
+ .order_by().filter(count__gt=1)
15
+
16
+ for value in duplicates:
17
+ dups = TracingRecord.objects.using(db_alias)\
18
+ .filter(meta__request_log_id=value['meta__request_log_id'])
19
+
20
+ if dups.filter(key='response').exists():
21
+ dups.filter(key='response').exclude(
22
+ id__in=[dups.filter(key='response').first().id]
23
+ ).delete()
24
+
25
+ if dups.filter(key='request').exists():
26
+ dups.filter(key='request').exclude(
27
+ id__in=[dups.filter(key='request').first().id],
28
+ ).delete()
29
+
30
+
31
+
32
+ def reverse_func(apps, schema_editor):
33
+ pass
34
+
35
+ class Migration(migrations.Migration):
36
+
37
+ dependencies = [
38
+ ('tracing', '0002_auto_20220710_1307'),
39
+ ]
40
+
41
+ operations = [
42
+ migrations.RunPython(forwards_func, reverse_func),
43
+ ]
@@ -0,0 +1,24 @@
1
+ # Generated by Django 4.1.3 on 2022-12-10 16:20
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.fields.json
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("tracing", "0003_auto_20221105_0317"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddIndex(
15
+ model_name="tracingrecord",
16
+ index=models.Index(
17
+ django.db.models.fields.json.KeyTextTransform(
18
+ "carrier_account_id", "meta"
19
+ ),
20
+ condition=models.Q(("meta__carrier_account_id__isnull", False)),
21
+ name="carrier_account_idx",
22
+ ),
23
+ ),
24
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 4.2.8 on 2023-12-21 04:13
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.fields.json
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("tracing", "0004_tracingrecord_carrier_account_idx"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveIndex(
14
+ model_name="tracingrecord",
15
+ name="request_log_idx",
16
+ ),
17
+ migrations.AddIndex(
18
+ model_name="tracingrecord",
19
+ index=models.Index(
20
+ django.db.models.fields.json.KeyTransform("request_log_id", "meta"),
21
+ condition=models.Q(("meta__request_log_id__isnull", False)),
22
+ name="request_log_idx",
23
+ ),
24
+ ),
25
+ ]
@@ -0,0 +1,49 @@
1
+ # Generated by Django 4.2.8 on 2023-12-27 19:41
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.fields.json
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("tracing", "0005_optimise_tracingrecord_request_log_idx"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterModelOptions(
14
+ name="tracingrecord",
15
+ options={
16
+ "ordering": ["-timestamp"],
17
+ "verbose_name": "Tracing Record",
18
+ "verbose_name_plural": "Tracing Records",
19
+ },
20
+ ),
21
+ migrations.AddIndex(
22
+ model_name="tracingrecord",
23
+ index=models.Index(
24
+ django.db.models.fields.json.KeyTextTransform(
25
+ "workflow_action_id", "meta"
26
+ ),
27
+ condition=models.Q(("meta__workflow_action_id__isnull", False)),
28
+ name="workflow_action_idx",
29
+ ),
30
+ ),
31
+ migrations.AddIndex(
32
+ model_name="tracingrecord",
33
+ index=models.Index(
34
+ django.db.models.fields.json.KeyTextTransform(
35
+ "workflow_event_id", "meta"
36
+ ),
37
+ condition=models.Q(("meta__workflow_event_id__isnull", False)),
38
+ name="workflow_event_idx",
39
+ ),
40
+ ),
41
+ migrations.AddIndex(
42
+ model_name="tracingrecord",
43
+ index=models.Index(
44
+ django.db.models.fields.json.KeyTextTransform("workflow_id", "meta"),
45
+ condition=models.Q(("meta__workflow_id__isnull", False)),
46
+ name="workflow_idx",
47
+ ),
48
+ ),
49
+ ]
@@ -0,0 +1,19 @@
1
+ # Generated by Django 5.2.5 on 2025-08-23 00:22
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("tracing", "0006_alter_tracingrecord_options_and_more"),
11
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddIndex(
16
+ model_name="tracingrecord",
17
+ index=models.Index(fields=["created_at"], name="tracing_created_at_idx"),
18
+ ),
19
+ ]
File without changes
@@ -0,0 +1,82 @@
1
+ from functools import partial
2
+ from django.conf import settings
3
+ from django.db import models
4
+ from django.db.models.fields import json
5
+
6
+ from karrio.core.utils import identity
7
+ from karrio.server.core.models import OwnedEntity, uuid
8
+
9
+
10
+ class TracingRecord(OwnedEntity):
11
+ HIDDEN_PROPS = (*(("org",) if settings.MULTI_ORGANIZATIONS else tuple()),)
12
+
13
+ class Meta:
14
+ db_table = "tracing-record"
15
+ verbose_name = "Tracing Record"
16
+ verbose_name_plural = "Tracing Records"
17
+ ordering = ["-timestamp"]
18
+ indexes = [
19
+ models.Index(
20
+ json.KeyTextTransform("object_id", "meta"),
21
+ condition=models.Q(meta__object_id__isnull=False),
22
+ name="trace_object_idx",
23
+ ),
24
+ models.Index(
25
+ json.KeyTransform("request_log_id", "meta"),
26
+ condition=models.Q(meta__request_log_id__isnull=False),
27
+ name="request_log_idx",
28
+ ),
29
+ models.Index(
30
+ json.KeyTextTransform("carrier_account_id", "meta"),
31
+ condition=models.Q(meta__carrier_account_id__isnull=False),
32
+ name="carrier_account_idx",
33
+ ),
34
+ models.Index(
35
+ json.KeyTextTransform("workflow_action_id", "meta"),
36
+ condition=models.Q(meta__workflow_action_id__isnull=False),
37
+ name="workflow_action_idx",
38
+ ),
39
+ models.Index(
40
+ json.KeyTextTransform("workflow_event_id", "meta"),
41
+ condition=models.Q(meta__workflow_event_id__isnull=False),
42
+ name="workflow_event_idx",
43
+ ),
44
+ models.Index(
45
+ json.KeyTextTransform("workflow_id", "meta"),
46
+ condition=models.Q(meta__workflow_id__isnull=False),
47
+ name="workflow_idx",
48
+ ),
49
+ # Index for archiving queries based on creation date
50
+ models.Index(fields=["created_at"], name="tracing_created_at_idx"),
51
+ ]
52
+
53
+ id = models.CharField(
54
+ max_length=50,
55
+ primary_key=True,
56
+ default=partial(uuid, prefix="trace_"),
57
+ editable=False,
58
+ )
59
+ created_by = models.ForeignKey(
60
+ settings.AUTH_USER_MODEL,
61
+ blank=True,
62
+ null=True,
63
+ on_delete=models.CASCADE,
64
+ editable=False,
65
+ )
66
+ key = models.CharField(max_length=50)
67
+ record = models.JSONField(
68
+ default=partial(identity, value={}),
69
+ help_text="Record data",
70
+ )
71
+ timestamp = models.FloatField()
72
+ meta = models.JSONField(
73
+ blank=True,
74
+ null=True,
75
+ default=partial(identity, value={}),
76
+ help_text="Readonly Context metadata use for filtering and premission check",
77
+ )
78
+ test_mode = models.BooleanField(null=False)
79
+
80
+ @property
81
+ def object_type(self):
82
+ return "tracking_record"
@@ -0,0 +1,3 @@
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
@@ -0,0 +1,109 @@
1
+ import karrio.lib as lib
2
+ import karrio.server.conf as conf
3
+ import karrio.server.core.utils as utils
4
+ import karrio.server.tracing.models as models
5
+ import karrio.server.serializers as serializers
6
+ from karrio.server.core.logging import logger
7
+
8
+
9
+ @utils.error_wrapper
10
+ def save_tracing_records(context, tracer: lib.Tracer = None, schema: str = None):
11
+ if conf.settings.PERSIST_SDK_TRACING is False:
12
+ return
13
+
14
+ tracer = tracer or getattr(context, "tracer", lib.Tracer())
15
+
16
+ # Process Karrio SDK tracing records to persist records of interest.
17
+ @utils.async_wrapper
18
+ @utils.tenant_aware
19
+ def persist_records(**kwarg):
20
+ actor = getattr(context, "user", None)
21
+ if len(tracer.records) == 0 or getattr(actor, "id", None) is None:
22
+ return
23
+
24
+ try:
25
+ records = []
26
+ exists = lib.identity(
27
+ models.TracingRecord.access_by(context)
28
+ .filter(
29
+ meta__request_log_id__isnull=False,
30
+ meta__request_log_id=tracer.context.get("request_log_id"),
31
+ )
32
+ .exists()
33
+ )
34
+
35
+ if exists:
36
+ return
37
+
38
+ for record in tracer.records:
39
+ connection: dict = record.metadata.get("connection")
40
+
41
+ records.append(
42
+ models.TracingRecord(
43
+ key=record.key,
44
+ record=record.data,
45
+ timestamp=record.timestamp,
46
+ created_by_id=getattr(actor, "id", None),
47
+ test_mode=connection.get("test_mode", False),
48
+ meta=lib.to_dict(
49
+ {
50
+ "tracer_id": tracer.id,
51
+ "object_id": tracer.context.get("object_id"),
52
+ "carrier_account_id": connection.get("id"),
53
+ "carrier_id": connection.get("carrier_id"),
54
+ "carrier_name": connection.get("carrier_name"),
55
+ "request_log_id": tracer.context.get("request_log_id"),
56
+ }
57
+ ),
58
+ )
59
+ )
60
+
61
+ saved_records = models.TracingRecord.objects.bulk_create(records)
62
+
63
+ if getattr(context, "org", None) is not None:
64
+ serializers.bulk_link_org(saved_records, context)
65
+
66
+ logger.info("Tracing records saved successfully", record_count=len(saved_records))
67
+ except Exception as e:
68
+ logger.error("Failed to save tracing records", error=str(e))
69
+
70
+ persist_records(schema=schema)
71
+
72
+
73
+ @utils.error_wrapper
74
+ def bulk_save_tracing_records(tracer: lib.Tracer, context=None):
75
+ if conf.settings.PERSIST_SDK_TRACING is False:
76
+ return
77
+
78
+ if len(tracer.records) == 0 or context is None:
79
+ return
80
+
81
+ records = []
82
+
83
+ for record in tracer.records:
84
+ logger.debug("Processing tracing record", record_key=record.key, metadata=record.metadata)
85
+ records.append(
86
+ models.TracingRecord(
87
+ key=record.key,
88
+ record=record.data,
89
+ timestamp=record.timestamp,
90
+ test_mode=getattr(context, "test_mode", False),
91
+ created_by_id=getattr(context.user, "id", None),
92
+ meta=lib.to_dict({"tracer_id": tracer.id, **(record.metadata or {})}),
93
+ )
94
+ )
95
+
96
+ saved_records = models.TracingRecord.objects.bulk_create(records)
97
+
98
+ if getattr(context, "org", None) is not None:
99
+ serializers.bulk_link_org(saved_records, context)
100
+
101
+ logger.info("Tracing records saved successfully", record_count=len(saved_records))
102
+
103
+
104
+ def set_tracing_context(**kwargs):
105
+
106
+ from karrio.server.core import middleware
107
+
108
+ request = middleware.SessionContext.get_current_request()
109
+ request.tracer.add_context(kwargs)
File without changes
@@ -0,0 +1,96 @@
1
+ from django.conf import settings
2
+ from django.contrib import auth
3
+ from django.contrib import admin
4
+ from django.contrib.auth import admin as auth_admin
5
+ from django.utils.translation import gettext_lazy as _
6
+
7
+ from karrio.server.user.models import Token, Group
8
+
9
+ User = auth.get_user_model()
10
+ admin.site.unregister(auth.models.Group)
11
+
12
+
13
+ class UserAdmin(auth_admin.UserAdmin):
14
+ add_form_template = None
15
+ fieldsets = (
16
+ (None, {"fields": ("email", "password")}),
17
+ (_("Personal info"), {"fields": ("full_name",)}),
18
+ (
19
+ _("Permissions"),
20
+ {
21
+ "fields": (
22
+ "is_active",
23
+ "is_staff",
24
+ "is_superuser",
25
+ "groups",
26
+ "user_permissions",
27
+ ),
28
+ },
29
+ ),
30
+ (_("Important dates"), {"fields": ("last_login", "date_joined")}),
31
+ )
32
+ add_fieldsets = (
33
+ (
34
+ None,
35
+ {
36
+ "classes": ("wide",),
37
+ "fields": ("email", "password1", "password2"),
38
+ },
39
+ ),
40
+ )
41
+ list_display = (
42
+ "email",
43
+ "full_name",
44
+ "is_staff",
45
+ "is_active",
46
+ "date_joined",
47
+ "last_login",
48
+ )
49
+ list_filter = (
50
+ "is_staff",
51
+ "is_superuser",
52
+ "is_active",
53
+ "groups",
54
+ "last_login",
55
+ "date_joined",
56
+ )
57
+ search_fields = ("email", "full_name")
58
+ ordering = ("email",)
59
+
60
+
61
+ class GroupAdmin(auth_admin.GroupAdmin):
62
+ pass
63
+
64
+
65
+ class TokenAdmin(admin.ModelAdmin):
66
+ list_display = (
67
+ "key",
68
+ "user",
69
+ "label",
70
+ *(["organization"] if settings.MULTI_ORGANIZATIONS else []),
71
+ "test_mode",
72
+ "created",
73
+ )
74
+ fields = ("user", "label", "test_mode")
75
+ ordering = ("-created",)
76
+
77
+ def get_queryset(self, request):
78
+ query = super().get_queryset(request)
79
+ return query.filter(user=request.user)
80
+
81
+ if settings.MULTI_ORGANIZATIONS:
82
+ from karrio.server.orgs.admin import TokenLinkInline
83
+
84
+ inlines = [TokenLinkInline]
85
+
86
+ def get_form(self, request, obj, change, **kwargs):
87
+ form = super().get_form(request, obj, change, **kwargs)
88
+ form.base_fields["user"].queryset = User.objects.filter(
89
+ orgs_organization__users__id=request.user.id
90
+ ).distinct()
91
+ return form
92
+
93
+
94
+ admin.site.register(User, UserAdmin)
95
+ admin.site.register(Group, GroupAdmin)
96
+ admin.site.register(Token, TokenAdmin)
@@ -0,0 +1,7 @@
1
+ from django.apps import AppConfig
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+
5
+ class UserConfig(AppConfig):
6
+ name = "karrio.server.user"
7
+ verbose_name = _("AUTHENTICATION AND AUTHORIZATION")
@@ -0,0 +1,35 @@
1
+ from django import forms
2
+ from django.db import transaction
3
+ from django.contrib.auth import get_user_model
4
+ from django.contrib.auth.forms import UserCreationForm
5
+ from django.utils.translation import gettext_lazy as _
6
+
7
+ from karrio.server.conf import settings
8
+ from karrio.server.user.utils import send_email
9
+
10
+
11
+ class SignUpForm(UserCreationForm):
12
+ redirect_url = forms.URLField(required=True)
13
+
14
+ class Meta:
15
+ model = get_user_model()
16
+ fields = ("email", "full_name")
17
+
18
+ @transaction.atomic
19
+ def save(self, commit=True):
20
+ if settings.ALLOW_SIGNUP == False:
21
+ raise Exception(
22
+ "Signup is not allowed. "
23
+ "Please contact your administrator to create an account."
24
+ )
25
+
26
+ user = super().save(commit=commit)
27
+
28
+ if commit and settings.EMAIL_ENABLED:
29
+ user.is_active = False
30
+ send_email(user, self.cleaned_data["redirect_url"])
31
+
32
+ if commit and settings.ALLOW_ADMIN_APPROVED_SIGNUP:
33
+ user.is_active = False
34
+
35
+ return user
@@ -0,0 +1,41 @@
1
+ # Generated by Django 3.1.2 on 2020-10-20 20:17
2
+
3
+ from django.db import migrations, models
4
+ import django.utils.timezone
5
+ import karrio.server.user.models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ initial = True
11
+
12
+ dependencies = [
13
+ ('auth', '0012_alter_user_first_name_max_length'),
14
+ ]
15
+
16
+ operations = [
17
+ migrations.CreateModel(
18
+ name='User',
19
+ fields=[
20
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21
+ ('password', models.CharField(max_length=128, verbose_name='password')),
22
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
23
+ ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
24
+ ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
25
+ ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
26
+ ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
27
+ ('full_name', models.CharField(blank=True, max_length=150, verbose_name='full name')),
28
+ ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
29
+ ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
30
+ ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
31
+ ],
32
+ options={
33
+ 'verbose_name': 'user',
34
+ 'verbose_name_plural': 'users',
35
+ 'abstract': False,
36
+ },
37
+ managers=[
38
+ ('objects', karrio.server.user.models.UserManager()),
39
+ ],
40
+ ),
41
+ ]
@@ -0,0 +1,29 @@
1
+ # Generated by Django 3.2.3 on 2021-05-20 10:27
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+ import karrio.server.core.models.base
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ dependencies = [
12
+ ('user', '0001_initial'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name='Token',
18
+ fields=[
19
+ ('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')),
20
+ ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
21
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL)),
22
+ ],
23
+ options={
24
+ 'verbose_name': 'Token',
25
+ 'verbose_name_plural': 'Tokens',
26
+ },
27
+ bases=(models.Model, karrio.server.core.models.base.ControlledAccessModel),
28
+ ),
29
+ ]
@@ -0,0 +1,20 @@
1
+ # Generated by Django 3.2.13 on 2022-07-06 13:50
2
+
3
+ from django.db import migrations, models
4
+ import functools
5
+ import karrio.server.core.models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('user', '0002_token'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddField(
16
+ model_name='token',
17
+ name='test_mode',
18
+ field=models.BooleanField(default=functools.partial(karrio.server.core.models._identity, *(), **{'value': False})),
19
+ ),
20
+ ]