Compare commits

..

2 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
54 changed files with 1510 additions and 358 deletions

View File

@@ -32,3 +32,10 @@ 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
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
# Call "byebug" anywhere in the code to stop execution and get a debugger console
gem "byebug", "~> 11.0.1", platforms: [:mri, :mingw, :x64_mingw]

View File

@@ -220,6 +220,7 @@ GEM
activesupport (>= 4.2.0)
hashdiff (1.0.1)
hashery (2.1.2)
hashie (4.1.0)
hexapdf (0.9.3)
cmdparse (~> 3.0, >= 3.0.3)
geom2d (~> 0.2)
@@ -297,6 +298,7 @@ GEM
money (~> 6.13.2)
railties (>= 3.0)
msgpack (1.3.1)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
nio4r (2.5.2)
@@ -308,6 +310,21 @@ GEM
warden
oath-generators (1.0.1)
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)
parity (3.2.0)
parser (2.6.5.0)
@@ -552,6 +569,8 @@ DEPENDENCIES
mux_ruby!
oath (~> 1.1.0)
oath-generators (~> 1.0.1)
omniauth-oauth2 (~> 1.6)
omniauth-rails_csrf_protection (~> 0.1.2)
parity (~> 3.2.0)
pdf-reader (~> 2.1.0)
pdfkit (~> 0.8.2)

View File

@@ -4,7 +4,6 @@ require './lib/knock_monkeypatch'
class Api::UserTokenController < Knock::AuthTokenController
include Oath::ControllerHelpers
include RememberMe::Controller
skip_before_action :verify_authenticity_token
before_action :sign_in_user

View File

@@ -6,12 +6,9 @@ class ApprovalsController < ApplicationController
def create
@releasable.approve_by(current_user)
@releasable.approved_by_user_signature.attach(approved_by_user_signature_params) if signature_data.present?
if @releasable.save(context: :approval)
if @releasable.save
redirect_to [@project, "#{@releasable_param.name.pluralize}"], notice: t('.release_approved', release_type: @releasable.model_name.human)
else
render :new
end
end
@@ -28,21 +25,4 @@ class ApprovalsController < ApplicationController
def set_project
@project = @releasable.project
end
def releasable_params
params.require(releasable_param.name).permit(approved_by_user_signature: :data)
end
def signature_data
releasable_params.dig(:approved_by_user_signature, :data)
end
def approved_by_user_signature_params
{
data: signature_data,
filename: "approved_by_user_signature.png",
content_type: "image/png",
identify: false,
}
end
end

View File

@@ -75,7 +75,7 @@ class BroadcastsController < ApplicationController
end
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
def set_project
@@ -113,7 +113,7 @@ class BroadcastsController < ApplicationController
end
def conference_url_for(broadcast)
broadcast.video_conference_url_override || url_for([broadcast.project, broadcast, :zoom_meeting])
broadcast.video_conference_url_override || url_for([broadcast.project, broadcast, :conference_meeting])
end
def log_create_analytics

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

@@ -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

@@ -1,24 +1,15 @@
module Approvable
extend ActiveSupport::Concern
included do
include ActiveStorageSupport::SupportForBase64
has_one_base64_attached :approved_by_user_signature
# Requires signature when saving in the approval context
with_options on: :approval do
validates :approved_by_user_signature, attached: true
end
def approve_by(user)
return unless approved_at.nil?
self.approved_by_user_name = user.full_name
self.approved_by_user_email = user.email
self.approved_at = BigMediaTime.time_zone_now
self.approved_at = Time.zone.now
end
def approved?
self.approved_at.present?
end

View File

@@ -1,13 +1,9 @@
<div class="card shadow-sm">
<%= card_header text: t(".heading", release_type: @releasable_param.name.titleize), close_action_path: [@project, "#{@releasable_param.name.pluralize}"] %>
<div class="card-body">
<embed class="embeded-contract-preview mb-3" type="application/pdf" src="<%= url_for [@releasable, :contracts, format: "pdf"] %>" width="90%" height="1200" />
<embed class="embeded-contract-preview" type="application/pdf" src="<%= url_for [@releasable, :contracts, format: "pdf"] %>" width="90%" height="1200" />
<%= errors_summary_for @releasable %>
<%= bootstrap_form_with model: @releasable, method: :post, url: public_send("#{@releasable_param.name}_approvals_path", @releasable), local: true do |form| %>
<%= card_field_set_tag 'Signature' do %>
<%= render "shared/signature_fields", form: form, signature_field: 'approved_by_user_signature[data]' %>
<% end %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [@releasable.project, "#{@releasable_param.name.pluralize}"], class: "col-3 text-reset" %>
<div class="col-9">
@@ -16,4 +12,4 @@
</div>
<% end %>
</div>
</div>
</div>

