Compare commits

..

11 Commits

Author SHA1 Message Date
Bilal
5147806483 add specs and use i18n 2020-08-19 15:47:01 +03:00
Bilal
f5628c47df allow selecting conference option 2020-08-19 13:05:16 +03:00
Bilal
27fade2d09 remove obsolete require 2020-08-18 20:46:38 +03:00
Bilal
be5261037e Complete teams meeting creation and token refresh 2020-08-18 20:43:33 +03:00
Bilal
f25a72004e create graph api client to handle requests 2020-08-12 16:36:47 +02:00
Bilal
3352217a03 update azure_ad strategy 2020-08-12 14:44:22 +02:00
Bilal
0cc3b2bd62 Get code and token from Azure AD and store it to the DB 2020-08-12 13:52:22 +02:00
Senad Uka
eb7f8f1a43 Initial teams commit 2020-08-06 16:57:39 +00:00
Senad Uka
190ff2854b Upstream sync 2020-08-06 16:56:40 +00:00
Senad Uka
8214ba9e67 Changes 2020-08-03 21:52:04 +00:00
Senad Uka
9cbd8d31a8 Upstream sync 2020-07-29 05:15:02 +00:00
38 changed files with 1359 additions and 128 deletions

View File

@@ -16,9 +16,10 @@ REDIS_URL=
# Required for Zoom.us integration # Required for Zoom.us integration
ZOOM_API_KEY= ZOOM_API_KEY=
ZOOM_API_SECRET= ZOOM_API_SECRET=
ZOOM_ACCOUNT_NUMBER=
ZOOM_PRO_USERS_LIMIT= # defaults to 3 ZOOM_PRO_USERS_LIMIT= # defaults to 3
ZOOM_USER_TYPE= # 'pro' / 'basic' ZOOM_USER_TYPE= # 'pro' / 'basic'
ZOOM_ENABLE_RECORDINGS=0 # 0 / 1 ZOOM_ENABLE_RECORDINGS= # true / false (default: false)
# Token for webhooks authorization # Token for webhooks authorization
ZOOM_VERIFICATION_TOKEN= ZOOM_VERIFICATION_TOKEN=
@@ -27,3 +28,11 @@ MUX_TOKEN_ID=
MUX_TOKEN_SECRET= MUX_TOKEN_SECRET=
MUX_BROADCAST_SERVER_URL=rtmp://global-live.mux.com:5222/app MUX_BROADCAST_SERVER_URL=rtmp://global-live.mux.com:5222/app
MUX_TEST_MODE_DISABLED= MUX_TEST_MODE_DISABLED=
# 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,15 @@ 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'
# authenticate via Microsoft
# gem 'omniauth-microsoft_graph', git: 'https://github.com/m4c3/omniauth-microsoft_graph'
# gem 'omniauth-microsoft_graph'
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

@@ -56,35 +56,74 @@ class AcquiredMediaReleasesController < ApplicationController
end end
end end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_company
person_email
person_title
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def acquired_media_release_params def acquired_media_release_params
params.require(:acquired_media_release).permit( params.require(:acquired_media_release).permit(person_params,
:name, guardian_params,
:territory, second_guardian_params,
:term, :minor,
:person_first_name, :name,
:person_last_name, :territory,
:person_phone, :term,
:person_email, :contract,
:person_company, :applicable_medium_id, :applicable_medium_text,
:person_title, :territory_id, :territory_text,
:person_address_street1, :term_id, :term_text,
:person_address_street2, :restriction_id, :restriction_text,
:person_address_city, categories: [],
:person_address_state, file_infos_attributes: %i[
:person_address_zip, filename
:person_address_country, content_type
:contract, byte_size
:applicable_medium_id, :applicable_medium_text, ])
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
categories: [],
file_infos_attributes: [
:filename,
:content_type,
:byte_size
]
)
end end
def build_acquired_media_release(attrs = {}) def build_acquired_media_release(attrs = {})

View File

@@ -26,7 +26,7 @@ class BroadcastsController < ApplicationController
end end
def show def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting] @conference_url = url_for [@broadcast.project, @broadcast, :conference_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.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 +72,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

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

@@ -41,31 +41,70 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
end end
end end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_fax
person_email
person_title
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def acquired_media_release_params def acquired_media_release_params
params.require(:acquired_media_release).permit( params.require(:acquired_media_release).permit(person_params,
:name, guardian_params,
:description, second_guardian_params,
:person_first_name, :minor,
:person_last_name, :name,
:person_email, :description,
:person_title, :signature_base64,
:person_phone, :locale, :contract_template,
:person_fax, categories: [],
:person_address_street1, file_infos_attributes: %i[
:person_address_street2, filename
:person_address_city, content_type
:person_address_state, byte_size
:person_address_zip, ])
:person_address_country,
:signature_base64,
:locale, :contract_template,
categories: [],
file_infos_attributes: [
:filename,
:content_type,
:byte_size
]
)
end end
def acquired_media_release_params_with_locale def acquired_media_release_params_with_locale

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

@@ -11,6 +11,10 @@ class AcquiredMediaRelease < ApplicationRecord
include PersonName include PersonName
include CsvExportable include CsvExportable
include Approvable include Approvable
include GuardianPhotoable
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
@@ -33,6 +37,38 @@ class AcquiredMediaRelease < ApplicationRecord
%w(person_address_country country) %w(person_address_country country)
] ]
composed_of :guardian_address,
class_name: 'Address',
mapping: [
%w[guardian_address_street1 street1],
%w[guardian_address_street2 street2],
%w[guardian_address_city city],
%w[guardian_address_state state],
%w[guardian_address_zip zip],
%w[guardian_address_country country]
]
composed_of :guardian_2_address,
class_name: 'Address',
mapping: [
%w[guardian_2_address_street1 street1],
%w[guardian_2_address_street2 street2],
%w[guardian_2_address_city city],
%w[guardian_2_address_state state],
%w[guardian_2_address_zip zip],
%w[guardian_2_address_country country]
]
# We don't care for the argument but method WILL receive option name
# when called from inside with_option block, hence * argument
def self.face_photo_acceptable_content_types(*)
['image/png', 'image/jpeg']
end
def self.acceptable_import_file_extensions
['.png', '.jpeg', '.jpg', '.pdf']
end
validates :name, presence: true validates :name, presence: true
validates :person_email, email: true, allow_blank: true validates :person_email, email: true, allow_blank: true
@@ -54,8 +90,8 @@ class AcquiredMediaRelease < ApplicationRecord
# CATEGORIES = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze # CATEGORIES = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze
CATEGORIES = ["Film Footage", "Video Footage", "Still Photograph"].freeze CATEGORIES = ["Film Footage", "Video Footage", "Still Photograph"].freeze
def minor? def second_guardian_present?
false guardian_2_first_name.present?
end end
def contact_person def contact_person

