diff --git a/app/controllers/feeds_controller.rb b/app/controllers/feeds_controller.rb index 8eba4651d..151cb23ad 100644 --- a/app/controllers/feeds_controller.rb +++ b/app/controllers/feeds_controller.rb @@ -9,8 +9,9 @@ def index # GET /feeds/1 def show - @feed.assign_attributes(feed_params_with_apple) + @feed.assign_attributes(feed_params) authorize @feed + @apple_show_options = get_apple_show_options(@feed) end # GET /feeds/new @@ -22,19 +23,25 @@ def new @feed.clear_attribute_changes(%i[file_name podcast_id private slug]) end + def get_apple_show_options(feed) + if feed.apple? && feed.apple_config&.key + feed.apple_show_options + end + end + def new_apple @feed = Feeds::AppleSubscription.new(podcast: @podcast, private: true) @feed.build_apple_config @feed.apple_config.build_key authorize @feed - @feed.assign_attributes(feed_params_with_apple) + @feed.assign_attributes(feed_params) render "new" end # POST /feeds def create - @feed = @podcast.feeds.new(feed_params_with_apple) + @feed = @podcast.feeds.new(feed_params) @feed.slug = "" if @feed.slug.nil? authorize @feed @@ -114,10 +121,6 @@ def feed_params params.fetch(:feed, {}).permit(:slug).merge(nilified_feed_params) end - def feed_params_with_apple - params.fetch(:feed, {}).permit(:slug).merge(nilified_feed_params).merge(apple_params) - end - def nilified_feed_params nilify params.fetch(:feed, {}).permit( :lock_version, @@ -144,20 +147,13 @@ def nilified_feed_params :paid, :sonic_id, :type, + :apple_show_id, itunes_category: [], itunes_subcategory: [], feed_tokens_attributes: %i[id label token _destroy], feed_images_attributes: %i[id original_url size alt_text caption credit _destroy _retry], - itunes_images_attributes: %i[id original_url size alt_text caption credit _destroy _retry] - ) - end - - def apple_params - nilify params.fetch(:feed, {}).permit( - apple_config_attributes: { - id: :id, - key_attributes: %i[id provider_id key_id key_pem_b64] - } + itunes_images_attributes: %i[id original_url size alt_text caption credit _destroy _retry], + apple_config_attributes: [:id, :publish_enabled, :sync_blocks_rss, {key_attributes: %i[id provider_id key_id key_pem_b64]}] ) end end diff --git a/app/javascript/controllers/apple_key_controller.js b/app/javascript/controllers/apple_key_controller.js index 0a32b592c..239143f88 100644 --- a/app/javascript/controllers/apple_key_controller.js +++ b/app/javascript/controllers/apple_key_controller.js @@ -30,14 +30,7 @@ export default class extends Controller { const keyId = fields[1].split(".")[0] this.providerTargets.forEach((target) => (target.value = provider)) - this.providerTarget.disabled = false - this.providerTarget.focus() - this.providerTarget.disabled = true - this.keyTargets.forEach((target) => (target.value = keyId)) - this.keyTarget.disabled = false - this.keyTarget.focus() - this.keyTarget.disabled = true } convertKeyToB64(fileText) { diff --git a/app/models/apple/key.rb b/app/models/apple/key.rb index 6f72616a7..af2370b8b 100644 --- a/app/models/apple/key.rb +++ b/app/models/apple/key.rb @@ -8,6 +8,16 @@ class Key < ApplicationRecord validate :provider_id_is_valid, if: :provider_id? validate :ec_key_format, if: :key_pem_b64? + validate :must_have_working_key + + def must_have_working_key + return if Rails.env.test? + api = Apple::Api.from_key(self) + Apple::Show.apple_shows_json(api) + rescue => err + logger.error(err) + errors.add(:key_id, "must have a working Apple key") + end def provider_id_is_valid if provider_id.include?("_") diff --git a/app/models/apple/show.rb b/app/models/apple/show.rb index 61b0ab3a8..be1b979b0 100644 --- a/app/models/apple/show.rb +++ b/app/models/apple/show.rb @@ -8,18 +8,29 @@ class Show :private_feed, :api + def self.apple_shows_json(api) + api.get_paged_collection("shows") + end + def self.apple_episode_json(api, show_id) api.get_paged_collection("shows/#{show_id}/episodes") end def self.connect_existing(apple_show_id, apple_config) - api = Apple::Api.from_apple_config(apple_config) - - SyncLog.log!(feeder_id: apple_config.public_feed.id, - feeder_type: :feeds, - sync_completed_at: Time.now.utc, - external_id: apple_show_id) + if (sl = SyncLog.find_by(feeder_id: apple_config.public_feed.id, feeder_type: :feeds)) + if apple_show_id.blank? + return sl.destroy! + elsif sl.external_id != apple_show_id + sl.update!(external_id: apple_show_id) + end + else + SyncLog.log!(feeder_id: apple_config.public_feed.id, + feeder_type: :feeds, + sync_completed_at: Time.now.utc, + external_id: apple_show_id) + end + api = Apple::Api.from_apple_config(apple_config) new(api: api, public_feed: apple_config.public_feed, private_feed: apple_config.private_feed) diff --git a/app/models/feeds/apple_subscription.rb b/app/models/feeds/apple_subscription.rb index f01ee467b..6e1d9a96b 100644 --- a/app/models/feeds/apple_subscription.rb +++ b/app/models/feeds/apple_subscription.rb @@ -14,6 +14,8 @@ class Feeds::AppleSubscription < Feed after_create :republish_public_feed + after_save_commit :update_apple_show + has_one :apple_config, class_name: "::Apple::Config", dependent: :destroy, autosave: true, validate: true, inverse_of: :feed accepts_nested_attributes_for :apple_config, allow_destroy: true, reject_if: :all_blank @@ -23,6 +25,14 @@ class Feeds::AppleSubscription < Feed validate :must_be_private validate :must_have_token + # for soft delete, need a unique slug to be able to make another + def paranoia_destroy_attributes + { + deleted_at: current_time_from_proper_timezone, + slug: "#{slug} - #{Time.now.to_i}" + } + end + def set_defaults self.slug ||= DEFAULT_FEED_SLUG self.title ||= DEFAULT_TITLE @@ -35,6 +45,25 @@ def set_defaults super end + def update_apple_show + if previous_changes[:apple_show_id] + Apple::Show.connect_existing(apple_show_id, apple_config) + end + end + + def apple_show_options + used_ids = Feed.apple.distinct.where("id != ?", id).pluck(:apple_show_id).compact + api = Apple::Api.from_apple_config(apple_config) + shows_json = Apple::Show.apple_shows_json(api) || [] + shows_json + .filter { |sj| sj["attributes"]["publishingState"] != "ARCHIVED" } + .filter { |sj| !used_ids.include?(sj["id"]) } + .map { |sj| ["#{sj["id"]} (#{sj["attributes"]["title"]})", sj["id"]] } + rescue => err + logger.error(err) + [] + end + def guess_audio_format default_feed_audio_format || episode_audio_format || DEFAULT_AUDIO_FORMAT end diff --git a/app/policies/apple/config_policy.rb b/app/policies/apple/config_policy.rb index 08245787c..48de881f8 100644 --- a/app/policies/apple/config_policy.rb +++ b/app/policies/apple/config_policy.rb @@ -12,6 +12,6 @@ def create? end def update? - false + FeedPolicy.new(token, resource.feed).update? end end diff --git a/app/policies/feed_policy.rb b/app/policies/feed_policy.rb index 6434f2d6b..5b60bf395 100644 --- a/app/policies/feed_policy.rb +++ b/app/policies/feed_policy.rb @@ -12,14 +12,14 @@ def create? end def new_apple? - create? + update? end def update? - PodcastPolicy.new(token, resource.podcast).update? + PodcastPolicy.new(token, resource.podcast).update? && !resource.edit_locked? end def destroy? - resource.custom? && update? && !resource.apple? + resource.custom? && update? end end diff --git a/app/views/feeds/_form.html.erb b/app/views/feeds/_form.html.erb index 46b36ec10..8575394ce 100644 --- a/app/views/feeds/_form.html.erb +++ b/app/views/feeds/_form.html.erb @@ -6,14 +6,24 @@ <%= form_with(url: url, model: model, method: method, html: {autocomplete: "off"}, data: data) do |form| %>
<%= t(".description") %>
- <%= t(".guide_link") %> + <%= t(".guide_link").html_safe %>