From ac91d9c2c4f247355dc373cf0e563771adb376b4 Mon Sep 17 00:00:00 2001 From: zmagoD Date: Sat, 8 May 2021 18:06:07 +0200 Subject: [PATCH] add assign user permission to experiment level --- .../experiments_controller.rb | 60 +++++++++++++++++++ app/controllers/projects_controller.rb | 2 +- app/helpers/user_assignments_helper.rb | 19 ++++++ app/helpers/user_roles_helper.rb | 4 ++ app/models/experiment_member.rb | 44 ++++++++++++++ .../experiments/edit.json.jbuilder | 13 ++++ .../experiment_member.json.jbuilder | 13 ++++ .../experiments/modals/_edit_modal.html.erb | 30 ++++++++++ .../experiments/modals/_show_modal.html.erb | 24 ++++++++ .../experiments/show.json.jbuilder | 12 ++++ .../_experiment_member_field.html.erb | 25 ++++++++ .../partials/_project_member_field.html.erb | 2 +- .../partials/_user_assignment.html.erb | 6 +- .../modals/_show_modal.html.erb | 6 +- .../projects/show.json.jbuilder | 2 +- .../projects/show/_experiment_card.html.erb | 3 + .../projects/show/_experiments_list.html.erb | 2 +- config/locales/en.yml | 17 ++++-- config/routes.rb | 4 +- 19 files changed, 275 insertions(+), 13 deletions(-) create mode 100644 app/controllers/access_permissions/experiments_controller.rb create mode 100644 app/models/experiment_member.rb create mode 100644 app/views/access_permissions/experiments/edit.json.jbuilder create mode 100644 app/views/access_permissions/experiments/experiment_member.json.jbuilder create mode 100644 app/views/access_permissions/experiments/modals/_edit_modal.html.erb create mode 100644 app/views/access_permissions/experiments/modals/_show_modal.html.erb create mode 100644 app/views/access_permissions/experiments/show.json.jbuilder create mode 100644 app/views/access_permissions/partials/_experiment_member_field.html.erb rename app/views/access_permissions/{ => projects}/modals/_show_modal.html.erb (73%) diff --git a/app/controllers/access_permissions/experiments_controller.rb b/app/controllers/access_permissions/experiments_controller.rb new file mode 100644 index 000000000..3daf2975a --- /dev/null +++ b/app/controllers/access_permissions/experiments_controller.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module AccessPermissions + class ExperimentsController < ApplicationController + before_action :set_project + before_action :set_experiment + before_action :check_read_permissions, only: %i(show) + before_action :check_manage_permissions, only: %i(create edit update) + + def show + respond_to do |format| + format.json + end + end + + def edit + respond_to do |format| + format.json + end + end + + def update + @experiment_member = ExperimentMember.new(current_user, @experiment, @project) + @experiment_member.update(permitted_update_params) + + respond_to do |format| + format.json do + render :experiment_member + end + end + end + + private + + def permitted_update_params + params.require(:experiment_member) + .permit(%i(user_role_id user_id)) + end + + def set_project + @project = current_team.projects.find_by(id: params[:project_id]) + + render_404 unless @project + end + + def set_experiment + @experiment = @project.experiments.includes(user_assignments: %i(user user_role)).find_by(id: params[:id]) + + render_404 unless @experiment + end + + def check_manage_permissions + render_403 unless can_manage_experiment?(@experiment) + end + + def check_read_permissions + render_403 unless can_read_experiment?(@experiment) + end + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bb9981a79..859250076 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -264,7 +264,7 @@ class ProjectsController < ApplicationController render json: { cards_html: render_to_string( partial: 'projects/show/experiments_list.html.erb', - locals: { cards: overview_service.experiments } + locals: { cards: overview_service.experiments, project: @project } ) } diff --git a/app/helpers/user_assignments_helper.rb b/app/helpers/user_assignments_helper.rb index 94b51f85c..b798cc23c 100644 --- a/app/helpers/user_assignments_helper.rb +++ b/app/helpers/user_assignments_helper.rb @@ -9,4 +9,23 @@ module UserAssignmentsHelper end sanitize_input(display_name) end + + def user_assignment_resource_role_name(user_assignment, user, resource) + # Triggers N+1 but the partial is cached + + if resource.is_a?(Experiment) + project_user_assignment = resource.permission_parent.user_assignments.find_by(user: user) + current_user_assignment_name = user_assignment&.user_role&.name + + [ + t('user_assignment.from_project', user_role: project_user_assignment.user_role.name), + current_user_assignment_name + ].compact.join(' / ') + elsif resource.is_a?(MyModule) + # TODO + else + user_assignment.user_role.name + end + end end + diff --git a/app/helpers/user_roles_helper.rb b/app/helpers/user_roles_helper.rb index ded0b012f..13a11db68 100644 --- a/app/helpers/user_roles_helper.rb +++ b/app/helpers/user_roles_helper.rb @@ -10,4 +10,8 @@ module UserRolesHelper def new_user_roles_collection [[t('user_assignment.select_role'), nil]] + user_roles_collection end + + def experiment_user_roles_collection + [[t('user_assignment.select_role'), nil]] + user_roles_collection + end end diff --git a/app/models/experiment_member.rb b/app/models/experiment_member.rb new file mode 100644 index 000000000..8c95a42e1 --- /dev/null +++ b/app/models/experiment_member.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class ExperimentMember + include ActiveModel::Model + + attr_accessor :user_id, :user_role_id + attr_reader :current_user, :experiment, :user, :project, :user_role + + + def initialize(current_user, experiment, project, user = nil) + @experiment = experiment + @current_user = current_user + @project = project + + if user + @user = user + @user_role = UserAssignment.find_by(assignable: experiment, user: user)&.user_role + end + end + + def update(params) + self.user_role_id = params[:user_role_id] + self.user_id = params[:user_id] + + ActiveRecord::Base.transaction do + @user = @project.users.find(user_id) + @user_role = UserRole.find_by(id: user_role_id) + user_assignment = UserAssignment.find_by(assignable: experiment, user: user) + + if user_assignment.present? && user_role.nil? + user_assignment.destroy + elsif user_assignment.present? + user_assignment.update!(user_role: user_role) + else + UserAssignment.create!( + assignable: experiment, + user: user, + user_role: user_role, + assigned_by: current_user + ) + end + end + end +end diff --git a/app/views/access_permissions/experiments/edit.json.jbuilder b/app/views/access_permissions/experiments/edit.json.jbuilder new file mode 100644 index 000000000..47e2605d7 --- /dev/null +++ b/app/views/access_permissions/experiments/edit.json.jbuilder @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +json.modal controller.render_to_string( + partial: 'access_permissions/experiments/modals/edit_modal', + formats: [:html], + locals: { + experiment: @experiment, + project: @project, + users: @project.users, + project_path: project_path(@project) + }, + layout: false +) diff --git a/app/views/access_permissions/experiments/experiment_member.json.jbuilder b/app/views/access_permissions/experiments/experiment_member.json.jbuilder new file mode 100644 index 000000000..d011d5652 --- /dev/null +++ b/app/views/access_permissions/experiments/experiment_member.json.jbuilder @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +json.form controller.render_to_string( + partial: 'access_permissions/partials/experiment_member_field', + formats: [:html], + locals: { + user: @experiment_member.user, + experiment: @experiment_member.experiment, + project: @experiment_member.project, + update_path: access_permissions_project_experiment_path(@experiment_member.project, @experiment_member.experiment) + }, + layout: false +) diff --git a/app/views/access_permissions/experiments/modals/_edit_modal.html.erb b/app/views/access_permissions/experiments/modals/_edit_modal.html.erb new file mode 100644 index 000000000..6e2a09c59 --- /dev/null +++ b/app/views/access_permissions/experiments/modals/_edit_modal.html.erb @@ -0,0 +1,30 @@ +<% # frozen_string_literal: true %> + + diff --git a/app/views/access_permissions/experiments/modals/_show_modal.html.erb b/app/views/access_permissions/experiments/modals/_show_modal.html.erb new file mode 100644 index 000000000..623a8455b --- /dev/null +++ b/app/views/access_permissions/experiments/modals/_show_modal.html.erb @@ -0,0 +1,24 @@ +<% # frozen_string_literal: true %> + + diff --git a/app/views/access_permissions/experiments/show.json.jbuilder b/app/views/access_permissions/experiments/show.json.jbuilder new file mode 100644 index 000000000..0a248266e --- /dev/null +++ b/app/views/access_permissions/experiments/show.json.jbuilder @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +json.modal controller.render_to_string( + partial: 'access_permissions/experiments/modals/show_modal', + formats: [:html], + locals: { + experiment: @experiment, + users: @project.users, + project_path: project_path(@project) + }, + layout: false +) diff --git a/app/views/access_permissions/partials/_experiment_member_field.html.erb b/app/views/access_permissions/partials/_experiment_member_field.html.erb new file mode 100644 index 000000000..1a3874469 --- /dev/null +++ b/app/views/access_permissions/partials/_experiment_member_field.html.erb @@ -0,0 +1,25 @@ +<% # frozen_string_literal: true %> + +<% + experiment_member = ExperimentMember.new(current_user, experiment, project, user) + item_id = dom_id(user, :experiment_member) +%> + +<%= form_with(model: experiment_member, url: update_path, method: :put, remote: true, html: { class: 'row experiment-member-item', id: item_id, data: { action: 'replace-form autosave-form' } }) do |f| %> + <%= f.hidden_field :user_id, value: f.object.user.id %> +
+ + <%= image_tag avatar_path(user, :icon_small), title: current_assignee_name(user), class: 'img-circle pull-left' %> + +
+
+ <%= current_assignee_name(user) %> +
+ <%= user_assignment_resource_role_name(experiment_member, user, experiment) %> +
+ <% unless user == current_user %> +
+ <%= f.select :user_role_id, options_for_select(experiment_user_roles_collection, selected: f.object.user_role&.id), {}, class: 'form-control selectpicker' %> +
+ <% end %> +<% end %> diff --git a/app/views/access_permissions/partials/_project_member_field.html.erb b/app/views/access_permissions/partials/_project_member_field.html.erb index 2170602fd..d915d5d9c 100644 --- a/app/views/access_permissions/partials/_project_member_field.html.erb +++ b/app/views/access_permissions/partials/_project_member_field.html.erb @@ -15,7 +15,7 @@
<%= current_assignee_name(user) %>
- <%= project_member.user_role.name %> + <%= user_assignment_resource_role_name(project_member, user, project) %>
<% unless user == current_user %>
diff --git a/app/views/access_permissions/partials/_user_assignment.html.erb b/app/views/access_permissions/partials/_user_assignment.html.erb index b7074a802..94b01bc54 100644 --- a/app/views/access_permissions/partials/_user_assignment.html.erb +++ b/app/views/access_permissions/partials/_user_assignment.html.erb @@ -3,13 +3,13 @@
- <%= image_tag avatar_path(user_assignment.user, :icon_small), title: current_assignee_name(user_assignment.user), class: 'img-circle pull-left' %> + <%= image_tag avatar_path(user, :icon_small), title: current_assignee_name(user), class: 'img-circle pull-left' %>
- <%= current_assignee_name(user_assignment.user) %> + <%= current_assignee_name(user) %>
- <%= user_assignment.user_role.name %> + <%= user_assignment_resource_role_name(user_assignment, user, resource) %>
diff --git a/app/views/access_permissions/modals/_show_modal.html.erb b/app/views/access_permissions/projects/modals/_show_modal.html.erb similarity index 73% rename from app/views/access_permissions/modals/_show_modal.html.erb rename to app/views/access_permissions/projects/modals/_show_modal.html.erb index 722ae9e0f..a6fbd8fa3 100644 --- a/app/views/access_permissions/modals/_show_modal.html.erb +++ b/app/views/access_permissions/projects/modals/_show_modal.html.erb @@ -8,7 +8,11 @@
+
<% if experiment.archived_branch? %> <%= link_to experiment.name, module_archive_experiment_path(experiment), title: experiment.name %> @@ -55,6 +56,8 @@
+ <%= link_to 'Experiment Accesss', edit_access_permissions_project_experiment_path(project, experiment), remote: true, data: { action: 'remote-modal'} %> + <%= link_to 'Show Experiment Accesss', access_permissions_project_experiment_path(project, experiment), remote: true, data: { action: 'remote-modal'} %>
<%= custom_auto_link(experiment.description, team: current_team) %>
diff --git a/app/views/projects/show/_experiments_list.html.erb b/app/views/projects/show/_experiments_list.html.erb index 13009eb54..4fceb027d 100644 --- a/app/views/projects/show/_experiments_list.html.erb +++ b/app/views/projects/show/_experiments_list.html.erb @@ -1,5 +1,5 @@ <% cards.each do |card| %> <% cache [current_user, card] do %> - <%= render partial: 'projects/show/experiment_card', locals: { experiment: card } %> + <%= render partial: 'projects/show/experiment_card', locals: { experiment: card, project: project } %> <% end %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 5b04be165..1f482e28e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2318,6 +2318,8 @@ en: user_assignment: current_assignee: "(you)" select_role: "Select role" + from_project: "%{user_role} [from project]" + experiment_select_role: "Change experiment role" access_permissions: create: success: @@ -2337,10 +2339,17 @@ en: submit_singular: "Grand access to 1 user" submit_plural: "Grand access to {num} users" find_people_html: "🔍 Find people" - modals: - show_modal: - title: "Access to %{resource_name}" - new_resource_assignments: "Grant new access to %{resource}" + projects: + modals: + show_modal: + title: "Access to %{resource_name}" + new_resource_assignments: "Grant new access to %{resource}" + experiments: + modals: + show_modal: + title: "Access to %{resource_name}" + edit_modal: + title: "Manage access for %{resource_name}" zip_export: modal_label: 'Export inventory' notification_title: 'Your requested export package is ready!' diff --git a/config/routes.rb b/config/routes.rb index f4f992cf0..021901a0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -228,7 +228,9 @@ Rails.application.routes.draw do end namespace :access_permissions do - resources :projects + resources :projects, defaults: { format: 'json' } do + resources :experiments, only: %i(show update edit) + end end resources :projects, except: [:destroy] do