View File

@@ -15,7 +15,7 @@ class AppHost
end end
def domain_with_port def domain_with_port
[domain, port].compact.join(":") [domain, port].reject(&:blank?).compact.join(":")
end end
def protocol def protocol

View File

@@ -1,6 +1,10 @@
<%= errors_summary_for acquired_media_release %> <%= errors_summary_for acquired_media_release %>
<%= bootstrap_form_with model: model, local: true do |form| %> <%= bootstrap_form_with model: model, local: true do |form| %>
<%= field_set_tag content_tag(:span, t(".acquired_media_details.heading"), class: "h6 text-muted text-uppercase") do %> <%= field_set_tag content_tag(:span, t(".acquired_media_details.heading"), class: "h6 text-muted text-uppercase") do %>
<%= form.form_group :minor do %>
<%= form.check_box :minor, label: t("helpers.label.talent_release.minor"), data: { target: "[data-ujs-target=guardian-fields]", toggle: "collapse" } %>
<% end %>
<div class="form-row"> <div class="form-row">
<%= form.text_field :name, required: true, wrapper_class: "col-12" %> <%= form.text_field :name, required: true, wrapper_class: "col-12" %>
</div> </div>
@@ -9,6 +13,28 @@
<%= form.check_box :categories, { multiple: true, label: category }, category, false %> <%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %> <% end %>
<% end %> <% end %>
<div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<%= card_field_set_tag t(".guardian_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_first_name, required: acquired_media_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_last_name, required: acquired_media_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian" %>
<% end %>
<%= card_field_set_tag t(".guardian_2_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian_2" %>
<% end %>
</div>
<% end %> <% end %>
<hr> <hr>
@@ -19,6 +45,44 @@
<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/file_infos_dropzone", form: form, releasable: acquired_media_release %>
<div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<br>
<div class="text-left">
<p><%= t(".photos.guardian_photo.heading") %></p>
<div id="guardian-photo-preview" class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span>No photo yet</span>
</div>
</div>
<% if acquired_media_release.guardian_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("#guardian-photo-preview", "<%= url_for(acquired_media_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="d-inline-block">
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if acquired_media_release.guardian_photo.attached?%>
<%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, help: "PNG or JPG only", accept: acquired_media_release.class.face_photo_acceptable_content_types.join(",") %>
</div>
<p><%= t(".photos.guardian_2_photo.heading") %></p>
<div id="guardian-2-photo-preview" class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-2-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span>No photo yet</span>
</div>
</div>
<% if acquired_media_release.guardian_2_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("#guardian-2-photo-preview", "<%= url_for(acquired_media_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="d-inline-block">
<%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if acquired_media_release.guardian_2_photo.attached?%>
<%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, help: "PNG or JPG only", accept: acquired_media_release.class.face_photo_acceptable_content_types.join(",") %>
</div>
</div>
<hr>
</div>
<% end %> <% end %>
<hr> <hr>

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

@@ -118,8 +118,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(appearance talent 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 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" %>
</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" %>

View File

@@ -33,7 +33,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> <th></th>
</tr> </tr>
</thead> </thead>

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

@@ -13,6 +13,17 @@
<hr> <hr>
<% unless @contract_template.guardian_clause.blank? %>
<%= form.form_group :minor do %>
<%= form.check_box :minor, label: t("helpers.label.appearance_release.minor"), data: { behavior: "update-required-status", target: "[data-ujs-target=guardian-fields]", toggle: "collapse" } %>
<% end %>
<%= card_field_set_tag t(".guardian_clause.heading") do %>
<p><%= @contract_template.guardian_clause %></p>
<% end %>
<hr>
<% end %>
<%= card_field_set_tag t(".acquired_media_info.heading") do %> <%= card_field_set_tag t(".acquired_media_info.heading") do %>
<div class="form-row"> <div class="form-row">
<%= form.text_field :name, required: true, wrapper_class: "col-12" %> <%= form.text_field :name, required: true, wrapper_class: "col-12" %>
@@ -49,6 +60,91 @@
<hr> <hr>
<% unless @contract_template.guardian_clause.blank? %>
<div class="<%= class_string("collapse" => !@acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<%= card_field_set_tag t(".guardian_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_first_name, required: @acquired_media_release.minor?, wrapper_class: "col-sm-3", data: { required_tag: "guardian" } %>
<%= form.text_field :guardian_last_name, required: @acquired_media_release.minor?, wrapper_class: "col-sm-3", data: { required_tag: "guardian" } %>
<%= form.phone_field :guardian_phone, required: @acquired_media_release.minor?, wrapper_class: "col-sm-6", data: { required_tag: "guardian" } %>
<%= form.text_field :guardian_email, required: @acquired_media_release.minor?, wrapper_class: "col-sm-6", data: { required_tag: "guardian" } %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian", required: @acquired_media_release.minor?, data: { required_tag: "guardian" } %>
<% end %>
<hr>
<%= card_field_set_tag t(".guardian_photo.heading") do %>
<div class="alert alert-warning font-weight-bold"><%= t ".guardian_photo.instructions" %></div>
<div class="text-center">
<div class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span><%= t ".photo.no_photo" %></span>
</div>
</div>
<div class="d-inline-block text-left">
<% if @acquired_media_release.guardian_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@acquired_media_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="hidden-file-input">
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if @acquired_media_release.guardian_photo.attached? %>
<%= form.file_field :guardian_photo, required: @acquired_media_release.minor?, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @acquired_media_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
</div>
<%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-photo-input]" } %>
</div>
<p class="p-2 font-weight-bold">
<small class="text-muted"><%= t ".photo.warning" %></small>
</p>
</div>
<% end %>
<hr>
<%= card_field_set_tag t(".guardian_2_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian_2" %>
<% end %>
<hr>
<%= card_field_set_tag t(".guardian_2_photo.heading") do %>
<div class="alert alert-warning font-weight-bold"><%= t ".guardian_2_photo.instructions" %></div>
<div class="text-center">
<div class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-2-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span><%= t ".photo.no_photo" %></span>
</div>
</div>
<div class="d-inline-block text-left">
<% if @acquired_media_release.guardian_2_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@acquired_media_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="hidden-file-input">
<%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if @acquired_media_release.guardian_2_photo.attached? %>
<%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, accept: @acquired_media_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
</div>
<%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-2-photo-input]" } %>
</div>
<p class="p-2 font-weight-bold">
<small class="text-muted"><%= t ".photo.warning" %></small>
</p>
</div>
<% end %>
<hr>
</div>
<% end %>
<%= card_field_set_tag t(".signature.heading") do %> <%= card_field_set_tag t(".signature.heading") do %>
<%= render "shared/signature_fields", form: form, signature_legal_text: @contract_template.signature_legal_text %> <%= render "shared/signature_fields", form: form, signature_legal_text: @contract_template.signature_legal_text %>
<% end %> <% end %>

View File

@@ -0,0 +1,17 @@
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
# Rails.application.config.middleware.use OmniAuth::Builder do
# provider :microsoft_graph, ENV['AZURE_CLIENT_ID'], ENV['AZURE_CLIENT_SECRET'], scope: 'openid email profile User.Read'
# end

View File

@@ -46,6 +46,15 @@ en:
heading: 3 of 3 Contract & Exploitable Rights heading: 3 of 3 Contract & Exploitable Rights
files: files:
heading: 2 of 3 Files heading: 2 of 3 Files
guardian_2_info:
heading: Second Guardian Information (if company requires)
guardian_info:
heading: Guardian Information
photos:
guardian_2_photo:
heading: Second Guardian Photo
guardian_photo:
heading: Guardian Photo
index: index:
actions: actions:
new: Import Release new: Import Release
@@ -253,6 +262,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
@@ -436,6 +448,27 @@ en:
label: label:
acquired_media_release: acquired_media_release:
description: Description of property description: Description of property
guardian_2_address_city: Guardian 2 city
guardian_2_address_country: Guardian 2 country
guardian_2_address_state: Guardian 2 state
guardian_2_address_street1: Guardian 2 address
guardian_2_address_street2: Guardian 2 address (Line 2)
guardian_2_address_zip: Guardian 2 zip code
guardian_2_email: Guardian 2 email
guardian_2_first_name: Guardian 2 first name
guardian_2_last_name: Guardian 2 last name
guardian_2_phone: Guardian 2 phone
guardian_address_city: Guardian city
guardian_address_country: Guardian country
guardian_address_state: Guardian state
guardian_address_street1: Guardian address
guardian_address_street2: Guardian address (Line 2)
guardian_address_zip: Guardian zip code
guardian_email: Guardian email
guardian_first_name: Guardian first name
guardian_last_name: Guardian last name
guardian_phone: Guardian phone
minor: Is the person a minor?
name: Name of property name: Name of property
person_address: Address person_address: Address
person_address_city: City person_address_city: City
@@ -721,6 +754,8 @@ en:
acquired_media_release: acquired_media_release:
create: Import Release create: Import Release
update: Save Changes update: Save Changes
acquired_media_releases:
create: Import Release
appearance_release: appearance_release:
create: Import Release create: Import Release
update: Save Changes update: Save Changes
@@ -789,7 +824,6 @@ en:
empty: Location Releases will appear here empty: Location Releases will appear here
table_headers: table_headers:
address: Address address: Address
amendment_signed: Amendment
approved: Approved approved: Approved
name: Location Name name: Location Name
notes: Notes notes: Notes
@@ -1043,10 +1077,28 @@ en:
cancel: Cancel cancel: Cancel
files: files:
heading: File Information heading: File Information
guardian_2_info:
heading: Second Guardian Information (if company requires)
guardian_2_photo:
heading: Second Guardian Photo
instructions: >
Lastly, it's time for second guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
guardian_clause:
heading: Guardian Clause
guardian_info:
heading: Guardian Information
guardian_photo:
heading: Guardian Photo
instructions: >
Lastly, it's time for guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
legal: legal:
heading: Legal heading: Legal
personal_info: personal_info:
heading: Licensor/Owner Contact Information heading: Licensor/Owner Contact Information
photo:
no_photo: No photo yet
take_photo: Take Photo
warning: If your photo appears sideways, it will be autocorrected when you submit your release.
signature: signature:
heading: Signature heading: Signature
amendments: amendments:
@@ -1505,3 +1557,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

@@ -2,6 +2,18 @@ es:
acquired_media_releases: acquired_media_releases:
acquired_media_release: acquired_media_release:
no_media: No Media (ES) no_media: No Media (ES)
create:
notice: The acquired media release has been created (ES)
form:
guardian_2_info:
heading: Guardian Information (if company requires) [ES]
guardian_info:
heading: Guardian Information (ES)
photos:
guardian_2_photo:
heading: Second Guardian Photo
guardian_photo:
heading: Guardian Photo
index: index:
table_headers: table_headers:
file_infos_count: No. Files (ES) file_infos_count: No. Files (ES)
@@ -108,6 +120,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:
@@ -222,6 +237,29 @@ es:
guardian_clause: Leave blank if not required for this contract (ES) guardian_clause: Leave blank if not required for this contract (ES)
signature_legal_text: Leave blank if not required for this contract (ES) signature_legal_text: Leave blank if not required for this contract (ES)
label: label:
acquired_media_release:
guardian_2_address_city: Guardian 2 city (ES)
guardian_2_address_country: Guardian 2 country (ES)
guardian_2_address_state: Guardian 2 state (ES)
guardian_2_address_street1: Guardian 2 address (ES)
guardian_2_address_street2: Guardian 2 address (Line 2) (ES)
guardian_2_address_zip: Guardian 2 zip code (ES)
guardian_2_email: Guardian 2 email (ES)
guardian_2_first_name: Guardian 2 first name (ES)
guardian_2_last_name: Guardian 2 last name (ES)
guardian_2_phone: Guardian 2 phone (ES)
guardian_address_city: Guardian city (ES)
guardian_address_country: Guardian country (ES)
guardian_address_state: Guardian state (ES)
guardian_address_street1: Dirección del tutor legal
guardian_address_street2: Dirección del tutor legal (Línea 2)
guardian_address_zip: Guardian zip code (ES)
guardian_email: Guardian email (ES)
guardian_first_name: Guardian first name (ES)
guardian_last_name: Guardian last name (ES)
guardian_name: Nómbre del tutor legal
guardian_phone: Número de teléfono del tutor legal
minor: El firmante es un menor
appearance_release: appearance_release:
guardian_2_address_city: Guardian 2 city (ES) guardian_2_address_city: Guardian 2 city (ES)
guardian_2_address_country: Guardian 2 country (ES) guardian_2_address_country: Guardian 2 country (ES)
@@ -328,6 +366,8 @@ es:
person_name: Jane Doe person_name: Jane Doe
person_phone: 555-555-5555 person_phone: 555-555-5555
submit: submit:
acquired_media_releases:
create: Import Release (ES)
appearance_release: appearance_release:
create: Crear Autorización create: Crear Autorización
broadcast: broadcast:
@@ -346,7 +386,6 @@ es:
index: index:
table_headers: table_headers:
address: Address (ES) address: Address (ES)
amendment_signed: Amendment (ES)
notes: Notes (ES) notes: Notes (ES)
signed_at: Date Signed (ES) signed_at: Date Signed (ES)
tags: Tags (ES) tags: Tags (ES)
@@ -402,6 +441,26 @@ es:
signed_at: Date Signed (ES) signed_at: Date Signed (ES)
tags: Tags (ES) tags: Tags (ES)
public: public:
acquired_media_releases:
new:
guardian_2_info:
heading: Second Guardian Information (if company requires) [ES]
guardian_2_photo:
heading: Second Guardian Photo (ES)
instructions: >
(ES) Lastly, it's time for second guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese! (ES)
guardian_clause:
heading: Guardian Clause (ES)
guardian_info:
heading: Guardian Information (ES)
guardian_photo:
heading: Guardian Photo (ES)
instructions: >
(ES) Lastly, it's time for guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese! (ES)
photo:
no_photo: No photo yet (ES)
take_photo: Take Photo (ES)
warning: If your photo appears sideways, it will be autocorrected when you submit your release. (ES)
amendments: amendments:
create: create:
amendment_already_signed_message: Release amendment is already signed! (ES) amendment_already_signed_message: Release amendment is already signed! (ES)
@@ -574,3 +633,11 @@ 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:
alert:
not_authenticated: ""
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
@@ -99,7 +101,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]
end end
resources :directories, except: [:index] do resources :directories, except: [:index] do
member do member do

View File

@@ -0,0 +1,25 @@
class AddGuardiansFieldsToAcquiredMediaReleases < ActiveRecord::Migration[6.0]
def change
add_column :acquired_media_releases, :minor, :boolean, default: false
add_column :acquired_media_releases, :guardian_first_name, :string
add_column :acquired_media_releases, :guardian_last_name, :string
add_column :acquired_media_releases, :guardian_email, :string
add_column :acquired_media_releases, :guardian_phone, :string
add_column :acquired_media_releases, :guardian_address_street1, :string
add_column :acquired_media_releases, :guardian_address_street2, :string
add_column :acquired_media_releases, :guardian_address_city, :string
add_column :acquired_media_releases, :guardian_address_state, :string
add_column :acquired_media_releases, :guardian_address_zip, :string
add_column :acquired_media_releases, :guardian_address_country, :string
add_column :acquired_media_releases, :guardian_2_first_name, :string
add_column :acquired_media_releases, :guardian_2_last_name, :string
add_column :acquired_media_releases, :guardian_2_email, :string
add_column :acquired_media_releases, :guardian_2_phone, :string
add_column :acquired_media_releases, :guardian_2_address_street1, :string
add_column :acquired_media_releases, :guardian_2_address_street2, :string
add_column :acquired_media_releases, :guardian_2_address_city, :string
add_column :acquired_media_releases, :guardian_2_address_state, :string
add_column :acquired_media_releases, :guardian_2_address_zip, :string
add_column :acquired_media_releases, :guardian_2_address_country, :string
end
end

View File

@@ -0,0 +1,7 @@
class AddMicrosoftTokensToUsers < ActiveRecord::Migration[6.0]
def change
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,5 @@
class AddMicrosoftUserIdToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :microsoft_user_id, :string
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

@@ -161,7 +161,28 @@ CREATE TABLE public.acquired_media_releases (
signed_at timestamp without time zone, signed_at timestamp without time zone,
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,
minor boolean DEFAULT false,
guardian_first_name character varying,
guardian_last_name character varying,
guardian_email character varying,
guardian_phone character varying,
guardian_address_street1 character varying,
guardian_address_street2 character varying,
guardian_address_city character varying,
guardian_address_state character varying,
guardian_address_zip character varying,
guardian_address_country character varying,
guardian_2_first_name character varying,
guardian_2_last_name character varying,
guardian_2_email character varying,
guardian_2_phone character varying,
guardian_2_address_street1 character varying,
guardian_2_address_street2 character varying,
guardian_2_address_city character varying,
guardian_2_address_state character varying,
guardian_2_address_zip character varying,
guardian_2_address_country character varying
); );
@@ -541,7 +562,9 @@ CREATE TABLE public.broadcasts (
token character varying, token character varying,
streamer_status integer DEFAULT 0, streamer_status integer DEFAULT 0,
shoot_location_time_zone character varying DEFAULT 'UTC'::character varying, shoot_location_time_zone character varying DEFAULT 'UTC'::character varying,
full_live_stream_playback_uid character varying full_live_stream_playback_uid character varying,
conference_option character varying,
conference_join_url character varying
); );
@@ -1734,7 +1757,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_access_token character varying,
microsoft_refresh_token character varying,
microsoft_token_expires_at integer,
microsoft_user_id character varying
); );
@@ -3944,6 +3971,10 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200716105723'), ('20200716105723'),
('20200720051634'), ('20200720051634'),
('20200720131309'), ('20200720131309'),
('20200721140821'); ('20200721140821'),
('20200725231419'),
('20200810140331'),
('20200812161119'),
('20200817233053');

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

