From 610a7898bb3821b78a36d263445112beca56d645 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:15:40 -0400 Subject: [PATCH 01/13] create a `user_can` method in template context, to check against user permissions add user permissions list to template context --- atst/routes/workspaces.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index 64faac94..ce0def86 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -12,10 +12,11 @@ from atst.domain.workspaces import Workspaces from atst.domain.projects import Projects from atst.forms.new_project import NewProjectForm from atst.forms.new_member import NewMemberForm +from atst.domain.authz import Authorization +from atst.models.permissions import Permissions bp = Blueprint("workspaces", __name__) - @bp.context_processor def workspace(): workspace = None @@ -26,8 +27,17 @@ def workspace(): ) except UnauthorizedError: pass - return {"workspace": workspace} + def user_can(permission): + if workspace: + return Authorization.has_workspace_permission(g.current_user, workspace, permission) + return false + + return { + "workspace": workspace, + "permissions": Permissions, + "user_can": user_can + } @bp.route("/workspaces") def workspaces(): From 8d8b769673fd6744782f9be6ca4a22afb8a53c51 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:16:11 -0400 Subject: [PATCH 02/13] Add sub_message to EmptyState component Change params to camel case --- templates/components/empty_state.html | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/templates/components/empty_state.html b/templates/components/empty_state.html index 7dc6f119..b0aaa038 100644 --- a/templates/components/empty_state.html +++ b/templates/components/empty_state.html @@ -1,13 +1,20 @@ {% from "components/icon.html" import Icon %} -{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%} +{% macro EmptyState(message, action_label, action_href, icon=None, sub_message=None) -%}
-

{{ message }}

+

{{ message }}

{% if icon %} {{ Icon(icon) }} {% endif %} - {{ actionLabel }} + {% if sub_message %} +

{{ sub_message }}

+ {% endif %} + + {% if action_href and action_label %} + {{ action_label }} + {% endif %} +
{%- endmacro %} From 8c6785f0f13c5fde7b91deffdce310c95a216abe Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:16:25 -0400 Subject: [PATCH 03/13] use camel case --- templates/workspace_members.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/workspace_members.html b/templates/workspace_members.html index 6fb852cb..29ac055d 100644 --- a/templates/workspace_members.html +++ b/templates/workspace_members.html @@ -8,8 +8,8 @@ {{ EmptyState( 'There are currently no members in this Workspace.', - actionLabel='Invite a new Member', - actionHref='/members/new', + action_label='Invite a new Member', + action_href='/members/new', icon='avatar' ) }} From 2c5bad75a5adcdc4a2fd48dd1ec11c4ad6156c59 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:17:28 -0400 Subject: [PATCH 04/13] use camel case --- templates/requests.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/requests.html b/templates/requests.html index 85190baf..31f2c7d1 100644 --- a/templates/requests.html +++ b/templates/requests.html @@ -29,8 +29,8 @@ {{ EmptyState( 'There are currently no active requests for you to see.', - actionLabel='Create a new JEDI Cloud Request', - actionHref=url_for('requests.requests_form_new', screen=1), + action_label='Create a new JEDI Cloud Request', + action_href=url_for('requests.requests_form_new', screen=1), icon='document' ) }} From 0dd350112cf439a5c91869b86f36e8355596a538 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:17:58 -0400 Subject: [PATCH 05/13] Display Empty State component on workspace project Adjust button and message depending on user permissions --- templates/workspace_projects.html | 71 ++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/templates/workspace_projects.html b/templates/workspace_projects.html index d2af0e17..fc9a0eb1 100644 --- a/templates/workspace_projects.html +++ b/templates/workspace_projects.html @@ -1,36 +1,57 @@ {% from "components/icon.html" import Icon %} {% from "components/alert.html" import Alert %} +{% from "components/empty_state.html" import EmptyState %} {% extends "base_workspace.html" %} + {% block workspace_content %} -{% for project in workspace.projects %} -
-
-

{{ project.name }} ({{ project.environments|length }} environments)

