Skip to content

Commit 0600462

Browse files
authored
Merge pull request #513 from supertokens/fix/emailverification-claim
feat!: remove default maxAgeInSeconds in emailverification claim
2 parents 33c4189 + 62428c4 commit 0600462

File tree

5 files changed

+119
-22
lines changed

5 files changed

+119
-22
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [unreleased]
1010

11+
## [0.24.0] - 2024-07-10
12+
13+
### Breaking change
14+
15+
- Removes the default `max_age_in_seconds` value (previously 300 seconds) in EmailVerification Claim. If the claim value is true and `max_age_in_seconds` is not provided, it will not be refetched.
16+
1117
## [0.23.1] - 2024-07-09
1218

1319
### Changes

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383

8484
setup(
8585
name="supertokens_python",
86-
version="0.23.1",
86+
version="0.24.0",
8787
author="SuperTokens",
8888
license="Apache 2.0",
8989
author_email="[email protected]",

supertokens_python/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from __future__ import annotations
1515

1616
SUPPORTED_CDI_VERSIONS = ["3.0"]
17-
VERSION = "0.23.1"
17+
VERSION = "0.24.0"
1818
TELEMETRY = "/telemetry"
1919
USER_COUNT = "/users/count"
2020
USER_DELETE = "/user/remove"

supertokens_python/recipe/emailverification/recipe.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -280,18 +280,15 @@ def add_get_email_for_user_id_func(self, f: TypeGetEmailForUserIdFunction):
280280

281281

282282
class EmailVerificationClaimValidators(BooleanClaimValidators):
283-
def __init__(self, claim: EmailVerificationClaimClass, default_max_age_in_sec: int):
284-
super().__init__(claim, default_max_age_in_sec)
285-
# required to override the type as "int":
286-
self.default_max_age_in_sec = default_max_age_in_sec
283+
def __init__(self, claim: EmailVerificationClaimClass):
284+
super().__init__(claim, None)
287285

288286
def is_verified(
289287
self,
290288
refetch_time_on_false_in_seconds: int = 10,
291289
max_age_in_seconds: Optional[int] = None,
292290
id_: Optional[str] = None,
293291
) -> SessionClaimValidator:
294-
max_age_in_seconds = max_age_in_seconds or self.default_max_age_in_sec
295292

296293
assert isinstance(self.claim, EmailVerificationClaimClass)
297294
return IsVerifiedSCV(
@@ -305,8 +302,6 @@ def is_verified(
305302

306303
class EmailVerificationClaimClass(BooleanClaim):
307304
def __init__(self):
308-
default_max_age_in_sec = 300
309-
310305
async def fetch_value(
311306
user_id: str, _tenant_id: str, user_context: Dict[str, Any]
312307
) -> bool:
@@ -322,11 +317,9 @@ async def fetch_value(
322317
return True
323318
raise Exception("UNKNOWN_USER_ID")
324319

325-
super().__init__("st-ev", fetch_value, default_max_age_in_sec)
320+
super().__init__("st-ev", fetch_value, None)
326321

327-
self.validators = EmailVerificationClaimValidators(
328-
claim=self, default_max_age_in_sec=default_max_age_in_sec
329-
)
322+
self.validators = EmailVerificationClaimValidators(claim=self)
330323

331324

332325
EmailVerificationClaim = EmailVerificationClaimClass()
@@ -477,14 +470,13 @@ def __init__(
477470
claim: EmailVerificationClaimClass,
478471
ev_claim_validators: EmailVerificationClaimValidators,
479472
refetch_time_on_false_in_seconds: int,
480-
max_age_in_seconds: int,
473+
max_age_in_seconds: Optional[int],
481474
):
482475
super().__init__(id_)
483476
self.claim: EmailVerificationClaimClass = claim
484477
self.ev_claim_validators = ev_claim_validators
485478
self.refetch_time_on_false_in_ms = refetch_time_on_false_in_seconds * 1000
486479
self.max_age_in_sec = max_age_in_seconds
487-
self.max_age_in_ms = max_age_in_seconds * 1000
488480

489481
async def validate(
490482
self, payload: JSONObject, user_context: Dict[str, Any]
@@ -500,13 +492,16 @@ def should_refetch(
500492
if value is None:
501493
return True
502494

495+
current_time = get_timestamp_ms()
503496
last_refetch_time = self.claim.get_last_refetch_time(payload, user_context)
504497
assert last_refetch_time is not None
505498

506-
return (last_refetch_time < get_timestamp_ms() - self.max_age_in_ms) or (
507-
value is False
508-
and (
509-
last_refetch_time
510-
< (get_timestamp_ms() - self.refetch_time_on_false_in_ms)
511-
)
512-
)
499+
if self.max_age_in_sec is not None:
500+
if last_refetch_time < current_time - self.max_age_in_sec * 1000:
501+
return True
502+
503+
if value is False:
504+
if last_refetch_time < current_time - self.refetch_time_on_false_in_ms:
505+
return True
506+
507+
return False
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
2+
#
3+
# This software is licensed under the Apache License, Version 2.0 (the
4+
# "License") as published by the Apache Software Foundation.
5+
#
6+
# You may not use this file except in compliance with the License. You may
7+
# obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
from supertokens_python.recipe.emailverification import EmailVerificationClaim
16+
import time
17+
18+
19+
def test_claim_value_should_be_fetched_if_it_is_None():
20+
validator = EmailVerificationClaim.validators.is_verified()
21+
22+
should_refetch_none = validator.should_refetch({}, {})
23+
assert should_refetch_none == True
24+
25+
26+
def test_claim_value_should_be_fetched_as_per_max_age_if_provided():
27+
validator = EmailVerificationClaim.validators.is_verified(10, 200)
28+
29+
payload = {
30+
"st-ev": {
31+
"v": True,
32+
"t": int(time.time() * 1000) - 199 * 1000,
33+
}
34+
}
35+
36+
should_refetch_valid = validator.should_refetch(payload, {})
37+
assert should_refetch_valid == False
38+
39+
payload = {
40+
"st-ev": {
41+
"v": True,
42+
"t": int(time.time() * 1000) - 201 * 1000,
43+
}
44+
}
45+
46+
should_refetch_expired = validator.should_refetch(payload, {})
47+
assert should_refetch_expired == True
48+
49+
50+
def test_claim_value_should_be_fetched_as_per_refetch_time_on_false_if_provided():
51+
validator = EmailVerificationClaim.validators.is_verified(8)
52+
53+
payload = {
54+
"st-ev": {
55+
"v": False,
56+
"t": int(time.time() * 1000) - 7 * 1000,
57+
}
58+
}
59+
60+
should_refetch_valid = validator.should_refetch(payload, {})
61+
assert should_refetch_valid == False
62+
63+
payload = {
64+
"st-ev": {
65+
"v": False,
66+
"t": int(time.time() * 1000) - 9 * 1000,
67+
}
68+
}
69+
70+
should_refetch_expired = validator.should_refetch(payload, {})
71+
assert should_refetch_expired == True
72+
73+
74+
def test_claim_value_should_be_fetched_as_per_default_refetch_time_on_false_if_not_provided():
75+
validator = EmailVerificationClaim.validators.is_verified()
76+
77+
# NOTE: the default value of refetchTimeOnFalseInSeconds is 10 seconds
78+
payload = {
79+
"st-ev": {
80+
"v": False,
81+
"t": int(time.time() * 1000) - 9 * 1000,
82+
}
83+
}
84+
85+
should_refetch_valid = validator.should_refetch(payload, {})
86+
assert should_refetch_valid == False
87+
88+
payload = {
89+
"st-ev": {
90+
"v": False,
91+
"t": int(time.time() * 1000) - 11 * 1000,
92+
}
93+
}
94+
95+
should_refetch_expired = validator.should_refetch(payload, {})
96+
assert should_refetch_expired == True

0 commit comments

Comments
 (0)