View File

@@ -131,16 +131,25 @@ RSpec.describe BroadcastsController, type: :controller do
expect(response.body).to have_xpath "//input[@readonly][@value='#{broadcast_url(broadcast.token)}']" expect(response.body).to have_xpath "//input[@readonly][@value='#{broadcast_url(broadcast.token)}']"
end end
it "displays zoom meeting button" do it "displays zoom meeting button for zoom conference option" do
get :show, params: { project_id: project.id, id: broadcast.id } get :show, params: { project_id: project.id, id: broadcast.id }
expect(response.body).to have_link("Video Conference", href: project_broadcast_zoom_meeting_url(project, broadcast)) expect(response.body).to have_content 'Zoom'
expect(response.body).to have_link("Video Conference", href: project_broadcast_conference_meeting_url(project, broadcast))
end
it "displays microsoft teams meeting button for MS Teams conference option" do
ms_teams_broadcast = create(:broadcast, :ms_teams_conference, project: project )
get :show, params: { project_id: project.id, id: ms_teams_broadcast.id }
expect(response.body).to have_content 'MS Teams'
expect(response.body).to have_link 'Video Conference', href: project_broadcast_conference_meeting_url(project, ms_teams_broadcast)
end end
it "assigns required variables" do it "assigns required variables" do
get :show, params: { project_id: project.id, id: broadcast.id } get :show, params: { project_id: project.id, id: broadcast.id }
expect(assigns(:conference_url)).to eq project_broadcast_zoom_meeting_url(project, broadcast) expect(assigns(:conference_url)).to eq project_broadcast_conference_meeting_url(project, broadcast)
expect(assigns(:broadcast)).to eq broadcast expect(assigns(:broadcast)).to eq broadcast
end end

