Merge branch 'saas' into cc-5709-airtime-analyzer-cloud-storage-saas

Conflicts:
	.gitignore
	airtime_mvc/application/configs/airtime-conf.php
	airtime_mvc/application/configs/classmap-airtime-conf.php
	airtime_mvc/application/models/RabbitMq.php
	airtime_mvc/application/models/Schedule.php
	airtime_mvc/application/models/StoredFile.php
	airtime_mvc/application/models/airtime/map/CcShowInstancesTableMap.php
	airtime_mvc/application/models/airtime/map/CcShowTableMap.php
	airtime_mvc/application/models/airtime/om/BaseCcShow.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstances.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstancesPeer.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstancesQuery.php
	airtime_mvc/application/models/airtime/om/BaseCcShowPeer.php
	airtime_mvc/application/models/airtime/om/BaseCcShowQuery.php
	airtime_mvc/application/modules/rest/Bootstrap.php
	airtime_mvc/application/modules/rest/controllers/MediaController.php
	airtime_mvc/build/sql/schema.sql
	airtime_mvc/public/index.php
This commit is contained in:
drigato 2014-11-03 12:29:58 -05:00
commit 0a45de7fba
163 changed files with 67857 additions and 56085 deletions

View file

@ -1038,7 +1038,7 @@ SQL;
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
// get only the files from the blocks
// we are about to delete

View file

@ -2,30 +2,44 @@
class Cache
{
private function createCacheKey($key, $isUserValue, $userId = null) {
$CC_CONFIG = Config::getConfig();
$a = $CC_CONFIG["apiKey"][0];
if ($isUserValue) {
$cacheKey = "{$key}{$userId}{$a}";
}
else {
$cacheKey = "{$key}{$a}";
}
private function createCacheKey($key, $isUserValue, $userId = null) {
$CC_CONFIG = Config::getConfig();
$a = $CC_CONFIG["apiKey"][0];
if ($isUserValue) {
$cacheKey = "{$key}{$userId}{$a}";
}
else {
$cacheKey = "{$key}{$a}";
}
return $cacheKey;
}
public function store($key, $value, $isUserValue, $userId = null) {
//$cacheKey = self::createCacheKey($key, $userId);
return false; ///apc_store($cacheKey, $value);
}
public function fetch($key, $isUserValue, $userId = null) {
//$cacheKey = self::createCacheKey($key, $isUserValue, $userId);
return false; //apc_fetch($cacheKey);
return $cacheKey;
}
public function store($key, $value, $isUserValue, $userId = null) {
$cacheKey = self::createCacheKey($key, $userId);
//XXX: Disabling APC on SaaS because it turns out we have multiple webservers
// running, which means we have to use a distributed data cache like memcached.
//return apc_store($cacheKey, $value);
return false;
}
public function fetch($key, $isUserValue, $userId = null) {
$cacheKey = self::createCacheKey($key, $isUserValue, $userId);
//XXX: Disabling APC on SaaS because it turns out we have multiple webservers
// running, which means we have to use a distributed data cache like memcached.
//return apc_fetch($cacheKey);
return false;
}
public static function clear()
{
// Disabled on SaaS
// apc_clear_cache('user');
// apc_clear_cache();
}
}

View file

@ -38,10 +38,16 @@ class Application_Model_Locale
} else {
$lang = $locale.'.'.$codeset;
}
putenv("LC_ALL=$lang");
putenv("LANG=$lang");
$res = setlocale(LC_MESSAGES, $lang);
//putenv("LC_ALL=$lang");
//putenv("LANG=$lang");
//Setting the LANGUAGE env var supposedly lets gettext search inside our locale dir even if the system
//doesn't have the particular locale that we want installed. This doesn't actually seem to work though. -- Albert
putenv("LANGUAGE=$locale");
if (setlocale(LC_MESSAGES, $lang) === false)
{
Logging::warn("Your system does not have the " . $lang . " locale installed. Run: sudo locale-gen " . $lang);
}
$domain = 'airtime';
bindtextdomain($domain, '../locale');
textdomain($domain);

View file

@ -987,7 +987,7 @@ SQL;
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
// get only the files from the playlists
// we are about to delete

View file

