Compare commits

...

3 Commits

Author SHA1 Message Date
Bilal
1d29f14953 add conference options to the broadcasts; implement auth to microsoft 2020-08-20 13:09:10 +03:00
Bilal
4b5238435a structure 2020-08-20 12:01:41 +03:00
Senad Uka
41bf88e358 Upstream sync 2020-08-20 06:50:51 +02:00
143 changed files with 1906 additions and 622 deletions

View File

@@ -29,3 +29,13 @@ MUX_TEST_MODE_DISABLED=
# Required for creating user through API # Required for creating user through API
CUSTOM_API_TOKEN= CUSTOM_API_TOKEN=
# Required for simulcasting to Millicast for director mode
MILLICAST_API_SECRET=
MILLICAST_ACCOUNT_ID=
# Required for Microsoft Azure AD Auth
AZURE_CLIENT_ID = Client App ID
AZURE_CLIENT_SECRET = Client App Secret
AZURE_TENANT_ID = Client App Tenant ID
AZURE_REDIRECT_URI = where microsoft will redirect after login, eg. http://localhost:3000/auth/azure_ad/callback
AZURE_SCOPES = Scopes required for Application, eg. 'openid email profile User.Read offline_access OnlineMeetings.ReadWrite'

View File

@@ -139,6 +139,11 @@ gem 'rack-cors'
# Ruby wrappers for the HubSpot REST API # Ruby wrappers for the HubSpot REST API
gem "hubspot-ruby" gem "hubspot-ruby"
# OAuth
gem 'omniauth-oauth2', '~> 1.6'
# OmniAuth CSRF protection
gem 'omniauth-rails_csrf_protection', '~> 0.1.2'
group :development, :test, :review do group :development, :test, :review do
# Call "byebug" anywhere in the code to stop execution and get a debugger console # Call "byebug" anywhere in the code to stop execution and get a debugger console
gem "byebug", "~> 11.0.1", platforms: [:mri, :mingw, :x64_mingw] gem "byebug", "~> 11.0.1", platforms: [:mri, :mingw, :x64_mingw]

View File

@@ -220,6 +220,7 @@ GEM
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
hashdiff (1.0.1) hashdiff (1.0.1)
hashery (2.1.2) hashery (2.1.2)
hashie (4.1.0)
hexapdf (0.9.3) hexapdf (0.9.3)
cmdparse (~> 3.0, >= 3.0.3) cmdparse (~> 3.0, >= 3.0.3)
geom2d (~> 0.2) geom2d (~> 0.2)
@@ -297,6 +298,7 @@ GEM
money (~> 6.13.2) money (~> 6.13.2)
railties (>= 3.0) railties (>= 3.0)
msgpack (1.3.1) msgpack (1.3.1)
multi_json (1.15.0)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.1.1) multipart-post (2.1.1)
nio4r (2.5.2) nio4r (2.5.2)
@@ -308,6 +310,21 @@ GEM
warden warden
oath-generators (1.0.1) oath-generators (1.0.1)
oath (>= 0.0.12) oath (>= 0.0.12)
oauth2 (1.4.4)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
omniauth (~> 1.9)
omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2)
omniauth (>= 1.3.1)
parallel (1.19.1) parallel (1.19.1)
parity (3.2.0) parity (3.2.0)
parser (2.6.5.0) parser (2.6.5.0)
@@ -552,6 +569,8 @@ DEPENDENCIES
mux_ruby! mux_ruby!
oath (~> 1.1.0) oath (~> 1.1.0)
oath-generators (~> 1.0.1) oath-generators (~> 1.0.1)
omniauth-oauth2 (~> 1.6)
omniauth-rails_csrf_protection (~> 0.1.2)
parity (~> 3.2.0) parity (~> 3.2.0)
pdf-reader (~> 2.1.0) pdf-reader (~> 2.1.0)
pdfkit (~> 0.8.2) pdfkit (~> 0.8.2)

View File

@@ -18,7 +18,6 @@ class AcquiredMediaReleasesController < ApplicationController
@acquired_media_release = build_acquired_media_release(acquired_media_release_params) @acquired_media_release = build_acquired_media_release(acquired_media_release_params)
if @acquired_media_release.save if @acquired_media_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@acquired_media_release) SetTagsForReleasableJob.perform_later(@acquired_media_release)
redirect_to [@project, :acquired_media_releases], notice: t(".notice") redirect_to [@project, :acquired_media_releases], notice: t(".notice")
else else
@@ -119,11 +118,8 @@ class AcquiredMediaReleasesController < ApplicationController
:term_id, :term_text, :term_id, :term_text,
:restriction_id, :restriction_text, :restriction_id, :restriction_text,
categories: [], categories: [],
file_infos_attributes: %i[ files: []
filename )
content_type
byte_size
])
end end
def build_acquired_media_release(attrs = {}) def build_acquired_media_release(attrs = {})
@@ -139,8 +135,4 @@ class AcquiredMediaReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AcquiredMediaRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -19,6 +19,11 @@ class Admin::BroadcastsController < Admin::ApplicationController
end end
def broadcast_update_params def broadcast_update_params
params.require(:broadcast).permit(:stream_url_override, :stream_key_override, :director_mode_video_embed) params.require(:broadcast).permit(
:video_conference_url_override,
:stream_url_override,
:stream_key_override,
:director_mode_video_embed
)
end end
end end

View File

@@ -21,7 +21,6 @@ class Api::ReleasesController < Api::ApiController
release.contract_template_id = @contract_template.id release.contract_template_id = @contract_template.id
handle_attachments(release, release_create_params[:photos]) handle_attachments(release, release_create_params[:photos])
release.save!(context: :native) release.save!(context: :native)
log_create_analytics
after_create(release) after_create(release)
handle_response(release, :created) handle_response(release, :created)
end end
@@ -181,8 +180,4 @@ class Api::ReleasesController < Api::ApiController
parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature) parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature)
parameters parameters
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_native_release, release_type: model_constant.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip, application: :ios)
end
end end

View File

@@ -18,7 +18,6 @@ class AppearanceReleasesController < ApplicationController
@appearance_release = build_appearance_release(appearance_release_params) @appearance_release = build_appearance_release(appearance_release_params)
if @appearance_release.save(context: :non_native) if @appearance_release.save(context: :non_native)
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project) AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@appearance_release) SetTagsForReleasableJob.perform_later(@appearance_release)
redirect_to [@project, :appearance_releases], notice: "The release has been imported. #{link_to_import_another}" redirect_to [@project, :appearance_releases], notice: "The release has been imported. #{link_to_import_another}"
@@ -127,8 +126,4 @@ class AppearanceReleasesController < ApplicationController
def link_to_import_another def link_to_import_another
view_context.link_to "Import Another", [:new, @project, :appearance_release] view_context.link_to "Import Another", [:new, @project, :appearance_release]
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -23,10 +23,13 @@ class BroadcastsController < ApplicationController
else else
render :new render :new
end end
rescue MuxRuby::ApiError, ActiveResource::ConnectionError => e
Raven.capture_exception(e)
redirect_to [@project, :broadcasts], alert: t(".alert")
end end
def show def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting] @conference_url = conference_url_for(@broadcast)
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application' render layout: 'application'
@@ -72,7 +75,7 @@ class BroadcastsController < ApplicationController
end end
def broadcast_params def broadcast_params
params.require(:broadcast).permit(:name, :shoot_location_time_zone, files: []) params.require(:broadcast).permit(:name, :shoot_location_time_zone, :conference_option, files: [])
end end
def set_project def set_project
@@ -109,6 +112,10 @@ class BroadcastsController < ApplicationController
results results
end end
def conference_url_for(broadcast)
broadcast.video_conference_url_override || url_for([broadcast.project, broadcast, :conference_meeting])
end
def log_create_analytics def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_live_stream, user_agent: request.user_agent, user_ip: request.remote_ip) TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_live_stream, user_agent: request.user_agent, user_ip: request.remote_ip)
end end

View File

@@ -0,0 +1,22 @@
class CallbacksController < ApplicationController
skip_before_action :require_login
skip_after_action :verify_authorized, except: :index
skip_after_action :verify_policy_scoped, only: :index
skip_before_action :verify_authenticity_token
def create
uid = request.env['omniauth.auth'][:uid]
token_data = request.env['omniauth.auth'][:credentials]
current_user&.tap do |user|
user.microsoft_user_id = uid
user.microsoft_access_token = token_data.token
user.microsoft_refresh_token = token_data.refresh_token
user.microsoft_token_expires_at = token_data.expires_at # Expiration time is returned in seconds
user.save
end
redirect_to profile_path
end
end

View File

@@ -0,0 +1,45 @@
class ConferenceMeetingsController < ApplicationController
require 'microsoft_graph'
def show
authorize broadcast = Broadcast.find(params[:broadcast_id])
case broadcast.conference_option
when 'zoom'
redirect_to broadcast.zoom_meeting_url
when 'ms_teams'
if broadcast.conference_join_url.nil?
begin
graph_api = MicrosoftGraph.new(
current_user,
ENV['AZURE_CLIENT_ID'],
ENV['AZURE_CLIENT_SECRET'],
ENV['AZURE_TENANT_ID'],
ENV['AZURE_SCOPES']
)
subject = "#{broadcast.name} Online Meeting"
teams_meeting = graph_api.create_teams_meeting(subject)
join_url = teams_meeting['joinUrl']
if join_url.present?
broadcast.conference_join_url = join_url
broadcast.save
else
raise StandardError, 'Failed to read teams meeting join URL'
end
rescue ActionController::InvalidAuthenticityToken => e
Rails.logger.error(e.message)
redirect_to project_broadcast_url(broadcast.project, broadcast), alert: t('.alerts.not_authenticated')
return
rescue StandardError => e
Rails.logger.error(e.message)
redirect_to project_broadcast_url(broadcast.project, broadcast), alert: t('.alerts.failed_to_join')
return
end
end
redirect_to broadcast.conference_join_url
else
redirect_to project_broadcast_url(broadcast.project, broadcast), alert: t('.alerts.unknown_conference_option')
end
end
end

View File

@@ -26,6 +26,7 @@ class ContractTemplatesController < ApplicationController
contract = Contract.new releasable_instance, true contract = Contract.new releasable_instance, true
send_file contract.to_pdf, download_attributes send_file contract.to_pdf, download_attributes
elsif @contract_template.save elsif @contract_template.save
log_create_analytics
redirect_to [@project, :contract_templates], notice: t('.notice') redirect_to [@project, :contract_templates], notice: t('.notice')
else else
@release_type = contract_template_params[:release_type] @release_type = contract_template_params[:release_type]
@@ -94,7 +95,9 @@ class ContractTemplatesController < ApplicationController
:question_9_text, :question_10_text, :question_9_text, :question_10_text,
:question_11_text, :question_12_text, :question_11_text, :question_12_text,
:question_13_text, :question_14_text, :question_13_text, :question_14_text,
:question_15_text) :question_15_text, :questionnaire_legal_text,
:exhibit_a_legal_text, :exhibit_a_question_text,
:exhibit_b_legal_text, :exhibit_b_question_text)
end end
def download_attributes def download_attributes
@@ -104,4 +107,8 @@ class ContractTemplatesController < ApplicationController
type: 'application/pdf' type: 'application/pdf'
} }
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_contract_template, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -1,4 +1,4 @@
class FileInfosController < ApplicationController class FilesController < ApplicationController
before_action :set_releasable before_action :set_releasable
layout "project" layout "project"
@@ -16,7 +16,7 @@ class FileInfosController < ApplicationController
if @releasable.update(releasable_params) if @releasable.update(releasable_params)
SetTagsForReleasableJob.perform_later(@releasable) SetTagsForReleasableJob.perform_later(@releasable)
redirect_to [@project, @releasable.model_name.plural], notice: t(".notice") redirect_to [@project, @releasable.model_name.plural], notice: "Files added successfully to the release."
else else
render :edit render :edit
end end
@@ -29,16 +29,10 @@ class FileInfosController < ApplicationController
end end
def set_releasable def set_releasable
@releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :"#{action_name}_file_infos?" @releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :edit_files?
end end
def releasable_params def releasable_params
params.fetch(releasable_param.name, {}).permit( params.fetch(releasable_param.name, {}).permit(files: [])
file_infos_attributes: [
:filename,
:content_type,
:byte_size
],
)
end end
end end

View File

@@ -18,7 +18,6 @@ class LocationReleasesController < ApplicationController
@location_release = build_location_release(location_release_params) @location_release = build_location_release(location_release_params)
if @location_release.save if @location_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@location_release) SetTagsForReleasableJob.perform_later(@location_release)
redirect_to [@project, :location_releases], notice: t(".notice") redirect_to [@project, :location_releases], notice: t(".notice")
else else
@@ -90,8 +89,4 @@ class LocationReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: LocationRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -18,7 +18,6 @@ class MaterialReleasesController < ApplicationController
@material_release = build_material_release(material_release_params) @material_release = build_material_release(material_release_params)
if @material_release.save if @material_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@material_release) SetTagsForReleasableJob.perform_later(@material_release)
redirect_to [@project, :material_releases], notice: t(".notice") redirect_to [@project, :material_releases], notice: t(".notice")
else else
@@ -136,8 +135,4 @@ class MaterialReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MaterialRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -22,7 +22,6 @@ class MusicReleasesController < ApplicationController
@music_release = build_music_release(music_release_params) @music_release = build_music_release(music_release_params)
if @music_release.save if @music_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@music_release) SetTagsForReleasableJob.perform_later(@music_release)
redirect_to [@project, :music_releases], notice: t(".notice") redirect_to [@project, :music_releases], notice: t(".notice")
else else
@@ -111,8 +110,4 @@ class MusicReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MusicRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -6,7 +6,7 @@ class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy] before_action :set_project, only: [:show, :edit, :update, :destroy]
def index def index
@projects = policy_scope(Current.account.projects).order_by_name @projects = filtered_projects.order_by_name
end end
def new def new
@@ -46,6 +46,20 @@ class ProjectsController < ApplicationController
private private
def filtered_projects
results = projects
if params[:query].present?
results = results.search(params[:query])
end
results
end
def projects
authorize policy_scope(Current.account.projects)
end
def set_project def set_project
@project = authorize projects.find(params[:id]) @project = authorize projects.find(params[:id])
end end

View File

@@ -10,7 +10,6 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
@acquired_media_release = build_acquired_media_release(acquired_media_release_params_with_locale_and_contract_template) @acquired_media_release = build_acquired_media_release(acquired_media_release_params_with_locale_and_contract_template)
if @acquired_media_release.save(context: :native) if @acquired_media_release.save(context: :native)
log_create_analytics
after_create(@acquired_media_release) after_create(@acquired_media_release)
else else
render :new render :new
@@ -100,11 +99,8 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
:signature_base64, :signature_base64,
:locale, :contract_template, :locale, :contract_template,
categories: [], categories: [],
file_infos_attributes: %i[ files: []
filename )
content_type
byte_size
])
end end
def acquired_media_release_params_with_locale def acquired_media_release_params_with_locale
@@ -114,8 +110,4 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
def acquired_media_release_params_with_locale_and_contract_template def acquired_media_release_params_with_locale_and_contract_template
acquired_media_release_params_with_locale.merge(contract_template: @contract_template) acquired_media_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AcquiredMediaRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::AppearanceReleasesController < Public::BaseController
@appearance_release = build_appearance_release(appearance_release_params_with_locale_and_contract_template) @appearance_release = build_appearance_release(appearance_release_params_with_locale_and_contract_template)
if @appearance_release.save(context: :native) if @appearance_release.save(context: :native)
log_create_analytics
after_create(@appearance_release) after_create(@appearance_release)
else else
render :new render :new
@@ -87,12 +86,35 @@ class Public::AppearanceReleasesController < Public::BaseController
] ]
end end
def questionnaire_params
[
:question_1_answer,
:question_2_answer,
:question_3_answer,
:question_4_answer,
:question_5_answer,
:question_6_answer,
:question_7_answer,
:question_8_answer,
:question_9_answer,
:question_10_answer,
:question_11_answer,
:question_12_answer,
:question_13_answer,
:question_14_answer,
:question_15_answer,
]
end
def appearance_release_params def appearance_release_params
params.require(:appearance_release).permit(person_params, guardian_params, params.require(:appearance_release).permit(person_params, guardian_params,
second_guardian_params, second_guardian_params,
questionnaire_params,
:minor, :signature_base64, :minor, :signature_base64,
:person_date_of_birth, :person_date_of_birth,
:locale, :contract_template) :locale, :contract_template,
:exhibit_a_answer, :exhibit_b_answer
)
end end
def appearance_release_params_with_locale def appearance_release_params_with_locale
@@ -102,8 +124,4 @@ class Public::AppearanceReleasesController < Public::BaseController
def appearance_release_params_with_locale_and_contract_template def appearance_release_params_with_locale_and_contract_template
appearance_release_params_with_locale.merge(contract_template: @contract_template) appearance_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AppearanceRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -3,7 +3,7 @@ class Public::BroadcastsController < Public::BaseController
before_action :set_broadcast, only: [:show, :update] before_action :set_broadcast, only: [:show, :update]
def show def show
@conference_url = broadcast_zoom_meeting_url(@broadcast.token) @conference_url = conference_url_for(@broadcast)
@multi_view_broadcasts = multi_view_broadcasts @multi_view_broadcasts = multi_view_broadcasts
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
@@ -43,6 +43,10 @@ class Public::BroadcastsController < Public::BaseController
end end
end end
def conference_url_for(broadcast)
broadcast.video_conference_url_override || broadcast_zoom_meeting_url(broadcast.token)
end
class MultiViewBroadcast class MultiViewBroadcast
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers

View File

@@ -10,7 +10,6 @@ class Public::LocationReleasesController < Public::BaseController
@location_release = build_location_release(location_release_params_with_locale_and_contract_template) @location_release = build_location_release(location_release_params_with_locale_and_contract_template)
if @location_release.save(context: :native) if @location_release.save(context: :native)
log_create_analytics
after_create(@location_release) after_create(@location_release)
else else
render :new render :new
@@ -76,8 +75,4 @@ class Public::LocationReleasesController < Public::BaseController
def location_release_params_with_locale_and_contract_template def location_release_params_with_locale_and_contract_template
location_release_params_with_locale.merge(contract_template: @contract_template) location_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: LocationRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::MaterialReleasesController < Public::BaseController
@material_release = build_material_release(material_release_params_with_locale_and_contract_template) @material_release = build_material_release(material_release_params_with_locale_and_contract_template)
if @material_release.save(context: :native) if @material_release.save(context: :native)
log_create_analytics
after_create(@material_release) after_create(@material_release)
else else
render :new render :new
@@ -104,8 +103,4 @@ class Public::MaterialReleasesController < Public::BaseController
def material_release_params_with_locale_and_contract_template def material_release_params_with_locale_and_contract_template
material_release_params_with_locale.merge(contract_template: @contract_template) material_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MaterialRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -12,7 +12,6 @@ class Public::MedicalReleasesController < Public::BaseController
if @medical_release.contract_template.present? if @medical_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@medical_release) AttachContractToReleasableJob.perform_later(@medical_release)
end end
log_create_analytics
else else
render :new render :new
end end
@@ -116,8 +115,4 @@ class Public::MedicalReleasesController < Public::BaseController
def medical_release_params_with_locale_and_contract_template def medical_release_params_with_locale_and_contract_template
medical_release_params_with_locale.merge(contract_template: @contract_template) medical_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MedicalRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -12,7 +12,6 @@ class Public::MiscReleasesController < Public::BaseController
if @misc_release.contract_template.present? if @misc_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@misc_release) AttachContractToReleasableJob.perform_later(@misc_release)
end end
log_create_analytics
else else
render :new render :new
end end
@@ -50,6 +49,14 @@ class Public::MiscReleasesController < Public::BaseController
:signature_base64, :signature_base64,
:locale, :locale,
:contract_template, :contract_template,
:applicable_medium_id,
:applicable_medium_text,
:territory_id,
:territory_text,
:term_id,
:term_text,
:restriction_id,
:restriction_text,
photos: [], photos: [],
) )
end end
@@ -113,8 +120,4 @@ class Public::MiscReleasesController < Public::BaseController
def misc_release_params_with_locale_and_contract_template def misc_release_params_with_locale_and_contract_template
misc_release_params_with_locale.merge(contract_template: @contract_template) misc_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MiscRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::TalentReleasesController < Public::BaseController
@talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template) @talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template)
if @talent_release.save(context: :native) if @talent_release.save(context: :native)
log_create_analytics
after_create(@talent_release) after_create(@talent_release)
else else
render :new render :new
@@ -108,8 +107,4 @@ class Public::TalentReleasesController < Public::BaseController
def talent_release_params_with_locale_and_contract_template def talent_release_params_with_locale_and_contract_template
talent_release_params_with_locale.merge(contract_template: @contract_template) talent_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: TalentRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -18,7 +18,6 @@ class TalentReleasesController < ApplicationController
@talent_release = build_talent_release(talent_release_params) @talent_release = build_talent_release(talent_release_params)
if @talent_release.save if @talent_release.save
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project) AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@talent_release) SetTagsForReleasableJob.perform_later(@talent_release)
redirect_to [@project, :talent_releases], notice: t(".notice") redirect_to [@project, :talent_releases], notice: t(".notice")
@@ -137,8 +136,4 @@ class TalentReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: TalentRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -1,6 +0,0 @@
class ZoomMeetingsController < ApplicationController
def show
authorize broadcast = Broadcast.find(params[:broadcast_id])
redirect_to broadcast.zoom_meeting_url
end
end

View File

@@ -0,0 +1,17 @@
module BroadcastConferencesHelper
def options_for_conference_select
[
['Zoom', 'zoom'],
['MS Teams', 'ms_teams']
]
end
def conference_option_name_from_key(key)
option = options_for_conference_select.find { |option| option[1] == key }
if option.present?
option.first
else
'Unknown conference option'
end
end
end

View File

@@ -6,6 +6,6 @@ module MailHelper
"1. Tell us the name of the video: \n\n" \ "1. Tell us the name of the video: \n\n" \
"2. Attach each EDL to this email. Please make sure to indicate whether the EDL is a Video Only, Graphics Only, or Audio Only EDL." "2. Attach each EDL to this email. Please make sure to indicate whether the EDL is a Video Only, Graphics Only, or Audio Only EDL."
mail_to "info@bigmedia.ai", content, subject: subject, body: body mail_to "info@mesuite.ai", content, subject: subject, body: body
end end
end end

View File

@@ -67,6 +67,23 @@ class ActiveStorageDropzone {
var upload = new that.UploaderClass(file, url, delegate); var upload = new that.UploaderClass(file, url, delegate);
createUpload(this, upload); createUpload(this, upload);
}); });
this.on("addedfile", function(file) {
// Show download link in dropzone previews
let div = document.createElement("div");
let anchor = document.createElement("a");
let download_icon = "<i class='fa fa-download' aria-hidden='true'></i> Download";
anchor.innerHTML = download_icon;
anchor.href = file.dataURL;
anchor.setAttribute('target', '_blank');
anchor.setAttribute('style', 'background-color: rgba(255, 255, 255, 0.4); padding: 0 0.4em; border: 1px solid transparent; text-decoration: none;');
div.append(anchor);
div.setAttribute('class', 'dz-download-link')
div.setAttribute('style', 'margin-top: 1em;')
$(file.previewElement.childNodes[3]).append(div);
});
}, },
}); });

View File

@@ -1,5 +1,5 @@
class AdminMailer < ApplicationMailer class AdminMailer < ApplicationMailer
default to: %w(bray@bigmedia.ai lee@bigmedia.ai) default to: %w[bray@mesuite.ai]
def new_video(video) def new_video(video)
@video = video @video = video

View File

@@ -1,4 +1,4 @@
class ApplicationMailer < ActionMailer::Base class ApplicationMailer < ActionMailer::Base
default from: ENV.fetch("MAILER_FROM_ADDRESS") { "support@bigmedia.ai" } default from: ENV.fetch("MAILER_FROM_ADDRESS") { "support@mesuite.ai" }
layout "mailer" layout "mailer"
end end

View File

@@ -18,13 +18,14 @@ class AcquiredMediaRelease < ApplicationRecord
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name file_infos_count] %i[name files_count owner_info]
end end
end end
# This association needs to be removed after changing the API. Removing it right now will cause failure in API specs.
has_many :file_infos, as: :releasable, dependent: :destroy has_many :file_infos, as: :releasable, dependent: :destroy
accepts_nested_attributes_for :file_infos has_many_attached :files
composed_of :person_address, composed_of :person_address,
class_name: "Address", class_name: "Address",
@@ -102,7 +103,19 @@ class AcquiredMediaRelease < ApplicationRecord
true true
end end
def file_infos_count def files_count
file_infos.any? ? file_infos.size : I18n.t('acquired_media_releases.acquired_media_release.no_media') files.any? ? files.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
end
def image_files
files_blobs.where("content_type ILIKE ?", "%image%")
end
def video_files
files_blobs.where("content_type ILIKE ?", "%video%")
end
def other_files
files_blobs.where("NOT content_type ILIKE ANY (array[?])", ["%image%", "%video%"])
end end
end end

View File

@@ -40,7 +40,7 @@ class AppHost
use_ssl: false, use_ssl: false,
}, },
production: { production: {
host: "bigmedia.ai", host: "mesuite.ai",
use_ssl: true, use_ssl: true,
} }
} }

View File

@@ -17,6 +17,9 @@ class AppearanceRelease < ApplicationRecord
include SecondGuardianName include SecondGuardianName
include CsvExportable include CsvExportable
include Approvable include Approvable
include Amendmenable
NUMBER_OF_CUSTOM_FIELDS = 15
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers

View File

@@ -49,11 +49,13 @@ class Broadcast < ApplicationRecord
private private
def create_mux_live_stream def create_mux_live_stream
stream = MuxLiveStream.new stream = MuxLiveStream.create_with_simulcast
self.stream_uid = stream.id self.stream_uid = stream.id
self.stream_key = stream.key self.stream_key = stream.key
self.stream_playback_uid = stream.playback_id self.stream_playback_uid = stream.playback_id
self.simulcast_uid = stream.simulcast_id
self.director_mode_video_embed ||= stream.simulcast_destination.try(:playback_embed)
self.save! self.save!
end end

View File

@@ -3,8 +3,8 @@
module CsvExportable module CsvExportable
extend ActiveSupport::Concern extend ActiveSupport::Concern
COMMON_HEADERS = %i[approved? notes tags signed_at].freeze COMMON_HEADERS = %i[approved notes tags signed_at].freeze
COMMON_VALUES = %w[clean_notes clean_tags signed_on].freeze COMMON_VALUES = %w[approved? clean_notes clean_tags signed_on].freeze
included do included do
class << self class << self
@@ -29,11 +29,20 @@ module CsvExportable
private private
def owner_info
compact_contact_info(name: person_name, address: person_address, phone: person_phone, email: person_email)
end
def contact_info def contact_info
owner_info
end
def compact_contact_info(name: nil, address: nil, phone: nil, email: nil)
contact_info = '' contact_info = ''
contact_info += "#{person_address}; " if person_address.present? contact_info += "#{name}; " if name.present?
contact_info += "P: #{person_phone}; " if person_phone.present? contact_info += "#{address}; " if address.present?
contact_info += "E: #{person_email}" if person_email.present? contact_info += "P: #{phone}; " if phone.present?
contact_info += "E: #{email}" if email.present?
contact_info.delete_suffix '; ' contact_info.delete_suffix '; '
end end

View File

@@ -23,6 +23,9 @@ class ContractTemplate < ApplicationRecord
has_rich_text :guardian_clause has_rich_text :guardian_clause
has_rich_text :signature_legal_text has_rich_text :signature_legal_text
has_rich_text :amendment_clause has_rich_text :amendment_clause
has_rich_text :exhibit_a_legal_text
has_rich_text :exhibit_b_legal_text
has_rich_text :questionnaire_legal_text
validates :name, presence: true validates :name, presence: true
validates :release_type, presence: true validates :release_type, presence: true
@@ -70,6 +73,14 @@ class ContractTemplate < ApplicationRecord
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence } (1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
end end
def has_exhibit_a?
exhibit_a_legal_text.present?
end
def has_exhibit_b?
exhibit_b_legal_text.present?
end
def editable? def editable?
releases.size.zero? releases.size.zero?
end end

View File

@@ -16,7 +16,7 @@ class LocationRelease < ApplicationRecord
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name address] %i[location_info owner_info amendment_signed_column]
end end
end end
@@ -67,6 +67,18 @@ class LocationRelease < ApplicationRecord
true true
end end
def location_info
compact_contact_info(name: name, address: address)
end
def amendment_signed_column
if amendment_signable?
amendment_signed?
else
I18n.t('location_releases.csv.no_amendment_clause')
end
end
private private
def end_date_after_start_date def end_date_after_start_date

View File

@@ -20,7 +20,7 @@ class MaterialRelease < ApplicationRecord
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name] %i[name owner_info]
end end
end end

View File

@@ -0,0 +1,41 @@
class MillicastDestination
attr_reader :name, :token
def self.create
token_stream_name = SecureRandom.urlsafe_base64
publish_token = Millicast::PublishToken.create(
label: SecureRandom.urlsafe_base64,
streams: [
{ streamName: token_stream_name }
]
)
new(token_stream_name, publish_token.data.token)
end
def initialize(name, token)
@name = name
@token = token
end
def account_id
ENV["MILLICAST_ACCOUNT_ID"]
end
def key
"#{name}?token=#{token}"
end
def url
"rtmp://live-rtmp-pub.millicast.com:1935/v2/pub"
end
def playback_url
"https://viewer.millicast.com/v2?streamId=#{account_id}/#{name}"
end
def playback_embed
"<iframe src=\"#{playback_url}\" allowfullscreen width=\"640\" height=\"480\"></iframe>"
end
end

View File

@@ -11,6 +11,7 @@ class MiscRelease < ApplicationRecord
include GuardianPhotoable include GuardianPhotoable
include CsvExportable include CsvExportable
include Approvable include Approvable
include Exploitable
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers

View File

@@ -1,4 +1,15 @@
class MuxLiveStream class MuxLiveStream
attr_accessor :simulcast_id, :simulcast_destination
def self.create_with_simulcast(destination = nil)
destination ||= MillicastDestination.create
MuxLiveStream.new.tap do |stream|
stream.id # force the live stream to be created by calling for its id
stream.create_simulcast(destination)
end
end
def id def id
live_stream.data.id live_stream.data.id
end end
@@ -15,6 +26,15 @@ class MuxLiveStream
client.delete_live_stream(stream_uid) client.delete_live_stream(stream_uid)
end end
def create_simulcast(destination)
return if test_mode_enabled?
request = MuxRuby::CreateSimulcastTargetRequest.new(stream_key: destination.key, url: destination.url)
result = client.create_live_stream_simulcast_target(id, request)
self.simulcast_destination = destination
self.simulcast_id = result.data.id
end
private private
def live_stream def live_stream

View File

@@ -2,6 +2,7 @@ class Project < ApplicationRecord
include Archivable include Archivable
include Filterable include Filterable
include Syncable include Syncable
include PgSearch
SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical misc) SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical misc)
AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical misc) AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical misc)
@@ -42,6 +43,15 @@ class Project < ApplicationRecord
} }
end end
pg_search_scope :search, {
against: [:name],
using: {
tsearch: {any_word: true, prefix: true},
trigram: {},
dmetaphone: {any_word: true}
}
}
validates :name, presence: true, uniqueness: { scope: :account_id } validates :name, presence: true, uniqueness: { scope: :account_id }
filterable_by :active, :inactive, :archived filterable_by :active, :inactive, :archived

View File

@@ -19,11 +19,7 @@ class AcquiredMediaReleasePolicy < ApplicationPolicy
true true
end end
def edit_file_infos? def edit_files?
true
end
def update_file_infos?
true true
end end

View File

@@ -34,4 +34,8 @@ class AppearanceReleasePolicy < ReleasePolicy
def approve? def approve?
review? review?
end end
def sign_amendment?
user.manager? || user.account_manager?
end
end end

View File

@@ -16,5 +16,5 @@ class SerializableAcquiredMediaRelease < JSONAPI::Serializable::Resource
meta do meta do
{ count: @object.file_infos.size } { count: @object.file_infos.size }
end end
end end
end end

View File

@@ -169,6 +169,24 @@ class Analytics
) )
end end
end end
def track_create_contract_template(user_agent:, user_ip:)
if analytics_enabled?
identify
track(
{
user_id: user.id,
event: "Contract Template Created",
properties: {
account: account.try(:name),
account_id: account.try(:id),
user_agent: user_agent,
ip: user_ip,
},
}
)
end
end
private private

View File

