Initial commit

This commit is contained in:
Senad Uka
2020-05-31 22:38:19 +02:00
commit 858fafc3c5
1280 changed files with 65918 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
class AccountAuthsController < ApplicationController
before_action :set_account_auth, only: [:update, :destroy]
def index
@account = Current.account
if params[:account_id]
@account = accounts.find(params[:account_id])
end
@members = account_auths.joins(:user).where(account: @account).order('role DESC, users.email ASC')
@account_auth = account_auths.new(user: current_user, account: @account, role: :account_manager)
end
def create
email = account_auths_create_params[:user_email]
account_id = account_auths_create_params[:account_id]
user = User.find_by(email: email)
if user.nil?
user = sign_up({ email: email, password: SecureRandom.alphanumeric })
@account_auth = build_account_auth({ user: user, account_id: account_id, role: :account_manager })
@account_auth.save!
UserMailer.welcome(@account_auth.user, @account_auth.account).deliver_later
else
@account_auth = build_account_auth({ user: user, account_id: account_id, role: :account_manager })
@account_auth.save!
UserMailer.existing_account(@account_auth.user, @account_auth.account).deliver_later
end
redirect_to account_auths_path({ account_id: @account_auth.account_id }), notice: t(".notice")
end
def update
AccountAuth.transaction do
if @account_auth.update(account_auth_update_params)
if @account_auth.account_manager?
@account_auth.user.project_memberships.where(project: @account_auth.account.projects).destroy_all
end
flash.notice = t(".notice")
else
flash.alert = t(".alert")
end
end
redirect_to account_auths_path
end
def destroy
ActiveRecord::Base.transaction do
ProjectMembership.where(user: @account_auth.user, project: @account_auth.account.projects).destroy_all
@account_auth.destroy
end
redirect_to account_auths_path, alert: t(".alert")
end
private
def build_account_auth(auth_params)
@account_auth = authorize account_auths.build(auth_params)
end
def account_auths_create_params
params.require(:account_auth).permit(:user_email, :account_id)
end
def account_auth_update_params
params.require(:account_auth).permit(:role)
end
def account_auths
policy_scope(AccountAuth)
end
def find_account_auth
authorize account_auths.find(params[:id])
end
def accounts
policy_scope(Account)
end
def set_account_auth
@account_auth = find_account_auth
end
end

View File

@@ -0,0 +1,13 @@
class AccountSessionsController < ApplicationController
def update
authorize :account_session, :update?
session[:active_account] = account_session_params[:account_id]
redirect_to signed_in_root_path
end
private
def account_session_params
params.require(:account_session).permit(:account_id)
end
end

View File

@@ -0,0 +1,56 @@
class AccountsController < ApplicationController
before_action :set_account, only: [:update]
skip_before_action :require_login, only: [:new, :create]
skip_after_action :verify_authorized, only: [:new, :create]
def new
end
def create
account = Account.create(account_params_for_create)
if account.valid?
user = sign_up(user_params)
if user.valid?
user.account_auths << AccountAuth.create(user: user, account: account, role: "account_manager")
if sign_in(user)
TrackAnalyticsJob.perform_later(user, user.primary_account, :track_guest_sign_up, user_agent: request.user_agent, user_ip: request.remote_ip)
SubmitHubspotFormJob.perform_later(user.email, account.name, i_m_interested_in: user.interested_product_name)
redirect_to signed_in_root_path
else
redirect_to new_session_path, alert: t(".notice")
end
else
redirect_to new_account_path, alert: t(".error")
end
else
redirect_to new_account_path, alert: t(".error")
end
end
def update
authorize @account
@account.update(account_params_for_update)
end
private
def set_account
@account = Current.account
end
def account_params_for_create
{ name: params[:user][:account_name], plan_uid: :me_suite }
end
def account_params_for_update
params.require(:account).permit(:logo)
end
def user_params
params.require(:user).except(:account_name).permit(:email, :password, :first_name, :last_name, :interested_product_name)
end
end

View File

