Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: added email verifications #34

Open
wants to merge 77 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
40df4ac
feat: added invitation templates
Aydawka Nov 28, 2023
b75d708
fix: added invitation function
Aydawka Nov 28, 2023
22b85ba
fix: email invitation templates
Aydawka Nov 28, 2023
391ca96
style: 🎨 fix code style issues with Black
lint-action Nov 28, 2023
3361449
chore: added flask mail
Aydawka Nov 28, 2023
427bffa
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Nov 28, 2023
0b5d2ef
fix: refactor invited_contributors table name to invite
Aydawka Nov 28, 2023
84abecd
fix: study invitation templates
Aydawka Nov 28, 2023
3a0c2f3
fix: email verification
Aydawka Dec 11, 2023
13565c1
fix: database changes through migrations
Aydawka Dec 12, 2023
90861e9
fix: model changes for verification
Aydawka Dec 12, 2023
aa1c7cb
fix: alembic revisions for email verification table
Aydawka Dec 14, 2023
214cb4d
fix: email verification ands resend endpoint
Aydawka Dec 14, 2023
f89d26b
wip: notification endpoint
Aydawka Dec 14, 2023
3eb58f3
style: 🎨 fix code style issues with Black
lint-action Dec 14, 2023
08b8780
fix: alembic email verification revision
Aydawka Dec 14, 2023
ed61089
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 14, 2023
d4ff6d6
style: 🎨 fix code style issues with Black
lint-action Dec 14, 2023
93f6d82
feat: added checkings to the alembic revisions
Aydawka Dec 15, 2023
fd87dec
fix: format
Aydawka Dec 15, 2023
cfc9199
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 15, 2023
5ca5925
style: 🎨 fix code style issues with Black
lint-action Dec 15, 2023
5c46c81
fix: revisions
Aydawka Dec 15, 2023
c8fe6d8
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 15, 2023
2a94260
style: 🎨 fix code style issues with Black
lint-action Dec 15, 2023
9864097
fix: testing
Aydawka Dec 15, 2023
e3406dc
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 15, 2023
3f2be41
fix: docker file
Aydawka Dec 15, 2023
8e36faa
fix: model class and docker file
Aydawka Dec 15, 2023
b8dacec
fix: testing constraint added
Aydawka Dec 15, 2023
10ac61d
merge: branch staging into email-invitations
Aydawka Dec 16, 2023
87f98e6
fix: testing environment added for notifications
Aydawka Dec 18, 2023
31147a7
fix: added test env to contributors
Aydawka Dec 18, 2023
8af5354
fix: deleted script from template
Aydawka Dec 18, 2023
3977af5
style: 🎨 fix code style issues with Black
lint-action Dec 18, 2023
114db97
fix: final revisions for testing
Aydawka Dec 18, 2023
7bad7a3
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 18, 2023
e15bc1b
style: 🎨 fix code style issues with Black
lint-action Dec 18, 2023
5e07e19
fix: modify db using alembic
Aydawka Dec 19, 2023
5766eca
fix: set up config file for localhost
Aydawka Dec 19, 2023
814b8ed
fix: invitation templates
Aydawka Dec 19, 2023
ffd8374
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 19, 2023
712b056
style: 🎨 fix code style issues with Black
lint-action Dec 19, 2023
27a1853
fix: email invitations
Aydawka Dec 20, 2023
149a540
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 20, 2023
78df1eb
Merge branch 'staging' into email-invitations
Aydawka Dec 20, 2023
6de5919
fix: added feature flag
Aydawka Dec 21, 2023
2df3f7d
fix: flask mailman
Aydawka Dec 21, 2023
bb0b68d
fix: remove auth duplication
Aydawka Dec 21, 2023
de117c3
fix: final revisions for emails
Aydawka Dec 21, 2023
45bfc15
style: 🎨 fix code style issues with Black
lint-action Dec 21, 2023
52534c3
Merge branch 'staging' into email-invitations
Aydawka Dec 21, 2023
875d9c3
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Dec 21, 2023
726ebfc
fix: poetry lock
Aydawka Dec 21, 2023
a15eb8e
fix: authentication for email verification
Aydawka Dec 21, 2023
e7445b8
fix: disabled alembic revisions
Aydawka Dec 21, 2023
a31d92c
fix: removed comment
Aydawka Dec 21, 2023
3adbbd1
fix: upgrade destroy schema to remove alembic table
Aydawka Dec 21, 2023
f3ea8a8
style: 🎨 fix code style issues with Black
lint-action Dec 21, 2023
d63e539
fix: format
Aydawka Jan 8, 2024
0679446
Merge remote-tracking branch 'origin/email-invitations' into email-in…
Aydawka Jan 8, 2024
1e5e157
fix: sort testing files
Aydawka Jan 9, 2024
816c26e
fix: sort testing files
Aydawka Jan 10, 2024
332617f
merge: staging into email invitations
Aydawka May 23, 2024
599e550
fix: additional details from staging
Aydawka May 23, 2024
581f0de
fix: modify template style
Aydawka May 28, 2024
b9f2500
style: minor email sending typo
Aydawka May 28, 2024
2662316
feat: add azure EmailClient system
Aydawka May 28, 2024
00da7a5
style: format
Aydawka May 28, 2024
3e8cacf
➕ chore: add dependency
megasanjay May 28, 2024
790866a
➕ chore: add dependency
megasanjay May 28, 2024
c241e37
style: template formats
Aydawka May 29, 2024
b78b87c
fix: email confirmation direction if verification is False
Aydawka May 30, 2024
7c007d8
fix: test issue
Aydawka May 30, 2024
9b13bb3
fix: test issue
Aydawka Jun 12, 2024
1d60710
chore: replace email names
Aydawka Jul 24, 2024
1d3ab5a
style: format
Aydawka Jul 24, 2024
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
24 changes: 24 additions & 0 deletions alembic/versions_backup/6173282aef08_remove_invite_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""remove_invite_info