- - {{ Icon('edit') }} - edit - -
- -
-{% endfor %} + {% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %} + {% set sub_message = None if can_create_projects else 'Please contact your workspace administrator to set up a new project.' %} + {% set action_label = 'Add a New Project' if can_create_projects else None %} + {% set action_href = url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None %} + + {{ EmptyState( + 'This workspace doesn’t have any projects yet.', + action_label=action_label, + action_href=action_href, + icon='cloud', + sub_message=sub_message + ) }} + +{% else %} + + {% for project in workspace.projects %} +
+
+

{{ project.name }} ({{ project.environments|length }} environments)

+ + {{ Icon('edit') }} + edit + +
+ +
+ {% endfor %} + +{% endif %} {% endblock %} From 853923856696b2bfc628eba2b6636048ac742e34 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:18:35 -0400 Subject: [PATCH 06/13] Only show "Add New Project" subnav if user has permissions to do so --- templates/navigation/workspace_navigation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/navigation/workspace_navigation.html b/templates/navigation/workspace_navigation.html index a3de6043..92393f30 100644 --- a/templates/navigation/workspace_navigation.html +++ b/templates/navigation/workspace_navigation.html @@ -6,7 +6,7 @@ "Projects", href=url_for("workspaces.workspace_projects", workspace_id=workspace.id), active=request.url_rule.rule.startswith('/workspaces//projects'), - subnav=[ + subnav=None if not user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) else [ { "label": "Add New Project", "href": url_for('workspaces.new_project', workspace_id=workspace.id), From e60cf161700911b4927f6c93c0177db6a5f3e4fa Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:18:52 -0400 Subject: [PATCH 07/13] Empty stat message and submessage styles --- styles/components/_empty_state.scss | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/styles/components/_empty_state.scss b/styles/components/_empty_state.scss index be8675ad..6117484b 100644 --- a/styles/components/_empty_state.scss +++ b/styles/components/_empty_state.scss @@ -14,7 +14,7 @@ @include icon-color($color-gray-light); } - p { + .empty-state__message { @include h2; line-height: 1.2; max-width: 15em; @@ -24,4 +24,13 @@ @include h1; } } + + .empty-state__sub-message { + @include h4; + color: $color-gray; + + @include media($large-screen) { + @include h3; + } + } } From 0af5b6a1b4ab19e6d8a7b5a7f880b62f829e1923 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:27:01 -0400 Subject: [PATCH 08/13] remove unnecessary vars being set --- templates/workspace_projects.html | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/templates/workspace_projects.html b/templates/workspace_projects.html index fc9a0eb1..0ad2d6ef 100644 --- a/templates/workspace_projects.html +++ b/templates/workspace_projects.html @@ -10,16 +10,13 @@ {% if not workspace.projects %} {% set can_create_projects = user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) %} - {% set sub_message = None if can_create_projects else 'Please contact your workspace administrator to set up a new project.' %} - {% set action_label = 'Add a New Project' if can_create_projects else None %} - {% set action_href = url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None %} {{ EmptyState( 'This workspace doesn’t have any projects yet.', - action_label=action_label, - action_href=action_href, + action_label='Add a New Project' if can_create_projects else None, + action_href=url_for('workspaces.new_project', workspace_id=workspace.id) if can_create_projects else None, icon='cloud', - sub_message=sub_message + sub_message=None if can_create_projects else 'Please contact your JEDI workspace administrator to set up a new project.' ) }} {% else %} From e90769fbd9def94ce146948d62eb4bbfa13644fd Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:27:21 -0400 Subject: [PATCH 09/13] Modify members empty state depending on permissions --- templates/workspace_members.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/templates/workspace_members.html b/templates/workspace_members.html index 29ac055d..d1e43515 100644 --- a/templates/workspace_members.html +++ b/templates/workspace_members.html @@ -6,10 +6,13 @@ {% if not workspace.members %} + {% set user_can_invite = user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) %} + {{ EmptyState( 'There are currently no members in this Workspace.', - action_label='Invite a new Member', - action_href='/members/new', + action_label='Invite a new Member' if user_can_invite else None, + action_href='/members/new' if user_can_invite else None, + sub_message=None if user_can_invite else 'Please contact your JEDI workspace administrator to invite new members.', icon='avatar' ) }} From 63dd4da80bed87f02b84d86683b9e99fd27faf45 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:29:54 -0400 Subject: [PATCH 10/13] Only display add new member button if user has permissions --- templates/navigation/workspace_navigation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/navigation/workspace_navigation.html b/templates/navigation/workspace_navigation.html index 92393f30..5ef3ec8c 100644 --- a/templates/navigation/workspace_navigation.html +++ b/templates/navigation/workspace_navigation.html @@ -20,7 +20,7 @@ "Members", href=url_for("workspaces.workspace_members", workspace_id=workspace.id), active=request.url_rule.rule.startswith('/workspaces//members'), - subnav=[ + subnav=None if not user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) else [ { "label": "Add New Member", "href": url_for("workspaces.new_member", workspace_id=workspace.id), From 6317580350984e0de54450d3d694f77b840ae57e Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:40:49 -0400 Subject: [PATCH 11/13] False not false --- atst/routes/workspaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index ce0def86..bafa86cd 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -31,7 +31,7 @@ def workspace(): def user_can(permission): if workspace: return Authorization.has_workspace_permission(g.current_user, workspace, permission) - return false + return False return { "workspace": workspace, From 7509ee9cfcae0a1b2bb18fbc942af100f366e6f3 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Mon, 27 Aug 2018 14:50:39 -0400 Subject: [PATCH 12/13] formatting magic --- atst/routes/workspaces.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index bafa86cd..fcc5f7ae 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -17,6 +17,7 @@ from atst.models.permissions import Permissions bp = Blueprint("workspaces", __name__) + @bp.context_processor def workspace(): workspace = None @@ -30,14 +31,13 @@ def workspace(): def user_can(permission): if workspace: - return Authorization.has_workspace_permission(g.current_user, workspace, permission) + return Authorization.has_workspace_permission( + g.current_user, workspace, permission + ) return False - return { - "workspace": workspace, - "permissions": Permissions, - "user_can": user_can - } + return {"workspace": workspace, "permissions": Permissions, "user_can": user_can} + @bp.route("/workspaces") def workspaces(): From a5f3061d99611fe240425e7c04295c14a0f33e25 Mon Sep 17 00:00:00 2001 From: Montana Date: Tue, 28 Aug 2018 12:48:19 -0400 Subject: [PATCH 13/13] Tests for viewing Add Project and Add Member buttons --- tests/routes/test_workspaces.py | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/routes/test_workspaces.py diff --git a/tests/routes/test_workspaces.py b/tests/routes/test_workspaces.py new file mode 100644 index 00000000..202a8127 --- /dev/null +++ b/tests/routes/test_workspaces.py @@ -0,0 +1,53 @@ +from tests.factories import UserFactory, WorkspaceFactory +from atst.domain.workspaces import Workspaces +from atst.models.workspace_user import WorkspaceUser + + +def test_user_with_permission_has_add_project_link(client, user_session): + user = UserFactory.create() + workspace = WorkspaceFactory.create() + Workspaces._create_workspace_role(user, workspace, "owner") + + user_session(user) + response = client.get("/workspaces/{}/projects".format(workspace.id)) + assert ( + 'href="/workspaces/{}/projects/new"'.format(workspace.id).encode() + in response.data + ) + + +def test_user_without_permission_has_no_add_project_link(client, user_session): + user = UserFactory.create() + workspace = WorkspaceFactory.create() + Workspaces._create_workspace_role(user, workspace, "developer") + user_session(user) + response = client.get("/workspaces/{}/projects".format(workspace.id)) + assert ( + 'href="/workspaces/{}/projects/new"'.format(workspace.id).encode() + not in response.data + ) + + +def test_user_with_permission_has_add_member_link(client, user_session): + user = UserFactory.create() + workspace = WorkspaceFactory.create() + Workspaces._create_workspace_role(user, workspace, "owner") + + user_session(user) + response = client.get("/workspaces/{}/members".format(workspace.id)) + assert ( + 'href="/workspaces/{}/members/new"'.format(workspace.id).encode() + in response.data + ) + + +def test_user_without_permission_has_no_add_member_link(client, user_session): + user = UserFactory.create() + workspace = WorkspaceFactory.create() + Workspaces._create_workspace_role(user, workspace, "developer") + user_session(user) + response = client.get("/workspaces/{}/members".format(workspace.id)) + assert ( + 'href="/workspaces/{}/members/new"'.format(workspace.id).encode() + not in response.data + )