Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions okta/models/access_policy_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,24 @@ def methods_validate_enum(cls, value):
for i in value:
if i not in set(
[
"PASSWORD",
"SECURITY_QUESTION",
"SMS",
"VOICE",
"EMAIL",
"PUSH",
"SIGNED_NONCE",
"OTP",
"TOTP",
"WEBAUTHN",
"DUO",
"IDP",
"CERT",
"password",
"security_question",
"sms",
"voice",
"email",
"push",
"signed_nonce",
"otp",
"totp",
"webauthn",
"duo",
"idp",
"cert",
]
):
raise ValueError(
"each list item must be one of ('PASSWORD', 'SECURITY_QUESTION', 'SMS', 'VOICE', 'EMAIL', 'PUSH', "
"'SIGNED_NONCE', 'OTP', 'TOTP', 'WEBAUTHN', 'DUO', 'IDP', 'CERT')"
"each list item must be one of ('password', 'security_question', 'sms', 'voice', 'email', 'push', "
"'signed_nonce', 'otp', 'totp', 'webauthn', 'duo', 'idp', 'cert')"
)
return value

Expand All @@ -129,18 +129,18 @@ def types_validate_enum(cls, value):
for i in value:
if i not in set(
[
"SECURITY_KEY",
"PHONE",
"EMAIL",
"PASSWORD",
"SECURITY_QUESTION",
"APP",
"FEDERATED",
"security_key",
"phone",
"email",
"password",
"security_question",
"app",
"federated",
]
):
raise ValueError(
"each list item must be one of ('SECURITY_KEY', 'PHONE', 'EMAIL', 'PASSWORD', 'SECURITY_QUESTION', "
"'APP', 'FEDERATED')"
"each list item must be one of ('security_key', 'phone', 'email', 'password', 'security_question', "
"'app', 'federated')"
)
return value

Expand Down
48 changes: 24 additions & 24 deletions okta/models/knowledge_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,24 @@ def methods_validate_enum(cls, value):
for i in value:
if i not in set(
[
"PASSWORD",
"SECURITY_QUESTION",
"SMS",
"VOICE",
"EMAIL",
"PUSH",
"SIGNED_NONCE",
"OTP",
"TOTP",
"WEBAUTHN",
"DUO",
"IDP",
"CERT",
"password",
"security_question",
"sms",
"voice",
"email",
"push",
"signed_nonce",
"otp",
"totp",
"webauthn",
"duo",
"idp",
"cert",
]
):
raise ValueError(
"each list item must be one of ('PASSWORD', 'SECURITY_QUESTION', 'SMS', 'VOICE', 'EMAIL', 'PUSH', "
"'SIGNED_NONCE', 'OTP', 'TOTP', 'WEBAUTHN', 'DUO', 'IDP', 'CERT')"
"each list item must be one of ('password', 'security_question', 'sms', 'voice', 'email', 'push', "
"'signed_nonce', 'otp', 'totp', 'webauthn', 'duo', 'idp', 'cert')"
)
return value

Expand All @@ -126,18 +126,18 @@ def types_validate_enum(cls, value):
for i in value:
if i not in set(
[
"SECURITY_KEY",
"PHONE",
"EMAIL",
"PASSWORD",
"SECURITY_QUESTION",
"APP",
"FEDERATED",
"security_key",
"phone",
"email",
"password",
"security_question",
"app",
"federated",
]
):
raise ValueError(
"each list item must be one of ('SECURITY_KEY', 'PHONE', 'EMAIL', 'PASSWORD', 'SECURITY_QUESTION', "
"'APP', 'FEDERATED')"
"each list item must be one of ('security_key', 'phone', 'email', 'password', 'security_question', "
"'app', 'federated')"
)
return value

Expand Down
48 changes: 24 additions & 24 deletions okta/models/possession_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,24 +137,24 @@ def methods_validate_enum(cls, value):
for i in value:
if i not in set(
[
"PASSWORD",
"SECURITY_QUESTION",
"SMS",
"VOICE",
"EMAIL",
"PUSH",
"SIGNED_NONCE",
"OTP",
"TOTP",
"WEBAUTHN",
"DUO",
"IDP",
"CERT",
"password",
"security_question",
"sms",
"voice",
"email",
"push",
"signed_nonce",
"otp",
"totp",
"webauthn",
"duo",
"idp",
"cert",
]
):
raise ValueError(
"each list item must be one of ('PASSWORD', 'SECURITY_QUESTION', 'SMS', 'VOICE', 'EMAIL', 'PUSH', "
"'SIGNED_NONCE', 'OTP', 'TOTP', 'WEBAUTHN', 'DUO', 'IDP', 'CERT')"
"each list item must be one of ('password', 'security_question', 'sms', 'voice', 'email', 'push', "
"'signed_nonce', 'otp', 'totp', 'webauthn', 'duo', 'idp', 'cert')"
)
return value

Expand All @@ -167,18 +167,18 @@ def types_validate_enum(cls, value):
for i in value:
if i not in set(
[
"SECURITY_KEY",
"PHONE",
"EMAIL",
"PASSWORD",
"SECURITY_QUESTION",
"APP",
"FEDERATED",
"security_key",
"phone",
"email",
"password",
"security_question",
"app",
"federated",
]
):
raise ValueError(
"each list item must be one of ('SECURITY_KEY', 'PHONE', 'EMAIL', 'PASSWORD', 'SECURITY_QUESTION', "
"'APP', 'FEDERATED')"
"each list item must be one of ('security_key', 'phone', 'email', 'password', 'security_question', "
"'app', 'federated')"
)
return value

