diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index aa6907c5226..5f71482907f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -10,7 +10,7 @@ on Discourse with: 1. Install VirtualBox: https://www.virtualbox.org/wiki/Downloads 2. Install Vagrant: https://www.vagrantup.com/ 3. Open a terminal -4. Clone the project: `git@github.com:discourse/discourse.git` +4. Clone the project: `git clone git@github.com:discourse/discourse.git` 5. Enter the project directory: `cd discourse` ### Using Vagrant diff --git a/app/assets/images/d-logo-sketch-small.png b/app/assets/images/d-logo-sketch-small.png new file mode 100644 index 00000000000..3467f147f55 Binary files /dev/null and b/app/assets/images/d-logo-sketch-small.png differ diff --git a/app/assets/images/d-logo-sketch.png b/app/assets/images/d-logo-sketch.png new file mode 100755 index 00000000000..56f3284fd3e Binary files /dev/null and b/app/assets/images/d-logo-sketch.png differ diff --git a/app/assets/javascripts/discourse/templates/topic_summary/private_message.js.handlebars b/app/assets/javascripts/discourse/templates/topic_summary/private_message.js.handlebars index b61798b62ad..550f7118f91 100644 --- a/app/assets/javascripts/discourse/templates/topic_summary/private_message.js.handlebars +++ b/app/assets/javascripts/discourse/templates/topic_summary/private_message.js.handlebars @@ -1,5 +1,4 @@

{{i18n private_message_info.title}}

-

{{{i18n private_message_info.description}}}