Revision ID: 6173282aef08
Revises: f150341d2741
Create Date: 2023-12-19 00:32:08.157538

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "6173282aef08"
down_revision: Union[str, None] = "f150341d2741"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.drop_column("invite", "info")
with op.batch_alter_table("notification") as batch_op:
batch_op.alter_column("target", nullable=True)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from typing import Sequence, Union

import alembic
import sqlalchemy as sa


# revision identifiers, used by Alembic.
Expand Down
38 changes: 38 additions & 0 deletions alembic/versions_backup/95d6e53e2578_edit_invite_table_pk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""edit invite table PK

Revision ID: 95d6e53e2578
Revises: db1b62d02def
Create Date: 2023-11-28 14:58:43.869472

"""
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
revision: str = "95d6e53e2578"
down_revision: Union[str, None] = "db1b62d02def"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade():
connection = op.get_bind()
inspector = sa.inspect(connection)

# Check if the table exists before dropping it
# if not inspector.has_table("invite"):
# if 'id' not in inspector.get_columns("invite"):
op.add_column("invite", sa.Column("id", sa.CHAR(36), nullable=True))
op.execute(
"UPDATE invite SET id = uuid_in(overlay(overlay(md5(random()::text || ':' "
"|| random()::text) placing '4' from 13) placing to_hex(floor(random()*(11-8+1) + 8)::int)"
"::text from 17)::cstring);"
)
op.execute("ALTER TABLE invite DROP CONSTRAINT invited_study_contributor_pkey")

op.create_primary_key("id", "invite", ["id"])
with op.batch_alter_table("invite") as batch_op:
batch_op.alter_column("study_id", nullable=True)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""delete_token_fron_user_table

Revision ID: b20e07d8924f
Revises: f189827ee101
Create Date: 2023-12-13 13:31:38.810816

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "b20e07d8924f"
down_revision: Union[str, None] = "f189827ee101"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.drop_column("user", "token")
op.drop_column("user", "token_generated")


def downgrade() -> None:
pass
25 changes: 25 additions & 0 deletions alembic/versions_backup/db1b62d02def_edit_invite_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""edit invite table

Revision ID: db1b62d02def
Revises: 72ac2b020c7c
Create Date: 2023-11-28 13:56:41.821141

"""
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op