@@ -0,0 +1,106 @@
class AcquiredMediaReleasesController < ApplicationController
include ProjectContext, AcquiredMediaReleaseContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_acquired_media_release, only: [:edit, :update, :destroy]
include ProjectLayout
def index
@acquired_media_releases = filtered_acquired_media_releases.order_by_recent.paginate(page: params[:page])
end
def new
@acquired_media_release = build_acquired_media_release
end
def create
@acquired_media_release = build_acquired_media_release(acquired_media_release_params)
if @acquired_media_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@acquired_media_release)
redirect_to [@project, :acquired_media_releases], notice: t(".notice")
else
render :new
end
end
def edit
@project = @acquired_media_release.project
end
def update
@project = @acquired_media_release.project
if @acquired_media_release.update(acquired_media_release_params)
redirect_to [@project, :acquired_media_releases], notice: t(".notice")
else
render :edit
end
end
def destroy
@project = @acquired_media_release.project
@acquired_media_release.destroy
redirect_to [@project, :acquired_media_releases], alert: t(".alert")
end
private
def acquired_media_releases
if @project
policy_scope(@project.acquired_media_releases)
else
policy_scope(AcquiredMediaRelease)
end
end
def acquired_media_release_params
params.require(:acquired_media_release).permit(
:name,
:territory,
:term,
:person_name,
:person_phone,
:person_email,
:person_company,
:person_title,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
:contract,
: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
def build_acquired_media_release(attrs = {})
authorize @project.acquired_media_releases.build(attrs)
end
def filtered_acquired_media_releases
results = acquired_media_releases
if params[:query].present?
results = results.search(params[:query])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AcquiredMediaRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,73 @@
class Admin::AccountsController < Admin::ApplicationController
before_action :set_account, only: [:show, :edit, :update]
def index
@accounts = filtered_accounts.order_by_name.paginate(page: params[:page])
end
def new
@account = build_account
end
def create
@account = build_account(account_params)
if @account.save
redirect_to account_auths_path({ account_id: @account.id }), notice: t(".notice")
else
render :new
end
end
def show
@videos = filtered_account_videos.order(created_at: :desc, project_id: :desc).paginate(page: params[:page])
end
def edit
end
def update
if @account.update(account_params)
redirect_to admin_accounts_path, notice: t(".notice")
else
render :edit
end
end
private
def set_account
@account = find_account
end
def find_account
authorize accounts.find_by(slug: params[:id])
end
def accounts
policy_scope(Account)
end
def build_account(params = {})
authorize accounts.new(params)
end
def account_params
params.require(:account).permit(:name, :plan_uid)
end
def filtered_accounts
if params[:query].present?
accounts.search(params[:query])
else
accounts
end
end
def filtered_account_videos
if params[:query].present?
@account.videos.search(params[:query])
else
@account.videos
end
end
end

View File

@@ -0,0 +1,18 @@
class Admin::ApplicationController < ActionController::Base
include Oath::ControllerHelpers # Methods for authentication
include Pundit # Methods for authorization
before_action :require_login
include SetCurrentRequestDetails
before_action :require_admin_login
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
private
def require_admin_login
if !Current.user.admin?
redirect_to signed_in_root_url, alert: "You are not authorized to access this"
end
end
end

View File

@@ -0,0 +1,33 @@
class Admin::MasqueradesController < Admin::ApplicationController
before_action :set_user, only: [:create]
skip_before_action :require_admin_login, only: [:destroy]
def create
authorize :masquerade, :create?
session[:admin_id] = current_user.id
sign_in @user
redirect_to signed_in_root_path
end
def destroy
authorize :masquerade, :destroy?
sign_in User.find session[:admin_id]
session.delete(:admin_id)
session.delete(:active_account)
redirect_to admin_users_path
end
private
def set_user
@user = find_user
end
def users
policy_scope User
end
def find_user
authorize users.find(params[:user_id])
end
end

View File

@@ -0,0 +1,90 @@
class Admin::UsersController < Admin::ApplicationController
before_action :set_user, only: [:edit, :update]
def index
@users = filtered_users.order("email")
end
def new
@user = build_user
@accounts = accounts
end
def create
auth_params = user_create_params.slice(:account_id, :role)
@user = authorize sign_up(user_create_params.except(:account_id, :role))
if @user.valid?
account = accounts.find(auth_params[:account_id])
@user.account_auths << AccountAuth.create(user: @user, account: account, role: auth_params[:role])
UserMailer.welcome(@user, account).deliver_later
redirect_to admin_users_path, notice: t(".notice")
else
@accounts = accounts
render :new
end
end
def edit
@accounts = accounts
end
def update
set_user_password
if @user.update(user_update_params.except(:password))
redirect_to admin_users_path, notice: t(".notice")
else
@accounts = accounts
render :edit
end
end
def destroy
@user = authorize User.find(params[:id])
@user.destroy
redirect_to admin_users_path, alert: t(".alert")
end
private
def set_user
@user = find_user
end
def accounts
policy_scope Account
end
def users
policy_scope User
end
def find_user
authorize users.find(params[:id])
end
def build_user(params = {})
authorize users.new(params)
end
def user_create_params
params.require(:user).permit(:email, :password, :admin, :account_id, :role)
end
def user_update_params
params.require(:user).permit(:email, :admin, :password)
end
def set_user_password
if user_update_params[:password].present?
Oath::Services::PasswordReset.new(@user, user_update_params[:password]).perform
end
end
def filtered_users
params[:query].present? ? users.search(params[:query]) : users
end
end

View File

@@ -0,0 +1,11 @@
class Api::AcquiredMediaReleasesController < Api::ReleasesController
deserializable_resource :acquired_media_release, only: [:create, :update]
def model_name
"acquired_media_release"
end
def attributes_for_index
[:name]
end
end

View File

@@ -0,0 +1,48 @@
class Api::ApiController < ActionController::Base
skip_before_action :verify_authenticity_token
include Knock::Authenticable
include Pundit
rescue_from Exception, :with => :return_error
before_action :authenticate_user
before_action do
Current.user = current_user if current_user.present?
end
def pundit_user
UserContext.new(Current.user, Current.account)
end
# Catch exception and return JSON-formatted error
def return_error(exception)
raise exception if Rails.env.test?
logger.error "==Handled======="
logger.error exception.message
logger.error exception.backtrace.join("\n")
logger.error "==Handled======="
case exception.class
when ActiveRecord::RecordNotFound
@status = 404
@message = 'Record not found'
when ActiveRecord::RecordInvalid
@status = 422
@message = 'Record invalid'
when ArgumentError
@status = 400
@message = 'Argument Error'
else
@status = 500
@message = 'Internal Error'
end
# for some reason render json_errors is not working
# simulating JSON API support
render json: {
errors: [{
status: @status.to_s,
title: @message
}]
}
end
end

View File

@@ -0,0 +1,23 @@
class Api::AppearanceReleasesController < Api::ReleasesController
deserializable_resource :appearance_release, only: [:create]
def model_name
"appearance_release"
end
def attributes_for_index
[:person_name]
end
def handle_attachments(release, _)
photo = release_create_params[:person_photo]
photo[:io] = StringIO.new(Base64.decode64(photo[:io]))
release.person_photo.attach(io: photo[:io], filename: photo[:filename])
guardian_photo = release_create_params[:guardian_photo]
if guardian_photo
guardian_photo[:io] = StringIO.new(Base64.decode64(guardian_photo[:io]))
release.guardian_photo.attach(io: guardian_photo[:io], filename: guardian_photo[:filename])
end
end
end

View File

@@ -0,0 +1,55 @@
# frozen_string_literal: true
class Api::BroadcastsController < Api::ApiController
deserializable_resource :broadcast, only: [:update]
include ProjectContext
before_action :set_project
before_action :set_broadcast, only: [:show, :update]
def index
render jsonapi: broadcasts, class: { Broadcast: SerializableBroadcast }
end
def show
render jsonapi:
@broadcast,
class: {
Broadcast: SerializableBroadcast,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment
},
include: [:files]
end
def update
file_params.each do |file|
file[:io] = StringIO.new(Base64.decode64(file[:io]))
@broadcast.files.attach(io: file[:io], filename: file[:filename])
end
@broadcast.save!
render jsonapi:
@broadcast,
class: {
Broadcast: SerializableBroadcast,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment
},
include: [:files]
end
private
def file_params
broadcast_params = params.require(:broadcast).permit!
broadcast_params[:files]
end
def broadcasts
policy_scope(@project.broadcasts.where(status: %w[created idle]))
end
def set_broadcast
@broadcast = authorize policy_scope(@project.broadcasts).find(params[:id])
end
end

View File

@@ -0,0 +1,63 @@
class Api::ContractTemplatesController < Api::ApiController
include ProjectContext
before_action :set_project, only: [:index]
before_action :set_contract_template, only: [:show]
def index
render jsonapi: contract_templates, class: { "ContractTemplate": index_serializable }
end
def show
handle_response(@contract_template)
end
def handle_response(contract_template, status = :ok)
mapping = {
"ContractTemplate": show_serializable,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment,
}
render jsonapi: contract_template,
status: status,
class: mapping
end
def attributes_for_index
[:name]
end
def index_serializable
name = "contract_template"
attributes_to_send = attributes_for_index
Class.new(JSONAPI::Serializable::Resource) do
type name
attributes_to_send.each do |attr|
attribute attr.to_sym
end
end
end
def show_serializable
name = "contract_template"
Class.new(JSONAPI::Serializable::Resource) do
type name
ContractTemplate.new.attributes.keys.each do |attr|
attribute attr.to_sym
end
end
end
private
def contract_templates
date = Date.parse(params.fetch(:updated_since, Date.new.to_s))
policy_scope(ContractTemplate.where(project_id: @project.id, updated_at: date..Float::INFINITY))
end
def set_contract_template
@contract_template = ContractTemplate.find(params[:id])
end
end

View File

@@ -0,0 +1,11 @@
class Api::LocationReleasesController < Api::ReleasesController
deserializable_resource :location_release, only: [:create, :update]
def model_name
"location_release"
end
def attributes_for_index
[:name]
end
end

View File

@@ -0,0 +1,11 @@
class Api::MaterialReleasesController < Api::ReleasesController
deserializable_resource :material_release, only: [:create, :update]
def model_name
"material_release"
end
def attributes_for_index
[:name]
end
end

View File

@@ -0,0 +1,35 @@
class Api::NotesController < Api::ApiController
before_action :set_release
deserializable_resource :note, only: [:create]
def index
render jsonapi: @release.notes, class: { Note: SerializableNote }
end
def create
note = @release.notes.new(note_create_params)
note.user_id = current_user.id
note.email = current_user.email
note.save!
render jsonapi: note, class: { Note: SerializableNote }, status: :created
end
private
def model_name
request.path.match(/(\w+_releases)/).captures.first.singularize
end
def model_constant
model_name.camelize.constantize
end
def set_release
@release = authorize model_constant.find(params["#{model_name}_id"])
end
def note_create_params
parameters = params.require(:note).permit!
parameters.slice(:content)
end
end

View File

@@ -0,0 +1,5 @@
class Api::ProfilesController < Api::ApiController
def show
render jsonapi: current_user
end
end

View File

@@ -0,0 +1,6 @@
class Api::ProjectsController < Api::ApiController
def index
projects = Current.user.accessible_projects_for(Current.account)
render jsonapi: projects
end
end

View File

@@ -0,0 +1,182 @@
class Api::ReleasesController < Api::ApiController
include ProjectContext
include CreateReleasableJobs
before_action :set_project, only: [:index]
before_action :set_release, only: [:show, :update]
before_action :set_template_and_project, only: [:create]
def index
render jsonapi: releases, class: { "#{model_name.camelize}": index_serializable }
end
def show
handle_response(@release)
end
def create
params_without_photo = release_create_params.except(:photos, :person_photo)
release = filtered_releases.new(params_without_photo)
release.project_id = @project.id
release.contract_template_id = @contract_template.id
handle_attachments(release, release_create_params[:photos])
release.save!(context: :native)
log_create_analytics
after_create(release)
handle_response(release, :created)
end
def update
if model_name == "acquired_media_release"
authorize @release, :update_file_infos?
@release.attributes = release_create_params
@release.save!
else
authorize @release, :update_photos?
handle_attachments(@release, release_create_params[:photos])
@release.save!
end
handle_response(@release)
end
def handle_response(release, status = :ok)
if model_name == "acquired_media_release"
mapping = {
"#{model_name.camelize}": SerializableAcquiredMediaRelease,
FileInfo: SerializableFileInfo
}
render jsonapi: release,
status: status,
class: mapping,
include: [:file_infos]
else
mapping = {
"#{model_name.camelize}": show_serializable,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment,
}
render jsonapi: release,
status: status,
class: mapping,
include: [:photos, :guardian_photos]
end
end
def model_name
raise "Please specify model name underscored and lowercase e.g. appearance_release"
end
def model_constant
model_name.camelize.constantize
end
def attributes_for_index
raise "Please specify attributes for index"
end
def index_serializable
name = model_name
attributes_to_send = attributes_for_index
Class.new(JSONAPI::Serializable::Resource) do
type name
attributes_to_send.each do |attr|
attribute attr.to_sym
end
end
end
def show_serializable
name = model_name
constant = model_constant
Class.new(JSONAPI::Serializable::Resource) do
type name
constant.new.attributes.keys.each do |attr|
attribute attr.to_sym
end
if ["appearance_release", "talent_release"].include?(name)
has_many :guardian_photos do
data do
[@object.guardian_photo.try(:attachment)].compact
end
meta do
{ count: @object.try(:guardian_photo).try(:attached?) ? 1 : 0 }
end
end
end
unless name == "acquired_media_release"
has_many :photos do
if name == "appearance_release"
data do
[@object.photo.attachment]
end
end
meta do
{ count: @object.photos.size }
end
end
end
end
end
def create_deserializable
constant = model_constant
Class.new(JSONAPI::Deserializable::Resource) do
constant.new.attributes.keys.except(:created_at, :updated_at, :id, :user_id).each do |attr|
attribute attr.to_sym
end
end
end
def handle_attachments(release, params_photos)
photos = params_photos || []
photos.each do |photo|
photo[:io] = StringIO.new(Base64.decode64(photo[:io]))
release.photos.attach(io: photo[:io], filename: photo[:filename])
end
end
private
def releases
date = Date.parse(params.fetch(:updated_since, Date.new.to_s))
table = model_constant.table_name
policy_scope(model_constant.where(["#{table}.project_id = ? and #{table}.updated_at >= ?", @project.id, date]))
end
def set_release
@release = model_constant.find(params[:id])
end
def set_template_and_project
@contract_template = ContractTemplate.find(params[:contract_template_id])
@project = @contract_template.project
end
def filtered_releases
if @project.present?
policy_scope(@project.public_send(model_name.pluralize))
else
releases
end
end
def release_create_params
parameters = params.require(model_name).permit!
keys = model_constant.new.attributes.keys + [:guardian_photo, :person_photo, :photos, :signature, :signature_base64, :file_infos_attributes]
parameters[:signature_base64] = parameters[:signature]
parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature)
parameters
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_native_release, release_type: model_constant.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip, application: :ios)
end
end

View File

@@ -0,0 +1,78 @@
# frozen_string_literal: true
class Api::SyncController < Api::ApiController
def index
accessible_projects = current_user.accessible_projects_for(Current.account)
@accounts = filter(current_user.accounts)
@projects = filter(Project).all
@contract_templates = filter(ContractTemplate.where(project: accessible_projects)).all
@acquired_media_releases = (AcquiredMediaRelease.where(project: accessible_projects))
@appearance_releases = (AppearanceRelease.where(project: accessible_projects))
@location_releases = (LocationRelease.where(project: accessible_projects))
@material_releases = (MaterialRelease.where(project: accessible_projects))
@talent_releases = (TalentRelease.where(project: accessible_projects))
@notes = notes_query(Note.where(notable: @appearance_releases + @location_releases + @material_releases + @talent_releases + @acquired_media_releases ))
render json: {
data: {
accounts: @accounts,
projects: @projects,
contract_templates: @contract_templates,
acquired_media_releases: releases_query(@acquired_media_releases),
appearance_releases: releases_query(@appearance_releases),
location_releases: releases_query(@location_releases),
material_releases: releases_query(@material_releases),
talent_releases: releases_query(@talent_releases),
notes: @notes
}
}
end
private
def releases_query(release)
filter(release).all.map { |release| release_json(release) }
end
def notes_query(notes)
filter(notes).all.map do |note|
json = note.as_json
json[:attributes][:email] = note.email
json
end
end
def release_json(release)
json = release.as_json
unless release.model_name.to_s == "AcquiredMediaRelease"
json[:attributes][:photos] = release.photos.map do |photo|
build_photo_object photo
end
end
if release.respond_to?(:guardian_photo)
photo = release.guardian_photo
json[:attributes][:guardian_photo] = photo.attached? ? build_photo_object(photo) : nil
end
json
end
def filter(relation)
policy_scope(relation)
end
def build_photo_object(photo)
{
id: photo.id.to_s,
type: 'active_storage_attachment',
attributes: {
filename: photo.filename.to_s,
content_type: photo.content_type,
url: Rails.application.routes.url_helpers.rails_blob_url(photo, host: AppHost.new.domain_with_port),
thumbnail_url: Rails.application.routes.url_helpers.rails_representation_url(photo.variant(resize: '150x150'), host: AppHost.new.domain_with_port)
}
}
end
end

View File

@@ -0,0 +1,21 @@
class Api::TalentReleasesController < Api::ReleasesController
deserializable_resource :talent_release, only: [:create, :update]
def model_name
"talent_release"
end
def attributes_for_index
[:person_name]
end
def handle_attachments(release, _)
super
guardian_photo = release_create_params[:guardian_photo]
if guardian_photo
guardian_photo[:io] = StringIO.new(Base64.decode64(guardian_photo[:io]))
release.guardian_photo.attach(io: guardian_photo[:io], filename: guardian_photo[:filename])
end
end
end

View File

@@ -0,0 +1,36 @@
class Api::UserTokenController < Knock::AuthTokenController
skip_before_action :verify_authenticity_token
rescue_from Exception, :with => :return_error
# Catch exception and return JSON-formatted error
def return_error(exception)
logger.error "==Handled======="
logger.error exception.message
logger.error exception.backtrace.join("\n")
logger.error "==Handled======="
case exception
when ActiveRecord::RecordNotFound
@status = 404
@message = 'Record not found'
when ActiveRecord::RecordInvalid
@status = 422
@message = 'Record invalid'
when ArgumentError
@status = 400
@message = 'Argument Error'
else
@status = 500
@message = 'Internal Error'
end
# for some reason render json_errors is not working
# simulating JSON API support
render json: {
errors: [{
status: @status.to_s,
title: @message
}]
}
end
end

View File

