diff --git a/admin/Gemfile b/admin/Gemfile index cb7f6563c..7c8ba4476 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -37,7 +37,8 @@ gem 'carrierwave', '0.9.0' gem 'carrierwave_direct' gem 'uuidtools', '2.1.2' gem 'bcrypt-ruby', '3.0.1' -gem 'jquery-rails', '2.3.0' # pinned because jquery-ui-rails was split from jquery-rails, but activeadmin doesn't support this gem yet +gem 'jquery-rails' # , '2.3.0' # pinned because jquery-ui-rails was split from jquery-rails, but activeadmin doesn't support this gem yet +gem 'jquery-ui-rails' gem 'rails3-jquery-autocomplete' gem 'activeadmin', '0.6.2' gem 'mime-types', '1.25' @@ -48,7 +49,8 @@ gem 'country-select' gem 'aasm', '3.0.16' gem 'postgres-copy', '0.6.0' gem 'aws-sdk', '1.29.1' -gem 'bugsnag' +gem 'bugsnag' +gem 'gon' gem 'resque' gem 'resque-retry' gem 'resque-failed-job-mailer' diff --git a/admin/app/admin/errored_mix.rb b/admin/app/admin/errored_mix.rb new file mode 100644 index 000000000..8d6270385 --- /dev/null +++ b/admin/app/admin/errored_mix.rb @@ -0,0 +1,52 @@ +ActiveAdmin.register JamRuby::Mix, :as => 'Errored Mixes' do + + config.filters = true + config.per_page = 50 + config.clear_action_items! + config.sort_order = "created_at_desc" + menu :parent => 'Sessions' + + controller do + + def scoped_collection + Mix.where('error_reason is not NULL and completed = FALSE') + end + + def mix_again + @mix = Mix.find(params[:id]) + @mix.enqueue + render :json => {} + end + end + + index :as => :block do |mix| + div :for => mix do + h3 "Mix (Users: #{mix.recording.users.map { |u| u.name }.join ','}) (When: #{mix.created_at.strftime('%b %d %Y, %H:%M')})" + columns do + column do + panel 'Mix Details' do + attributes_table_for(mix) do + row :recording do |mix| auto_link(mix.recording, mix.recording.id) end + row :created_at do |mix| mix.created_at.strftime('%b %d %Y, %H:%M') end + row :s3_url do |mix| mix.url end + row :manifest do |mix| mix.manifest end + row :completed do |mix| "#{mix.completed ? "finished" : "not finished"}" end + if mix.completed + row :completed_at do |mix| mix.completed_at.strftime('%b %d %Y, %H:%M') end + elsif mix.error_count > 0 + row :error_count do |mix| "#{mix.error_count} times failed" end + row :error_reason do |mix| "last reason failed: #{mix.error_reason}" end + row :error_detail do |mix| "last error detail: #{mix.error_detail}" end + row :mix_again do |mix| div :class => 'mix-again' do + span do link_to "Mix Again", '#', :class => 'mix-again', :'data-mix-id' => mix.id end + span do div :class => 'mix-again-dialog' do end end + end + end + end + end + end + end + end + end + end +end diff --git a/admin/app/admin/mix.rb b/admin/app/admin/mix.rb index 7c56bec29..f2c86e7ec 100644 --- a/admin/app/admin/mix.rb +++ b/admin/app/admin/mix.rb @@ -6,6 +6,14 @@ ActiveAdmin.register JamRuby::Mix, :as => 'Mixes' do config.sort_order = "created_at_desc" menu :parent => 'Sessions' + controller do + + def mix_again + @mix = Mix.find(params[:id]) + @mix.enqueue + render :json => {} + end + end index :as => :block do |mix| div :for => mix do @@ -25,7 +33,11 @@ ActiveAdmin.register JamRuby::Mix, :as => 'Mixes' do row :error_count do |mix| "#{mix.error_count} times failed" end row :error_reason do |mix| "last reason failed: #{mix.error_reason}" end row :error_detail do |mix| "last error detail: #{mix.error_detail}" end - row :what do |mix| link_to "Your Mom", '/' end + row :mix_again do |mix| div :class => 'mix-again' do + span do link_to "Mix Again", '#', :class => 'mix-again', :'data-mix-id' => mix.id end + span do div :class => 'mix-again-dialog' do end end + end + end end end end diff --git a/admin/app/assets/javascripts/active_admin.js b/admin/app/assets/javascripts/active_admin.js index 7498ec940..0ebd669c5 100644 --- a/admin/app/assets/javascripts/active_admin.js +++ b/admin/app/assets/javascripts/active_admin.js @@ -1,2 +1,11 @@ -//= require active_admin/base -//= require autocomplete-rails \ No newline at end of file +// //= require active_admin/base +//= require jquery +//= require jquery_ujs +//= require jquery.ui.core +//= require jquery.ui.widget +//= require jquery.ui.datepicker +//= require jquery.ui.dialog +//= require active_admin/application +//= require autocomplete-rails +//= require base +//= require_tree . diff --git a/admin/app/assets/javascripts/admin_rest.js b/admin/app/assets/javascripts/admin_rest.js new file mode 100644 index 000000000..e41ea253a --- /dev/null +++ b/admin/app/assets/javascripts/admin_rest.js @@ -0,0 +1,38 @@ +(function(context,$) { + + /** + * Javascript wrappers for the REST API + */ + + "use strict"; + + context.JK = context.JK || {}; + context.JK.RestAdmin = function() { + + var self = this; + var logger = context.JK.logger; + + function tryMixAgain(options) { + var mixId = options['mix_id'] + return $.ajax({ + type: "POST", + dataType: "json", + url: gon.global.prefix + 'api/mix/' + mixId + '/enqueue', + contentType: 'application/json', + processData: false + }); + } + + function initialize() { + return self; + } + + // Expose publics + this.initialize = initialize; + this.tryMixAgain = tryMixAgain; + + return this; + }; + + +})(window,jQuery); \ No newline at end of file diff --git a/admin/app/assets/javascripts/application.js b/admin/app/assets/javascripts/application.js index 9097d830e..fb7cad79b 100644 --- a/admin/app/assets/javascripts/application.js +++ b/admin/app/assets/javascripts/application.js @@ -12,4 +12,3 @@ // //= require jquery //= require jquery_ujs -//= require_tree . diff --git a/admin/app/assets/javascripts/base.js b/admin/app/assets/javascripts/base.js new file mode 100644 index 000000000..1ee58192f --- /dev/null +++ b/admin/app/assets/javascripts/base.js @@ -0,0 +1,23 @@ +(function(context,$) { + + context.JK = {} + + var console_methods = [ + 'log', 'debug', 'info', 'warn', 'error', 'assert', + 'clear', 'dir', 'dirxml', 'trace', 'group', + 'groupCollapsed', 'groupEnd', 'time', 'timeEnd', + 'timeStamp', 'profile', 'profileEnd', 'count', + 'exception', 'table' + ]; + + if ('undefined' === typeof(context.console)) { + context.console = {}; + $.each(console_methods, function(index, value) { + context.console[value] = $.noop; + }); + } + + context.JK.logger = context.console; + + +})(window, jQuery); \ No newline at end of file diff --git a/admin/app/assets/javascripts/logger.js b/admin/app/assets/javascripts/logger.js new file mode 100644 index 000000000..e69de29bb diff --git a/admin/app/assets/javascripts/mix_again.js b/admin/app/assets/javascripts/mix_again.js new file mode 100644 index 000000000..5086e7a14 --- /dev/null +++ b/admin/app/assets/javascripts/mix_again.js @@ -0,0 +1,22 @@ +(function(context,$) { + + + var restAdmin = context.JK.RestAdmin(); + + $(function() { + // convert mix again links to ajax + $('a.mix-again').click(function() { + var $link = $(this); + restAdmin.tryMixAgain({mix_id: $link.attr('data-mix-id')}) + .done(function(response) { + $link.closest('div.mix-again').find('div.mix-again-dialog').html('
Mix enqueued
Resque Web').dialog(); + }) + .error(function(jqXHR) { + $link.closest('div.mix-again').find('div.mix-again-dialog').html('Mix failed: ' + jqXHR.responseText).dialog(); + }) + + return false; + }) + + }); +})(window, jQuery); \ No newline at end of file diff --git a/admin/app/assets/stylesheets/active_admin.css.scss b/admin/app/assets/stylesheets/active_admin.css.scss index 0f919ef50..4798f7467 100644 --- a/admin/app/assets/stylesheets/active_admin.css.scss +++ b/admin/app/assets/stylesheets/active_admin.css.scss @@ -7,6 +7,9 @@ // For example, to change the sidebar width: // $sidebar-width: 242px; +/* +*= require jquery.ui.all +*/ // Active Admin's got SASS! @import "active_admin/mixins"; @import "active_admin/base"; diff --git a/admin/app/assets/stylesheets/application.css b/admin/app/assets/stylesheets/application.css index 3192ec897..290b7aab4 100644 --- a/admin/app/assets/stylesheets/application.css +++ b/admin/app/assets/stylesheets/application.css @@ -9,5 +9,6 @@ * compiled file, but it's generally better to create a new file per style scope. * *= require_self + *= require jquery.ui.all *= require_tree . */ diff --git a/admin/app/assets/stylesheets/custom.css.scss b/admin/app/assets/stylesheets/custom.css.scss index bbaf0546b..97651a7af 100644 --- a/admin/app/assets/stylesheets/custom.css.scss +++ b/admin/app/assets/stylesheets/custom.css.scss @@ -1,3 +1,4 @@ + .version-info { font-size:small; color:lightgray; diff --git a/admin/app/controllers/application_controller.rb b/admin/app/controllers/application_controller.rb index e8065d950..ba9580ff2 100644 --- a/admin/app/controllers/application_controller.rb +++ b/admin/app/controllers/application_controller.rb @@ -1,3 +1,10 @@ class ApplicationController < ActionController::Base protect_from_forgery + + before_filter :prepare_gon + + def prepare_gon + gon.another = 'hello' + gon.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || '/' + end end diff --git a/admin/build b/admin/build index 4064b6082..dea84d1da 100755 --- a/admin/build +++ b/admin/build @@ -22,7 +22,7 @@ cp ../pb/target/ruby/jampb/jampb-${GEM_VERSION}.gem vendor/cache/ || { echo "una cp ../ruby/jam_ruby-${GEM_VERSION}.gem vendor/cache/ || { echo "unable to copy jam-ruby gem"; exit 1; } # put all dependencies into vendor/bundle -rm -rf vendor/bundle +#rm -rf vendor/bundle -- let jenkins config 'wipe workspace' decide this rm Gemfile.lock # if we don't want versions to float, pin it in the Gemfile, not count on Gemfile.lock bundle install --path vendor/bundle bundle update diff --git a/admin/config/application.rb b/admin/config/application.rb index 54f1e0a15..9e768f775 100644 --- a/admin/config/application.rb +++ b/admin/config/application.rb @@ -80,14 +80,26 @@ module JamAdmin config.storage_type = :fog # these only need to be set if store_artifact_to_files = false - config.aws_artifact_access_key_id = ENV['AWS_KEY'] - config.aws_artifact_secret_access_key = ENV['AWS_SECRET'] - config.aws_artifact_region = 'us-east-1' - config.aws_artifact_bucket_public = 'jamkazam-dev-public' - config.aws_artifact_bucket = 'jamkazam-dev' - config.aws_artifact_cache = '315576000' + config.aws_access_key_id = ENV['AWS_KEY'] + config.aws_secret_access_key = ENV['AWS_SECRET'] + config.aws_region = 'us-east-1' + config.aws_bucket_public = 'jamkazam-dev-public' + config.aws_bucket = 'jamkazam-dev' + config.aws_cache = '315576000' # for carrierwave_direct config.action_controller.allow_forgery_protection = false + + config.redis_host = "localhost:6379" + + config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails + config.email_generic_from = 'nobody@jamkazam.com' + config.email_smtp_address = 'smtp.sendgrid.net' + config.email_smtp_port = 587 + config.email_smtp_domain = 'www.jamkazam.com' + config.email_smtp_authentication = :plain + config.email_smtp_user_name = 'jamkazam' + config.email_smtp_password = 'jamjamblueberryjam' + config.email_smtp_starttls_auto = true end end diff --git a/admin/config/environment.rb b/admin/config/environment.rb index 4942864e3..d7cd279be 100644 --- a/admin/config/environment.rb +++ b/admin/config/environment.rb @@ -1,5 +1,7 @@ # Load the rails application require File.expand_path('../application', __FILE__) +APP_CONFIG = Rails.application.config + # Initialize the rails application JamAdmin::Application.initialize! diff --git a/admin/config/environments/production.rb b/admin/config/environments/production.rb index 30cd4e4e1..a071fa961 100644 --- a/admin/config/environments/production.rb +++ b/admin/config/environments/production.rb @@ -71,6 +71,6 @@ JamAdmin::Application.configure do # Show the logging configuration on STDOUT config.show_log_configuration = false - config.aws_artifact_bucket_public = 'jamkazam-public' - config.aws_artifact_bucket = 'jamkazam' + config.aws_bucket_public = 'jamkazam-public' + config.aws_bucket = 'jamkazam' end diff --git a/admin/config/initializers/active_admin.rb b/admin/config/initializers/active_admin.rb index 1b7899669..ab2394c35 100644 --- a/admin/config/initializers/active_admin.rb +++ b/admin/config/initializers/active_admin.rb @@ -2,6 +2,7 @@ class Footer < ActiveAdmin::Component def build super(id: "footer") para "version info: web=#{::JamAdmin::VERSION} lib=#{JamRuby::VERSION} db=#{JamDb::VERSION}" + render :inline => include_gon end end diff --git a/admin/config/initializers/carrierwave.rb b/admin/config/initializers/carrierwave.rb index 8a3a54052..f00908608 100644 --- a/admin/config/initializers/carrierwave.rb +++ b/admin/config/initializers/carrierwave.rb @@ -10,13 +10,13 @@ CarrierWave.configure do |config| config.storage = :fog config.fog_credentials = { :provider => 'AWS', - :aws_access_key_id => JamAdmin::Application.config.aws_artifact_access_key_id, - :aws_secret_access_key => JamAdmin::Application.config.aws_artifact_secret_access_key, - :region => JamAdmin::Application.config.aws_artifact_region, + :aws_access_key_id => JamAdmin::Application.config.aws_access_key_id, + :aws_secret_access_key => JamAdmin::Application.config.aws_secret_access_key, + :region => JamAdmin::Application.config.aws_region, } - config.fog_directory = JamAdmin::Application.config.aws_artifact_bucket_public # required + config.fog_directory = JamAdmin::Application.config.aws_bucket_public # required config.fog_public = true # optional, defaults to true - config.fog_attributes = {'Cache-Control'=>"max-age=#{JamAdmin::Application.config.aws_artifact_cache}"} # optional, defaults to {} + config.fog_attributes = {'Cache-Control'=>"max-age=#{JamAdmin::Application.config.aws_cache}"} # optional, defaults to {} end end diff --git a/admin/config/initializers/email.rb b/admin/config/initializers/email.rb index 8b6bb118f..41e1651d0 100644 --- a/admin/config/initializers/email.rb +++ b/admin/config/initializers/email.rb @@ -1,11 +1,11 @@ ActionMailer::Base.raise_delivery_errors = true ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp ActionMailer::Base.smtp_settings = { - :address => "smtp.sendgrid.net", - :port => 587, - :domain => "www.jamkazam.com", - :authentication => :plain, - :user_name => "jamkazam", - :password => "jamjamblueberryjam", - :enable_starttls_auto => true + :address => Rails.application.config.email_smtp_address, + :port => Rails.application.config.email_smtp_port, + :domain => Rails.application.config.email_smtp_domain, + :authentication => Rails.application.config.email_smtp_authentication, + :user_name => Rails.application.config.email_smtp_user_name, + :password => Rails.application.config.email_smtp_password , + :enable_starttls_auto => Rails.application.config.email_smtp_starttls_auto } \ No newline at end of file diff --git a/admin/config/initializers/gon.rb b/admin/config/initializers/gon.rb new file mode 100644 index 000000000..9eb7ab9da --- /dev/null +++ b/admin/config/initializers/gon.rb @@ -0,0 +1 @@ +Gon.global.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || '/' \ No newline at end of file diff --git a/admin/config/initializers/resque.rb b/admin/config/initializers/resque.rb new file mode 100644 index 000000000..5c3c402fc --- /dev/null +++ b/admin/config/initializers/resque.rb @@ -0,0 +1 @@ +Resque.redis = Rails.application.config.redis_host \ No newline at end of file diff --git a/admin/config/routes.rb b/admin/config/routes.rb index 44f4c475e..a86cb918a 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -15,6 +15,7 @@ JamAdmin::Application.routes.draw do ActiveAdmin.routes(self) match '/api/artifacts' => 'artifacts#update_artifacts', :via => :post + match '/api/mix/:id/enqueue' => 'admin/mixes#mix_again', :via => :post mount Resque::Server.new, :at => "/resque" diff --git a/db/manifest b/db/manifest index 1ca790e3d..5a9d3c4c8 100755 --- a/db/manifest +++ b/db/manifest @@ -87,4 +87,5 @@ discardable_recorded_tracks2.sql icecast.sql home_page_promos.sql mix_job_watch.sql -music_session_constraints.sql \ No newline at end of file +music_session_constraints.sql +mixes_drop_manifest_add_retry.sql \ No newline at end of file diff --git a/db/up/icecast.sql b/db/up/icecast.sql index 01385f055..a04a62df8 100644 --- a/db/up/icecast.sql +++ b/db/up/icecast.sql @@ -147,11 +147,11 @@ create table icecast_relays ( -- mount at server. eg /example.ogg mount VARCHAR(128) not null, -- eg /different.ogg - local_mount VARCHAR(128) not null, + local_mount VARCHAR(128) not null default '/relaymout.ogg', -- eg joe. could be null - username VARCHAR(64) default NULL , + username VARCHAR(64) not null default 'jkicerelayusr' , -- user password - password VARCHAR(64) default null , + password VARCHAR(64) not null default 'jkicerelaypwd' , relay_shoutcast_metadata INTEGER default 0, --- relay only if we have someone wanting to listen on_demand INTEGER default 0, @@ -164,28 +164,28 @@ create TABLE icecast_user_authentications( id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(), --"htpasswd or url" -- real name is type - stype VARCHAR(16) DEFAULT NULL , + stype VARCHAR(16) DEFAULT 'url' , -- these are for httpasswd filename VARCHAR(256) default NULL, - allow_duplicate_users INTEGER DEFAULT 0, + allow_duplicate_users INTEGER DEFAULT 1, -- these options are for url -- eg value="http://myauthserver.com/stream_start.php" - mount_add VARCHAR(256) default NULL, + mount_add VARCHAR(256) DEFAULT 'http://icecastauth.jamkazam.com/stream_start.php', --value="http://myauthserver.com/stream_end.php" - mount_remove VARCHAR(256) default NULL, + mount_remove VARCHAR(256) default 'http://icecastauth.jamkazam.com/stream_end.php', --value="http://myauthserver.com/listener_joined.php" - listener_add VARCHAR(256) default NULL, + listener_add VARCHAR(256) default 'http://icecastauth.jamkazam.com/listener_joined.php', --value="http://myauthserver.com/listener_left.php" - listener_remove VARCHAR(256) default NULL, + listener_remove VARCHAR(256) default 'http://icecastauth.jamkazam.com/listener_left.php', -- value="user" - username VARCHAR(64) default NULL, + username VARCHAR(64) default 'jkuser', -- value="pass" - password VARCHAR(64) default NULL, + password VARCHAR(64) DEFAULT 'jkhackpass', -- value="icecast-auth-user: 1" - auth_header VARCHAR(64) default NULL, + auth_header VARCHAR(64) default 'icecast-auth-user: 1', -- value="icecast-auth-timelimit:" - timelimit_header VARCHAR(64) default NULL, + timelimit_header VARCHAR(64) default 'icecast-auth-timelimit:', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP @@ -197,7 +197,7 @@ create table icecast_mounts ( -- eg/example-complex.ogg mount_name VARCHAR(128) UNIQUE NOT NULL, username VARCHAR(64) NOT NULL DEFAULT 'jamsource', - password VARCHAR(64) NOT NULL DEFAULT 'jamksource', + password VARCHAR(64) NOT NULL DEFAULT 'jamhackmesourcepwd', max_listeners INTEGER NOT NULL DEFAULT 4, max_listener_duration INTEGER NOT NULL DEFAULT 3600, -- dump of the stream coming through on this mountpoint. @@ -248,6 +248,8 @@ create table icecast_mounts ( on_connect VARCHAR(256) DEFAULT '/home/icecast/bin/source-start', on_disconnect VARCHAR(256) DEFAULT '/home/icecast/bin/source-end', + user_authentication_id varchar(64) DEFAULT NULL references icecast_user_authentications(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); @@ -294,15 +296,60 @@ create table icecast_securities ( updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); + create TABLE icecast_servers( id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), - icecast_limit_id VARCHAR(64) REFERENCES icecast_limits(id) + --use this to mark the server configuration as needing to be regenerated + config_changed INTEGER DEFAULT 0, + limit_id VARCHAR(64) REFERENCES icecast_limits(id), + adminauth_id VARCHAR(64) REFERENCES icecast_admin_authentications(id), + directory_id VARCHAR(64) REFERENCES icecast_directories(id), + misc_id VARCHAR(64) REFERENCES icecast_servermiscs(id), + master_relay_id VARCHAR(64) REFERENCES icecast_mastersvr_relays(id), + /* relay_ids VARCHAR(64) REFERENCES icecast_serverrelays(id), + mount_ids VARCHAR(64) REFERENCES icecast_servermounts(id), + socket_ids VARCHAR(64) REFERENCES icecast_serversockets(id) , + */ - -- configs - -- mounts + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); +CREATE TABLE icecast_servermounts ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + mount_id VARCHAR(64) REFERENCES icecast_mounts(id) ON DELETE CASCADE, + server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE icecast_servermounts ADD CONSTRAINT server_mount_uniqkey UNIQUE (server_id, mount_id); + +CREATE TABLE icecast_serverrelays ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + relay_id VARCHAR(64) REFERENCES icecast_relays(id) ON DELETE CASCADE, + server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE icecast_serverrelays ADD CONSTRAINT server_relay_uniqkey UNIQUE (server_id, relay_id); + +CREATE TABLE icecast_serversockets ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + socket_id VARCHAR(64) REFERENCES icecast_listen_sockets(id) ON DELETE CASCADE, + server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +ALTER TABLE icecast_serversockets ADD CONSTRAINT server_socket_uniqkey UNIQUE (server_id, socket_id); + + + + + diff --git a/db/up/mixes_drop_manifest_add_retry.sql b/db/up/mixes_drop_manifest_add_retry.sql new file mode 100644 index 000000000..d7ce1dafa --- /dev/null +++ b/db/up/mixes_drop_manifest_add_retry.sql @@ -0,0 +1,2 @@ +ALTER TABLE mixes DROP COLUMN manifest; +ALTER TABLE mixes ADD COLUMN should_retry BOOLEAN NOT NULL DEFAULT FALSE; \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 4634f4814..0a36ead74 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -29,6 +29,7 @@ require "jam_ruby/lib/s3_util" require "jam_ruby/lib/s3_manager" require "jam_ruby/lib/profanity" require "jam_ruby/resque/audiomixer" +require "jam_ruby/resque/scheduled/audiomixer_retry" require "jam_ruby/mq_router" require "jam_ruby/base_manager" require "jam_ruby/connection_manager" diff --git a/ruby/lib/jam_ruby/models/icecast_admin_authentication.rb b/ruby/lib/jam_ruby/models/icecast_admin_authentication.rb index d94aeb1d1..f4ce4a1df 100644 --- a/ruby/lib/jam_ruby/models/icecast_admin_authentication.rb +++ b/ruby/lib/jam_ruby/models/icecast_admin_authentication.rb @@ -1,26 +1,19 @@ - -module JSONable - def jdumpXml (ovb, nm, ident=1, output=$stdout) - - serialized = Hash.new - ovb.myattr_accessor.each do |attribute| - #serialized[attribute] = ovb[attribute] - puts "attribute = #{attribute}" - #serialized[attribute] = self.public_send attribute - end - - hash = serialized +module JAmXml + def jdumpXml (hash, nm, ident=1, output=$stdout, child=nil) tb = "\t" tbs = tb * ident - tbse = tb * (ident-1) - output.puts "#{tbse}<#{nm}>" + unless ident <= 0 + tbse = tb * (ident-1) + output.puts "#{tbse}<#{nm}>" + end + hash.each do |key, val| #puts "attrib: key=#{key} val=#{val}" el = key - if key.present? + if !key.nil? && !key.empty? el = key.gsub(/_/, '-') end @@ -28,15 +21,45 @@ module JSONable sv = val if val.to_s.empty? #skip ??? + next if val.to_s.empty? else if val.instance_of? String #encode the string to be xml safe sv = CGI.escapeHTML(val) end end - output.puts "#{tbs}<#{el}>#{sv}" + + if key.empty? + output.puts "#{tbs}<#{sv}/>" + else + output.puts "#{tbs}<#{el}>#{sv}" + end end - puts "#{tbse}" + + if !child.nil? + if child.kind_of? Array + child.each { |x| x.dumpXml(ident+1,output)} + else + child.dumpXml(ident+1,output) + end + end + unless ident <= 0 + puts "#{tbse}" + end + end + + def jMakeStrXmlSafe(val) + sv = val + if val.to_s.empty? + #skip ??? + sv ="" + else + if val.instance_of? String + #encode the string to be xml safe + sv = CGI.escapeHTML(val) + end + end + return sv end end @@ -44,7 +67,7 @@ end module JamRuby class IcecastAdminAuthentication < ActiveRecord::Base - include JSONable + include JAmXml attr_accessible :source_password, :relay_user, :relay_password, :admin_user, :admin_password #myattr_accessor = [:source_password, :relay_user, :relay_password, :admin_user, :admin_password ] @@ -65,7 +88,13 @@ module JamRuby validates :admin_password, presence: true, length: {minimum: 5} def dumpXml (ident=1, output=$stdout) - self.jdumpXml(self,"authentication", ident,output) + hash = Hash["source_password" => self.source_password, + "relay_user" => self.relay_user, + "relay_password" => self.relay_password, + "admin_user" => self.admin_user, + "admin_password" => self.admin_password] + + self.jdumpXml(hash,"authentication", ident,output) end diff --git a/ruby/lib/jam_ruby/models/icecast_directory.rb b/ruby/lib/jam_ruby/models/icecast_directory.rb index f86a7f7c9..79f0f012a 100644 --- a/ruby/lib/jam_ruby/models/icecast_directory.rb +++ b/ruby/lib/jam_ruby/models/icecast_directory.rb @@ -1,10 +1,17 @@ module JamRuby class IcecastDirectory < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' + attr_accessible :yp_url_timeout, :yp_url - attr_accessor :yp_url_timeout, :yp_url + validates :yp_url_timeout, numericality: {only_integer: true}, length: {in: 1..30} + + def dumpXml (ident=1, output=$stdout) + hash = Hash["yp_url_timeout" => self.yp_url_timeout, + "yp_url" => self.yp_url] + self.jdumpXml(hash, "directory", ident, output) + end end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_limit.rb b/ruby/lib/jam_ruby/models/icecast_limit.rb index 02251b794..b3670b8bd 100644 --- a/ruby/lib/jam_ruby/models/icecast_limit.rb +++ b/ruby/lib/jam_ruby/models/icecast_limit.rb @@ -1,14 +1,13 @@ module JamRuby class IcecastLimit < ActiveRecord::Base - include JSONable + include JAmXml self.primary_key = 'id' attr_accessible :clients, :sources, :queue_size, :client_timeout, :header_timeout, :source_timeout, :burst_size - #attr_accessor :clients, :sources, :queue_size, :client_timeout, :header_timeout, :source_timeout, :burst_size - #validates :clients, numericality: {only_integer: true}, length: {in: 1..15000} - validates :clients, numericality: {only_integer: true} + validates :clients, numericality: {only_integer: true}, length: {in: 1..15000} + after_initialize :init @@ -23,12 +22,17 @@ module JamRuby self.burst_size ||= 65536 end - def setclients(val) - @clients = val - end + def dumpXml (ident=1, output=$stdout) - self.jdumpXml(self, "limits", ident, output) + hash = Hash["clients" => self.clients, + "sources" => self.sources, + "queue_size" => self.queue_size, + "client_timeout" => self.client_timeout, + "header_timeout" => self.header_timeout] + hash.merge! "source_timeout" => self.source_timeout, + "burst_size" => self.burst_size + self.jdumpXml(hash, "limits", ident, output) end end -end \ No newline at end of file +end diff --git a/ruby/lib/jam_ruby/models/icecast_listen_socket.rb b/ruby/lib/jam_ruby/models/icecast_listen_socket.rb index b4e1741f8..65d721b1a 100644 --- a/ruby/lib/jam_ruby/models/icecast_listen_socket.rb +++ b/ruby/lib/jam_ruby/models/icecast_listen_socket.rb @@ -1,13 +1,19 @@ module JamRuby class IcecastListenSocket < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :port, :bind_address, :shoutcast_mount, :shoutcast_compat - attr_accessor :port, :bind_address, :shoutcast_mount, :shoutcast_compat - def dumpXml() + belongs_to :server, :class_name => "JamRuby::IcecastServer" , :inverse_of => :sockets + def dumpXml (ident=1, output=$stdout) + hash = Hash["port" => self.port, + "bind_address" => self.bind_address, + "shoutcast_mount" => self.shoutcast_mount, + "shoutcast_compat" => self.shoutcast_compat] + + self.jdumpXml(hash, "listen-socket", ident, output) end diff --git a/ruby/lib/jam_ruby/models/icecast_logging.rb b/ruby/lib/jam_ruby/models/icecast_logging.rb index a2aa1cc88..45cd97401 100644 --- a/ruby/lib/jam_ruby/models/icecast_logging.rb +++ b/ruby/lib/jam_ruby/models/icecast_logging.rb @@ -1,12 +1,18 @@ module JamRuby class IcecastLogging < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :accesslog, :errorlog, :playlistlog, :loglevel - attr_accessor :accesslog, :errorlog, :playlistlog, :loglevel - def dumpXml() + def dumpXml (ident=1, output=$stdout) + + hash = Hash["accesslog" => self.accesslog, + "errorlog" => self.errorlog, + "loglevel" => self.loglevel, + "playlistlog" => self.playlistlog] + + self.jdumpXml(hash, "logging", ident, output) end diff --git a/ruby/lib/jam_ruby/models/icecast_mastersvr_relay.rb b/ruby/lib/jam_ruby/models/icecast_mastersvr_relay.rb index cd949c3d2..8cb9bd3a9 100644 --- a/ruby/lib/jam_ruby/models/icecast_mastersvr_relay.rb +++ b/ruby/lib/jam_ruby/models/icecast_mastersvr_relay.rb @@ -1,12 +1,18 @@ module JamRuby class IcecastMastersvrRelay < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :master_server, :master_server_port, :master_username, :master_password, :relays_on_demand - attr_accessible :master_server, :master_server_port, :master_username, :master_password, :relays_on_demand + validates :master_password, :master_username, presence: true - def dumpXml() + def dumpXml (ident=0, output=$stdout) + hash = Hash["master_server" => self.master_server, + "master_server_port" => self.master_server_port, + "master_username" => self.master_username, + "master_password" => self.master_password, + "relays_on_demand" => self.relays_on_demand] + self.jdumpXml(hash, "masterrelay", ident, output) end end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_mount.rb b/ruby/lib/jam_ruby/models/icecast_mount.rb index 47731cbf1..91b5873a6 100644 --- a/ruby/lib/jam_ruby/models/icecast_mount.rb +++ b/ruby/lib/jam_ruby/models/icecast_mount.rb @@ -1,24 +1,64 @@ module JamRuby class IcecastMount < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :mount_name, :username, :password, :max_listeners, :max_listener_duration, :dump_file - attr_accessor :mount_name, :username, :password, :max_listeners, :max_listener_duration, :dump_file - attr_accessible :intro, :fallback_mount, :fallback_override, :fallback_when_full, :charset - attr_accessor :intro, :fallback_mount, :fallback_override, :fallback_when_full, :charset - attr_accessible :publicc, :stream_name, :stream_description, :stream_url, :genre, :bitrate - attr_accessor :publicc, :stream_name, :stream_description, :stream_url, :genre, :bitrate - attr_accessible :mtype, :subtype, :hidden, :burst_size, :mp3_metadata_interval, :on_connect, :on_disconnect - attr_accessor :mtype, :subtype, :hidden, :burst_size, :mp3_metadata_interval, :on_connect, :on_disconnect + validates :mount_name, presence: true + validates :username, presence: true + validates :password, presence: true + + #has_one :authentication, :class_name => "IcecastUserAuthentication" has_one :authentication, :class_name => "IcecastUserAuthentication" + belongs_to :servermount, :class_name => "JamRuby::IcecastServermount" , :inverse_of => :mount - def dumpXml() + def dumpXml (ident=1, output=$stdout) + hash = Hash["mount_name" => self.mount_name, + "username" => self.username, + "password" => self.password, + "max_listeners" => self.max_listeners, + "max_listener_duration" => self.max_listener_duration, + "dump_file" => self.dump_file, + "intro" => self.intro, + "fallback_mount" => self.fallback_mount, + "fallback_override" => self.fallback_override, + "fallback_when_full" => self.fallback_when_full, + "charset" => self.charset, + + "public" => self.publicc, + "stream_name" => self.stream_name, + "stream_description" => self.stream_description, + "stream_url" => self.stream_url, + "genre" => self.genre, + "bitrate" => self.bitrate, + + "type" => self.mtype, + "subtype" => self.subtype, + "hidden" => self.hidden, + "burst_size" => self.burst_size, + "mp3_metadata_interval" => self.mp3_metadata_interval, + "on_connect" => self.on_connect, + "on_disconnect" => self.on_disconnect + ] + + self.jdumpXml(hash, "mount", ident, output, self.authentication) end + + def getMediaUrl + if !self.servermount.nil? + @server = self.servermount.server + @misc = @server.misc + url = "http://" + @misc.hostname + self.mount_name + return url; + else + raise ("Undefined severid") + end + end + end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_path.rb b/ruby/lib/jam_ruby/models/icecast_path.rb index a6f01e122..19edb23ab 100644 --- a/ruby/lib/jam_ruby/models/icecast_path.rb +++ b/ruby/lib/jam_ruby/models/icecast_path.rb @@ -1,13 +1,24 @@ module JamRuby class IcecastPath < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :basedir, :logdir, :pidfile, :webroot, :adminroot, :allow_ip, :deny_ip, :aliass - attr_accessor :basedir, :logdir, :pidfile, :webroot, :adminroot, :allow_ip, :deny_ip, :aliass - def dumpXml() + def dumpXml (ident=1, output=$stdout) + a = "alias #{self.aliass}" + hash = Hash["basedir" => self.basedir, + "logdir" => self.logdir, + "pidfile" => self.pidfile, + "webroot" => self.webroot, + "adminroot" => self.adminroot, + + "allow_ip" => self.allow_ip, + "deny_ip" => self.deny_ip, + "" => a, + ] + self.jdumpXml(hash, "paths", ident, output) end end diff --git a/ruby/lib/jam_ruby/models/icecast_relay.rb b/ruby/lib/jam_ruby/models/icecast_relay.rb index 19d9b275d..74f693f57 100644 --- a/ruby/lib/jam_ruby/models/icecast_relay.rb +++ b/ruby/lib/jam_ruby/models/icecast_relay.rb @@ -1,14 +1,35 @@ module JamRuby class IcecastRelay < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :server, :port, :mount, :local_mount, :username, :password, :relay_shoutcast_metadata, :on_demand - attr_accessor :server, :port, :mount, :local_mount, :username, :password, :relay_shoutcast_metadata, :on_demand - def dumpXml() + validates :port, numericality: {only_integer: true}, length: {in: 1..65000} + validates :mount, presence: true + validates :server, presence: true + validates :local_mount, presence: true + validates :username, presence: true + validates :password, presence: true + belongs_to :sserver, :class_name => "JamRuby::IcecastServerrelay" + + + def dumpXml (ident=1, output=$stdout) + + hash = Hash["server" => self.server, + "port" => self.port, + "mount" => self.mount, + "local_mount" => self.local_mount, + "username" => self.username, + + "password" => self.password, + "relay_shoutcast_metadata" => self.relay_shoutcast_metadata, + "on_demand" => self.on_demand + ] + self.jdumpXml(hash, "relay", ident, output) end + end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_sercurity.rb b/ruby/lib/jam_ruby/models/icecast_sercurity.rb index 318c055ed..3a8dafef8 100644 --- a/ruby/lib/jam_ruby/models/icecast_sercurity.rb +++ b/ruby/lib/jam_ruby/models/icecast_sercurity.rb @@ -1,12 +1,39 @@ module JamRuby class IcecastSecurity < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :chroot, :changeowner_user, :changeowner_group - attr_accessor :chroot, :changeowner_user, :changeowner_group - def dumpXml() + validates :chroot, numericality: {only_integer: true}, length: {in: 0..1} + + + def dumpXml (ident=1, output=$stdout) + + tb = "\t" + tbs = tb * (ident) + tbs2 = tb * (ident+1) + tbse = tb * (ident-1) + if tbse.empty? || tbse.nil? + tbse="" + end + + + nm = "security" + output.puts "#{tbse}<#{nm}>" + + output.puts "#{tbs}#{self.chroot}" + output.puts "#{tbs}" + + v = jMakeStrXmlSafe(self.changeowner_user) + output.puts "#{tbs2}#{v}" + + v = jMakeStrXmlSafe(self.changeowner_group) + output.puts "#{tbs2}#{v}" + + output.puts "#{tbs}" + + output.puts "#{tbse}" end diff --git a/ruby/lib/jam_ruby/models/icecast_server.rb b/ruby/lib/jam_ruby/models/icecast_server.rb index 8f837edc8..c753e44e0 100644 --- a/ruby/lib/jam_ruby/models/icecast_server.rb +++ b/ruby/lib/jam_ruby/models/icecast_server.rb @@ -1,21 +1,75 @@ module JamRuby class IcecastServer < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' - has_one :limit, :class_name => "JamRuby::IcecastLimit" - has_one :adminauth, :class_name => "JamRuby::IcecastAdminAuthentication" - has_one :directory, :class_name => "JamRuby::IcecastDirectory" - has_one :misc, :class_name => "JamRuby::IcecastServermisc" - has_many :listen_sockets, :class_name => "JamRuby::IcecastListenSocket" - has_one :master_relay, :class_name => "JamRuby::IcecastMastersvrRelay" - has_one :relay, :class_name => "JamRuby::IcecastRelay" - has_many :mounts, :class_name => "JamRuby::IcecastMount" - has_one :path, :class_name => "JamRuby::IcecastPath" - has_one :logging, :class_name => "JamRuby::IcecastLogging" - has_one :security, :class_name => "JamRuby::IceCastSecurity" + has_one :limit, :class_name => "JamRuby::IcecastLimit" , foreign_key: "id" + has_one :adminauth, :class_name => "JamRuby::IcecastAdminAuthentication" , foreign_key: "id" + has_one :directory, :class_name => "JamRuby::IcecastDirectory" , foreign_key: "id" + has_one :misc, :class_name => "JamRuby::IcecastServermisc" , foreign_key: "id" - def dumpXml() + has_one :master_relay, :class_name => "JamRuby::IcecastMastersvrRelay" , foreign_key: "id" + + has_many :smounts, :class_name => "JamRuby::IcecastServermount" + has_many :mounts, :class_name => "JamRuby::IcecastMount", :through => :smounts + + has_many :ssockets, :class_name => "JamRuby::IcecastServersocket" + has_many :sockets, :class_name => "JamRuby::IcecastListenSocket" ,:through => :ssockets + + has_many :srelays, :class_name => "JamRuby::IcecastServerrelay" , :inverse_of => :server + has_many :relays, :class_name => "JamRuby::IcecastRelay" , :through => :srelays + + + has_one :path, :class_name => "JamRuby::IcecastPath" , foreign_key: "id" + has_one :logging, :class_name => "JamRuby::IcecastLogging" , foreign_key: "id" + has_one :security, :class_name => "JamRuby::IcecastSecurity" , foreign_key: "id" + + def dumpXml (ident=1, output=$stdout) + ident += 1 + unless self.limit.nil? + self.limit.dumpXml(ident,output) + end + unless self.adminauth.nil? + self.adminauth.dumpXml(ident,output) + end + + unless self.directory.nil? + self.directory.dumpXml(ident,output) + end + + unless self.misc.nil? + self.misc.dumpXml(ident,output) + end + + unless self.master_relay.nil? + self.master_relay.dumpXml(ident,output) + end + + + unless self.path.nil? + self.path.dumpXml(ident,output) + end + + unless self.logging.nil? + self.logging.dumpXml(ident,output) + end + + unless self.security.nil? + self.security.dumpXml(ident,output) + end + + + self.relays.each do |rl| + sock.rl(ident,output) + end + + self.sockets.each do |sock| + sock.dumpXml(ident,output) + end + + self.mounts.each do |mount| + mount.dumpXml(ident,output) + end end diff --git a/ruby/lib/jam_ruby/models/icecast_servermisc.rb b/ruby/lib/jam_ruby/models/icecast_servermisc.rb index 881a1c811..cdc2b2c95 100644 --- a/ruby/lib/jam_ruby/models/icecast_servermisc.rb +++ b/ruby/lib/jam_ruby/models/icecast_servermisc.rb @@ -1,12 +1,12 @@ module JamRuby class IcecastServermisc < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :hostname, :location, :admin, :fileserve, :server_id - attr_accessor :hostname, :location, :admin, :fileserve, :server_id - def dumpXml() + + def dumpXml (ident=0, output=$stdout) end diff --git a/ruby/lib/jam_ruby/models/icecast_servermount.rb b/ruby/lib/jam_ruby/models/icecast_servermount.rb new file mode 100644 index 000000000..633bc6af2 --- /dev/null +++ b/ruby/lib/jam_ruby/models/icecast_servermount.rb @@ -0,0 +1,14 @@ +module JamRuby + class IcecastServermount < ActiveRecord::Base + + self.primary_key = 'id' + + belongs_to :mount, :class_name => "JamRuby::IcecastMount" , :inverse_of => :servermount + belongs_to :server, :class_name => "JamRuby::IcecastServer" + + validates :server_id, :presence => true + validates :mount_id, :presence => true + + + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_serverrelay.rb b/ruby/lib/jam_ruby/models/icecast_serverrelay.rb new file mode 100644 index 000000000..14b80220c --- /dev/null +++ b/ruby/lib/jam_ruby/models/icecast_serverrelay.rb @@ -0,0 +1,14 @@ +module JamRuby + class IcecastServerrelay < ActiveRecord::Base + + self.primary_key = 'id' + + belongs_to :relay, :class_name => "JamRuby::IcecastRelay" + belongs_to :server, :class_name => "JamRuby::IcecastServer" + + validates :server_id, :presence => true + validates :relay_id, :presence => true + + + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_serversocket.rb b/ruby/lib/jam_ruby/models/icecast_serversocket.rb new file mode 100644 index 000000000..c677e23d2 --- /dev/null +++ b/ruby/lib/jam_ruby/models/icecast_serversocket.rb @@ -0,0 +1,14 @@ +module JamRuby + class IcecastServersocket < ActiveRecord::Base + + self.primary_key = 'id' + + belongs_to :socket, :class_name => "JamRuby::IcecastListenSocket" , foreign_key: "id" + belongs_to :server, :class_name => "JamRuby::IcecastServer" , foreign_key: "id" + + validates :socket_id, :presence => true + validates :server_id, :presence => true + + + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/icecast_user_authentication.rb b/ruby/lib/jam_ruby/models/icecast_user_authentication.rb index 12d4f1520..a28056bae 100644 --- a/ruby/lib/jam_ruby/models/icecast_user_authentication.rb +++ b/ruby/lib/jam_ruby/models/icecast_user_authentication.rb @@ -1,16 +1,76 @@ module JamRuby class IcecastUserAuthentication < ActiveRecord::Base - + include JAmXml self.primary_key = 'id' attr_accessible :stype, :filename, :allow_duplicate_users, :mount_add, :mount_remove, :listener_add, :listener_remove, :username, :password, :auth_header, :timelimit_header - attr_accessor :stype, :filename, :allow_duplicate_users, :mount_add, :mount_remove, - :listener_add, :listener_remove, :username, :password, :auth_header, :timelimit_header - def dumpXml() + validates :stype, presence: true + + def dumpXml (ident=1, output=$stdout) + + tb = "\t" + tbs = tb * (ident) + tbse = tb * (ident-1) + if tbse.empty? || tbse.nil? + tbse="" + end + + if self.stype.nil? + return + elsif self.stype.empty? + return + elsif self.stype == "htpasswd" + nm = "" + + output.puts "#{tbse}#{nm}" + fname = jMakeStrXmlSafe(self.filename) + + output.puts "#{tbs}