@@ -12,8 +12,8 @@
<%= acquired_media_release.name %> <%= acquired_media_release.name %>
</td> </td>
<td> <td>
<% if acquired_media_release.file_infos.any? %> <% if acquired_media_release.files.any? %>
<%= acquired_media_release.file_infos.size %> <%= acquired_media_release.files.size %>
<% else %> <% else %>
<%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %> <%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %>
<% end %> <% end %>
@@ -40,8 +40,8 @@
<% if policy(acquired_media_release.tags).new? %> <% if policy(acquired_media_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, acquired_media_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, acquired_media_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %> <% end %>
<% if policy(acquired_media_release).edit_file_infos? %> <% if policy(acquired_media_release).edit_files? %>
<%= link_to fa_icon("file fw", text: "Add Media"), [:edit, acquired_media_release, :file_infos], class: "dropdown-item" %> <%= link_to fa_icon("file fw", text: "Media"), [:edit, acquired_media_release, :files], class: "dropdown-item" %>
<% end %> <% end %>
<% if policy(Contract).show? && (acquired_media_release.contract.attached? || acquired_media_release.contract_template.present?) %> <% if policy(Contract).show? && (acquired_media_release.contract.attached? || acquired_media_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [acquired_media_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <%= link_to fa_icon("download fw", text: "Download"), [acquired_media_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>

View File

@@ -44,7 +44,7 @@
<%= fa_icon "warning" %> <%= fa_icon "warning" %>
<strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong> <strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong>
</div> </div>
<%= render "shared/file_infos_dropzone", form: form, releasable: acquired_media_release %> <%= render "shared/releasable_files_dropzone", form: form, releasable: acquired_media_release %>
<div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields"> <div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<br> <br>

View File

@@ -28,7 +28,7 @@
<th data-behavior="all-selectable"><%= check_box_tag "acquired_media_release_ids[]", false, false %></th> <th data-behavior="all-selectable"><%= check_box_tag "acquired_media_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></th> <th><%= t '.table_headers.approved'%></th>
<th><%= AcquiredMediaRelease.human_attribute_name(:name) %></th> <th><%= AcquiredMediaRelease.human_attribute_name(:name) %></th>
<th><%= t(".table_headers.file_infos_count") %></th> <th><%= t(".table_headers.files_count") %></th>
<th><%= t(".table_headers.owner_info") %></th> <th><%= t(".table_headers.owner_info") %></th>
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>

View File

@@ -8,6 +8,9 @@
<td> <td>
<%= account.projects.size %> <%= account.projects.size %>
</td> </td>
<td>
<%= account.total_number_of_releases %>
</td>
<td> <td>
<%= number_with_delimiter convert_duration(account.current_month_video_duration_total, from: :seconds, to: :minutes).round %> minutes <%= number_with_delimiter convert_duration(account.current_month_video_duration_total, from: :seconds, to: :minutes).round %> minutes
</td> </td>

View File

@@ -15,6 +15,7 @@
<th>Name</th> <th>Name</th>
<th>Plan</th> <th>Plan</th>
<th># Projects</th> <th># Projects</th>
<th># Releases Signed</th>
<th>Monthly Video Upload Minutes</th> <th>Monthly Video Upload Minutes</th>
<th>Total Video Upload Minutes</th> <th>Total Video Upload Minutes</th>
<th>Total Storage</th> <th>Total Storage</th>

View File

@@ -1,6 +1,7 @@
<%= errors_summary_for broadcast %> <%= errors_summary_for broadcast %>
<%= bootstrap_form_with model: model, local: true do |form| %> <%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.text_field :video_conference_url_override %>
<%= form.text_field :stream_url_override %> <%= form.text_field :stream_url_override %>
<%= form.text_field :stream_key_override %> <%= form.text_field :stream_key_override %>
<%= form.text_area :director_mode_video_embed %> <%= form.text_area :director_mode_video_embed %>

View File

@@ -34,6 +34,17 @@
<td> <td>
<%= appearance_release.signed_on %> <%= appearance_release.signed_on %>
</td> </td>
<td class="text-center">
<% if appearance_release.amendment_signed? %>
<i class="fa fa-check-square-o text-dark"
data-toggle="tooltip"
title="<%= t '.messages.amendment_signed_tooltip' %>"></i>
<% elsif appearance_release.amendment_signable? %>
<i class="fa fa-square-o"
data-toggle="tooltip"
title="<%= t '.messages.amendment_not_signed_tooltip' %>"></i>
<% end %>
</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> <div class="btn-group">
<%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %> <%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
@@ -44,6 +55,9 @@
<% if policy(appearance_release.tags).new? %> <% if policy(appearance_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, appearance_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, appearance_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %> <% end %>
<% if policy(appearance_release).sign_amendment? && appearance_release.amendment_signable? && !appearance_release.amendment_signed? %>
<%= link_to fa_icon("file-text fw", text: t('.actions.sign_amendment')), [:new, appearance_release.project.account, appearance_release.project, appearance_release.contract_template, appearance_release, :amendment], class: "dropdown-item", target: "_blank" %>
<% end %>
<% if policy(Contract).show? && (appearance_release.contract.attached? || appearance_release.contract_template.present?) %> <% if policy(Contract).show? && (appearance_release.contract.attached? || appearance_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [appearance_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <%= link_to fa_icon("download fw", text: "Download"), [appearance_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>
<% end %> <% end %>

View File

@@ -51,6 +51,7 @@
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th> <th><%= t(".table_headers.signed_at") %></th>
<th><%= t '.table_headers.amendment_signed' %></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>

View File

@@ -2,6 +2,7 @@
<%= bootstrap_form_with model: model, local: true do |form| %> <%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.text_field :name %> <%= form.text_field :name %>
<%= form.select :conference_option, options_for_conference_select, { label: t('.labels.conference_option') }, class: "form-control custom-select" %>
<%= form.time_zone_select(:shoot_location_time_zone, nil, label: "Time zone of shoot location") %> <%= form.time_zone_select(:shoot_location_time_zone, nil, label: "Time zone of shoot location") %>
<div class="row align-items-center text-center mt-4"> <div class="row align-items-center text-center mt-4">

View File

@@ -127,8 +127,8 @@
</div> </div>
<hr> <hr>
<% end %> <% end %>
<p class="card-text">If you want to join the ZOOM meeting dedicated to this broadcast, follow the link below.</p> <p class="card-text"><%= "If you want to join the #{conference_option_name_from_key(@broadcast.conference_option)} meeting dedicated to this broadcast, follow the link below." %></p>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary btn-block', target: '_blank' %> <%= link_to 'Video Conference', @conference_url, class: "btn btn-primary btn-block", target: '_blank' %>
</div> </div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings"> <div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings">
<div id="broadcast_recordings"> <div id="broadcast_recordings">

View File

@@ -2,7 +2,7 @@
<%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %> <%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row"> <div class="form-row">
<%= form.text_field :name, wrapper_class: "col-sm-6" %> <%= form.text_field :name, wrapper_class: "col-sm-6" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(acquired_media appearance talent material misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical misc), "#amendment_clause": %w(location) } }, class: "form-control custom-select" %> <%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(acquired_media appearance talent material misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media misc), "#custom_fields": %w(medical misc appearance), "#amendment_clause": %w(appearance location), "#exhibit_fields": %w(appearance) } }, class: "form-control custom-select" %>
</div> </div>
<div class="form-row mb-3"> <div class="form-row mb-3">
<%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %> <%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %>
@@ -34,6 +34,25 @@
<%= form.rich_text_area :amendment_clause %> <%= form.rich_text_area :amendment_clause %>
<% end %> <% end %>
</div> </div>
<div id="exhibit_fields">
<%= form.form_group do %>
<%= form.rich_text_area :exhibit_a_legal_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.text_area :exhibit_a_question_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.rich_text_area :exhibit_b_legal_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.text_area :exhibit_b_question_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
</div>
<div id="signature_legal_text"> <div id="signature_legal_text">
<%= form.form_group do %> <%= form.form_group do %>
<%= form.rich_text_area :signature_legal_text %> <%= form.rich_text_area :signature_legal_text %>

View File

@@ -0,0 +1,8 @@
<p class="heading"><strong><u><%= t ".heading.#{releasable.model_name.param_key}" %></u></strong></p>
<h4>Legal</h4>
<p><%= releasable.contract_template.exhibit_a_legal_text %></p>
<% if releasable.contract_template.exhibit_a_question_text.present? %>
<h4>Question</h4>
<p><strong><%= releasable.contract_template.exhibit_a_question_text %></strong></p>
<p><%= releasable.exhibit_a_answer %></p>
<% end %>

View File

@@ -0,0 +1,8 @@
<p class="heading"><strong><u><%= t ".heading.#{releasable.model_name.param_key}" %></u></strong></p>
<h4>Legal</h4>
<p><%= releasable.contract_template.exhibit_b_legal_text %></p>
<% if releasable.contract_template.exhibit_b_question_text.present? %>
<h4>Question</h4>
<p><strong><%= releasable.contract_template.exhibit_b_question_text %></strong></p>
<p><%= releasable.exhibit_b_answer %></p>
<% end %>

View File

@@ -8,38 +8,37 @@
Description: <%= release.description %> Description: <%= release.description %>
</p> </p>
<% end %> <% end %>
<% photos = release.image_files %>
<% photos = release.file_infos.photo %>
<% unless photos.empty? %> <% unless photos.empty? %>
<h3>Photos</h3> <h3>Photos</h3>
<ul> <ul>
<% photos.each do |file_info| %> <% photos.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
<% videos = release.file_infos.video %> <% videos = release.video_files %>
<% unless videos.empty? %> <% unless videos.empty? %>
<h3>Videos</h3> <h3>Videos</h3>
<ul> <ul>
<% videos.each do |file_info| %> <% videos.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
<% other = release.file_infos.other %> <% other = release.other_files %>
<% unless other.empty? %> <% unless other.empty? %>
<h3>Other files</h3> <h3>Other files</h3>
<ul> <ul>
<% other.each do |file_info| %> <% other.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>

View File

@@ -6,3 +6,5 @@
<p><%= releasable.public_send("question_#{n}_answer") %></p> <p><%= releasable.public_send("question_#{n}_answer") %></p>
<% end %> <% end %>
<% end %> <% end %>
<%= contract_template.questionnaire_legal_text %>

View File

@@ -16,7 +16,8 @@
<%= contract_template.guardian_clause %> <%= contract_template.guardian_clause %>
<% end %> <% end %>
<% if releasable.model_name.in? %w(MedicalRelease MiscRelease) %> <%# if releasable.model_name.in? %w(MedicalRelease MiscRelease AppearanceRelease) %>
<% if releasable.respond_to?(:question_1_answer) %>
<div class="page"> <div class="page">
<%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %> <%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>
</div> </div>
@@ -30,7 +31,22 @@
<div class="page"> <div class="page">
<%= render "contracts/amendment_page", releasable: releasable, preview: preview %> <%= render "contracts/amendment_page", releasable: releasable, preview: preview %>
</div> </div>
<%end %> <% end %>
<% if releasable.respond_to?(:exhibit_a_answer) %>
<% if contract_template.has_exhibit_a? %>
<div class="page">
<%= render "contracts/exhibit_a_page", releasable: releasable, preview: preview %>
</div>
<% end %>
<% if contract_template.has_exhibit_b? %>
<div class="page">
<%= render "contracts/exhibit_b_page", releasable: releasable, preview: preview %>
</div>
<% end %>
<% end %>
<% if releasable.respond_to?(:approved?) && releasable.approved? %> <% if releasable.respond_to?(:approved?) && releasable.approved? %>
<div class="page"> <div class="page">

View File

@@ -1,7 +1,7 @@
<div class="card shadow-sm"> <div class="card shadow-sm">
<%= card_header text: t(".heading"), subtext: @releasable.name, close_action_path: [@project, @releasable.model_name.plural] %> <%= card_header text: t(".heading"), subtext: @releasable.name, close_action_path: [@project, @releasable.model_name.plural] %>
<div class="card-body"> <div class="card-body">
<% if @releasable.file_infos.any? %> <% if @releasable.files.any? %>
<div class="alert alert-info text-center text-md-left"> <div class="alert alert-info text-center text-md-left">
<%= fa_icon "info-circle" %> <%= fa_icon "info-circle" %>
<strong>To Add Photos & Videos to the release: Drag & Drop Files or Click or Tap here to browse media.</strong> <strong>To Add Photos & Videos to the release: Drag & Drop Files or Click or Tap here to browse media.</strong>
@@ -11,8 +11,8 @@
<%= fa_icon "warning" %> <%= fa_icon "warning" %>
<strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong> <strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong>
</div> </div>
<%= bootstrap_form_with model: @releasable, url: [@releasable, :file_infos] do |form| %> <%= bootstrap_form_with model: @releasable, url: [@releasable, :files] do |form| %>
<%= render "shared/file_infos_dropzone", form: form, releasable: @releasable %> <%= render "shared/releasable_files_dropzone", form: form, releasable: @releasable %>
<div class="row align-items-center text-center mt-4"> <div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [@project, @releasable.model_name.plural], class: "col-3 text-reset" %> <%= link_to t("shared.cancel"), [@project, @releasable.model_name.plural], class: "col-3 text-reset" %>

View File

@@ -17,6 +17,7 @@
<%= @user.role_for(Current.account).to_s.titleize %> <%= @user.role_for(Current.account).to_s.titleize %>
<% end %> <% end %>
</p> </p>
<%= link_to 'Auth to Microsoft', '/auth/azure_ad', method: :post, class: "btn btn-primary" %>
</div> </div>
<div class="mt-3"> <div class="mt-3">

View File

@@ -0,0 +1,10 @@
<% if policy(Project).new? %>
<div class="col-sm-6 col-md-4 col-lg-3 mt-4">
<li class="card h-100 shadow-sm">
<div class="card-body d-flex flex-column justify-content-center align-items-center">
<%= fa_icon("plus-circle", class: "text-success", style: "font-size:4rem") %>
<%= link_to t(".actions.new"), [:new, :project], class: "mt-4 text-reset text-decoration-none stretched-link" %>
</div>
</li>
</div>
<% end %>

View File

@@ -1,17 +1,14 @@
<% if @projects.any? %> <% if @projects.any? %>
<section class="container mt-5"> <section class="container mt-5">
<h1 class="h3"><%= t(".heading") %> (<%= @projects.size %>)</h1> <div class="d-flex flex-row justify-content-between align-items-center mb-3">
<ul class="list-unstyled mt-2 row"> <h1 class="h3"><%= t(".heading") %> (<%= @projects.size %>)</h1>
<% if policy(Project).new? %>
<div class="col-sm-6 col-md-4 col-lg-3 mt-4"> <%= bootstrap_form_with url: [@account, :projects], method: :get, remote: true, layout: :inline, id: "search" do |form| %>
<li class="card h-100 shadow-sm"> <%= form.search_field :query, hide_label: true, placeholder: t(".actions.search"), class: "rounded-pill-right", value: params[:query], prepend: form.button(fa_icon("search"), class: "btn btn-light border rounded-pill-left") %>
<div class="card-body d-flex flex-column justify-content-center align-items-center">
<%= fa_icon("plus-circle", class: "text-success", style: "font-size:4rem") %>
<%= link_to t(".actions.new"), [:new, :project], class: "mt-4 text-reset text-decoration-none stretched-link" %>
</div>
</li>
</div>
<% end %> <% end %>
</div>
<ul id="projects" class="list-unstyled mt-2 row">
<%= render partial: "new_project_button" %>
<%= render @projects %> <%= render @projects %>
</ul> </ul>
</section> </section>

View File

@@ -0,0 +1,4 @@
$("#projects").html("")
$("#projects").append("<%= j render(partial: "new_project_button") %>");
$("#projects").append("<%= j render(@projects) %>");
$("form input[type='search']").val("<%= params[:query] %>");

View File

@@ -55,7 +55,7 @@
<hr> <hr>
<%= card_field_set_tag t(".files.heading") do %> <%= card_field_set_tag t(".files.heading") do %>
<%= render "shared/file_infos_dropzone", form: form, releasable: @acquired_media_release %> <%= render "shared/releasable_files_dropzone", form: form, releasable: @acquired_media_release %>
<% end %> <% end %>
<hr> <hr>

View File

@@ -13,6 +13,29 @@
<% end %> <% end %>
<hr> <hr>
<% if @contract_template.has_exhibit_a? %>
<%= card_field_set_tag t(".exhibits.exhibit_a.heading") do %>
<p><%= @contract_template.exhibit_a_legal_text %></p>
<% if @contract_template.exhibit_a_question_text.present? %>
<div class="form-row">
<%= form.text_area :exhibit_a_answer, label: @contract_template.exhibit_a_question_text, wrapper_class: "col-sm-12" %>
</div>
<% end %>
<% end %>
<hr>
<% end %>
<% if @contract_template.has_exhibit_b? %>
<%= card_field_set_tag t(".exhibits.exhibit_b.heading") do %>
<p><%= @contract_template.exhibit_b_legal_text %></p>
<% if @contract_template.exhibit_b_question_text.present? %>
<div class="form-row">
<%= form.text_area :exhibit_b_answer, label: @contract_template.exhibit_b_question_text, wrapper_class: "col-sm-12" %>
</div>
<% end %>
<% end %>
<hr>
<% end %>
<% unless @contract_template.guardian_clause.blank? %> <% unless @contract_template.guardian_clause.blank? %>
<%= form.form_group :minor do %> <%= form.form_group :minor do %>
@@ -25,6 +48,19 @@
<hr> <hr>
<% end %> <% end %>
<% if @contract_template.has_questionnaire? %>
<%= card_field_set_tag t(".questionnaire.heading") do %>
<% (1..AppearanceRelease::NUMBER_OF_CUSTOM_FIELDS).each do |n| %>
<% if @contract_template.public_send("question_#{n}_text").present? %>
<div class="form-row">
<%= form.text_area "question_#{n}_answer", wrapper_class: "col-sm-12", label: @contract_template.public_send("question_#{n}_text") %>
</div>
<% end %>
<% end %>
<% end %>
<hr>
<% end %>
<%= card_field_set_tag t(".personal_info.heading") do %> <%= card_field_set_tag t(".personal_info.heading") do %>
<div class="alert alert-warning font-weight-bold"><%= t ".personal_info.instructions" %></div> <div class="alert alert-warning font-weight-bold"><%= t ".personal_info.instructions" %></div>
<div class="form-row"> <div class="form-row">

View File

@@ -4,7 +4,7 @@
<%= bootstrap_form_with model: [@account, @project, @contract_template, @medical_release], local: true, validation_context: :native do |form| %> <%= bootstrap_form_with model: [@account, @project, @contract_template, @medical_release], local: true, validation_context: :native do |form| %>
<div class="alert alert-warning font-weight-bold"><%= t ".instructions_html", name: @project.name %></div> <div class="alert alert-warning font-weight-bold"><%= t ".instructions_html", name: @project.name %></div>
<%= card_field_set_tag t(".legal.heading") do %> <%= card_field_set_tag t(".legal.heading") do %>
<p><%= @contract_template.body %></p> <%= @contract_template.body %>
<% if @contract_template.fee? %> <% if @contract_template.fee? %>
<p> <p>
Fee <span class="font-weight-bold text-success"><%= number_to_currency @contract_template.fee %></span> Fee <span class="font-weight-bold text-success"><%= number_to_currency @contract_template.fee %></span>
@@ -34,6 +34,9 @@
</div> </div>
<% end %> <% end %>
<% end %> <% end %>
<% if @contract_template.questionnaire_legal_text.present? %>
<%= @contract_template.questionnaire_legal_text %>
<% end %>
<% end %> <% end %>
<hr> <hr>
<% end %> <% end %>
@@ -153,4 +156,4 @@
</div> </div>
<% end %> <% end %>
</div> </div>
</div> </div>

View File

@@ -3,3 +3,6 @@
<%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %> <%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %>
</div> </div>
<% end%> <% end%>
<%= form.form_group do %>
<%= form.rich_text_area :questionnaire_legal_text, hint: true %>
<% end %>

View File

@@ -15,4 +15,3 @@
data-placeholder="<%= dropzone_placeholder_message_for(releasable) %>" data-placeholder="<%= dropzone_placeholder_message_for(releasable) %>"
data-submit-button="#submit_release"> data-submit-button="#submit_release">
</div> </div>

View File

@@ -0,0 +1,17 @@
<div class="field d-none">
<%= form.label :files %>
<%= form.file_field :files, disable: true, direct_upload: true, multiple: true, id: "releasable_files", hide_label: true %>
<% releasable.files.each do |file| %>
<% unless file.persisted? %>
<%= hidden_field_tag "#{releasable.model_name.param_key}[files][]", file.signed_id %>
<% end %>
<% end %>
</div>
<div class="dropzone field border-dashed"
data-accepted-files="audio/*,image/*,video/*,application/*"
data-behavior="dropzone"
data-file-input-id="releasable_files"
data-existing-files="<%= mock_photos_json(releasable.files) %>"
data-placeholder="<%= dropzone_placeholder_message_for(releasable) %>"
data-submit-button="#submit_folder"></div>

View File

@@ -10,5 +10,5 @@
</p> </p>
<p> <p>
If you have questions about how to use the software, please visit <%= link_to "BiGMedia.ai", "https://www.bigmedia.ai/contact" %>. If you have questions about how to use the software, please visit <%= link_to "MESuite.ai", "https://www.mesuite.ai/contact" %>.
</p> </p>

View File

@@ -7,4 +7,4 @@ Please click below to set your password.
<%= edit_password_reset_url(id: @user.password_reset_token, host: AppHost.new.domain_with_port) %> <%= edit_password_reset_url(id: @user.password_reset_token, host: AppHost.new.domain_with_port) %>
<% end %> <% end %>
If you have questions about how to use the software, please visit https://www.bigmedia.ai/contact. If you have questions about how to use the software, please visit https://www.mesuite.ai/contact.

View File

@@ -49,4 +49,5 @@ Rails.application.configure do
ENV["ENABLE_ANALYTICS"] = "true" ENV["ENABLE_ANALYTICS"] = "true"
ENV["BRAYNIAC_AI_API_ENDPOINT"] ||= "" ENV["BRAYNIAC_AI_API_ENDPOINT"] ||= ""
ENV["MILLICAST_API_SECRET"] ||= ""
end end

View File

@@ -0,0 +1,2 @@
require "millicast"

View File

@@ -0,0 +1,13 @@
require 'azure_ad'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :azure_ad,
client_id: ENV['AZURE_CLIENT_ID'],
client_secret: ENV['AZURE_CLIENT_SECRET'],
redirect_uri: ENV['AZURE_REDIRECT_URI'],
client_options: {
token_url: "#{ENV['AZURE_TENANT_ID']}/oauth2/v2.0/token",
authorize_url: "#{ENV['AZURE_TENANT_ID']}/oauth2/v2.0/authorize"
},
scope: ENV['AZURE_SCOPES']
end

View File

@@ -62,12 +62,12 @@ en:
empty: Acquired Media Releases will appear here empty: Acquired Media Releases will appear here
table_headers: table_headers:
approved: Approved approved: Approved
file_infos_count: No. Files files_count: No. Files
name: Name name: Name
notes: Notes notes: Notes
owner_info: Owner Info
signed_at: Date Signed signed_at: Date Signed
tags: Tags tags: Tags
owner_info: Owner Info
new: new:
heading: Import Acquired Media Release heading: Import Acquired Media Release
update: update:
@@ -141,7 +141,10 @@ en:
actions: actions:
manage: Manage manage: Manage
review: Review review: Review
sign_amendment: Sign Additional Clause
messages: messages:
amendment_not_signed_tooltip: Additional Clause Not Yet Signed
amendment_signed_tooltip: Additional Clause Signed
approved_tooltip: Approved by %{user} on %{timestamp} approved_tooltip: Approved by %{user} on %{timestamp}
no_photos: Needs Photo no_photos: Needs Photo
create: create:
@@ -174,6 +177,7 @@ en:
empty: Appearance Releases will appear here empty: Appearance Releases will appear here
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release
table_headers: table_headers:
amendment_signed: Additional Clause
approved: Approved approved: Approved
contact_info: Contact info contact_info: Contact info
name: Name name: Name
@@ -227,6 +231,7 @@ en:
broadcast_recordings: broadcast_recordings:
confirm_hide: Are you sure you want to hide this recording from everyone? confirm_hide: Are you sure you want to hide this recording from everyone?
create: create:
alert: A live stream could not be created. Please try again later or contact support.
notice: A live stream has been created notice: A live stream has been created
destroy: destroy:
alert: A live stream has been deleted alert: A live stream has been deleted
@@ -270,6 +275,9 @@ en:
stream_multiple_cameras: Stream multiple cameras at one time stream_multiple_cameras: Stream multiple cameras at one time
update: update:
reset_notice: The Share URL has been reset, and the previous URL will no longer work. Please click "Copy URL" and share it again with those who you want to have access to this live stream reset_notice: The Share URL has been reset, and the previous URL will no longer work. Please click "Copy URL" and share it again with those who you want to have access to this live stream
form:
labels:
conference_option: Conference Option
bulk_taggings: bulk_taggings:
new_bulk_tag_modal: new_bulk_tag_modal:
submit: Add submit: Add
@@ -307,6 +315,10 @@ en:
custom_fields: custom_fields:
heading: Questionnaire heading: Questionnaire
instructions: Please list the questions you wish the signer to answer. Any unused question fields will be hidden. instructions: Please list the questions you wish the signer to answer. Any unused question fields will be hidden.
exhibits:
heading: Exhibits
help:
option_field: Leave blank if not required for this contract.
exploitable_rights: exploitable_rights:
heading: Exploitable Rights heading: Exploitable Rights
legal: legal:
@@ -347,10 +359,16 @@ en:
contracts: contracts:
amendment_page: amendment_page:
description_labels: description_labels:
amendment_clause: Amendment Clause amendment_clause: Clause
amendment_signature: Amendment Signature amendment_signature: Clause Signature
amendment_signer_name: Amendment Signer Name amendment_signer_name: Clause Signer Name
heading: Amendment heading: Additional Clause
exhibit_a_page:
heading:
appearance_release: Exhibit A
exhibit_b_page:
heading:
appearance_release: Exhibit B
for_office_use_only: for_office_use_only:
description_labels: description_labels:
date_issued: Date Issued date_issued: Date Issued
@@ -370,6 +388,7 @@ en:
other: Minor photos other: Minor photos
questionnaire: questionnaire:
heading: heading:
appearance_release: Questionnaire
medical_release: Medical Questionnaire medical_release: Medical Questionnaire
misc_release: Questionnaire misc_release: Questionnaire
signature_page: signature_page:
@@ -431,17 +450,16 @@ en:
download_type: Type download_type: Type
errors_helper: errors_helper:
failure_message: "The following errors have prevented this %{model_name} from being submitted:" failure_message: "The following errors have prevented this %{model_name} from being submitted:"
file_infos: files:
edit: edit:
heading: Add Media heading: Media
update:
notice: The release has been updated
helpers: helpers:
help: help:
contract_template: contract_template:
amendment_clause: Leave blank if not required for this contract amendment_clause: Leave blank if not required for this contract
fee: Leave at $0.00 for no-fee fee: Leave at $0.00 for no-fee
guardian_clause: Leave blank if not required for this contract guardian_clause: Leave blank if not required for this contract
questionnaire_legal_text: Leave blank if not required for this contract
signature_legal_text: Leave blank if not required for this contract signature_legal_text: Leave blank if not required for this contract
task_request: task_request:
time_allowed: Minimum of 2 hours, no partial hours allowed time_allowed: Minimum of 2 hours, no partial hours allowed
@@ -829,6 +847,8 @@ en:
location_releases: location_releases:
create: create:
notice: The location release has been created notice: The location release has been created
csv:
no_amendment_clause: No additional contract clause
destroy: destroy:
alert: The location release has been deleted alert: The location release has been deleted
edit: edit:
@@ -853,6 +873,7 @@ en:
table_headers: table_headers:
address: Address address: Address
amendment_signed: Additional Clause amendment_signed: Additional Clause
amendment_signed_column: Additional Clause
approved: Approved approved: Approved
location_info: Location Info location_info: Location Info
notes: Notes notes: Notes
@@ -865,8 +886,8 @@ en:
review: Review review: Review
sign_amendment: Sign Additional Clause sign_amendment: Sign Additional Clause
messages: messages:
amendment_not_signed_tooltip: Amendment not yet signed amendment_not_signed_tooltip: Additional clause not yet signed
amendment_signed_tooltip: Amendment Signed amendment_signed_tooltip: Additional clause signed
approved_tooltip: Approved by %{user} on %{timestamp} approved_tooltip: Approved by %{user} on %{timestamp}
no_photos: Needs Photo no_photos: Needs Photo
new: new:
@@ -932,7 +953,6 @@ en:
empty: Medical releases will appear here empty: Medical releases will appear here
table_headers: table_headers:
approved: Approved approved: Approved
approved?: Approved
contact_info: Contact info contact_info: Contact info
name: Person name name: Person name
notes: Notes notes: Notes
@@ -1082,9 +1102,13 @@ en:
actions: actions:
folder: Add Folder folder: Add Folder
new: Create New Project new: Create New Project
search: Search
heading: Open Projects heading: Open Projects
new: new:
heading: Create New Project heading: Create New Project
new_project_button:
actions:
new: Create New Project
project: project:
actions: actions:
delete: Delete delete: Delete
@@ -1142,12 +1166,12 @@ en:
heading: Signature heading: Signature
amendments: amendments:
create: create:
amendment_already_signed_message: Release amendment is already signed! amendment_already_signed_message: Release additional clause is already signed!
amendment_signed_message: Release amendment signed successfully! Thank you amendment_signed_message: Release additional clause signed successfully! Thank you
new: new:
amendment: amendment:
heading: Additional Clause heading: Additional Clause
copy_url: Copy sign amendment URL copy_url: Copy sign additional clause URL
signature: signature:
heading: Signature heading: Signature
signed_contract_preview: Signed Contract Preview signed_contract_preview: Signed Contract Preview
@@ -1156,6 +1180,11 @@ en:
notice: Your release has been signed. Thank you! notice: Your release has been signed. Thank you!
new: new:
cancel: Cancel cancel: Cancel
exhibits:
exhibit_a:
heading: Exhibit A
exhibit_b:
heading: Exhibit B
guardian_2_info: guardian_2_info:
heading: Second Guardian Information (if company requires) heading: Second Guardian Information (if company requires)
guardian_2_photo: guardian_2_photo:
@@ -1185,6 +1214,8 @@ en:
no_photo: No photo yet no_photo: No photo yet
take_photo: Take Photo take_photo: Take Photo
warning: If your photo appears sideways, it will be autocorrected when you submit your release. warning: If your photo appears sideways, it will be autocorrected when you submit your release.
questionnaire:
heading: Questionnaire
signature: signature:
heading: Sign Below heading: Sign Below
broadcasts: broadcasts:
@@ -1614,3 +1645,9 @@ en:
edit: Edit edit: Edit
report: Report report: Report
generating: Generating... generating: Generating...
conference_meetings:
show:
alerts:
not_authenticated: You are not authenticated via Microsoft, please authenticate and try again
failed_to_join: Failed to join conference
unknown_conference_option: Unknown conference option

View File

@@ -16,12 +16,13 @@ es:
heading: Guardian Photo heading: Guardian Photo
index: index:
table_headers: table_headers:
approved: Appproved (ES)
file_infos_count: No. Files (ES) file_infos_count: No. Files (ES)
name: Name (ES) name: Name (ES)
notes: Notes (ES) notes: Notes (ES)
owner_info: Owner Info (ES)
signed_at: Date Signed (ES) signed_at: Date Signed (ES)
tags: Tags (ES) tags: Tags (ES)
owner_info: Owner Info (ES)
activerecord: activerecord:
attributes: attributes:
appearance_release: appearance_release:
@@ -46,6 +47,13 @@ es:
models: models:
appearance_release: Autorización de Aparacimiento appearance_release: Autorización de Aparacimiento
appearance_releases: appearance_releases:
appearance_release:
actions:
manage: Manage (ES)
sign_amendment: Sign Additional Clause (ES)
messages:
amendment_not_signed_tooltip: Amendment not yet signed (ES)
amendment_signed_tooltip: Amendment signed (ES)
create: create:
failed_import: Failed to create appearance release for files listed below (ES) failed_import: Failed to create appearance release for files listed below (ES)
matching_started: Matching started (ES) matching_started: Matching started (ES)
@@ -65,6 +73,8 @@ es:
index: index:
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release (ES) imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release (ES)
table_headers: table_headers:
amendment_signed: Additional Clause (ES)
approved: Approved (ES)
contact_info: "" contact_info: ""
name: "" name: ""
notes: "" notes: ""
@@ -121,6 +131,9 @@ es:
stream_multiple_cameras: Stream multiple cameras at one time stream_multiple_cameras: Stream multiple cameras at one time
update: update:
reset_notice: The Share URL has been reset, and the previous URL will no longer work. Please click "Copy URL" and share it again with those who you want to have access to this live stream reset_notice: The Share URL has been reset, and the previous URL will no longer work. Please click "Copy URL" and share it again with those who you want to have access to this live stream
form:
labels:
conference_option: Conference Option (ES)
contract_templates: contract_templates:
blank_contracts: blank_contracts:
create: create:
@@ -170,7 +183,7 @@ es:
amendment_clause: Amendment Clause (ES) amendment_clause: Amendment Clause (ES)
amendment_signature: Amendment Signature (ES) amendment_signature: Amendment Signature (ES)
amendment_signer_name: Amendment Signer Name (ES) amendment_signer_name: Amendment Signer Name (ES)
heading: Amendment (ES) heading: Secondary Clause (ES)
for_office_use_only: for_office_use_only:
description_labels: description_labels:
date_issued: Date Issued (ES) date_issued: Date Issued (ES)
@@ -405,6 +418,8 @@ es:
update: Approve (ES) update: Approve (ES)
update: 'Actualizar %{model}' update: 'Actualizar %{model}'
location_releases: location_releases:
csv:
no_amendment_clause: No amendment clause (ES)
form: form:
photos: photos:
dropzone_label: Tap to take a photo of the Property (optional) (ES) dropzone_label: Tap to take a photo of the Property (optional) (ES)
@@ -412,6 +427,8 @@ es:
table_headers: table_headers:
address: Address (ES) address: Address (ES)
amendment_signed: Additional Clause (ES) amendment_signed: Additional Clause (ES)
amendment_signed_column: Amendment signed (ES)
approved: Approved (ES)
notes: Notes (ES) notes: Notes (ES)
signed_at: Date Signed (ES) signed_at: Date Signed (ES)
tags: Tags (ES) tags: Tags (ES)
@@ -437,6 +454,7 @@ es:
heading: Guardian Photo heading: Guardian Photo
index: index:
table_headers: table_headers:
approved: Approved (ES)
name: Name (ES) name: Name (ES)
notes: Notes (ES) notes: Notes (ES)
owner_info: Owner Info owner_info: Owner Info
@@ -448,7 +466,6 @@ es:
index: index:
table_headers: table_headers:
approved: Approved (ES) approved: Approved (ES)
approved?: Approved (ES)
contact_info: Contact info (ES) contact_info: Contact info (ES)
name: Person name (ES) name: Person name (ES)
notes: Notes (ES) notes: Notes (ES)
@@ -462,6 +479,7 @@ es:
misc_releases: misc_releases:
index: index:
table_headers: table_headers:
approved: Approved (ES)
contact_info: Contact info (ES) contact_info: Contact info (ES)
name: Person name (ES) name: Person name (ES)
notes: Notes (ES) notes: Notes (ES)
@@ -470,6 +488,7 @@ es:
music_releases: music_releases:
index: index:
table_headers: table_headers:
approved: Approved (ES)
composers_count: No. Composers (ES) composers_count: No. Composers (ES)
file_infos_count: No. Files (ES) file_infos_count: No. Files (ES)
name: Name (ES) name: Name (ES)
@@ -631,6 +650,7 @@ es:
heading: Guardian Photo (ES) heading: Guardian Photo (ES)
index: index:
table_headers: table_headers:
approved: Approved (ES)
email: Email (ES) email: Email (ES)
name: Name (ES) name: Name (ES)
notes: Notes (ES) notes: Notes (ES)
@@ -688,3 +708,9 @@ es:
production_elements_logs: Production Elements Logs, and more (ES) production_elements_logs: Production Elements Logs, and more (ES)
reduces_labor_cost: Reduces labor costs (ES) reduces_labor_cost: Reduces labor costs (ES)
simplifies_cue_sheets: Simplifies Music Cue Sheets, Graphic Cue Sheets (ES) simplifies_cue_sheets: Simplifies Music Cue Sheets, Graphic Cue Sheets (ES)
conference_meetings:
show:
alerts:
not_authenticated: You are not authenticated via Microsoft, please authenticate and try again (ES)
failed_to_join: Failed to join conference (ES)
unknown_conference_option: Unknown conference option (ES)

View File

@@ -4,6 +4,8 @@ require 'sidekiq/web'
Rails.application.routes.draw do Rails.application.routes.draw do
AVAILABLE_LOCALES_REGEX = /#{I18n.available_locales.join("|")}/.freeze AVAILABLE_LOCALES_REGEX = /#{I18n.available_locales.join("|")}/.freeze
get 'auth/azure_ad/callback', to: 'callbacks#create'
concern :confirmable do concern :confirmable do
resources :video_release_confirmations, only: [:new, :create, :destroy] resources :video_release_confirmations, only: [:new, :create, :destroy]
end end
@@ -19,8 +21,8 @@ Rails.application.routes.draw do
concern :taggable do concern :taggable do
resources :acts_as_taggable_on_tags, only: [:new, :create, :destroy], controller: "tags" resources :acts_as_taggable_on_tags, only: [:new, :create, :destroy], controller: "tags"
end end
concern :file_infoable do concern :file_uploadable do
resource :file_infos, only: [:edit, :update] resource :files, only: [:edit, :update]
end end
concern :approvable do concern :approvable do
resource :approvals, only: [:new, :create] resource :approvals, only: [:new, :create]
@@ -51,7 +53,7 @@ Rails.application.routes.draw do
resource :account, only: [:new, :create, :update] resource :account, only: [:new, :create, :update]
resources :account_auths, only: [:index, :create, :update, :destroy] resources :account_auths, only: [:index, :create, :update, :destroy]
resources :projects, shallow: true do resources :projects, shallow: true do
resources :acquired_media_releases, except: [:show], concerns: [:contractable, :notable, :file_infoable] resources :acquired_media_releases, except: [:show], concerns: [:contractable, :notable, :file_uploadable]
resources :appearance_releases, except: [:show], concerns: [:contractable, :notable] resources :appearance_releases, except: [:show], concerns: [:contractable, :notable]
resources :appearance_release_imports, only: [:create] resources :appearance_release_imports, only: [:create]
resources :location_releases, except: [:show], concerns: [:contractable, :notable, :photoable] resources :location_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
@@ -100,7 +102,7 @@ Rails.application.routes.draw do
member do member do
delete :destroy_file delete :destroy_file
end end
resource :zoom_meeting, only: [:show] resource :conference_meeting, only: [:show]
resources :broadcast_recordings, only: :destroy resources :broadcast_recordings, only: :destroy
end end
resources :directories, except: [:index] do resources :directories, except: [:index] do
@@ -131,7 +133,9 @@ Rails.application.routes.draw do
resources :projects, only: [] do resources :projects, only: [] do
resources :contract_templates, only: [:index] do resources :contract_templates, only: [:index] do
resources :talent_releases, only: [:new, :create] resources :talent_releases, only: [:new, :create]
resources :appearance_releases, only: [:new, :create] resources :appearance_releases, only: [:new, :create] do
resources :amendments, only: [:new, :create]
end
resources :acquired_media_releases, only: [:new, :create] resources :acquired_media_releases, only: [:new, :create]
resources :location_releases, only: [:new, :create] do resources :location_releases, only: [:new, :create] do
resources :amendments, only: [:new, :create] resources :amendments, only: [:new, :create]

View File

@@ -0,0 +1,5 @@
class AddAmendmentSignerDetailsToAppearanceReleases < ActiveRecord::Migration[6.0]
def change
add_column :appearance_releases, :amendment_signer_name, :string
end
end

View File

@@ -0,0 +1,5 @@
class AddSimulcastUidToBroadcasts < ActiveRecord::Migration[6.0]
def change
add_column :broadcasts, :simulcast_uid, :string
end
end

View File

@@ -0,0 +1,11 @@
class AddExhibitFieldsToContractTemplates < ActiveRecord::Migration[6.0]
def change
add_column :contract_templates, :exhibit_a_legal_text, :text
add_column :contract_templates, :exhibit_a_question_text, :text
add_column :contract_templates, :exhibit_b_legal_text, :text
add_column :contract_templates, :exhibit_b_question_text, :text
add_column :appearance_releases, :exhibit_a_answer, :text
add_column :appearance_releases, :exhibit_b_answer, :text
end
end

View File

@@ -0,0 +1,19 @@
class AddQuestionAnswersToAppearanceReleases < ActiveRecord::Migration[6.0]
def change
add_column :appearance_releases, :question_1_answer, :text
add_column :appearance_releases, :question_2_answer, :text
add_column :appearance_releases, :question_3_answer, :text
add_column :appearance_releases, :question_4_answer, :text
add_column :appearance_releases, :question_5_answer, :text
add_column :appearance_releases, :question_6_answer, :text
add_column :appearance_releases, :question_7_answer, :text
add_column :appearance_releases, :question_8_answer, :text
add_column :appearance_releases, :question_9_answer, :text
add_column :appearance_releases, :question_10_answer, :text
add_column :appearance_releases, :question_11_answer, :text
add_column :appearance_releases, :question_12_answer, :text
add_column :appearance_releases, :question_13_answer, :text
add_column :appearance_releases, :question_14_answer, :text
add_column :appearance_releases, :question_15_answer, :text
end
end

View File

@@ -0,0 +1,5 @@
class AddVideoConferenceUrlOverrideToBroadcasts < ActiveRecord::Migration[6.0]
def change
add_column :broadcasts, :video_conference_url_override, :string
end
end

View File

@@ -0,0 +1,8 @@
class AddMicrosoftInfoToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :microsoft_user_id, :string
add_column :users, :microsoft_access_token, :string
add_column :users, :microsoft_refresh_token, :string
add_column :users, :microsoft_token_expires_at, :integer
end
end

View File

@@ -0,0 +1,6 @@
class AddConferenceDetailsToBroadcasts < ActiveRecord::Migration[6.0]
def change
add_column :broadcasts, :conference_option, :string
add_column :broadcasts, :conference_join_url, :string
end
end

View File

@@ -9,20 +9,6 @@ SET xmloption = content;
SET client_min_messages = warning; SET client_min_messages = warning;
SET row_security = off; SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
-- --
-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: - -- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: -
-- --
@@ -379,7 +365,25 @@ CREATE TABLE public.appearance_releases (
guardian_2_address_country character varying, guardian_2_address_country character varying,
approved_by_user_name text, approved_by_user_name text,
approved_by_user_email text, approved_by_user_email text,
approved_at timestamp without time zone approved_at timestamp without time zone,
amendment_signer_name character varying,
exhibit_a_answer text,
exhibit_b_answer text,
question_1_answer text,
question_2_answer text,
question_3_answer text,
question_4_answer text,
question_5_answer text,
question_6_answer text,
question_7_answer text,
question_8_answer text,
question_9_answer text,
question_10_answer text,
question_11_answer text,
question_12_answer text,
question_13_answer text,
question_14_answer text,
question_15_answer text
); );
@@ -580,7 +584,11 @@ CREATE TABLE public.broadcasts (
full_live_stream_playback_uid character varying, full_live_stream_playback_uid character varying,
stream_url_override character varying, stream_url_override character varying,
stream_key_override character varying, stream_key_override character varying,
director_mode_video_embed text director_mode_video_embed text,
simulcast_uid character varying,
video_conference_url_override character varying,
conference_option character varying,
conference_join_url character varying
); );
@@ -678,7 +686,11 @@ CREATE TABLE public.contract_templates (
question_13_text text, question_13_text text,
question_14_text text, question_14_text text,
question_15_text text, question_15_text text,
accessibility integer DEFAULT 0 accessibility integer DEFAULT 0,
exhibit_a_legal_text text,
exhibit_a_question_text text,
exhibit_b_legal_text text,
exhibit_b_question_text text
); );
@@ -1479,6 +1491,7 @@ CREATE TABLE public.settings (
-- --
CREATE SEQUENCE public.settings_id_seq CREATE SEQUENCE public.settings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1514,6 +1527,7 @@ CREATE TABLE public.taggings (
-- --
CREATE SEQUENCE public.taggings_id_seq CREATE SEQUENCE public.taggings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1544,6 +1558,7 @@ CREATE TABLE public.tags (
-- --
CREATE SEQUENCE public.tags_id_seq CREATE SEQUENCE public.tags_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1791,7 +1806,11 @@ CREATE TABLE public.users (
remember_created_at timestamp without time zone, remember_created_at timestamp without time zone,
first_name character varying, first_name character varying,
last_name character varying, last_name character varying,
time_zone character varying DEFAULT 'UTC'::character varying NOT NULL time_zone character varying DEFAULT 'UTC'::character varying NOT NULL,
microsoft_user_id character varying,
microsoft_access_token character varying,
microsoft_refresh_token character varying,
microsoft_token_expires_at integer
); );
@@ -4007,6 +4026,13 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200727143209'), ('20200727143209'),
('20200730050903'), ('20200730050903'),
('20200803145912'), ('20200803145912'),
('20200803150138'); ('20200803150138'),
('20200804093409'),
('20200807190607'),
('20200811102720'),
('20200812060406'),
('20200819070738'),
('20200820081251'),
('20200820081524');

124
lib/azure_ad.rb Normal file
View File

@@ -0,0 +1,124 @@
require 'omniauth-oauth2'
# This file is from omniauth-microsoft_graph lib (not installed)
# It is modified to make auth work
module OmniAuth
module Strategies
class AzureAd < OmniAuth::Strategies::OAuth2
BASE_SCOPE_URL = 'https://graph.microsoft.com/'
BASE_SCOPES = %w[offline_access openid email profile].freeze
DEFAULT_SCOPE = 'offline_access openid email profile User.Read'.freeze
option :name, :azure_ad
option :client_options,
site: 'https://login.microsoftonline.com/'
option :authorize_options, %i[state callback_url scope response_mode]
option :token_params, {}
option :scope, DEFAULT_SCOPE
option :authorized_client_ids, []
uid { raw_info["id"] }
info do
{
# 'email' => raw_info["mail"],
# 'first_name' => raw_info["givenName"],
# 'last_name' => raw_info["surname"],
# 'name' => [raw_info["givenName"], raw_info["surname"]].join(' '),
# 'nickname' => raw_info["displayName"],
}
end
extra do
{
# 'raw_info' => raw_info,
# 'params' => access_token.params,
# 'aud' => options.client_id
}
end
def authorize_params
super.tap do |params|
options[:authorize_options].each do |k|
params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
end
params[:scope] = get_scope(params)
session['omniauth.state'] = params[:state] if params[:state]
end
end
def raw_info
@raw_info ||= access_token.get('https://graph.microsoft.com/v1.0/me').parsed
end
def callback_url
options[:callback_url] || full_host + script_name + callback_path
end
def custom_build_access_token
token_response = get_access_token(request)
session[:microsoft_graph_api_token] = token_response.token
token_response
end
alias build_access_token custom_build_access_token
private
def get_access_token(request)
verifier = request.params['code']
redirect_uri = request.params['redirect_uri'] || request.params['callback_url']
if verifier && request.xhr?
client_get_token(verifier, redirect_uri || '/auth/azure_ad/callback')
elsif verifier
client_get_token(verifier, redirect_uri || callback_url)
elsif verify_token(request.params['access_token'])
::OAuth2::AccessToken.from_hash(client, request.params.dup)
elsif request.content_type =~ /json/i
begin
body = JSON.parse(request.body.read)
request.body.rewind # rewind request body for downstream middlewares
verifier = body && body['code']
client_get_token(verifier, '/auth/azure_ad/callback') if verifier
rescue JSON::ParserError => e
warn "[omniauth google-oauth2] JSON parse error=#{e}"
end
end
end
def client_get_token(verifier, redirect_uri)
client.auth_code.get_token(verifier, get_token_options(redirect_uri), get_token_params)
end
def get_token_params
deep_symbolize(options.auth_token_params || {})
end
def get_token_options(redirect_uri = '')
{ redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true))
end
def get_scope(params)
raw_scope = params[:scope] || DEFAULT_SCOPE
scope_list = raw_scope.split(' ').map { |item| item.split(',') }.flatten
scope_list.map! { |s| s =~ %r{^https?://} || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" }
scope_list.join(' ')
end
def verify_token(access_token)
return false unless access_token
# access_token.get('https://graph.microsoft.com/v1.0/me').parsed
raw_response = client.request(:get, 'https://graph.microsoft.com/v1.0/me',
params: { access_token: access_token }).parsed
(raw_response['aud'] == options.client_id) || options.authorized_client_ids.include?(raw_response['aud'])
end
end
end
end

107
lib/microsoft_graph.rb Normal file
View File

@@ -0,0 +1,107 @@
require 'httparty'
class MicrosoftGraph
BASE_URL = 'https://graph.microsoft.com/v1.0'.freeze
def initialize(current_user, client_id, client_secret, tenant_id, scopes)
@current_user = current_user
@uid = current_user.microsoft_user_id
@token = current_user.microsoft_access_token
@refresh_token = current_user.microsoft_refresh_token
@token_expires_at = current_user.microsoft_token_expires_at
@client_id = client_id
@client_secret = client_secret
@tenant_id = tenant_id
@scopes = scopes
end
def create_teams_meeting(subject)
if @refresh_token.nil? || @token_expires_at.nil?
raise ActionController::InvalidAuthenticityToken, 'Missing refresh token / token expiration'
return
end
# Obtain new token if token is expired or will expire in less than 5 minutes
if 5.minutes.from_now.to_i > @token_expires_at.seconds
refresh_access_token
end
if @token.nil?
raise ActionController::InvalidAuthenticityToken, 'Missing access token'
return
end
response = HTTParty.post(
"#{BASE_URL}/me/onlineMeetings",
body: {
subject: subject,
participants: {
organizer: {
identity: {
user: {
id: @uid
}
}
}
}
}.to_json,
headers: {
Authorization: "Bearer #{@token}",
'Content-Type': 'application/json'
}
)
raise StandardError, 'Authenticated user does not have a permission to create Teams Online Meeting' if response.code == 403
if response.code != 201
Rails.logger.error('[Microsoft Graph Error]')
Rails.logger.error(response.inspect)
raise StandardError, "Failed to create teams meeting [#{response.code}]"
else
JSON.parse(response.body)
end
end
private
def refresh_token_url
"https://login.microsoftonline.com/#{@tenant_id}/oauth2/v2.0/token"
end
def refresh_access_token
response = HTTParty.post(refresh_token_url,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: {
client_id: @client_id,
client_secret: @client_secret,
refresh_token: @refresh_token,
grant_type: 'refresh_token',
scope: @scopes
})
if response.code != 200
Rails.logger.error '[Microsoft Graph Error] Failed to obtain new access token using refresh token'
Rails.logger.error(response.inspect)
raise StandardError, 'Failed to obtain new access token'
end
parsed_response = JSON.parse(response.body)
new_access_token = parsed_response['access_token']
new_refresh_token = parsed_response['refresh_token']
token_expires_in = parsed_response['expires_in'] # For how long access token is valid (in seconds)
token_new_expiration_time = Time.now.to_i + token_expires_in
@current_user.microsoft_access_token = new_access_token
@current_user.microsoft_refresh_token = new_refresh_token
@current_user.microsoft_token_expires_at = token_new_expiration_time
@current_user.save!
@token = new_access_token
@refresh_token = new_refresh_token
@token_expires_at = token_new_expiration_time
end
end

2
lib/millicast.rb Normal file
View File

@@ -0,0 +1,2 @@
require_relative "./millicast/base"
require_relative "./millicast/publish_token"

14
lib/millicast/base.rb Normal file
View File

@@ -0,0 +1,14 @@
module Millicast
class Base < ActiveResource::Base
self.site = 'https://api.millicast.com/api'
self.connection.auth_type = :bearer
self.connection.bearer_token = ENV.fetch("MILLICAST_API_SECRET")
self.include_format_in_path = false
def self.enable_logging
ActiveSupport::Notifications.subscribe('request.active_resource') do |name, start, finish, id, payload|
puts payload
end
end
end
end

View File

@@ -0,0 +1,5 @@
module Millicast
class PublishToken < Base
self.collection_name = "publish_token"
end
end

View File

@@ -87,26 +87,10 @@ RSpec.describe AcquiredMediaReleasesController, type: :controller do
}.to have_enqueued_job(SetTagsForReleasableJob).with(AcquiredMediaRelease.last) }.to have_enqueued_job(SetTagsForReleasableJob).with(AcquiredMediaRelease.last)
end end
it "creates nested file info records" do it "adds files to release" do
expect { post :create, params: { project_id: project, acquired_media_release: acquired_media_release_params.merge(file_params) }
post :create, params: {
project_id: project,
acquired_media_release: acquired_media_release_params.merge(
file_infos_attributes: {
0 => attributes_for(:file_info)
}
)
}
}.to change(FileInfo, :count).by(1)
expect(AcquiredMediaRelease.last.file_infos.size).to eq(1)
end
it "logs analytics" do expect(AcquiredMediaRelease.last.files.size).to eq(1)
expect {
post :create, params: { project_id: project, acquired_media_release: acquired_media_release_params }
}.to(
have_enqueued_job(TrackAnalyticsJob).with(user, account, :track_create_non_native_release, release_type: "AcquiredMediaRelease", user_agent: "Rails Testing", user_ip: "0.0.0.0")
)
end end
context "when the record would be invalid" do context "when the record would be invalid" do
@@ -206,4 +190,11 @@ RSpec.describe AcquiredMediaReleasesController, type: :controller do
restriction_text: "restrictions", restriction_text: "restrictions",
} }
end end
def file_params
path = Rails.root.join("spec", "fixtures", "files", "contract.pdf")
contract_file = Rack::Test::UploadedFile.new(path, "application/pdf")
{ files: [contract_file] }
end
end end