@@ -0,0 +1,89 @@
# frozen_string_literal: true
class AppearanceReleaseImportsController < ApplicationController
include AppearanceReleaseContext
include ProjectContext
include CreateReleasableJobs
before_action :set_project, only: [:create]
include ProjectLayout
def create
authorize AppearanceRelease
@failed_files = []
attachments = appearance_release_params
if attachments.nil?
alert_message = t 'appearance_releases.create.no_attachments'
else
attachments.each do |attachment|
create_imported_appearance_release attachment
end
end
unless @failed_files.empty?
alert_message = t 'appearance_releases.create.failed_import'
alert_message += '<br><ul>'
@failed_files.each { |file_name| alert_message += "<li>#{file_name}</li>" }
alert_message += '</ul>'
end
redirect_to [@project, :appearance_releases], alert: alert_message
end
private
def appearance_releases
if @project
policy_scope(@project.appearance_releases)
else
super
end
end
def appearance_release_params
params.require(:attachments)
end
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
def create_imported_appearance_release(attachment)
blob = ActiveStorage::Blob.find_signed(attachment)
return if blob.nil?
extension = blob.filename.extension_with_delimiter
unless AppearanceRelease.acceptable_import_file_extensions.include? extension
blob.purge
@failed_files << blob.filename
return
end
random_contract_no = AppearanceRelease.random_contract_number.to_s
appearance_release_params = {
person_last_name: random_contract_no
}
if blob.image?
appearance_release_params[:person_photo] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_headshot_name')
elsif extension == '.pdf'
appearance_release_params[:contract] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_contract_name')
end
appearance_release = build_appearance_release(appearance_release_params)
if appearance_release.save(context: :non_native)
log_create_analytics
after_create appearance_release
else
@failed_files << blob.filename
end
end
end

View File

@@ -0,0 +1,100 @@
class AppearanceReleasesController < ApplicationController
include ProjectContext, AppearanceReleaseContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_appearance_release, only: [:edit, :update, :destroy]
include ProjectLayout
def index
@appearance_releases = filtered_appearance_releases.order_by_recent.paginate(page: params[:page])
end
def new
@appearance_release = build_appearance_release
end
def create
@appearance_release = build_appearance_release(appearance_release_params)
if @appearance_release.save(context: :non_native)
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@appearance_release)
redirect_to [@project, :appearance_releases], notice: "The release has been imported. #{link_to_import_another}"
else
render :new
end
end
def edit
@project = @appearance_release.project
end
def update
@project = @appearance_release.project
@appearance_release.attributes = appearance_release_params
if @appearance_release.save(context: :non_native)
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
redirect_to [@project, :appearance_releases], notice: "The release has been updated"
else
render :edit
end
end
def destroy
@project = @appearance_release.project
if @appearance_release.destroy
AddHeadshotCollectionUidToProjectJob.perform_later(@appearance_release.project)
redirect_to [@project, :appearance_releases], alert: "The release has been deleted"
end
end
private
def appearance_releases
if @project
policy_scope(@project.appearance_releases)
else
super
end
end
def filtered_appearance_releases
results = case params[:type_filter]
when 'complete'
appearance_releases.complete
when 'incomplete'
appearance_releases.incomplete
else
appearance_releases
end
results = results.search(params[:query]) if params[:query].present?
results
end
def appearance_release_params
params.require(:appearance_release).permit(:contract, :guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text, :person_date_of_birth,
:restriction_id, :restriction_text)
end
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
end
def link_to_import_another
view_context.link_to "Import Another", [:new, @project, :appearance_release]
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,70 @@
class ApplicationController < ActionController::Base
include Oath::ControllerHelpers # Methods for authentication
include Pundit # Methods for authorization
include RememberMe::Controller
before_action :disable_browser_page_caching
before_action :set_locale
before_action :require_login
before_action :set_raven_context
after_action :verify_authorized, except: :index
after_action :verify_policy_scoped, only: :index
include SetCurrentRequestDetails
before_action :redirect_accountless
private
def require_login
if !masquerading? && remembered_user = remember("user")
sign_in(remembered_user)
end
super
end
def redirect_accountless
if Current.user && Current.account.nil?
redirect_to accountless_user_path
end
end
def signed_in_as_admin?
signed_in? && current_user.admin?
end
helper_method :signed_in_as_admin?
# Ensure that all url helpers include the current locale
def default_url_options
super.merge(locale: I18n.locale) # Use merge to avoid clobbering any options set during config
end
# Set the locale for the current request
def set_locale
I18n.locale = params[:locale] || request.env["rack.locale"] || I18n.default_locale
end
# Run authorization against Current.user which will ensure it works in async jobs and channels as well
# All authorization depends on the Current.account as users will have a different role for each
def pundit_user
UserContext.new(Current.user, Current.account)
end
# Set the context for Sentry exception handling service
def set_raven_context
account_id = (session[:active_account] || try(:current_user).try(:accounts).try(:first))
Raven.user_context(id: current_user.id, account_id: account_id) if signed_in?
Raven.extra_context(params: params.to_unsafe_h, url: request.url)
end
def disable_browser_page_caching
response.headers["Cache-Control"] = "no-cache, no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
end
def masquerading?
session[:admin_id].present?
end
helper_method :masquerading?
end

View File

@@ -0,0 +1,34 @@
class AudioReportsController < ApplicationController
def show
report = build_report(params[:type])
respond_to do |format|
format.xlsx { send_data(report.to_xls, download_attributes_xls(report)) }
end
end
private
def video
authorize policy_scope(Video).find(params[:video_id])
end
def build_report(type)
case type
when "big"
authorize ExcelReports::AudioReports::BrayInnovationGroupMusicCueReport.new(video)
when "nat_geo"
authorize ExcelReports::AudioReports::NatGeoMusicCueSheet.new(video)
when "nat_geo-original"
authorize ExcelReports::AudioReports::NatGeoOriginalMusicLog.new(video)
else
authorize ExcelReports::AudioReports::DiscoveryMusicCueReport.new(video)
end
end
def download_attributes_xls(report)
{
filename: report.filename,
type: Mime[:xlsx]
}
end
end

View File

@@ -0,0 +1,58 @@
class BookmarksController < ApplicationController
before_action :set_video, except: [:destroy, :edit, :update]
before_action :set_bookmark, only: [:destroy, :edit, :update]
def new
@bookmark = @video.bookmarks.build(bookmark_params)
end
def create
@bookmark = @video.bookmarks.build(bookmark_params)
@bookmark.save
@bookmarks = @video.bookmarks
end
def edit
end
def update
@video = @bookmark.video
@bookmark.update(bookmark_params)
@bookmarks = @video.bookmarks
end
def destroy
@video = @bookmark.video
@bookmark.destroy
@bookmarks = @video.bookmarks
end
private
def bookmark_params
params.require(:bookmark).permit(:notes, :time_elapsed, :category)
end
def bookmarks
if @video
policy_scope(@video.bookmarks)
else
policy_scope(Bookmark)
end
end
def videos
policy_scope(Video)
end
def set_bookmark
@bookmark = authorize bookmarks.find(params[:id])
end
def set_video
@video = authorize videos.find(params[:video_id])
end
end

View File

@@ -0,0 +1,109 @@
class BroadcastsController < ApplicationController
layout "project"
before_action :set_project
before_action :build_broadcast, only: [:new, :create]
before_action :set_broadcast, only: [:show, :destroy, :update]
before_action :set_multi_view_broadcasts, only: [:show]
def index
@broadcasts = filtered_broadcasts.order_by_recent.paginate(page: params[:page])
end
def new
end
def create
@broadcast.attributes = broadcast_params
if @broadcast.save
log_create_analytics
redirect_to [@project, :broadcasts], notice: t(".notice")
else
render :new
end
end
def update
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab] })
BroadcastsChannel.file_upload_updates(@broadcast, @files, pagination_content)
end
def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page])
render layout: 'application'
end
def destroy
if @broadcast.destroy
redirect_to [@project, :broadcasts], alert: t(".alert")
else
redirect_to [@project, :broadcasts], alert: t(".api_error")
end
end
private
def broadcast_params
params.require(:broadcast).permit(:name, files: [])
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_broadcast
@broadcast = authorize policy_scope(Broadcast).find(params[:id])
end
def build_broadcast
@broadcast = authorize @project.broadcasts.build
end
def broadcasts
authorize policy_scope(@project.broadcasts)
end
def set_multi_view_broadcasts
authorized_broadcasts = authorize policy_scope(Broadcast).where(id: params[:multi_view_ids]).order_by_recent
@multi_view_broadcasts = authorized_broadcasts.map { |b| MultiViewBroadcast.new(b, params[:multi_view_ids]) }
end
def filtered_broadcasts
results = broadcasts
if params[:query].present?
results = results.search(params[:query])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_live_stream, user_agent: request.user_agent, user_ip: request.remote_ip)
end
class MultiViewBroadcast
include Rails.application.routes.url_helpers
delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_ids)
@broadcast = broadcast
@multi_view_ids = multi_view_ids
end
def url
project_broadcast_path(@broadcast.project, @broadcast, multi_view_ids: @multi_view_ids, locale: I18n.locale)
end
def uid
id
end
end
end

View File

@@ -0,0 +1,40 @@
class BulkTaggingsController < ApplicationController
before_action :set_project
before_action :set_releasables
before_action :authorize_bulk_taggings, only: [:new, :create]
def new
@releasable_ids = releasable_params[:ids]
end
def create
@releasables.each do |releasable|
releasable.tag_list.add(params[:name])
releasable.save
end
all_releasables
end
private
def releasable_params
{ type: params[:releasable_name].classify.constantize, ids: JSON.parse(params[:releasable_ids]) }
end
def set_releasables
@releasables = releasable_params[:type].where(id: releasable_params[:ids])
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def authorize_bulk_taggings
authorize @releasables.first.tags
end
def all_releasables
@all_releasables = policy_scope(releasable_params[:type].where(project: @project)).order_by_recent.paginate(page: params[:page])
end
end

View File

View File

@@ -0,0 +1,13 @@
module AcquiredMediaReleaseContext
extend ActiveSupport::Concern
def acquired_media_releases
policy_scope(AcquiredMediaRelease)
end
def set_acquired_media_release
acquired_media_release_id = params[:acquired_media_release_id] || params[:id]
@acquired_media_release = authorize acquired_media_releases.find(acquired_media_release_id)
end
end

View File

@@ -0,0 +1,13 @@
module AppearanceReleaseContext
extend ActiveSupport::Concern
def appearance_releases
policy_scope(AppearanceRelease)
end
def set_appearance_release
appearance_release_id = params[:appearance_release_id] || params[:id]
@appearance_release = authorize appearance_releases.find(appearance_release_id)
end
end

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
module CreateReleasableJobs
extend ActiveSupport::Concern
def after_create(releasable)
if headshots?(releasable)
AddHeadshotCollectionUidToProjectJob.perform_later(releasable.project)
end
SetTagsForReleasableJob.perform_later(releasable)
if releasable.contract_template.present?
AttachContractToReleasableJob.perform_later(releasable)
end
end
private
def headshots?(releasable)
[AppearanceRelease, TalentRelease].include?(releasable.class)
end
end

View File

@@ -0,0 +1,13 @@
module LocationReleaseContext
extend ActiveSupport::Concern
def location_releases
policy_scope(LocationRelease)
end
def set_location_release
location_release_id = params[:location_release_id] || params[:id]
@location_release = authorize location_releases.find(location_release_id)
end
end

View File

