Skip to content

Commit

Permalink
Add page for listing a user's applications
Browse files Browse the repository at this point in the history
https://trello.com/c/7Hfe7eu0

The new page is available for the current user at
`/account/applications` but isn't yet navigable from the user interface.

I'm restricting access to this page to GOV.UK Admins (i.e. superadmins
and admins) for now although the plan is to allow Publishing Managers
(i.e. super organisation admins and organisation admins) to access it in
future. This page will eventually allow users to manage their own
permissions for the apps they have access to, and there's some
additional complexity around Publishing Managers that I want to defer
tackling until later.

I'm currently only showing the apps the current user has the signin
permission for. This is a subset of apps that a GOV.UK Admin would see
when viewing their own edit page at `/users/<id>/edit` because it
currently excludes any apps that the user does not have the signin
permission for. Note that this can differ from the list of apps shown on
a user's dashboard as the dashboard list is additionally restricted to
apps where `show_on_dashboard` is `true`[1].

Note that in integration the following apps have `show_on_dashboard` set
to `false` (i.e. they won't appear on a user's dashboard but can appear
in this new /account/applications page):

```
Doorkeeper::Application.where(show_on_dashboard: false).map(&:name)
=> ["Content Preview", "Data Publisher", "Special Route Publisher", "Transition (Paas)"]
```

[1]: https://github.com/alphagov/signon/blob/cc4da25cb7da4393d40b64d4cfb0df62c331a563/app/controllers/root_controller.rb#L9
  • Loading branch information
chrisroos committed Sep 7, 2023
1 parent 354f2cf commit 4a41a54
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 1 deletion.
11 changes: 11 additions & 0 deletions app/controllers/account/applications_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Account::ApplicationsController < ApplicationController
layout "admin_layout"

before_action :authenticate_user!

def index
authorize :account_applications

@applications = Doorkeeper::Application.can_signin(current_user)
end
end
5 changes: 5 additions & 0 deletions app/policies/account_applications_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AccountApplicationsPolicy < BasePolicy
def index?
current_user.govuk_admin?
end
end
34 changes: 34 additions & 0 deletions app/views/account/applications/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<% content_for :title, "GOV.UK apps" %>

<% content_for :breadcrumbs,
render("govuk_publishing_components/components/breadcrumbs", {
collapse_on_mobile: true,
breadcrumbs: [
{
title: "Dashboard",
url: root_path,
},
{
title: "GOV.UK apps",
}
]
})
%>

<table class="govuk-table">
<caption class="govuk-table__caption govuk-table__caption--m">Apps you have access to</caption>
<thead class="govuk-table__head">
<tr class="govuk-table__row">
<th scope="col" class="govuk-table__header govuk-!-width-one-quarter">Name</th>
<th scope="col" class="govuk-table__header govuk-!-width-three-quarters">Description</th>
</tr>
</thead>
<tbody class="govuk-table__body">
<% @applications.each do |application| %>
<tr class="govuk-table__row">
<td class="govuk-table__cell"><%= application.name %></td>
<td class="govuk-table__cell"><%= application.description %></td>
</tr>
<% end %>
</tbody>
</table>
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
resource :user, only: [:show]

resource :account, only: [:show]
namespace :account do
resources :applications, only: [:index]
end

resources :batch_invitations, only: %i[new create show]
resources :bulk_grant_permission_sets, only: %i[new create show]
Expand Down
2 changes: 1 addition & 1 deletion test/factories/users.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FactoryBot.define do
factory :user do
factory :user, aliases: [:normal_user] do
transient do
with_permissions { {} }
with_signin_permissions_for { [] }
Expand Down
49 changes: 49 additions & 0 deletions test/integration/account_applications_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require "test_helper"

class AccountApplicationsTest < ActionDispatch::IntegrationTest
context "#index" do
setup do
@application = create(:application, name: "app-name", description: "app-description")
@retired_application = create(:application, retired: true, name: "retired-app-name")
@user = FactoryBot.create(:admin_user)
end

should "not be accessible to signed out users" do
visit account_applications_path

assert_current_url new_user_session_path
end

should "list the applications the user has access to" do
@user.grant_application_signin_permission(@application)

visit new_user_session_path
signin_with @user

visit account_applications_path

assert page.has_content?("app-name")
assert page.has_content?("app-description")
end

should "not list retired applications the user has access to" do
@user.grant_application_signin_permission(@retired_application)

visit new_user_session_path
signin_with @user

visit account_applications_path

assert_not page.has_content?("retired-app-name")
end

should "not list the applications the user does not have access to" do
visit new_user_session_path
signin_with @user

visit account_applications_path

assert_not page.has_content?("app-name")
end
end
end
32 changes: 32 additions & 0 deletions test/policies/account_applications_policy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "test_helper"
require "support/policy_helpers"

class AccountApplicationsPolicyTest < ActiveSupport::TestCase
include PolicyHelpers

context "accessing index?" do
%i[superadmin admin].each do |user_role|
context "for #{user_role} users" do
setup do
@current_user = FactoryBot.build(:"#{user_role}_user")
end

should "be permitted" do
assert permit?(@current_user, nil, :index)
end
end
end

%i[super_organisation_admin organisation_admin normal].each do |user_role|
context "for #{user_role} users" do
setup do
@current_user = FactoryBot.build(:"#{user_role}_user")
end

should "be forbidden" do
assert forbid?(@current_user, nil, :index)
end
end
end
end
end

0 comments on commit 4a41a54

Please sign in to comment.