mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-06 13:14:29 +08:00
add assign user permission to experiment level
This commit is contained in:
parent
331a68e9b6
commit
ac91d9c2c4
19 changed files with 275 additions and 13 deletions
60
app/controllers/access_permissions/experiments_controller.rb
Normal file
60
app/controllers/access_permissions/experiments_controller.rb
Normal file
|
@ -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
|
|
@ -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 }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
44
app/models/experiment_member.rb
Normal file
44
app/models/experiment_member.rb
Normal file
|
@ -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
|
13
app/views/access_permissions/experiments/edit.json.jbuilder
Normal file
13
app/views/access_permissions/experiments/edit.json.jbuilder
Normal file
|
@ -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
|
||||
)
|
|
@ -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
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
<% # frozen_string_literal: true %>
|
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" data-action="modal-close" data-target="<%= project_path %>">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content" id="user_assignments_modal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><%= t '.title', resource_name: experiment.name %></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<% users.each do |user| %>
|
||||
<% user_assignment = experiment.user_assignments.find_by(user: user) %>
|
||||
|
||||
<% cache [user_assignment, experiment, user] do %>
|
||||
<%= render partial: 'access_permissions/partials/experiment_member_field',
|
||||
locals: {
|
||||
user: user,
|
||||
project: project,
|
||||
experiment: experiment,
|
||||
update_path: access_permissions_project_experiment_path(project, experiment)
|
||||
} %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type='button' class='btn btn-default' data-dismiss='modal'><%= t('general.cancel')%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,24 @@
|
|||
<% # frozen_string_literal: true %>
|
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" data-action="modal-close" data-target="<%= project_path %>">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content" id="user_assignments_modal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><%= t '.title', resource_name: experiment.name %></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<% users.each do |user| %>
|
||||
<% user_assignment = experiment.user_assignments.find_by(user: user) %>
|
||||
|
||||
<% cache [user_assignment, experiment, current_user, user] do %>
|
||||
<%= render partial: 'access_permissions/partials/user_assignment', locals: { user_assignment: user_assignment, user: user, resource: experiment } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type='button' class='btn btn-default' data-dismiss='modal'><%= t('general.cancel')%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
12
app/views/access_permissions/experiments/show.json.jbuilder
Normal file
12
app/views/access_permissions/experiments/show.json.jbuilder
Normal file
|
@ -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
|
||||
)
|
|
@ -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 %>
|
||||
<div class="col-xs-1">
|
||||
<span class="global-avatar-container">
|
||||
<%= image_tag avatar_path(user, :icon_small), title: current_assignee_name(user), class: 'img-circle pull-left' %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<span><%= current_assignee_name(user) %></span>
|
||||
<br>
|
||||
<small class="text-muted"><%= user_assignment_resource_role_name(experiment_member, user, experiment) %></small>
|
||||
</div>
|
||||
<% unless user == current_user %>
|
||||
<div class="col-xs-5">
|
||||
<%= f.select :user_role_id, options_for_select(experiment_user_roles_collection, selected: f.object.user_role&.id), {}, class: 'form-control selectpicker' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -15,7 +15,7 @@
|
|||
<div class="col-xs-3">
|
||||
<span><%= current_assignee_name(user) %></span>
|
||||
<br>
|
||||
<small class="text-muted"><%= project_member.user_role.name %></small>
|
||||
<small class="text-muted"><%= user_assignment_resource_role_name(project_member, user, project) %></small>
|
||||
</div>
|
||||
<% unless user == current_user %>
|
||||
<div class="col-xs-7">
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<div class="row project-member-item">
|
||||
<div class="col-xs-2">
|
||||
<span class="global-avatar-container">
|
||||
<%= 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' %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-10 col-sm-4">
|
||||
<span><%= current_assignee_name(user_assignment.user) %></span>
|
||||
<span><%= current_assignee_name(user) %></span>
|
||||
<br>
|
||||
<small class="text-muted"><%= user_assignment.user_role.name %></small>
|
||||
<small class="text-muted"><%= user_assignment_resource_role_name(user_assignment, user, resource) %></small>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
<h4 class="modal-title"><%= t '.title', resource_name: resource.name %></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%= render partial: 'access_permissions/partials/user_assignment', collection: resource.user_assignments, cached: ->(user_assignment) { [user_assignment. resource, current_user] } %>
|
||||
<% resource.user_assignments.each do |user_assignment| %>
|
||||
<% cache [user_assignment, resource, current_user, user_assignment.user] do %>
|
||||
<%= render partial: 'access_permissions/partials/user_assignment', locals: { user_assignment: user_assignment, user: user_assignment.user, resource: resource } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<% if can_manage_resource %>
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
json.modal controller.render_to_string(
|
||||
partial: 'access_permissions/modals/show_modal',
|
||||
partial: 'access_permissions/projects/modals/show_modal',
|
||||
formats: [:html],
|
||||
locals: {
|
||||
resource: @project,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<span class="sci-checkbox-label"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="experiment-name-cell table-cell">
|
||||
<% if experiment.archived_branch? %>
|
||||
<%= link_to experiment.name, module_archive_experiment_path(experiment), title: experiment.name %>
|
||||
|
@ -55,6 +56,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="description-cell table-cell">
|
||||
<%= 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'} %>
|
||||
<div class="description-text">
|
||||
<%= custom_auto_link(experiment.description, team: current_team) %>
|
||||
</div>
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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!'
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue