forked from External/greenlight
		
	Merge branch 'master' into webhooks
This commit is contained in:
		
							
								
								
									
										6
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Gemfile
									
									
									
									
									
								
							@@ -82,3 +82,9 @@ gem 'slack-notifier'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# For landing background image uploading.
 | 
					# For landing background image uploading.
 | 
				
			||||||
gem 'paperclip', '~> 4.2'
 | 
					gem 'paperclip', '~> 4.2'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For uploading recordings to Youtube.
 | 
				
			||||||
 | 
					gem 'yt', '~> 0.28.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Simple HTTP client.
 | 
				
			||||||
 | 
					gem 'faraday'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -229,6 +229,8 @@ GEM
 | 
				
			|||||||
      websocket-extensions (>= 0.1.0)
 | 
					      websocket-extensions (>= 0.1.0)
 | 
				
			||||||
    websocket-extensions (0.1.2)
 | 
					    websocket-extensions (0.1.2)
 | 
				
			||||||
    xml-simple (1.1.5)
 | 
					    xml-simple (1.1.5)
 | 
				
			||||||
 | 
					    yt (0.28.5)
 | 
				
			||||||
 | 
					      activesupport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PLATFORMS
 | 
					PLATFORMS
 | 
				
			||||||
  ruby
 | 
					  ruby
 | 
				
			||||||
@@ -240,6 +242,7 @@ DEPENDENCIES
 | 
				
			|||||||
  byebug
 | 
					  byebug
 | 
				
			||||||
  coffee-rails (~> 4.2)
 | 
					  coffee-rails (~> 4.2)
 | 
				
			||||||
  dotenv-rails
 | 
					  dotenv-rails
 | 
				
			||||||
 | 
					  faraday
 | 
				
			||||||
  font-awesome-sass
 | 
					  font-awesome-sass
 | 
				
			||||||
  http_accept_language
 | 
					  http_accept_language
 | 
				
			||||||
  jbuilder (~> 2.5)
 | 
					  jbuilder (~> 2.5)
 | 
				
			||||||
@@ -267,6 +270,7 @@ DEPENDENCIES
 | 
				
			|||||||
  tzinfo-data
 | 
					  tzinfo-data
 | 
				
			||||||
  uglifier (>= 1.3.0)
 | 
					  uglifier (>= 1.3.0)
 | 
				
			||||||
  web-console
 | 
					  web-console
 | 
				
			||||||
 | 
					  yt (~> 0.28.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUBY VERSION
 | 
					RUBY VERSION
 | 
				
			||||||
   ruby 2.3.4p301
 | 
					   ruby 2.3.4p301
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,9 +20,9 @@ For a overview of how GreenLight works, see the following video
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation on the BigBlueButton server
 | 
					## Installation on the BigBlueButton server
 | 
				
			||||||
We designed GreenLight to install on a [BigBlueButton 1.1-beta](http://docs.bigbluebutton.org/1.1/install.html) (or later) server.  This means you don't need a separate server to run GreenLight.
 | 
					We designed GreenLight to install on a [BigBlueButton 1.1-beta](http://docs.bigbluebutton.org/install/green-light.html) (or later) server.  This means you don't need a separate server to run GreenLight.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For more informaiton see [Installing GreenLight](http://docs.bigbluebutton.org/1.1/green-light.html).
 | 
					For more informaiton see [Installing GreenLight](http://docs.bigbluebutton.org/install/green-light.html).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Source Code
 | 
					# Source Code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,18 @@ class @Recordings
 | 
				
			|||||||
    COLUMN[c] = i++
 | 
					    COLUMN[c] = i++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor: ->
 | 
					  constructor: ->
 | 
				
			||||||
 | 
					    recordingsObject = this
 | 
				
			||||||
 | 
					    canUpload = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Determine which recordings can be uploaded to Youtube.
 | 
				
			||||||
 | 
					    $.ajax({
 | 
				
			||||||
 | 
					      method: 'GET',
 | 
				
			||||||
 | 
					      async: false,
 | 
				
			||||||
 | 
					      url: recordingsObject.getRecordingsURL() + '/can_upload'
 | 
				
			||||||
 | 
					    }).success((res_data) ->
 | 
				
			||||||
 | 
					      canUpload = res_data
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # configure the datatable for recordings
 | 
					    # configure the datatable for recordings
 | 
				
			||||||
    this.table = $('#recordings').dataTable({
 | 
					    this.table = $('#recordings').dataTable({
 | 
				
			||||||
      data: [],
 | 
					      data: [],
 | 
				
			||||||
@@ -131,6 +143,14 @@ class @Recordings
 | 
				
			|||||||
              trigger = recordingActions.find('.recording-update-trigger')
 | 
					              trigger = recordingActions.find('.recording-update-trigger')
 | 
				
			||||||
              trigger.removeClass(classes.join(' '))
 | 
					              trigger.removeClass(classes.join(' '))
 | 
				
			||||||
              trigger.addClass(cls)
 | 
					              trigger.addClass(cls)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              upload_btn = recordingActions.find('.cloud-upload')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              if canUpload[row.id]
 | 
				
			||||||
 | 
					                upload_btn.attr('data-popover-body', '.mail_youtube_popover')
 | 
				
			||||||
 | 
					              else
 | 
				
			||||||
 | 
					                upload_btn.attr('data-popover-body', '.mail_popover')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              return recordingActions.html()
 | 
					              return recordingActions.html()
 | 
				
			||||||
            return data
 | 
					            return data
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -151,6 +171,22 @@ class @Recordings
 | 
				
			|||||||
    options.title = I18n.play_recording
 | 
					    options.title = I18n.play_recording
 | 
				
			||||||
    $('#recordings').tooltip(options)
 | 
					    $('#recordings').tooltip(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options.selector = '.youtube-tooltip'
 | 
				
			||||||
 | 
					    options.title = I18n.upload_youtube
 | 
				
			||||||
 | 
					    $('#recordings').tooltip(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options.selector = '.upload-tooltip'
 | 
				
			||||||
 | 
					    options.title = I18n.share
 | 
				
			||||||
 | 
					    $('#recordings').tooltip(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options.selector = '.mail-tooltip'
 | 
				
			||||||
 | 
					    options.title = I18n.mail_recording
 | 
				
			||||||
 | 
					    $('#recordings').tooltip(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options.selector = '.disabled-tooltip'
 | 
				
			||||||
 | 
					    options.title = I18n.youtube_disabled
 | 
				
			||||||
 | 
					    $('#recordings').tooltip(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(document).one "turbolinks:before-cache", =>
 | 
					    $(document).one "turbolinks:before-cache", =>
 | 
				
			||||||
      @getTable().api().clear().draw().destroy()
 | 
					      @getTable().api().clear().draw().destroy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -229,6 +265,7 @@ class @Recordings
 | 
				
			|||||||
  setupActionHandlers: ->
 | 
					  setupActionHandlers: ->
 | 
				
			||||||
    table_api = this.table.api()
 | 
					    table_api = this.table.api()
 | 
				
			||||||
    recordingsObject = this
 | 
					    recordingsObject = this
 | 
				
			||||||
 | 
					    selectedUpload = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @getTable().on 'click', '.recording-update', (event) ->
 | 
					    @getTable().on 'click', '.recording-update', (event) ->
 | 
				
			||||||
      btn = $(this)
 | 
					      btn = $(this)
 | 
				
			||||||
@@ -273,12 +310,73 @@ class @Recordings
 | 
				
			|||||||
          showAlert(I18n.recording_deleted, 4000);
 | 
					          showAlert(I18n.recording_deleted, 4000);
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @getTable().on 'click', '.upload-button', (event) ->
 | 
				
			||||||
 | 
					      btn = $(this)
 | 
				
			||||||
 | 
					      row = table_api.row($(this).closest('tr')).data()
 | 
				
			||||||
 | 
					      url = recordingsObject.getRecordingsURL()
 | 
				
			||||||
 | 
					      id = row.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      title = $('#video-title').val()
 | 
				
			||||||
 | 
					      privacy_status = $('input[name=privacy_status]:checked').val()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if title == ''
 | 
				
			||||||
 | 
					        title = row.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $.ajax({
 | 
				
			||||||
 | 
					        method: 'POST',
 | 
				
			||||||
 | 
					        url: url+'/'+id
 | 
				
			||||||
 | 
					        data: {video_title: title, privacy_status: privacy_status}
 | 
				
			||||||
 | 
					        success: () ->
 | 
				
			||||||
 | 
					          cloud = selectedUpload.find('.cloud-blue')
 | 
				
			||||||
 | 
					          check = selectedUpload.find('.green-check')
 | 
				
			||||||
 | 
					          spinner = selectedUpload.find('.load-spinner')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          spinner.hide()
 | 
				
			||||||
 | 
					          check.show()
 | 
				
			||||||
 | 
					          setTimeout ( ->
 | 
				
			||||||
 | 
					            cloud.show()
 | 
				
			||||||
 | 
					            check.hide()
 | 
				
			||||||
 | 
					          ), 4000
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      selectedUpload.find('.cloud-blue').hide()
 | 
				
			||||||
 | 
					      selectedUpload.find('.load-spinner').show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @getTable().on 'click', '.mail-recording', (event) ->
 | 
				
			||||||
 | 
					      btn = $(this)
 | 
				
			||||||
 | 
					      row = table_api.row($(this).closest('tr')).data()
 | 
				
			||||||
 | 
					      url = recordingsObject.getRecordingsURL()
 | 
				
			||||||
 | 
					      id = row.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Take the username from the header.
 | 
				
			||||||
 | 
					      username = $('#title-header').text().replace('Welcome ', '').trim()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      recording_url = row.playbacks[0].url
 | 
				
			||||||
 | 
					      webcams_url = getHostName(recording_url) + '/presentation/' + id + '/video/webcams.webm'
 | 
				
			||||||
 | 
					      subject = username + I18n.recording_mail_subject
 | 
				
			||||||
 | 
					      body = I18n.recording_mail_body + "\n\n" + recording_url + "\n\n" + I18n.email_footer_1 + "\n" + I18n.email_footer_2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      mailto = "mailto:?subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(body);
 | 
				
			||||||
 | 
					      window.open(mailto);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @getTable().on 'click', '.youtube-upload', (event) ->
 | 
				
			||||||
 | 
					      row = table_api.row($(this).closest('tr')).data()
 | 
				
			||||||
 | 
					      $('#video-title').attr('value', row.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @getTable().on 'click', '.cloud-upload', (event) ->
 | 
				
			||||||
 | 
					      selectedUpload = $(this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @getTable().on 'draw.dt', (event) ->
 | 
					    @getTable().on 'draw.dt', (event) ->
 | 
				
			||||||
      $('time[data-time-ago]').timeago();
 | 
					      $('time[data-time-ago]').timeago();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getTable: ->
 | 
					  getTable: ->
 | 
				
			||||||
    @table
 | 
					    @table
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getHostName = (url) ->
 | 
				
			||||||
 | 
					    parser = document.createElement('a');
 | 
				
			||||||
 | 
					    parser.href = url;
 | 
				
			||||||
 | 
					    parser.origin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getRecordingsURL: ->
 | 
					  getRecordingsURL: ->
 | 
				
			||||||
    if $(".page-wrapper.rooms").data('main-room')
 | 
					    if $(".page-wrapper.rooms").data('main-room')
 | 
				
			||||||
      base_url = Meeting.buildRootURL()+'/'+$('body').data('resource')+'/'+Meeting.getInstance().getAdminId()
 | 
					      base_url = Meeting.buildRootURL()+'/'+$('body').data('resource')+'/'+Meeting.getInstance().getAdminId()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,3 +94,23 @@
 | 
				
			|||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					.youtube-red {
 | 
				
			||||||
 | 
					  color: red;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.cloud-blue {
 | 
				
			||||||
 | 
					  color: cornflowerblue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.green-check {
 | 
				
			||||||
 | 
					  color: limegreen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.top-buffer {
 | 
				
			||||||
 | 
					  margin-top: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tooltip-wrapper {
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -170,6 +170,41 @@ class BbbController < ApplicationController
 | 
				
			|||||||
    render_bbb_response bbb_res
 | 
					    render_bbb_response bbb_res
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # POST /rooms/:room_id/recordings/:record_id
 | 
				
			||||||
 | 
					  # POST /rooms/:room_id/:id/recordings/:record_id
 | 
				
			||||||
 | 
					  def youtube_publish
 | 
				
			||||||
 | 
					    # If we can't get the client, then they don't have a Youtube account.
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					      client = Yt::Account.new(access_token: current_user.token)
 | 
				
			||||||
 | 
					      video = client.upload_video(get_webcams_url(params[:record_id]),
 | 
				
			||||||
 | 
					              title: params[:video_title],
 | 
				
			||||||
 | 
					              description: t('youtube_description', url: 'https://bigbluebutton.org/'),
 | 
				
			||||||
 | 
					              privacy_status: params[:privacy_status])
 | 
				
			||||||
 | 
					    rescue
 | 
				
			||||||
 | 
					      # In this case, they don't have a youtube channel connected to their account, so prompt to create one.
 | 
				
			||||||
 | 
					      redirect_to 'https://m.youtube.com/create_channel'
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # GET /rooms/:room_id/recordings/can_upload
 | 
				
			||||||
 | 
					  def can_upload
 | 
				
			||||||
 | 
					    upload_data = {}
 | 
				
			||||||
 | 
					    bbb_get_recordings[:recordings].each{ |recording_data|
 | 
				
			||||||
 | 
					      next if recording_data[:recordID] == ""
 | 
				
			||||||
 | 
					      # The recording is uploadable if it contains webcam data and they are logged in thorugh Google.
 | 
				
			||||||
 | 
					      uploadable = Faraday.head(get_webcams_url(recording_data[:recordID])).status == 200 &&
 | 
				
			||||||
 | 
					                   Rails.application.config.omniauth_google &&
 | 
				
			||||||
 | 
					                   current_user.provider == 'google'
 | 
				
			||||||
 | 
					      upload_data[recording_data[:recordID]] = uploadable
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    render json: upload_data
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def get_webcams_url(recording_id)
 | 
				
			||||||
 | 
					    uri = URI.parse(ENV['BIGBLUEBUTTON_ENDPOINT'])
 | 
				
			||||||
 | 
					    uri.scheme + '://' + uri.host + '/presentation/' + recording_id + '/video/webcams.webm'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def load_room!
 | 
					  def load_room!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,6 +141,7 @@ module BbbApi
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res[:recordings].each do |recording|
 | 
					    res[:recordings].each do |recording|
 | 
				
			||||||
 | 
					      next if recording.key?(:error)
 | 
				
			||||||
      pref_preview = {}
 | 
					      pref_preview = {}
 | 
				
			||||||
      recording[:length] = recording[:playback][:format].is_a?(Hash) ? recording[:playback][:format][:length] : recording[:playback][:format].first[:length]
 | 
					      recording[:length] = recording[:playback][:format].is_a?(Hash) ? recording[:playback][:format][:length] : recording[:playback][:format].first[:length]
 | 
				
			||||||
      # create a playbacks attribute on recording for playback formats
 | 
					      # create a playbacks attribute on recording for playback formats
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@ class User < ApplicationRecord
 | 
				
			|||||||
    user.username = self.send("#{auth_hash['provider']}_username", auth_hash) rescue nil
 | 
					    user.username = self.send("#{auth_hash['provider']}_username", auth_hash) rescue nil
 | 
				
			||||||
    user.email = self.send("#{auth_hash['provider']}_email", auth_hash) rescue nil
 | 
					    user.email = self.send("#{auth_hash['provider']}_email", auth_hash) rescue nil
 | 
				
			||||||
    user.name = auth_hash['info']['name']
 | 
					    user.name = auth_hash['info']['name']
 | 
				
			||||||
 | 
					    user.token = auth_hash['credentials']['token'] rescue nil
 | 
				
			||||||
    user.save!
 | 
					    user.save!
 | 
				
			||||||
    user
 | 
					    user
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<% content_for :title do %>
 | 
					<% content_for :title do %>
 | 
				
			||||||
  <div class="title">
 | 
					  <div class="title">
 | 
				
			||||||
    <h2>
 | 
					    <h2 id = 'title-header'>
 | 
				
			||||||
      <% if admin? && !@meeting_running %>
 | 
					      <% if admin? && !@meeting_running %>
 | 
				
			||||||
        <%= t('admin_room_title', user: @user.name) %>
 | 
					        <%= t('admin_room_title', user: @user.name) %>
 | 
				
			||||||
      <% else %>
 | 
					      <% else %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,49 @@
 | 
				
			|||||||
      <%= t('no') %>
 | 
					      <%= t('no') %>
 | 
				
			||||||
    </button>
 | 
					    </button>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class="youtube-popover">
 | 
				
			||||||
 | 
					    <form class = "form-inline">
 | 
				
			||||||
 | 
					      <div class = "row">
 | 
				
			||||||
 | 
					        <div class="col-xs-12">
 | 
				
			||||||
 | 
					          <input type="title" class="form-control" id="video-title" placeholder="<%= t('video_title') %>">
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class = "row top-buffer text-center">
 | 
				
			||||||
 | 
					        <div class = "col-xs-10 col-xs-offset-1">
 | 
				
			||||||
 | 
					          <form class="privacy_form">
 | 
				
			||||||
 | 
					            <label class="radio-inline"><input type="radio" name="privacy_status" value="public" checked><%= t('youtube_privacy_options.public') %> </label>
 | 
				
			||||||
 | 
					            <label class="radio-inline"><input type="radio" name="privacy_status" value="private"><%= t('youtube_privacy_options.private') %> </label>
 | 
				
			||||||
 | 
					            <label class="radio-inline"><input type="radio" name="privacy_status" value="unlisted"><%= t('youtube_privacy_options.unlisted') %></label>
 | 
				
			||||||
 | 
					          </form>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					        <div class="row top-buffer text-center">
 | 
				
			||||||
 | 
					          <button type="button" class="btn btn-success upload-button centered" data-dismiss="popover">
 | 
				
			||||||
 | 
					            <%= t('upload') %>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class='mail_youtube_popover'>
 | 
				
			||||||
 | 
					    <button type="button" class="btn btn-default mail-recording mail-tooltip">
 | 
				
			||||||
 | 
					      <%= icon('envelope-o') %>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button type="button" class="btn btn-default has-popover youtube-upload youtube-tooltip"
 | 
				
			||||||
 | 
					          data-placement="top" data-popover-body=".youtube-popover"
 | 
				
			||||||
 | 
					          data-popover-title="<%= t('upload_to_youtube') %>" >
 | 
				
			||||||
 | 
					      <div class = 'youtube-red'> <%= icon('youtube-play') %> </div>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class='mail_popover'>
 | 
				
			||||||
 | 
					    <button type="button" class="btn btn-default mail-recording mail-tooltip fa-2x">
 | 
				
			||||||
 | 
					      <%= icon('envelope-o') %>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <div class="tooltip-wrapper disabled disabled-tooltip">
 | 
				
			||||||
 | 
					      <button type="button" class="btn btn-default" disabled>
 | 
				
			||||||
 | 
					          <%= icon('youtube-play') %>
 | 
				
			||||||
 | 
					      </button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
  <div class="recording-visibility-popover">
 | 
					  <div class="recording-visibility-popover">
 | 
				
			||||||
    <button type="button" class="btn btn-default btn-success recording-update" data-visibility="published">
 | 
					    <button type="button" class="btn btn-default btn-success recording-update" data-visibility="published">
 | 
				
			||||||
      <%= t('client.published') %>
 | 
					      <%= t('client.published') %>
 | 
				
			||||||
@@ -72,6 +115,12 @@
 | 
				
			|||||||
            data-popover-title="<%= t('change_recording_visibility') %>">
 | 
					            data-popover-title="<%= t('change_recording_visibility') %>">
 | 
				
			||||||
      <%= icon('eye') %>
 | 
					      <%= icon('eye') %>
 | 
				
			||||||
    </button>
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button type="button" class="btn btn-default has-popover cloud-upload upload-tooltip"
 | 
				
			||||||
 | 
					            data-placement="top">
 | 
				
			||||||
 | 
					      <div class = 'cloud-blue'> <%= icon('cloud-upload') %> </div>
 | 
				
			||||||
 | 
					      <div class = 'green-check' hidden> <%= icon('check') %> </div>
 | 
				
			||||||
 | 
					      <div class = 'load-spinner fa-spin' hidden> <%= icon('spinner') %> </div>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
    <a tabindex="0" role="button" class="btn btn-default has-popover delete-tooltip"
 | 
					    <a tabindex="0" role="button" class="btn btn-default has-popover delete-tooltip"
 | 
				
			||||||
       data-placement="top" data-popover-body=".delete-popover-body"
 | 
					       data-placement="top" data-popover-body=".delete-popover-body"
 | 
				
			||||||
       data-popover-title="<%= t('are_you_sure') %>">
 | 
					       data-popover-title="<%= t('are_you_sure') %>">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,5 +7,5 @@ Rails.application.config.omniauth_twitter = ENV['TWITTER_ID'].present?
 | 
				
			|||||||
Rails.application.config.middleware.use OmniAuth::Builder do
 | 
					Rails.application.config.middleware.use OmniAuth::Builder do
 | 
				
			||||||
  provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET']
 | 
					  provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET']
 | 
				
			||||||
  provider :google_oauth2, ENV['GOOGLE_OAUTH2_ID'], ENV['GOOGLE_OAUTH2_SECRET'],
 | 
					  provider :google_oauth2, ENV['GOOGLE_OAUTH2_ID'], ENV['GOOGLE_OAUTH2_SECRET'],
 | 
				
			||||||
    scope: ['profile', 'email'], access_type: 'online', name: 'google'
 | 
					    scope: ['profile', 'email', 'youtube', 'youtube.upload'], access_type: 'online', name: 'google'
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								config/initializers/youtube.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								config/initializers/youtube.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2016 BigBlueButton Inc. and by respective authors (see below).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This program is free software; you can redistribute it and/or modify it under the
 | 
				
			||||||
 | 
					# terms of the GNU Lesser General Public License as published by the Free Software
 | 
				
			||||||
 | 
					# Foundation; either version 3.0 of the License, or (at your option) any later
 | 
				
			||||||
 | 
					# version.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
 | 
				
			||||||
 | 
					# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 | 
				
			||||||
 | 
					# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# You should have received a copy of the GNU Lesser General Public License along
 | 
				
			||||||
 | 
					# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Yt.configure do |config|
 | 
				
			||||||
 | 
					  config.log_level = :debug
 | 
				
			||||||
 | 
					  config.client_id = ENV['GOOGLE_OAUTH2_ID']
 | 
				
			||||||
 | 
					  config.client_secret = ENV['GOOGLE_OAUTH2_SECRET']
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -47,8 +47,11 @@ en-US:
 | 
				
			|||||||
  client:
 | 
					  client:
 | 
				
			||||||
    are_you_sure: Are you sure?
 | 
					    are_you_sure: Are you sure?
 | 
				
			||||||
    change_visibility: Change visibility
 | 
					    change_visibility: Change visibility
 | 
				
			||||||
    delete_recording: Delete recording
 | 
					    delete_recording: Delete
 | 
				
			||||||
 | 
					    email_footer_1: This e-mail is auto-generated by your friendly neighbourhood BigBlueButton server. Do no reply to this e-mail.
 | 
				
			||||||
 | 
					    email_footer_2: BigBlueButton is an open source web conferencing system. For more information on BigBlueButton and it's amazing capabilities, see https://bigbluebutton.org/ .
 | 
				
			||||||
    enter_name: Enter a name to join
 | 
					    enter_name: Enter a name to join
 | 
				
			||||||
 | 
					    mail_recording: Mail
 | 
				
			||||||
    meeting_ended: Meeting was ended
 | 
					    meeting_ended: Meeting was ended
 | 
				
			||||||
    meeting_started: Meeting was started
 | 
					    meeting_started: Meeting was started
 | 
				
			||||||
    no_recordings: No Recordings
 | 
					    no_recordings: No Recordings
 | 
				
			||||||
@@ -59,13 +62,18 @@ en-US:
 | 
				
			|||||||
    recording_created: A recording was created
 | 
					    recording_created: A recording was created
 | 
				
			||||||
    recording_deleted: Recording was deleted
 | 
					    recording_deleted: Recording was deleted
 | 
				
			||||||
    recording_published: Recording was published
 | 
					    recording_published: Recording was published
 | 
				
			||||||
 | 
					    recording_mail_subject: " has invited you to view a recording."
 | 
				
			||||||
 | 
					    recording_mail_body: "To view the recording, follow the link below:"
 | 
				
			||||||
    recording_unlisted: Recording was unlisted
 | 
					    recording_unlisted: Recording was unlisted
 | 
				
			||||||
    recording_unpublished: Recording was unpublished
 | 
					    recording_unpublished: Recording was unpublished
 | 
				
			||||||
 | 
					    share: Share
 | 
				
			||||||
    unpublish_recording: Hide recording
 | 
					    unpublish_recording: Hide recording
 | 
				
			||||||
    unlisted: Unlisted
 | 
					    unlisted: Unlisted
 | 
				
			||||||
    unpublished: No one
 | 
					    unpublished: No one
 | 
				
			||||||
 | 
					    upload_youtube: Youtube
 | 
				
			||||||
    user_waiting_body: "%{user} is waiting to join %{meeting}!"
 | 
					    user_waiting_body: "%{user} is waiting to join %{meeting}!"
 | 
				
			||||||
    user_waiting_title: A user is waiting
 | 
					    user_waiting_title: A user is waiting
 | 
				
			||||||
 | 
					    youtube_disabled: Recording did not contain any video.
 | 
				
			||||||
  copied: Copied
 | 
					  copied: Copied
 | 
				
			||||||
  copy_error: Use Ctrl-c to copy
 | 
					  copy_error: Use Ctrl-c to copy
 | 
				
			||||||
  create_your_session: Create your own meeting
 | 
					  create_your_session: Create your own meeting
 | 
				
			||||||
@@ -156,11 +164,18 @@ en-US:
 | 
				
			|||||||
      phrase1: This is a test email sent to %{email}
 | 
					      phrase1: This is a test email sent to %{email}
 | 
				
			||||||
  thumbnails: Thumbnails
 | 
					  thumbnails: Thumbnails
 | 
				
			||||||
  upload: Upload
 | 
					  upload: Upload
 | 
				
			||||||
 | 
					  upload_to_youtube: Upload to Youtube
 | 
				
			||||||
  url_copy_explanation: Copy this URL to invite others to the meeting
 | 
					  url_copy_explanation: Copy this URL to invite others to the meeting
 | 
				
			||||||
  user_person_room: "%{name} personal room"
 | 
					  user_person_room: "%{name} personal room"
 | 
				
			||||||
  video: Video
 | 
					  video: Video
 | 
				
			||||||
 | 
					  video_title: Video title
 | 
				
			||||||
  visibility: Visibility
 | 
					  visibility: Visibility
 | 
				
			||||||
  wait_for_mod_msg: Looks like you're the first one here...
 | 
					  wait_for_mod_msg: Looks like you're the first one here...
 | 
				
			||||||
  wait_for_mod_explanation: You will automatically join when the meeting starts
 | 
					  wait_for_mod_explanation: You will automatically join when the meeting starts
 | 
				
			||||||
  watch: Watch
 | 
					  watch: Watch
 | 
				
			||||||
  'yes': 'Yes'
 | 
					  'yes': 'Yes'
 | 
				
			||||||
 | 
					  youtube_description: This recording was recorded with BigBlueButton. For more information check out %{url}.
 | 
				
			||||||
 | 
					  youtube_privacy_options:
 | 
				
			||||||
 | 
					    public: Public
 | 
				
			||||||
 | 
					    private: Private
 | 
				
			||||||
 | 
					    unlisted: Unlisted
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,8 @@ Rails.application.routes.draw do
 | 
				
			|||||||
    scope '/:room_id', :constraints => {:room_id => disallow_slash} do
 | 
					    scope '/:room_id', :constraints => {:room_id => disallow_slash} do
 | 
				
			||||||
      # recording routes for updating, deleting and viewing recordings
 | 
					      # recording routes for updating, deleting and viewing recordings
 | 
				
			||||||
      get '/(:id)/recordings', to: 'bbb#recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
					      get '/(:id)/recordings', to: 'bbb#recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
				
			||||||
 | 
					      get '/(:id)/recordings/can_upload', to: 'bbb#can_upload', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
				
			||||||
 | 
					      post '/(:id)/recordings/:record_id', to: 'bbb#youtube_publish', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
				
			||||||
      patch '/(:id)/recordings/:record_id', to: 'bbb#update_recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
					      patch '/(:id)/recordings/:record_id', to: 'bbb#update_recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
				
			||||||
      delete '/(:id)/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
					      delete '/(:id)/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {id: nil, format: 'json'}, :constraints => {:id => disallow_slash}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								db/migrate/20170518190442_add_token_to_users.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								db/migrate/20170518190442_add_token_to_users.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					class AddTokenToUsers < ActiveRecord::Migration[5.0]
 | 
				
			||||||
 | 
					  def change
 | 
				
			||||||
 | 
					    add_column :users, :token, :string
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema.define(version: 20170510175654) do
 | 
					ActiveRecord::Schema.define(version: 20170518190442) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  create_table "users", force: :cascade do |t|
 | 
					  create_table "users", force: :cascade do |t|
 | 
				
			||||||
    t.string   "provider",                null: false
 | 
					    t.string   "provider",                null: false
 | 
				
			||||||
@@ -25,6 +25,7 @@ ActiveRecord::Schema.define(version: 20170510175654) do
 | 
				
			|||||||
    t.string   "background_content_type"
 | 
					    t.string   "background_content_type"
 | 
				
			||||||
    t.integer  "background_file_size"
 | 
					    t.integer  "background_file_size"
 | 
				
			||||||
    t.datetime "background_updated_at"
 | 
					    t.datetime "background_updated_at"
 | 
				
			||||||
 | 
					    t.string   "token"
 | 
				
			||||||
    t.index ["email"], name: "index_users_on_email", unique: true
 | 
					    t.index ["email"], name: "index_users_on_email", unique: true
 | 
				
			||||||
    t.index ["encrypted_id"], name: "index_users_on_encrypted_id", unique: true
 | 
					    t.index ["encrypted_id"], name: "index_users_on_encrypted_id", unique: true
 | 
				
			||||||
    t.index ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true
 | 
					    t.index ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user