Skip to content

Commit

Permalink
WIP: Move API user manage tokens page to GOV.UK Design System
Browse files Browse the repository at this point in the history
  • Loading branch information
floehopper committed Jan 3, 2024
1 parent 07d936f commit c455212
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 78 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api_users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class ApiUsersController < ApplicationController
include UserPermissionsControllerMethods

layout "admin_layout", only: %w[index new create edit]
layout "admin_layout", only: %w[index new create edit manage_tokens]

before_action :authenticate_user!
before_action :load_and_authorize_api_user, only: %i[edit manage_permissions manage_tokens update]
Expand Down
148 changes: 87 additions & 61 deletions app/views/api_users/manage_tokens.html.erb
Original file line number Diff line number Diff line change
@@ -1,68 +1,94 @@
<% content_for :title_caption, "Manage API users" %>
<% content_for :title, "Manage tokens for #{@api_user.name}" %>
<ol class="breadcrumb">
<li><%= link_to "Dashboard", root_path %></li>
<li><%= link_to "API users", api_users_path %></li>
<li><%= link_to @api_user.name, edit_api_user_path(@api_user) %></li>
<li class="active">Manage tokens</li>
</ol>

<h1>Manage tokens for API User <%= @api_user.name %></h1>
<% content_for :breadcrumbs,
render("govuk_publishing_components/components/breadcrumbs", {
collapse_on_mobile: true,
breadcrumbs: [
{
title: "Dashboard",
url: root_path,
},
{
title: "API users",
url: api_users_path,
},
{
title: @api_user.name,
url: edit_api_user_path(@api_user),
},
{
title: "Manage tokens",
}
]
})
%>
<% if authorisation = flash[:authorisation] %>
<div class="alert alert-danger">
Make sure to copy the access token for <%= authorisation["application_name"] %> now. You won't be able to see it again!
</div>
<div class="alert alert-info">
Access token for <%= authorisation["application_name"] %>: <span id='access-token'><%= authorisation["token"] %></span>
<%= link_to 'Copy to clipboard', '#', class: 'btn btn-info add-left-margin', data: { 'clipboard-target' => 'access-token' }, id: 'clip-button', title: 'Click to copy access token' %>
</div>
<% content_for :custom_alerts do %>
<%= render "govuk_publishing_components/components/success_alert", {
message: "Make sure to copy the access token for #{authorisation["application_name"]} now. You won't be able to see it again!",
description: render("govuk_publishing_components/components/copy_to_clipboard", {
label: "Access token for #{authorisation["application_name"]}",
copyable_content: authorisation["token"],
button_text: "Copy access token",
})
} %>
<% end %>
<% end %>
<table id="authorisations" class="table table-bordered table-on-white">
<thead>
<tr class="table-header">
<th>Application</th>
<th>Token (hidden)</th>
<th>Generated</th>
<th>Expires</th>
<th>State</th>
<th>Action</th>
</tr>
</thead>
<tbody>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<div class="govuk-form-group">
<%= render "govuk_publishing_components/components/button", {
text: "Add application token",
href: new_api_user_authorisation_path(@api_user),
} %>
</div>

<% @api_user.authorisations.not_revoked.ordered_by_application_name.ordered_by_expires_at.each do |authorisation| %>
<tr>
<td><%= authorisation.application.name %></td>
<td><code><%= truncate_access_token(authorisation.token) %></code></td>
<td>
<%= authorisation.created_at.to_date.to_fs(:govuk_date) %>
</td>
<td>
<%= authorisation.expires_at.to_date.to_fs(:govuk_date) %>
</td>
<td>
<% if authorisation.expired? %>
<span class="label label-danger">Expired</span>
<% else %>
<span class="label label-success">Valid</span>
<% end %>
</td>
<td>
<%= link_to edit_api_user_authorisation_path(@api_user, authorisation) do %>
Revoke<span class="invisible"> token giving <%= @api_user.name %> access to <%= authorisation.application.name %></span>
<% end %>
</td>
<div class="govuk-summary-card">
<div class="govuk-summary-card__title-wrapper">
<h2 class="govuk-summary-card__title"><%= authorisation.application.name %></h2>
<ul class="govuk-summary-card__actions">
<li class="govuk-summary-card__action">
<a class="govuk-link" href="<%= edit_api_user_authorisation_path(@api_user, authorisation) %>">
Revoke<span class="govuk-visually-hidden"> token giving <%= @api_user.name %> access to <%= authorisation.application.name %></span>
</a>
</li>
</ul>
</div>
<div class="govuk-summary-card__content">
<dl class="govuk-summary-list">
<div class="govuk-summary-list__row">
<dt class="govuk-summary-list__key">
Token (hidden)
</dt>
<dd class="govuk-summary-list__value">
<code>
<%= truncate_access_token(authorisation.token) %>
</code>
</dd>
</div>
<div class="govuk-summary-list__row">
<dt class="govuk-summary-list__key">
Generated
</dt>
<dd class="govuk-summary-list__value">
<%= authorisation.created_at.to_date.to_fs(:govuk_date) %>
</dd>
</div>
<div class="govuk-summary-list__row">
<dt class="govuk-summary-list__key">
Expires
</dt>
<dd class="govuk-summary-list__value">
<%= authorisation.expires_at.to_date.to_fs(:govuk_date) %>
</dd>
</div>
</dl>
</div>
</div>
<% end %>
</tbody>
</table>
<p>
<%= link_to new_api_user_authorisation_path(@api_user), class: "btn btn-default" do %>
<span class="glyphicon glyphicon-plus glyphicon-smaller-than-text"></span> Add application token
<% end %>
</p>