View File

@@ -2,6 +2,7 @@
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= 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") %>
<div class="row align-items-center text-center mt-4">

View File

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

View File

@@ -10,10 +10,4 @@
<%= description_list_pair t('.description_labels.issued_to'), releasable.name %>
<%= description_list_pair t('.description_labels.issued_by'), releasable.approved_by_user_name %>
<%= description_list_pair t('.description_labels.date_issued'), releasable.approved_at %>
</dl>
<% if preview %>
<%= image_tag dummy_signature %>
<% elsif releasable.approved_by_user_signature.attached? %>
<%= image_tag releasable.approved_by_user_signature.variant(auto_orient: true, resize: "200x200") %>
<% end %>
</dl>

View File

@@ -16,10 +16,11 @@
<%= contract_template.guardian_clause %>
<% end %>
<%# if releasable.model_name.in? %w(MedicalRelease MiscRelease AppearanceRelease) %>
<% if releasable.respond_to?(:question_1_answer) %>
<div class="page">
<%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>
</div>
</div>
<% end %>
<div class="page">
@@ -46,7 +47,8 @@
<% end %>
<% end %>
<% if releasable.try(:approved?) %>
<% if releasable.respond_to?(:approved?) && releasable.approved? %>
<div class="page">
<%= render "contracts/for_office_use_only", releasable: releasable, preview: preview %>
</div>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
<head>
<title>ME Suite</title>
<title>MESuite.ai App</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
<head>
<title>ME Suite</title>
<title>MESuite.ai App</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

View File

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

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

@@ -1 +0,0 @@
Rails.application.config.session_store :cookie_store, key: '_easy_release_session', expire_after: 1.month

View File

@@ -275,6 +275,9 @@ en:
stream_multiple_cameras: Stream multiple cameras at one time
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
form:
labels:
conference_option: Conference Option
bulk_taggings:
new_bulk_tag_modal:
submit: Add
@@ -1642,3 +1645,9 @@ en:
edit: Edit
report: Report
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

