Skip to content

Commit

Permalink
add email verification for creating organization (#311)
Browse files Browse the repository at this point in the history
  • Loading branch information
JKL98ISR authored Dec 7, 2023
1 parent 6cdb3ac commit 15b62f2
Show file tree
Hide file tree
Showing 7 changed files with 15 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/license-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
with:
requirements: "backend/requirements-all.txt"
fail: "Copyleft,Other,Error"
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.*)'
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.*)'
# psycopg2 is LGPL 2
# pyzmq is Revised BSD https://github.com/zeromq/pyzmq/blob/main/examples/LICENSE
# debugpy is MIT https://github.com/microsoft/debugpy/blob/main/LICENSE
Expand Down
5 changes: 4 additions & 1 deletion backend/deepchecks_monitoring/ee/features_control_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ def _load_tier(self):

ld_user = context.build()
tier_conf = self.ld_client.variation("paid-features", ld_user, default={})
self._signup_enabled = self.ld_client.variation("signUpEnabled", ld_user, default=True)
if getattr(self.user, "email_verified", False):
self._signup_enabled = self.ld_client.variation("signUpEnabled", ld_user, default=True)
else:
self._signup_enabled = False
tier_conf = TierConfSchema(**tier_conf)
self._custom_checks_enabled = tier_conf.custom_checks
self._data_retention_months = tier_conf.data_retention_months
Expand Down
1 change: 1 addition & 0 deletions backend/deepchecks_monitoring/ee/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ async def wrapped_send(message: Message):
"email": access_token.email,
"is_admin": access_token.is_admin,
"exp": access_token.exp,
"email_verified": access_token.email_verified,
}

if state and (user := state.get("user")):
Expand Down
1 change: 1 addition & 0 deletions backend/deepchecks_monitoring/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def _fill_user_and_token_from_state(info, state):
"email": access_token.email,
"is_admin": access_token.is_admin,
"exp": access_token.exp,
"email_verified": access_token.email_verified,
}

# TODO: this creates DetachedInstanceError for some reason
Expand Down
3 changes: 2 additions & 1 deletion backend/deepchecks_monitoring/public_models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class UserOAuthDTO(PydanticModel):

name: str
email: EmailStr
email_verified: t.Optional[bool] = False
picture: t.Optional[AnyHttpUrl] = None


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

# Checking if the user is already in the database
Expand Down
8 changes: 5 additions & 3 deletions backend/deepchecks_monitoring/utils/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

class UserAccessToken(BaseModel):
email: EmailStr
email_verified: bool
is_admin: bool
exp: t.Optional[float] = None

Expand All @@ -54,14 +55,16 @@ async def get_user(
return

if isinstance(token, UserAccessToken):
return (await session.scalar(
user = (await session.scalar(
select(models.User)
.where(models.User.email == token.email)
.options(
joinedload(models.User.organization),
joinedload(models.User.roles)
)
))
user.email_verified = token.email_verified
return user

if isinstance(token, APIAccessToken):
# If we have api token query the user and validate the secret
Expand Down Expand Up @@ -274,8 +277,7 @@ async def __call__(
if self.enforce:
raise Unauthorized("expired or invalid access token")
return
else:
return request.state.user
return request.state.user


class CurrentActiveUser(CurrentUser):
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async def generate_user(
f = faker.Faker()
email = email or f.email()
u = await User.from_oauth_info(
info=UserOAuthDTO(email=email, name=f.name()),
info=UserOAuthDTO(email=email, name=f.name(), email_verified=True),
session=session,
auth_jwt_secret=auth_jwt_secret,
eula=eula
Expand Down

0 comments on commit 15b62f2

Please sign in to comment.