@@ -0,0 +1,13 @@
module MusicReleaseContext
extend ActiveSupport::Concern
def music_releases
policy_scope(MusicRelease)
end
def set_music_release
music_release_id = params[:music_release_id] || params[:id]
@music_release = authorize music_releases.find(music_release_id)
end
end

View File

@@ -0,0 +1,13 @@
module ProjectContext
extend ActiveSupport::Concern
def projects
policy_scope(Project)
end
def set_project
project_id = params[:project_id]
@project = projects.find(project_id)
end
end

View File

@@ -0,0 +1,15 @@
module ProjectLayout
extend ActiveSupport::Concern
included do
layout "project"
breadcrumb -> { t("shared.files") }, -> { project_for_layout }, match: :exact
breadcrumb -> { controller_name.titleize }, -> { [project_for_layout, controller_name] }, match: :exact
breadcrumb -> { action_name.titleize }, :url_for, only: [:new, :edit]
def project_for_layout
@project || instance_variable_get("@#{controller_name.singularize}").project
end
end
end

View File

@@ -0,0 +1,10 @@
module SetCurrentRequestDetails
extend ActiveSupport::Concern
included do
before_action do
Current.user = current_user if signed_in?
Current.account = Account.find(session[:active_account]) if session[:active_account]
end
end
end

View File

@@ -0,0 +1,13 @@
module TalentReleaseContext
extend ActiveSupport::Concern
def talent_releases
policy_scope(TalentRelease)
end
def set_talent_release
talent_release_id = params[:talent_release_id] || params[:id]
@talent_release = authorize talent_releases.find(talent_release_id)
end
end

View File

@@ -0,0 +1,34 @@
class ContractDownloadsController < ApplicationController
include ProjectContext
before_action :set_project, only: [:index, :create]
include ProjectLayout
def create
authorize policy_scope(Download).create
fetch_releases
download = @project.downloads.create!(release_type: params[:release_type])
other_downloads_in_progress = @project.downloads.unfinished_desc_order.offset(1)
if other_downloads_in_progress.any?
in_progress_downloads_details = render_to_string "_other_pending_downloads", locals: { downloads: other_downloads_in_progress, release_type: params[:release_type] }, :layout => false
ProjectsChannel.broadcast_download_generation_update(download, in_progress_downloads_details)
else
ProjectsChannel.broadcast_download_generation_update(download, I18n.t("contract_downloads.download.pending", release_type: params[:release_type].titleize))
end
GenerateContractsZipJob.perform_later(@project, download, params[:release_type], @releases.ids)
end
private
def fetch_releases
@releases = policy_scope(@project.public_send(releases))
end
def releases
params[:release_type].constantize.model_name.plural
end
end

View File

@@ -0,0 +1,69 @@
# frozen_string_literal: true
class ContractTemplates::BlankContractsController < ApplicationController
before_action :set_contract_template
def show
send_file contract.to_pdf, download_attributes
end
def new
authorize BlankContract
render 'blank_contracts/new'
end
def create
if number_of_copies_valid?
send_file contract.to_pdf, download_attributes
else
authorize BlankContract
redirect_back fallback_location: [:new, @contract_template, :blank_contracts], notice: t('.number_of_copies_invalid_notice')
end
end
private
def number_of_copies_valid?
number_of_copies = params[:number_of_copies].to_i
number_of_copies.positive?
rescue StandardError
false
end
def contract_templates
policy_scope(ContractTemplate)
end
def set_contract_template
@contract_template = contract_templates.find(params[:contract_template_id])
end
def releasable
create_releasable_instance
end
def create_releasable_instance
template_release_type = @contract_template[:release_type]
releasable = "#{template_release_type}_release".classify.safe_constantize.new
releasable.contract_template = @contract_template
releasable.project_id = @contract_template.project_id
releasable
end
def contract
authorize BlankContract.new(releasable, params[:number_of_copies])
end
def download_attributes
{
disposition: 'inline',
filename: contract.filename,
type: 'application/pdf'
}
end
def render_sample_html
# NOTE: For development purposes, this contract renders with the current locale, not the locale of the release itself
render contract.render_attributes
end
end

View File

@@ -0,0 +1,28 @@
class ContractTemplates::QrCodesController < ApplicationController
before_action :set_contract_template
def show
send_file qr_code.to_png, download_attributes
end
private
def contract_templates
policy_scope(ContractTemplate)
end
def set_contract_template
@contract_template = contract_templates.find(params[:contract_template_id])
end
def qr_code
authorize QrCode.build_from_contract_template(@contract_template)
end
def download_attributes
{
filename: qr_code.filename,
type: "image/png",
}
end
end

View File

@@ -0,0 +1,74 @@
# frozen_string_literal: true
class ContractTemplatesController < ApplicationController
include ProjectContext
layout 'project'
before_action :set_project, except: [:destroy]
before_action :set_contract_template, only: [:destroy]
def index
@contract_templates = contract_templates.non_archived.order_by_name.paginate(page: params[:page])
end
def new
@contract_template = build_contract_template
end
def create
@contract_template = build_contract_template(contract_template_params)
if params[:commit] == 'preview'
ctp = ContractTemplatePreview.new(@contract_template)
releasable_instance = ctp.build_releasable
contract = Contract.new releasable_instance, true
send_file contract.to_pdf, download_attributes
elsif @contract_template.save
redirect_to [@project, :contract_templates], notice: t('.notice')
else
@release_type = contract_template_params[:release_type]
render :new
end
end
def destroy
@contract_template.archive
redirect_to [@contract_template.project, :contract_templates], alert: t('.archived_notice')
end
private
def set_contract_template
@contract_template = authorize contract_templates.find(params[:id])
end
def contract_templates
if @project
policy_scope(@project.contract_templates)
else
policy_scope(ContractTemplate)
end
end
def build_contract_template(attrs = {})
authorize contract_templates.build(attrs)
end
def contract_template_params
params
.require(:contract_template)
.permit(:name, :release_type, :body, :guardian_clause, :fee,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text)
end
def download_attributes
{
disposition: 'inline',
filename: 'contract-preview.pdf',
type: 'application/pdf'
}
end
end

View File

@@ -0,0 +1,55 @@
class ContractsController < ApplicationController
def show
respond_to do |format|
format.pdf { send_contract_pdf }
if Rails.env.development?
format.html { render_sample_html }
end
end
end
private
def releases
if @project
policy_scope(@project.public_send(releasable_param.name.pluralize))
else
policy_scope(releasable_param.type)
end
end
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def releasable
authorize releases.find(releasable_param.id)
end
def contract
authorize Contract.new(releasable)
end
def download_attributes
{
disposition: "inline",
filename: contract.filename,
type: "application/pdf",
}
end
def render_sample_html
# NOTE: For development purposes, this contract renders with the current locale, not the locale of the release itself
render contract.render_attributes
end
def send_contract_pdf
# Native release contracts must be generated on-the-fly; non-native releases have a contract attachment
if releasable.native?
send_file contract.to_pdf, download_attributes
else
redirect_to releasable.contract.service_url
end
end
end

View File

@@ -0,0 +1,89 @@
class DirectoriesController < ApplicationController
before_action :set_project
before_action :build_directory, only: [:new, :create]
before_action :set_directory, except: [:new, :create]
layout "project"
breadcrumb -> { t("shared.files") }, -> { @project }, match: :exact
breadcrumb -> { @directory.name.titleize }, -> { [@project, @directory] }, match: :exact, except: [:new, :create]
def new
end
def create
@directory.attributes = directory_params_with_user
if @directory.save
log_create_analytics
redirect_to [@project, @directory], notice: "The folder has been created"
else
render :new
end
end
def show
@files = filtered_files.paginate(page: params[:page])
end
def edit
end
def update
if @directory.update(directory_params)
redirect_to [@project, @directory], notice: t(".notice")
else
render :edit
end
end
def destroy
@directory.destroy
redirect_to @project, alert: t(".alert")
end
def new_file
end
def destroy_file
file = ActiveStorage::Attachment.find(params[:file_id])
file.purge
redirect_to [@project, @directory], alert: t(".alert")
end
private
def filtered_files
results = @directory.files
if params[:query].present?
results = @directory.search_files(params[:query])
end
results
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_directory
@directory = authorize policy_scope(Directory).find(params[:id])
end
def build_directory
@directory = authorize @project.directories.build
end
def directory_params_with_user
directory_params.merge(user: current_user)
end
def directory_params
params.require(:directory).permit(:name, :category, :permissions, files: [])
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_custom_folder, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,43 @@
class DownloadsController < ApplicationController
include ProjectContext
before_action :set_project, only: [:index, :destroy]
before_action :set_download, only: [:destroy]
include ProjectLayout
def index
@downloads = filtered_downloads.paginate(page: params[:page])
end
def destroy
authorize @download
@project = @download.project
if @download.destroy
redirect_to [@project, :downloads], alert: "The download has been deleted"
end
end
def project_for_layout
@project || @download.project
end
private
def downloads
authorize policy_scope(@project.downloads)
end
def downloads_desc_order
downloads.order("created_at DESC")
end
def filtered_downloads
params[:query].present? ? downloads_desc_order.search(params[:query]) : downloads_desc_order
end
def set_download
@download = policy_scope(@project.downloads).find(params[:id])
end
end

View File

@@ -0,0 +1,44 @@
class FileInfosController < ApplicationController
before_action :set_releasable
layout "project"
breadcrumb -> { t("shared.files") }, -> { @releasable.project }, match: :exact
breadcrumb -> { @releasable.model_name.plural.titleize }, -> { [@releasable.project, @releasable.model_name.plural] }, match: :exact
breadcrumb -> { t(".heading") }, :url_for
def edit
@project = @releasable.project
end
def update
@project = @releasable.project
if @releasable.update(releasable_params)
SetTagsForReleasableJob.perform_later(@releasable)
redirect_to [@project, @releasable.model_name.plural], notice: t(".notice")
else
render :edit
end
end
private
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def set_releasable
@releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :"#{action_name}_file_infos?"
end
def releasable_params
params.fetch(releasable_param.name, {}).permit(
file_infos_attributes: [
:filename,
:content_type,
:byte_size
],
)
end
end

View File

@@ -0,0 +1,30 @@
class GraphicReportsController < ApplicationController
def show
report = build_report(params[:type])
respond_to do |format|
format.xlsx { send_data(report.to_xls, download_attributes_xls(report)) }
end
end
private
def video
authorize policy_scope(Video).find(params[:video_id])
end
def build_report(type)
case type
when "nat_geo"
authorize ExcelReports::GraphicReports::NatGeoTextGraphicsLog.new(video)
else
authorize ExcelReports::GraphicReports::DiscoveryGfxCueList.new(video)
end
end
def download_attributes_xls(report)
{
filename: report.filename,
type: Mime[:xlsx]
}
end
end

View File

@@ -0,0 +1,31 @@
class IssuesAndConcernsReportsController < ApplicationController
def show
respond_to do |format|
format.xlsx { send_issues_and_concerns_report_xls }
end
end
private
def videos
policy_scope(Video)
end
def video
authorize videos.find(params[:video_id])
end
def issues_and_concerns_report
authorize ExcelReports::IssuesAndConcernsReports::IssuesAndConcernsReport.new(video)
end
def send_issues_and_concerns_report_xls
send_data(
issues_and_concerns_report.to_xls,
{
filename: issues_and_concerns_report.filename,
type: Mime[:xlsx]
}
)
end
end

View File

