From 49f5edfe29e63aa1c41a5c93be15da3882c75f62 Mon Sep 17 00:00:00 2001 From: dandds Date: Thu, 25 Oct 2018 11:25:58 -0400 Subject: [PATCH] new workspace members are provisional until they log in for the first time --- ...c1ac77c_add_provisional_column_to_users.py | 28 +++++++++++++++++++ atst/domain/users.py | 9 ++++++ atst/domain/workspaces/workspaces.py | 1 + atst/models/user.py | 4 ++- atst/routes/__init__.py | 4 +++ tests/domain/test_workspaces.py | 17 +++++++++++ tests/test_auth.py | 14 ++++++++++ 7 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 alembic/versions/5284ac1ac77c_add_provisional_column_to_users.py diff --git a/alembic/versions/5284ac1ac77c_add_provisional_column_to_users.py b/alembic/versions/5284ac1ac77c_add_provisional_column_to_users.py new file mode 100644 index 00000000..8ad52723 --- /dev/null +++ b/alembic/versions/5284ac1ac77c_add_provisional_column_to_users.py @@ -0,0 +1,28 @@ +"""add provisional column to users + +Revision ID: 5284ac1ac77c +Revises: 25bcba9b99a9 +Create Date: 2018-10-25 11:04:49.879393 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '5284ac1ac77c' +down_revision = '25bcba9b99a9' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('users', sa.Column('provisional', sa.Boolean(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('users', 'provisional') + # ### end Alembic commands ### diff --git a/atst/domain/users.py b/atst/domain/users.py index 7494f5f4..97947080 100644 --- a/atst/domain/users.py +++ b/atst/domain/users.py @@ -89,3 +89,12 @@ class Users(object): db.session.commit() return user + + @classmethod + def finalize(cls, user): + user.provisional = False + + db.session.add(user) + db.session.commit() + + return user diff --git a/atst/domain/workspaces/workspaces.py b/atst/domain/workspaces/workspaces.py index f8e2c560..dc2f4202 100644 --- a/atst/domain/workspaces/workspaces.py +++ b/atst/domain/workspaces/workspaces.py @@ -86,6 +86,7 @@ class Workspaces(object): last_name=data["last_name"], email=data["email"], atat_role_name="default", + provisional=True, ) return Workspaces.add_member(workspace, new_user, data["workspace_role"]) diff --git a/atst/models/user.py b/atst/models/user.py index bb89c51b..5f8765dd 100644 --- a/atst/models/user.py +++ b/atst/models/user.py @@ -1,4 +1,4 @@ -from sqlalchemy import String, ForeignKey, Column, Date +from sqlalchemy import String, ForeignKey, Column, Date, Boolean from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID @@ -26,6 +26,8 @@ class User(Base, mixins.TimestampsMixin, mixins.AuditableMixin): designation = Column(String) date_latest_training = Column(Date) + provisional = Column(Boolean) + @property def atat_permissions(self): return self.atat_role.permissions diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py index 5051ad5a..0149ace5 100644 --- a/atst/routes/__init__.py +++ b/atst/routes/__init__.py @@ -101,6 +101,10 @@ def login_redirect(): auth_context = _make_authentication_context() auth_context.authenticate() user = auth_context.get_user() + + if user.provisional: + Users.finalize(user) + session["user_id"] = user.id return redirect(redirect_after_login_url()) diff --git a/tests/domain/test_workspaces.py b/tests/domain/test_workspaces.py index 86064c1e..79d8c57b 100644 --- a/tests/domain/test_workspaces.py +++ b/tests/domain/test_workspaces.py @@ -86,6 +86,23 @@ def test_can_create_workspace_user(workspace, workspace_owner): new_member = Workspaces.create_member(workspace_owner, workspace, user_data) assert new_member.workspace == workspace + assert new_member.user.provisional + + +def test_can_add_existing_user_to_workspace(workspace, workspace_owner): + user = UserFactory.create() + user_data = { + "first_name": "New", + "last_name": "User", + "email": "new.user@mail.com", + "workspace_role": "developer", + "dod_id": user.dod_id, + } + + new_member = Workspaces.create_member(workspace_owner, workspace, user_data) + assert new_member.workspace == workspace + assert new_member.user.email == user.email + assert not new_member.user.provisional def test_need_permission_to_create_workspace_user(workspace, workspace_owner): diff --git a/tests/test_auth.py b/tests/test_auth.py index 099dc4ec..13a6896c 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -211,3 +211,17 @@ def test_redirected_on_login(client, monkeypatch): target_route = url_for("requests.requests_form_new", screen=1) response = _login(client, next=target_route) assert target_route in response.headers.get("Location") + + +def test_invited_user_finalized_on_login(monkeypatch, client): + user = UserFactory.create(provisional=True) + monkeypatch.setattr( + "atst.domain.authnid.AuthenticationContext.authenticate", lambda *args: True + ) + monkeypatch.setattr( + "atst.domain.authnid.AuthenticationContext.get_user", lambda *args: user + ) + + resp = _login(client) + + assert not user.provisional