Skip to content

Commit

Permalink
Invite Users to GSE (#3080)
Browse files Browse the repository at this point in the history
* Add users resource to `routes.rb`
* Adds links to manage users on the school dashboard
* Adds UsersController 
* Adds views to manage users in a school
* Adds DSI API service to fetch school's ukprn from DSI
* Adds DSI API service to fetch users in a school
* Adds DSI API service to add users to a school
* Adds relevant specs
  • Loading branch information
ekumachidi authored Mar 11, 2024
1 parent e71c267 commit c280eb6
Show file tree
Hide file tree
Showing 13 changed files with 495 additions and 1 deletion.
44 changes: 44 additions & 0 deletions app/controllers/schools/users_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Schools
class UsersController < BaseController
def index
@users = DFESignInAPI::OrganisationUsers.new(current_user.sub, current_school.urn).users
@dfe_sign_in_request_organisation_url =
Rails.application.config.x.dfe_sign_in_request_organisation_url.presence
end

def new
@user_invite = DFESignInAPI::UserInvite.new
end

def create
@user_invite = DFESignInAPI::UserInvite.new(user_params)
@user_invite.organisation_id = DFESignInAPI::Organisation.new(current_user.sub, current_school.urn).current_organisation_id

if params[:confirmed] == 'true'
if @user_invite.valid?
@user_invite.create
redirect_to schools_users_path, notice: "#{@user_invite.email} has been added."
else
render :new
end
else
render :show, locals: { user_invite: @user_invite }
end
end

def show
render :show
end

def edit
@user_invite = DFESignInAPI::UserInvite.new(user_params)
render :new, locals: { user_invite: @user_invite }
end

private

def user_params
params.require(:schools_dfe_sign_in_api_user_invite).permit(:email, :firstname, :lastname, :organisation_id)
end
end
end
24 changes: 24 additions & 0 deletions app/services/schools/dfe_sign_in_api/organisation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Schools
module DFESignInAPI
class Organisation < Organisations
attr_accessor :current_school_urn

def initialize(user_uuid, current_school_urn)
super(user_uuid)
self.current_school_urn = current_school_urn
end

def current_organisation
organisations.find { |org| org['urn'].to_i == current_school_urn }
end

def current_organisation_ukprn
current_organisation['ukprn'] if current_organisation
end

def current_organisation_id
current_organisation['id'] if current_organisation
end
end
end
end
29 changes: 29 additions & 0 deletions app/services/schools/dfe_sign_in_api/organisation_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Schools
module DFESignInAPI
class OrganisationUsers < Client
attr_accessor :user_uuid, :current_school_urn

def initialize(user_uuid, current_school_urn)
self.user_uuid = user_uuid
self.current_school_urn = current_school_urn
end

def ukprn
Organisation.new(user_uuid, current_school_urn).current_organisation_ukprn
end

def users
@users ||= response&.fetch('users', nil)
end

private

def endpoint
URI::HTTPS.build(
host: Rails.configuration.x.dfe_sign_in_api_host,
path: ['/organisations', ukprn, 'users'].join('/')
)
end
end
end
end
59 changes: 59 additions & 0 deletions app/services/schools/dfe_sign_in_api/user_invite.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Schools
module DFESignInAPI
class UserInvite < Client
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveRecord::AttributeAssignment

attribute :email, :string
attribute :firstname, :string
attribute :lastname, :string
attribute :organisation_id, :string

validates :firstname, presence: true, length: { maximum: 50 }
validates :lastname, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 100 }
validates :email, email_format: true, if: -> { email.present? }
validates :organisation_id, presence: true

def create
@response = response
end

private

def response
raise ApiDisabled unless enabled?

resp = faraday.post(endpoint) do |req|
req.headers['Authorization'] = "bearer #{token}"
req.headers['Content-Type'] = 'application/json'
req.body = payload.to_json
end

resp.body
end

def service_id
ENV.fetch('DFE_SIGNIN_SCHOOL_EXPERIENCE_ADMIN_SERVICE_ID')
end

def endpoint
URI::HTTPS.build(
host: Rails.configuration.x.dfe_sign_in_api_host,
path: ['/services', service_id, 'invitations'].join('/')
)
end

def payload
super.merge(
sourceId: SecureRandom.uuid,
given_name: firstname,
family_name: lastname,
email: email,
organisation: organisation_id
)
end
end
end
end
2 changes: 1 addition & 1 deletion app/views/schools/dashboards/_profile_and_dates.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<%= link_to "Update school profile", schools_on_boarding_profile_path %>
</li>
<li>
<%= link_to "Manage users" %>
<%= link_to "Manage users", schools_users_path %>
</li>
</ul>
<hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">
Expand Down
25 changes: 25 additions & 0 deletions app/views/schools/users/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<% self.page_title = 'Add user details' %>
<% content_for :back_link do govuk_back_link; end %>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<%= form_for(@user_invite, url: schools_users_path, method: :post, html: {novalidate: false}) do |f| %>

<%= f.govuk_error_summary %>

<span class="govuk-caption-xl govuk-!-margin-top-4"> Add user details </span>
<h1 class="govuk-heading-l"> Personal details </h1>

<%= f.govuk_error_summary %>

<%= f.govuk_text_field :firstname, autocomplete: 'given-name' %>

<%= f.govuk_text_field :lastname, autocomplete: 'family-name' %>

<%= f.govuk_email_field :email, autocomplete: 'on' %>

