Skip to content

Commit 5e4b2fb

Browse files
SK-3039:Update context to other valid data types.
1 parent 9d6b3a3 commit 5e4b2fb

3 files changed

Lines changed: 48 additions & 9 deletions

File tree

skyflow/utils/validations/_validations.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ def validate_token_options(logger, credentials, config_id_type=None, config_id=N
115115
SkyflowMessages.Error.EMPTY_CONTEXT_IN_CONFIG.value.format(config_id_type, config_id)
116116
if config_id_type and config_id else SkyflowMessages.Error.EMPTY_CONTEXT.value
117117
)
118+
# Scalars are accepted because the token engine and the auth service both support
119+
# them as ctx claims - bool is listed explicitly even though it is an int subclass.
118120
validate_required_field(
119-
logger, credentials, CredentialField.CONTEXT, (str, dict),
121+
logger, credentials, CredentialField.CONTEXT, (str, dict, bool, int, float),
120122
empty_context_error,
121123
SkyflowMessages.Error.INVALID_CONTEXT_IN_CONFIG.value.format(config_id_type, config_id)
122124
if config_id_type and config_id else SkyflowMessages.Error.INVALID_CONTEXT.value

tests/utils/validations/test__validations.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,31 @@ def test_validate_credentials_with_invalid_dict_context_key(self):
186186
SkyflowMessages.Error.INVALID_CTX_MAP_KEY.value.format("invalid key")
187187
)
188188

189-
def test_validate_credentials_with_invalid_context_type(self):
190-
for invalid_context in [123, ["user_12345"], True]:
191-
credentials = {
192-
"api_key": "sky-abc12-1234567890abcdef1234567890abcdef",
193-
"context": invalid_context
194-
}
195-
with self.assertRaises(SkyflowError) as context:
189+
def test_validate_credentials_with_scalar_context(self):
190+
"""Numbers and booleans are valid ctx claims, so they must not be rejected here.
191+
192+
The token engine and the auth service both accept them; rejecting them would make the
193+
client stricter than generate_bearer_token for no reason. Falsy scalars are included
194+
because nothing on this path may test truthiness.
195+
"""
196+
for scalar_context in [123, 0, 1.5, 0.0, True, False]:
197+
with self.subTest(context=scalar_context):
198+
credentials = {
199+
"api_key": "sky-abc12-1234567890abcdef1234567890abcdef",
200+
"context": scalar_context
201+
}
196202
validate_credentials(self.logger, credentials)
197-
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_CONTEXT.value)
203+
204+
def test_validate_credentials_with_invalid_context_type(self):
205+
for invalid_context in [["user_12345"], ("user_12345",), None, object()]:
206+
with self.subTest(context=invalid_context):
207+
credentials = {
208+
"api_key": "sky-abc12-1234567890abcdef1234567890abcdef",
209+
"context": invalid_context
210+
}
211+
with self.assertRaises(SkyflowError) as context:
212+
validate_credentials(self.logger, credentials)
213+
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_CONTEXT.value)
198214

199215
def test_validate_credentials_with_dict_context_in_config(self):
200216
"""Config-scoped messages are used when a config id is available."""

tests/vault/client/test__client.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,27 @@ def test_get_bearer_token_forwards_dict_context_unmodified(self, mock_generate):
345345
self.assertEqual(options["ctx"], DICT_CONTEXT)
346346
self.assertNotIn("role_ids", options)
347347

348+
@patch("skyflow.vault.client.client.generate_bearer_token", return_value=("sa_token", None))
349+
def test_get_bearer_token_forwards_scalar_context_unmodified(self, mock_generate):
350+
"""Numbers and booleans reach the token engine as-is, with their type preserved.
351+
352+
A ctx of 123 and a ctx of "123" are different JWT claims, so a coercion here would
353+
silently change which policies match. Falsy scalars are covered too - they must not
354+
be dropped by a truthiness check.
355+
"""
356+
for scalar_context in [123, 0, 1.5, 0.0, True, False]:
357+
with self.subTest(context=scalar_context):
358+
mock_generate.reset_mock()
359+
self.vault_client._VaultClient__bearer_token = None
360+
credentials = {**CREDENTIALS_WITH_PATH, "context": scalar_context}
361+
362+
self.vault_client.get_bearer_token(credentials)
363+
364+
_, options, _ = mock_generate.call_args[0]
365+
self.assertEqual(options["ctx"], scalar_context)
366+
# assertEqual alone would pass on True vs 1, so pin the exact type.
367+
self.assertIs(type(options["ctx"]), type(scalar_context))
368+
348369
@patch("skyflow.vault.client.client.generate_bearer_token", return_value=("sa_token", None))
349370
def test_get_bearer_token_omits_options_when_roles_and_context_absent(self, mock_generate):
350371
self.vault_client.get_bearer_token(CREDENTIALS_WITH_PATH)

0 commit comments

Comments
 (0)