@@ -0,0 +1,23 @@
class LocationReleases::PhotosController < ApplicationController
include LocationReleaseContext
before_action :set_location_release
def edit
end
def update
if @location_release.update(location_release_params)
SetTagsForReleasableJob.perform_later(@location_release)
redirect_to @location_release.project, notice: t(".notice")
else
render :new
end
end
private
def location_release_params
params.require(:location_release).permit(photos: [])
end
end

View File

@@ -0,0 +1,96 @@
class LocationReleasesController < ApplicationController
include ProjectContext, LocationReleaseContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_location_release, only: [:edit, :update, :destroy]
include ProjectLayout
def index
@location_releases = filtered_location_releases.order_by_recent.paginate(page: params[:page])
end
def new
@location_release = build_location_release
end
def create
@location_release = build_location_release(location_release_params)
if @location_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@location_release)
redirect_to [@project, :location_releases], notice: t(".notice")
else
render :new
end
end
def edit
@project = @location_release.project
end
def update
@project = @location_release.project
if @location_release.update(location_release_params)
redirect_to [@project, :location_releases], notice: t(".notice")
else
render :edit
end
end
def destroy
@project = @location_release.project
@location_release.destroy
redirect_to [@project, :location_releases], alert: t(".alert")
end
private
def location_releases
if @project
policy_scope(@project.location_releases)
else
policy_scope(LocationRelease)
end
end
def location_release_params
params.require(:location_release).permit(
:name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country,
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:contract, { photos: [] },
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
:filming_started_on, :filming_ended_on
)
end
def build_location_release(attrs = {})
authorize @project.location_releases.build(attrs)
end
def filtered_location_releases
results = location_releases
if params[:query].present?
results = results.search(params[:query])
end
if params[:video_id].present?
results = results.appearing_in(params[:video_id])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: LocationRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,96 @@
class MaterialReleasesController < ApplicationController
include ProjectContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_material_release, only: [:edit, :update, :destroy]
include ProjectLayout
def index
@material_releases = filtered_material_releases.order_by_recent.paginate(page: params[:page])
end
def new
@material_release = build_material_release
end
def create
@material_release = build_material_release(material_release_params)
if @material_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@material_release)
redirect_to [@project, :material_releases], notice: t(".notice")
else
render :new
end
end
def edit
@project = @material_release.project
end
def update
@project = @material_release.project
if @material_release.update(material_release_params)
redirect_to [@project, :material_releases], notice: t(".notice")
else
render :edit
end
end
def destroy
@project = @material_release.project
@material_release.destroy
redirect_to [@project, :material_releases], alert: t(".alert")
end
private
def material_release_params
params.require(:material_release).permit(
:name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country,
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
:description,
:contract, { photos: [] }
)
end
def material_releases
if @project
policy_scope(@project.material_releases)
else
policy_scope(MaterialRelease)
end
end
def build_material_release(attrs = {})
authorize @project.material_releases.build(attrs)
end
def set_material_release
@material_release = authorize material_releases.find(params[:id])
end
def filtered_material_releases
results = material_releases
if params[:query].present?
results = results.search(params[:query])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MaterialRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,33 @@
class MultipartSignaturesController < ApplicationController
skip_after_action :verify_authorized
def create
render plain: hmac_data, status: 200
end
private
def hmac_data
aws_secret = ENV['AWS_SECRET_ACCESS_KEY']
timestamp = params[:datetime]
# TESTING UTF-8 encoding
aws_secret = aws_secret.encode('UTF-8')
details = params[:to_sign].encode('UTF-8')
date = hmac("AWS4#{aws_secret}", timestamp[0..7])
region = hmac(date, ENV["AWS_REGION"])
service = hmac(region, "s3")
signing = hmac(service, 'aws4_request')
hexhmac(signing, details)
end
def hmac(key, value)
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, value)
end
def hexhmac(key, value)
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, value)
end
end

View File

@@ -0,0 +1,118 @@
class MusicReleasesController < ApplicationController
include ProjectContext, MusicReleaseContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_music_release, only: [:edit, :update, :destroy]
include ProjectLayout
NUMBER_OF_COMPOSERS = 5
NUMBER_OF_PUBLISHERS = 2
def index
@music_releases = filtered_music_releases.order_by_recent.paginate(page: params[:page])
end
def new
@music_release = build_music_release
prefill_composers_and_publishers
end
def create
@music_release = build_music_release(music_release_params)
if @music_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@music_release)
redirect_to [@project, :music_releases], notice: t(".notice")
else
prefill_composers_and_publishers
render :new
end
end
def edit
@project = @music_release.project
prefill_composers_and_publishers
end
def update
@project = @music_release.project
if @music_release.update(music_release_params)
redirect_to [@project, :music_releases], notice: t(".notice")
else
prefill_composers_and_publishers
render :edit
end
end
def destroy
@project = @music_release.project
@music_release.destroy
redirect_to [@project, :music_releases], alert: t(".alert")
end
private
def prefill_composers_and_publishers
(NUMBER_OF_COMPOSERS - @music_release.composers.size).times { @music_release.composers.build }
(NUMBER_OF_PUBLISHERS - @music_release.publishers.size).times { @music_release.publishers.build }
end
def music_releases
if @project
policy_scope(@project.music_releases)
else
policy_scope(MusicRelease)
end
end
def music_release_params
params.require(:music_release).permit(
:name, :person_first_name, :person_last_name, :person_phone, :person_email, :person_company, :person_title,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:contract,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
file_infos_attributes: [
:filename,
:content_type,
:byte_size
],
composers_attributes: [
:id,
:name,
:affiliation,
:percentage,
:cae_number,
],
publishers_attributes: [
:id,
:name,
:affiliation,
:percentage
]
)
end
def build_music_release(attrs = {})
authorize @project.music_releases.build(attrs)
end
def filtered_music_releases
results = music_releases
if params[:query].present?
results = results.search(params[:query])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MusicRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,38 @@
class NotesController < ApplicationController
before_action :set_releasable
before_action :set_note, except: :index
def index
@notes = policy_scope(@releasable.notes)
end
def new
end
def create
@note.attributes = note_params_with_user
@note.save
end
private
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def set_releasable
@releasable = policy_scope(releasable_param.type).find(releasable_param.id)
end
def set_note
@note = authorize @releasable.notes.build
end
def note_params_with_user
note_params.merge(user: current_user, email: current_user.email)
end
def note_params
params.require(:note).permit(:content)
end
end

View File

@@ -0,0 +1,62 @@
class NotificationsController < 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
case notification_type
when "SubscriptionConfirmation"
Rails.logger.info(subscribe_url)
when "Notification"
case job_status
when "SUCCEEDED" then analysis_notification.success!
when "FAILED" then analysis_notification.failure!
else
Rails.logger.alert "Notification with status #{job_status}\n#{notification}"
end
else
Rails.logger.alert "Notification with type #{notification_type}\n#{notification}"
end
head :ok
end
private
# TODO: Verify the message
def notification
@notification ||= JSON.parse(request.raw_post)
end
def notification_type
notification.fetch("Type")
end
def subscribe_url
notification.fetch("SubscribeURL")
end
def message
@message ||= JSON.parse(notification.fetch("Message"))
end
def job_id
message.fetch("JobId")
end
def job_status
message.fetch("Status")
end
def analysis_type
message.fetch("AnalysisType")
end
def analysis_notification
@analysis_notification ||= AnalysisNotification.build(analysis_type, job_id)
end
end

View File

@@ -0,0 +1,7 @@
class PagesController < ApplicationController
include HighVoltage::StaticPage
skip_before_action :redirect_accountless
skip_after_action :verify_authorized
skip_after_action :verify_policy_scoped
skip_before_action :require_login
end

View File

@@ -0,0 +1,59 @@
class PasswordResetsController < ApplicationController
skip_before_action :require_login
skip_after_action :verify_authorized
before_action :set_user, only: [:edit, :update]
def new
end
def create
@user = find_user_by_email
if @user
UserMailer.password_reset(@user).deliver_later
end
redirect_to new_session_path, notice: t(".notice")
end
def edit
redirect_to new_session_path, notice: t(".notice") if @user.nil?
end
def update
if @user && reset_password(@user, new_password_param)
@user.regenerate_password_reset_token
redirect_to new_session_path, notice: t(".notice")
end
rescue ActiveRecord::RecordInvalid
flash.alert = t(".alert")
render :edit
end
private
def set_user
@user = find_user_by_token
end
def password_reset_params
params.require(:password_reset).permit(:email, :password)
end
def email_param
password_reset_params.dig(:email)
end
def new_password_param
password_reset_params.dig(:password)
end
def find_user_by_email
@user = User.find_by(email: email_param)
end
def find_user_by_token
@user = User.find_by(password_reset_token: params[:id])
end
end

View File

@@ -0,0 +1,40 @@
class PhotosController < ApplicationController
before_action :set_releasable
layout "project"
breadcrumb -> { t("shared.files") }, -> { @releasable.project }, match: :exact
breadcrumb -> { @releasable.model_name.plural.titleize }, -> { [@releasable.project, @releasable.model_name.plural] }, match: :exact
breadcrumb -> { t(".heading") }, :url_for
def edit
@project = @releasable.project
end
def update
@project = @releasable.project
if @releasable.update(releasable_params)
SetTagsForReleasableJob.perform_later(@releasable)
redirect_to [@project, @releasable.model_name.plural], notice: t(".notice")
else
render :edit
end
end
private
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def set_releasable
@releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :"#{action_name}_photos?"
end
def releasable_params
params.fetch(releasable_param.name, {}).permit(
photos: [],
)
end
end

View File

@@ -0,0 +1,25 @@
class ProfilesController < ApplicationController
before_action :set_user
skip_before_action :redirect_accountless
def show
end
def update
if @user.update(user_params)
redirect_to profile_path, notice: t(".notice")
else
render :show
end
end
private
def set_user
@user = authorize current_user, policy_class: ProfilePolicy
end
def user_params
params.require(:user).permit(:first_name, :last_name, :avatar, :time_zone)
end
end

View File

@@ -0,0 +1,66 @@
class ProjectMembershipsController < ApplicationController
include ProjectContext
layout "project"
before_action :set_project, except: :destroy
before_action :set_project_membership, only: [:destroy]
def index
@account_managers = @project.account.managers.order(:email)
@project_memberships = project_memberships.order_by_user_role_and_user_email(Current.account)
@project_membership = project_memberships.build
end
def create
@project_membership = build_project_membership(project_membership_params)
if @project_membership.save_and_update_account_membership
flash.notice = t(".notice")
UserMailer.project_invitation(@project_membership.user, @project, user_is_new: @project_membership.new_user?).deliver_later
else
flash.alert = alert_for(@project_membership)
end
redirect_to [@project, :project_memberships]
end
def destroy
@project_membership.destroy
redirect_to [@project_membership.project, :project_memberships], alert: t(".alert")
end
private
def set_project_membership
@project_membership = authorize project_memberships.find(params[:id])
end
def project_memberships
if @project
policy_scope(@project.project_memberships)
else
policy_scope(ProjectMembership)
end
end
def build_project_membership(params = {})
authorize project_memberships.build(params)
end
def project_membership_params
params.require(:project_membership).permit(:user_email)
end
def user_email_param
project_membership_params.fetch(:user_email)
end
def alert_for(project_membership)
if project_membership.errors.any?
project_membership.errors.full_messages.first
else
t(".alert")
end
end
end

View File