<%= f.govuk_submit 'Continue' %>
<% end %>
<%= link_to "Cancel", schools_users_path, 'aria-label': "Cancel user invite" %>
</div>
</div>
60 changes: 60 additions & 0 deletions app/views/schools/users/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<%
self.page_title = "Manage Users"

self.breadcrumbs = {
@current_school.name => schools_dashboard_path,
'users' => nil
}
%>

<div class="govuk-grid-row">
<div class="govuk-grid-column-full">
<h1>Manage users at <%= @current_school.name %> </h1>
<%= link_to 'Add user', new_schools_user_path, class: 'govuk-button' %>

<p>
Users will be able to:
<ul ul class="govuk-list govuk-list--bullet">
<li>advertise experience at your school</li>
<li>allow candidates to request experience</li>
<li>accept or reject candidates requests for experience</li>
<li>add other users from your school</li>
</ul>
</p>
<p> To remove and manage users, you should go to
<%= link_to 'DFE Sign-in', @dfe_sign_in_request_organisation_url %>
</p>

<% if @users.any? %>
<div class="pagination-info higher">
<div class="pagination-slice">
</div>
</div>
<table id="invited-users" class="govuk-table">
<thead class="govuk-table__head">
<tr class="govuk-table__row">
<th class="govuk-table__header">Name</th>
<th class="govuk-table__header">Email</th>
</tr>
</thead>
<tbody class="govuk-table__body">
<% @users.each do |user| %>
<tr class="govuk-table__row">
<td class="govuk-table__cell"><%= "#{user['firstName']} #{user['lastName']}" %></td>
<td class="govuk-table__cell"><%= user['email'] %></td>
</tr>
<% end %>

</tbody>
</table>
<div class="pagination-info lower">
</div>
<% else %>
<p>
There are no other users in this school.
</p>
<% end %>

<%= govuk_link_to "Return to dashboard", schools_dashboard_path, secondary: true %>
</div>
</div>
1 change: 1 addition & 0 deletions app/views/schools/users/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= render partial: "form", locals: { user_invite: @user_invite } %>
61 changes: 61 additions & 0 deletions app/views/schools/users/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<% self.page_title = 'Check your answers' %>
<% content_for :back_link do govuk_back_link; end %>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<%= form_for(@user_invite, url: schools_users_path, method: :post) do |f| %>
<section id="personal-details">
<span class="govuk-caption-xl govuk-!-margin-top-4"> Add user </span>
<h1 class="govuk-heading-l"> Check your answers </h1>

<dl class="placement-details govuk-summary-list">
<div class="address govuk-summary-list__row">
<dt class="govuk-summary-list__key">
First name
</dt>
<dd class="govuk-summary-list__value">
<%= @user_invite.firstname %>
<%= f.hidden_field :firstname, value: @user_invite.firstname %>
</dd>
<dd>
<%= link_to 'Change', edit_schools_user_path(schools_dfe_sign_in_api_user_invite: { firstname: @user_invite.firstname, lastname: @user_invite.lastname, email: @user_invite.email }) %>
</dd>
</div>

<div class="phone-number govuk-summary-list__row">
<dt class="govuk-summary-list__key">
Last name
</dt>
<dd class="govuk-summary-list__value">
<%= @user_invite.lastname %>
<%= f.hidden_field :lastname, value: @user_invite.lastname %>
</dd>
<dd>
<%= link_to 'Change', edit_schools_user_path(schools_dfe_sign_in_api_user_invite: { firstname: @user_invite.firstname, lastname: @user_invite.lastname, email: @user_invite.email }) %>
</dd>
</div>

<div class="email-address govuk-summary-list__row">
<dt class="govuk-summary-list__key">
Email address
</dt>
<dd class="govuk-summary-list__value">
<%= @user_invite.email %>
<%= f.hidden_field :email, value: @user_invite.email %>
</dd>
<dd>
<%= link_to 'Change', edit_schools_user_path(schools_dfe_sign_in_api_user_invite: { firstname: @user_invite.firstname, lastname: @user_invite.lastname, email: @user_invite.email }) %>
</dd>
</div>
<%= hidden_field_tag :confirmed, true %>
</dl>
<div class="govuk-inset-text">
<p>The user will be sent an email to create an account and will have access to the school's dashboard.</p>
</div>

<%= f.govuk_submit 'Accept and submit', data: { prevent_double_click_target: "submitButton" } %>
</section>
<%= link_to "Cancel", schools_users_path, 'aria-label': "Cancel user invite" %>
<% end %>
</div>
</div>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
get '/cookies_policy', to: 'pages#cookies_policy'
get '/schools_privacy_policy', to: 'pages#schools_privacy_policy'
get '/schools/request_organisation', to: 'pages#schools_request_organisation'
get '/schools/users/edit', to: 'schools/users#edit', as: :edit_schools_user
resources :service_updates, only: %i[index show]
get '/service_update', to: 'service_updates#index'
get '/help_and_support_access_needs', to: 'pages#help_and_support_access_needs'
Expand All @@ -63,6 +64,7 @@
resource :switch, only: %i[new show], controller: 'switch'

resource :change_school, only: %i[show create], as: 'change', path: 'change', controller: 'change_schools'
resources :users, only: %i[index new create show], controller: 'users'
resource :prepopulate_school_profiles, only: %i[create]

resource :dashboard, only: :show
Expand Down
Loading

0 comments on commit c280eb6

Please sign in to comment.