karrio-server-graph 2025.5rc34__py3-none-any.whl → 2025.5rc36__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.
- karrio/server/graph/schemas/base/inputs.py +1 -0
- karrio/server/graph/schemas/base/mutations.py +2 -2
- karrio/server/graph/schemas/base/types.py +5 -4
- karrio/server/graph/tests/base.py +20 -0
- karrio/server/graph/tests/test_registration.py +56 -52
- {karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/METADATA +1 -1
- {karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/RECORD +9 -9
- {karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/WHEEL +0 -0
- {karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/top_level.txt +0 -0
|
@@ -10,6 +10,7 @@ import karrio.server.graph.utils as utils
|
|
|
10
10
|
|
|
11
11
|
@strawberry.input
|
|
12
12
|
class LogFilter(utils.Paginated):
|
|
13
|
+
query: typing.Optional[str] = strawberry.UNSET
|
|
13
14
|
api_endpoint: typing.Optional[str] = strawberry.UNSET
|
|
14
15
|
remote_addr: typing.Optional[str] = strawberry.UNSET
|
|
15
16
|
date_after: typing.Optional[datetime.datetime] = strawberry.UNSET
|
|
@@ -868,7 +868,7 @@ class CreateCarrierConnectionMutation(utils.BaseMutation):
|
|
|
868
868
|
@staticmethod
|
|
869
869
|
@utils.error_wrapper
|
|
870
870
|
@utils.authentication_required
|
|
871
|
-
@utils.authorization_required(["
|
|
871
|
+
@utils.authorization_required(["write_carriers"])
|
|
872
872
|
def mutate(info: Info, **input) -> "CreateCarrierConnectionMutation":
|
|
873
873
|
data = input.copy()
|
|
874
874
|
|
|
@@ -893,7 +893,7 @@ class UpdateCarrierConnectionMutation(utils.BaseMutation):
|
|
|
893
893
|
@staticmethod
|
|
894
894
|
@utils.error_wrapper
|
|
895
895
|
@utils.authentication_required
|
|
896
|
-
@utils.authorization_required(["
|
|
896
|
+
@utils.authorization_required(["write_carriers"])
|
|
897
897
|
def mutate(info: Info, **input) -> "UpdateCarrierConnectionMutation":
|
|
898
898
|
data = input.copy()
|
|
899
899
|
id = data.get("id")
|
|
@@ -1067,7 +1067,6 @@ class PaymentType:
|
|
|
1067
1067
|
paid_by: typing.Optional[utils.PaidByEnum] = None
|
|
1068
1068
|
currency: typing.Optional[utils.CurrencyCodeEnum] = None
|
|
1069
1069
|
|
|
1070
|
-
|
|
1071
1070
|
@strawberry.type
|
|
1072
1071
|
class ShipmentType:
|
|
1073
1072
|
id: str
|
|
@@ -1316,7 +1315,9 @@ class SystemConnectionType:
|
|
|
1316
1315
|
_filter = filter if not utils.is_unset(filter) else inputs.CarrierFilter()
|
|
1317
1316
|
connections = filters.CarrierFilters(
|
|
1318
1317
|
_filter.to_dict(),
|
|
1319
|
-
providers.Carrier.system_carriers.
|
|
1318
|
+
providers.Carrier.system_carriers.resolve_config_for(
|
|
1319
|
+
info.context.request
|
|
1320
|
+
).filter(
|
|
1320
1321
|
active=True,
|
|
1321
1322
|
test_mode=getattr(info.context.request, "test_mode", False),
|
|
1322
1323
|
),
|
|
@@ -1368,7 +1369,7 @@ class CarrierConnectionType:
|
|
|
1368
1369
|
@staticmethod
|
|
1369
1370
|
@utils.utils.error_wrapper
|
|
1370
1371
|
@utils.authentication_required
|
|
1371
|
-
@utils.authorization_required(["
|
|
1372
|
+
@utils.authorization_required(["read_carriers"])
|
|
1372
1373
|
def resolve(
|
|
1373
1374
|
info,
|
|
1374
1375
|
id: str,
|
|
@@ -1381,7 +1382,7 @@ class CarrierConnectionType:
|
|
|
1381
1382
|
@staticmethod
|
|
1382
1383
|
@utils.utils.error_wrapper
|
|
1383
1384
|
@utils.authentication_required
|
|
1384
|
-
@utils.authorization_required(["
|
|
1385
|
+
@utils.authorization_required(["read_carriers"])
|
|
1385
1386
|
def resolve_list(
|
|
1386
1387
|
info,
|
|
1387
1388
|
filter: typing.Optional[inputs.CarrierFilter] = strawberry.UNSET,
|
|
@@ -25,8 +25,28 @@ class GraphTestCase(BaseAPITestCase):
|
|
|
25
25
|
self.user = get_user_model().objects.create_superuser(
|
|
26
26
|
"admin@example.com", "test"
|
|
27
27
|
)
|
|
28
|
+
|
|
28
29
|
self.token = Token.objects.create(user=self.user, test_mode=False)
|
|
29
30
|
|
|
31
|
+
# Create organization for multi-org support (if enabled)
|
|
32
|
+
from django.conf import settings
|
|
33
|
+
if settings.MULTI_ORGANIZATIONS:
|
|
34
|
+
from karrio.server.orgs.models import Organization, TokenLink
|
|
35
|
+
self.organization = Organization.objects.create(
|
|
36
|
+
name="Test Organization",
|
|
37
|
+
slug="test-org"
|
|
38
|
+
)
|
|
39
|
+
# Add user as owner (triggers permission sync via signals)
|
|
40
|
+
owner = self.organization.add_user(self.user, is_admin=True)
|
|
41
|
+
self.organization.change_owner(owner)
|
|
42
|
+
self.organization.save()
|
|
43
|
+
|
|
44
|
+
# Link token to organization
|
|
45
|
+
TokenLink.objects.create(
|
|
46
|
+
item=self.token,
|
|
47
|
+
org=self.organization
|
|
48
|
+
)
|
|
49
|
+
|
|
30
50
|
# Setup API client.
|
|
31
51
|
self.client = APIClient()
|
|
32
52
|
self.client.credentials(HTTP_AUTHORIZATION="Token " + self.token.key)
|
|
@@ -6,14 +6,14 @@ User = get_user_model()
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class TestUserRegistration(GraphTestCase):
|
|
9
|
-
|
|
10
|
-
@patch(
|
|
11
|
-
@patch(
|
|
9
|
+
|
|
10
|
+
@patch("karrio.server.conf.settings.ALLOW_SIGNUP", True)
|
|
11
|
+
@patch("karrio.server.conf.settings.EMAIL_ENABLED", False)
|
|
12
12
|
def test_register_user_mutation(self):
|
|
13
13
|
"""Test successful user registration"""
|
|
14
14
|
# Ensure user doesn't exist
|
|
15
15
|
User.objects.filter(email="newuser@example.com").delete()
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
response = self.query(
|
|
18
18
|
"""
|
|
19
19
|
mutation register_user($data: RegisterUserMutationInput!) {
|
|
@@ -33,21 +33,26 @@ class TestUserRegistration(GraphTestCase):
|
|
|
33
33
|
"full_name": "New Test User",
|
|
34
34
|
"password1": "TestPassword123!",
|
|
35
35
|
"password2": "TestPassword123!",
|
|
36
|
-
"redirect_url": "http://
|
|
36
|
+
"redirect_url": "http://example.com/email",
|
|
37
37
|
}
|
|
38
|
-
}
|
|
38
|
+
},
|
|
39
39
|
)
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
self.assertResponseNoErrors(response)
|
|
42
|
-
self.assertIsNotNone(response.data[
|
|
43
|
-
self.assertEqual(
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
self.assertIsNotNone(response.data["data"]["register_user"]["user"])
|
|
43
|
+
self.assertEqual(
|
|
44
|
+
response.data["data"]["register_user"]["user"]["email"],
|
|
45
|
+
"newuser@example.com",
|
|
46
|
+
)
|
|
47
|
+
self.assertEqual(
|
|
48
|
+
response.data["data"]["register_user"]["user"]["full_name"], "New Test User"
|
|
49
|
+
)
|
|
50
|
+
|
|
46
51
|
# Verify user was created in database
|
|
47
52
|
user = User.objects.get(email="newuser@example.com")
|
|
48
53
|
self.assertEqual(user.full_name, "New Test User")
|
|
49
|
-
|
|
50
|
-
@patch(
|
|
54
|
+
|
|
55
|
+
@patch("karrio.server.conf.settings.ALLOW_SIGNUP", True)
|
|
51
56
|
def test_register_user_password_mismatch(self):
|
|
52
57
|
"""Test registration fails with mismatched passwords"""
|
|
53
58
|
response = self.query(
|
|
@@ -67,25 +72,25 @@ class TestUserRegistration(GraphTestCase):
|
|
|
67
72
|
"full_name": "Mismatch User",
|
|
68
73
|
"password1": "TestPassword123!",
|
|
69
74
|
"password2": "DifferentPassword123!",
|
|
70
|
-
"redirect_url": "http://
|
|
75
|
+
"redirect_url": "http://example.com/email",
|
|
71
76
|
}
|
|
72
|
-
}
|
|
77
|
+
},
|
|
73
78
|
)
|
|
74
|
-
|
|
79
|
+
|
|
75
80
|
# Should have errors
|
|
76
|
-
self.assertIsNotNone(response.data.get(
|
|
77
|
-
self.assertIn("password", str(response.data[
|
|
78
|
-
|
|
79
|
-
@patch(
|
|
81
|
+
self.assertIsNotNone(response.data.get("errors"))
|
|
82
|
+
self.assertIn("password", str(response.data["errors"][0]))
|
|
83
|
+
|
|
84
|
+
@patch("karrio.server.conf.settings.ALLOW_SIGNUP", True)
|
|
80
85
|
def test_register_user_duplicate_email(self):
|
|
81
86
|
"""Test registration fails with duplicate email"""
|
|
82
87
|
# First create a user
|
|
83
88
|
User.objects.create_user(
|
|
84
89
|
email="existing@example.com",
|
|
85
90
|
password="ExistingPass123!",
|
|
86
|
-
full_name="Existing User"
|
|
91
|
+
full_name="Existing User",
|
|
87
92
|
)
|
|
88
|
-
|
|
93
|
+
|
|
89
94
|
response = self.query(
|
|
90
95
|
"""
|
|
91
96
|
mutation register_user($data: RegisterUserMutationInput!) {
|
|
@@ -103,15 +108,15 @@ class TestUserRegistration(GraphTestCase):
|
|
|
103
108
|
"full_name": "Duplicate User",
|
|
104
109
|
"password1": "TestPassword123!",
|
|
105
110
|
"password2": "TestPassword123!",
|
|
106
|
-
"redirect_url": "http://
|
|
111
|
+
"redirect_url": "http://example.com/email",
|
|
107
112
|
}
|
|
108
|
-
}
|
|
113
|
+
},
|
|
109
114
|
)
|
|
110
|
-
|
|
115
|
+
|
|
111
116
|
# Should have errors about duplicate email
|
|
112
|
-
self.assertIsNotNone(response.data.get(
|
|
113
|
-
|
|
114
|
-
@patch(
|
|
117
|
+
self.assertIsNotNone(response.data.get("errors"))
|
|
118
|
+
|
|
119
|
+
@patch("karrio.server.conf.settings.ALLOW_SIGNUP", False)
|
|
115
120
|
def test_register_user_signup_disabled(self):
|
|
116
121
|
"""Test registration fails when signup is disabled"""
|
|
117
122
|
response = self.query(
|
|
@@ -131,28 +136,28 @@ class TestUserRegistration(GraphTestCase):
|
|
|
131
136
|
"full_name": "Disabled User",
|
|
132
137
|
"password1": "TestPassword123!",
|
|
133
138
|
"password2": "TestPassword123!",
|
|
134
|
-
"redirect_url": "http://
|
|
139
|
+
"redirect_url": "http://example.com/email",
|
|
135
140
|
}
|
|
136
|
-
}
|
|
141
|
+
},
|
|
137
142
|
)
|
|
138
|
-
|
|
143
|
+
|
|
139
144
|
# Should have errors about signup not allowed
|
|
140
|
-
self.assertIsNotNone(response.data.get(
|
|
141
|
-
self.assertIn("Signup is not allowed", str(response.data[
|
|
145
|
+
self.assertIsNotNone(response.data.get("errors"))
|
|
146
|
+
self.assertIn("Signup is not allowed", str(response.data["errors"][0]))
|
|
142
147
|
|
|
143
148
|
|
|
144
149
|
class TestPasswordReset(GraphTestCase):
|
|
145
|
-
|
|
150
|
+
|
|
146
151
|
def setUp(self):
|
|
147
152
|
super().setUp()
|
|
148
153
|
# Create a test user for password reset
|
|
149
154
|
self.reset_user = User.objects.create_user(
|
|
150
155
|
email="resetuser@example.com",
|
|
151
156
|
password="OldPassword123!",
|
|
152
|
-
full_name="Reset User"
|
|
157
|
+
full_name="Reset User",
|
|
153
158
|
)
|
|
154
|
-
|
|
155
|
-
@patch(
|
|
159
|
+
|
|
160
|
+
@patch("django.core.mail.send_mail")
|
|
156
161
|
def test_request_password_reset(self, mock_send_mail):
|
|
157
162
|
"""Test requesting a password reset"""
|
|
158
163
|
response = self.query(
|
|
@@ -168,22 +173,25 @@ class TestPasswordReset(GraphTestCase):
|
|
|
168
173
|
variables={
|
|
169
174
|
"data": {
|
|
170
175
|
"email": "resetuser@example.com",
|
|
171
|
-
"redirect_url": "http://
|
|
176
|
+
"redirect_url": "http://example.com/password/reset",
|
|
172
177
|
}
|
|
173
|
-
}
|
|
178
|
+
},
|
|
174
179
|
)
|
|
175
|
-
|
|
180
|
+
|
|
176
181
|
self.assertResponseNoErrors(response)
|
|
177
|
-
self.assertEqual(
|
|
182
|
+
self.assertEqual(
|
|
183
|
+
response.data["data"]["request_password_reset"]["email"],
|
|
184
|
+
"resetuser@example.com",
|
|
185
|
+
)
|
|
178
186
|
|
|
179
187
|
|
|
180
188
|
class TestEmailConfirmation(GraphTestCase):
|
|
181
|
-
|
|
182
|
-
@patch(
|
|
189
|
+
|
|
190
|
+
@patch("karrio.server.graph.schemas.base.mutations.email_verification.verify_token")
|
|
183
191
|
def test_confirm_email(self, mock_verify):
|
|
184
192
|
"""Test email confirmation"""
|
|
185
193
|
mock_verify.return_value = (True, None)
|
|
186
|
-
|
|
194
|
+
|
|
187
195
|
response = self.query(
|
|
188
196
|
"""
|
|
189
197
|
mutation confirm_email($data: ConfirmEmailMutationInput!) {
|
|
@@ -193,13 +201,9 @@ class TestEmailConfirmation(GraphTestCase):
|
|
|
193
201
|
}
|
|
194
202
|
""",
|
|
195
203
|
operation_name="confirm_email",
|
|
196
|
-
variables={
|
|
197
|
-
"data": {
|
|
198
|
-
"token": "test-confirmation-token"
|
|
199
|
-
}
|
|
200
|
-
}
|
|
204
|
+
variables={"data": {"token": "test-confirmation-token"}},
|
|
201
205
|
)
|
|
202
|
-
|
|
206
|
+
|
|
203
207
|
self.assertResponseNoErrors(response)
|
|
204
|
-
self.assertTrue(response.data[
|
|
205
|
-
mock_verify.assert_called_once_with("test-confirmation-token")
|
|
208
|
+
self.assertTrue(response.data["data"]["confirm_email"]["success"])
|
|
209
|
+
mock_verify.assert_called_once_with("test-confirmation-token")
|
{karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/RECORD
RENAMED
|
@@ -16,24 +16,24 @@ karrio/server/graph/migrations/0002_auto_20210512_1353.py,sha256=TnUwR9EP0qp3gJ3
|
|
|
16
16
|
karrio/server/graph/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
karrio/server/graph/schemas/__init__.py,sha256=Kn-I1j3HP3jwZccpz6FL9r1k6b3UEAMVh2kFPCKNS0w,80
|
|
18
18
|
karrio/server/graph/schemas/base/__init__.py,sha256=nnOfynQW842qOA0qD6bYz8GSHQCQeBW36vbq0sqRkJs,15121
|
|
19
|
-
karrio/server/graph/schemas/base/inputs.py,sha256=
|
|
20
|
-
karrio/server/graph/schemas/base/mutations.py,sha256=
|
|
21
|
-
karrio/server/graph/schemas/base/types.py,sha256=
|
|
19
|
+
karrio/server/graph/schemas/base/inputs.py,sha256=p6_u4sG1cbd18CpPjkyG3CD4cbvf4gBa3De4RDgCZ80,21419
|
|
20
|
+
karrio/server/graph/schemas/base/mutations.py,sha256=6ljP3_2UpUHpYIl06I7n-owQjUp2TT5jDgZ_fEzvB6o,35043
|
|
21
|
+
karrio/server/graph/schemas/base/types.py,sha256=FBayGYWlqcHK0tm43xFA6ZkUFlr1htM7-TutRKPmTkc,47613
|
|
22
22
|
karrio/server/graph/templates/graphql/graphiql.html,sha256=MQjQbBqoRE0QLsOUck8SaXo6B2oJO8dT6YZzUqbDan0,3786
|
|
23
23
|
karrio/server/graph/templates/karrio/email_change_email.html,sha256=gr55F97GYzY27TVKGl49037yd60eSYD0b0GXRlyoco4,552
|
|
24
24
|
karrio/server/graph/templates/karrio/email_change_email.txt,sha256=NXXuzLR63hn2F1fVAjzmuguptuuTvujwqI7YLSrQoio,431
|
|
25
25
|
karrio/server/graph/templates/karrio/password_reset_email.html,sha256=dttqYVL73cQNuTFsVdn2GV4Ckee8PTY8oEF53GbDRcg,553
|
|
26
26
|
karrio/server/graph/tests/__init__.py,sha256=dPzsYY5hoO5gmY6fhL8tiz7Bfst8RB3JzsBVHZazHRE,338
|
|
27
|
-
karrio/server/graph/tests/base.py,sha256=
|
|
27
|
+
karrio/server/graph/tests/base.py,sha256=dzLiva3eTAsbBM5Ga8SI2fxSanBQgAqswS0YVdtTfEg,5122
|
|
28
28
|
karrio/server/graph/tests/test_carrier_connections.py,sha256=qZ1OL8CgZrHuluKJd7cjFXaRZ0VpogN5Srjk2EApLWU,6892
|
|
29
29
|
karrio/server/graph/tests/test_metafield.py,sha256=K7Oon0CLEm_MUMbmcu0t2iAZvFN8Wl7Kp4QAWeUXo_Y,12783
|
|
30
30
|
karrio/server/graph/tests/test_partial_shipments.py,sha256=dPIdIq4wiyovOaIIzbIX69eZnBqCA4ZvBSiGKYADM2g,19031
|
|
31
31
|
karrio/server/graph/tests/test_rate_sheets.py,sha256=cUzPV8dXQFPFh1r7W8bY6Lou3fjh8f9VGpyZrfbMXec,10300
|
|
32
|
-
karrio/server/graph/tests/test_registration.py,sha256=
|
|
32
|
+
karrio/server/graph/tests/test_registration.py,sha256=0vCTqlsLc0cl2m78umgfm7grnDgTI_NZJWNUrRUlQBY,7107
|
|
33
33
|
karrio/server/graph/tests/test_templates.py,sha256=WVU6vcfr6tEk917uSn1dECU8bkQtgD7FNuE-GJuFido,21626
|
|
34
34
|
karrio/server/graph/tests/test_user_info.py,sha256=K91BL7SgxLWflCZriSVI8Vt5M5RIqmSCHKrgN2w8GmM,1928
|
|
35
35
|
karrio/server/settings/graph.py,sha256=cz2yQHbp3xCfyFKuUkPEFfkI2fFVggExIY49wGz7mt0,106
|
|
36
|
-
karrio_server_graph-2025.
|
|
37
|
-
karrio_server_graph-2025.
|
|
38
|
-
karrio_server_graph-2025.
|
|
39
|
-
karrio_server_graph-2025.
|
|
36
|
+
karrio_server_graph-2025.5rc36.dist-info/METADATA,sha256=yn36YEqc52mn_0qvRKPzGOqZDH8H-q64jd4I-goLvgo,744
|
|
37
|
+
karrio_server_graph-2025.5rc36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
38
|
+
karrio_server_graph-2025.5rc36.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
|
|
39
|
+
karrio_server_graph-2025.5rc36.dist-info/RECORD,,
|
|
File without changes
|
{karrio_server_graph-2025.5rc34.dist-info → karrio_server_graph-2025.5rc36.dist-info}/top_level.txt
RENAMED
|
File without changes
|