@@ -131,6 +131,9 @@ es:
stream_multiple_cameras: Stream multiple cameras at one time
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
form:
labels:
conference_option: Conference Option (ES)
contract_templates:
blank_contracts:
create:
@@ -705,3 +708,9 @@ es:
production_elements_logs: Production Elements Logs, and more (ES)
reduces_labor_cost: Reduces labor costs (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
AVAILABLE_LOCALES_REGEX = /#{I18n.available_locales.join("|")}/.freeze
get 'auth/azure_ad/callback', to: 'callbacks#create'
concern :confirmable do
resources :video_release_confirmations, only: [:new, :create, :destroy]
end
@@ -100,7 +102,7 @@ Rails.application.routes.draw do
member do
delete :destroy_file
end
resource :zoom_meeting, only: [:show]
resource :conference_meeting, only: [:show]
resources :broadcast_recordings, only: :destroy
end
resources :directories, except: [:index] do

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

@@ -586,7 +586,9 @@ CREATE TABLE public.broadcasts (
stream_key_override character varying,
director_mode_video_embed text,
simulcast_uid character varying,
video_conference_url_override character varying
video_conference_url_override character varying,
conference_option character varying,
conference_join_url character varying
);
@@ -1804,7 +1806,11 @@ CREATE TABLE public.users (
remember_created_at timestamp without time zone,
first_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
);
@@ -4025,6 +4031,8 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200807190607'),
('20200811102720'),
('20200812060406'),
('20200819070738');
('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

View File

@@ -27,17 +27,10 @@ RSpec.describe ApprovalsController, type: :controller do
expect(MedicalRelease.last.approved?).to eq false
post :create, params: { medical_release_id: medical_release, medical_release: approvable_params }
post :create, params: { medical_release_id: medical_release }
expect(response).to redirect_to [project, :medical_releases]
expect(MedicalRelease.last.approved?).to eq true
end
end
private
def approvable_params
signature_base64 ||= Base64Image.from_image(file_fixture('signature.png')).data_uri
{ approved_by_user_signature: { data: signature_base64 } }
end
end

View File

@@ -157,16 +157,24 @@ RSpec.describe BroadcastsController, type: :controller do
expect(response.body).to have_xpath "//input[@readonly][@value='#{broadcast_url(broadcast.token)}']"
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 }
expect(response.body).to have_link("Video Conference", href: project_broadcast_zoom_meeting_url(project, broadcast))
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
it "assigns required variables" do
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
end

View File

@@ -0,0 +1,75 @@
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")
stub_mux_live_stream
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")
stub_mux_live_stream
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

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

View File

@@ -1,191 +0,0 @@
require 'rails_helper'
feature 'User approving releasables' do
shared_examples 'an approvable UI' do
let(:current_user) { create(:user, :associate) }
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
before :each do
sign_in current_user
end
shared_examples 'not authorized to review' do
it 'does not show the review action' do
visit polymorphic_path [project, subject.model_name.plural]
click_on manage_button
expect(page).not_to have_link(review_action, exact: true)
end
end
scenario 'approval status is indicating by a checkmark' do
approved_releasable = create("#{subject.model_name.singular}", approved_at: 1.day.ago, project: project)
visit polymorphic_path [project, subject.model_name.plural]
expect(page).not_to be_approved(subject)
expect(page).not_to be_approved(approved_releasable)
end
context 'as an account manager' do
let(:current_user) { create(:user, :account_manager) }
scenario 'approving a release', js: true do
visit polymorphic_path [project, subject.model_name.plural]
click_on manage_button
click_link review_action
expect(page).to have_content review_page_heading(subject.model_name)
expect(page).to have_content approve_button
expect(page).to have_content signature_field
click_on approve_button
expect(page).not_to have_content approved_notice(subject.model_name)
expect(page).to have_content 'is not attached'
by 'adding signature' do
draw_signature file_fixture('signature.png'), signature_data_field(subject.model_name)
click_on approve_button
expect(page).to have_content approved_notice(subject.model_name)
end
end
scenario 'viewing the contract PDF for an unapproved release' do
visit polymorphic_path [project, subject.model_name.plural]
click_on 'Manage'
click_link 'Download'
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only
end
scenario 'viewing the contract PDF of an approved release' do
approver = create(:user, email: 'big.doe@test.com', first_name: 'Big', last_name: 'Joe')
subject.approve_by(approver)
subject.save!
visit polymorphic_path([subject, :contracts], format: 'pdf')
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
end
context 'as a manager' do
let(:current_user) { create(:user, :manager) }
include_examples 'not authorized to review'
end
context 'as an associate' do
let(:current_user) { create(:user, :associate) }
include_examples 'not authorized to review'
end
private
def approve_button
t 'approvals.new.actions.approve'
end
def approved_notice(model_name)
t('approvals.create.release_approved', release_type: model_name.human)
end
def be_approved(releasable)
releasable_dom_id = "##{releasable.model_name.singular}_#{releasable.id}"
have_css("#{releasable_dom_id }i.fa.fa-check-circle.fa-2x", count: 1)
end
def manage_button
'Manage'
end
def review_action
'Review'
end
def review_page_heading(model_name)
t 'approvals.new.heading', release_type: model_name.human.titleize
end
def signature_field
'SIGNATURE'
end
def signature_data_field(model_name)
"#{model_name.singular}_approved_by_user_signature[data]"
end
def for_office_use_only
t('contracts.for_office_use_only.heading').upcase
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
end
context 'for an appearance release' do
subject { create(:appearance_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a talent release' do
subject { create(:talent_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a location release' do
subject { create(:location_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a material release' do
subject { create(:material_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a acquired media release' do
subject { create(:acquired_media_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a medical release' do
subject { create(:medical_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
context 'for a misc release' do
subject { create(:misc_release_with_contract_template, :native, project: project) }
it_behaves_like 'an approvable UI'
end
end

View File

@@ -444,9 +444,104 @@ feature "User managing acquired_media releases" do
end
context "when the user is account manager" do
let(:current_user) { create(:user, :account_manager) }
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:acquired_media_release_with_contract_template, :native, project: project)
visit project_acquired_media_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:acquired_media_release_with_contract_template, :native, project: project)
visit project_acquired_media_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:acquired_media_release_with_contract_template, :native, project: project)
visit project_acquired_media_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:acquired_media_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_acquired_media_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
acquired_media_release = create(:acquired_media_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
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(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
acquired_media_release = create(:acquired_media_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
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(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
end
context "when the user is project manager" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is not visible" do
create(:acquired_media_release_with_contract_template, project: project)
visit project_acquired_media_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
context "when the user is associate" do
@@ -608,6 +703,42 @@ feature "User managing acquired_media releases" do
'Some signature legal language'
end
def review_action
t 'acquired_media_releases.acquired_media_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Acquired Media Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
def person_is_minor_checkbox
'acquired_media_release_minor'
end

View File

@@ -687,9 +687,103 @@ feature 'User managing appearance releases' do
context "when the user is account manager" do
let(:current_user) { create(:user, :account_manager) }
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:appearance_release_with_contract_template, :native, project: project)
visit project_appearance_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:appearance_release_with_contract_template, :native, project: project)
visit project_appearance_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:appearance_release_with_contract_template, :native, project: project)
visit project_appearance_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:appearance_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_appearance_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
appearance_release = create(:appearance_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_appearance_releases_path(project)
click_link *view_release_pdf_link_for(appearance_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
appearance_release = create(:appearance_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_appearance_releases_path(project)
click_link *view_release_pdf_link_for(appearance_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
end
context "when the user is project manager" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is not visible" do
create(:appearance_release_with_contract_template, :native, project: project)
visit project_appearance_releases_path(project)
click_on manage_button
expect(page).not_to have_link(review_action, exact: true)
end
end
context 'when the user is associate' do
@@ -707,6 +801,15 @@ feature 'User managing appearance releases' do
click_on manage_button
expect(page).not_to have_link('Download', exact: true)
end
scenario "Review action in Manage menu is not visible" do
create(:appearance_release_with_contract_template, :native, project: project)
visit project_appearance_releases_path(project)
click_on manage_button
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -936,6 +1039,42 @@ feature 'User managing appearance releases' do
'Some signature legal language'
end
def review_action
t 'appearance_releases.appearance_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Appearance Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
def amendments_heading
t 'public.amendments.new.amendment.heading'
end

View File

@@ -25,6 +25,7 @@ feature 'User managing broadcasts' do
by 'filling out the form' do
fill_in broadcast_name_field, with: 'My Broadcast'
select_conference_option('Zoom')
select_time_zone("New Delhi")
end
@@ -352,5 +353,10 @@ feature 'User managing broadcasts' do
t 'broadcasts.file.actions.delete_file'
end
def select_conference_option(value)
if value.present?
select value, from: "broadcast[conference_option]"
end
end
end

View File

@@ -383,9 +383,104 @@ feature "User managing location releases" do
end
context "when the user is account manager" do
let(:current_user) { create(:user, :account_manager) }
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:location_release_with_contract_template, :native, project: project)
visit project_location_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:location_release_with_contract_template, :native, project: project)
visit project_location_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:location_release_with_contract_template, :native, project: project)
visit project_location_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:location_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_location_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
location_release = create(:location_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_location_releases_path(project)
click_link *view_release_pdf_link_for(location_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
location_release = create(:location_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_location_releases_path(project)
click_link *view_release_pdf_link_for(location_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
end
context "when the user is project manager" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is not visible" do
create(:location_release_with_contract_template, :native, project: project)
visit project_location_releases_path(project)
click_on manage_button
expect(page).not_to have_link(review_action, exact: true)
end
end
context "when the user is associate" do
@@ -403,6 +498,15 @@ feature "User managing location releases" do
click_on manage_button
expect(page).not_to have_link("Download", exact: true)
end
scenario "Review action in Manage menu is not visible" do
create(:location_release_with_contract_template, :native, project: project)
visit project_location_releases_path(project)
click_on manage_button
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -546,6 +650,42 @@ feature "User managing location releases" do
'Some signature legal language'
end
def review_action
t 'location_releases.location_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Location Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
def amendments_heading
t 'public.amendments.new.amendment.heading'
end

View File

@@ -421,9 +421,104 @@ feature "User managing material releases" do
end
context "when the user is account manager" do
let(:current_user) { create(:user, :account_manager) }
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:material_release_with_contract_template, :native, project: project)
visit project_material_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:material_release_with_contract_template, :native, project: project)
visit project_material_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:material_release_with_contract_template, :native, project: project)
visit project_material_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:material_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_material_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
material_release = create(:material_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_material_releases_path(project)
click_link *view_release_pdf_link_for(material_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
material_release = create(:material_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_material_releases_path(project)
click_link *view_release_pdf_link_for(material_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
end
context "when the user is project manager" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is not visible" do
create(:material_release_with_contract_template, :native, project: project)
visit project_material_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
context "when the user is associate" do
@@ -441,6 +536,15 @@ feature "User managing material releases" do
click_on "Manage"
expect(page).not_to have_link("Download", exact: true)
end
scenario "Review action in Manage menu is not visible" do
create(:material_release_with_contract_template, :native, project: project)
visit project_material_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -589,6 +693,42 @@ feature "User managing material releases" do
'Some signature legal language'
end
def review_action
t 'material_releases.material_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Material Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
def person_is_minor_checkbox
'material_release_minor'
end

View File

@@ -215,6 +215,15 @@ feature "User managing medical releases" do
expect(page).to have_link("Download", exact: true, count: 2)
end
scenario "Review action in Manage menu is visible" do
create(:medical_release_with_contract_template, :native, project: project)
create(:medical_release_with_contract_template, :non_native, project: project)
visit project_medical_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Downloading PDF of native medical release is possible" do
native_release = create(:medical_release_with_contract_template, :native, project: project)
@@ -224,6 +233,64 @@ feature "User managing medical releases" do
expect(content_type).to eq('application/pdf')
end
scenario "Reviewing release" do
create(:medical_release_with_contract_template, :native, project: project)
visit project_medical_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
medical_release = create(:medical_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_medical_releases_path(project)
click_link *view_release_pdf_link_for(medical_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
medical_release = create(:medical_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_medical_releases_path(project)
click_link *view_release_pdf_link_for(medical_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
scenario 'viewing contract PDF with medical questionnaire' do
contract_template = create(:medical_release_contract_template, project: project, questionnaire_legal_text: "Questionnaire legal text", question_1_text: "Question 1 text")
medical_release = create(:medical_release,
@@ -276,6 +343,15 @@ feature "User managing medical releases" do
expect(page).to have_link("Download", exact: true, count: 0)
end
scenario "Review action in Manage menu is not visible" do
create(:medical_release_with_contract_template, :native, project: project)
create(:medical_release_with_contract_template, :non_native, project: project)
visit project_medical_releases_path(project)
expect(page).not_to have_link(review_action, exact: true)
end
scenario "Downloading PDF of native medical release is not possible" do
native_release = create(:medical_release_with_contract_template, :native, project: project)
@@ -320,6 +396,15 @@ feature "User managing medical releases" do
expect(page).to have_link("Download", exact: true, count: 0)
end
scenario "Review action in Manage menu is not visible" do
create(:medical_release_with_contract_template, :native, project: project)
create(:medical_release_with_contract_template, :non_native, project: project)
visit project_medical_releases_path(project)
expect(page).not_to have_link(review_action, exact: true)
end
scenario "Downloading PDF of native medical release is not possible" do
native_release = create(:medical_release_with_contract_template, :native, project: project)
@@ -499,4 +584,40 @@ feature "User managing medical releases" do
def dummy_signature_legal_text
'Some signature legal language'
end
def review_action
t 'medical_releases.medical_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Medical Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
end

View File

@@ -79,6 +79,83 @@ feature "User managing misc releases" do
expect(content_type).to eq('application/pdf')
end
scenario "Review action in Manage menu is visible" do
create(:misc_release_with_contract_template, :native, project: project)
visit project_misc_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:misc_release_with_contract_template, :native, project: project)
visit project_misc_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:misc_release_with_contract_template, :native, project: project)
visit project_misc_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:misc_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_misc_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
misc_release = create(:misc_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_misc_releases_path(project)
click_link *view_release_pdf_link_for(misc_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
misc_release = create(:misc_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_misc_releases_path(project)
click_link *view_release_pdf_link_for(misc_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
scenario 'viewing the contract PDF' do
misc_release = create(:misc_release,
@@ -141,6 +218,14 @@ feature "User managing misc releases" do
expect(page).to have_link("Download", exact: true, count: 0)
end
scenario "Review action in Manage menu is not visible" do
create(:misc_release_with_contract_template, :native, project: project)
visit project_misc_releases_path(project)
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -215,4 +300,40 @@ feature "User managing misc releases" do
def view_release_pdf_link_for(release)
['Download', href: misc_release_contracts_path(release, format: 'pdf')]
end
def review_action
t 'misc_releases.misc_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Misc Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
end

View File

@@ -92,9 +92,39 @@ feature "User managing music releases" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:music_release_with_contract_template, project: project)
visit project_music_releases_path(project)
click_on "Manage"
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:music_release_with_contract_template, project: project)
visit project_music_releases_path(project)
click_on "Manage"
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
end
context "when the user is project manager" do
scenario "Review action in Manage menu is not visible" do
create(:music_release_with_contract_template, project: project)
sign_in current_user
visit project_music_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
context "when the user is associate" do
@@ -103,15 +133,24 @@ feature "User managing music releases" do
before do
sign_in current_user
end
scenario "should not show download" do
collection1 = create(:music_release, name: "EDM Music", project: project)
visit project_music_releases_path(project)
click_on "Manage"
expect(page).not_to have_link("Download", exact: true)
end
scenario "Review action in Manage menu is not visible" do
create(:music_release_with_contract_template, project: project)
visit project_music_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -177,4 +216,16 @@ feature "User managing music releases" do
select "Other", from: "Restriction"
fill_in "Describe other restrictions", with: "Test"
end
def review_action
t 'music_releases.music_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Music Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
end

View File

@@ -374,9 +374,104 @@ feature "User managing talent releases" do
end
context "when the user is account manager" do
let(:current_user) { create(:user, :account_manager) }
before do
sign_in current_user
end
scenario "Review action in Manage menu is visible" do
create(:talent_release_with_contract_template, :native, project: project)
visit project_talent_releases_path(project)
expect(page).to have_link(review_action, exact: true)
end
scenario "Reviewing release" do
create(:talent_release_with_contract_template, :native, project: project)
visit project_talent_releases_path(project)
click_link review_action
expect(page).to have_content review_page_heading
expect(page).to have_content approve_button
end
scenario "Approved releases have checkmark and non-approved releases don't have checkmarks" do
create(:talent_release_with_contract_template, :native, project: project)
visit project_talent_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 0)
create(:talent_release_with_contract_template, :native, project: project, approved_by_user_email: "some@email.com", approved_at: DateTime.now)
visit project_talent_releases_path(project)
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end
scenario 'When viewing the contract PDF of approved release there is page for office use only' do
talent_release = create(:talent_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe',
approved_by_user_name: "Big Joe",
approved_by_user_email: "some@email.com",
approved_at: DateTime.now)
sign_in(current_user)
visit project_talent_releases_path(project)
click_link *view_release_pdf_link_for(talent_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).to have_content for_office_use_only.upcase
expect(pdf_body).to have_content producer_label
expect(pdf_body).to have_content production_label
expect(pdf_body).to have_content issued_to_label
expect(pdf_body).to have_content issued_by_label
expect(pdf_body).to have_content date_issued
expect(pdf_body).to have_content 'Big Joe'
end
scenario 'When viewing the contract PDF of not approved release there is no page for office use only' do
talent_release = create(:talent_release_with_contract_template,
:native,
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe')
sign_in(current_user)
visit project_talent_releases_path(project)
click_link *view_release_pdf_link_for(talent_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_body).not_to have_content for_office_use_only.upcase
expect(pdf_body).not_to have_content producer_label
expect(pdf_body).not_to have_content production_label
expect(pdf_body).not_to have_content issued_to_label
expect(pdf_body).not_to have_content issued_by_label
expect(pdf_body).not_to have_content date_issued
expect(pdf_body).not_to have_content 'Big Joe'
end
end
context "when the user is project manager" do
before do
sign_in current_user
end
scenario "Review action in Manage menu is not visible" do
create(:talent_release_with_contract_template, :native, project: project)
visit project_talent_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
context "when the user is associate" do
@@ -394,6 +489,15 @@ feature "User managing talent releases" do
click_on "Manage"
expect(page).not_to have_link("Download", exact: true)
end
scenario "Review action in Manage menu is not visible" do
create(:talent_release_with_contract_template, :native, project: project)
visit project_talent_releases_path(project)
click_on "Manage"
expect(page).not_to have_link(review_action, exact: true)
end
end
private
@@ -575,4 +679,40 @@ feature "User managing talent releases" do
def dummy_signature_legal_text
'Some signature legal language'
end
def review_action
t 'talent_releases.talent_release.actions.review'
end
def review_page_heading
t 'approvals.new.heading', release_type: "Talent Release"
end
def approve_button
t 'approvals.new.actions.approve'
end
def for_office_use_only
t 'contracts.for_office_use_only.heading'
end
def producer_label
t 'contracts.for_office_use_only.description_labels.producer'
end
def production_label
t 'contracts.for_office_use_only.description_labels.production'
end
def issued_to_label
t 'contracts.for_office_use_only.description_labels.issued_to'
end
def issued_by_label
t 'contracts.for_office_use_only.description_labels.issued_by'
end
def date_issued
t 'contracts.for_office_use_only.description_labels.date_issued'
end
end

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe AcquiredMediaRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "an exploitable"
it_behaves_like "a notable"

View File

@@ -3,7 +3,6 @@
require 'rails_helper'
RSpec.describe AppearanceRelease do
it_behaves_like 'an approvable'
it_behaves_like 'a contractable'
it_behaves_like 'an exploitable'
it_behaves_like 'a notable'

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe LocationRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "an exploitable"
it_behaves_like "a notable"

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe MaterialRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "an exploitable"
it_behaves_like "a notable"

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe MedicalRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "a notable"
it_behaves_like "a photoable"

View File

@@ -1,7 +1,6 @@
require 'rails_helper'
RSpec.describe MiscRelease, type: :model do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "a notable"
it_behaves_like "a photoable"

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe MusicRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "an exploitable"
it_behaves_like "a notable"

View File

@@ -1,7 +1,6 @@
require "rails_helper"
RSpec.describe TalentRelease do
it_behaves_like 'an approvable'
it_behaves_like "a contractable"
it_behaves_like "an exploitable"
it_behaves_like "a notable"

View File

@@ -1,47 +0,0 @@
shared_examples_for "an approvable" do
it { is_expected.to respond_to(:approved_by_user_signature) }
describe "#approve_by" do
before do
allow(BigMediaTime).to receive(:time_zone_now).and_return(1.week.ago)
end
it "stores info about the approving user" do
user = double(full_name: "Jane Doe", email: "jane.doe@test.com")
subject.approve_by(user)
expect(subject.approved_by_user_name).to eq "Jane Doe"
expect(subject.approved_by_user_email).to eq "jane.doe@test.com"
expect(subject.approved_at).to eq BigMediaTime.time_zone_now
end
context "when approval has already been given" do
it "does not change the existing info" do
user1 = double(full_name: "Jane Doe", email: "jane.doe@test.com")
subject.approve_by(user1)
expect(subject.approved_by_user_name).to eq "Jane Doe"
expect(subject.approved_by_user_email).to eq "jane.doe@test.com"
expect(subject.approved_at).to eq BigMediaTime.time_zone_now
user2 = double(full_name: "John Doe", email: "john.doe@test.com")
subject.approve_by(user2)
expect(subject.approved_by_user_name).to eq "Jane Doe"
expect(subject.approved_by_user_email).to eq "jane.doe@test.com"
expect(subject.approved_at).to eq BigMediaTime.time_zone_now
end
end
end
describe "#approved?" do
it "indicates whether or not it has been approved" do
subject.approved_at = nil
expect(subject).not_to be_approved
subject.approved_at = 1.week.ago
expect(subject).to be_approved
end
end
end

View File

@@ -2,7 +2,7 @@ module SignatureHelper
def draw_signature(file, signature_field_id)
data_uri = ActionController::Base.helpers.escape_javascript(Base64Image.from_image(file).data_uri)
page.execute_script <<-JS
document.getElementById("#{signature_field_id}").value = "#{data_uri}";
$("##{signature_field_id}").val("#{data_uri}")
JS
end
end