<script>
$(document).ready(function() {
new ZeroClipboard($("#clip-button"));
});
</script>
</div>
</div>
29 changes: 21 additions & 8 deletions app/views/authorisations/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,26 @@

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<div class="govuk-button-group">
<%= form_tag(revoke_api_user_authorisation_path(@api_user, @authorisation), method: :post) do %>
<%= render "govuk_publishing_components/components/button", {
text: "Revoke token",
destructive: true,
} %>
<% end %>
</div>
<section>
<%= render "govuk_publishing_components/components/summary_list", {
title: "Access token details",
items: [
{ field: "Application", value: @authorisation.application.name },
{ field: "Token (hidden)", value: truncate_access_token(@authorisation.token) },
{ field: "Generated", value: @authorisation.created_at.to_date.to_fs(:govuk_date) },
{ field: "Expires", value: @authorisation.expires_at.to_date.to_fs(:govuk_date) },
]
} %>
</section>
<section>
<div class="govuk-button-group">
<%= form_tag(revoke_api_user_authorisation_path(@api_user, @authorisation), method: :post) do %>
<%= render "govuk_publishing_components/components/button", {
text: "Revoke token",
destructive: true,
} %>
<% end %>
</div>
</section>
</div>
</div>
2 changes: 2 additions & 0 deletions app/views/layouts/admin_layout.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
} %>
<% end %>
<%= yield(:custom_alerts) %>
<%= yield(:error_summary) %>

<div class="govuk-grid-row">
Expand Down
8 changes: 4 additions & 4 deletions test/controllers/api_users_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ class ApiUsersControllerTest < ActionController::TestCase

get :manage_tokens, params: { id: @api_user }

assert_select "table#authorisations tbody td", text: application.name do |td|
assert_select td.first.parent, "code", text: /^#{token[0..7]}/
assert_select ".govuk-summary-card__title", text: application.name do |divs|
assert_select divs.first.parent.parent, "code", text: /^#{token[0..7]}/
end
end

Expand All @@ -207,7 +207,7 @@ class ApiUsersControllerTest < ActionController::TestCase

get :manage_tokens, params: { id: @api_user }

assert_select "table#authorisations tbody td", text: application.name, count: 0
assert_select ".govuk-summary-card__title", text: application.name, count: 0
end

should "not show API user's access tokens for retired applications" do
Expand All @@ -216,7 +216,7 @@ class ApiUsersControllerTest < ActionController::TestCase

get :manage_tokens, params: { id: @api_user }

assert_select "table#authorisations tbody td", text: application.name, count: 0
assert_select ".govuk-summary-card__title", text: application.name, count: 0
end
end

Expand Down
9 changes: 5 additions & 4 deletions test/integration/manage_api_users_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ class ManageApiUsersTest < ActionDispatch::IntegrationTest
click_button "Create access token"

token = @api_user.authorisations.last.token
assert page.has_selector?("div.alert-danger", text: "Make sure to copy the access token for Whitehall now. You won't be able to see it again!")
assert page.has_selector?("div.alert-info", text: "Access token for Whitehall: #{token}")
assert page.has_selector?("div[role='alert']", text: /Make sure to copy the access token for Whitehall now. You won't be able to see it again!/)
assert page.has_selector?("div[role='alert'] label", text: /Access token for Whitehall/)
assert page.has_selector?("div[role='alert'] input[value='#{token}']")

# shows truncated token
assert page.has_selector?("code", text: (token[0..7]).to_s)
Expand Down Expand Up @@ -90,12 +91,12 @@ class ManageApiUsersTest < ActionDispatch::IntegrationTest
click_link @api_user.name
click_link "Manage tokens"

assert page.has_selector?("td:first-child", text: @application.name)
assert page.has_selector?(".govuk-summary-card__title", text: @application.name)
click_link "Revoke"
click_button "Revoke"

assert page.has_text?("Access for #{@application.name} was revoked")
assert_not page.has_selector?("td:first-child", text: @application.name)
assert_not page.has_selector?(".govuk-summary-card__title", text: @application.name)

click_link @api_user.name
click_link "View account access log"
Expand Down

0 comments on commit c455212

Please sign in to comment.