@ -6,7 +6,7 @@ class Application_Model_Preference
{
private static function getUserId()
{
{
//pass in true so the check is made with the autoloader
//we need this check because saas calls this function from outside Zend
if (!class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) {
@ -733,11 +733,7 @@ class Application_Model_Preference
$outputArray['NUM_OF_PAST_SHOWS'] = Application_Model_ShowInstance::GetShowInstanceCount(gmdate("Y-m-d H:i:s"));
$outputArray['UNIQUE_ID'] = self::GetUniqueId();
$outputArray['SAAS'] = self::GetPlanLevel();
if ($outputArray['SAAS'] != 'disabled') {
$outputArray['TRIAL_END_DATE'] = self::GetTrialEndingDate();
} else {
$outputArray['TRIAL_END_DATE'] = NULL;
}
$outputArray['TRIAL_END_DATE'] = self::GetTrialEndingDate();
$outputArray['INSTALL_METHOD'] = self::GetInstallMethod();
$outputArray['NUM_OF_STREAMS'] = self::GetNumOfStreams();
$outputArray['STREAM_INFO'] = Application_Model_StreamSetting::getStreamInfoForDataCollection();
@ -763,9 +759,7 @@ class Application_Model_Preference
$outputString .= $key." : FALSE\n";
}
} elseif ($key == "SAAS") {
if (strcmp($out, 'disabled')!=0) {
$outputString .= $key.' : '.$out."\n";
}
$outputString .= $key.' : '.$out."\n";
} else {
$outputString .= $key.' : '.$out."\n";
}
@ -1023,6 +1017,24 @@ class Application_Model_Preference
Logging::warn("Attempting to set client_id to invalid value: $id");
}
}
public static function GetLiveChatEnabled()
{
$liveChat = self::getValue("live_chat", false);
if (is_null($liveChat) || $liveChat == "" || $liveChat == "1") { //Defaults to on
return true;
}
return false;
}
public static function SetLiveChatEnabled($toggle)
{
if (is_bool($toggle)) {
self::setValue("live_chat", $toggle ? "1" : "0");
} else {
Logging::warn("Attempting to set live_chat to invalid value: $toggle. Must be a bool.");
}
}
/* User specific preferences start */

View file

@ -82,8 +82,24 @@ class Application_Model_RabbitMq
public static function SendMessageToAnalyzer($tmpFilePath, $importedStorageDirectory, $originalFilename,
$callbackUrl, $apiKey)
{
$exchange = 'airtime-uploads';
//Hack for Airtime Pro. The RabbitMQ settings for communicating with airtime_analyzer are global
//and shared between all instances on Airtime Pro.
$CC_CONFIG = Config::getConfig();
$devEnv = "production"; //Default
if (array_key_exists("dev_env", $CC_CONFIG)) {
$devEnv = $CC_CONFIG["dev_env"];
}
$config = parse_ini_file("/etc/airtime-saas/rabbitmq-analyzer-" . $devEnv . ".ini", true);
$conn = new AMQPConnection($config["rabbitmq"]["host"],
$config["rabbitmq"]["port"],
$config["rabbitmq"]["user"],
$config["rabbitmq"]["password"],
$config["rabbitmq"]["vhost"]);
$exchange = 'airtime-uploads';
$exchangeType = 'topic';
$queue = 'airtime-uploads';
$autoDeleteExchange = false;
$data['tmp_file_path'] = $tmpFilePath;
$data['import_directory'] = $importedStorageDirectory;
$data['original_filename'] = $originalFilename;
@ -91,6 +107,68 @@ class Application_Model_RabbitMq
$data['api_key'] = $apiKey;
$jsonData = json_encode($data);
self::sendMessage($exchange, 'topic', false, $jsonData, 'airtime-uploads');
//self::sendMessage($exchange, 'topic', false, $jsonData, 'airtime-uploads');
if (!isset($conn)) {
throw new Exception("Cannot connect to RabbitMQ server");
}
$channel = $conn->channel();
$channel->access_request($config["rabbitmq"]["vhost"], false, false,
true, true);
//I'm pretty sure we DON'T want to autodelete ANY exchanges but I'm keeping the code
//the way it is just so I don't accidentally break anything when I add the Analyzer code in. -- Albert, March 13, 2014
$channel->exchange_declare($exchange, $exchangeType, false, true, $autoDeleteExchange);
$msg = new AMQPMessage($jsonData, array('content_type' => 'text/plain'));
$channel->basic_publish($msg, $exchange);
$channel->close();
$conn->close();
}
public static function SendMessageToHaproxyConfigDaemon($md){
$config = parse_ini_file("/etc/airtime-saas/rabbitmq.ini", true);
$conn = new AMQPConnection($config["rabbitmq"]["host"],
$config["rabbitmq"]["port"],
$config["rabbitmq"]["user"],
$config["rabbitmq"]["password"],
$config["rabbitmq"]["vhost"]);
$exchange = $config["rabbitmq"]["queue"];
$queue = $config["rabbitmq"]["queue"];
$ch = $conn->channel();
/*
name: $queue
passive: false
durable: true // the queue will survive server restarts
exclusive: false // the queue can be accessed in other channels
auto_delete: false //the queue won't be deleted once the channel is closed.
*/
$ch->queue_declare($queue, false, true, false, false);
/*
name: $exchange
type: direct
passive: false
durable: true // the exchange will survive server restarts
auto_delete: false //the exchange won't be deleted once the channel is closed.
*/
$ch->exchange_declare($exchange, 'direct', false, true, false);
$ch->queue_bind($queue, $exchange);
$data = json_encode($md).PHP_EOL;
$msg = new AMQPMessage($data, array('content_type' => 'application/json'));
$ch->basic_publish($msg, $exchange);
$ch->close();
$conn->close();
}
}

