From 97ace0f06ab72b82ed0be4ca5c481f4f16a3c847 Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 1 Apr 2016 02:25:36 -0700 Subject: api: added super simple motd, closes #7866 --- app/controllers/v1/messages_controller.rb | 112 +++++++++++++++++++++++-- config/application.rb | 7 +- config/initializers/customization.rb | 3 +- test/files/motd/1.de.md | 1 + test/files/motd/1.en.md | 1 + test/files/motd/1.es.md | 1 + test/files/motd/2.en.md | 1 + test/functional/v1/messages_controller_test.rb | 42 ++++++++++ 8 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 test/files/motd/1.de.md create mode 100644 test/files/motd/1.en.md create mode 100644 test/files/motd/1.es.md create mode 100644 test/files/motd/2.en.md diff --git a/app/controllers/v1/messages_controller.rb b/app/controllers/v1/messages_controller.rb index a496378..c0ca0c7 100644 --- a/app/controllers/v1/messages_controller.rb +++ b/app/controllers/v1/messages_controller.rb @@ -4,17 +4,115 @@ module V1 before_filter :require_login def index - render json: current_user.messages + if Dir.exist?(motd_dir) + if !CommonLanguages::available_code?(params[:locale]) + locale = 'en' + else + locale = params[:locale] + end + render json: motd_files_for_locale(locale) + else + render json: [] + end + end + + # disable per-user messages for now, not supported in the client + #def update + # if message = Message.find(params[:id]) + # message.mark_as_read_by(current_user) + # message.save + # render json: success(:marked_as_read) + # else + # render json: error(:not_found), status: :not_found + # end + #end + + private + + # + # returns list of messages, for example: + # + # [ + # {"id": 1, "locale": "en", "text": ""}, + # {"id": 2, "locale": "en", "text": ""} + # ] + # + # Each message is present only once, using the best choice + # for the locale. The order is determined by the id. + # + def motd_files_for_locale(locale) + files = [] + motd_files.keys.each do |id| + if motd_files[id].key?(locale) + msg_locale = locale + elsif motd_files[id].key?('en') + msg_locale = 'en' + else + msg_locale = motd_files[id].keys.first + end + files << { + "id" => id, + "locale" => msg_locale, + "text" => motd_files[id][msg_locale] + } + end + files.sort! {|a,b| a["id"].to_i <=> b["id"].to_i } + return files + end + + # + # returns messages of the day as a hash: + # { "1": {"en": "message"}, "2": {"en": "message"} } + # + def motd_files + if motd_changed? || @motd_files.nil? + @motd_files = load_motd_files + else + @motd_files + end end - def update - if message = Message.find(params[:id]) - message.mark_as_read_by(current_user) - message.save - render json: success(:marked_as_read) + def motd_changed? + newest = Dir.glob(File.join(motd_dir, '*.{html,md}')).collect{|file| File.mtime(file)}.max + if @timestamp.nil? + @timestamp = newest + return true + elsif @timestamp < newest + @timestamp = newest + return true else - render json: error(:not_found), status: :not_found + return false + end + end + + def load_motd_files + files = {} + Dir.glob(File.join(motd_dir, '*.{html,md}')).each do |file| + id, locale, msg = parse_motd_file(file) + next unless id + files[id] ||= {} + files[id][locale] = msg + end + files + end + + def parse_motd_file(file) + id, locale, ext = File.basename(file).split('.') + if id.nil? || locale.nil? || ext.nil? || id.to_i.to_s != id || !['md', 'html'].include?(ext) + Rails.logger.error "ERROR: Could not parse MOTD file #{file}" + return nil + end + contents = File.read(file) + if ext == "md" + msg = RDiscount.new(contents, :autolink).to_html + elsif ext == "html" + msg = File.read(file) end + return id, locale, msg + end + + def motd_dir + File.join(APP_CONFIG['customization_directory'], 'motd') end end diff --git a/config/application.rb b/config/application.rb index 8555f48..b13c7d9 100644 --- a/config/application.rb +++ b/config/application.rb @@ -90,7 +90,12 @@ module LeapWeb ## CUSTOMIZATION ## see initializers/customization.rb ## - config.paths['app/views'].unshift "config/customization/views" + if APP_CONFIG["customization_directory"] + custom_view_path = (Pathname.new(APP_CONFIG["customization_directory"]).relative_path_from(Rails.root) + 'views').to_s + else + custom_view_path = "config/customization/views" + end + config.paths['app/views'].unshift custom_view_path # handle http errors ourselves config.exceptions_app = self.routes diff --git a/config/initializers/customization.rb b/config/initializers/customization.rb index 76a2947..aaa2939 100644 --- a/config/initializers/customization.rb +++ b/config/initializers/customization.rb @@ -1,7 +1,8 @@ # # When deploying, common customizations can be dropped in config/customizations. This initializer makes this work. # -customization_directory = "#{Rails.root}/config/customization" +APP_CONFIG["customization_directory"] ||= "#{Rails.root}/config/customization" +customization_directory = APP_CONFIG["customization_directory"] # # Set customization views as the first view path diff --git a/test/files/motd/1.de.md b/test/files/motd/1.de.md new file mode 100644 index 0000000..89928b8 --- /dev/null +++ b/test/files/motd/1.de.md @@ -0,0 +1 @@ +Dies ist eine sehr feine Nachricht. https://bitmask.net \ No newline at end of file diff --git a/test/files/motd/1.en.md b/test/files/motd/1.en.md new file mode 100644 index 0000000..b4c451c --- /dev/null +++ b/test/files/motd/1.en.md @@ -0,0 +1 @@ +"This" is a **very** fine message. https://bitmask.net \ No newline at end of file diff --git a/test/files/motd/1.es.md b/test/files/motd/1.es.md new file mode 100644 index 0000000..58dc05d --- /dev/null +++ b/test/files/motd/1.es.md @@ -0,0 +1 @@ +Este es un mensaje **muy** fino. https://bitmask.net \ No newline at end of file diff --git a/test/files/motd/2.en.md b/test/files/motd/2.en.md new file mode 100644 index 0000000..fec4590 --- /dev/null +++ b/test/files/motd/2.en.md @@ -0,0 +1 @@ +Today's message is: "be excellent to each other" \ No newline at end of file diff --git a/test/functional/v1/messages_controller_test.rb b/test/functional/v1/messages_controller_test.rb index 720d862..67f34a1 100644 --- a/test/functional/v1/messages_controller_test.rb +++ b/test/functional/v1/messages_controller_test.rb @@ -2,6 +2,47 @@ require 'test_helper' class V1::MessagesControllerTest < ActionController::TestCase + setup do + @user = FactoryGirl.build(:user) + @user.save + end + + # NOTE: the available languages for test are :en and :de + # so :es will result in english response. + + test "get the motd" do + with_config("customization_directory" => Rails.root+'test/files') do + login @user + get :index, :locale => 'es' + body = JSON.parse(response.body) + p body + message1 = "

\"This\" is a very fine message. https://bitmask.net

\n" + assert_equal 2, body.size, 'there should be two messages' + assert_equal message1, body.first["text"], 'first message text should match files/motd/1.en.md' + end + end + + test "get localized motd" do + with_config("customization_directory" => Rails.root+'test/files') do + login @user + get :index, :locale => 'de' + body = JSON.parse(response.body) + message1 = "

Dies ist eine sehr feine Nachricht. https://bitmask.net

\n" + assert_equal message1, body.first["text"], 'first message text should match files/motd/1.de.md' + end + end + + test "get empty motd" do + login @user + get :index + assert_equal "[]", response.body, "motd response should be empty if no motd directory exists" + end + + ## + ## For now, only the static file MOTD is supported, not messages in the db. + ## so, this is disabled: + ## +=begin setup do InviteCodeValidator.any_instance.stubs(:validate) @user = FactoryGirl.build(:user) @@ -54,5 +95,6 @@ class V1::MessagesControllerTest < ActionController::TestCase get :index, :format => :json assert_login_required end +=end end -- cgit v1.2.3