sintonia/legacy/application/controllers/PreferenceController.php
Thomas Göttgens 170d09545e
feat(legacy): disable public radio page and redirect to login (#2903)
### Description

Many people don't need the public page and use libretime purely for
playout management. This adds the ability to have libretime publicly
available but only present the login page to the user.

**I have updated the documentation to reflect these changes**:

no, but i will add documentation if this PR is accepted.

### Testing Notes

**What I did:**

Toggle the new ceckbox on the general settings, log out and back in and
check behaviour.

note: this may have conflicts with the trim overbooked PR since the
toggle sits in the same place. If both are accepted this needs to be
formatted nicely :-)

---------

Co-authored-by: Thomas Göttgens <tgoettgens@mail.com>
Co-authored-by: Jonas L. <jooola@users.noreply.github.com>
Co-authored-by: Kyle Robbertze <paddatrapper@users.noreply.github.com>
Co-authored-by: jo <ljonas@riseup.net>
2024-02-02 19:04:12 +01:00

388 lines
16 KiB
PHP

<?php
class PreferenceController extends Zend_Controller_Action
{
public function init()
{
// Initialize action controller here
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('server-browse', 'json')
->addActionContext('change-stor-directory', 'json')
->addActionContext('reload-watch-directory', 'json')
->addActionContext('remove-watch-directory', 'json')
->addActionContext('is-import-in-progress', 'json')
->addActionContext('change-stream-setting', 'json')
->addActionContext('get-liquidsoap-status', 'json')
->addActionContext('get-admin-password-status', 'json')
->initContext();
}
public function indexAction()
{
$request = $this->getRequest();
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
$baseUrl = Config::getBasePath();
$this->view->headScript()->appendFile(Assets::url('js/airtime/preferences/preferences.js'), 'text/javascript');
$this->view->statusMsg = '';
$form = new Application_Form_Preferences();
$values = [];
SessionHelper::reopenSessionForWriting();
if ($request->isPost()) {
$values = $request->getPost();
if ($form->isValid($values)) {
Application_Model_Preference::SetHeadTitle($values['stationName'], $this->view);
Application_Model_Preference::SetStationDescription($values['stationDescription']);
Application_Model_Preference::SetTrackTypeDefault($values['tracktypeDefault']);
Application_Model_Preference::SetDefaultCrossfadeDuration($values['stationDefaultCrossfadeDuration']);
Application_Model_Preference::SetDefaultFadeIn($values['stationDefaultFadeIn']);
Application_Model_Preference::SetDefaultFadeOut($values['stationDefaultFadeOut']);
Application_Model_Preference::SetPodcastAlbumOverride($values['podcastAlbumOverride']);
Application_Model_Preference::SetPodcastAutoSmartblock($values['podcastAutoSmartblock']);
Application_Model_Preference::SetIntroPlaylist($values['introPlaylistSelect']);
Application_Model_Preference::SetOutroPlaylist($values['outroPlaylistSelect']);
Application_Model_Preference::SetAllow3rdPartyApi($values['thirdPartyApi']);
Application_Model_Preference::SetDefaultLocale($values['locale']);
Application_Model_Preference::SetWeekStartDay($values['weekStartDay']);
Application_Model_Preference::setRadioPageDisplayLoginButton($values['radioPageLoginButton']);
Application_Model_Preference::setRadioPageDisabled($values['radioPageDisabled']);
Application_Model_Preference::SetFeaturePreviewMode($values['featurePreviewMode']);
$logoUploadElement = $form->getSubForm('preferences_general')->getElement('stationLogo');
$logoUploadElement->receive();
$imagePath = $logoUploadElement->getFileName();
// Only update the image logo if the new logo is non-empty
if (!empty($imagePath) && $imagePath != '') {
Application_Model_Preference::SetStationLogo($imagePath);
}
Application_Model_Preference::setTuneinEnabled($values['enable_tunein']);
Application_Model_Preference::setTuneinStationId($values['tunein_station_id']);
Application_Model_Preference::setTuneinPartnerKey($values['tunein_partner_key']);
Application_Model_Preference::setTuneinPartnerId($values['tunein_partner_id']);
$this->view->statusMsg = "<div class='success'>" . _('Preferences updated.') . '</div>';
$form = new Application_Form_Preferences();
$this->view->form = $form;
// $this->_helper->json->sendJson(array("valid"=>"true", "html"=>$this->view->render('preference/index.phtml')));
} else {
$this->view->form = $form;
// $this->_helper->json->sendJson(array("valid"=>"false", "html"=>$this->view->render('preference/index.phtml')));
}
}
$this->view->logoImg = Application_Model_Preference::GetStationLogo();
$this->view->form = $form;
}
public function stationPodcastSettingsAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$values = json_decode($this->getRequest()->getRawBody());
if (!Application_Model_Preference::getStationPodcastPrivacy() && $values->stationPodcastPrivacy == 1) {
// Refresh the download key when enabling privacy
Application_Model_Preference::setStationPodcastDownloadKey();
}
// Append sharing token (download key) to Station podcast URL
$stationPodcast = PodcastQuery::create()->findOneByDbId(Application_Model_Preference::getStationPodcastId());
$key = Application_Model_Preference::getStationPodcastDownloadKey();
$url = Config::getPublicUrl() .
(((int) $values->stationPodcastPrivacy) ? "feeds/station-rss?sharing_token={$key}" : 'feeds/station-rss');
$stationPodcast->setDbUrl($url)->save();
Application_Model_Preference::setStationPodcastPrivacy($values->stationPodcastPrivacy);
$this->_helper->json->sendJson(['url' => $url]);
}
public function directoryConfigAction() {}
public function removeLogoAction()
{
SessionHelper::reopenSessionForWriting();
$this->view->layout()->disableLayout();
// Remove reliance on .phtml files to render requests
$this->_helper->viewRenderer->setNoRender(true);
if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) {
Logging::error(__FILE__ . ': Invalid CSRF token');
$this->_helper->json->sendJson(['jsonrpc' => '2.0', 'valid' => false, 'error' => 'CSRF token did not match.']);
return;
}
Application_Model_Preference::SetStationLogo('');
}
public function streamSettingAction()
{
$request = $this->getRequest();
Zend_Layout::getMvcInstance()->assign('parent_page', 'Settings');
$this->view->headScript()->appendFile(Assets::url('js/airtime/preferences/streamsetting.js'), 'text/javascript');
SessionHelper::reopenSessionForWriting();
$name_map = [
'ogg' => 'Ogg Vorbis',
'fdkaac' => 'AAC+',
'aac' => 'AAC',
'opus' => 'Opus',
'mp3' => 'MP3',
];
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
$form = new Application_Form_StreamSetting();
$csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
$csrf_element = new Zend_Form_Element_Hidden('csrf');
$csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
$form->addElement($csrf_element);
$live_stream_subform = new Application_Form_LiveStreamingPreferences();
$form->addSubForm($live_stream_subform, 'live_stream_subform');
// get current settings
$setting = Application_Model_StreamSetting::getStreamSetting();
$form->setSetting($setting);
if ($num_of_stream > MAX_NUM_STREAMS) {
Logging::error('Your streams count (' . $num_of_stream . ') exceed the maximum, some of them will not be displayed');
$num_of_stream = MAX_NUM_STREAMS;
}
for ($i = 1; $i <= $num_of_stream; ++$i) {
$subform = new Application_Form_StreamSettingSubForm();
$subform->setPrefix($i);
$subform->setSetting($setting);
$subform->startForm();
$form->addSubForm($subform, 's' . $i . '_subform');
}
$live_stream_subform->updateVariables();
$form->startFrom();
if ($request->isPost()) {
$params = $request->getPost();
/* Parse through post data and put in format
* $form->isValid() is expecting it in
*/
$postData = explode('&', $params['data']);
$values = [];
foreach ($postData as $k => $v) {
$v = explode('=', urldecode($v));
$values[$v[0]] = $v[1];
}
if ($form->isValid($values)) {
// this goes into cc_pref table
$this->setStreamPreferences($values);
// compare new values with current value
$changeRGenabled = Application_Model_Preference::GetEnableReplayGain() != $values['enableReplayGain'];
$changeRGmodifier = Application_Model_Preference::getReplayGainModifier() != $values['replayGainModifier'];
if ($changeRGenabled || $changeRGmodifier) {
Application_Model_Preference::SetEnableReplayGain($values['enableReplayGain']);
Application_Model_Preference::setReplayGainModifier($values['replayGainModifier']);
$md = ['schedule' => Application_Model_Schedule::getSchedule()];
Application_Model_RabbitMq::SendMessageToPypo('update_schedule', $md);
// Application_Model_RabbitMq::PushSchedule();
}
// store stream update timestamp
Application_Model_Preference::SetStreamUpdateTimestamp();
$this->view->statusMsg = "<div class='success'>" . _('Stream Setting Updated.') . '</div>';
}
}
$this->view->num_stream = $num_of_stream;
$this->view->enable_stream_conf = Application_Model_Preference::GetEnableStreamConf();
$this->view->form = $form;
if ($request->isPost()) {
if ($form->isValid($values)) {
$this->_helper->json->sendJson([
'valid' => 'true',
'html' => $this->view->render('preference/stream-setting.phtml'),
]);
} else {
$this->_helper->json->sendJson(['valid' => 'false', 'html' => $this->view->render('preference/stream-setting.phtml')]);
}
}
}
/**
* Set stream settings preferences.
*
* @param array $values stream setting preference values
*/
private function setStreamPreferences($values)
{
Application_Model_Preference::setOffAirMeta($values['offAirMeta']);
Application_Model_Preference::SetStreamLabelFormat($values['streamFormat']);
Application_Model_Preference::SetLiveStreamMasterUsername($values['master_username']);
Application_Model_Preference::SetLiveStreamMasterPassword($values['master_password']);
Application_Model_Preference::SetDefaultTransitionFade($values['transition_fade']);
Application_Model_Preference::SetAutoTransition($values['auto_transition']);
Application_Model_Preference::SetAutoSwitch($values['auto_switch']);
}
public function serverBrowseAction()
{
$request = $this->getRequest();
$path = $request->getParam('path', null);
$result = [];
if (is_null($path)) {
$element = [];
$element['name'] = _('path should be specified');
$element['isFolder'] = false;
$element['isError'] = true;
$result[$path] = $element;
} else {
$path .= '/';
$handle = opendir($path);
if ($handle !== false) {
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..') {
// only show directories that aren't private.
if (is_dir($path . $file) && substr($file, 0, 1) != '.') {
$element = [];
$element['name'] = $file;
$element['isFolder'] = true;
$element['isError'] = false;
$result[$file] = $element;
}
}
}
}
}
ksort($result);
// returns format serverBrowse is looking for.
$this->_helper->json->sendJson($result);
}
public function isImportInProgressAction()
{
$now = time();
$res = false;
if (Application_Model_Preference::GetImportTimestamp() + 10 > $now) {
$res = true;
}
$this->_helper->json->sendJson($res);
}
public function getLiquidsoapStatusAction()
{
$out = [];
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
for ($i = 1; $i <= $num_of_stream; ++$i) {
$status = Application_Model_Preference::getLiquidsoapError($i);
$status = $status == null ? _('Problem with Liquidsoap...') : $status;
if (!Application_Model_StreamSetting::getStreamEnabled($i)) {
$status = 'N/A';
}
$out[] = ['id' => $i, 'status' => $status];
}
$this->_helper->json->sendJson($out);
}
public function getAdminPasswordStatusAction()
{
SessionHelper::reopenSessionForWriting();
$out = [];
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
for ($i = 1; $i <= $num_of_stream; ++$i) {
if (Application_Model_StreamSetting::getAdminPass('s' . $i) == '') {
$out['s' . $i] = false;
} else {
$out['s' . $i] = true;
}
}
$this->_helper->json->sendJson($out);
}
public function deleteAllFilesAction()
{
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
if (!SecurityHelper::verifyCSRFToken($this->_getParam('csrf_token'))) {
Logging::error(__FILE__ . ': Invalid CSRF token');
$this->_helper->json->sendJson(['jsonrpc' => '2.0', 'valid' => false, 'error' => 'CSRF token did not match.']);
return;
}
// Only admin users should get here through ACL permissioning
// Only allow POST requests
$method = $_SERVER['REQUEST_METHOD'];
if (!($method == 'POST')) {
$this->getResponse()
->setHttpResponseCode(405)
->appendBody(_('Request method not accepted') . ": {$method}");
return;
}
$this->deleteFutureScheduleItems();
$this->deleteStoredFiles();
$this->getResponse()
->setHttpResponseCode(200)
->appendBody('OK');
}
private function deleteFutureScheduleItems()
{
$utcTimezone = new DateTimeZone('UTC');
$nowDateTime = new DateTime('now', $utcTimezone);
$scheduleItems = CcScheduleQuery::create()
->filterByDbEnds($nowDateTime->format(DEFAULT_TIMESTAMP_FORMAT), Criteria::GREATER_THAN)
->find();
// Delete all the schedule items
foreach ($scheduleItems as $i) {
// If this is the currently playing track, cancel the current show
if ($i->isCurrentItem()) {
$instanceId = $i->getDbInstanceId();
$instance = CcShowInstancesQuery::create()->findPk($instanceId);
$showId = $instance->getDbShowId();
// From ScheduleController
$scheduler = new Application_Model_Scheduler();
$scheduler->cancelShow($showId);
Application_Model_StoredFile::updatePastFilesIsScheduled();
}
$i->delete();
}
}
private function deleteStoredFiles()
{
// Delete all files from the database
$files = CcFilesQuery::create()->find();
foreach ($files as $file) {
$storedFile = new Application_Model_StoredFile($file, null);
// Delete the files quietly to avoid getting Sentry errors for
// every S3 file we delete.
$storedFile->delete(true);
}
}
}