View File

@@ -0,0 +1,76 @@
require 'rails_helper'
RSpec.describe ConferenceMeetingsController, type: :controller do
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
let(:broadcast) { create(:broadcast, name: "Broadcast", project: project) }
let(:ms_teams_broadcast) { create(:broadcast, :ms_teams_conference, project: project) }
let(:unknown_option_broadcast) { create(:broadcast, project: project, conference_option: 'google') }
let(:meeting_start_url) { "http://meeting_start_url" }
let(:meeting_hash) { HashWithIndifferentAccess.new(start_url: meeting_start_url) }
let(:user_create_response) { {"id" => "new_host_id"} }
let(:roles_assign_response) { {"ids" => ["new_host_id"]} }
let(:roles_list_response) { {"roles" => [{"name" => "directme-host"}]} }
before :each do
allow_any_instance_of(ZoomGateway).to receive(:find_meeting).and_return(meeting_hash)
allow_any_instance_of(ZoomGateway).to receive(:create_meeting).and_return("meeting_id")
allow_any_instance_of(ZoomGateway).to receive(:create_host).and_return("host_id")
allow(MuxLiveStream).to receive(:new).and_return OpenStruct.new(id: 'id', key: 'key', playback_id: 'playback_id')
end
describe "#show" do
before { sign_in user }
it "redirects to meeting start url with Zoom conference option" do
get :show, params: { project_id: project.id, broadcast_id: broadcast.id }
expect(response).to redirect_to(meeting_start_url)
end
it "redirects to the broadcast show page with alert if user is not authenticated via microsoft and tries to create MS Teams meeting" do
get :show, params: { project_id: project.id, broadcast_id: ms_teams_broadcast.id }
expect(response).to redirect_to project_broadcast_path(project, ms_teams_broadcast)
expect(flash.alert).to eq not_authenticated_alert
end
it "redirects to the broadcast show page with alert if user is authenticated via microsoft and tries to create MS Teams meeting but Graph API fails to create meeting" do
allow_any_instance_of(MicrosoftGraph).to receive(:create_teams_meeting).and_return(nil)
get :show, params: { project_id: project.id, broadcast_id: ms_teams_broadcast.id }
expect(response).to redirect_to project_broadcast_path(project, ms_teams_broadcast)
expect(flash.alert).to eq failed_to_join_alert
end
it "redirects to the broadcast show page with alert if conference option is not reckognized" do
get :show, params: { project_id: project.id, broadcast_id: unknown_option_broadcast.id }
expect(response).to redirect_to project_broadcast_path(project, unknown_option_broadcast)
expect(flash.alert).to eq unknown_conference_option_alert
end
it "redirects to meeting start url with MS Teams conference option" do
new_ms_teams_meeting = JSON.parse({
joinUrl: meeting_start_url
}.to_json)
allow_any_instance_of(MicrosoftGraph).to receive(:create_teams_meeting).and_return(new_ms_teams_meeting)
get :show, params: { project_id: project.id, broadcast_id: ms_teams_broadcast.id }
expect(response).to redirect_to(meeting_start_url)
end
end
private
def not_authenticated_alert
t 'conference_meetings.show.alerts.not_authenticated'
end
def failed_to_join_alert
t 'conference_meetings.show.alerts.failed_to_join'
end
def unknown_conference_option_alert
t 'conference_meetings.show.alerts.unknown_conference_option'
end
end

