feat: add lock podcast according to the Podcastindex podcast-namespace to prevent unauthozized import

This commit is contained in:
Benjamin Bellamy 2020-10-20 13:46:00 +00:00
parent e49b223926
commit 72b301272e
11 changed files with 71 additions and 20 deletions

View File

@ -156,6 +156,7 @@ class Podcast extends BaseController
'copyright' => $this->request->getPost('copyright'), 'copyright' => $this->request->getPost('copyright'),
'block' => $this->request->getPost('block') === 'yes', 'block' => $this->request->getPost('block') === 'yes',
'complete' => $this->request->getPost('complete') === 'yes', 'complete' => $this->request->getPost('complete') === 'yes',
'lock' => $this->request->getPost('lock') === 'yes',
'created_by' => user(), 'created_by' => user(),
'updated_by' => user(), 'updated_by' => user(),
]); ]);
@ -244,10 +245,19 @@ class Podcast extends BaseController
' ⎋</a>', ' ⎋</a>',
]); ]);
} }
$nsItunes = $feed->channel[0]->children( $nsItunes = $feed->channel[0]->children(
'http://www.itunes.com/dtds/podcast-1.0.dtd' 'http://www.itunes.com/dtds/podcast-1.0.dtd'
); );
$nsPodcast = $feed->channel[0]->children(
'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md'
);
if ((string) $nsPodcast->locked === 'yes') {
return redirect()
->back()
->withInput()
->with('errors', [lang('PodcastImport.lock_import')]);
}
$podcast = new \App\Entities\Podcast([ $podcast = new \App\Entities\Podcast([
'name' => $this->request->getPost('name'), 'name' => $this->request->getPost('name'),
@ -453,6 +463,7 @@ class Podcast extends BaseController
$this->podcast->block = $this->request->getPost('block') === 'yes'; $this->podcast->block = $this->request->getPost('block') === 'yes';
$this->podcast->complete = $this->podcast->complete =
$this->request->getPost('complete') === 'yes'; $this->request->getPost('complete') === 'yes';
$this->podcast->lock = $this->request->getPost('lock') === 'yes';
$this->updated_by = user(); $this->updated_by = user();
$db = \Config\Database::connect(); $db = \Config\Database::connect();

View File

@ -79,6 +79,10 @@ class AddPodcasts extends Migration
'constraint' => 1024, 'constraint' => 1024,
'null' => true, 'null' => true,
], ],
'episode_description_footer' => [
'type' => 'TEXT',
'null' => true,
],
'block' => [ 'block' => [
'type' => 'TINYINT', 'type' => 'TINYINT',
'constraint' => 1, 'constraint' => 1,
@ -89,19 +93,12 @@ class AddPodcasts extends Migration
'constraint' => 1, 'constraint' => 1,
'default' => 0, 'default' => 0,
], ],
'episode_description_footer' => [ 'lock' => [
'type' => 'TEXT', 'type' => 'TINYINT',
'null' => true, 'constraint' => 1,
], 'comment' =>
'created_by' => [ 'This tells other podcast platforms whether they are allowed to import this feed.',
'type' => 'INT', 'default' => 1,
'constraint' => 11,
'unsigned' => true,
],
'updated_by' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
], ],
'imported_feed_url' => [ 'imported_feed_url' => [
'type' => 'VARCHAR', 'type' => 'VARCHAR',
@ -117,6 +114,16 @@ class AddPodcasts extends Migration
'The RSS new feed URL if this podcast is moving out, NULL otherwise.', 'The RSS new feed URL if this podcast is moving out, NULL otherwise.',
'null' => true, 'null' => true,
], ],
'created_by' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'updated_by' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'created_at' => [ 'created_at' => [
'type' => 'TIMESTAMP', 'type' => 'TIMESTAMP',
], ],

View File

@ -76,13 +76,14 @@ class Podcast extends Entity
'owner_email' => '?string', 'owner_email' => '?string',
'type' => 'string', 'type' => 'string',
'copyright' => '?string', 'copyright' => '?string',
'episode_description_footer' => '?string',
'block' => 'boolean', 'block' => 'boolean',
'complete' => 'boolean', 'complete' => 'boolean',
'episode_description_footer' => '?string', 'lock' => 'boolean',
'created_by' => 'integer',
'updated_by' => 'integer',
'imported_feed_url' => '?string', 'imported_feed_url' => '?string',
'new_feed_url' => '?string', 'new_feed_url' => '?string',
'created_by' => 'integer',
'updated_by' => 'integer',
]; ];
/** /**

View File

@ -21,8 +21,11 @@ function get_rss_feed($podcast)
$itunes_namespace = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; $itunes_namespace = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
$podcast_namespace =
'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md';
$rss = new SimpleRSSElement( $rss = new SimpleRSSElement(
"<?xml version='1.0' encoding='utf-8'?><rss version='2.0' xmlns:itunes='$itunes_namespace' xmlns:content='http://purl.org/rss/1.0/modules/content/'></rss>" "<?xml version='1.0' encoding='utf-8'?><rss version='2.0' xmlns:itunes='$itunes_namespace' xmlns:podcast='$podcast_namespace' xmlns:content='http://purl.org/rss/1.0/modules/content/'></rss>"
); );
$channel = $rss->addChild('channel'); $channel = $rss->addChild('channel');
@ -60,7 +63,9 @@ function get_rss_feed($podcast)
$itunes_image = $channel->addChild('image', null, $itunes_namespace); $itunes_image = $channel->addChild('image', null, $itunes_namespace);
$itunes_image->addAttribute('href', $podcast->image->original_url); $itunes_image->addAttribute('href', $podcast->image->original_url);
$channel->addChild('language', $podcast->language); $channel->addChild('language', $podcast->language);
$channel
->addChild('locked', $podcast->lock ? 'yes' : 'no', $podcast_namespace)
->addAttribute('owner', $podcast->owner_email);
// set main category first, then other categories as apple // set main category first, then other categories as apple
add_category_tag($channel, $podcast->category); add_category_tag($channel, $podcast->category);
foreach ($podcast->other_categories as $other_category) { foreach ($podcast->other_categories as $other_category) {

View File

@ -65,6 +65,9 @@ return [
'status_section_subtitle' => 'Dead or alive?', 'status_section_subtitle' => 'Dead or alive?',
'block' => 'Podcast should be hidden from all platforms', 'block' => 'Podcast should be hidden from all platforms',
'complete' => 'Podcast will not be having new episodes', 'complete' => 'Podcast will not be having new episodes',
'lock' => 'Podcast is locked for export',
'lock_hint' =>
'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.',
'submit_create' => 'Create podcast', 'submit_create' => 'Create podcast',
'submit_edit' => 'Save podcast', 'submit_edit' => 'Save podcast',
], ],

View File

@ -40,5 +40,7 @@ return [
'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.',
'max_episodes' => 'Maximum number of episodes to import', 'max_episodes' => 'Maximum number of episodes to import',
'max_episodes_hint' => 'Leave blank to import all episodes', 'max_episodes_hint' => 'Leave blank to import all episodes',
'lock_import' =>
'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.',
'submit' => 'Import podcast', 'submit' => 'Import podcast',
]; ];

View File

@ -66,6 +66,9 @@ return [
'status_section_subtitle' => 'Vivant ou mort?', 'status_section_subtitle' => 'Vivant ou mort?',
'block' => 'Le podcast doit être masqué sur toutes les plateformes', 'block' => 'Le podcast doit être masqué sur toutes les plateformes',
'complete' => 'Le podcast naura plus de nouveaux épisodes.', 'complete' => 'Le podcast naura plus de nouveaux épisodes.',
'lock' => 'Le podcast est fermé à lexport',
'lock_hint' =>
'Le but est dindiquer aux autres plates-formes de podcast si elles sont autorisées à importer ce flux. La valeur «oui» signifie que toute tentative dimportation de ce flux dans une nouvelle plateforme doit être rejetée.',
'submit_create' => 'Créer le podcast', 'submit_create' => 'Créer le podcast',
'submit_edit' => 'Enregistrer le podcast', 'submit_edit' => 'Enregistrer le podcast',
], ],

View File

@ -41,5 +41,7 @@ return [
'Utilisez ceci si le podcast à importer ne contient pas de numéros de saison mais que vous souhaitez en définir un. Laissez vide sinon.', 'Utilisez ceci si le podcast à importer ne contient pas de numéros de saison mais que vous souhaitez en définir un. Laissez vide sinon.',
'max_episodes' => 'Nombre maximum dépisodes à importer', 'max_episodes' => 'Nombre maximum dépisodes à importer',
'max_episodes_hint' => 'Laissez vide pour importer tous les épisodes', 'max_episodes_hint' => 'Laissez vide pour importer tous les épisodes',
'lock_import' =>
'Ce flux est protégé. Vous ne pouvez pas limporter. Si en vous êtes le propriétaire, déprotégez-le sur la plate-forme dorigine.',
'submit' => 'Importer le podcast', 'submit' => 'Importer le podcast',
]; ];

View File

@ -32,6 +32,7 @@ class PodcastModel extends Model
'copyright', 'copyright',
'block', 'block',
'complete', 'complete',
'lock',
'created_by', 'created_by',
'updated_by', 'updated_by',
'imported_feed_url', 'imported_feed_url',

View File

@ -262,6 +262,13 @@
old('complete', false) old('complete', false)
) ?> ) ?>
<?= form_switch(
lang('Podcast.form.lock'),
['id' => 'lock', 'name' => 'lock'],
'yes',
old('lock', $podcast->lock)
) ?>
<?= form_section_close() ?> <?= form_section_close() ?>

View File

@ -269,7 +269,16 @@
lang('Podcast.form.complete'), lang('Podcast.form.complete'),
['id' => 'complete', 'name' => 'complete'], ['id' => 'complete', 'name' => 'complete'],
'yes', 'yes',
old('complete', $podcast->complete) old('complete', $podcast->complete),
'mb-2'
) ?>
<?= form_switch(
lang('Podcast.form.lock') .
hint_tooltip(lang('Podcast.form.lock_hint'), 'ml-1'),
['id' => 'lock', 'name' => 'lock'],
'yes',
old('lock', $podcast->lock)
) ?> ) ?>
<?= form_section_close() ?> <?= form_section_close() ?>