scinote-web/app/controllers/asset_sync_controller.rb

228 lines
6.4 KiB
Ruby

# frozen_string_literal: true
class AssetSyncController < ApplicationController
include FileIconsHelper
skip_before_action :authenticate_user!, only: %i(update download)
skip_before_action :verify_authenticity_token, only: %i(update download)
prepend_before_action :authenticate_asset_sync_token!, only: %i(update download)
before_action :check_asset_sync
def show
asset = Asset.find_by(id: params[:asset_id])
render_error(:forbidden) and return unless asset && can_manage_asset?(asset)
asset_sync_token = current_user.asset_sync_tokens.find_or_create_by(asset_id: params[:asset_id])
unless asset_sync_token.token_valid?
asset_sync_token = current_user.asset_sync_tokens.create(asset_id: params[:asset_id])
end
render json: AssetSyncTokenSerializer.new(asset_sync_token).as_json
end
def download
redirect_to(@asset.file.url, allow_other_host: true)
end
def update
if @asset_sync_token.conflicts?(request.headers['VersionToken'])
ActiveRecord::Base.transaction do
conflict_response = AssetSyncTokenSerializer.new(conflicting_asset_copy_token).as_json
error_message = { message: I18n.t('assets.conflict_error', filename: @asset.file.filename) }
log_activity(:create)
render json: conflict_response.merge(error_message), status: :conflict
end
return
end
orig_file_size = @asset.file_size
ActiveRecord::Base.transaction do
@asset.update(last_modified_by: current_user)
if wopi_file?(@asset)
@asset.update_contents(request.body)
else
@asset.file.attach(io: request.body, filename: @asset.file.filename)
@asset.touch
end
@asset.team.release_space(orig_file_size)
@asset.post_process_file
log_activity(:edit)
end
render json: AssetSyncTokenSerializer.new(@asset_sync_token).as_json
end
def api_url
render plain: Constants::ASSET_SYNC_URL
end
def log_activity(action)
case action
when :edit
log_edit_activity
when :create
log_create_activity
end
end
private
def render_error(status, filename = nil, message = nil)
message ||= if filename.present?
I18n.t('assets.default_error_with_filename', filename: filename)
else
I18n.t('assets.default_error')
end
render json: { message: message }, status: status
end
def conflicting_asset_copy_token
Asset.transaction do
new_asset = @asset.dup
new_asset.save
blob = ActiveStorage::Blob.create_and_upload!(
io: request.body,
filename: "#{@asset.file.filename.base} (#{t('general.copy')}).#{@asset.file.filename.extension}",
metadata: @asset.blob.metadata
)
new_asset.file.attach(blob)
case @asset.parent
when Step
StepAsset.create!(step: @asset.step, asset: new_asset)
when Result
ResultAsset.create!(result: @asset.result, asset: new_asset)
end
@asset = new_asset.reload
new_asset.post_process_file
current_user.asset_sync_tokens.create!(asset_id: new_asset.id)
end
end
def authenticate_asset_sync_token!
@asset_sync_token = AssetSyncToken.find_by(token: request.headers['Authentication'])
render_error(:unauthorized) and return unless @asset_sync_token&.token_valid?
@asset = @asset_sync_token.asset
sign_in(@asset_sync_token.user)
render_error(:forbidden, @asset.file.filename) and return unless can_manage_asset?(@asset)
end
def log_create_activity
assoc = @asset.step
assoc ||= @asset.result
case assoc
when Step
type_of = assoc.protocol.in_module? ? :task_step_file_added : :protocol_step_file_added
message_items = {
step: assoc.id,
step_position: { id: assoc.id,
value_for: 'position_plus_one' },
file: @asset.file_name,
my_module: assoc.protocol.in_module? ? assoc.my_module.id : nil,
protocol: assoc.protocol.in_module? ? nil : assoc.protocol.id
}.compact
project = assoc.protocol.in_module? ? assoc.my_module.project : nil
when Result
type_of = :result_file_added
message_items = { result: assoc.id }
project = assoc.my_module.project
end
Activities::CreateActivityService.call(
activity_type: type_of,
owner: current_user,
team: assoc.team,
subject: @asset,
project: project,
message_items: message_items
)
end
def log_edit_activity
assoc ||= @asset.step
assoc ||= @asset.result
case assoc
when Step
if assoc.protocol.in_module?
log_step_edit_activity(
:edit_task_step_file_locally,
assoc,
assoc.my_module.project,
my_module: assoc.my_module.id,
file: @asset.file_name,
user: current_user.id,
step_position_original: @asset.step.position + 1,
step: assoc.id
)
else
log_step_edit_activity(
:edit_protocol_template_file_locally,
assoc,
nil,
{
file: @asset.file_name,
user: current_user.id,
step_position_original: @asset.step.position + 1,
step: assoc.id
}
)
end
when Result
log_result_edit_activity(
:edit_task_result_file_locally,
assoc,
file: @asset.file_name,
user: current_user.id,
result: Result.first.id
)
end
end
def log_step_edit_activity(type_of, step, project = nil, message_items = {})
default_items = { step: step.id,
step_position: { id: step.id, value_for: 'position_plus_one' } }
message_items = default_items.merge(message_items)
Activities::CreateActivityService
.call(activity_type: type_of,
owner: current_user,
subject: step.protocol,
team: step.protocol.team,
project: project,
message_items: message_items)
end
def log_result_edit_activity(type_of, result, message_items)
Activities::CreateActivityService
.call(activity_type: type_of,
owner: current_user,
subject: result,
team: result.my_module.team,
project: result.my_module.project,
message_items: {
result: result.id
}.merge(message_items))
end
def check_asset_sync
render_404 if ENV['ASSET_SYNC_URL'].blank?
end
end