@@ -0,0 +1,73 @@
class ProjectsController < ApplicationController
include ProjectContext
layout "project", only: [:show]
before_action :set_project, only: [:show, :edit, :update, :destroy]
def index
@projects = policy_scope(Current.account.projects).order_by_name
end
def new
@project = build_project
end
def create
@project = build_project(project_params_with_current_account)
if @project.save
log_create_analytics
redirect_to @project, notice: "The project has been created"
else
render :new
end
end
def show
@directories = policy_scope(@project.directories).order_by_name
end
def edit
end
def update
if @project.update(project_params)
redirect_to @project, notice: "The project has been updated"
else
render :edit
end
end
def destroy
@project.destroy
redirect_to signed_in_root_path, alert: t(".alert")
end
private
def set_project
@project = authorize projects.find(params[:id])
end
def build_project(params = {})
authorize projects.build(params.merge(account: Current.account))
end
def project_params
params.require(:project).permit(:client_name, :description, :details, :name, :producer_address, :producer_name,
:predefined_client_name, features_settings: features_settings_params)
end
def features_settings_params
%i(appearance_release location_release material_release acquired_media_release music_release talent_release video_analysis)
end
def project_params_with_current_account
project_params.merge(account: Current.account)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_project, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,79 @@
class Public::AcquiredMediaReleasesController < Public::BaseController
include CreateReleasableJobs
before_action :set_account, :set_project, :set_contract_template
def new
@acquired_media_release = build_acquired_media_release
end
def create
@acquired_media_release = build_acquired_media_release(acquired_media_release_params_with_locale_and_contract_template)
if @acquired_media_release.save(context: :native)
log_create_analytics
after_create(@acquired_media_release)
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def acquired_media_releases
policy_scope(@project.acquired_media_releases)
end
def build_acquired_media_release(params = {})
acquired_media_releases.build(params).tap do |acquired_media_release|
authorize(acquired_media_release)
end
end
def acquired_media_release_params
params.require(:acquired_media_release).permit(
:name,
:description,
:person_title,
:person_phone,
:person_fax,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
:signature_base64,
:locale, :contract_template,
categories: [],
file_infos_attributes: [
:filename,
:content_type,
:byte_size
]
)
end
def acquired_media_release_params_with_locale
acquired_media_release_params.merge(locale: I18n.locale)
end
def acquired_media_release_params_with_locale_and_contract_template
acquired_media_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AcquiredMediaRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,60 @@
class Public::AppearanceReleasesController < Public::BaseController
include CreateReleasableJobs
before_action :set_account, :set_project, :set_contract_template
def new
@appearance_release = build_appearance_release
end
def create
@appearance_release = build_appearance_release(appearance_release_params_with_locale_and_contract_template)
if @appearance_release.save(context: :native)
log_create_analytics
after_create(@appearance_release)
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def appearance_releases
policy_scope(@project.appearance_releases)
end
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
end
def appearance_release_params
params.require(:appearance_release).permit(:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
:signature_base64, :person_date_of_birth,
:locale, :contract_template,)
end
def appearance_release_params_with_locale
appearance_release_params.merge(locale: I18n.locale)
end
def appearance_release_params_with_locale_and_contract_template
appearance_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AppearanceRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,3 @@
class Public::BaseController < ApplicationController
skip_before_action :require_login
end

View File

@@ -0,0 +1,57 @@
class Public::BroadcastsController < Public::BaseController
skip_after_action :verify_authorized
before_action :set_broadcast, only: [:show, :update]
def show
@conference_url = broadcast_zoom_meeting_url(@broadcast.token)
@multi_view_broadcasts = multi_view_broadcasts
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page])
render 'broadcasts/show'
end
def update
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab] })
BroadcastsChannel.file_upload_updates(@broadcast, @files, pagination_content)
end
private
def broadcast_params
params.require(:broadcast).permit(files: [])
end
def multi_view_broadcasts
Broadcast.
where(token: params[:multi_view_tokens]).
order_by_recent.
map { |b| MultiViewBroadcast.new(b, params[:multi_view_tokens]) }
end
def set_broadcast
@broadcast = Broadcast.find_by_token(params[:token])
end
class MultiViewBroadcast
include Rails.application.routes.url_helpers
delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_tokens)
@broadcast = broadcast
@multi_view_tokens = multi_view_tokens
end
def url
broadcast_url(uid, multi_view_tokens: @multi_view_tokens, host: AppHost.new.domain_with_port, locale: I18n.locale)
end
def uid
token
end
end
end

View File

@@ -0,0 +1,81 @@
class Public::LocationReleasesController < Public::BaseController
include CreateReleasableJobs
before_action :set_account, :set_project, :set_contract_template
def new
@location_release = build_location_release
end
def create
@location_release = build_location_release(location_release_params_with_locale_and_contract_template)
if @location_release.save(context: :native)
log_create_analytics
after_create(@location_release)
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def location_releases
policy_scope(@project.location_releases)
end
def build_location_release(params = {})
location_releases.build(params).tap do |location_release|
authorize(location_release)
end
end
def location_release_params
params.require(:location_release).permit(
:name,
:address_street1,
:address_street2,
:address_city,
:address_state,
:address_zip,
:address_country,
:person_first_name,
:person_last_name,
:person_title,
:person_company,
:person_phone,
:person_email,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
:signature_base64,
:locale, :contract_template, :filming_started_on, :filming_ended_on
)
end
def location_release_params_with_locale
location_release_params.merge(locale: I18n.locale)
end
def location_release_params_with_locale_and_contract_template
location_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: LocationRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,63 @@
class Public::MaterialReleasesController < Public::BaseController
include CreateReleasableJobs
before_action :set_account, :set_project, :set_contract_template
def new
@material_release = build_material_release
end
def create
@material_release = build_material_release(material_release_params_with_locale_and_contract_template)
if @material_release.save(context: :native)
log_create_analytics
after_create(@material_release)
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def material_releases
policy_scope(@project.material_releases)
end
def build_material_release(params = {})
authorize material_releases.build(params)
end
def material_release_params
params.require(:material_release).permit(
:name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country,
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:signature_base64,
:locale, :contract_template, :description
)
end
def material_release_params_with_locale
material_release_params.merge(locale: I18n.locale)
end
def material_release_params_with_locale_and_contract_template
material_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MaterialRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,98 @@
class Public::TalentReleasesController < Public::BaseController
include CreateReleasableJobs
before_action :set_account, :set_project, :set_contract_template
def new
@talent_release = build_talent_release
end
def create
@talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template)
if @talent_release.save(context: :native)
log_create_analytics
after_create(@talent_release)
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def talent_releases
policy_scope(@project.talent_releases)
end
def build_talent_release(params = {})
authorize talent_releases.build(params)
end
def talent_release_params
params
.require(:talent_release)
.permit(
person_params,
guardian_params,
:signature_base64,
:locale,
:contract_template,
photos: [],
)
end
def person_params
[
:person_first_name,
:person_last_name,
:person_phone,
:person_email,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
]
end
def guardian_params
[
:guardian_first_name,
:guardian_last_name,
:guardian_phone,
:guardian_email,
:minor,
:guardian_address_street1,
:guardian_address_street2,
:guardian_address_city,
:guardian_address_state,
:guardian_address_zip,
:guardian_address_country,
:guardian_photo,
]
end
def talent_release_params_with_locale
talent_release_params.merge(locale: I18n.locale)
end
def talent_release_params_with_locale_and_contract_template
talent_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: TalentRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,8 @@
class Public::ZoomMeetingsController < Public::BaseController
skip_after_action :verify_authorized
def show
broadcast = Broadcast.find_by_token!(params[:broadcast_token])
redirect_to broadcast.zoom_meeting_url
end
end

View File

@@ -0,0 +1,48 @@
require 'will_paginate/array'
class ReleaseTemplateImportsController < ApplicationController
include ProjectContext
layout "project"
before_action :set_project
def new
authorize ContractTemplate, :new?
templates = []
filtered_contract_templates.each do |contract_template|
next if contract_template.duplicated? || contract_template.project == @project
already_imported = contract_template.duplicates.non_archived.pluck(:project_id).include?(@project.id)
templates << OpenStruct.new(template: contract_template, already_imported?: already_imported)
end
# Already imported templates to the end of list
templates.sort_by! { |t| t.already_imported? ? 1 : 0 }
@importable_templates = templates.paginate(page: params[:page])
end
def create
authorize ContractTemplate, :create?
# Authorize each of the contract templates separately
ContractTemplate.where(id: params[:template_ids]).each { |ct| authorize ct, :import? }
if @project.import_contract_templates(params[:template_ids])
redirect_to project_contract_templates_path(@project), notice: t(".imported")
else
redirect_to project_contract_templates_path(@project), alert: t(".error")
end
end
private
def filtered_contract_templates
if params[:query].present?
search_results = ContractTemplate.search(params[:query])
policy_scope(ContractTemplate).where(id: search_results.select(:id))
else
policy_scope(ContractTemplate)
end
end
end

View File

@@ -0,0 +1,17 @@
class ReportDownloadsController < ApplicationController
include ProjectContext
before_action :set_project, only: [:index, :create]
include ProjectLayout
def create
authorize(Download)
name = "#{@project.name.parameterize}_#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}"
download = @project.downloads.create!(name: name, release_type: "reports")
ProjectsChannel.broadcast_download_generation_update(download, I18n.t("report_downloads.download.pending"))
GenerateReportsZipJob.perform_later(@project, download, name)
end
end

View File

@@ -0,0 +1,97 @@
require "will_paginate/array"
class ReportsController < ApplicationController
include ProjectContext
before_action :set_project
include ProjectLayout
def index
@reports = filtered_reports.paginate(page: params[:page])
end
private
def filtered_reports
results = reports
if params[:query].present?
results = reports.select{ |report| report.name.include?(params[:query])}
end
results
end
def reports
videos = @project.videos.reports_published
videos.published_at_desc_order.flat_map { |video| build_reports_for(video) }
end
def build_reports_for(video)
client_name = @project.client_name
reports = case client_name
when "Nat Geo"
nat_geo_reports_for(video)
else
discovery_reports_for(video)
end
reports += default_reports_for(video)
end
def default_reports_for(video)
[
Report.new(video, "BiG Music Cue Sheet", build_report_path(video, :audio_reports, "big")),
Report.new(video, "Issues and Concerns Report", build_report_path(video, :issues_and_concerns_reports)),
]
end
def nat_geo_reports_for(video)
[
Report.new(video, "Legal Binder Log", build_report_path(video, :video_reports, "nat_geo")),
Report.new(video, "Text Graphics Log", build_report_path(video, :graphic_reports, "nat_geo")),
Report.new(video, "Music Cue Sheet", build_report_path(video, :audio_reports, "nat_geo")),
Report.new(video, "Original Music Log", build_report_path(video, :audio_reports, "nat_geo-original")),
]
end
def discovery_reports_for(video)
[
Report.new(video, "Production Elements Log", build_report_path(video, :video_reports, "discovery")),
Report.new(video, "GFX Cue List", build_report_path(video, :graphic_reports, "discovery")),
Report.new(video, "Music Cue Sheet", build_report_path(video, :audio_reports, "discovery")),
]
end
def build_report_path(video, category, type = nil)
# TODO: Use Current for locale
[video, category, { format: "xlsx", locale: I18n.locale, type: type }]
end
class Report
include ActiveModel::Model
attr_reader :name, :url
delegate :number, :name, to: :video, prefix: true
def initialize(video, name, url)
@video = video
@name = name
@url = url
end
def to_partial_path
"reports/report"
end
def published_at
video.report_published_at
end
private
attr_reader :video
end
end

View File