View File

@@ -117,7 +117,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end end
it "paginates the broadcast list" do it "paginates the broadcast list" do
allow(MuxLiveStream).to receive(:new).and_return(double(id: "id", key: "key", playback_id: "playback_id")) stub_mux_live_stream
project = create(:project, account: current_user.primary_account) project = create(:project, account: current_user.primary_account)
create_list(:broadcast, 20, project: project ) create_list(:broadcast, 20, project: project )

View File

@@ -7,7 +7,7 @@ RSpec.describe Admin::BroadcastsController, type: :controller do
before do before do
sign_in(current_user) sign_in(current_user)
allow(MuxLiveStream).to receive(:new).and_return(double(id: "id", key: "key", playback_id: "playback_id")) stub_mux_live_stream
end end
describe "#edit" do describe "#edit" do

View File

@@ -7,7 +7,7 @@ RSpec.describe Api::BroadcastsController, type: :controller do
describe '#index' do describe '#index' do
before do before do
allow(MuxLiveStream).to receive(:new).and_return(double(id: 'id', key: 'key', playback_id: 'playback_id')) stub_mux_live_stream
end end
it 'returns a list of all broadcasts ready for streaming in the project' do it 'returns a list of all broadcasts ready for streaming in the project' do

View File

@@ -152,14 +152,6 @@ RSpec.describe AppearanceReleasesController, tye: :controller do
}.to have_enqueued_job(SetTagsForReleasableJob).with(AppearanceRelease.last) }.to have_enqueued_job(SetTagsForReleasableJob).with(AppearanceRelease.last)
end end
it "logs analytics" do
expect {
post :create, params: { project_id: project, appearance_release: appearance_release_params }
}.to(
have_enqueued_job(TrackAnalyticsJob).with(user, account, :track_create_non_native_release, release_type: "AppearanceRelease", user_agent: "Rails Testing", user_ip: "0.0.0.0")
)
end
context "when the record would be invalid" do context "when the record would be invalid" do
before do before do
allow_any_instance_of(AppearanceRelease).to receive(:save).and_return(false) allow_any_instance_of(AppearanceRelease).to receive(:save).and_return(false)

Some files were not shown because too many files have changed in this diff Show More