View File

@@ -1,30 +0,0 @@
require 'rails_helper'
RSpec.describe ZoomMeetingsController, type: :controller do
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
let(:broadcast) { create(:broadcast, name: "Broadcast", project: project) }
let(:meeting_start_url) { "http://meeting_start_url" }
let(:meeting_hash) { HashWithIndifferentAccess.new(start_url: meeting_start_url) }
let(:user_create_response) { {"id" => "new_host_id"} }
let(:roles_assign_response) { {"ids" => ["new_host_id"]} }
let(:roles_list_response) { {"roles" => [{"name" => "directme-host"}]} }
before :each do
allow_any_instance_of(ZoomGateway).to receive(:find_meeting).and_return(meeting_hash)
allow_any_instance_of(ZoomGateway).to receive(:create_meeting).and_return("meeting_id")
allow_any_instance_of(ZoomGateway).to receive(:create_host).and_return("host_id")
allow(MuxLiveStream).to receive(:new).and_return OpenStruct.new(id: 'id', key: 'key', playback_id: 'playback_id')
end
describe "#show" do
before { sign_in user }
it "redirects to meeting start url" do
get :show, params: { project_id: project.id, broadcast_id: broadcast.id }
expect(response).to redirect_to(meeting_start_url)
end
end
end

View File

