Merge branch 'saas' into saas-embed-player
This commit is contained in:
commit
40d6249229
|
@ -18,9 +18,11 @@ require_once 'Preference.php';
|
|||
require_once 'Locale.php';
|
||||
require_once "DateHelper.php";
|
||||
require_once "LocaleHelper.php";
|
||||
require_once "FileDataHelper.php";
|
||||
require_once "HTTPHelper.php";
|
||||
require_once "OsPath.php";
|
||||
require_once "Database.php";
|
||||
require_once "ProvisioningHelper.php";
|
||||
require_once "Timezone.php";
|
||||
require_once "Auth.php";
|
||||
require_once __DIR__.'/forms/helpers/ValidationTypes.php';
|
||||
|
@ -33,6 +35,13 @@ require_once __DIR__.'/modules/rest/controllers/MediaController.php';
|
|||
require_once (APPLICATION_PATH."/logging/Logging.php");
|
||||
Logging::setLogPath('/var/log/airtime/zendphp.log');
|
||||
|
||||
// We need to manually route because we can't load Zend without the database being initialized first.
|
||||
if (array_key_exists("REQUEST_URI", $_SERVER) && (strpos($_SERVER["REQUEST_URI"], "/provisioning/create") !== false)) {
|
||||
$provisioningHelper = new ProvisioningHelper($CC_CONFIG["apiKey"][0]);
|
||||
$provisioningHelper->createAction();
|
||||
die();
|
||||
}
|
||||
|
||||
Config::setAirtimeVersion();
|
||||
require_once __DIR__."/configs/navigation.php";
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
class FileDataHelper {
|
||||
|
||||
/**
|
||||
* We want to throw out invalid data and process the upload successfully
|
||||
* at all costs, so check the data and sanitize it if necessary
|
||||
* @param array $data array containing new file metadata
|
||||
*/
|
||||
public static function sanitizeData(&$data)
|
||||
{
|
||||
if (array_key_exists("track_number", $data)) {
|
||||
// If the track number isn't numeric, this will return 0
|
||||
$data["track_number"] = intval($data["track_number"]);
|
||||
}
|
||||
if (array_key_exists("year", $data)) {
|
||||
// If the track number isn't numeric, this will return 0
|
||||
$data["year"] = intval($data["year"]);
|
||||
}
|
||||
if (array_key_exists("bpm", $data)) {
|
||||
//Some BPM tags are silly and include the word "BPM". Let's strip that...
|
||||
$data["bpm"] = str_ireplace("BPM", "", $data["bpm"]);
|
||||
// This will convert floats to ints too.
|
||||
$data["bpm"] = intval($data["bpm"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
|
||||
/** This class provides the business logic for station provisioning. */
|
||||
class ProvisioningHelper
|
||||
{
|
||||
|
||||
/* @var $dbh PDO */
|
||||
static $dbh;
|
||||
|
||||
// Parameter values
|
||||
private $dbuser, $dbpass, $dbname, $dbhost, $dbowner, $apikey;
|
||||
private $instanceId;
|
||||
|
||||
public function __construct($apikey)
|
||||
{
|
||||
$this->apikey = $apikey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint for setting up and installing the Airtime database. This all has to be done without Zend
|
||||
* which is why the code looks so old school (eg. http_response_code). (We can't currently bootstrap our
|
||||
* Zend app without the database unfortunately.)
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$apikey = $_SERVER['PHP_AUTH_USER'];
|
||||
if (!isset($apikey) || $apikey != $this->apikey) {
|
||||
Logging::info("Invalid API Key: $apikey");
|
||||
http_response_code(403);
|
||||
echo "ERROR: Incorrect API key";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
$this->parsePostParams();
|
||||
|
||||
//For security, the Airtime Pro provisioning system creates the database for the user.
|
||||
// $this->setNewDatabaseConnection();
|
||||
//if ($this->checkDatabaseExists()) {
|
||||
// throw new Exception("ERROR: Airtime database already exists");
|
||||
//}
|
||||
//$this->createDatabase();
|
||||
|
||||
//All we need to do is create the database tables.
|
||||
$this->createDatabaseTables();
|
||||
$this->initializeMusicDirsTable($this->instanceId);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(400);
|
||||
Logging::error($e->getMessage());
|
||||
echo $e->getMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
http_response_code(201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the database settings and credentials given are valid
|
||||
* @return boolean true if the database given exists and the user is valid and can access it
|
||||
*/
|
||||
private function checkDatabaseExists()
|
||||
{
|
||||
$statement = self::$dbh->prepare("SELECT datname FROM pg_database WHERE datname = :dbname");
|
||||
$statement->execute(array(":dbname" => $this->dbname));
|
||||
$result = $statement->fetch();
|
||||
return isset($result[0]);
|
||||
}
|
||||
|
||||
private function parsePostParams()
|
||||
{
|
||||
$this->dbuser = $_POST['dbuser'];
|
||||
$this->dbpass = $_POST['dbpass'];
|
||||
$this->dbname = $_POST['dbname'];
|
||||
$this->dbhost = $_POST['dbhost'];
|
||||
$this->dbowner = $_POST['dbowner'];
|
||||
$this->instanceId = $_POST['instanceid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a new database connection based on the parameters in the request
|
||||
* @throws PDOException upon failure to connect
|
||||
*/
|
||||
private function setNewDatabaseConnection()
|
||||
{
|
||||
self::$dbh = new PDO("pgsql:host=" . $this->dbhost
|
||||
. ";dbname=postgres"
|
||||
. ";port=5432" . ";user=" . $this->dbuser
|
||||
. ";password=" . $this->dbpass);
|
||||
$err = self::$dbh->errorInfo();
|
||||
if ($err[1] != null) {
|
||||
throw new PDOException("ERROR: Could not connect to database");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Airtime database using the given credentials
|
||||
* @throws Exception
|
||||
*/
|
||||
private function createDatabase()
|
||||
{
|
||||
Logging::info("Creating database...");
|
||||
$statement = self::$dbh->prepare("CREATE DATABASE " . pg_escape_string($this->dbname)
|
||||
. " WITH ENCODING 'UTF8' TEMPLATE template0"
|
||||
. " OWNER " . pg_escape_string($this->dbowner));
|
||||
if (!$statement->execute()) {
|
||||
throw new Exception("ERROR: Failed to create Airtime database");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the Airtime database
|
||||
* @throws Exception
|
||||
*/
|
||||
private function createDatabaseTables()
|
||||
{
|
||||
Logging::info("Creating database tables...");
|
||||
$sqlDir = dirname(APPLICATION_PATH) . "/build/sql/";
|
||||
$files = array("schema.sql", "sequences.sql", "views.sql", "triggers.sql", "defaultdata.sql");
|
||||
foreach ($files as $f) {
|
||||
/*
|
||||
* Unfortunately, we need to use exec here due to PDO's lack of support for importing
|
||||
* multi-line .sql files. PDO->exec() almost works, but any SQL errors stop the import,
|
||||
* so the necessary DROPs on non-existent tables make it unusable. Prepared statements
|
||||
* have multiple issues; they similarly die on any SQL errors, fail to read in multi-line
|
||||
* commands, and fail on any unescaped ? or $ characters.
|
||||
*/
|
||||
exec("PGPASSWORD=$this->dbpass psql -U $this->dbuser --dbname $this->dbname -h $this->dbhost -f $sqlDir$f", $out, $status);
|
||||
if ($status != 0) {
|
||||
throw new Exception("ERROR: Failed to create database tables");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function initializeMusicDirsTable($instanceId)
|
||||
{
|
||||
if (!is_string($instanceId) || empty($instanceId) || !is_numeric($instanceId))
|
||||
{
|
||||
throw new Exception("Invalid instance id: " . $instanceId);
|
||||
}
|
||||
|
||||
$instanceIdPrefix = $instanceId[0];
|
||||
|
||||
//Reinitialize Propel, just in case...
|
||||
Propel::init(__DIR__."/../configs/airtime-conf-production.php");
|
||||
|
||||
//Create the cc_music_dir entry
|
||||
$musicDir = new CcMusicDirs();
|
||||
$musicDir->setType("stor");
|
||||
$musicDir->setExists(true);
|
||||
$musicDir->setWatched(true);
|
||||
$musicDir->setDirectory("/mnt/airtimepro/instances/$instanceIdPrefix/$instanceId/srv/airtime/stor/");
|
||||
$musicDir->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -55,7 +55,8 @@ $ccAcl->allow('G', 'index')
|
|||
->allow('G', 'upgrade')
|
||||
->allow('G', 'provisioning')
|
||||
->allow('G', 'downgrade')
|
||||
->allow('G', 'rest:show-image')
|
||||
->allow('G', 'rest:show-image', 'get')
|
||||
->allow('H', 'rest:show-image')
|
||||
->allow('G', 'rest:media', 'get')
|
||||
->allow('H', 'rest:media')
|
||||
->allow('H', 'preference', 'is-import-in-progress')
|
||||
|
|
|
@ -8,14 +8,17 @@
|
|||
|
||||
class Config {
|
||||
private static $CC_CONFIG = null;
|
||||
private static $rootDir;
|
||||
public static function loadConfig() {
|
||||
|
||||
self::$rootDir = __DIR__."/../..";
|
||||
$CC_CONFIG = array(
|
||||
/* ================================================ storage configuration */
|
||||
|
||||
'soundcloud-client-id' => '2CLCxcSXYzx7QhhPVHN4A',
|
||||
'soundcloud-client-secret' => 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs',
|
||||
|
||||
"rootDir" => __DIR__."/../.."
|
||||
"rootDir" => self::$rootDir
|
||||
);
|
||||
|
||||
//In the unit testing environment, we always want to use our local airtime.conf in airtime_mvc/application/test:
|
||||
|
@ -89,7 +92,8 @@ class Config {
|
|||
public static function setAirtimeVersion() {
|
||||
$airtime_version = Application_Model_Preference::GetAirtimeVersion();
|
||||
$uniqueid = Application_Model_Preference::GetUniqueId();
|
||||
self::$CC_CONFIG['airtime_version'] = md5($airtime_version.$uniqueid);
|
||||
$buildVersion = file_get_contents(self::$rootDir."/../VERSION");
|
||||
self::$CC_CONFIG['airtime_version'] = md5($airtime_version.$buildVersion);
|
||||
}
|
||||
|
||||
public static function getConfig() {
|
||||
|
|
|
@ -204,10 +204,14 @@ class AudiopreviewController extends Zend_Controller_Action
|
|||
$elementMap['element_mp3'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/ogg') {
|
||||
$elementMap['element_oga'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/vorbis') {
|
||||
$elementMap['element_oga'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/mp4') {
|
||||
$elementMap['element_m4a'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/wav') {
|
||||
$elementMap['element_wav'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/x-wav') {
|
||||
$elementMap['element_wav'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/x-flac') {
|
||||
$elementMap['element_flac'] = $track['item_id'];
|
||||
} else {
|
||||
|
@ -289,10 +293,14 @@ class AudiopreviewController extends Zend_Controller_Action
|
|||
$elementMap['element_mp3'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/ogg') {
|
||||
$elementMap['element_oga'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/vorbis') {
|
||||
$elementMap['element_oga'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/mp4') {
|
||||
$elementMap['element_m4a'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/wav') {
|
||||
$elementMap['element_wav'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/x-wav') {
|
||||
$elementMap['element_wav'] = $track['item_id'];
|
||||
} elseif (strtolower($mime) === 'audio/x-flac') {
|
||||
$elementMap['element_flac'] = $track['item_id'];
|
||||
} else {
|
||||
|
|
|
@ -77,8 +77,6 @@ class LibraryController extends Zend_Controller_Action
|
|||
|
||||
$obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
|
||||
if (isset($obj_sess->id)) {
|
||||
$objInfo = Application_Model_Library::getObjInfo($obj_sess->type);
|
||||
|
||||
$objInfo = Application_Model_Library::getObjInfo($obj_sess->type);
|
||||
$obj = new $objInfo['className']($obj_sess->id);
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
|
@ -423,9 +421,6 @@ class LibraryController extends Zend_Controller_Action
|
|||
|
||||
$request = $this->getRequest();
|
||||
|
||||
|
||||
|
||||
|
||||
$file_id = $this->_getParam('id', null);
|
||||
$file = Application_Model_StoredFile::RecallById($file_id);
|
||||
|
||||
|
@ -446,23 +441,11 @@ class LibraryController extends Zend_Controller_Action
|
|||
$serialized[$j["name"]] = $j["value"];
|
||||
}
|
||||
|
||||
// Sanitize any wildly incorrect metadata before it goes to be validated.
|
||||
FileDataHelper::sanitizeData($serialized);
|
||||
|
||||
if ($form->isValid($serialized)) {
|
||||
|
||||
$formValues = $this->_getParam('data', null);
|
||||
$formdata = array();
|
||||
foreach ($formValues as $val) {
|
||||
$formdata[$val["name"]] = $val["value"];
|
||||
}
|
||||
$file->setDbColMetadata($formdata);
|
||||
|
||||
$data = $file->getMetadata();
|
||||
|
||||
// set MDATA_KEY_FILEPATH
|
||||
$data['MDATA_KEY_FILEPATH'] = $file->getFilePath();
|
||||
Logging::info($data['MDATA_KEY_FILEPATH']);
|
||||
Application_Model_RabbitMq::SendMessageToMediaMonitor("md_update", $data);
|
||||
|
||||
$this->_redirect('Library');
|
||||
$file->setDbColMetadata($serialized);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,18 @@ use Aws\S3\S3Client;
|
|||
|
||||
class ProvisioningController extends Zend_Controller_Action
|
||||
{
|
||||
|
||||
public function init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The "create action" is in ProvisioningHelper because it needs to have no dependency on Zend,
|
||||
* since when we bootstrap Zend, we already need the database set up and working (Bootstrap.php is a mess).
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Delete the Airtime Pro station's files from Amazon S3
|
||||
*/
|
||||
|
@ -16,8 +25,8 @@ class ProvisioningController extends Zend_Controller_Action
|
|||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
if (!$this->verifyAPIKey()) {
|
||||
|
||||
if (!RestAuth::verifyAuth(true, true, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,28 +41,5 @@ class ProvisioningController extends Zend_Controller_Action
|
|||
->setHttpResponseCode(200)
|
||||
->appendBody("OK");
|
||||
}
|
||||
|
||||
private function verifyAPIKey()
|
||||
{
|
||||
// The API key is passed in via HTTP "basic authentication":
|
||||
// http://en.wikipedia.org/wiki/Basic_access_authentication
|
||||
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
// Decode the API key that was passed to us in the HTTP request.
|
||||
$authHeader = $this->getRequest()->getHeader("Authorization");
|
||||
$encodedRequestApiKey = substr($authHeader, strlen("Basic "));
|
||||
$encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":");
|
||||
|
||||
if ($encodedRequestApiKey === $encodedStoredApiKey)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("ERROR: Incorrect API key.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class Application_Form_EditAudioMD extends Zend_Form
|
|||
$track_number->class = 'input_text';
|
||||
$track_number->setLabel('Track Number:')
|
||||
->setFilters(array('StringTrim'))
|
||||
->setValidators(array(new Zend_Validate_Digits()));
|
||||
->setValidators(array(new Zend_Validate_Int()));
|
||||
$this->addElement($track_number);
|
||||
|
||||
// Add genre field
|
||||
|
|
|
@ -172,6 +172,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
$file->save();
|
||||
return;
|
||||
} else if ($file && isset($requestData["resource_id"])) {
|
||||
|
||||
$file->fromArray($whiteList, BasePeer::TYPE_FIELDNAME);
|
||||
|
||||
//store the original filename
|
||||
|
@ -200,8 +201,10 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode(CcFiles::sanitizeResponse($file)));
|
||||
} else if ($file) {
|
||||
|
||||
//local file storage
|
||||
$file->setDbDirectory(self::MUSIC_DIRS_STOR_PK);
|
||||
|
||||
$file->fromArray($whiteList, BasePeer::TYPE_FIELDNAME);
|
||||
//Our RESTful API takes "full_path" as a field, which we then split and translate to match
|
||||
//our internal schema. Internally, file path is stored relative to a directory, with the directory
|
||||
|
@ -294,12 +297,15 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
|
||||
private function validateRequestData($file, &$whiteList)
|
||||
{
|
||||
// Sanitize any wildly incorrect metadata before it goes to be validated
|
||||
FileDataHelper::sanitizeData($whiteList);
|
||||
|
||||
try {
|
||||
// EditAudioMD form is used here for validation
|
||||
$fileForm = new Application_Form_EditAudioMD();
|
||||
$fileForm->startForm($file->getDbId());
|
||||
$fileForm->populate($whiteList);
|
||||
|
||||
|
||||
/*
|
||||
* Here we are truncating metadata of any characters greater than the
|
||||
* max string length set in the database. In the rare case a track's
|
||||
|
|
|
@ -40,12 +40,6 @@ class Rest_ShowImageController extends Zend_Rest_Controller {
|
|||
* RESTful POST endpoint; used when uploading show images
|
||||
*/
|
||||
public function postAction() {
|
||||
if (!RestAuth::verifyAuth(true, true)) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("Authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
$showId = $this->getShowId();
|
||||
|
||||
|
@ -89,12 +83,6 @@ class Rest_ShowImageController extends Zend_Rest_Controller {
|
|||
* RESTful DELETE endpoint; used when deleting show images
|
||||
*/
|
||||
public function deleteAction() {
|
||||
if (!RestAuth::verifyAuth(true, true)) {
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody("Authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
$showId = $this->getShowId();
|
||||
|
||||
|
|
|
@ -1,64 +1,60 @@
|
|||
<?php
|
||||
|
||||
class RestAuth
|
||||
{
|
||||
public static function verifyAuth($checkApiKey, $checkSession)
|
||||
{
|
||||
//Session takes precedence over API key for now:
|
||||
if ($checkSession && RestAuth::verifySession()
|
||||
|| $checkApiKey && RestAuth::verifyAPIKey())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$resp = $this->getResponse();
|
||||
$resp->setHttpResponseCode(401);
|
||||
$resp->appendBody("ERROR: Incorrect API key.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getOwnerId()
|
||||
{
|
||||
try {
|
||||
if (RestAuth::verifySession()) {
|
||||
$service_user = new Application_Service_UserService();
|
||||
return $service_user->getCurrentUser()->getDbId();
|
||||
} else {
|
||||
$defaultOwner = CcSubjsQuery::create()
|
||||
->filterByDbType('A')
|
||||
->orderByDbId()
|
||||
->findOne();
|
||||
if (!$defaultOwner) {
|
||||
// what to do if there is no admin user?
|
||||
// should we handle this case?
|
||||
return null;
|
||||
}
|
||||
return $defaultOwner->getDbId();
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static function verifySession()
|
||||
{
|
||||
$auth = Zend_Auth::getInstance();
|
||||
return $auth->hasIdentity();
|
||||
}
|
||||
|
||||
private static function verifyAPIKey()
|
||||
{
|
||||
//The API key is passed in via HTTP "basic authentication":
|
||||
// http://en.wikipedia.org/wiki/Basic_access_authentication
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
//Decode the API key that was passed to us in the HTTP request.
|
||||
$authHeader = $this->getRequest()->getHeader("Authorization");
|
||||
$encodedRequestApiKey = substr($authHeader, strlen("Basic "));
|
||||
$encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":");
|
||||
|
||||
return ($encodedRequestApiKey === $encodedStoredApiKey);
|
||||
}
|
||||
|
||||
class RestAuth {
|
||||
|
||||
public static function verifyAuth($checkApiKey, $checkSession, $action) {
|
||||
//Session takes precedence over API key for now:
|
||||
if ($checkSession && self::verifySession()
|
||||
|| $checkApiKey && self::verifyAPIKey($action)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$action->getResponse()
|
||||
->setHttpResponseCode(401)
|
||||
->appendBody(json_encode(array("message" => "ERROR: Incorrect API key.")));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getOwnerId() {
|
||||
try {
|
||||
if (self::verifySession()) {
|
||||
$service_user = new Application_Service_UserService();
|
||||
return $service_user->getCurrentUser()->getDbId();
|
||||
} else {
|
||||
$defaultOwner = CcSubjsQuery::create()
|
||||
->filterByDbType(array('A', 'S'), Criteria::IN)
|
||||
->orderByDbId()
|
||||
->findOne();
|
||||
if (!$defaultOwner) {
|
||||
// what to do if there is no admin user?
|
||||
// should we handle this case?
|
||||
return null;
|
||||
}
|
||||
return $defaultOwner->getDbId();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Logging::info($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static function verifySession() {
|
||||
$auth = Zend_Auth::getInstance();
|
||||
return $auth->hasIdentity();
|
||||
}
|
||||
|
||||
private static function verifyAPIKey($action) {
|
||||
//The API key is passed in via HTTP "basic authentication":
|
||||
// http://en.wikipedia.org/wiki/Basic_access_authentication
|
||||
$CC_CONFIG = Config::getConfig();
|
||||
|
||||
//Decode the API key that was passed to us in the HTTP request.
|
||||
$authHeader = $action->getRequest()->getHeader("Authorization");
|
||||
$encodedRequestApiKey = substr($authHeader, strlen("Basic "));
|
||||
$encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":");
|
||||
|
||||
return ($encodedRequestApiKey === $encodedStoredApiKey);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
-- Schema version
|
||||
INSERT INTO cc_pref("keystr", "valstr") VALUES('system_version', '2.5.9');
|
||||
|
||||
INSERT INTO cc_subjs ("login", "type", "pass") VALUES ('admin', 'A', md5('admin'));
|
||||
-- added in 2.3
|
||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('off_air_meta', 'Airtime - offline', 'string');
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
@ -316,15 +316,24 @@ var AIRTIME = (function(AIRTIME) {
|
|||
};
|
||||
|
||||
mod.fnDeleteItems = function(aMedia) {
|
||||
|
||||
|
||||
//Prevent the user from spamming the delete button while the AJAX request is in progress
|
||||
AIRTIME.button.disableButton("btn-group #sb-trash", false);
|
||||
//Hack to immediately show the "Processing" div in DataTables to give the user some sort of feedback.
|
||||
$(".dataTables_processing").css('visibility','visible');
|
||||
|
||||
$.post(baseUrl+"library/delete",
|
||||
{"format": "json", "media": aMedia},
|
||||
function(json){
|
||||
if (json.message !== undefined) {
|
||||
alert(json.message);
|
||||
}
|
||||
|
||||
chosenItems = {};
|
||||
oTable.fnStandingRedraw();
|
||||
|
||||
//Re-enable the delete button
|
||||
AIRTIME.button.enableButton("btn-group #sb-trash", false);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
composer install
|
||||
|
||||
git rev-parse HEAD > VERSION
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
import os
|
||||
import logging
|
||||
import uuid
|
||||
import socket
|
||||
from boto.s3.connection import S3Connection
|
||||
from boto.s3.key import Key
|
||||
|
||||
STORAGE_BACKEND_FILE = "file"
|
||||
SOCKET_TIMEOUT = 240
|
||||
|
||||
class CloudStorageUploader:
|
||||
""" A class that uses Python-Boto SDK to upload objects into Amazon S3.
|
||||
|
@ -88,6 +90,10 @@ class CloudStorageUploader:
|
|||
|
||||
resource_id = "%s/%s/%s_%s%s" % (metadata['file_prefix'], unique_id_prefix, file_name, unique_id, extension)
|
||||
|
||||
# Boto uses the "global default timeout" by default, which is infinite! To prevent network problems from
|
||||
# turning into deadlocks, we explicitly set the global default timeout period here:
|
||||
socket.setdefaulttimeout(SOCKET_TIMEOUT)
|
||||
|
||||
conn = S3Connection(self._api_key, self._api_key_secret, host=self._host)
|
||||
bucket = conn.get_bucket(self._bucket)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from nose.tools import *
|
||||
from ConfigParser import SafeConfigParser
|
||||
import os
|
||||
import shutil
|
||||
import multiprocessing
|
||||
|
@ -21,8 +22,11 @@ def teardown():
|
|||
def test_basic():
|
||||
filename = os.path.basename(DEFAULT_AUDIO_FILE)
|
||||
q = multiprocessing.Queue()
|
||||
cloud_storage_config_path = '/etc/airtime-saas/production/cloud_storage.conf'
|
||||
cloud_storage_config = config_file.read_config_file(cloud_storage_config_path)
|
||||
#cloud_storage_config_path = '/etc/airtime-saas/production/cloud_storage.conf'
|
||||
#cloud_storage_config = config_file.read_config_file(cloud_storage_config_path)
|
||||
cloud_storage_config = SafeConfigParser()
|
||||
cloud_storage_config.add_section("current_backend")
|
||||
cloud_storage_config.set("current_backend", "storage_backend", "file")
|
||||
file_prefix = u''
|
||||
#This actually imports the file into the "./Test Artist" directory.
|
||||
AnalyzerPipeline.run_analysis(q, DEFAULT_AUDIO_FILE, u'.', filename, file_prefix, cloud_storage_config)
|
||||
|
|
Loading…
Reference in New Issue