Skip to content

Commit 15b62f2

Browse files
authored
add email verification for creating organization (#311)
1 parent 6cdb3ac commit 15b62f2

File tree

7 files changed

+15
-7
lines changed

7 files changed

+15
-7
lines changed

.github/workflows/license-check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
with:
5151
requirements: "backend/requirements-all.txt"
5252
fail: "Copyleft,Other,Error"
53-
exclude: '(psycopg2.*2\.9\.3|fqdn.*1\.5\.1|pyzmq.*25\.1\.1|debugpy.*1\.6\.7|certifi.*2023\.11\.17|tqdm.*4\.66\.1|webencodings.*0\.5\.1|torch.*1\.10\.2.*|torch.*1\.11\.0.*|pytorch-ignite.*0\.4\.10.*|torchaudio.*0\.11\.0.*|torchvision.*0\.12\.0.*|terminado.*0\.15\.0|qudida.*0\.0\.4|expiringdict.*1\.2\.2|botocore.*1\.29\.80|orderedmultidict.*1\.0\.1|deepchecks.*)'
53+
exclude: '(psycopg2.*2\.9\.3|fqdn.*1\.5\.1|pyzmq.*25\.1\.2|debugpy.*1\.6\.7|certifi.*2023\.11\.17|tqdm.*4\.66\.1|webencodings.*0\.5\.1|torch.*1\.10\.2.*|torch.*1\.11\.0.*|pytorch-ignite.*0\.4\.10.*|torchaudio.*0\.11\.0.*|torchvision.*0\.12\.0.*|terminado.*0\.15\.0|qudida.*0\.0\.4|expiringdict.*1\.2\.2|botocore.*1\.29\.80|orderedmultidict.*1\.0\.1|deepchecks.*)'
5454
# psycopg2 is LGPL 2
5555
# pyzmq is Revised BSD https://github.com/zeromq/pyzmq/blob/main/examples/LICENSE
5656
# debugpy is MIT https://github.com/microsoft/debugpy/blob/main/LICENSE

backend/deepchecks_monitoring/ee/features_control_cloud.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ def _load_tier(self):
125125

126126
ld_user = context.build()
127127
tier_conf = self.ld_client.variation("paid-features", ld_user, default={})
128-
self._signup_enabled = self.ld_client.variation("signUpEnabled", ld_user, default=True)
128+
if getattr(self.user, "email_verified", False):
129+
self._signup_enabled = self.ld_client.variation("signUpEnabled", ld_user, default=True)
130+
else:
131+
self._signup_enabled = False
129132
tier_conf = TierConfSchema(**tier_conf)
130133
self._custom_checks_enabled = tier_conf.custom_checks
131134
self._data_retention_months = tier_conf.data_retention_months

backend/deepchecks_monitoring/ee/middlewares.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ async def wrapped_send(message: Message):
140140
"email": access_token.email,
141141
"is_admin": access_token.is_admin,
142142
"exp": access_token.exp,
143+
"email_verified": access_token.email_verified,
143144
}
144145

145146
if state and (user := state.get("user")):

backend/deepchecks_monitoring/middlewares.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def _fill_user_and_token_from_state(info, state):
2121
"email": access_token.email,
2222
"is_admin": access_token.is_admin,
2323
"exp": access_token.exp,
24+
"email_verified": access_token.email_verified,
2425
}
2526

2627
# TODO: this creates DetachedInstanceError for some reason

backend/deepchecks_monitoring/public_models/user.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class UserOAuthDTO(PydanticModel):
3636

3737
name: str
3838
email: EmailStr
39+
email_verified: t.Optional[bool] = False
3940
picture: t.Optional[AnyHttpUrl] = None
4041

4142

@@ -98,7 +99,7 @@ async def from_oauth_info(
9899
organization_id: int | None = None
99100
) -> Self:
100101
"""Create or get user instance from ouath info."""
101-
token_data = auth.UserAccessToken(email=info.email, is_admin=True)
102+
token_data = auth.UserAccessToken(email=info.email, email_verified=info.email_verified, is_admin=True)
102103
access_token = auth.create_access_token(token_data, auth_jwt_secret, expires_delta=pdl.duration(days=7))
103104

104105
# Checking if the user is already in the database

backend/deepchecks_monitoring/utils/auth.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
class UserAccessToken(BaseModel):
3434
email: EmailStr
35+
email_verified: bool
3536
is_admin: bool
3637
exp: t.Optional[float] = None
3738

@@ -54,14 +55,16 @@ async def get_user(
5455
return
5556

5657
if isinstance(token, UserAccessToken):
57-
return (await session.scalar(
58+
user = (await session.scalar(
5859
select(models.User)
5960
.where(models.User.email == token.email)
6061
.options(
6162
joinedload(models.User.organization),
6263
joinedload(models.User.roles)
6364
)
6465
))
66+
user.email_verified = token.email_verified
67+
return user
6568

6669
if isinstance(token, APIAccessToken):
6770
# If we have api token query the user and validate the secret
@@ -274,8 +277,7 @@ async def __call__(
274277
if self.enforce:
275278
raise Unauthorized("expired or invalid access token")
276279
return
277-
else:
278-
return request.state.user
280+
return request.state.user
279281

280282

281283
class CurrentActiveUser(CurrentUser):

backend/tests/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async def generate_user(
4141
f = faker.Faker()
4242
email = email or f.email()
4343
u = await User.from_oauth_info(
44-
info=UserOAuthDTO(email=email, name=f.name()),
44+
info=UserOAuthDTO(email=email, name=f.name(), email_verified=True),
4545
session=session,
4646
auth_jwt_secret=auth_jwt_secret,
4747
eula=eula

0 commit comments

Comments
 (0)