diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 494a3f62..640d7250 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -36,11 +36,12 @@ $routes->addPlaceholder('username', '[a-zA-Z0-9 ]{3,}'); // route since we don't have to scan directories. $routes->get('/', 'Home::index', ['as' => 'home']); +// Public routes $routes->group('@(:podcastName)', function ($routes) { - $routes->add('/', 'Podcast/$1', ['as' => 'podcast']); + $routes->get('/', 'Podcast/$1', ['as' => 'podcast']); - $routes->add('feed.xml', 'Feed/$1', ['as' => 'podcast_feed']); - $routes->add('episodes/(:episodeSlug)', 'Episode/$1/$2', [ + $routes->get('feed.xml', 'Feed/$1', ['as' => 'podcast_feed']); + $routes->get('episodes/(:episodeSlug)', 'Episode/$1/$2', [ 'as' => 'episode', ]); }); @@ -51,74 +52,119 @@ $routes->add('stats/(:num)/(:num)/(:any)', 'Analytics::hit/$1/$2/$3', [ ]); // Show the Unknown UserAgents -$routes->add('.well-known/unknown-useragents', 'UnknownUserAgents'); -$routes->add('.well-known/unknown-useragents/(:num)', 'UnknownUserAgents/$1'); +$routes->get('.well-known/unknown-useragents', 'UnknownUserAgents'); +$routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgents/$1'); // Admin area $routes->group( config('App')->adminGateway, ['namespace' => 'App\Controllers\Admin'], function ($routes) { - $routes->add('/', 'Home', [ + $routes->get('/', 'Home', [ 'as' => 'admin', ]); - $routes->add('new-podcast', 'Podcast::create', [ - 'as' => 'podcast_create', + $routes->get('my-podcasts', 'Podcast::myPodcasts', [ + 'as' => 'my_podcasts', + ]); + $routes->get('podcasts', 'Podcast::list', [ + 'as' => 'podcast_list', + 'filter' => 'permission:podcasts-list', + ]); + $routes->get('new-podcast', 'Podcast::create', [ + 'as' => 'podcast_create', + 'filter' => 'permission:podcasts-create', + ]); + $routes->post('new-podcast', 'Podcast::attemptCreate', [ + 'filter' => 'permission:podcasts-create', ]); - $routes->add('podcasts', 'Podcast::list', ['as' => 'podcast_list']); - $routes->group('podcasts/@(:podcastName)', function ($routes) { - $routes->add('edit', 'Podcast::edit/$1', [ + // Use ids in admin area to help permission and group lookups + $routes->group('podcasts/(:num)', function ($routes) { + $routes->get('edit', 'Podcast::edit/$1', [ 'as' => 'podcast_edit', ]); + $routes->post('edit', 'Podcast::attemptEdit/$1'); $routes->add('delete', 'Podcast::delete/$1', [ 'as' => 'podcast_delete', ]); - $routes->add('new-episode', 'Episode::create/$1', [ - 'as' => 'episode_create', - ]); - $routes->add('episodes', 'Episode::list/$1', [ + // Podcast episodes + $routes->get('episodes', 'Episode::list/$1', [ 'as' => 'episode_list', ]); + $routes->get('new-episode', 'Episode::create/$1', [ + 'as' => 'episode_create', + ]); + $routes->post('new-episode', 'Episode::attemptCreate/$1'); - $routes->add( - 'episodes/(:episodeSlug)/edit', - 'Episode::edit/$1/$2', + $routes->get('episodes/(:num)/edit', 'Episode::edit/$1/$2', [ + 'as' => 'episode_edit', + ]); + $routes->post('episodes/(:num)/edit', 'Episode::attemptEdit/$1/$2'); + $routes->add('episodes/(:num)/delete', 'Episode::delete/$1/$2', [ + 'as' => 'episode_delete', + ]); + + // Podcast contributors + $routes->get('contributors', 'Contributor::list/$1', [ + 'as' => 'contributor_list', + ]); + $routes->get('add-contributor', 'Contributor::add/$1', [ + 'as' => 'contributor_add', + ]); + $routes->post('add-contributor', 'Contributor::attemptAdd/$1'); + $routes->get( + 'contributors/(:num)/edit', + 'Contributor::edit/$1/$2', [ - 'as' => 'episode_edit', + 'as' => 'contributor_edit', ] ); + $routes->post( + 'contributors/(:num)/edit', + 'Contributor::attemptEdit/$1/$2' + ); $routes->add( - 'episodes/(:episodeSlug)/delete', - 'Episode::delete/$1/$2', - [ - 'as' => 'episode_delete', - ] + 'contributors/(:num)/remove', + 'Contributor::remove/$1/$2', + ['as' => 'contributor_remove'] ); }); // Users - $routes->add('users', 'User::list', ['as' => 'user_list']); - $routes->add('new-user', 'User::create', ['as' => 'user_create']); - - $routes->add('users/@(:any)/ban', 'User::ban/$1', [ - 'as' => 'user_ban', + $routes->get('users', 'User::list', [ + 'as' => 'user_list', + 'filter' => 'permission:users-list', ]); - $routes->add('users/@(:any)/unban', 'User::unBan/$1', [ + $routes->get('new-user', 'User::create', [ + 'as' => 'user_create', + 'filter' => 'permission:users-create', + ]); + $routes->post('new-user', 'User::attemptCreate', [ + 'filter' => 'permission:users-create', + ]); + + $routes->add('users/(:num)/ban', 'User::ban/$1', [ + 'as' => 'user_ban', + 'filter' => 'permission:users-manage_bans', + ]); + $routes->add('users/(:num)/unban', 'User::unBan/$1', [ 'as' => 'user_unban', + 'filter' => 'permission:users-manage_bans', ]); $routes->add( - 'users/@(:any)/force-pass-reset', + 'users/(:num)/force-pass-reset', 'User::forcePassReset/$1', [ 'as' => 'user_force_pass_reset', + 'filter' => 'permission:users-force_pass_reset', ] ); - $routes->add('users/@(:any)/delete', 'User::delete/$1', [ + $routes->add('users/(:num)/delete', 'User::delete/$1', [ 'as' => 'user_delete', + 'filter' => 'permission:users-delete', ]); // My account diff --git a/app/Controllers/Admin/Contributor.php b/app/Controllers/Admin/Contributor.php new file mode 100644 index 00000000..1cf39aee --- /dev/null +++ b/app/Controllers/Admin/Contributor.php @@ -0,0 +1,187 @@ +podcast = $podcast_model->find($params[0]); + + if (count($params) > 1) { + $user_model = new UserModel(); + if ( + !($this->user = $user_model + ->select('users.*') + ->join( + 'users_podcasts', + 'users_podcasts.user_id = users.id' + ) + ->where([ + 'users.id' => $params[1], + 'podcast_id' => $params[0], + ]) + ->first()) + ) { + throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); + } + } + + return $this->$method(); + } + + public function list() + { + $data = [ + 'podcast' => $this->podcast, + ]; + + echo view('admin/contributor/list', $data); + } + + public function add() + { + $user_model = new UserModel(); + $group_model = new GroupModel(); + + $roles = $group_model + ->select('auth_groups.*') + ->like('name', 'podcasts:' . $this->podcast->id, 'after') + ->findAll(); + + $data = [ + 'podcast' => $this->podcast, + 'users' => $user_model->findAll(), + 'roles' => $roles, + ]; + + echo view('admin/contributor/add', $data); + } + + public function attemptAdd() + { + $authorize = Services::authorization(); + + $user_id = (int) $this->request->getPost('user'); + $group_id = (int) $this->request->getPost('role'); + + // Add user to chosen group + $authorize->addUserToGroup($user_id, $group_id); + + (new PodcastModel())->addContributorToPodcast( + $user_id, + $this->podcast->id + ); + + return redirect()->route('contributor_list', [$this->podcast->id]); + } + + public function edit() + { + $group_model = new GroupModel(); + + $roles = $group_model + ->select('auth_groups.*') + ->like('name', 'podcasts:' . $this->podcast->id, 'after') + ->findAll(); + + $user_role = $group_model + ->select('auth_groups.*') + ->join( + 'auth_groups_users', + 'auth_groups_users.group_id = auth_groups.id' + ) + ->where('auth_groups_users.user_id', $this->user->id) + ->like('name', 'podcasts:' . $this->podcast->id, 'after') + ->first(); + + $data = [ + 'podcast' => $this->podcast, + 'user' => $this->user, + 'user_role' => $user_role, + 'roles' => $roles, + ]; + + echo view('admin/contributor/edit', $data); + } + + public function attemptEdit() + { + $authorize = Services::authorization(); + + $group_model = new GroupModel(); + + $group = $group_model + ->select('auth_groups.*') + ->join( + 'auth_groups_users', + 'auth_groups_users.group_id = auth_groups.id' + ) + ->where('user_id', $this->user->id) + ->like('name', 'podcasts:' . $this->podcast->id, 'after') + ->first(); + + $authorize->removeUserFromGroup( + (int) $this->user->id, + (int) $group->id + ); + + $authorize->addUserToGroup( + (int) $this->user->id, + (int) $this->request->getPost('role') + ); + + return redirect()->route('contributor_list', [$this->podcast->id]); + } + + public function remove() + { + $authorize = Services::authorization(); + + $group_model = new GroupModel(); + + $group = $group_model + ->select('auth_groups.*') + ->join( + 'auth_groups_users', + 'auth_groups_users.group_id = auth_groups.id' + ) + ->like('name', 'podcasts:' . $this->podcast->id, 'after') + ->where('user_id', $this->user->id) + ->first(); + + $authorize->removeUserFromGroup( + (int) $this->user->id, + (int) $group->id + ); + + (new PodcastModel())->removeContributorFromPodcast( + $this->user->id, + $this->podcast->id + ); + + return redirect()->route('contributor_list', [$this->podcast->id]); + } +} diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/Episode.php index 105aed97..2dc9aabc 100644 --- a/app/Controllers/Admin/Episode.php +++ b/app/Controllers/Admin/Episode.php @@ -17,23 +17,52 @@ class Episode extends BaseController public function _remap($method, ...$params) { + switch ($method) { + case 'list': + if ( + !has_permission('episodes-list') || + !has_permission("podcasts:$params[0]:episodes-list") + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + case 'edit': + if ( + !has_permission('episodes-edit') || + !has_permission("podcasts:$params[0]:episodes-edit") + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + case 'delete': + if ( + !has_permission('episodes-delete') || + !has_permission("podcasts:$params[0]:episodes-delete") + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + } + $podcast_model = new PodcastModel(); - $this->podcast = $podcast_model->where('name', $params[0])->first(); + $this->podcast = $podcast_model->find($params[0]); if (count($params) > 1) { $episode_model = new EpisodeModel(); if ( - !($episode = $episode_model + !($this->episode = $episode_model ->where([ - 'podcast_id' => $this->podcast->id, - 'slug' => $params[1], + 'id' => $params[1], + 'podcast_id' => $params[0], ]) ->first()) ) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } - $this->episode = $episode; } return $this->$method(); @@ -41,13 +70,8 @@ class Episode extends BaseController public function list() { - $episode_model = new EpisodeModel(); - $data = [ 'podcast' => $this->podcast, - 'all_podcast_episodes' => $episode_model - ->where('podcast_id', $this->podcast->id) - ->find(), ]; return view('admin/episode/list', $data); @@ -57,105 +81,118 @@ class Episode extends BaseController { helper(['form']); - if ( - !$this->validate([ - 'enclosure' => 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]', - 'image' => - 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', - 'title' => 'required', - 'slug' => 'required|regex_match[[a-zA-Z0-9\-]{1,191}]', - 'description' => 'required', - 'type' => 'required', - ]) - ) { - $data = [ - 'podcast' => $this->podcast, - ]; + $data = [ + 'podcast' => $this->podcast, + ]; - echo view('admin/episode/create', $data); - } else { - $new_episode = new \App\Entities\Episode([ - 'podcast_id' => $this->podcast->id, - 'title' => $this->request->getVar('title'), - 'slug' => $this->request->getVar('slug'), - 'enclosure' => $this->request->getFile('enclosure'), - 'pub_date' => $this->request->getVar('pub_date'), - 'description' => $this->request->getVar('description'), - 'image' => $this->request->getFile('image'), - 'explicit' => $this->request->getVar('explicit') or false, - 'number' => $this->request->getVar('episode_number'), - 'season_number' => $this->request->getVar('season_number'), - 'type' => $this->request->getVar('type'), - 'author_name' => $this->request->getVar('author_name'), - 'author_email' => $this->request->getVar('author_email'), - 'block' => $this->request->getVar('block') or false, - ]); + echo view('admin/episode/create', $data); + } - $episode_model = new EpisodeModel(); - $episode_model->save($new_episode); + public function attemptCreate() + { + $rules = [ + 'enclosure' => 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]', + 'image' => + 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', + ]; - return redirect()->route('episode_list', [$this->podcast->name]); + if (!$this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); } + + $new_episode = new \App\Entities\Episode([ + 'podcast_id' => $this->podcast->id, + 'title' => $this->request->getPost('title'), + 'slug' => $this->request->getPost('slug'), + 'enclosure' => $this->request->getFile('enclosure'), + 'pub_date' => $this->request->getPost('pub_date'), + 'description' => $this->request->getPost('description'), + 'image' => $this->request->getFile('image'), + 'explicit' => (bool) $this->request->getPost('explicit'), + 'number' => $this->request->getPost('episode_number'), + 'season_number' => $this->request->getPost('season_number'), + 'type' => $this->request->getPost('type'), + 'author_name' => $this->request->getPost('author_name'), + 'author_email' => $this->request->getPost('author_email'), + 'block' => (bool) $this->request->getPost('block'), + ]); + + $episode_model = new EpisodeModel(); + + if (!$episode_model->save($new_episode)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $episode_model->errors()); + } + + return redirect()->route('episode_list', [$this->podcast->id]); } public function edit() { helper(['form']); - if ( - !$this->validate([ - 'enclosure' => - 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]|permit_empty', - 'image' => - 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', - 'title' => 'required', - 'slug' => 'required|regex_match[[a-zA-Z0-9\-]{1,191}]', - 'description' => 'required', - 'type' => 'required', - ]) - ) { - $data = [ - 'podcast' => $this->podcast, - 'episode' => $this->episode, - ]; + $data = [ + 'podcast' => $this->podcast, + 'episode' => $this->episode, + ]; - echo view('admin/episode/edit', $data); - } else { - $this->episode->title = $this->request->getVar('title'); - $this->episode->slug = $this->request->getVar('slug'); - $this->episode->pub_date = $this->request->getVar('pub_date'); - $this->episode->description = $this->request->getVar('description'); - $this->episode->explicit = - ($this->request->getVar('explicit') or false); - $this->episode->number = $this->request->getVar('episode_number'); - $this->episode->season_number = $this->request->getVar( - 'season_number' - ) - ? $this->request->getVar('season_number') - : null; - $this->episode->type = $this->request->getVar('type'); - $this->episode->author_name = $this->request->getVar('author_name'); - $this->episode->author_email = $this->request->getVar( - 'author_email' - ); - $this->episode->block = ($this->request->getVar('block') or false); + echo view('admin/episode/edit', $data); + } - $enclosure = $this->request->getFile('enclosure'); - if ($enclosure->isValid()) { - $this->episode->enclosure = $this->request->getFile( - 'enclosure' - ); - } - $image = $this->request->getFile('image'); - if ($image) { - $this->episode->image = $this->request->getFile('image'); - } + public function attemptEdit() + { + $rules = [ + 'enclosure' => + 'uploaded[enclosure]|ext_in[enclosure,mp3,m4a]|permit_empty', + 'image' => + 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', + ]; - $episode_model = new EpisodeModel(); - $episode_model->save($this->episode); - - return redirect()->route('episode_list', [$this->podcast->name]); + if (!$this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); } + + $this->episode->title = $this->request->getPost('title'); + $this->episode->slug = $this->request->getPost('slug'); + $this->episode->pub_date = $this->request->getPost('pub_date'); + $this->episode->description = $this->request->getPost('description'); + $this->episode->explicit = (bool) $this->request->getPost('explicit'); + $this->episode->number = $this->request->getPost('episode_number'); + $this->episode->season_number = $this->request->getPost('season_number') + ? $this->request->getPost('season_number') + : null; + $this->episode->type = $this->request->getPost('type'); + $this->episode->author_name = $this->request->getPost('author_name'); + $this->episode->author_email = $this->request->getPost('author_email'); + $this->episode->block = (bool) $this->request->getPost('block'); + + $enclosure = $this->request->getFile('enclosure'); + if ($enclosure->isValid()) { + $this->episode->enclosure = $enclosure; + } + $image = $this->request->getFile('image'); + if ($image) { + $this->episode->image = $image; + } + + $episode_model = new EpisodeModel(); + + if (!$episode_model->save($this->episode)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $episode_model->errors()); + } + + return redirect()->route('episode_list', [$this->podcast->id]); } public function delete() @@ -163,6 +200,6 @@ class Episode extends BaseController $episode_model = new EpisodeModel(); $episode_model->delete($this->episode->id); - return redirect()->route('episode_list', [$this->podcast->name]); + return redirect()->route('episode_list', [$this->podcast->id]); } } diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/Podcast.php index 502f1532..3fa3110b 100644 --- a/app/Controllers/Admin/Podcast.php +++ b/app/Controllers/Admin/Podcast.php @@ -6,7 +6,6 @@ */ namespace App\Controllers\Admin; -use App\Entities\UserPodcast; use App\Models\CategoryModel; use App\Models\LanguageModel; use App\Models\PodcastModel; @@ -18,18 +17,59 @@ class Podcast extends BaseController public function _remap($method, ...$params) { if (count($params) > 0) { + switch ($method) { + case 'edit': + if ( + !has_permission('podcasts-edit') || + !has_permission("podcasts:$params[0]-edit") + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + case 'delete': + if ( + !has_permission('podcasts-delete') || + !has_permission("podcasts:$params[0]-delete") + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + case 'listContributors': + case 'addContributor': + case 'editContributor': + case 'deleteContributor': + if ( + !has_permission('podcasts-manage_contributors') || + !has_permission( + "podcasts:$params[0]-manage_contributors" + ) + ) { + throw new \RuntimeException( + lang('Auth.notEnoughPrivilege') + ); + } + } + $podcast_model = new PodcastModel(); - if ( - !($podcast = $podcast_model->where('name', $params[0])->first()) - ) { + if (!($this->podcast = $podcast_model->find($params[0]))) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } - $this->podcast = $podcast; } return $this->$method(); } + public function myPodcasts() + { + $data = [ + 'all_podcasts' => (new PodcastModel())->getUserPodcasts(user()->id), + ]; + + return view('admin/podcast/list', $data); + } + public function list() { $podcast_model = new PodcastModel(); @@ -42,133 +82,141 @@ class Podcast extends BaseController public function create() { helper(['form', 'misc']); - $podcast_model = new PodcastModel(); - if ( - !$this->validate([ - 'title' => 'required', - 'name' => 'required|regex_match[[a-zA-Z0-9\_]{1,191}]', - 'description' => 'required|max_length[4000]', - 'image' => - 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]', - 'owner_email' => 'required|valid_email', - 'type' => 'required', - ]) - ) { - $languageModel = new LanguageModel(); - $categoryModel = new CategoryModel(); - $data = [ - 'languages' => $languageModel->findAll(), - 'categories' => $categoryModel->findAll(), - 'browser_lang' => get_browser_language( - $this->request->getServer('HTTP_ACCEPT_LANGUAGE') - ), - ]; + $languageModel = new LanguageModel(); + $categoryModel = new CategoryModel(); + $data = [ + 'languages' => $languageModel->findAll(), + 'categories' => $categoryModel->findAll(), + 'browser_lang' => get_browser_language( + $this->request->getServer('HTTP_ACCEPT_LANGUAGE') + ), + ]; - echo view('admin/podcast/create', $data); - } else { - $podcast = new \App\Entities\Podcast([ - 'title' => $this->request->getVar('title'), - 'name' => $this->request->getVar('name'), - 'description' => $this->request->getVar('description'), - 'episode_description_footer' => $this->request->getVar( - 'episode_description_footer' - ), - 'image' => $this->request->getFile('image'), - 'language' => $this->request->getVar('language'), - 'category' => $this->request->getVar('category'), - 'explicit' => $this->request->getVar('explicit') or false, - 'author_name' => $this->request->getVar('author_name'), - 'author_email' => $this->request->getVar('author_email'), - 'owner_name' => $this->request->getVar('owner_name'), - 'owner_email' => $this->request->getVar('owner_email'), - 'type' => $this->request->getVar('type'), - 'copyright' => $this->request->getVar('copyright'), - 'block' => $this->request->getVar('block') or false, - 'complete' => $this->request->getVar('complete') or false, - 'custom_html_head' => $this->request->getVar( - 'custom_html_head' - ), - ]); + echo view('admin/podcast/create', $data); + } - $db = \Config\Database::connect(); + public function attemptCreate() + { + $rules = [ + 'image' => 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]', + ]; - $db->transStart(); - - $new_podcast_id = $podcast_model->insert($podcast, true); - - $user_podcast_model = new \App\Models\UserPodcastModel(); - $user_podcast_model->save([ - 'user_id' => user()->id, - 'podcast_id' => $new_podcast_id, - ]); - - $db->transComplete(); - - return redirect()->route('podcast_list', [$podcast->name]); + if (!$this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); } + + $podcast = new \App\Entities\Podcast([ + 'title' => $this->request->getPost('title'), + 'name' => $this->request->getPost('name'), + 'description' => $this->request->getPost('description'), + 'episode_description_footer' => $this->request->getPost( + 'episode_description_footer' + ), + 'image' => $this->request->getFile('image'), + 'language' => $this->request->getPost('language'), + 'category' => $this->request->getPost('category'), + 'explicit' => (bool) $this->request->getPost('explicit'), + 'author_name' => $this->request->getPost('author_name'), + 'author_email' => $this->request->getPost('author_email'), + 'owner' => user(), + 'owner_name' => $this->request->getPost('owner_name'), + 'owner_email' => $this->request->getPost('owner_email'), + 'type' => $this->request->getPost('type'), + 'copyright' => $this->request->getPost('copyright'), + 'block' => (bool) $this->request->getPost('block'), + 'complete' => (bool) $this->request->getPost('complete'), + 'custom_html_head' => $this->request->getPost('custom_html_head'), + ]); + + $podcast_model = new PodcastModel(); + $db = \Config\Database::connect(); + + $db->transStart(); + + if (!($new_podcast_id = $podcast_model->insert($podcast, true))) { + $db->transComplete(); + return redirect() + ->back() + ->withInput() + ->with('errors', $podcast_model->errors()); + } + + $podcast_model->addContributorToPodcast(user()->id, $new_podcast_id); + + $db->transComplete(); + + return redirect()->route('podcast_list'); } public function edit() { - helper(['form', 'misc']); + helper('form'); - if ( - !$this->validate([ - 'title' => 'required', - 'name' => 'required|regex_match[[a-zA-Z0-9\_]{1,191}]', - 'description' => 'required|max_length[4000]', - 'image' => - 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', - 'owner_email' => 'required|valid_email', - 'type' => 'required', - ]) - ) { - $languageModel = new LanguageModel(); - $categoryModel = new CategoryModel(); - $data = [ - 'podcast' => $this->podcast, - 'languages' => $languageModel->findAll(), - 'categories' => $categoryModel->findAll(), - ]; + $languageModel = new LanguageModel(); + $categoryModel = new CategoryModel(); + $data = [ + 'podcast' => $this->podcast, + 'languages' => $languageModel->findAll(), + 'categories' => $categoryModel->findAll(), + ]; - echo view('admin/podcast/edit', $data); - } else { - $this->podcast->title = $this->request->getVar('title'); - $this->podcast->name = $this->request->getVar('name'); - $this->podcast->description = $this->request->getVar('description'); - $this->podcast->episode_description_footer = $this->request->getVar( - 'episode_description_footer' - ); + echo view('admin/podcast/edit', $data); + } - $image = $this->request->getFile('image'); - if ($image->isValid()) { - $this->podcast->image = $this->request->getFile('image'); - } - $this->podcast->language = $this->request->getVar('language'); - $this->podcast->category = $this->request->getVar('category'); - $this->podcast->explicit = - ($this->request->getVar('explicit') or false); - $this->podcast->author_name = $this->request->getVar('author_name'); - $this->podcast->author_email = $this->request->getVar( - 'author_email' - ); - $this->podcast->owner_name = $this->request->getVar('owner_name'); - $this->podcast->owner_email = $this->request->getVar('owner_email'); - $this->podcast->type = $this->request->getVar('type'); - $this->podcast->copyright = $this->request->getVar('copyright'); - $this->podcast->block = ($this->request->getVar('block') or false); - $this->podcast->complete = - ($this->request->getVar('complete') or false); - $this->podcast->custom_html_head = $this->request->getVar( - 'custom_html_head' - ); + public function attemptEdit() + { + $rules = [ + 'image' => + 'uploaded[image]|is_image[image]|ext_in[image,jpg,png]|permit_empty', + ]; - $podcast_model = new PodcastModel(); - $podcast_model->save($this->podcast); - - return redirect()->route('podcast_list', [$this->podcast->name]); + if (!$this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); } + + $this->podcast->title = $this->request->getPost('title'); + $this->podcast->name = $this->request->getPost('name'); + $this->podcast->description = $this->request->getPost('description'); + $this->podcast->episode_description_footer = $this->request->getPost( + 'episode_description_footer' + ); + + $image = $this->request->getFile('image'); + if ($image->isValid()) { + $this->podcast->image = $image; + } + $this->podcast->language = $this->request->getPost('language'); + $this->podcast->category = $this->request->getPost('category'); + $this->podcast->explicit = (bool) $this->request->getPost('explicit'); + $this->podcast->author_name = $this->request->getPost('author_name'); + $this->podcast->author_email = $this->request->getPost('author_email'); + $this->podcast->owner_name = $this->request->getPost('owner_name'); + $this->podcast->owner_email = $this->request->getPost('owner_email'); + $this->podcast->type = $this->request->getPost('type'); + $this->podcast->copyright = $this->request->getPost('copyright'); + $this->podcast->block = (bool) $this->request->getPost('block'); + $this->podcast->complete = (bool) $this->request->getPost('complete'); + $this->podcast->custom_html_head = $this->request->getPost( + 'custom_html_head' + ); + + $podcast_model = new PodcastModel(); + + if (!$podcast_model->save($this->podcast)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $podcast_model->errors()); + } + + return redirect()->route('podcast_list'); } public function delete() diff --git a/app/Controllers/Admin/User.php b/app/Controllers/Admin/User.php index 4faffc23..4a8342f5 100644 --- a/app/Controllers/Admin/User.php +++ b/app/Controllers/Admin/User.php @@ -17,12 +17,9 @@ class User extends BaseController { if (count($params) > 0) { $user_model = new UserModel(); - if ( - !($user = $user_model->where('username', $params[0])->first()) - ) { + if (!($this->user = $user_model->find($params[0]))) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } - $this->user = $user; } return $this->$method(); @@ -38,6 +35,11 @@ class User extends BaseController } public function create() + { + echo view('admin/user/create'); + } + + public function attemptCreate() { $user_model = new UserModel(); @@ -53,30 +55,33 @@ class User extends BaseController ); if (!$this->validate($rules)) { - echo view('admin/user/create'); - } else { - // Save the user - $user = new \Myth\Auth\Entities\User($this->request->getPost()); - - // Activate user - $user->activate(); - - // Force user to reset his password on first connection - $user->force_pass_reset = true; - $user->generateResetHash(); - - if (!$user_model->save($user)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $user_model->errors()); - } - - // Success! return redirect() - ->route('user_list') - ->with('message', lang('User.createSuccess')); + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); } + + // Save the user + $user = new \Myth\Auth\Entities\User($this->request->getPost()); + + // Activate user + $user->activate(); + + // Force user to reset his password on first connection + $user->force_pass_reset = true; + $user->generateResetHash(); + + if (!$user_model->save($user)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $user_model->errors()); + } + + // Success! + return redirect() + ->route('user_list') + ->with('message', lang('User.createSuccess')); } public function forcePassReset() diff --git a/app/Controllers/Episode.php b/app/Controllers/Episode.php index 4721a658..b5174ad6 100644 --- a/app/Controllers/Episode.php +++ b/app/Controllers/Episode.php @@ -24,7 +24,7 @@ class Episode extends BaseController if (count($params) > 1) { $episode_model = new EpisodeModel(); if ( - !($episode = $episode_model + !($this->episode = $episode_model ->where([ 'podcast_id' => $this->podcast->id, 'slug' => $params[1], @@ -33,7 +33,6 @@ class Episode extends BaseController ) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } - $this->episode = $episode; } return $this->$method(); diff --git a/app/Controllers/Podcast.php b/app/Controllers/Podcast.php index 70db9d60..5fd0e141 100644 --- a/app/Controllers/Podcast.php +++ b/app/Controllers/Podcast.php @@ -17,11 +17,12 @@ class Podcast extends BaseController if (count($params) > 0) { $podcast_model = new PodcastModel(); if ( - !($podcast = $podcast_model->where('name', $params[0])->first()) + !($this->podcast = $podcast_model + ->where('name', $params[0]) + ->first()) ) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); } - $this->podcast = $podcast; } return $this->$method(); diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php index 4cf12a61..cd35fe37 100644 --- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php +++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php @@ -81,17 +81,23 @@ class AddPodcasts extends Migration 'Email of the group responsible for creating the show. Show author most often refers to the parent company or network of a podcast, but it can also be used to identify the host(s) if none exists. Author information is especially useful if a company or organization publishes multiple podcasts. Providing this information will allow listeners to see all shows created by the same entity.', 'null' => true, ], + 'owner_id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'unsigned' => true, + 'comment' => 'The podcast owner.', + ], 'owner_name' => [ 'type' => 'VARCHAR', 'constraint' => 1024, - 'owner_name' => + 'comment' => 'The podcast owner name. Note: The owner information is for administrative communication about the podcast and isn’t displayed in Apple Podcasts.', 'null' => true, ], 'owner_email' => [ 'type' => 'VARCHAR', 'constraint' => 1024, - 'owner_email' => + 'comment' => 'The podcast owner email address. Note: The owner information is for administrative communication about the podcast and isn’t displayed in Apple Podcasts. Please make sure the email address is active and monitored.', 'null' => true, ], @@ -147,6 +153,7 @@ class AddPodcasts extends Migration ], ]); $this->forge->addKey('id', true); + $this->forge->addForeignKey('owner_id', 'users', 'id'); $this->forge->createTable('podcasts'); } diff --git a/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php b/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php index 16381819..abed46d5 100644 --- a/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php +++ b/app/Database/Migrations/2020-07-03-191500_add_users_podcasts.php @@ -17,12 +17,6 @@ class AddUsersPodcasts extends Migration public function up() { $this->forge->addField([ - 'id' => [ - 'type' => 'BIGINT', - 'constraint' => 20, - 'unsigned' => true, - 'auto_increment' => true, - ], 'user_id' => [ 'type' => 'INT', 'constraint' => 11, @@ -34,8 +28,7 @@ class AddUsersPodcasts extends Migration 'unsigned' => true, ], ]); - $this->forge->addPrimaryKey('id'); - $this->forge->addUniqueKey(['user_id', 'podcast_id']); + $this->forge->addPrimaryKey(['user_id', 'podcast_id']); $this->forge->addForeignKey('user_id', 'users', 'id'); $this->forge->addForeignKey('podcast_id', 'podcasts', 'id'); $this->forge->createTable('users_podcasts'); diff --git a/app/Database/Seeds/AuthSeeder.php b/app/Database/Seeds/AuthSeeder.php new file mode 100644 index 00000000..cbbbe4f1 --- /dev/null +++ b/app/Database/Seeds/AuthSeeder.php @@ -0,0 +1,153 @@ + 1, 'name' => 'superadmin', 'description' => '']]; + + /** Build permissions array as a list of: + * + * ``` + * context => [ + * [action, description], + * [action, description], + * ... + * ] + * ``` + */ + $permissions = [ + 'users' => [ + ['name' => 'create', 'description' => 'Create a user'], + ['name' => 'list', 'description' => 'List all users'], + [ + 'name' => 'manage_authorizations', + 'description' => + 'Add or remove roles/permissions to a user', + ], + [ + 'name' => 'manage_bans', + 'description' => 'Ban / unban a user', + ], + [ + 'name' => 'force_pass_reset', + 'description' => + 'Force a user to update his password upon next login', + ], + [ + 'name' => 'delete', + 'description' => + 'Delete user without removing him from database', + ], + [ + 'name' => 'delete_permanently', + 'description' => + 'Delete all occurrences of a user from the database', + ], + ], + 'podcasts' => [ + ['name' => 'create', 'description' => 'Add a new podcast'], + [ + 'name' => 'list', + 'description' => 'List all podcasts and their episodes', + ], + ['name' => 'edit', 'description' => 'Edit any podcast'], + [ + 'name' => 'manage_contributors', + 'description' => 'Add / remove contributors to a podcast', + ], + [ + 'name' => 'manage_publication', + 'description' => 'Publish / unpublish a podcast', + ], + [ + 'name' => 'delete', + 'description' => + 'Delete a podcast without removing it from database', + ], + [ + 'name' => 'delete_permanently', + 'description' => 'Delete any podcast from the database', + ], + ], + 'episodes' => [ + [ + 'name' => 'list', + 'description' => 'List all episodes of any podcast', + ], + [ + 'name' => 'create', + 'description' => 'Add a new episode to any podcast', + ], + ['name' => 'edit', 'description' => 'Edit any podcast episode'], + [ + 'name' => 'manage_publications', + 'description' => 'Publish / unpublish any podcast episode', + ], + [ + 'name' => 'delete', + 'description' => + 'Delete any podcast episode without removing it from database', + ], + [ + 'name' => 'delete_permanently', + 'description' => 'Delete any podcast episode from database', + ], + ], + ]; + + // Map permissions to a format the `auth_permissions` table expects + $data_permissions = []; + $data_groups_permissions = []; + $permission_id = 0; + foreach ($permissions as $context => $actions) { + foreach ($actions as $action) { + array_push($data_permissions, [ + 'id' => ++$permission_id, + 'name' => get_permission($context, $action['name']), + 'description' => $action['description'], + ]); + + // add all permissions to superadmin + array_push($data_groups_permissions, [ + 'group_id' => 1, + 'permission_id' => $permission_id, + ]); + } + } + + $this->db->table('auth_permissions')->insertBatch($data_permissions); + $this->db->table('auth_groups')->insertBatch($groups); + $this->db + ->table('auth_groups_permissions') + ->insertBatch($data_groups_permissions); + + // TODO: Remove superadmin user as it is used for testing purposes + $this->db->table('users')->insert([ + 'id' => 1, + 'username' => 'admin', + 'email' => 'admin@castopod.com', + 'password_hash' => + // password: AGUehL3P + '$2y$10$TXJEHX/djW8jtzgpDVf7dOOCGo5rv1uqtAYWdwwwkttQcDkAeB2.6', + 'active' => 1, + ]); + $this->db + ->table('auth_groups_users') + ->insert(['group_id' => 1, 'user_id' => 1]); + } +} diff --git a/app/Database/Seeds/UserSeeder.php b/app/Database/Seeds/UserSeeder.php deleted file mode 100644 index 826f1332..00000000 --- a/app/Database/Seeds/UserSeeder.php +++ /dev/null @@ -1,30 +0,0 @@ - 'admin', - 'email' => 'admin@castopod.com', - 'password_hash' => - // password: AGUehL3P - '$2y$10$TXJEHX/djW8jtzgpDVf7dOOCGo5rv1uqtAYWdwwwkttQcDkAeB2.6', - 'active' => 1, - ]; - - $this->db->table('users')->insert($data); - } -} diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 386be65c..edd59e2b 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -9,6 +9,7 @@ namespace App\Entities; use App\Models\EpisodeModel; use CodeIgniter\Entity; +use Myth\Auth\Models\UserModel; class Podcast extends Entity { @@ -17,6 +18,8 @@ class Podcast extends Entity protected $image_media_path; protected $image_url; protected $episodes; + protected $owner; + protected $contributors; protected $casts = [ 'id' => 'integer', @@ -29,6 +32,7 @@ class Podcast extends Entity 'explicit' => 'boolean', 'author_name' => '?string', 'author_email' => '?string', + 'owner_id' => 'integer', 'owner_name' => '?string', 'owner_email' => '?string', 'type' => 'string', @@ -92,7 +96,7 @@ class Podcast extends Entity ); } - if (empty($this->permissions)) { + if (empty($this->episodes)) { $this->episodes = (new EpisodeModel())->getPodcastEpisodes( $this->id ); @@ -100,4 +104,40 @@ class Podcast extends Entity return $this->episodes; } + + /** + * Returns the podcast owner + * + * @return \Myth\Auth\Entities\User + */ + public function getOwner() + { + if (empty($this->id)) { + throw new \RuntimeException( + 'Podcast must be created before getting owner.' + ); + } + + if (empty($this->owner)) { + $this->owner = (new UserModel())->find($this->owner_id); + } + + return $this->owner; + } + + public function setOwner(\Myth\Auth\Entities\User $user) + { + $this->attributes['owner_id'] = $user->id; + + return $this; + } + + public function getContributors() + { + return (new UserModel()) + ->select('users.*') + ->join('users_podcasts', 'users_podcasts.user_id = users.id') + ->where('users_podcasts.podcast_id', $this->attributes['id']) + ->findAll(); + } } diff --git a/app/Entities/UserPodcast.php b/app/Entities/UserPodcast.php deleted file mode 100644 index d951557d..00000000 --- a/app/Entities/UserPodcast.php +++ /dev/null @@ -1,18 +0,0 @@ - 'integer', - 'podcast_id' => 'integer', - ]; -} diff --git a/app/Helpers/auth_helper.php b/app/Helpers/auth_helper.php new file mode 100644 index 00000000..344e0636 --- /dev/null +++ b/app/Helpers/auth_helper.php @@ -0,0 +1,19 @@ + 'Podcast contributors', + 'add' => 'Add contributor', + 'add_contributor' => 'Add a contributor for {0}', + 'edit_role' => 'Update role for {0}', + 'edit' => 'Edit', + 'remove' => 'Remove', + 'form' => [ + 'user' => 'User', + 'role' => 'Role', + 'submit_add' => 'Add contributor', + 'submit_edit' => 'Update role' + ] +]; diff --git a/app/Language/en/Episode.php b/app/Language/en/Episode.php index 22ff6a53..80ae2df6 100644 --- a/app/Language/en/Episode.php +++ b/app/Language/en/Episode.php @@ -7,7 +7,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', - 'create_one' => 'Add a new one', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', 'delete' => 'Delete', diff --git a/app/Language/en/MyAccount.php b/app/Language/en/MyAccount.php index c1935bcc..f32684b7 100644 --- a/app/Language/en/MyAccount.php +++ b/app/Language/en/MyAccount.php @@ -7,5 +7,6 @@ return [ 'passwordChangeSuccess' => 'Password has been successfully changed!', - 'changePassword' => 'Change my password' + 'changePassword' => 'Change my password', + 'info' => 'My account info' ]; diff --git a/app/Language/en/Podcast.php b/app/Language/en/Podcast.php index 767d54e0..54601135 100644 --- a/app/Language/en/Podcast.php +++ b/app/Language/en/Podcast.php @@ -8,13 +8,13 @@ return [ 'all_podcasts' => 'All podcasts', 'no_podcast' => 'No podcast found!', - 'create_one' => 'Add a new one', 'create' => 'Create a Podcast', 'new_episode' => 'New Episode', 'feed' => 'RSS feed', 'edit' => 'Edit', 'delete' => 'Delete', 'see_episodes' => 'See episodes', + 'see_contributors' => 'See contributors', 'goto_page' => 'Go to page', 'form' => [ 'title' => 'Title', diff --git a/app/Language/en/User.php b/app/Language/en/User.php index fcf9134c..c9e0fc03 100644 --- a/app/Language/en/User.php +++ b/app/Language/en/User.php @@ -10,11 +10,13 @@ return [ 'forcePassResetSuccess' => 'The user will be prompted with a password reset during his next login attempt.', 'banSuccess' => 'User has been banned.', 'unbanSuccess' => 'User has been unbanned.', + 'deleteSuccess' => 'User has been deleted.', 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'Delete', 'create' => 'Create a user', + 'all_users' => 'All users', 'form' => [ 'email' => 'Email', 'username' => 'Username', diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index ed2ea4e9..eb372fa4 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -19,11 +19,8 @@ class EpisodeModel extends Model 'title', 'slug', 'enclosure_uri', - 'enclosure_length', - 'enclosure_type', 'pub_date', 'description', - 'duration', 'image_uri', 'explicit', 'number', @@ -39,6 +36,21 @@ class EpisodeModel extends Model protected $useSoftDeletes = true; protected $useTimestamps = true; + protected $validationRules = [ + 'podcast_id' => 'required', + 'title' => 'required', + 'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,191}$/]', + 'enclosure_uri' => 'required', + 'pub_date' => 'required|valid_date', + 'description' => 'required', + 'image_uri' => 'required', + 'number' => 'required', + 'season_number' => 'required', + 'author_email' => 'valid_email|permit_empty', + 'type' => 'required', + ]; + protected $validationMessages = []; + protected $afterInsert = ['writeEnclosureMetadata', 'clearCache']; protected $afterUpdate = ['writeEnclosureMetadata', 'clearCache']; diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index 09712b6a..8d7365a9 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -8,6 +8,8 @@ namespace App\Models; use CodeIgniter\Model; +use Myth\Auth\Authorization\GroupModel; +use Myth\Auth\Config\Services; class PodcastModel extends Model { @@ -26,6 +28,7 @@ class PodcastModel extends Model 'explicit', 'author_name', 'author_email', + 'owner_id', 'owner_name', 'owner_email', 'type', @@ -40,8 +43,60 @@ class PodcastModel extends Model protected $useTimestamps = true; - protected $afterInsert = ['clearCache']; + protected $validationRules = [ + 'title' => 'required', + 'name' => + 'required|regex_match[/^[a-zA-Z0-9\_]{1,191}$/]|is_unique[podcasts.name,id,{id}]', + 'description' => 'required', + 'image_uri' => 'required', + 'language' => 'required', + 'category' => 'required', + 'author_email' => 'valid_email|permit_empty', + 'owner_id' => 'required', + 'owner_email' => 'required|valid_email', + 'type' => 'required', + ]; + protected $validationMessages = []; + + protected $afterInsert = ['clearCache', 'createPodcastPermissions']; protected $afterUpdate = ['clearCache']; + protected $beforeDelete = ['clearCache']; + + /** + * Gets all the podcasts a given user is contributing to + * + * @param int $user_id + * + * @return \App\Entities\Podcast[] podcasts + */ + public function getUserPodcasts($user_id) + { + return $this->select('podcasts.*') + ->join('users_podcasts', 'users_podcasts.podcast_id = podcasts.id') + ->where('users_podcasts.user_id', $user_id) + ->findAll(); + } + + public function addContributorToPodcast($user_id, $podcast_id) + { + $data = [ + 'user_id' => (int) $user_id, + 'podcast_id' => (int) $podcast_id, + ]; + + return $this->db->table('users_podcasts')->insert($data); + } + + public function removeContributorFromPodcast($user_id, $podcast_id) + { + return $this->db + ->table('users_podcasts') + ->where([ + 'user_id' => $user_id, + 'podcast_id' => $podcast_id, + ]) + ->delete(); + } protected function clearCache(array $data) { @@ -56,5 +111,95 @@ class PodcastModel extends Model // foreach ($podcast->episodes as $episode) { // $cache->delete(md5($episode->link)); // } + + $data['podcast'] = $podcast; + + return $data; + } + + protected function createPodcastPermissions(array $data) + { + $authorize = Services::authorization(); + + $podcast = $data['podcast']; + + $podcast_permissions = [ + 'podcasts:' . $podcast->id => [ + [ + 'name' => 'edit', + 'description' => "Edit the $podcast->name podcast", + ], + [ + 'name' => 'delete', + 'description' => "Delete the $podcast->name podcast without removing it from the database", + ], + [ + 'name' => 'delete_permanently', + 'description' => "Delete the $podcast->name podcast from the database", + ], + [ + 'name' => 'manage_contributors', + 'description' => "Add / remove contributors to the $podcast->name podcast and edit their roles", + ], + [ + 'name' => 'manage_publication', + 'description' => "Publish / unpublish $podcast->name", + ], + ], + 'podcasts:' . $podcast->id . ':episodes' => [ + [ + 'name' => 'list', + 'description' => "List all episodes of the $podcast->name podcast", + ], + [ + 'name' => 'create', + 'description' => "Add new episodes for the $podcast->name podcast", + ], + [ + 'name' => 'edit', + 'description' => "Edit an episode of the $podcast->name podcast", + ], + [ + 'name' => 'delete', + 'description' => "Delete an episode of the $podcast->name podcast without removing it from the database", + ], + [ + 'name' => 'delete_permanently', + 'description' => "Delete all occurrences of an episode of the $podcast->name podcast from the database", + ], + [ + 'name' => 'manage_publications', + 'description' => "Publish / unpublish episodes of the $podcast->name podcast", + ], + ], + ]; + + $group_model = new GroupModel(); + $owner_group_id = $group_model->insert( + [ + 'name' => "podcasts:$podcast->id" . '_owner', + 'description' => "The owner of the $podcast->name podcast", + ], + true + ); + + // add podcast owner to owner group + $authorize->addUserToGroup($podcast->owner_id, $owner_group_id); + + foreach ($podcast_permissions as $context => $actions) { + foreach ($actions as $action) { + $permission_id = $authorize->createPermission( + get_permission($context, $action['name']), + $action['description'] + ); + + $authorize->addPermissionToGroup( + $permission_id, + $owner_group_id + ); + } + } + + return $data; } } diff --git a/app/Models/UserPodcastModel.php b/app/Models/UserPodcastModel.php deleted file mode 100644 index 32d36b05..00000000 --- a/app/Models/UserPodcastModel.php +++ /dev/null @@ -1,23 +0,0 @@ -has('message')): ?> -
+
has('error')): ?> -
+
has('errors')): ?> -