Expand Down
40 changes: 20 additions & 20 deletions openapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57789,19 +57789,19 @@ components:
items:
type: string
enum:
- PASSWORD
- SECURITY_QUESTION
- SMS
- VOICE
- EMAIL
- PUSH
- SIGNED_NONCE
- OTP
- TOTP
- WEBAUTHN
- DUO
- IDP
- CERT
- password
- security_question
- sms
- voice
- email
- push
- signed_nonce
- otp
- totp
- webauthn
- duo
- idp
- cert
type: array
reauthenticateIn:
description: The duration after which the user must re-authenticate regardless of user activity. This re-authentication interval overrides the Verification Method object's `reauthenticateIn` interval. The supported values use ISO 8601 period format for recurring time intervals (for example, `PT1H`).
Expand All @@ -57814,13 +57814,13 @@ components:
items:
type: string
enum:
- SECURITY_KEY
- PHONE
- EMAIL
- PASSWORD
- SECURITY_QUESTION
- APP
- FEDERATED
- security_key
- phone
- email
- password
- security_question
- app
- federated
type: array
AccessPolicyConstraints:
description: Specifies constraints for the authenticator. Constraints are logically evaluated such that only one constraint object needs to be satisfied. But, within a constraint object, each constraint property must be satisfied.
Expand Down
126 changes: 126 additions & 0 deletions tests/test_access_policy_constraint_enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# The Okta software accompanied by this notice is provided pursuant to the following terms:
# Copyright © 2025-Present, Okta, Inc.
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
# License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under the License.
# coding: utf-8

"""
Unit tests verifying that `methods` and `types` enum validators on
`AccessPolicyConstraint`, `KnowledgeConstraint`, and `PossessionConstraint`
accept lowercase values (matching the live Okta API response casing) and
reject UPPERCASE / invalid values.

Related: Alignment of OAS3 enum casing with the API.
"""

import pytest
from pydantic import ValidationError

from okta.models.access_policy_constraint import AccessPolicyConstraint
from okta.models.knowledge_constraint import KnowledgeConstraint
from okta.models.possession_constraint import PossessionConstraint


VALID_METHODS = [
"password", "security_question", "sms", "voice", "email",
"push", "signed_nonce", "otp", "totp", "webauthn", "duo", "idp", "cert",
]
VALID_TYPES = [
"security_key", "phone", "email", "password",
"security_question", "app", "federated",
]


class TestAccessPolicyConstraintEnums:
"""Validator tests for the base `AccessPolicyConstraint` model."""

def test_lowercase_methods_accepted(self):
obj = AccessPolicyConstraint(methods=["password", "push", "webauthn"])
assert obj.methods == ["password", "push", "webauthn"]

def test_lowercase_types_accepted(self):
obj = AccessPolicyConstraint(types=["password", "security_key", "phone"])
assert obj.types == ["password", "security_key", "phone"]

def test_all_valid_methods_accepted(self):
obj = AccessPolicyConstraint(methods=list(VALID_METHODS))
assert obj.methods == VALID_METHODS

def test_all_valid_types_accepted(self):
obj = AccessPolicyConstraint(types=list(VALID_TYPES))
assert obj.types == VALID_TYPES

def test_uppercase_methods_rejected(self):
with pytest.raises(ValidationError):
AccessPolicyConstraint(methods=["PASSWORD"])

def test_uppercase_types_rejected(self):
with pytest.raises(ValidationError):
AccessPolicyConstraint(types=["PASSWORD"])

def test_unknown_method_rejected(self):
with pytest.raises(ValidationError):
AccessPolicyConstraint(methods=["not_a_real_method"])

def test_unknown_type_rejected(self):
with pytest.raises(ValidationError):
AccessPolicyConstraint(types=["not_a_real_type"])

def test_from_dict_lowercase_payload(self):
"""Simulates a real API response payload."""
payload = {
"methods": ["password", "push"],
"types": ["password"],
"required": True,
"reauthenticateIn": "PT2H",
}
obj = AccessPolicyConstraint.from_dict(payload)
assert obj.methods == ["password", "push"]
assert obj.types == ["password"]
assert obj.required is True
assert obj.reauthenticate_in == "PT2H"


class TestKnowledgeConstraintEnums:
"""Validator tests for `KnowledgeConstraint` (inherits the same enums)."""

def test_lowercase_methods_accepted(self):
obj = KnowledgeConstraint(methods=["password"])
assert obj.methods == ["password"]

def test_lowercase_types_accepted(self):
obj = KnowledgeConstraint(types=["password", "security_question"])
assert obj.types == ["password", "security_question"]

def test_uppercase_methods_rejected(self):
with pytest.raises(ValidationError):
KnowledgeConstraint(methods=["PASSWORD"])

def test_uppercase_types_rejected(self):
with pytest.raises(ValidationError):
KnowledgeConstraint(types=["PASSWORD"])


class TestPossessionConstraintEnums:
"""Validator tests for `PossessionConstraint` (inherits the same enums)."""

def test_lowercase_methods_accepted(self):
obj = PossessionConstraint(methods=["push", "signed_nonce", "webauthn"])
assert obj.methods == ["push", "signed_nonce", "webauthn"]

def test_lowercase_types_accepted(self):
obj = PossessionConstraint(types=["security_key", "phone"])
assert obj.types == ["security_key", "phone"]

def test_uppercase_methods_rejected(self):
with pytest.raises(ValidationError):
PossessionConstraint(methods=["PUSH"])

def test_uppercase_types_rejected(self):
with pytest.raises(ValidationError):
PossessionConstraint(types=["SECURITY_KEY"])