View file

@ -62,7 +62,14 @@ SQL;
*/
public static function GetPlayOrderRange($utcTimeEnd = null, $showsToRetrieve = 5)
{
// Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up.
//Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up.
if (!is_int($p_prev) || !is_int($p_next)) {
//must enter integers to specify ranges
Logging::info("Invalid range parameters: $p_prev or $p_next");
return array();
}
// when timeEnd is unspecified, return to the default behaviour - set a range of 48 hours from current time
if (!$utcTimeEnd) {
@ -873,7 +880,7 @@ SQL;
$CC_CONFIG = Config::getConfig();
$utcTimeZone = new DateTimeZone('UTC');
/* if $p_fromDateTime and $p_toDateTime function parameters are null,
then set range * from "now" to "now + 24 hours". */
if (is_null($p_fromDateTime)) {
@ -931,6 +938,7 @@ SQL;
//row is from "file"
$media_id = $item['file_id'];
$storedFile = Application_Model_StoredFile::RecallById($media_id);
$file = $storedFile->getPropelOrm();
$uri = $file->getAbsoluteFilePath();
@ -939,13 +947,13 @@ SQL;
$object_name = $storedFile->getResourceId();
}
self::createFileScheduleEvent($data, $item, $media_id, $uri, $object_name);
}
}
elseif (!is_null($item['stream_id'])) {
//row is type "webstream"
$media_id = $item['stream_id'];
$uri = $item['url'];
self::createStreamScheduleEvent($data, $item, $media_id, $uri);
}
}
else {
throw new Exception("Unknown schedule type: ".print_r($item, true));
}
@ -1021,7 +1029,6 @@ SQL;
$needScheduleUntil->add(new DateInterval("P1D"));
}
Application_Model_Show::createAndFillShowInstancesPastPopulatedUntilDate($needScheduleUntil);
list($range_start, $range_end) = self::getRangeStartAndEnd($p_fromDateTime, $p_toDateTime);
$data = array();

View file

@ -877,11 +877,14 @@ SELECT si1.starts AS starts,
si1.instance_id AS record_id,
si1.show_id AS show_id,
show.name AS name,
show.description AS description,
show.color AS color,
show.background_color AS background_color,
show.image_path AS image_path,
show.linked AS linked,
si1.file_id AS file_id,
si1.id AS instance_id,
si1.description AS instance_description,
si1.created AS created,
si1.last_scheduled AS last_scheduled,
si1.time_filled AS time_filled,
@ -1076,10 +1079,13 @@ SQL;
SELECT si.starts AS start_timestamp,
si.ends AS end_timestamp,
s.name,
s.description,
s.id,
si.id AS instance_id,
si.description AS instance_description,
si.record,
s.url,
s.image_path,
starts,
ends
FROM cc_show_instances si
@ -1211,7 +1217,7 @@ SQL;
$CC_CONFIG = Config::getConfig();
$con = Propel::getConnection();
//TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
$sql = <<<SQL
SELECT si.starts AS start_timestamp,
@ -1310,16 +1316,16 @@ SQL;
"id" => $rows[$i]['id'],
"instance_id" => $rows[$i]['instance_id'],
"instance_description" => $rows[$i]['instance_description'],
"name" => $rows[$i]['name'],
"name" => $rows[$i]['name'],
"description" => $rows[$i]['description'],
"url" => $rows[$i]['url'],
"url" => $rows[$i]['url'],
"start_timestamp" => $rows[$i]['start_timestamp'],
"end_timestamp" => $rows[$i]['end_timestamp'],
"starts" => $rows[$i]['starts'],
"ends" => $rows[$i]['ends'],
"record" => $rows[$i]['record'],
"image_path" => $rows[$i]['image_path'],
"type" => "show");
"type" => "show");
break;
}
}
@ -1369,11 +1375,14 @@ SQL;
SELECT si.starts AS start_timestamp,
si.ends AS end_timestamp,
s.name,
s.description,
s.id,
si.id AS instance_id,
si.description AS instance_description,
si.record,
s.url,
starts,
s.image_path,
starts,
ends
FROM cc_show_instances si
LEFT JOIN cc_show s

View file