{{#each content.allowed_users}}
diff --git a/app/assets/stylesheets/application/topic.css.scss b/app/assets/stylesheets/application/topic.css.scss index a63f9235393..6b5a30472e8 100644 --- a/app/assets/stylesheets/application/topic.css.scss +++ b/app/assets/stylesheets/application/topic.css.scss @@ -387,7 +387,7 @@ kbd { z-index: 1; } button { - padding: 0; + padding: 0 1px; cursor: pointer; z-index: 1000; position: absolute; diff --git a/app/models/post.rb b/app/models/post.rb index 496224570c3..b97aa40af49 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -115,10 +115,21 @@ class Post < ActiveRecord::Base self.cooked = nil end + def self.white_listed_image_classes + @white_listed_image_classes ||= ['avatar'] + end + def image_count return 0 unless self.raw.present? - cooked_document.search("img.emoji").remove - cooked_document.search("img").count + + cooked_document.search("img").reject{ |t| + dom_class = t["class"] + if dom_class + (Post.white_listed_image_classes & dom_class.split(" ")).count > 0 + else + false + end + }.count end def link_count diff --git a/app/models/post_alert_observer.rb b/app/models/post_alert_observer.rb index 2fb9164546e..08112cb58cf 100644 --- a/app/models/post_alert_observer.rb +++ b/app/models/post_alert_observer.rb @@ -101,7 +101,7 @@ class PostAlertObserver < ActiveRecord::Observer result = [] post.raw.scan(/\[quote=\"([^,]+),.+\"\]/).uniq.each do |m| username = m.first.strip.downcase - user = User.where("(LOWER(username_lower) = :username or LOWER(name) = :username) and id != :id", username: username, id: post.user_id).first + user = User.where("username_lower = :username and id != :id", username: username, id: post.user_id).first result << user if user.present? end result diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index 37ec0810eab..708c15d0c98 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -10,8 +10,8 @@ class SiteSetting < ActiveRecord::Base # settings available in javascript under Discourse.SiteSettings client_setting(:title, "Discourse") - client_setting(:logo_url, '/assets/logo.png') - client_setting(:logo_small_url, '') + client_setting(:logo_url, '/assets/d-logo-sketch.png') + client_setting(:logo_small_url, '/assets/d-logo-sketch-small.png') client_setting(:traditional_markdown_linebreaks, false) client_setting(:popup_delay, 1500) client_setting(:top_menu, 'popular|new|unread|favorited|categories') diff --git a/config/discourse.pill.sample b/config/discourse.pill.sample new file mode 100644 index 00000000000..9b8165d73b4 --- /dev/null +++ b/config/discourse.pill.sample @@ -0,0 +1,89 @@ +rails_env = ENV['RAILS_ENV'] || "production" +rails_root = ENV['RAILS_ROOT'] || "/var/rails/my_discourse" + +user = ENV["DISCOURSE_USER"] || ENV['USER'] || 'user_running_app' +group = ENV["DISCOURSE_GROUP"] || ENV['GROUP'] || 'www-data' +num_webs = ENV["NUM_WEBS"].to_i > 0 ? ENV["NUM_WEBS"].to_i : 4 + +# to debug use +#Bluepill.application("your_app", :foreground => true) do |app| +Bluepill.application("your_app") do |app| + + app.gid = group + app.uid = user + + # getting this to work was a nightmare + # bundle exec spawns a process totally messing with the demonize option + # so we suck the environment out and set it up first + app.environment = `env -i BUNDLE_GEMFILE=#{rails_root}/Gemfile /usr/local/rvm/bin/bootup_bundle exec env`.lines.inject({}) do |env_hash,l| + kv = l.chomp.split('=',2) + env_hash[kv[0]] = kv[1] + env_hash + end if File.exist?("/usr/local/rvm/bin/rvm") + + app.environment ||= {} + app.environment['RAILS_ENV'] = rails_env + + app.gid = group + app.uid = user + + app.working_dir = rails_root + num_webs.times do |i| + app.process("thin-#{i}") do |process| + process.start_command = "bundle exec thin start -e production -t 0 -p #{9040 + i} -P #{rails_root}/tmp/pids/thin#{i}.pid -d" + process.pid_file = "#{rails_root}/tmp/pids/thin#{i}.pid" + process.start_grace_time = 30.seconds + process.stop_grace_time = 10.seconds + process.restart_grace_time = 10.seconds + process.group = "thins" + process.uid = user + process.gid = group + process.daemonize = false + process.stdout = process.stderr = "#{rails_root}/log/thin#{i}.log" + end + end + +#debug instance + app.process("thin-debug") do |process| + process.start_command = "bundle exec thin start -e development -t 0 -p 10040 -P #{rails_root}/tmp/pids/thin-debug.pid -d" + process.pid_file = "#{rails_root}/tmp/pids/thin-debug.pid" + process.start_grace_time = 30.seconds + process.stop_grace_time = 10.seconds + process.restart_grace_time = 10.seconds + process.group = "thins" + process.uid = user + process.gid = group + process.daemonize = false + process.stdout = process.stderr = "#{rails_root}/log/thin-debug.log" + end + + app.process("sidekiq-worker") do |process| + pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid" + + process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq" + process.pid_file = pidfile + process.start_grace_time = 30.seconds + process.stop_grace_time = 10.seconds + process.restart_grace_time = 10.seconds + process.uid = user + process.gid = group + process.daemonize = true + end + + if `hostname`.strip == "host to run on" + app.process("clockwork") do |process| + pidfile = "#{rails_root}/tmp/pids/clockwork.pid" + + process.start_command = "/usr/bin/env RAILS_ENV=#{rails_env} bundle exec clockwork config/clock.rb" + process.pid_file = pidfile + process.start_grace_time = 30.seconds + process.stop_grace_time = 10.seconds + process.restart_grace_time = 10.seconds + process.uid = user + process.gid = group + process.daemonize = true + end + end + +end + diff --git a/config/locales/en.yml b/config/locales/en.yml index 114e3241cee..e6a0203b993 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -596,7 +596,6 @@ en: private_message_info: title: "Private Conversation" - description: "Participants in this private conversation" invite: "Invite Others..." email: 'Email' diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index 929afd1e0df..00000000000 --- a/db/schema.rb +++ /dev/null @@ -1,514 +0,0 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended to check this file into your version control system. - -ActiveRecord::Schema.define(:version => 20130205021905) do - - create_table "categories", :force => true do |t| - t.string "name", :limit => 50, :null => false - t.string "color", :limit => 6, :default => "AB9364", :null => false - t.integer "topic_id" - t.integer "top1_topic_id" - t.integer "top2_topic_id" - t.integer "top1_user_id" - t.integer "top2_user_id" - t.integer "topic_count", :default => 0, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "user_id", :null => false - t.integer "topics_year" - t.integer "topics_month" - t.integer "topics_week" - t.string "slug", :null => false - end - - add_index "categories", ["name"], :name => "index_categories_on_name", :unique => true - add_index "categories", ["topic_count"], :name => "index_categories_on_forum_thread_count" - - create_table "categories_search", :id => false, :force => true do |t| - t.integer "id", :null => false - t.tsvector "search_data" - end - - add_index "categories_search", ["search_data"], :name => "idx_search_category" - - create_table "category_featured_topics", :id => false, :force => true do |t| - t.integer "category_id", :null => false - t.integer "topic_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "category_featured_topics", ["category_id", "topic_id"], :name => "cat_featured_threads", :unique => true - - create_table "category_featured_users", :force => true do |t| - t.integer "category_id" - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "category_featured_users", ["category_id", "user_id"], :name => "index_category_featured_users_on_category_id_and_user_id", :unique => true - - create_table "draft_sequences", :force => true do |t| - t.integer "user_id", :null => false - t.string "draft_key", :null => false - t.integer "sequence", :null => false - end - - add_index "draft_sequences", ["user_id", "draft_key"], :name => "index_draft_sequences_on_user_id_and_draft_key", :unique => true - - create_table "drafts", :force => true do |t| - t.integer "user_id", :null => false - t.string "draft_key", :null => false - t.text "data", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "sequence", :default => 0, :null => false - end - - add_index "drafts", ["user_id", "draft_key"], :name => "index_drafts_on_user_id_and_draft_key" - - create_table "email_logs", :force => true do |t| - t.string "to_address", :null => false - t.string "email_type", :null => false - t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "email_logs", ["created_at"], :name => "index_email_logs_on_created_at", :order => {"created_at"=>:desc} - add_index "email_logs", ["user_id", "created_at"], :name => "index_email_logs_on_user_id_and_created_at", :order => {"created_at"=>:desc} - - create_table "email_tokens", :force => true do |t| - t.integer "user_id", :null => false - t.string "email", :null => false - t.string "token", :null => false - t.boolean "confirmed", :default => false, :null => false - t.boolean "expired", :default => false, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "email_tokens", ["token"], :name => "index_email_tokens_on_token", :unique => true - - create_table "facebook_user_infos", :force => true do |t| - t.integer "user_id", :null => false - t.integer "facebook_user_id", :limit => 8, :null => false - t.string "username", :null => false - t.string "first_name" - t.string "last_name" - t.string "email" - t.string "gender" - t.string "name" - t.string "link" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "facebook_user_infos", ["facebook_user_id"], :name => "index_facebook_user_infos_on_facebook_user_id", :unique => true - add_index "facebook_user_infos", ["user_id"], :name => "index_facebook_user_infos_on_user_id", :unique => true - - create_table "incoming_links", :force => true do |t| - t.string "url", :limit => 1000, :null => false - t.string "referer", :limit => 1000, :null => false - t.string "domain", :limit => 100, :null => false - t.integer "topic_id" - t.integer "post_number" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "incoming_links", ["topic_id", "post_number"], :name => "incoming_index" - - create_table "invites", :force => true do |t| - t.string "invite_key", :limit => 32, :null => false - t.string "email", :null => false - t.integer "invited_by_id", :null => false - t.integer "user_id" - t.datetime "redeemed_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.datetime "deleted_at" - end - - add_index "invites", ["email", "invited_by_id"], :name => "index_invites_on_email_and_invited_by_id", :unique => true - add_index "invites", ["invite_key"], :name => "index_invites_on_invite_key", :unique => true - - create_table "message_bus", :force => true do |t| - t.string "name" - t.string "context" - t.text "data" - t.datetime "created_at" - end - - add_index "message_bus", ["created_at"], :name => "index_message_bus_on_created_at" - - create_table "notifications", :force => true do |t| - t.integer "notification_type", :null => false - t.integer "user_id", :null => false - t.string "data", :null => false - t.boolean "read", :default => false, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "topic_id" - t.integer "post_number" - t.integer "post_action_id" - end - - add_index "notifications", ["post_action_id"], :name => "index_notifications_on_post_action_id" - add_index "notifications", ["user_id", "created_at"], :name => "index_notifications_on_user_id_and_created_at" - - create_table "onebox_renders", :force => true do |t| - t.string "url", :null => false - t.text "cooked", :null => false - t.datetime "expires_at", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "preview" - end - - add_index "onebox_renders", ["url"], :name => "index_onebox_renders_on_url", :unique => true - - create_table "post_action_types", :force => true do |t| - t.string "name_key", :limit => 50, :null => false - t.boolean "is_flag", :default => false, :null => false - t.string "icon", :limit => 20 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position", :default => 0, :null => false - end - - create_table "post_actions", :force => true do |t| - t.integer "post_id", :null => false - t.integer "user_id", :null => false - t.integer "post_action_type_id", :null => false - t.datetime "deleted_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "deleted_by" - t.text "message" - end - - add_index "post_actions", ["post_id"], :name => "index_post_actions_on_post_id" - add_index "post_actions", ["user_id", "post_action_type_id", "post_id", "deleted_at"], :name => "idx_unique_actions", :unique => true - - create_table "post_onebox_renders", :id => false, :force => true do |t| - t.integer "post_id", :null => false - t.integer "onebox_render_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "post_onebox_renders", ["post_id", "onebox_render_id"], :name => "index_post_onebox_renders_on_post_id_and_onebox_render_id", :unique => true - - create_table "post_replies", :id => false, :force => true do |t| - t.integer "post_id" - t.integer "reply_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "post_replies", ["post_id", "reply_id"], :name => "index_post_replies_on_post_id_and_reply_id", :unique => true - - create_table "post_timings", :id => false, :force => true do |t| - t.integer "topic_id", :null => false - t.integer "post_number", :null => false - t.integer "user_id", :null => false - t.integer "msecs", :null => false - end - - add_index "post_timings", ["topic_id", "post_number", "user_id"], :name => "post_timings_unique", :unique => true - add_index "post_timings", ["topic_id", "post_number"], :name => "post_timings_summary" - - create_table "posts", :force => true do |t| - t.integer "user_id", :null => false - t.integer "topic_id", :null => false - t.integer "post_number", :null => false - t.text "raw", :null => false - t.text "cooked", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "reply_to_post_number" - t.integer "cached_version", :default => 1, :null => false - t.integer "reply_count", :default => 0, :null => false - t.integer "quote_count", :default => 0, :null => false - t.integer "reply_below_post_number" - t.datetime "deleted_at" - t.integer "off_topic_count", :default => 0, :null => false - t.integer "like_count", :default => 0, :null => false - t.integer "incoming_link_count", :default => 0, :null => false - t.integer "bookmark_count", :default => 0, :null => false - t.integer "avg_time" - t.float "score" - t.integer "reads", :default => 0, :null => false - t.integer "post_type", :default => 1, :null => false - t.integer "vote_count", :default => 0, :null => false - t.integer "sort_order" - t.integer "last_editor_id" - t.boolean "hidden", :default => false, :null => false - t.integer "hidden_reason_id" - t.integer "custom_flag_count", :default => 0, :null => false - t.integer "spam_count", :default => 0, :null => false - t.integer "illegal_count", :default => 0, :null => false - t.integer "inappropriate_count", :default => 0, :null => false - t.datetime "last_version_at", :null => false - end - - add_index "posts", ["reply_to_post_number"], :name => "index_posts_on_reply_to_post_number" - add_index "posts", ["topic_id", "post_number"], :name => "index_posts_on_topic_id_and_post_number", :unique => true - - create_table "posts_search", :id => false, :force => true do |t| - t.integer "id", :null => false - t.tsvector "search_data" - end - - add_index "posts_search", ["search_data"], :name => "idx_search_post" - - create_table "site_customizations", :force => true do |t| - t.string "name", :null => false - t.text "stylesheet" - t.text "header" - t.integer "position", :null => false - t.integer "user_id", :null => false - t.boolean "enabled", :null => false - t.string "key", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "override_default_style", :default => false, :null => false - t.text "stylesheet_baked", :default => "", :null => false - end - - add_index "site_customizations", ["key"], :name => "index_site_customizations_on_key" - - create_table "site_settings", :force => true do |t| - t.string "name", :null => false - t.integer "data_type", :null => false - t.text "value" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "topic_allowed_users", :force => true do |t| - t.integer "user_id", :null => false - t.integer "topic_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "topic_allowed_users", ["topic_id", "user_id"], :name => "index_topic_allowed_users_on_topic_id_and_user_id", :unique => true - add_index "topic_allowed_users", ["user_id", "topic_id"], :name => "index_topic_allowed_users_on_user_id_and_topic_id", :unique => true - - create_table "topic_invites", :force => true do |t| - t.integer "topic_id", :null => false - t.integer "invite_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "topic_invites", ["invite_id"], :name => "index_topic_invites_on_invite_id" - add_index "topic_invites", ["topic_id", "invite_id"], :name => "index_topic_invites_on_topic_id_and_invite_id", :unique => true - - create_table "topic_link_clicks", :force => true do |t| - t.integer "topic_link_id", :null => false - t.integer "user_id" - t.integer "ip", :limit => 8, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "topic_link_clicks", ["topic_link_id"], :name => "index_forum_thread_link_clicks_on_forum_thread_link_id" - - create_table "topic_links", :force => true do |t| - t.integer "topic_id", :null => false - t.integer "post_id" - t.integer "user_id", :null => false - t.string "url", :limit => 500, :null => false - t.string "domain", :limit => 100, :null => false - t.boolean "internal", :default => false, :null => false - t.integer "link_topic_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "reflection", :default => false - t.integer "clicks", :default => 0, :null => false - t.integer "link_post_id" - end - - add_index "topic_links", ["topic_id", "post_id", "url"], :name => "index_forum_thread_links_on_forum_thread_id_and_post_id_and_url", :unique => true - add_index "topic_links", ["topic_id"], :name => "index_forum_thread_links_on_forum_thread_id" - - create_table "topic_users", :id => false, :force => true do |t| - t.integer "user_id", :null => false - t.integer "topic_id", :null => false - t.boolean "starred", :default => false, :null => false - t.boolean "posted", :default => false, :null => false - t.integer "last_read_post_number" - t.integer "seen_post_count" - t.datetime "starred_at" - t.datetime "last_visited_at" - t.datetime "first_visited_at" - t.integer "notification_level", :default => 1, :null => false - t.datetime "notifications_changed_at" - t.integer "notifications_reason_id" - t.integer "total_msecs_viewed", :default => 0, :null => false - end - - add_index "topic_users", ["topic_id", "user_id"], :name => "index_forum_thread_users_on_forum_thread_id_and_user_id", :unique => true - -# Could not dump table "topics" because of following StandardError -# Unknown type 'hstore' for column 'meta_data' - - create_table "twitter_user_infos", :force => true do |t| - t.integer "user_id", :null => false - t.string "screen_name", :null => false - t.integer "twitter_user_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "twitter_user_infos", ["twitter_user_id"], :name => "index_twitter_user_infos_on_twitter_user_id", :unique => true - add_index "twitter_user_infos", ["user_id"], :name => "index_twitter_user_infos_on_user_id", :unique => true - - create_table "uploads", :force => true do |t| - t.integer "user_id", :null => false - t.integer "topic_id", :null => false - t.string "original_filename", :null => false - t.integer "filesize", :null => false - t.integer "width" - t.integer "height" - t.string "url", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "uploads", ["topic_id"], :name => "index_uploads_on_forum_thread_id" - add_index "uploads", ["user_id"], :name => "index_uploads_on_user_id" - - create_table "user_actions", :force => true do |t| - t.integer "action_type", :null => false - t.integer "user_id", :null => false - t.integer "target_topic_id" - t.integer "target_post_id" - t.integer "target_user_id" - t.integer "acting_user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "user_actions", ["acting_user_id"], :name => "index_actions_on_acting_user_id" - add_index "user_actions", ["action_type", "user_id", "target_topic_id", "target_post_id", "acting_user_id"], :name => "idx_unique_rows", :unique => true - add_index "user_actions", ["user_id", "action_type"], :name => "index_actions_on_user_id_and_action_type" - - create_table "user_open_ids", :force => true do |t| - t.integer "user_id", :null => false - t.string "email", :null => false - t.string "url", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "active", :null => false - end - - add_index "user_open_ids", ["url"], :name => "index_user_open_ids_on_url" - - create_table "user_visits", :force => true do |t| - t.integer "user_id", :null => false - t.date "visited_at", :null => false - end - - add_index "user_visits", ["user_id", "visited_at"], :name => "index_user_visits_on_user_id_and_visited_at", :unique => true - - create_table "users", :force => true do |t| - t.string "username", :limit => 20, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "name" - t.text "bio_raw" - t.integer "seen_notification_id", :default => 0, :null => false - t.datetime "last_posted_at" - t.string "email", :limit => 256, :null => false - t.string "password_hash", :limit => 64 - t.string "salt", :limit => 32 - t.boolean "active" - t.string "username_lower", :limit => 20, :null => false - t.string "auth_token", :limit => 32 - t.datetime "last_seen_at" - t.string "website" - t.boolean "admin", :default => false, :null => false - t.datetime "last_emailed_at" - t.boolean "email_digests", :default => true, :null => false - t.integer "trust_level", :null => false - t.text "bio_cooked" - t.boolean "email_private_messages", :default => true - t.boolean "email_direct", :default => true, :null => false - t.boolean "approved", :default => false, :null => false - t.integer "approved_by_id" - t.datetime "approved_at" - t.integer "topics_entered", :default => 0, :null => false - t.integer "posts_read_count", :default => 0, :null => false - t.integer "digest_after_days", :default => 7, :null => false - t.datetime "previous_visit_at" - t.datetime "banned_at" - t.datetime "banned_till" - t.date "date_of_birth" - t.integer "auto_track_topics_after_msecs" - t.integer "views", :default => 0, :null => false - t.integer "flag_level", :default => 0, :null => false - t.integer "time_read", :default => 0, :null => false - t.integer "days_visited", :default => 0, :null => false - t.string "ip_address", :limit => nil - end - - add_index "users", ["auth_token"], :name => "index_users_on_auth_token" - add_index "users", ["email"], :name => "index_users_on_email", :unique => true - add_index "users", ["last_posted_at"], :name => "index_users_on_last_posted_at" - add_index "users", ["username"], :name => "index_users_on_username", :unique => true - add_index "users", ["username_lower"], :name => "index_users_on_username_lower", :unique => true - - create_table "users_search", :id => false, :force => true do |t| - t.integer "id", :null => false - t.tsvector "search_data" - end - - add_index "users_search", ["search_data"], :name => "idx_search_user" - - create_table "versions", :force => true do |t| - t.integer "versioned_id" - t.string "versioned_type" - t.integer "user_id" - t.string "user_type" - t.string "user_name" - t.text "modifications" - t.integer "number" - t.integer "reverted_from" - t.string "tag" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "versions", ["created_at"], :name => "index_versions_on_created_at" - add_index "versions", ["number"], :name => "index_versions_on_number" - add_index "versions", ["tag"], :name => "index_versions_on_tag" - add_index "versions", ["user_id", "user_type"], :name => "index_versions_on_user_id_and_user_type" - add_index "versions", ["user_name"], :name => "index_versions_on_user_name" - add_index "versions", ["versioned_id", "versioned_type"], :name => "index_versions_on_versioned_id_and_versioned_type" - - create_table "views", :id => false, :force => true do |t| - t.integer "parent_id", :null => false - t.string "parent_type", :limit => 50, :null => false - t.integer "ip", :limit => 8, :null => false - t.date "viewed_at", :null => false - t.integer "user_id" - end - - add_index "views", ["parent_id", "parent_type"], :name => "index_views_on_parent_id_and_parent_type" - -end diff --git a/lib/discourse_plugin_registry.rb b/lib/discourse_plugin_registry.rb index a56862a67e9..8f7abca4c8d 100644 --- a/lib/discourse_plugin_registry.rb +++ b/lib/discourse_plugin_registry.rb @@ -9,10 +9,21 @@ class DiscoursePluginRegistry attr_accessor :stylesheets end - def register_js(filename, options={}) - self.class.javascripts ||= Set.new - self.class.server_side_javascripts ||= Set.new + # Default accessor values + # + def self.stylesheets + @stylesheets ||= Set.new + end + + def self.javascripts + @javascripts ||= Set.new + end + + def self.server_side_javascripts + @server_side_javascripts ||= Set.new + end + def register_js(filename, options={}) # If we have a server side option, add that too. self.class.server_side_javascripts << options[:server_side] if options[:server_side].present? @@ -20,12 +31,11 @@ class DiscoursePluginRegistry end def register_css(filename) - self.class.stylesheets ||= Set.new self.class.stylesheets << filename end def stylesheets - self.class.stylesheets || Set.new + self.class.stylesheets end def register_archetype(name, options={}) @@ -33,17 +43,17 @@ class DiscoursePluginRegistry end def server_side_javascripts - self.class.javascripts || Set.new + self.class.javascripts end def javascripts - self.class.javascripts || Set.new + self.class.javascripts end def self.clear - self.stylesheets = Set.new - self.server_side_javascripts = Set.new - self.javascripts = Set.new + self.stylesheets = nil + self.server_side_javascripts = nil + self.javascripts = nil end def self.setup(plugin_class) @@ -52,6 +62,4 @@ class DiscoursePluginRegistry plugin.setup end - - end diff --git a/lib/oneboxer/gist_onebox.rb b/lib/oneboxer/gist_onebox.rb index d64f05474ab..a3f63cb8638 100644 --- a/lib/oneboxer/gist_onebox.rb +++ b/lib/oneboxer/gist_onebox.rb @@ -7,22 +7,16 @@ module Oneboxer favicon 'github.png' def translate_url - m = @url.match(/gist\.github\.com\/(?[0-9a-f]+)/mi) + m = @url.match(/gist\.github\.com\/([^\/]+\/)?(?[0-9a-f]+)/mi) return "https://api.github.com/gists/#{m[:id]}" if m - @url end def parse(data) - parsed = JSON.parse(data) - result = {files: [], title: parsed['description']} - parsed['files'].each do |filename, attrs| result[:files] << {filename: filename}.merge!(attrs) end - - result end diff --git a/lib/search.rb b/lib/search.rb index e91486da791..b6ebf70de52 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -100,7 +100,7 @@ module Search db_result = [] [user_query_sql, category_query_sql, topic_query_sql].each do |sql| - sql << " limit " << Search.per_facet.to_s + sql << " LIMIT " << Search.per_facet.to_s db_result += ActiveRecord::Base.exec_sql(sql , query: terms.join(" & ")).to_a end end @@ -109,12 +109,14 @@ module Search expected_topics = 0 expected_topics = Search.facets.size unless type_filter.present? - expected_topics = Search.per_facet * Search.facets.size if type_filter == 'topic' + expected_topics = Search.per_facet * Search.facets.size if type_filter == 'topic' + if expected_topics > 0 db_result.each do |row| expected_topics -= 1 if row['type'] == 'topic' end end + if expected_topics > 0 tmp = ActiveRecord::Base.exec_sql "#{post_query_sql} limit :per_facet", query: terms.join(" & "), per_facet: expected_topics * 3 @@ -134,11 +136,9 @@ module Search db_result += tmp[0..expected_topics-1] end - # Group the results by type grouped = {} db_result.each do |row| - type = row.delete('type') # Add the slug for topics diff --git a/lib/slug.rb b/lib/slug.rb index c4fe8fdfb0f..86025079c5f 100644 --- a/lib/slug.rb +++ b/lib/slug.rb @@ -6,23 +6,24 @@ module Slug def self.for(string) + str = string.dup.strip.downcase + + # The characters we want to replace with a hyphen + str.tr!("·/_,:;.", "\-") - str = string.dup - str.gsub!(/^\s+|\s+$/, '') - str.downcase! - - from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;." - to = "aaaaeeeeiiiioooouuuunc-------" - - idx = 0 - from.each_char do |c| - str.gsub!(c, to[idx]) - idx += 1 - end - + # Convert to ASCII or remove if transliteration is unknown. + str = ActiveSupport::Inflector.transliterate(str, '') + + # Remove everything except alphanumberic, space, and hyphen characters. str.gsub!(/[^a-z0-9 -]/, '') + + # Replace multiple spaces with one hyphen. str.gsub!(/\s+/, '-') + + # Replace multiple hyphens with one hyphen. str.gsub!(/\-+/, '-') + + # Remove leading and trailing hyphens str.gsub!(/^-|-$/, '') str diff --git a/spec/components/discourse_plugin_registry_spec.rb b/spec/components/discourse_plugin_registry_spec.rb index fe064e6bced..ea2ad312ca5 100644 --- a/spec/components/discourse_plugin_registry_spec.rb +++ b/spec/components/discourse_plugin_registry_spec.rb @@ -4,6 +4,27 @@ require 'discourse_plugin_registry' describe DiscoursePluginRegistry do let(:registry) { DiscoursePluginRegistry.new } + + context '#stylesheets' do + it 'defaults to an empty Set' do + DiscoursePluginRegistry.stylesheets = nil + DiscoursePluginRegistry.stylesheets.should == Set.new + end + end + + context '#javascripts' do + it 'defaults to an empty Set' do + DiscoursePluginRegistry.javascripts = nil + DiscoursePluginRegistry.javascripts.should == Set.new + end + end + + context '#server_side_javascripts' do + it 'defaults to an empty Set' do + DiscoursePluginRegistry.server_side_javascripts = nil + DiscoursePluginRegistry.server_side_javascripts.should == Set.new + end + end context '.register_css' do before do diff --git a/spec/components/oneboxer/gist_onebox_spec.rb b/spec/components/oneboxer/gist_onebox_spec.rb new file mode 100644 index 00000000000..9a8bf5fd4a3 --- /dev/null +++ b/spec/components/oneboxer/gist_onebox_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' +require 'oneboxer' +require 'oneboxer/gist_onebox' + +describe Oneboxer::GistOnebox do + it "does not trip on user names" do + o = Oneboxer::GistOnebox.new('https://gist.github.com/aaa/4599619') + o.translate_url.should == 'https://api.github.com/gists/4599619' + end + + it "works for old school urls too" do + o = Oneboxer::GistOnebox.new('https://gist.github.com/4599619') + o.translate_url.should == 'https://api.github.com/gists/4599619' + end +end + diff --git a/spec/components/slug_spec.rb b/spec/components/slug_spec.rb index fde5ebd8e33..44bd1177e8c 100644 --- a/spec/components/slug_spec.rb +++ b/spec/components/slug_spec.rb @@ -1,12 +1,10 @@ # encoding: utf-8 require 'spec_helper' - require 'slug' describe Slug do - it 'replaces spaces with hyphens' do Slug.for("hello world").should == 'hello-world' end @@ -35,5 +33,11 @@ describe Slug do Slug.for("...hello").should == "hello" end + it 'handles our initial transliteration' do + from = "àáäâčďèéëěêìíïîľĺňòóöôŕřšťůùúüûýžñç" + to = "aaaacdeeeeeiiiillnoooorrstuuuuuyznc" + Slug.for(from).should == to + end + end diff --git a/spec/models/post_alert_observer_spec.rb b/spec/models/post_alert_observer_spec.rb index 7b6ad2cf35c..0daed2202c3 100644 --- a/spec/models/post_alert_observer_spec.rb +++ b/spec/models/post_alert_observer_spec.rb @@ -37,11 +37,6 @@ describe PostAlertObserver do context 'quotes' do - it 'notifies a user by display username' do - lambda { - Fabricate(:post, raw: '[quote="Evil Trout, post:1"]whatup[/quote]') - }.should change(evil_trout.notifications, :count).by(1) - end it 'notifies a user by username' do lambda { diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 88c943ec0ca..146a51599f8 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -86,7 +86,8 @@ describe Post do let(:post_no_images) { Fabricate.build(:post, post_args) } let(:post_one_image) { Fabricate.build(:post, post_args.merge(raw: "![sherlock](http://bbc.co.uk/sherlock.jpg)")) } let(:post_two_images) { Fabricate.build(:post, post_args.merge(raw: " ")) } - let(:post_with_emoticons) { Fabricate.build(:post, post_args.merge(raw: 'smiley wink')) } + let(:post_with_avatars) { Fabricate.build(:post, post_args.merge(raw: 'smiley wink')) } + let(:post_with_two_classy_images) { Fabricate.build(:post, post_args.merge(raw: " ")) } it "returns 0 images for an empty post" do Fabricate.build(:post).image_count.should == 0 @@ -100,10 +101,14 @@ describe Post do post_two_images.image_count.should == 2 end - it "doesn't count emoticons as images" do - post_with_emoticons.image_count.should == 0 + it "doesn't count avatars as images" do + post_with_avatars.image_count.should == 0 end + it "doesn't count whitelisted images" do + Post.stubs(:white_listed_image_classes).returns(["classy"]) + post_with_two_classy_images.image_count.should == 0 + end context "validation" do it "allows a new user to make a post with one image" do diff --git a/vendor/gems/discourse_emoji/lib/discourse_emoji/engine.rb b/vendor/gems/discourse_emoji/lib/discourse_emoji/engine.rb index 3944406a357..5caafd703d2 100644 --- a/vendor/gems/discourse_emoji/lib/discourse_emoji/engine.rb +++ b/vendor/gems/discourse_emoji/lib/discourse_emoji/engine.rb @@ -9,8 +9,9 @@ module DiscourseEmoji app.config.after_initialize do DiscoursePluginRegistry.setup(DiscourseEmoji::Plugin) + Post.white_listed_image_classes << "emoji" end end end -end \ No newline at end of file +end diff --git a/vendor/gems/message_bus/lib/message_bus.rb b/vendor/gems/message_bus/lib/message_bus.rb index 7b3fefc09df..514e6f2001b 100644 --- a/vendor/gems/message_bus/lib/message_bus.rb +++ b/vendor/gems/message_bus/lib/message_bus.rb @@ -10,6 +10,7 @@ require "message_bus/client" require "message_bus/connection_manager" require "message_bus/message_handler" require "message_bus/rack/middleware" +require "message_bus/rack/diagnostics" # we still need to take care of the logger if defined?(::Rails) @@ -71,19 +72,28 @@ module MessageBus::Implementation end def site_id_lookup(&blk) - @site_id_lookup ||= blk + @site_id_lookup = blk if blk + @site_id_lookup end def user_id_lookup(&blk) - @user_id_lookup ||= blk + @user_id_lookup = blk if blk + @user_id_lookup + end + + def is_admin_lookup(&blk) + @is_admin_lookup = blk if blk + @is_admin_lookup end def on_connect(&blk) - @on_connect ||= blk + @on_connect = blk if blk + @on_connect end def on_disconnect(&blk) - @on_disconnect ||= blk + @on_disconnect = blk if blk + @on_disconnect end def allow_broadcast=(val) diff --git a/vendor/gems/message_bus/lib/message_bus/rack/diagnostics.rb b/vendor/gems/message_bus/lib/message_bus/rack/diagnostics.rb new file mode 100644 index 00000000000..09426227884 --- /dev/null +++ b/vendor/gems/message_bus/lib/message_bus/rack/diagnostics.rb @@ -0,0 +1,35 @@ +module MessageBus::Rack; end + +class MessageBus::Rack::Diagnostics + def initialize(app, config = {}) + @app = app + end + + def index + html = < + + + +

Message Bus Diags

+ + +HTML + return [200, {"content-type" => "text/html;"}, html] + end + + def call(env) + + return @app.call(env) unless env['PATH_INFO'].start_with? '/message-bus/_diagnostics' + + route = env['PATH_INFO'].split('/message_bus/_diagnostics')[1] + + if MessageBus.is_admin_lookup.nil? || !MessageBus.is_admin_lookup.call + return [403, {}, ["not allowed"]] + end + + return index unless route + + return [404, {}, ["not found"]] + end +end diff --git a/vendor/gems/message_bus/lib/message_bus/rack/middleware.rb b/vendor/gems/message_bus/lib/message_bus/rack/middleware.rb index 7f9e0ec402f..f240266a4f0 100644 --- a/vendor/gems/message_bus/lib/message_bus/rack/middleware.rb +++ b/vendor/gems/message_bus/lib/message_bus/rack/middleware.rb @@ -46,6 +46,11 @@ class MessageBus::Rack::Middleware return [200,{"Content-Type" => "text/html"},["sent"]] end + if env['PATH_INFO'].start_with? '/message-bus/_diagnostics' + diags = MessageBus::Rack::Diagnostics.new(@app) + return diags.call(env) + end + client_id = env['PATH_INFO'].split("/")[2] return [404, {}, ["not found"]] unless client_id diff --git a/vendor/gems/message_bus/spec/lib/middleware_spec.rb b/vendor/gems/message_bus/spec/lib/middleware_spec.rb index 1d7bd279797..65306cf5c65 100644 --- a/vendor/gems/message_bus/spec/lib/middleware_spec.rb +++ b/vendor/gems/message_bus/spec/lib/middleware_spec.rb @@ -107,11 +107,22 @@ describe MessageBus::Rack::Middleware do ensure MessageBus.long_polling_interval = 5000 end - - end end + describe "diagnostics" do + + it "should return a 403 if a user attempts to get at the _diagnostics path" do + get "/message-bus/_diagnostics" + last_response.status.should == 403 + end + + it "should get a 200 with html for an authorized user" do + MessageBus.stub(:is_admin_lookup).and_return(lambda{ true }) + get "/message-bus/_diagnostics" + last_response.status.should == 200 + end + end describe "polling" do before do