@@ -18,6 +18,16 @@ FactoryBot.define do
end end
end end
trait :minor do
minor true
guardian_first_name "Guardian1"
guardian_last_name "First"
guardian_2_first_name "Guardian2"
guardian_2_last_name "Second"
guardian_phone "1111"
guardian_2_phone "2222"
end
factory :acquired_media_release_with_contract_template do factory :acquired_media_release_with_contract_template do
after(:build) do |acquired_media_release, _| after(:build) do |acquired_media_release, _|
acquired_media_release.contract_template = build(:acquired_media_release_contract_template) acquired_media_release.contract_template = build(:acquired_media_release_contract_template)

View File

@@ -2,11 +2,16 @@ FactoryBot.define do
factory :broadcast do factory :broadcast do
association :project association :project
name "My Live Stream" name "My Live Stream"
conference_option "zoom"
transient do transient do
skip_create_callback false skip_create_callback false
end end
trait :ms_teams_conference do
conference_option "ms_teams"
end
trait :with_stream do trait :with_stream do
stream_uid "mux_stream" stream_uid "mux_stream"
stream_key "mux_key" stream_key "mux_key"

View File

@@ -160,7 +160,7 @@ RSpec.feature 'User manages contract templates', type: :feature do
expect(content_disposition).to include('inline') expect(content_disposition).to include('inline')
expect(pdf_body).to have_content('PREVIEW ONLY') expect(pdf_body).to have_content('PREVIEW ONLY')
expect(pdf_body).to have_content('Acquired Media Release') expect(pdf_body).to have_content('Acquired Media Release')
expect(pdf_body).not_to have_content('Guardian') expect(pdf_body).to have_content('Guardian')
visit new_project_contract_template_path(project) visit new_project_contract_template_path(project)
select 'Location Release', from: 'Release type' select 'Location Release', from: 'Release type'

View File

