Merge branch '2.2.x' of dev.sourcefabric.org:airtime into cc-4585

This commit is contained in:
Rudi Grinberg 2012-11-01 15:14:53 -04:00
commit 270eb97128
7 changed files with 158 additions and 103 deletions

View File

@ -181,7 +181,8 @@ class LibraryController extends Zend_Controller_Action
} }
} }
} }
if ($isAdminOrPM) {
if ($isAdminOrPM || $file->getFileOwnerId() == $user->getId()) {
$menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete"); $menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete");
$menu["edit"] = array("name"=> "Edit Metadata", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}"); $menu["edit"] = array("name"=> "Edit Metadata", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}");
} }
@ -276,6 +277,7 @@ class LibraryController extends Zend_Controller_Action
$streams = array(); $streams = array();
$message = null; $message = null;
$noPermissionMsg = "You don't have permission to delete selected items.";
foreach ($mediaItems as $media) { foreach ($mediaItems as $media) {
@ -293,19 +295,21 @@ class LibraryController extends Zend_Controller_Action
try { try {
Application_Model_Playlist::deletePlaylists($playlists, $user->getId()); Application_Model_Playlist::deletePlaylists($playlists, $user->getId());
} catch (PlaylistNoPermissionException $e) { } catch (PlaylistNoPermissionException $e) {
$this->view->message = "You don't have permission to delete selected items."; $message = $noPermissionMsg;
return;
} }
try { try {
Application_Model_Block::deleteBlocks($blocks, $user->getId()); Application_Model_Block::deleteBlocks($blocks, $user->getId());
} catch (BlockNoPermissionException $e) {
$message = $noPermissionMsg;
} catch (Exception $e) { } catch (Exception $e) {
//TODO: warn user that not all blocks could be deleted. //TODO: warn user that not all blocks could be deleted.
} }
try { try {
Application_Model_Webstream::deleteStreams($streams, $user->getId()); Application_Model_Webstream::deleteStreams($streams, $user->getId());
} catch (WebstreamNoPermissionException $e) {
$message = $noPermissionMsg;
} catch (Exception $e) { } catch (Exception $e) {
//TODO: warn user that not all streams could be deleted. //TODO: warn user that not all streams could be deleted.
Logging::info($e); Logging::info($e);
@ -318,6 +322,8 @@ class LibraryController extends Zend_Controller_Action
if (isset($file)) { if (isset($file)) {
try { try {
$res = $file->delete(true); $res = $file->delete(true);
} catch (FileNoPermissionException $e) {
$message = $noPermissionMsg;
} catch (Exception $e) { } catch (Exception $e) {
//could throw a scheduled in future exception. //could throw a scheduled in future exception.
$message = "Could not delete some scheduled files."; $message = "Could not delete some scheduled files.";
@ -364,15 +370,17 @@ class LibraryController extends Zend_Controller_Action
{ {
$user = Application_Model_User::getCurrentUser(); $user = Application_Model_User::getCurrentUser();
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if (!$isAdminOrPM) {
return;
}
$request = $this->getRequest(); $request = $this->getRequest();
$form = new Application_Form_EditAudioMD();
$file_id = $this->_getParam('id', null); $file_id = $this->_getParam('id', null);
$file = Application_Model_StoredFile::Recall($file_id); $file = Application_Model_StoredFile::Recall($file_id);
if (!$isAdminOrPM && $file->getFileOwnerId() != $user->getId()) {
return;
}
$form = new Application_Form_EditAudioMD();
$form->populate($file->getDbColMetadata()); $form->populate($file->getDbColMetadata());
if ($request->isPost()) { if ($request->isPost()) {

View File

@ -344,6 +344,13 @@ SQL;
throw new DeleteScheduledFileException(); throw new DeleteScheduledFileException();
} }
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if (!$isAdminOrPM && $this->getFileOwnerId() != $user->getId()) {
throw new FileNoPermissionException();
}
$music_dir = Application_Model_MusicDir::getDirByPK($this->_file->getDbDirectory()); $music_dir = Application_Model_MusicDir::getDirByPK($this->_file->getDbDirectory());
$type = $music_dir->getType(); $type = $music_dir->getType();
@ -1161,6 +1168,10 @@ SQL;
return $this->_file->getDbFileExists(); return $this->_file->getDbFileExists();
} }
public function getFileOwnerId()
{
return $this->_file->getDbOwnerId();
}
// note: never call this method from controllers because it does a sleep // note: never call this method from controllers because it does a sleep
public function uploadToSoundCloud() public function uploadToSoundCloud()
@ -1209,3 +1220,4 @@ SQL;
class DeleteScheduledFileException extends Exception {} class DeleteScheduledFileException extends Exception {}
class FileDoesNotExistException extends Exception {} class FileDoesNotExistException extends Exception {}
class FileNoPermissionException extends Exception {}

View File

@ -92,7 +92,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
if (count($leftOver) == 0) { if (count($leftOver) == 0) {
CcWebstreamQuery::create()->findPKs($p_ids)->delete(); CcWebstreamQuery::create()->findPKs($p_ids)->delete();
} else { } else {
throw new Exception("Invalid user permissions"); throw new WebstreamNoPermissionException;
} }
} }
@ -370,3 +370,6 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
return $webstream->getDbId(); return $webstream->getDbId();
} }
} }
class WebstreamNoPermissionException extends Exception {}

View File

@ -1,6 +1,6 @@
<div class="ui-widget ui-widget-content block-shadow simple-formblock clearfix padded-strong"> <div class="ui-widget ui-widget-content block-shadow simple-formblock clearfix padded-strong">
<h2>Edit Metadata</h2> <h2>Edit Metadata</h2>
<?php $this->form->setAction($this->url()); <?php //$this->form->setAction($this->url());
echo $this->form; ?> echo $this->form; ?>
</div> </div>

View File

@ -252,11 +252,11 @@ var AIRTIME = (function(AIRTIME) {
}; };
/* /*
* selects all items which the user can currently see. * selects all items which the user can currently see. (behaviour taken from
* (behaviour taken from gmail) * gmail)
* *
* by default the items are selected in reverse order * by default the items are selected in reverse order so we need to reverse
* so we need to reverse it back * it back
*/ */
mod.selectCurrentPage = function() { mod.selectCurrentPage = function() {
$.fn.reverse = [].reverse; $.fn.reverse = [].reverse;
@ -276,8 +276,8 @@ var AIRTIME = (function(AIRTIME) {
}; };
/* /*
* deselects all items that the user can currently see. * deselects all items that the user can currently see. (behaviour taken
* (behaviour taken from gmail) * from gmail)
*/ */
mod.deselectCurrentPage = function() { mod.deselectCurrentPage = function() {
var $inputs = $libTable.find("tbody input:checkbox"), var $inputs = $libTable.find("tbody input:checkbox"),
@ -433,7 +433,8 @@ var AIRTIME = (function(AIRTIME) {
oTable = $libTable.dataTable( { oTable = $libTable.dataTable( {
//put hidden columns at the top to insure they can never be visible on the table through column reordering. // put hidden columns at the top to insure they can never be visible
// on the table through column reordering.
"aoColumns": [ "aoColumns": [
/* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } , /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } ,
/* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } , /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } ,
@ -524,11 +525,12 @@ var AIRTIME = (function(AIRTIME) {
"sAjaxDataProp": "files", "sAjaxDataProp": "files",
"fnServerData": function ( sSource, aoData, fnCallback ) { "fnServerData": function ( sSource, aoData, fnCallback ) {
/* The real validation check is done in dataTables.columnFilter.js /*
* We also need to check it here because datatable is redrawn everytime * The real validation check is done in
* an action is performed in the Library page. * dataTables.columnFilter.js We also need to check it here
* In order for datatable to redraw the advanced search fields * because datatable is redrawn everytime an action is performed
* MUST all be valid. * in the Library page. In order for datatable to redraw the
* advanced search fields MUST all be valid.
*/ */
var advSearchFields = $("div#advanced_search").children(':visible'); var advSearchFields = $("div#advanced_search").children(':visible');
var advSearchValid = validateAdvancedSearch(advSearchFields); var advSearchValid = validateAdvancedSearch(advSearchFields);
@ -555,27 +557,34 @@ var AIRTIME = (function(AIRTIME) {
// add the play function to the library_type td // add the play function to the library_type td
$(nRow).find('td.library_type').click(function(){ $(nRow).find('td.library_type').click(function(){
if (aData.ftype === 'playlist' && aData.length !== '0.0'){ if (aData.ftype === 'playlist' && aData.length !== '0.0'){
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_ playlistIndex = $(this).parent().attr('id').substring(3); // remove
// the
// pl_
open_playlist_preview(playlistIndex, 0); open_playlist_preview(playlistIndex, 0);
} else if (aData.ftype === 'audioclip') { } else if (aData.ftype === 'audioclip') {
open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name);
} else if (aData.ftype == 'stream') { } else if (aData.ftype == 'stream') {
open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name);
} else if (aData.ftype == 'block' && aData.bl_type == 'static') { } else if (aData.ftype == 'block' && aData.bl_type == 'static') {
blockIndex = $(this).parent().attr('id').substring(3); //remove the bl_ blockIndex = $(this).parent().attr('id').substring(3); // remove
// the
// bl_
open_block_preview(blockIndex, 0); open_block_preview(blockIndex, 0);
} }
return false; return false;
}); });
alreadyclicked=false; alreadyclicked=false;
//call the context menu so we can prevent the event from propagating. // call the context menu so we can prevent the event from
// propagating.
$(nRow).find('td:not(.library_checkbox, .library_type)').click(function(e){ $(nRow).find('td:not(.library_checkbox, .library_type)').click(function(e){
var el=$(this); var el=$(this);
if (alreadyclicked) if (alreadyclicked)
{ {
alreadyclicked=false; // reset alreadyclicked=false; // reset
clearTimeout(alreadyclickedTimeout); // prevent this from happening clearTimeout(alreadyclickedTimeout); // prevent this
// from
// happening
// do what needs to happen on double click. // do what needs to happen on double click.
$tr = $(el).parent(); $tr = $(el).parent();
@ -596,7 +605,8 @@ var AIRTIME = (function(AIRTIME) {
return false; return false;
}); });
//add a tool tip to appear when the user clicks on the type icon. // add a tool tip to appear when the user clicks on the type
// icon.
$(nRow).find("td:not(.library_checkbox, .library_type)").qtip({ $(nRow).find("td:not(.library_checkbox, .library_type)").qtip({
content: { content: {
text: "Loading...", text: "Loading...",
@ -620,7 +630,8 @@ var AIRTIME = (function(AIRTIME) {
}, },
my: 'left center', my: 'left center',
at: 'right center', at: 'right center',
viewport: $(window), // Keep the tooltip on-screen at all times viewport: $(window), // Keep the tooltip on-screen at
// all times
effect: false // Disable positioning animation effect: false // Disable positioning animation
}, },
style: { style: {
@ -641,7 +652,8 @@ var AIRTIME = (function(AIRTIME) {
// remove any selected nodes before the draw. // remove any selected nodes before the draw.
"fnPreDrawCallback": function( oSettings ) { "fnPreDrawCallback": function( oSettings ) {
//make sure any dragging helpers are removed or else they'll be stranded on the screen. // make sure any dragging helpers are removed or else they'll be
// stranded on the screen.
$("#draggingContainer").remove(); $("#draggingContainer").remove();
}, },
"fnDrawCallback": AIRTIME.library.fnDrawCallback, "fnDrawCallback": AIRTIME.library.fnDrawCallback,
@ -674,17 +686,32 @@ var AIRTIME = (function(AIRTIME) {
setColumnFilter(oTable); setColumnFilter(oTable);
oTable.fnSetFilteringDelay(350); oTable.fnSetFilteringDelay(350);
var simpleSearchText;
$libContent.on("click", "legend", function(){ $libContent.on("click", "legend", function(){
$simpleSearch = $libContent.find("#library_display_filter label"); $simpleSearch = $libContent.find("#library_display_filter label");
var $fs = $(this).parents("fieldset"); var $fs = $(this).parents("fieldset");
if ($fs.hasClass("closed")) { if ($fs.hasClass("closed")) {
$fs.removeClass("closed"); $fs.removeClass("closed");
//keep value of simple search for when user switches back to it
simpleSearchText = $simpleSearch.find('input').val();
// clear the simple search text field and reset datatable
$(".dataTables_filter input").val("").keyup();
$simpleSearch.addClass("sp-invisible"); $simpleSearch.addClass("sp-invisible");
} }
else { else {
$fs.addClass("closed"); //clear the advanced search fields and reset datatable
$(".filter_column input").val("").keyup();
//reset datatable with previous simple search results (if any)
$(".dataTables_filter input").val(simpleSearchText).keyup();
$simpleSearch.removeClass("sp-invisible"); $simpleSearch.removeClass("sp-invisible");
$fs.addClass("closed");
} }
}); });
@ -799,12 +826,16 @@ var AIRTIME = (function(AIRTIME) {
callback = function() { callback = function() {
if (data.ftype === 'playlist' && data.length !== '0.0'){ if (data.ftype === 'playlist' && data.length !== '0.0'){
playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_ playlistIndex = $(this).parent().attr('id').substring(3); // remove
// the
// pl_
open_playlist_preview(playlistIndex, 0); open_playlist_preview(playlistIndex, 0);
} else if (data.ftype === 'audioclip' || data.ftype === 'stream') { } else if (data.ftype === 'audioclip' || data.ftype === 'stream') {
open_audio_preview(data.ftype, data.audioFile, data.track_title, data.artist_name); open_audio_preview(data.ftype, data.audioFile, data.track_title, data.artist_name);
} else if (data.ftype === 'block') { } else if (data.ftype === 'block') {
blockIndex = $(this).parent().attr('id').substring(3); //remove the pl_ blockIndex = $(this).parent().attr('id').substring(3); // remove
// the
// pl_
open_block_preview(blockIndex, 0); open_block_preview(blockIndex, 0);
} }
}; };
@ -815,7 +846,8 @@ var AIRTIME = (function(AIRTIME) {
if (oItems.del !== undefined) { if (oItems.del !== undefined) {
// delete through the playlist controller, will reset // delete through the playlist controller, will reset
//playlist screen if this is the currently edited playlist. // playlist screen if this is the currently edited
// playlist.
if ((data.ftype === "playlist" || data.ftype === "block") && screen === "playlist") { if ((data.ftype === "playlist" || data.ftype === "block") && screen === "playlist") {
callback = function() { callback = function() {
aMedia = []; aMedia = [];
@ -988,7 +1020,8 @@ function addQtipToSCIcons(){
viewport: $(window) viewport: $(window)
}, },
show: { show: {
ready: true // Needed to make it show on first mouseover event ready: true // Needed to make it show on first mouseover
// event
} }
}); });
} }
@ -1015,7 +1048,8 @@ function addQtipToSCIcons(){
viewport: $(window) viewport: $(window)
}, },
show: { show: {
ready: true // Needed to make it show on first mouseover event ready: true // Needed to make it show on first mouseover
// event
} }
}); });
}else if($(this).hasClass("sc-error")){ }else if($(this).hasClass("sc-error")){
@ -1042,7 +1076,8 @@ function addQtipToSCIcons(){
viewport: $(window) viewport: $(window)
}, },
show: { show: {
ready: true // Needed to make it show on first mouseover event ready: true // Needed to make it show on first mouseover
// event
} }
}); });
} }
@ -1104,11 +1139,11 @@ function validateAdvancedSearch(divs) {
addRemoveValidationIcons(valid, $(field), searchTermType); addRemoveValidationIcons(valid, $(field), searchTermType);
/* Empty fields should not have valid/invalid indicator /*
* Range values are considered valid even if only the * Empty fields should not have valid/invalid indicator Range values
* 'From' value is provided. Therefore, if the 'To' value * are considered valid even if only the 'From' value is provided.
* is empty but the 'From' value is not empty we need to * Therefore, if the 'To' value is empty but the 'From' value is not
* keep the validation icon on screen. * empty we need to keep the validation icon on screen.
*/ */
} else if (searchTerm[0] === "" && searchTerm[1] !== "" || } else if (searchTerm[0] === "" && searchTerm[1] !== "" ||
searchTerm[0] === "" && searchTerm[1] === ""){ searchTerm[0] === "" && searchTerm[1] === ""){
@ -1161,12 +1196,9 @@ function addRemoveValidationIcons(valid, field, searchTermType) {
} }
} }
/* Validation types: /*
* s => string * Validation types: s => string i => integer n => numeric (positive/negative,
* i => integer * whole/decimals) t => timestamp l => length
* n => numeric (positive/negative, whole/decimals)
* t => timestamp
* l => length
*/ */
var validationTypes = { var validationTypes = {
"album_title" : "s", "album_title" : "s",

View File

@ -27,11 +27,11 @@ code=`lsb_release -cs`
if [ "$dist" = "Debian" ]; then if [ "$dist" = "Debian" ]; then
set +e set +e
grep -E "deb +http://www.deb-multimedia.org/? squeeze +main +non-free" /etc/apt/sources.list grep -E "deb http://backports.debian.org/debian-backports squeeze-backports main" /etc/apt/sources.list
returncode=$? returncode=$?
set -e set -e
if [ "$returncode" -ne "0" ]; then if [ "$returncode" -ne "0" ]; then
echo "deb http://www.deb-multimedia.org squeeze main non-free" >> /etc/apt/sources.list echo "deb http://backports.debian.org/debian-backports squeeze-backports main" >> /etc/apt/sources.list
fi fi
fi fi

View File

@ -29,9 +29,9 @@ dist=`lsb_release -is`
code=`lsb_release -cs` code=`lsb_release -cs`
if [ "$dist" -eq "Debian" ]; then if [ "$dist" -eq "Debian" ]; then
grep "deb http://www.deb-multimedia.org squeeze main non-free" /etc/apt/sources.list grep "deb http://backports.debian.org/debian-backports squeeze-backports main" /etc/apt/sources.list
if [ "$?" -ne "0" ]; then if [ "$?" -ne "0" ]; then
echo "deb http://www.deb-multimedia.org squeeze main non-free" >> /etc/apt/sources.list echo "deb http://backports.debian.org/debian-backports squeeze-backports main" >> /etc/apt/sources.list
fi fi
fi fi