@@ -0,0 +1,32 @@
class SessionsController < ApplicationController
skip_before_action :require_login, only: [:new, :create], raise: false
skip_before_action :redirect_accountless, only: [:new, :create, :destroy]
skip_after_action :verify_authorized, only: [:new, :create, :destroy], raise: false
def new
end
def create
user = authenticate_session(session_params)
if sign_in(user)
remember_me(user) if remember_me?
TrackAnalyticsJob.perform_later(user, user.primary_account, :track_user_sign_in, user_agent: request.user_agent, user_ip: request.remote_ip)
redirect_to signed_in_root_path
else
redirect_to new_session_path, alert: t(".alert")
end
end
def destroy
forget_me(current_user)
sign_out
redirect_to new_session_path
end
private
def session_params
params.require(:session).permit(:email, :password)
end
end

View File

@@ -0,0 +1,72 @@
class StreamNotificationsController < 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
before_action :set_broadcast, only: :create
def create
case notification_type
when "video.live_stream.connected"
@broadcast.streamer_connected!
notify_users
when "video.live_stream.recording"
@broadcast.streamer_recording!
notify_users
when "video.live_stream.active"
@broadcast.active!
notify_users
when "video.live_stream.disconnected"
@broadcast.streamer_disconnected!
notify_users
when "video.live_stream.idle"
@broadcast.streamer_idle!
@broadcast.idle!
notify_users
when "video.asset.static_renditions.ready"
asset_uid = notification.dig(:object, :id)
playback_uid = notification.dig(:data, :playback_ids, 0, :id)
file_name = notification.dig(:data, :static_renditions, :files, -1, :name)
recording = @broadcast.broadcast_recordings.create!(asset_uid: asset_uid, asset_playback_uid: playback_uid, file_name: file_name)
recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank")
message = "Your recent live stream has been recorded and is available for download here: #{link}"
BroadcastsChannel.stream_recording_ready(@broadcast, recordings, message)
else
Rails.logger.info notification_type
Rails.logger.info notification
end
head :ok
end
private
def notification
params
end
def notification_type
notification.dig(:type)
end
def notification_object_id
notification.dig(:object, :id)
end
def set_broadcast
if notification_type == "video.asset.static_renditions.ready"
live_stream_id = notification.dig(:stream_notification, :data, :live_stream_id)
@broadcast = Broadcast.find_by!(stream_uid: live_stream_id)
else
@broadcast = Broadcast.find_by!(stream_uid: notification_object_id)
end
end
def notify_users
BroadcastsChannel.broadcast_stream_updates(@broadcast)
end
end

View File

@@ -0,0 +1,42 @@
class TagsController < ApplicationController
before_action :set_releasable
before_action :set_tag, only: [:new]
before_action :authorize_tags, only: [:create, :destroy]
def new
end
def create
@releasable.tag_list.add(tag_params[:name])
@releasable.save
end
def destroy
@tag = ActsAsTaggableOn::Tag.find(params[:id])
@releasable.tag_list.remove(@tag.name)
@releasable.save
end
private
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def set_releasable
@releasable = policy_scope(releasable_param.type).find(releasable_param.id)
end
def set_tag
@tag = authorize @releasable.tags.build
end
def tag_params
params.require(:acts_as_taggable_on_tag).permit(:name)
end
def authorize_tags
authorize @releasable.tags
end
end

View File

@@ -0,0 +1,92 @@
class TalentReleasesController < ApplicationController
include ProjectContext, TalentReleaseContext
before_action :set_project, only: [:index, :new, :create]
before_action :set_talent_release, only: [:edit, :update, :destroy]
include ProjectLayout
def index
@talent_releases = filtered_talent_releases.order_by_recent.paginate(page: params[:page])
end
def new
@talent_release = build_talent_release
end
def create
@talent_release = build_talent_release(talent_release_params)
if @talent_release.save
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@talent_release)
redirect_to [@project, :talent_releases], notice: t(".notice")
else
render :new
end
end
def edit
@project = @talent_release.project
end
def update
@project = @talent_release.project
if @talent_release.update(talent_release_params)
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
redirect_to [@project, :talent_releases], notice: t(".notice")
else
render :edit
end
end
def destroy
@project = @talent_release.project
if @talent_release.destroy
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
redirect_to [@project, :talent_releases], alert: t(".alert")
end
end
private
def talent_releases
if @project
policy_scope(@project.talent_releases)
else
policy_scope(TalentRelease)
end
end
def talent_release_params
params.require(:talent_release).permit(
:person_first_name, :person_last_name, :person_phone, :guardian_photo, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_email, :minor,
:guardian_address_street1, :guardian_address_street2, :guardian_address_city, :guardian_address_state, :guardian_address_zip, :guardian_address_country,
:contract, { photos: [] },
:applicable_medium_id, :applicable_medium_text, :territory_id, :territory_text, :term_id, :term_text, :restriction_id, :restriction_text
)
end
def build_talent_release(attrs = {})
authorize @project.talent_releases.build(attrs)
end
def filtered_talent_releases
results = talent_releases
if params[:query].present?
results = results.search(params[:query])
end
results
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: TalentRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,28 @@
class VideoAnalyses::AcquiredMediaReleasesController < ApplicationController
before_action :set_video
def index
@acquired_media_file_infos = filtered_file_infos
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_file_infos
releasables = policy_scope(@video.acquired_media_releases)
results = FileInfo.where(releasable: releasables)
if query_param.present?
results = results.search_filename(query_param)
end
results
end
end

View File

@@ -0,0 +1,27 @@
class VideoAnalyses::AppearanceReleasesController < ApplicationController
before_action :set_video
def index
@appearance_releases = filtered_releases
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_releases
results = policy_scope(@video.appearance_releases)
if query_param.present?
results = results.search(query_param)
end
results
end
end

View File

@@ -0,0 +1,77 @@
class VideoAnalyses::AudioConfirmationsController < ApplicationController
before_action :set_video, only: [:new, :create]
def new
@matched_file_name = params.delete(:matched_file_name)
@audio_confirmation = filtered_audio_confirmations.build(audio_confirmation_params)
@edl_events_data = build_presenter(@audio_confirmation.edl_type).present
@audio_confirmation.attributes = @edl_events_data[:edl_attributes]
end
def create
audio_confirmation = filtered_audio_confirmations.build(audio_confirmation_params)
audio_confirmation.save
@audio_confirmation_data = ::AudioConfirmations::AudioConfirmationPresenter.new.present(audio_confirmation)
@audio_confirmations_data = ::AudioConfirmations::AudioConfirmationsPresenter.new.present(filtered_audio_confirmations)
end
def destroy
audio_confirmation = find_audio_confirmation
video = audio_confirmation.video
audio_confirmation.destroy
@audio_confirmation_data = ::AudioConfirmations::AudioConfirmationPresenter.new.present(audio_confirmation)
@audio_confirmations_data = ::AudioConfirmations::AudioConfirmationsPresenter.new.present(video.audio_confirmations)
end
private
def build_presenter(edl_type)
files_for_request = if edl_type == "all_tracks"
FilesForRequest.new(@video)
else
AudioFilesForRequest.new(@video, @video.edl_timecode_start)
end
EdlEventsPresenter.new(
EdlEventGateway.new(
files_for_request,
@audio_confirmation.appears_at,
@audio_confirmation.appears_at,
channel_filter: ENV["DISABLE_EDL_CHANNEL_FILTER"] ? "" : "A",
)
)
end
def find_audio_confirmation
authorize policy_scope(AudioConfirmation).find(params[:id])
end
def set_video
@video = authorize policy_scope(Video).find(params[:video_id])
end
def filtered_audio_confirmations
policy_scope(@video.audio_confirmations)
end
def audio_confirmation_params
params.require(:audio_confirmation).permit(
:time_elapsed,
:channel,
:timecode_in,
:timecode_out,
:duration,
:source_file_name,
:clip_name,
:description,
:music_type,
:music_category,
:composer_info,
:publisher_info,
:catalog,
:title,
:confirmation_type,
:edl_type,
)
end
end

View File

@@ -0,0 +1,32 @@
class VideoAnalyses::EdlEventsController < ApplicationController
before_action :set_video
def create
@timecode = timecode
@edl_events = edl_event_gateway.edl_events
@info_message = t(".info_message", count: @edl_events.size)
end
private
def videos
policy_scope(Video)
end
def set_video
@video = authorize videos.find(params[:video_id])
end
def edl_event_gateway
@edl_event_gateway ||= EdlEventGateway.new(FilesForRequest.new(@video), timecode, timecode)
end
def edl_event_params
params.require(:edl_event).permit(:time_elapsed)
end
def timecode
time_elapsed = edl_event_params.fetch(:time_elapsed)
Timecode.from_seconds(time_elapsed.to_f).to_s
end
end

View File

@@ -0,0 +1,85 @@
class VideoAnalyses::GraphicsElementsController < ApplicationController
before_action :set_video, only: [:new, :create]
def new
@matched_file_name = params.delete(:matched_file_name)
@graphics_element = filtered_graphics_elements.build(graphics_element_params)
@edl_events_data = build_presenter(@graphics_element.edl_type).present
@graphics_element.attributes = @edl_events_data[:edl_attributes]
end
def create
graphics_element = filtered_graphics_elements.build(graphics_element_params)
graphics_element.save
@graphics_element_data = ::GraphicsElements::GraphicsElementPresenter.new.present(graphics_element)
@graphics_elements_data = ::GraphicsElements::GraphicsElementsPresenter.new.present(filtered_graphics_elements)
end
def edit
@graphics_element = find_graphics_element
@video = @graphics_element.video
@edl_events_data = build_presenter(@graphics_element.edl_type).present
end
def update
graphics_element = find_graphics_element
graphics_element.update(graphics_element_params)
@video = graphics_element.video
@graphics_element_data = ::GraphicsElements::GraphicsElementPresenter.new.present(graphics_element)
@graphics_elements_data = ::GraphicsElements::GraphicsElementsPresenter.new.present(filtered_graphics_elements)
end
def destroy
graphics_element = find_graphics_element
@graphics_element_data = ::GraphicsElements::GraphicsElementPresenter.new.present(graphics_element)
graphics_element.destroy
@graphics_elements_data = ::GraphicsElements::GraphicsElementsPresenter.new.present(graphics_element.video.graphics_elements)
end
private
def find_graphics_element
authorize policy_scope(GraphicsElement).find(params[:id])
end
def build_presenter(edl_type)
files_for_request = if edl_type == "all_tracks"
FilesForRequest.new(@video)
else
GraphicsFilesForRequest.new(@video, @video.edl_timecode_start)
end
EdlEventsPresenter.new(
EdlEventGateway.new(
files_for_request,
@graphics_element.appears_at,
@graphics_element.appears_at,
channel_filter: ENV["DISABLE_EDL_CHANNEL_FILTER"] ? "" : "V",
)
)
end
def set_video
@video = authorize policy_scope(Video).find(params[:video_id])
end
def filtered_graphics_elements
policy_scope(@video.graphics_elements)
end
def graphics_element_params
params.require(:graphics_element).permit(
:graphic_type,
:text,
:time_elapsed,
:channel,
:timecode_in,
:timecode_out,
:duration,
:source_file_name,
:clip_name,
:description,
:edl_type,
)
end
end

View File

@@ -0,0 +1,27 @@
class VideoAnalyses::LocationReleasesController < ApplicationController
before_action :set_video
def index
@location_releases = filtered_releases
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_releases
results = policy_scope(@video.location_releases)
if query_param.present?
results = results.search(query_param)
end
results
end
end