@ -69,6 +69,13 @@ SQL;
return $show->getDbName();
}
public function getImagePath()
{
$show = CcShowQuery::create()->findPK($this->getShowId());
return $show->getDbImagePath();
}
public function getGenre()
{

View file

@ -375,7 +375,7 @@ SQL;
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if (!$isAdminOrPM && $this->getFileOwnerId() != $user->getId()) {
throw new FileNoPermissionException();
}
@ -972,6 +972,8 @@ SQL;
// Did all the checks for real, now trying to copy
$audio_stor = Application_Common_OsPath::join($stor, "organize",
$originalFilename);
Logging::info($originalFilename);
Logging::info($audio_stor);
$user = Application_Model_User::getCurrentUser();
if (is_null($user)) {
$uid = Application_Model_User::getFirstAdminId();

View file

@ -215,23 +215,25 @@ class Application_Model_Systemstatus
{
$partitions = array();
/* First lets get all the watched directories. Then we can group them
* into the same partitions by comparing the partition sizes. */
$musicDirs = Application_Model_MusicDir::getWatchedDirs();
$musicDirs[] = Application_Model_MusicDir::getStorDir();
//connect to DB and find how much total space user has allocated.
$totalSpace = Application_Model_Preference::GetDiskQuota();
foreach ($musicDirs as $md) {
$totalSpace = disk_total_space($md->getDirectory());
if (!isset($partitions[$totalSpace])) {
$partitions[$totalSpace] = new StdClass;
$partitions[$totalSpace]->totalSpace = $totalSpace;
$partitions[$totalSpace]->totalFreeSpace = disk_free_space($md->getDirectory());
}
$partitions[$totalSpace]->dirs[] = $md->getDirectory();
$usedSpace = Application_Model_Preference::getDiskUsage();
if (empty($usedSpace)) {
$usedSpace = 0;
}
/* $path = $_SERVER['AIRTIME_BASE']."etc/airtime/num_bytes.ini";
$arr = parse_ini_file($path);
$usedSpace = 0;
if ($arr !== false) {
$usedSpace = $arr['num_bytes'];
} */
$partitions[$totalSpace] = new stdClass();
$partitions[$totalSpace]->totalSpace = $totalSpace;
$partitions[$totalSpace]->totalFreeSpace = $totalSpace - $usedSpace;
//Logging::info($partitions[$totalSpace]->totalFreeSpace);
return array_values($partitions);
}
@ -241,7 +243,7 @@ class Application_Model_Systemstatus
$diskInfo = self::GetDiskInfo();
$diskInfo = $diskInfo[0];
$diskUsage = $diskInfo->totalSpace - $diskInfo->totalFreeSpace;
if ($diskUsage >= $diskInfo->totalSpace) {
if ($diskUsage > 0 && $diskUsage >= $diskInfo->totalSpace) {
return true;
}

View file

@ -49,14 +49,20 @@ class Application_Model_User
{
return $this->isUserType(UTYPE_ADMIN);
}
public function isSuperAdmin()
{
return $this->isUserType(UTYPE_SUPERADMIN);
}
public function canSchedule($p_showId)
{
$type = $this->getType();
$result = false;
if ($type === UTYPE_ADMIN ||
$type === UTYPE_PROGRAM_MANAGER ||
if ($this->isAdmin() ||
$this->isSuperAdmin() ||
$this->isPM() ||
self::isHostOfShow($p_showId)) {
$result = true;
}
@ -239,10 +245,14 @@ class Application_Model_User
}
public static function getFirstAdmin() {
$admins = Application_Model_User::getUsersOfType('A');
if (count($admins) > 0) { // found admin => pick first one
return $admins[0];
$superAdmins = Application_Model_User::getUsersOfType('S');
if (count($superAdmins) > 0) { // found superadmin => pick first one
return $superAdmins[0];
} else {
$admins = Application_Model_User::getUsersOfType('A');
if (count($admins) > 0) { // found admin => pick first one
return $admins[0];
}
Logging::warn("Warning. no admins found in database");
return null;
}
@ -324,16 +334,26 @@ class Application_Model_User
$res = Application_Model_Datatables::findEntries($con, $displayColumns, $fromTable, $datatables);
// mark record which is for the current user
foreach ($res['aaData'] as &$record) {
foreach($res['aaData'] as $key => &$record){
if ($record['login'] == $username) {
$record['delete'] = "self";
} else {
$record['delete'] = "";
}
if($record['login'] == 'sourcefabric_admin'){
//arrays in PHP are basically associative arrays that can be iterated in order.
//Deleting an earlier element does not change the keys of elements that come after it. --MK
unset($res['aaData'][$key]);
$res['iTotalDisplayRecords']--;
$res['iTotalRecords']--;
}
$record = array_map('htmlspecialchars', $record);
}
$res['aaData'] = array_values($res['aaData']);
return $res;
}

View file

@ -15,7 +15,7 @@ class CcSubjs extends BaseCcSubjs {
public function isAdminOrPM()
{
return $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
return $this->type === UTYPE_SUPERADMIN || $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
}
public function isHostOfShow($showId)