class AssetsController < ApplicationController include WopiUtil # include ActionView::Helpers include ActionView::Helpers::AssetTagHelper include ActionView::Helpers::TextHelper include ActionView::Helpers::UrlHelper include ActionView::Context include InputSanitizeHelper include FileIconsHelper include WopiHelper before_action :load_vars before_action :check_read_permission, except: :file_present before_action :load_vars, except: :signature before_action :check_read_permission, except: [:signature, :file_present] before_action :check_edit_permission, only: :edit # Validates asset and then generates S3 upload posts, because # otherwise untracked files could be uploaded to S3 def signature respond_to do |format| format.json { asset = Asset.new(asset_params) if asset.valid? posts = generate_upload_posts asset render json: { posts: posts } else render json: { status: 'error', errors: asset.errors }, status: :bad_request end } end end def file_present respond_to do |format| format.json do if @asset.file.processing? render json: {}, status: 404 else # Only if file is present, # check_read_permission check_read_permission # If check_read_permission already rendered error, # stop execution return if performed? # If check permission passes, return :ok render json: { 'asset-id' => @asset.id, 'image-tag-url' => @asset.url(:medium), 'preview-url' => large_image_url_asset_path(@asset), 'filename' => truncate(@asset.file_file_name, length: Constants::FILENAME_TRUNCATION_LENGTH), 'download-url' => download_asset_path(@asset), 'type' => asset_data_type(@asset), 'wopi-file-name' => wopi_asset_file_name(@asset, true), 'wopi-edit' => (wopi_asset_edit_button(@asset) if wopi_file?(@asset)), 'wopi-view' => (wopi_asset_view_button(@asset) if wopi_file?(@asset)) }, status: 200 end end end end def large_image_url respond_to do |format| format.json do render json: { 'large-preview-url' => @asset.url(:large), 'filename' => truncate(@asset.file_file_name, length: Constants::FILENAME_TRUNCATION_LENGTH), 'download-url' => download_asset_path(@asset), 'type' => (@asset.is_image? ? 'image' : 'file') } end end end def download if !@asset.file_present render_404 and return elsif @asset.file.is_stored_on_s3? redirect_to @asset.presigned_url(download: true), status: 307 else send_file @asset.file.path, filename: URI.unescape(@asset.file_file_name), type: @asset.file_content_type end end def edit @action_url = append_wd_params(@asset .get_action_url(current_user, 'edit', false)) @favicon_url = @asset.favicon_url('edit') tkn = current_user.get_wopi_token @token = tkn.token @ttl = (tkn.ttl * 1000).to_s create_wopi_file_activity(current_user, true) render layout: false end def view @action_url = append_wd_params(@asset .get_action_url(current_user, 'view', false)) @favicon_url = @asset.favicon_url('view') tkn = current_user.get_wopi_token @token = tkn.token @ttl = (tkn.ttl * 1000).to_s render layout: false end private def load_vars @asset = Asset.find_by_id(params[:id]) render_404 unless @asset step_assoc = @asset.step result_assoc = @asset.result @assoc = step_assoc unless step_assoc.nil? @assoc = result_assoc unless result_assoc.nil? if @assoc.class == Step @protocol = @asset.step.protocol else @my_module = @assoc.my_module end end def check_read_permission if @assoc.class == Step unless can_view_or_download_step_assets(@protocol) render_403 and return end elsif @assoc.class == Result unless can_view_or_download_result_assets(@my_module) render_403 and return end end end def check_edit_permission if @assoc.class == Step unless can_edit_step_in_protocol(@protocol) render_403 and return end elsif @assoc.class == Result unless can_edit_result_asset_in_module(@my_module) render_403 and return end end end def generate_upload_posts(asset) posts = [] s3_post = S3_BUCKET.presigned_post( key: asset.file.path[1..-1], success_action_status: '201', acl: 'private', storage_class: "STANDARD", content_length_range: 1..Constants::FILE_MAX_SIZE_MB.megabytes, content_type: asset.file_content_type ) posts.push({ url: s3_post.url, fields: s3_post.fields }) condition = %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}} if condition === asset.file_content_type asset.file.options[:styles].each do |style, option| s3_post = S3_BUCKET.presigned_post( key: asset.file.path(style)[1..-1], success_action_status: '201', acl: 'public-read', storage_class: "REDUCED_REDUNDANCY", content_length_range: 1..Constants::FILE_MAX_SIZE_MB.megabytes, content_type: asset.file_content_type ) posts.push({ url: s3_post.url, fields: s3_post.fields, style_option: option, mime_type: asset.file_content_type }) end end posts end def append_wd_params(url) wd_params = '' params.keys.select { |i| i[/^wd.*/] }.each do |wd| next if wd == 'wdPreviousSession' || wd == 'wdPreviousCorrelation' wd_params += "&#{wd}=#{params[wd]}" end url + wd_params end def asset_params params.permit( :file ) end def asset_data_type(asset) return 'wopi' if wopi_file?(asset) return 'image' if asset.is_image? 'file' end end