Merge pull request #7757 from rekonder/aj_SCI_10882

Add permissions for storage location and rename box to container [SCI-10882]
This commit is contained in:
ajugo 2024-07-29 09:54:33 +02:00 committed by GitHub
commit 66d620b5da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 146 additions and 50 deletions

View file

@ -3,9 +3,9 @@
class StorageLocationRepositoryRowsController < ApplicationController
before_action :load_storage_location_repository_row, only: %i(update destroy)
before_action :load_storage_location
before_action :load_repository_row, only: %i(update destroy)
before_action :check_read_permissions, only: :index
before_action :check_manage_permissions, except: :index
before_action :load_repository_row, only: %i(create update destroy)
before_action :check_read_permissions, except: %i(create actions_toolbar)
before_action :check_manage_permissions, only: %i(create update destroy)
def index
storage_location_repository_row = Lists::StorageLocationRepositoryRowsService.new(
@ -90,10 +90,12 @@ class StorageLocationRepositoryRowsController < ApplicationController
end
def check_read_permissions
render_403 unless true
render_403 unless can_read_storage_location_containers?(current_team)
end
def check_manage_permissions
render_403 unless true
unless can_manage_storage_location_containers?(current_team) && can_read_repository?(@repository_row.repository)
render_403
end
end
end

View file

@ -2,8 +2,9 @@
class StorageLocationsController < ApplicationController
before_action :load_storage_location, only: %i(update destroy duplicate move show)
before_action :check_read_permissions, only: :index
before_action :check_manage_permissions, except: :index
before_action :check_read_permissions, except: %i(index create tree actions_toolbar)
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions, only: %i(update destroy duplicate move)
before_action :set_breadcrumbs_items, only: %i(index show)
def index
@ -111,11 +112,27 @@ class StorageLocationsController < ApplicationController
end
def check_read_permissions
render_403 unless true
if @storage_location.container
render_403 unless can_read_storage_location_containers?(current_team)
else
render_403 unless can_read_storage_locations?(current_team)
end
end
def check_create_permissions
if storage_location_params[:container]
render_403 unless can_create_storage_location_containers?(current_team)
else
render_403 unless can_create_storage_locations?(current_team)
end
end
def check_manage_permissions
render_403 unless true
if @storage_location.container
render_403 unless can_manage_storage_location_containers?(current_team)
else
render_403 unless can_manage_storage_locations?(current_team)
end
end
def set_breadcrumbs_items

View file

@ -1,10 +1,10 @@
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import StorageLocationsBox from '../../vue/storage_locations/box.vue';
import StorageLocationsContainer from '../../vue/storage_locations/container.vue';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
const app = createApp();
app.component('StorageLocationsBox', StorageLocationsBox);
app.component('StorageLocationsContainer', StorageLocationsContainer);
app.config.globalProperties.i18n = window.I18n;
app.use(PerfectScrollbar);
mountWithTurbolinks(app, '#storageLocationsBox');
mountWithTurbolinks(app, '#StorageLocationsContainer');

View file

@ -13,7 +13,7 @@
</div>
<div class="h-full bg-white p-4">
<DataTable :columnDefs="columnDefs"
tableId="StorageLocationsBox"
tableId="StorageLocationsContainer"
:dataUrl="dataSource"
ref="table"
:reloadingTable="reloadingTable"
@ -34,7 +34,7 @@ import DataTable from '../shared/datatable/table.vue';
import Grid from './grid.vue';
export default {
name: 'StorageLocationsBox',
name: 'StorageLocationsContainer',
components: {
DataTable,
Grid

View file

@ -26,7 +26,7 @@
</div>
<span v-if="this.errors.name" class="text-sn-coral text-xs">{{ this.errors.name }}</span>
</div>
<div v-if="editModalMode == 'box'" class="mb-6">
<div v-if="editModalMode == 'container'" class="mb-6">
<label class="sci-label">
{{ i18n.t(`storage_locations.index.edit_modal.dimensions_label`) }}
</label>
@ -163,7 +163,7 @@ export default {
SmartAnnotation.init($(this.$refs.description), false);
$(this.$refs.modal).on('hidden.bs.modal', this.handleAtWhoModalClose);
this.object.container = this.editModalMode === 'box';
this.object.container = this.editModalMode === 'container';
},
methods: {
submit() {

View file

@ -7,7 +7,7 @@
:toolbarActions="toolbarActions"
:actionsUrl="actionsUrl"
@create_location="openCreateLocationModal"
@create_box="openCreateBoxModal"
@create_container="openCreateContainerModal"
@edit="edit"
@duplicate="duplicate"
@tableReloaded="reloadingTable = false"
@ -149,9 +149,9 @@ export default {
buttonStyle: 'btn btn-primary'
});
left.push({
name: 'create_box',
name: 'create_container',
icon: 'sn-icon sn-icon-item',
label: this.i18n.t('storage_locations.index.new_box'),
label: this.i18n.t('storage_locations.index.new_container'),
type: 'emit',
path: this.createUrl,
buttonStyle: 'btn btn-secondary'
@ -169,14 +169,14 @@ export default {
this.editModalMode = 'location';
this.editStorageLocation = null;
},
openCreateBoxModal() {
openCreateContainerModal() {
this.openEditModal = true;
this.editModalMode = 'box';
this.editModalMode = 'container';
this.editStorageLocation = null;
},
edit(action, params) {
this.openEditModal = true;
this.editModalMode = params[0].container ? 'box' : 'location';
this.editModalMode = params[0].container ? 'container' : 'location';
[this.editStorageLocation] = params;
},
duplicate(action) {
@ -195,13 +195,13 @@ export default {
name,
urls
} = params.data;
let boxIcon = '';
let containerIcon = '';
if (params.data.container) {
boxIcon = '<i class="sn-icon sn-icon-item"></i>';
containerIcon = '<i class="sn-icon sn-icon-item"></i>';
}
return `<a class="hover:no-underline flex items-center gap-1"
title="${name}" href="${urls.show}">
${boxIcon}
${containerIcon}
<span class="truncate">${name}</span>
</a>`;
},
@ -214,7 +214,7 @@ export default {
this.moveToUrl = event.path;
},
async deleteStorageLocation(event, rows) {
const storageLocationType = rows[0].container ? this.i18n.t('storage_locations.box') : this.i18n.t('storage_locations.location');
const storageLocationType = rows[0].container ? this.i18n.t('storage_locations.container') : this.i18n.t('storage_locations.location');
const description = `
<p>${this.i18n.t('storage_locations.index.delete_modal.description_1_html',
{ name: rows[0].name, type: storageLocationType, num_of_items: event.number_of_items })}</p>

View file

@ -43,12 +43,28 @@ Canaid::Permissions.register_for(Team) do
within_limits && team.permission_granted?(user, TeamPermissions::INVENTORIES_CREATE)
end
can :read_storage_locations do |user, team|
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATIONS_READ)
end
can :create_storage_locations do |user, team|
true # TODO: Add permission check
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATIONS_CREATE)
end
can :manage_storage_locations do |user, team|
true # TODO: Add permission check
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATIONS_MANAGE)
end
can :read_storage_location_containers do |user, team|
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATION_CONTAINERS_READ)
end
can :create_storage_location_containers do |user, team|
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATION_CONTAINERS_CREATE)
end
can :manage_storage_location_containers do |user, team|
team.permission_granted?(user, TeamPermissions::STORAGE_LOCATION_CONTAINERS_MANAGE)
end
can :create_reports do |user, team|

View file

@ -9,7 +9,7 @@ module Lists
end
def fetch_records
@records = StorageLocation.where(team: @team, parent_id: @parent_id)
@records = @team.storage_locations.where(parent_id: @parent_id)
end
def filter_records; end

View file

@ -8,9 +8,9 @@
<h1><%= @storage_location.name %></h1>
</div>
</div>
<div class="content-body" data-e2e="e2e-CO-storage_locations_box">
<div id="storageLocationsBox" class="fixed-content-body">
<storage-locations-box
<div class="content-body" data-e2e="e2e-CO-storage_locations_container">
<div id="StorageLocationsContainer" class="fixed-content-body">
<storage-locations-container
actions-url="<%= actions_toolbar_storage_location_storage_location_repository_rows_path(@storage_location) %>"
data-source="<%= storage_location_storage_location_repository_rows_path(@storage_location) %>"
:with-grid="<%= @storage_location.with_grid? %>"
@ -20,5 +20,5 @@
</div>
</div>
<%= javascript_include_tag 'vue_storage_locations_box' %>
<%= javascript_include_tag 'vue_storage_locations_container' %>
<% end %>

View file

@ -13,7 +13,13 @@ module PermissionExtends
REPORTS_CREATE
LABEL_TEMPLATES_READ
LABEL_TEMPLATES_MANAGE
).each { |permission| const_set(permission, "team_#{permission.underscore}") }
STORAGE_LOCATIONS_CREATE
STORAGE_LOCATIONS_MANAGE
STORAGE_LOCATIONS_READ
STORAGE_LOCATION_CONTAINERS_CREATE
STORAGE_LOCATION_CONTAINERS_MANAGE
STORAGE_LOCATION_CONTAINERS_READ
).each { |permission| const_set(permission, "team_#{permission.parameterize}") }
end
module ProtocolPermissions
@ -24,7 +30,7 @@ module PermissionExtends
MANAGE
USERS_MANAGE
MANAGE_DRAFT
).each { |permission| const_set(permission, "protocol_#{permission.underscore}") }
).each { |permission| const_set(permission, "protocol_#{permission.parameterize}") }
end
module ReportPermissions
@ -33,7 +39,7 @@ module PermissionExtends
READ
MANAGE
USERS_MANAGE
).each { |permission| const_set(permission, "report_#{permission.underscore}") }
).each { |permission| const_set(permission, "report_#{permission.parameterize}") }
end
module ProjectPermissions
@ -51,7 +57,7 @@ module PermissionExtends
COMMENTS_MANAGE_OWN
TAGS_MANAGE
EXPERIMENTS_CREATE
).each { |permission| const_set(permission, "project_#{permission.underscore}") }
).each { |permission| const_set(permission, "project_#{permission.parameterize}") }
end
module ExperimentPermissions
@ -65,7 +71,7 @@ module PermissionExtends
USERS_MANAGE
READ_CANVAS
ACTIVITIES_READ
).each { |permission| const_set(permission, "experiment_#{permission.underscore}") }
).each { |permission| const_set(permission, "experiment_#{permission.parameterize}") }
end
module MyModulePermissions
@ -107,7 +113,7 @@ module PermissionExtends
USERS_MANAGE
DESIGNATED_USERS_MANAGE
STOCK_CONSUMPTION_UPDATE
).each { |permission| const_set(permission, "task_#{permission.underscore}") }
).each { |permission| const_set(permission, "task_#{permission.parameterize}") }
end
module RepositoryPermissions
@ -127,7 +133,7 @@ module PermissionExtends
COLUMNS_DELETE
USERS_MANAGE
FILTERS_MANAGE
).each { |permission| const_set(permission, "inventory_#{permission.underscore}") }
).each { |permission| const_set(permission, "inventory_#{permission.parameterize}") }
end
module PredefinedRoles
@ -147,6 +153,12 @@ module PermissionExtends
TeamPermissions::REPORTS_CREATE,
TeamPermissions::LABEL_TEMPLATES_READ,
TeamPermissions::LABEL_TEMPLATES_MANAGE,
TeamPermissions::STORAGE_LOCATIONS_READ,
TeamPermissions::STORAGE_LOCATIONS_CREATE,
TeamPermissions::STORAGE_LOCATIONS_MANAGE,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_READ,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_CREATE,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_MANAGE,
ProtocolPermissions::READ,
ProtocolPermissions::READ_ARCHIVED,
ProtocolPermissions::MANAGE_DRAFT,
@ -241,6 +253,8 @@ module PermissionExtends
VIEWER_PERMISSIONS = [
TeamPermissions::LABEL_TEMPLATES_READ,
TeamPermissions::STORAGE_LOCATIONS_READ,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_READ,
ProtocolPermissions::READ,
ProtocolPermissions::READ_ARCHIVED,
ReportPermissions::READ,

View file

@ -2671,7 +2671,7 @@ en:
errors:
my_module_references_missing: 'Task references are not set'
storage_locations:
box: 'box'
container: 'box'
location: 'location'
show:
table:
@ -2687,7 +2687,7 @@ en:
index:
head_title: "Locations"
new_location: "New location"
new_box: "New box"
new_container: "New box"
duplicate:
success_message: "Location was successfully duplicated."
toolbar:
@ -2707,15 +2707,15 @@ en:
description: "Description"
edit_modal:
title_create_location: "Create new location"
title_create_box: "Create new box"
title_create_container: "Create new box"
title_edit_location: "Edit location"
title_edit_box: "Edit box"
title_edit_container: "Edit box"
description_create_location: "Fill in the fields and create a new location."
description_create_box: "Fill in the fields to create a new box. Defining the box dimensions allows you to control the number of available spaces for placing inventory items."
description_create_container: "Fill in the fields to create a new box. Defining the box dimensions allows you to control the number of available spaces for placing inventory items."
name_label_location: "Location name"
image_label_location: "Image of location"
name_label_box: "Box name"
image_label_box: "Image of box"
name_label_container: "Box name"
image_label_container: "Image of box"
drag_and_drop_supporting_text: ".png or .jpg file"
description_label: "Description"
name_placeholder: "Big freezer"
@ -2726,9 +2726,9 @@ en:
no_grid_tooltip: "You can assign unlimited items to the “No-grid” box but they do not have assigned position."
success_message:
create_location: "Location %{name} was successfully created."
create_box: "Box %{name} was successfully created."
create_container: "Box %{name} was successfully created."
edit_location: "Location %{name} was successfully updated."
edit_box: "Box %{name} was successfully updated."
edit_container: "Box %{name} was successfully updated."
errors:
max_length: "is too long (maximum is %{max_length} characters)"
move_modal:

View file

@ -67,7 +67,7 @@ const entryList = {
vue_legacy_repository_menu_dropdown: './app/javascript/packs/vue/legacy/repository_menu_dropdown.js',
vue_dashboard_new_task: './app/javascript/packs/vue/dashboard_new_task.js',
vue_storage_locations_table: './app/javascript/packs/vue/storage_locations_table.js',
vue_storage_locations_box: './app/javascript/packs/vue/storage_locations_box.js'
vue_storage_locations_container: './app/javascript/packs/vue/storage_locations_container.js'
};
// Engine pack loading based on https://github.com/rails/webpacker/issues/348#issuecomment-635480949

View file

@ -0,0 +1,47 @@
# frozen_string_literal: true
class AddStorageLocationPermissions < ActiveRecord::Migration[7.0]
STORAGE_LOCATIONS_MANAGE_PERMISSION = [
TeamPermissions::STORAGE_LOCATIONS_CREATE,
TeamPermissions::STORAGE_LOCATIONS_MANAGE,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_CREATE,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_MANAGE
].freeze
STORAGE_LOCATIONS_READ_PERMISSION = [
TeamPermissions::STORAGE_LOCATIONS_READ,
TeamPermissions::STORAGE_LOCATION_CONTAINERS_READ
].freeze
def up
@owner_role = UserRole.find_predefined_owner_role
@normal_user_role = UserRole.find_predefined_normal_user_role
@viewer_user_role = UserRole.find_predefined_viewer_role
@owner_role.permissions = @owner_role.permissions | STORAGE_LOCATIONS_MANAGE_PERMISSION |
STORAGE_LOCATIONS_READ_PERMISSION
@normal_user_role.permissions = @normal_user_role.permissions | STORAGE_LOCATIONS_MANAGE_PERMISSION |
STORAGE_LOCATIONS_READ_PERMISSION
@viewer_user_role.permissions = @viewer_user_role.permissions | STORAGE_LOCATIONS_READ_PERMISSION
@owner_role.save(validate: false)
@normal_user_role.save(validate: false)
@viewer_user_role.save(validate: false)
end
def down
@owner_role = UserRole.find_predefined_owner_role
@normal_user_role = UserRole.find_predefined_normal_user_role
@viewer_user_role = UserRole.find_predefined_viewer_role
@owner_role.permissions = @owner_role.permissions - STORAGE_LOCATIONS_MANAGE_PERMISSION -
STORAGE_LOCATIONS_READ_PERMISSION
@normal_user_role.permissions = @normal_user_role.permissions - STORAGE_LOCATIONS_MANAGE_PERMISSION -
STORAGE_LOCATIONS_READ_PERMISSION
@viewer_user_role.permissions = @viewer_user_role.permissions - STORAGE_LOCATIONS_READ_PERMISSION
@owner_role.save(validate: false)
@normal_user_role.save(validate: false)
@viewer_user_role.save(validate: false)
end
end