
Previously, we were not properly rejecting the submission, so that the channel name was still evaluated (leading to errors). Now, we handle these cases as well. Fixes CODEOCEAN-V2
97 lines
2.9 KiB
Ruby
97 lines
2.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class SynchronizedEditorChannel < ApplicationCable::Channel
|
|
def subscribed
|
|
set_and_authorize_exercise
|
|
authorize_programming_group
|
|
|
|
stream_from specific_channel unless subscription_rejected?
|
|
|
|
# We generate a session_id for the user and send it to the client
|
|
@session_id = SecureRandom.uuid
|
|
|
|
# We need to wait for the subscription to be confirmed before we can send further messages
|
|
send_after_streaming_confirmed do
|
|
connection.transmit identifier: @identifier, message: {action: :session_id, session_id: @session_id}
|
|
|
|
message = create_message('connection_change', 'connected')
|
|
Event::SynchronizedEditor.create_for_connection_change(message, current_user, programming_group)
|
|
ActionCable.server.broadcast(specific_channel, message)
|
|
end
|
|
end
|
|
|
|
def unsubscribed
|
|
# Any cleanup needed when channel is unsubscribed
|
|
stop_all_streams
|
|
return unless programming_group && @session_id
|
|
|
|
message = create_message('connection_change', 'disconnected')
|
|
|
|
Event::SynchronizedEditor.create_for_connection_change(message, current_user, programming_group)
|
|
ActionCable.server.broadcast(specific_channel, message)
|
|
end
|
|
|
|
def editor_change(message)
|
|
change = message.deep_symbolize_keys
|
|
|
|
Event::SynchronizedEditor.create_for_editor_change(change, current_user, programming_group)
|
|
ActionCable.server.broadcast(specific_channel, change)
|
|
end
|
|
|
|
def connection_status
|
|
message = create_message('connection_status', 'connected')
|
|
|
|
Event::SynchronizedEditor.create_for_connection_change(message, current_user, programming_group)
|
|
ActionCable.server.broadcast(specific_channel, message)
|
|
end
|
|
|
|
def current_content(message)
|
|
Event::SynchronizedEditor.create_for_current_content(message, current_user, programming_group)
|
|
ActionCable.server.broadcast(specific_channel, message)
|
|
end
|
|
|
|
def reset_content(content)
|
|
message = create_reset_content_message(content)
|
|
ActionCable.server.broadcast(specific_channel, message)
|
|
end
|
|
|
|
private
|
|
|
|
def specific_channel
|
|
"synchronized_editor_channel_group_#{programming_group.id}"
|
|
end
|
|
|
|
def programming_group
|
|
current_contributor if current_contributor.programming_group?
|
|
end
|
|
|
|
def create_message(action, status)
|
|
{
|
|
action:,
|
|
status:,
|
|
user: current_user.to_page_context,
|
|
session_id: @session_id,
|
|
}
|
|
end
|
|
|
|
def create_reset_content_message(content)
|
|
{
|
|
action: content['action'],
|
|
files: content['files'],
|
|
user: current_user.to_page_context,
|
|
session_id: @session_id,
|
|
}
|
|
end
|
|
|
|
def set_and_authorize_exercise
|
|
@exercise = Exercise.find(params[:exercise_id])
|
|
reject unless ExercisePolicy.new(current_user, @exercise).implement?
|
|
rescue ActiveRecord::RecordNotFound
|
|
reject
|
|
end
|
|
|
|
def authorize_programming_group
|
|
reject unless ProgrammingGroupPolicy.new(current_user, programming_group).stream_sync_editor?
|
|
end
|
|
end
|