View File

@@ -0,0 +1,27 @@
class VideoAnalyses::MaterialReleasesController < ApplicationController
before_action :set_video
def index
@material_releases = filtered_releases
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_releases
results = policy_scope(@video.material_releases)
if query_param.present?
results = results.search(query_param)
end
results
end
end

View File

@@ -0,0 +1,28 @@
class VideoAnalyses::MusicReleasesController < ApplicationController
before_action :set_video
def index
@music_release_file_infos = filtered_file_infos
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_file_infos
releasables = policy_scope(@video.project.music_releases)
results = FileInfo.where(releasable: releasables)
if query_param.present?
results = results.search_filename(query_param)
end
results
end
end

View File

@@ -0,0 +1,27 @@
class VideoAnalyses::TalentReleasesController < ApplicationController
before_action :set_video
def index
@talent_releases = filtered_releases
end
private
def set_video
@video = Video.find(params[:video_id])
end
def query_param
params[:query]
end
def filtered_releases
results = policy_scope(@video.talent_releases)
if query_param.present?
results = results.search(query_param)
end
results
end
end

View File

@@ -0,0 +1,77 @@
class VideoAnalyses::UnreleasedAppearancesController < ApplicationController
before_action :set_video, except: [:edit, :update, :destroy]
def new
@unreleased_appearance = @video.unreleased_appearances.build(unreleased_appearance_params)
@edl_events_data = build_presenter.present
@unreleased_appearance.attributes = @edl_events_data[:edl_attributes]
end
def create
@unreleased_appearance = @video.unreleased_appearances.build(unreleased_appearance_params)
@unreleased_appearance.save
@unreleased_appearances_data = UnreleasedAppearancesPresenter.new.present(@video.unreleased_appearances)
end
def edit
@unreleased_appearance = find_unreleased_appearance
@video = @unreleased_appearance.video
@edl_events_data = build_presenter.present
end
def update
unreleased_appearance = find_unreleased_appearance
unreleased_appearance.update(unreleased_appearance_params)
@unreleased_appearances_data = UnreleasedAppearancesPresenter.new.present(unreleased_appearance.video.unreleased_appearances)
end
def destroy
unreleased_appearance = find_unreleased_appearance
video = unreleased_appearance.video
unreleased_appearance.destroy
@unreleased_appearances_data = UnreleasedAppearancesPresenter.new.present(video.unreleased_appearances)
end
private
def build_presenter
EdlEventsPresenter.new(EdlEventGateway.new(FilesForRequest.new(@video), @unreleased_appearance.appears_at, @unreleased_appearance.appears_at))
end
def unreleased_appearance_params
params
.require(:unreleased_appearance)
.permit(
:notes,
:time_elapsed,
:channel,
:timecode_in,
:timecode_out,
:duration,
:source_file_name,
:clip_name,
:description,
:note_category
)
end
def unreleased_appearances
if @video
policy_scope(@video.unreleased_appearances)
else
policy_scope(UnreleasedAppearance)
end
end
def videos
policy_scope(Video)
end
def find_unreleased_appearance
authorize unreleased_appearances.find(params[:id])
end
def set_video
@video = authorize videos.find(params[:video_id])
end
end

View File

@@ -0,0 +1,38 @@
class VideoAnalysesController < ApplicationController
before_action :set_video, only: [:create, :show]
def create
AnalyzeVideoJob.perform_later(@video, reanalysis: true)
AnalyzeAudioJob.perform_later(@video)
redirect_to [@video, :video_analyses], notice: t(".notice")
end
def show
@video_release_confirmations = @video.video_release_confirmations.order_by_ranked_release_type
@talent_releases = @video.project.talent_releases
@appearance_releases = @video.project.appearance_releases
@location_releases = @video.project.location_releases
@acquired_media_releases = @video.project.acquired_media_releases
@music_releases = @video.project.music_releases
@material_releases = @video.project.material_releases
@bookmarks = @video.bookmarks
video_analysis = authorize(VideoAnalysis.new(@video, false))
audio_analysis = AudioAnalysis.new(@video)
@video_analysis_presenter = VideoAnalysisService.new.presenter(
@video,
video_analysis,
audio_analysis,
)
@graphics_elements_data = GraphicsElements::GraphicsElementsPresenter.new.present(@video.graphics_elements)
@unreleased_appearances_data = UnreleasedAppearancesPresenter.new.present(@video.unreleased_appearances)
@audio_confirmations = @video.audio_confirmations
end
private
def set_video
@video = authorize Video.find(params[:video_id]), policy_class: VideoAnalysisPolicy
end
end

View File

@@ -0,0 +1,90 @@
class VideoReleaseConfirmationsController < ApplicationController
before_action :set_releasable, except: [:destroy]
before_action :set_video, except: [:destroy]
before_action :set_video_release_confirmation, only: [:destroy]
def new
@video_release_confirmation = build_video_release_confirmation(video_release_confirmation_params_with_releasable)
edl_events_presenter = build_presenter
@edl_events_data = edl_events_presenter.present
@video_release_confirmation.attributes = @edl_events_data[:edl_attributes]
end
def create
@video_release_confirmation = build_video_release_confirmation(video_release_confirmation_params_with_releasable)
@video_release_confirmation.save
set_video_release_confirmations
respond_to do |format|
format.html { redirect_to [@video, :video_analyses] }
format.js
end
end
def destroy
@releasable = @video_release_confirmation.releasable
@video = @video_release_confirmation.video
@video_release_confirmation.destroy
set_video_release_confirmations
respond_to do |format|
format.html { redirect_to [@video_release_confirmation.video, :video_analyses] }
format.js
end
end
private
def set_video_release_confirmations
@video_release_confirmations = @video.video_release_confirmations.order_by_ranked_release_type.order(created_at: :desc)
end
def build_presenter
EdlEventsPresenter.new(
EdlEventGateway.new(
FilesForRequest.new(@video),
@video_release_confirmation.appears_at,
@video_release_confirmation.appears_at,
channel_filter: ENV["DISABLE_EDL_CHANNEL_FILTER"] ? "" : "V",
))
end
def build_video_release_confirmation(attrs = {})
@video.video_release_confirmations.build(attrs)
end
def set_releasable
releasable_param = ReleasableParam.new(params.to_unsafe_h)
@releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id)
end
def set_video
@video = authorize policy_scope(Video).find(params[:video_id])
end
def set_video_release_confirmation
@video_release_confirmation = authorize policy_scope(VideoReleaseConfirmation).find(params[:id])
end
def video_release_confirmation_params
params.require(:video_release_confirmation).permit(
:time_elapsed,
:file_info_id,
:channel,
:timecode_in,
:timecode_out,
:duration,
:source_file_name,
:clip_name,
:description
)
end
def video_release_confirmation_params_with_releasable
video_release_confirmation_params.merge(releasable: @releasable)
end
end

View File

@@ -0,0 +1,30 @@
class VideoReportsController < ApplicationController
def show
report = build_report(params[:type])
respond_to do |format|
format.xlsx { send_data(report.to_xls, download_attributes_xls(report)) }
end
end
private
def video
authorize policy_scope(Video).find(params[:video_id])
end
def build_report(type)
case type
when "nat_geo"
authorize ExcelReports::VideoReports::NatGeoLegalBinderLog.new(video)
else
authorize ExcelReports::VideoReports::DiscoveryProductionElementsLog.new(video)
end
end
def download_attributes_xls(report)
{
filename: report.filename,
type: Mime[:xlsx]
}
end
end

View File

@@ -0,0 +1,25 @@
class Videos::ReportPublicationsController < ApplicationController
before_action :set_video
def create
@video.publish_report!
redirect_to [@video, :video_analyses], notice: "Report has been published"
end
def destroy
@video.unpublish_report!
redirect_to [@video, :video_analyses], notice: "Report has been un-published"
end
private
def videos
policy_scope(Video)
end
def set_video
@video = authorize videos.find(params[:video_id]), policy_class: Videos::ReportPublicationPolicy
end
end

View File

@@ -0,0 +1,129 @@
class VideosController < ApplicationController
layout "project"
before_action :set_project, only: [:index, :new, :create, :landing]
before_action :set_video, only: [:edit, :update]
def landing
authorize Video, :new?
end
def index
@videos = filtered_videos.order(created_at: :desc).paginate(page: params[:page])
end
def new
@video = build_video(video_editing_system: params[:video_editing_system])
end
def create
@video = build_video(video_create_params)
if @video.save
log_create_analytics
AnalyzeVideoJob.perform_later(@video)
AnalyzeAudioJob.perform_later(@video)
AdminMailer.new_video(@video).deliver_later
redirect_to [@project, :videos], notice: t(".notice")
else
render :new
end
end
def edit
@project = @video.project
end
def update
@project = @video.project
if @video.update(video_update_params)
if edl_file_changed?
@video.unpublish_report!
AdminMailer.updated_video_edl_file(@video).deliver_later
end
if graphics_only_edl_file_changed?
@video.unpublish_report!
AdminMailer.updated_video_graphics_only_edl_file(@video).deliver_later
end
if audio_only_edl_file_changed?
@video.unpublish_report!
AdminMailer.updated_video_audio_only_edl_file(@video).deliver_later
end
redirect_to [@project, :videos], notice: t(".notice")
else
render :edit
end
end
private
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_video
@video = authorize videos.find(params[:id])
end
def build_video(params = {})
authorize videos.build(params)
end
def videos
if @project
policy_scope(@project.videos)
else
policy_scope(Video)
end
end
def filtered_videos
if params[:query]
videos.search(params[:query])
else
videos
end
end
def edl_file_changed?
video_update_params.has_key?(:edl_file)
end
def graphics_only_edl_file_changed?
video_update_params.has_key?(:graphics_only_edl_file)
end
def audio_only_edl_file_changed?
video_update_params.has_key?(:audio_only_edl_file)
end
def video_create_params
params.require(:video).permit(
:name,
:number,
:file,
:edl_file,
:graphics_only_edl_file,
:audio_only_edl_file,
:video_editing_system,
)
end
def video_update_params
params.require(:video).permit(
:name,
:number,
:edl_file,
:graphics_only_edl_file,
:audio_only_edl_file,
)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_video_upload, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -0,0 +1,6 @@
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,55 @@
class ZoomNotificationsController < ApplicationController
skip_before_action :require_login
skip_after_action :verify_authorized
skip_after_action :verify_policy_scoped
skip_before_action :verify_authenticity_token
before_action :authorize_zoom
before_action :set_zoom_meeting, only: :create
def create
case notification_event
when 'meeting.started'
@zoom_meeting.started!
when 'meeting.ended'
@zoom_meeting.ended!
when 'recording.completed'
recording = notification.dig(:payload, :object, :recording_files).first
AttachRecordingToZoomMeetingJob.perform_later(@zoom_meeting, recording, notification['download_token'])
else
Rails.logger.info notification_event
Rails.logger.info notification
end
head :ok
end
private
def notification
params.to_unsafe_h
end
def notification_event
notification.dig(:event)
end
def notification_meeting_id
notification.dig(:payload, :object, :id)
end
def notification_host_id
notification.dig(:payload, :object, :host_id)
end
def set_zoom_meeting
@zoom_meeting = ZoomMeeting.find_by!(api_meeting_id: notification_meeting_id)
end
def authorize_zoom
if request.headers['Authorization'] != ENV['ZOOM_VERIFICATION_TOKEN']
head :forbidden
end
end
end