@@ -12,7 +12,7 @@ feature "User managing acquired_media releases" do
expect(country_field_value).to eq "US" expect(country_field_value).to eq "US"
end end
scenario "creating a release", js: true do scenario "creating a release for an adult", js: true do
contract_template = create(:contract_template, project: project) contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template) visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template)
@@ -35,11 +35,121 @@ feature "User managing acquired_media releases" do
draw_signature file_fixture("signature.png"), "acquired_media_release_signature_base64" draw_signature file_fixture("signature.png"), "acquired_media_release_signature_base64"
end end
click_button "I have read and agree to the above" click_button submit_release_button
expect(AcquiredMediaRelease.last.categories).to include("Video Footage") expect(AcquiredMediaRelease.last.categories).to include("Video Footage")
expect(AcquiredMediaRelease.last.categories).to include("Still Photograph") expect(AcquiredMediaRelease.last.categories).to include("Still Photograph")
expect(page).to have_content("Your release was successfully submitted. Thank you.") expect(page).to have_content successful_submission_message
end
scenario "creating a release for a minor - guardian fields are required when minor checkbox is checked", js: true do
contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template)
all('input[data-required-tag="guardian"]').each do |field|
expect(field['required']).to eq 'false'
expect(field).not_to be_visible
end
page.check person_is_minor_checkbox
all('input[data-required-tag="guardian"]').each do |field|
expect(field['required']).to eq 'true'
expect(field).to be_visible
end
end
scenario 'creating a release for a minor', js: true do
project = create(:project, members: current_user, account: current_user.primary_account)
contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template)
expect(page).not_to have_content guardian_information_heading.upcase
expect(page).not_to have_content guardian_photo_heading.upcase
page.check person_is_minor_checkbox
expect(page).to have_content guardian_information_heading.upcase
expect(page).to have_content guardian_photo_heading.upcase
expect(page).to have_content guardian_email_field.titleize
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
fill_in acquried_media_description_field, with: "Description"
fill_in acquried_media_owner_first_name, with: "Jane"
fill_in acquried_media_owner_last_name, with: "Doe"
fill_in acquired_media_person_title, with: "Ms."
fill_in acquired_media_person_phone, with: "555-5555-5555"
fill_in acquired_media_person_email, with: "person@example.com"
fill_in acquired_media_person_fax, with: "FAX"
fill_in acquired_media_person_address_street_1, with: "Street 1"
fill_in acquired_media_person_address_city, with: "City"
fill_in acquired_media_person_address_state, with: "State"
fill_in acquired_media_release_person_address_zip, with: "ZIP"
fill_in guardian_first_name_field, with: 'Guardian'
fill_in guardian_last_name_field, with: 'Name'
fill_in guardian_phone_field, with: '001101'
fill_in guardian_email_field, with: 'valid@email.com'
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
fill_in_guardian_address_fields
draw_signature file_fixture("signature.png"), "acquired_media_release_signature_base64"
click_button submit_release_button
expect(page).to have_content(successful_submission_message)
end
scenario 'creating a release for a minor with two guardians', js: true do
project = create(:project, members: current_user, account: current_user.primary_account)
contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template)
expect(page).not_to have_content guardian_2_information_heading.upcase
expect(page).not_to have_content guardian_2_photo_heading.upcase
page.check person_is_minor_checkbox
expect(page).to have_content guardian_information_heading.upcase
expect(page).to have_content guardian_photo_heading.upcase
expect(page).to have_content guardian_email_field.titleize
expect(page).to have_content guardian_2_information_heading.upcase
expect(page).to have_content guardian_2_photo_heading.upcase
expect(page).to have_content guardian_2_phone_field.titleize
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
fill_in acquried_media_description_field, with: "Description"
fill_in acquried_media_owner_first_name, with: "Jane"
fill_in acquried_media_owner_last_name, with: "Doe"
fill_in acquired_media_person_title, with: "Ms."
fill_in acquired_media_person_phone, with: "555-5555-5555"
fill_in acquired_media_person_email, with: "person@example.com"
fill_in acquired_media_person_fax, with: "FAX"
fill_in acquired_media_person_address_street_1, with: "Street 1"
fill_in acquired_media_person_address_city, with: "City"
fill_in acquired_media_person_address_state, with: "State"
fill_in acquired_media_release_person_address_zip, with: "ZIP"
fill_in guardian_first_name_field, with: 'Guardian'
fill_in guardian_last_name_field, with: 'Name'
fill_in guardian_phone_field, with: '001101'
fill_in guardian_email_field, with: 'valid@email.com'
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
fill_in_guardian_address_fields
draw_signature file_fixture("signature.png"), "acquired_media_release_signature_base64"
fill_in guardian_2_first_name_field, with: 'Second'
fill_in guardian_2_last_name_field, with: 'Guardian'
fill_in guardian_2_phone_field, with: '999'
click_button submit_release_button
expect(page).to have_content(successful_submission_message)
expect(AcquiredMediaRelease.last.guardian_2_first_name).to eq 'Second'
end end
scenario "creating a release, if contract template contains signature legal language, it is shown" do scenario "creating a release, if contract template contains signature legal language, it is shown" do
@@ -51,6 +161,106 @@ feature "User managing acquired_media releases" do
end end
context "when signed in" do context "when signed in" do
before do
sign_in current_user
end
scenario "creating a release for an adult", js: true do
visit new_project_acquired_media_release_path(project)
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
attach_file contract_field, Rails.root.join(file_fixture("contract.pdf")), visible: false
click_button import_release_button
expect(page).to have_content successful_import_message
end
scenario "creating a release for a minor - guardian fields are required when minor checkbox is checked", js: true do
visit new_project_acquired_media_release_path(project)
all('input[data-required-tag="guardian"]').each do |field|
expect(field['required']).to eq 'false'
expect(field).not_to be_visible
end
page.check person_is_minor_checkbox
all('input[data-required-tag="guardian"]').each do |field|
expect(field['required']).to eq 'true'
expect(field).to be_visible
end
end
scenario "creating a release for a minor", js: true do
visit new_project_acquired_media_release_path(project)
expect(page).not_to have_content guardian_information_heading.upcase
expect(page).not_to have_content guardian_photo_heading
page.check person_is_minor_checkbox
expect(page).to have_content guardian_information_heading.upcase
expect(page).to have_content guardian_photo_heading
expect(page).to have_content guardian_email_field.titleize
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
attach_file contract_field, Rails.root.join(file_fixture("contract.pdf")), visible: false
fill_in guardian_first_name_field, with: 'Guardian'
fill_in guardian_last_name_field, with: 'Name'
fill_in guardian_phone_field, with: '001101'
fill_in guardian_email_field, with: 'valid@email.com'
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
fill_in_guardian_address_fields
click_button import_release_button
expect(page).to have_content successful_import_message
expect(AcquiredMediaRelease.last.guardian_first_name).to eq 'Guardian'
end
scenario "creating a release for a minor with two guardians", js: true do
visit new_project_acquired_media_release_path(project)
expect(page).not_to have_content guardian_2_information_heading.upcase
expect(page).not_to have_content guardian_2_photo_heading
page.check person_is_minor_checkbox
expect(page).to have_content guardian_information_heading.upcase
expect(page).to have_content guardian_photo_heading
expect(page).to have_content guardian_email_field.titleize
expect(page).to have_content guardian_2_information_heading.upcase
expect(page).to have_content guardian_2_photo_heading
expect(page).to have_content guardian_2_phone_field.titleize
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
attach_file contract_field, Rails.root.join(file_fixture("contract.pdf")), visible: false
fill_in guardian_first_name_field, with: 'Guardian'
fill_in guardian_last_name_field, with: 'Name'
fill_in guardian_phone_field, with: '001101'
fill_in guardian_email_field, with: 'valid@email.com'
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
fill_in_guardian_address_fields
fill_in guardian_2_first_name_field, with: 'Second'
fill_in guardian_2_last_name_field, with: 'Guardian'
fill_in guardian_2_phone_field, with: '999'
click_button import_release_button
expect(page).to have_content successful_import_message
expect(AcquiredMediaRelease.last.guardian_first_name).to eq 'Guardian'
expect(AcquiredMediaRelease.last.guardian_2_first_name).to eq 'Second'
end
scenario "creating, updating, destroying a release", js: true do scenario "creating, updating, destroying a release", js: true do
release_data = { release_data = {
name: "Test Acquired Media Release", name: "Test Acquired Media Release",
@@ -65,7 +275,7 @@ feature "User managing acquired_media releases" do
visit new_project_acquired_media_release_path(project) visit new_project_acquired_media_release_path(project)
by "attaching only a contract" do by "attaching only a contract" do
attach_file "acquired_media_release[contract]", Rails.root.join(file_fixture("contract.pdf")), visible: false attach_file contract_field, Rails.root.join(file_fixture("contract.pdf")), visible: false
click_button create_release_button click_button create_release_button
expect(page).to have_invalid_field(acquired_media_name_field) expect(page).to have_invalid_field(acquired_media_name_field)
@@ -117,7 +327,7 @@ feature "User managing acquired_media releases" do
end end
end end
scenario "viewing the contract PDF" do scenario "viewing the contract PDF for an adult" do
acquired_media_release = create(:acquired_media_release_with_contract_template, acquired_media_release = create(:acquired_media_release_with_contract_template,
:native, :native,
project: project, project: project,
@@ -176,6 +386,25 @@ feature "User managing acquired_media releases" do
expect(pdf_body).to have_content("Other files") expect(pdf_body).to have_content("Other files")
end end
scenario "viewing the contract PDF for a minor" do
acquired_media_release = create(:acquired_media_release_with_contract_template,
:native,
:minor,
project: project,
person_name: "Jane Doe")
visit project_acquired_media_releases_path(project)
click_link *view_release_pdf_link_for(acquired_media_release)
expect(content_type).to eq("application/pdf")
expect(pdf_body).to have_content acquired_media_release.guardian_first_name
expect(pdf_body).to have_content acquired_media_release.guardian_last_name
expect(pdf_body).to have_content acquired_media_release.guardian_2_first_name
expect(pdf_body).to have_content acquired_media_release.guardian_2_last_name
expect(pdf_body).to have_content acquired_media_release.guardian_phone
expect(pdf_body).to have_content acquired_media_release.guardian_2_phone
end
scenario "searching for a release", js: true do scenario "searching for a release", js: true do
collection1 = create(:acquired_media_release, name: "EDM Music", project: project) collection1 = create(:acquired_media_release, name: "EDM Music", project: project)
collection2 = create(:acquired_media_release, name: "Classical Music", project: project) collection2 = create(:acquired_media_release, name: "Classical Music", project: project)
@@ -508,4 +737,103 @@ feature "User managing acquired_media releases" do
def date_issued def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued' t 'contracts.for_office_use_only.description_labels.date_issued'
end end
def person_is_minor_checkbox
'acquired_media_release_minor'
end
def guardian_2_first_name_field
t 'helpers.label.acquired_media_release.guardian_2_first_name'
end
def guardian_2_last_name_field
t 'helpers.label.acquired_media_release.guardian_2_last_name'
end
def guardian_2_phone_field
t 'helpers.label.acquired_media_release.guardian_2_phone'
end
def guardian_first_name_field
t 'helpers.label.acquired_media_release.guardian_first_name'
end
def guardian_last_name_field
t 'helpers.label.acquired_media_release.guardian_last_name'
end
def guardian_phone_field
t 'helpers.label.acquired_media_release.guardian_phone'
end
def guardian_email_field
t 'helpers.label.acquired_media_release.guardian_email'
end
def guardian_address_street1_field
t('helpers.label.acquired_media_release.guardian_address_street1')
end
def guardian_address_city_field
t('helpers.label.acquired_media_release.guardian_address_city')
end
def guardian_address_state_field
t('helpers.label.acquired_media_release.guardian_address_state')
end
def guardian_address_zip_field
t('helpers.label.acquired_media_release.guardian_address_zip')
end
def guardian_photo_field
'acquired_media_release[guardian_photo]'
end
def guardian_2_photo_field
'acquired_media_release[guardian_2_photo]'
end
def fill_in_guardian_address_fields
fill_in guardian_address_street1_field, with: "124 Test Lane"
fill_in guardian_address_city_field, with: "New York"
fill_in guardian_address_state_field, with: "NY"
fill_in guardian_address_zip_field, with: '1000'
end
def submit_release_button
'I have read and agree to the above'
end
def successful_submission_message
'Your release was successfully submitted. Thank you.'
end
def guardian_information_heading
t 'public.acquired_media_releases.new.guardian_info.heading'
end
def guardian_photo_heading
t 'public.acquired_media_releases.new.guardian_photo.heading'
end
def guardian_2_information_heading
t 'public.acquired_media_releases.new.guardian_2_info.heading'
end
def guardian_2_photo_heading
t 'public.acquired_media_releases.new.guardian_2_photo.heading'
end
def contract_field
'acquired_media_release[contract]'
end
def import_release_button
t 'helpers.submit.acquired_media_releases.create'
end
def successful_import_message
t 'acquired_media_releases.create.notice'
end
end end

View File

@@ -24,6 +24,7 @@ feature 'User managing broadcasts' do
by 'filling out the form' do by 'filling out the form' do
fill_in broadcast_name_field, with: 'My Broadcast' fill_in broadcast_name_field, with: 'My Broadcast'
select_conference_option('Zoom')
select_time_zone("New Delhi") select_time_zone("New Delhi")
end end
@@ -267,6 +268,12 @@ feature 'User managing broadcasts' do
end end
end end
def select_conference_option(value)
if value.present?
select value, from: "broadcast[conference_option]"
end
end
def click_checkboxes def click_checkboxes
all('input[type="checkbox"]')[0].click all('input[type="checkbox"]')[0].click
all('input[type="checkbox"]')[1].click all('input[type="checkbox"]')[1].click

View File

@@ -127,14 +127,6 @@ feature "User managing location releases" do
sign_in current_user sign_in current_user
end end
scenario "listing all releases, table have correct headers", js:true do
ct = create(:contract_template, :with_amendment_clause, project: project)
create(:location_release, :native, project: project, contract_template: ct)
visit project_location_releases_path(project)
table_headers.each { |s| expect(page).to have_content s }
end
scenario "creating a release", js: true do scenario "creating a release", js: true do
visit new_project_location_release_path(project) visit new_project_location_release_path(project)
@@ -737,16 +729,4 @@ feature "User managing location releases" do
def amendment_signature_label def amendment_signature_label
t 'contracts.amendment_page.description_labels.amendment_signature' t 'contracts.amendment_page.description_labels.amendment_signature'
end end
def table_headers
[
t('location_releases.index.table_headers.approved'),
t('location_releases.index.table_headers.name'),
t('location_releases.index.table_headers.address'),
t('location_releases.index.table_headers.notes'),
t('location_releases.index.table_headers.tags'),
t('location_releases.index.table_headers.signed_at'),
t('location_releases.index.table_headers.amendment_signed')
]
end
end end