diff --git a/app/controllers/super_admin/orgs_controller.rb b/app/controllers/super_admin/orgs_controller.rb index 72d338b..a208f67 100644 --- a/app/controllers/super_admin/orgs_controller.rb +++ b/app/controllers/super_admin/orgs_controller.rb @@ -21,6 +21,8 @@ org.logo = params[:logo] if params[:logo] if params[:org_links].present? org.links = JSON.parse(params[:org_links]) + else + org.links = { org: [] } end begin diff --git a/app/controllers/super_admin/users_controller.rb b/app/controllers/super_admin/users_controller.rb new file mode 100644 index 0000000..051ce42 --- /dev/null +++ b/app/controllers/super_admin/users_controller.rb @@ -0,0 +1,47 @@ +module SuperAdmin + class UsersController < ApplicationController + + after_action :verify_authorized + + def edit + user = User.find(params[:id]) + if user.present? + authorize user + languages = Language.sorted_by_abbreviation + orgs = Org.where(parent_id: nil).order("name") + identifier_schemes = IdentifierScheme.where(active: true).order(:name) + + render 'super_admin/users/edit', + locals: { user: user, + languages: languages, + orgs: orgs, + identifier_schemes: identifier_schemes, + default_org: user.org } + else + redirect_to admin_index_users_path, alert: _('User not found.') + end + end + + def update + user = User.find(params[:id]) + if user.present? + authorize user + topic = _('%{username}\'s profile') % { username: user.name(false) } + if user.update_attributes(user_params) + redirect_to edit_super_admin_user_path(user), + notice: _('Successfully updated %{username}') % { username: topic } + else + redirect_to edit_super_admin_user_path(user), + alert: _('Unable to update %{username}') % { username: topic } + end + else + redirect_to edit_super_admin_user_path(user), alert: _('User not found.') + end + end + + private + def user_params + params.require(:super_admin_user).permit(:email, :firstname, :surname, :org_id, :language_id) + end + end +end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4737072..5da6539 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -52,6 +52,7 @@ authorize @user perms_ids = params[:perm_ids].blank? ? [] : params[:perm_ids].map(&:to_i) perms = Perm.where( id: perms_ids) + privileges_changed = false current_user.perms.each do |perm| if @user.perms.include? perm if ! perms.include? perm @@ -59,20 +60,24 @@ if perm.id == Perm.use_api.id @user.remove_token! end + privileges_changed = true end else if perms.include? perm @user.perms << perm if perm.id == Perm.use_api.id @user.keep_or_generate_token! + privileges_changed = true end end end end if @user.save! - deliver_if(recipients: @user, key: 'users.admin_privileges') do |r| - UserMailer.admin_privileges(r).deliver_now + if privileges_changed + deliver_if(recipients: @user, key: 'users.admin_privileges') do |r| + UserMailer.admin_privileges(r).deliver_now + end end render(json: { code: 1, @@ -123,6 +128,29 @@ end end + # PUT /users/:id/activate + # ----------------------------------------------------- + def activate + authorize current_user + + user = User.find(params[:id]) + if user.present? + begin + user.active = !user.active + user.save! + render json: { + code: 1, + msg: _('Successfully %{action} %{username}\'s account.') % { action: user.active ? _('activated') : _('deactivated'), username: user.name(false) } + } + rescue Exception + render json: { + code: 0, + msg: _('Unable to %{action} %{username}') % { action: user.active ? _('activate') : _('deactivate'), username: user.name(false) } + } + end + end + end + private def org_swap_params params.require(:user).permit(:org_id, :org_name) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index b54bf09..6fa76b0 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -23,9 +23,11 @@ def permissions_change_notification(role, user) @role = role @user = user - FastGettext.with_locale FastGettext.default_locale do - mail(to: @role.user.email, - subject: _('Changed permissions on a Data Management Plan in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }) + if user.active? + FastGettext.with_locale FastGettext.default_locale do + mail(to: @role.user.email, + subject: _('Changed permissions on a Data Management Plan in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }) + end end end @@ -33,24 +35,18 @@ @user = user @plan = plan @current_user = current_user - FastGettext.with_locale FastGettext.default_locale do - mail(to: @user.email, - subject: "#{_('Permissions removed on a DMP in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }}") - end - end - - def api_token_granted_notification(user) - @user = user + if user.active? FastGettext.with_locale FastGettext.default_locale do mail(to: @user.email, - subject: _('API rights in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }) + subject: "#{_('Permissions removed on a DMP in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }}") end + end end def feedback_notification(recipient, plan, requestor) @user = requestor - if @user.org.present? + if @user.org.present? && recipient.active? @org = @user.org @plan = plan @recipient = recipient @@ -67,16 +63,18 @@ @user = recipient @plan = plan - FastGettext.with_locale FastGettext.default_locale do - mail(to: recipient.email, - subject: _("%{application_name}: Expert feedback has been provided for %{plan_title}") % {application_name: Rails.configuration.branding[:application][:name], plan_title: @plan.title}) + if recipient.active? + FastGettext.with_locale FastGettext.default_locale do + mail(to: recipient.email, + subject: _("%{application_name}: Expert feedback has been provided for %{plan_title}") % {application_name: Rails.configuration.branding[:application][:name], plan_title: @plan.title}) + end end end def feedback_confirmation(recipient, plan, requestor) user = requestor - if user.org.present? + if user.org.present? && recipient.active? org = user.org plan = plan @@ -96,9 +94,11 @@ def plan_visibility(user, plan) @user = user @plan = plan - FastGettext.with_locale FastGettext.default_locale do - mail(to: @user.email, - subject: _('DMP Visibility Changed: %{plan_title}') %{ :plan_title => @plan.title }) + if user.active? + FastGettext.with_locale FastGettext.default_locale do + mail(to: @user.email, + subject: _('DMP Visibility Changed: %{plan_title}') %{ :plan_title => @plan.title }) + end end end @@ -106,7 +106,8 @@ # @param plan - Plan for which the comment is associated to def new_comment(commenter, plan) if commenter.is_a?(User) && plan.is_a?(Plan) - if plan.owner.present? + owner = plan.owner + if owner.present? && owner.active? @commenter = commenter @plan = plan FastGettext.with_locale FastGettext.default_locale do @@ -119,9 +120,11 @@ def admin_privileges(user) @user = user - FastGettext.with_locale FastGettext.default_locale do - mail(to: user.email, subject: - _('Administrator privileges granted in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }) + if user.active? + FastGettext.with_locale FastGettext.default_locale do + mail(to: user.email, subject: + _('Administrator privileges granted in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }) + end end end end diff --git a/app/models/user.rb b/app/models/user.rb index 4fca8fc..0bee5c5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -50,8 +50,8 @@ # Retrieves all of the org_admins for the specified org scope :org_admins, -> (org_id) { - joins(:perms).where("users.org_id = ? AND perms.name IN (?)", org_id, - ['grant_permissions', 'modify_templates', 'modify_guidance', 'change_org_details']) + joins(:perms).where("users.org_id = ? AND perms.name IN (?) AND users.active = ?", org_id, + ['grant_permissions', 'modify_templates', 'modify_guidance', 'change_org_details'], true) } scope :search, -> (term) { @@ -67,6 +67,12 @@ after_update :when_org_changes + ## + # This method uses Devise's built-in handling for inactive users + def active_for_authentication? + super && self.active? + end + # EVALUATE CLASS AND INSTANCE METHODS BELOW # # What do they do? do they do it efficiently, and do we need them? diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 070e52f..f9f6f47 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -28,6 +28,18 @@ user.can_super_admin? end + def activate? + user.can_super_admin? + end + + def edit? + user.can_super_admin? + end + + def update? + user.can_super_admin? + end + class Scope < Scope def resolve scope.where(org_id: user.org_id) diff --git a/app/views/paginable/users/_index.html.erb b/app/views/paginable/users/_index.html.erb index 377b95f..af5a861 100644 --- a/app/views/paginable/users/_index.html.erb +++ b/app/views/paginable/users/_index.html.erb @@ -1,3 +1,4 @@ +<% is_super_admin = current_user.can_super_admin? %>
@@ -6,10 +7,13 @@ <%= _('Name') %> <%= paginable_sort_link('firstname') %> <%= _('Email') %> <%= paginable_sort_link('email') %> - <%= _('Last activity') %> <%= paginable_sort_link('last_sign_in_at') %> + <%= _('Organisation') %> <%= paginable_sort_link('orgs.name') %> + <%= _('Created date') %> <%= paginable_sort_link('created_at') %> + <%= _('Last activity') %> <%= paginable_sort_link('last_sign_in_at') %> <%= _('Plans') %> <%= _('Current Privileges') %> - <%= _('Edit Privileges') %> + <%= _('Active') %> + <%= _('Privileges') %> @@ -18,11 +22,17 @@ <% if !user.name.nil? %> - <%= user.name(false) %> + <%= is_super_admin ? link_to(user.name(false), edit_super_admin_user_path(user)) : user.name(false) %> + <% else %> + <%= is_super_admin ? link_to(_('Edit Profile'), edit_user_registration_path(user)) : '' %> <% end %> - - <%= user.email %> + <%= user.email %> + <%= user.org.name if user.org.present? %> + + <% if !user.created_at.nil? %> + <%= l user.created_at.to_date, :formats => :short %> + <% end %> <% if !user.last_sign_in_at.nil? %> @@ -38,12 +48,20 @@ <%= render partial: 'users/current_privileges', locals: { user: user } %> + + <% if is_super_admin %> + <%= form_for user, url: activate_user_path(user), html: { method: :put, remote: true, class: 'activate-user' } do |f| %> + <%= check_box_tag(:active, "1", user.active) %> + <%= f.submit(_('Update'), style: 'display: none;') %> + <% end %> + <% else %> + <%= user.active? ? _('Yes') : _('No') %> + <% end %> + <%# Do not allow a user to change their own permissions or a super admin's permissions if they are not a super admin %> - <% unless current_user == user || - !current_user.can_super_admin? && user.can_super_admin? %> - <% b_label = _('Edit') %> - <%= link_to( b_label, admin_grant_permissions_user_path(user)) %> + <% unless current_user == user || !is_super_admin && user.can_super_admin? %> + <%= link_to( _('Edit'), admin_grant_permissions_user_path(user)) %> <% end %> diff --git a/app/views/shared/_my_org.html.erb b/app/views/shared/_my_org.html.erb index 11a7051..076501a 100644 --- a/app/views/shared/_my_org.html.erb +++ b/app/views/shared/_my_org.html.erb @@ -1,7 +1,7 @@ <%= f.label :org_name, _('Organisation'), class: 'control-label' %> <%= render partial: "shared/accessible_combobox", - locals: {name: "user[org_name]", - id: "user_org_name", + locals: {name: "#{f.object_name}[org_name]", + id: "#{f.object_name}_org_name", default_selection: default_org, models: orgs, attribute: 'name'} %> diff --git a/app/views/super_admin/users/edit.html.erb b/app/views/super_admin/users/edit.html.erb new file mode 100644 index 0000000..afd88bb --- /dev/null +++ b/app/views/super_admin/users/edit.html.erb @@ -0,0 +1,47 @@ +
+
+

+ <%= _('Editing profile for %{username}') % { username: user.name(false) } %> + <%= link_to(_('View all users'), admin_index_users_path, class: 'btn btn-default pull-right', role: 'button') %> +

+
+
+ +
+
+ <%= form_for(user, as: :super_admin_user, url: super_admin_user_path(user), html: {method: :put, id: 'super_admin_user_edit' }) do |f| %> +
+ <%= f.label(:email, _('Email'), class: 'control-label') %> + <%= f.email_field(:email, class: "form-control", "aria-required": true, value: user.email) %> +
+ +
+ <%= f.label(:firstname, _('First name'), class: 'control-label') %> + <%= f.text_field(:firstname, class: "form-control", "aria-required": true, value: user.firstname) %> +
+ +
+ <%= f.label(:surname, _('Last name'), class: 'control-label') %> + <%= f.text_field(:surname, class: "form-control", "aria-required": true, value: user.surname) %> +
+ +
+ <%= render partial: "shared/my_org", locals: {f: f, default_org: default_org, orgs: orgs, allow_other_orgs: true} %> +
+ + <% if MANY_LANGUAGES %> +
+ <% lang_id = user.language.nil? ? Language.id_for(FastGettext.default_locale) : user.language.id %> + <%= f.label(:language_id, _('Language'), class: 'control-label') %> + <%= select_tag(:super_admin_user_language_id, + options_from_collection_for_select(languages, "id", "name", lang_id), + class: "form-control", name: 'super_admin_user[language_id]') %> +
+ <% end %> + +
+ <%= f.button(_('Save'), class: 'btn btn-default', type: "submit", id: "personal_details_registration_form_submit") %> +
+ <% end %> +
+
diff --git a/app/views/users/_admin_grant_permissions.html.erb b/app/views/users/_admin_grant_permissions.html.erb index 9d3c407..15ae0a4 100644 --- a/app/views/users/_admin_grant_permissions.html.erb +++ b/app/views/users/_admin_grant_permissions.html.erb @@ -6,12 +6,11 @@ data-dismiss="modal" aria-label="Close"> -

<%= _('Edit user privileges') %>

+
- <%= form_tag( admin_update_permissions_user_path(user), method: :put, remote: true, class: 'admin_update_permissions' ) do %> + <%= form_for user, url: admin_update_permissions_user_path(user), html: { method: :put, remote: true, class: 'admin_update_permissions' } do |f| %>