revision: str = "db1b62d02def"
down_revision: Union[str, None] = "72ac2b020c7c"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.rename_table("invited_study_contributor", "invite")
op.add_column("invite", sa.Column("info", sa.String(), nullable=True))
op.create_unique_constraint(
"study_per_user", "invite", ["study_id", "email_address"]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""role_nullable_and_fk_user_id

Revision ID: eee9610b2cdc
Revises: 95d6e53e2578
Create Date: 2023-12-01 00:09:44.745776

"""
from typing import Sequence, Union

import sqlalchemy as sa
import datetime
import uuid
from alembic import op


# revision identifiers, used by Alembic.
revision: str = "eee9610b2cdc"
down_revision: Union[str, None] = "95d6e53e2578"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

created_at = int(datetime.datetime.now(datetime.timezone.utc).timestamp())

id = str(uuid.uuid4())
hashed = str(uuid.uuid4())


def upgrade() -> None:
op.add_column("invite", sa.Column("user_id", sa.CHAR(36)))
op.execute(
f'INSERT INTO "user" ("id", "email_address", "username", "hash", "created_at", "email_verified") VALUES '
f"('{id}', '[email protected]', 'eee9610b2cdc', '{hashed}', '{created_at}', False)"
)

user_obj = f"SELECT * FROM user WHERE id = '{id}'"
if len(user_obj) < 1:
return "error", 403
op.execute(f"UPDATE invite SET user_id ='{id}'")

with op.batch_alter_table("invite") as batch_op:
batch_op.alter_column("permission", nullable=True)
batch_op.alter_column("user_id", nullable=False)
op.create_foreign_key(
"fk_user_id",
"invite",
"user",
["user_id"],
["id"],
)

with op.batch_alter_table("notification") as batch_op:
batch_op.alter_column("title", nullable=False)
batch_op.alter_column("message", nullable=False)
batch_op.alter_column("type", nullable=False)
batch_op.alter_column("target", nullable=False)
batch_op.alter_column("read", nullable=False)
35 changes: 35 additions & 0 deletions alembic/versions_backup/f150341d2741_modify_email_verification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""modify_email_verification

Revision ID: f150341d2741
Revises: b20e07d8924f
Create Date: 2023-12-13 20:43:24.637259

"""
from typing import Sequence, Union

import sqlalchemy as sa
import datetime
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "f150341d2741"
down_revision: Union[str, None] = "b20e07d8924f"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

created_at = int(datetime.datetime.now(datetime.timezone.utc).timestamp())


def upgrade() -> None:
op.alter_column("email_verification", "token", type_=sa.String)
op.alter_column("email_verification", "user_id", type_=sa.CHAR(36))

op.drop_column("email_verification", "created_at")

op.add_column(
"email_verification", sa.Column("created_at", sa.BIGINT(), nullable=True)
)

op.execute(f"UPDATE \"email_verification\" SET created_at ='{created_at}'")

op.alter_column("email_verification", "created_at", nullable=False)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""user_table_email_verfication

Revision ID: f189827ee101
Revises: fed13d793eff
Create Date: 2023-12-11 14:54:31.303523

"""
from typing import Sequence, Union
import sqlalchemy as sa
import datetime
import random
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "f189827ee101"
down_revision: Union[str, None] = "fed13d793eff"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
token_generated = int(datetime.datetime.now(datetime.timezone.utc).timestamp())
token = random.randint(10 ** (7 - 1), (10**7) - 1)


def upgrade():
op.add_column("user", sa.Column("token_generated", sa.BIGINT, nullable=True))
op.add_column("user", sa.Column("token", sa.String, nullable=True))
op.execute(f"UPDATE \"user\" SET token_generated ='{token_generated}'")
op.execute(f"UPDATE \"user\" SET token ='{token}'")
op.execute("UPDATE invite SET info ='info'")
op.execute(f'UPDATE "user" SET email_verified = FALSE')

with op.batch_alter_table("user") as batch_op:
batch_op.alter_column("token", nullable=False)
batch_op.alter_column("token_generated", nullable=False)
batch_op.alter_column("email_verified", nullable=False)
with op.batch_alter_table("invite") as batch_op:
batch_op.alter_column("info", nullable=False)
27 changes: 27 additions & 0 deletions alembic/versions_backup/fed13d793eff_email_verified_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""email_verified_type

Revision ID: fed13d793eff
Revises: eee9610b2cdc
Create Date: 2023-12-05 16:03:51.166254

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "fed13d793eff"
down_revision: Union[str, None] = "eee9610b2cdc"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
with op.batch_alter_table("user") as batch_op:
batch_op.alter_column(
"email_verified",
type_=sa.Boolean(),
postgresql_using="email_verified::boolean",
)
5 changes: 3 additions & 2 deletions apis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Initialize the api system for the backend"""
from flask_restx import Api, Resource

from apis.dataset_metadata_namespace import api as dataset_metadata_namespace
from apis.study_metadata_namespace import api as study_metadata_namespace

Expand All @@ -22,6 +21,7 @@
from .dataset_metadata.dataset_subject import api as subject
from .dataset_metadata.dataset_title import api as title
from .file import api as file_api
from .invite_users import api as invite_general_users
from .participant import api as participants_api
from .study import api as study_api
from .study_metadata.study_arm import api as arm
Expand Down Expand Up @@ -88,12 +88,14 @@
"identification",
"study_description",
"dataset_contributor",
"invite_general_users",
]


api.add_namespace(dataset_metadata_namespace)
api.add_namespace(study_metadata_namespace)
api.add_namespace(authentication)
api.add_namespace(invite_general_users)


@api.route("/echo", endpoint="echo")
Expand All @@ -104,7 +106,6 @@ class HelloEverynyan(Resource):
@api.response(400, "Validation Error")
def get(self):
"""Returns a simple 'Server Active' message"""

return "Server active!"


Expand Down
Loading
Loading