From adb570fe538038d7631c55a868cbf250abe27b2d Mon Sep 17 00:00:00 2001 From: "Jason W. May" Date: Mon, 24 Nov 2014 12:12:48 -0800 Subject: [PATCH 001/144] use limit & offset for pagination of group members --- app/controllers/groups_controller.rb | 7 +++++-- spec/controllers/groups_controller_spec.rb | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index dd1feec96b..a687cded1f 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -18,8 +18,11 @@ class GroupsController < ApplicationController def members group = find_group(:group_id) - members = group.users.order('username_lower asc') - members = members.limit(200) if group.automatic + + limit = (params[:limit] || 200).to_i + offset = (params[:offset] || 0).to_i + members = group.users.order('username_lower asc').limit(limit).offset(offset) + render_serialized(members.to_a, GroupUserSerializer) end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index bbaa136d20..04881cbc86 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -67,5 +67,19 @@ describe GroupsController do xhr :get, :posts, group_id: group.name response.should be_success end + + it "ensures that membership can be paginated" do + 5.times { group.add(Fabricate(:user)) } + xhr :get, :members, group_id: group.name, limit: 3 + response.should be_success + members = JSON.parse(response.body) + members.count.should eq(3) + + xhr :get, :members, group_id: group.name, limit: 250, offset: 250 + xhr :get, :members, group_id: group.name, limit: 3, offset: 3 + response.should be_success + members = JSON.parse(response.body) + members.count.should eq(2) + end end end From 610c2a4d652ef61b6a405089ee6395b02ba45f0f Mon Sep 17 00:00:00 2001 From: "Jason W. May" Date: Tue, 25 Nov 2014 09:12:24 -0800 Subject: [PATCH 002/144] checking actual values in the spec, not just counts --- spec/controllers/groups_controller_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 04881cbc86..63ac27d4b3 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -70,16 +70,17 @@ describe GroupsController do it "ensures that membership can be paginated" do 5.times { group.add(Fabricate(:user)) } + usernames = group.users.map{ |m| m['username'] }.sort + xhr :get, :members, group_id: group.name, limit: 3 response.should be_success members = JSON.parse(response.body) - members.count.should eq(3) + members.map{ |m| m['username'] }.should eq(usernames[0..2]) - xhr :get, :members, group_id: group.name, limit: 250, offset: 250 xhr :get, :members, group_id: group.name, limit: 3, offset: 3 response.should be_success members = JSON.parse(response.body) - members.count.should eq(2) + members.map{ |m| m['username'] }.should eq(usernames[3..4]) end end end From a85a3da1674a41306b6425373d918305c2e7f1bb Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Fri, 28 Nov 2014 00:38:08 -0800 Subject: [PATCH 003/144] move digest email featured post category underneath --- app/views/user_notifications/digest.html.erb | 1 + lib/email/styles.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/user_notifications/digest.html.erb b/app/views/user_notifications/digest.html.erb index 4367821cb0..84db1389c3 100644 --- a/app/views/user_notifications/digest.html.erb +++ b/app/views/user_notifications/digest.html.erb @@ -21,6 +21,7 @@ <%- @featured_topics.each_with_index do |t, i| %> diff --git a/lib/email/styles.rb b/lib/email/styles.rb index b3cbeac05a..c031a6caaf 100644 --- a/lib/email/styles.rb +++ b/lib/email/styles.rb @@ -136,7 +136,7 @@ module Email style('pre', 'word-wrap: break-word; max-width: 694px;') style('code', 'background-color: #f1f1ff; padding: 2px 5px;') style('pre code', 'display: block; background-color: #f1f1ff; padding: 5px;') - style('.featured-topic a', 'text-decoration: none; font-weight: bold; color: #006699; margin-right: 5px') + style('.featured-topic a', 'text-decoration: none; font-weight: bold; color: #006699; line-height:2em;') onebox_styles plugin_styles From 37a3e956b64b7a1f1c729178917a27081e8bb8ef Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 28 Nov 2014 13:44:40 -0500 Subject: [PATCH 004/144] UX: Link categories in digest emails --- app/helpers/user_notifications_helper.rb | 10 ++++++---- app/views/user_notifications/digest.html.erb | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb index 1b3dccf049..da0baf4e9f 100644 --- a/app/helpers/user_notifications_helper.rb +++ b/app/helpers/user_notifications_helper.rb @@ -69,14 +69,16 @@ module UserNotificationsHelper result = "" + category_url = "#{Discourse.base_url}#{category.url}" + if opts[:only_stripe] - result << " " - result << "#{category.name}" + result << " " + result << "#{category.name}" else if category.parent_category.present? - result << " " + result << " " end - result << "#{category.name}" + result << "#{category.name}" end result.html_safe diff --git a/app/views/user_notifications/digest.html.erb b/app/views/user_notifications/digest.html.erb index 84db1389c3..d9c6c16816 100644 --- a/app/views/user_notifications/digest.html.erb +++ b/app/views/user_notifications/digest.html.erb @@ -58,7 +58,7 @@
<%- @new_by_category.each do |c| %> - <%= c[0].name %> <%= c[1] %> + <%= c[0].name %> <%= c[1] %> <%- end %>
From cb0e7a5724834ff13f523b5cb47d984d5e5238f9 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 28 Nov 2014 14:20:43 -0500 Subject: [PATCH 005/144] For performance reasons, use `delete_all` when removing a user's email logs --- app/models/user.rb | 2 +- spec/services/user_destroyer_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 56cad0d705..8a846ee2d9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,7 +25,7 @@ class User < ActiveRecord::Base has_many :post_actions, dependent: :destroy has_many :user_badges, -> {where('user_badges.badge_id IN (SELECT id FROM badges where enabled)')}, dependent: :destroy has_many :badges, through: :user_badges - has_many :email_logs, dependent: :destroy + has_many :email_logs, dependent: :delete_all has_many :post_timings has_many :topic_allowed_users, dependent: :destroy has_many :topics_allowed, through: :topic_allowed_users, source: :topic diff --git a/spec/services/user_destroyer_spec.rb b/spec/services/user_destroyer_spec.rb index efb50f0bd2..b7b685a558 100644 --- a/spec/services/user_destroyer_spec.rb +++ b/spec/services/user_destroyer_spec.rb @@ -283,6 +283,17 @@ describe UserDestroyer do end end + context 'user got an email' do + let(:user) { Fabricate(:user) } + let!(:email_log) { Fabricate(:email_log, user: user) } + + it "deletes the email log" do + expect { + UserDestroyer.new(@admin).destroy(user, {delete_posts: true}) + }.to change { EmailLog.count }.by(-1) + end + end + context 'user liked things' do before do @topic = Fabricate(:topic, user: Fabricate(:user)) From cb9507d292b87648a8137b6a76fc44e713c59644 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Fri, 28 Nov 2014 11:44:59 -0800 Subject: [PATCH 006/144] tighten up title line height in digest email --- lib/email/styles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/email/styles.rb b/lib/email/styles.rb index c031a6caaf..1d421dd529 100644 --- a/lib/email/styles.rb +++ b/lib/email/styles.rb @@ -136,7 +136,7 @@ module Email style('pre', 'word-wrap: break-word; max-width: 694px;') style('code', 'background-color: #f1f1ff; padding: 2px 5px;') style('pre code', 'display: block; background-color: #f1f1ff; padding: 5px;') - style('.featured-topic a', 'text-decoration: none; font-weight: bold; color: #006699; line-height:2em;') + style('.featured-topic a', 'text-decoration: none; font-weight: bold; color: #006699; line-height:1.5em;') onebox_styles plugin_styles From 003d32babeec033200429dcef5c8720852e6fddd Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Sat, 29 Nov 2014 03:58:44 -0800 Subject: [PATCH 007/144] decrease size of cat color stripe in digests a bit --- app/helpers/user_notifications_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb index da0baf4e9f..dbbe353f7c 100644 --- a/app/helpers/user_notifications_helper.rb +++ b/app/helpers/user_notifications_helper.rb @@ -72,7 +72,7 @@ module UserNotificationsHelper category_url = "#{Discourse.base_url}#{category.url}" if opts[:only_stripe] - result << " " + result << " " result << "#{category.name}" else if category.parent_category.present? From 529014d56ea5085a9f64621401f5f8b63c14001e Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Tue, 25 Nov 2014 22:14:59 +0530 Subject: [PATCH 008/144] FEATURE: switch to GitHub email_reply_parser library and parse plain text email content --- Gemfile | 6 +- Gemfile.lock | 4 +- lib/email/receiver.rb | 6 +- spec/components/email/receiver_spec.rb | 79 ++++++++++ spec/fixtures/emails/android_gmail.eml | 177 +++++++++++++++++++++ spec/fixtures/emails/gmail_web.eml | 181 ++++++++++++++++++++++ spec/fixtures/emails/ios_default.eml | 136 ++++++++++++++++ spec/fixtures/emails/iphone_signature.eml | 29 ++++ spec/fixtures/emails/newlines.eml | 84 ++++++++++ spec/fixtures/emails/previous_replies.eml | 180 +++++++++++++++++++++ spec/fixtures/emails/windows_8_metro.eml | 173 +++++++++++++++++++++ 11 files changed, 1045 insertions(+), 10 deletions(-) create mode 100644 spec/fixtures/emails/android_gmail.eml create mode 100644 spec/fixtures/emails/gmail_web.eml create mode 100644 spec/fixtures/emails/ios_default.eml create mode 100644 spec/fixtures/emails/iphone_signature.eml create mode 100644 spec/fixtures/emails/newlines.eml create mode 100644 spec/fixtures/emails/previous_replies.eml create mode 100644 spec/fixtures/emails/windows_8_metro.eml diff --git a/Gemfile b/Gemfile index cf663f22a9..362809608b 100644 --- a/Gemfile +++ b/Gemfile @@ -118,11 +118,7 @@ gem 'fastimage' gem 'fog', '1.22.1', require: false gem 'unf', require: false -# see: https://twitter.com/samsaffron/status/412360162297393152 -# Massive amount of changes made in branch we use, no PR upstreamed -# We need to get this sorted -# https://github.com/samsaffron/email_reply_parser -gem 'email_reply_parser-discourse', require: 'email_reply_parser' +gem 'email_reply_parser' # note: for image_optim to correctly work you need # sudo apt-get install -y advancecomp gifsicle jpegoptim libjpeg-progs optipng pngcrush diff --git a/Gemfile.lock b/Gemfile.lock index 0f56e0cbc1..bc96345db3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -65,7 +65,7 @@ GEM dotenv (0.11.1) dotenv-deployment (~> 0.0.2) dotenv-deployment (0.0.2) - email_reply_parser-discourse (0.6) + email_reply_parser (0.5.8) ember-data-source (0.14) ember-source ember-rails (0.14.1) @@ -412,7 +412,7 @@ DEPENDENCIES better_errors binding_of_caller certified - email_reply_parser-discourse + email_reply_parser ember-rails ember-source (= 1.6.0.beta.2) eventmachine diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index 5d2dfcfa11..1a7a1ee199 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -117,9 +117,9 @@ module Email if message.multipart? html = fix_charset message.html_part text = fix_charset message.text_part - # TODO picking text if available may be better - # in case of email reply from MS Outlook client, prefer text - if (text && !html) || (text && (message.header.to_s =~ /X-MS-Has-Attach/ || message.header.to_s =~ /Microsoft Outlook/)) + + # prefer plain text + if text return text end elsif message.content_type =~ /text\/html/ diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index 55a7df2027..a7e93873f2 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -93,6 +93,85 @@ Pleasure to have you here! ) end + it "handles newlines" do + test_parse_body(fixture_file("emails/newlines.eml")). + should == ( +"This is my reply. +It is my best reply. +It will also be my *only* reply." + ) + end + + it "should not include previous replies" do + test_parse_body(fixture_file("emails/previous_replies.eml")).should_not match /Previous Replies/ + end + + it "strips iPhone signature" do + test_parse_body(fixture_file("emails/iphone_signature.eml")).should_not match /Sent from my iPhone/ + end + + it "properly renders email reply from gmail web client" do + test_parse_body(fixture_file("emails/gmail_web.eml")). + should == ( +"### This is a reply from standard GMail in Google Chrome. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. + +Here's some **bold** text in Markdown. + +Here's a link http://example.com" + ) + end + + it "properly renders email reply from iOS default mail client" do + test_parse_body(fixture_file("emails/ios_default.eml")). + should == ( +"### this is a reply from iOS default mail + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + +Here's some **bold** markdown text. + +Here's a link http://example.com" + ) + end + + it "properly renders email reply from Android 5 gmail client" do + test_parse_body(fixture_file("emails/android_gmail.eml")). + should == ( +"### this is a reply from Android 5 gmail + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. + +This is **bold** in Markdown. + +This is a link to http://example.com" + ) + end + + it "properly renders email reply from Windows 8.1 Metro default mail client" do + test_parse_body(fixture_file("emails/windows_8_metro.eml")). + should == ( +"### reply from default mail client in Windows 8.1 Metro + + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + + +This is a **bold** word in Markdown + + +This is a link http://example.com" + ) + end + it "properly renders email reply from MS Outlook client" do test_parse_body(fixture_file("emails/outlook.eml")).should == "Microsoft Outlook 2010" end diff --git a/spec/fixtures/emails/android_gmail.eml b/spec/fixtures/emails/android_gmail.eml new file mode 100644 index 0000000000..21c5dde234 --- /dev/null +++ b/spec/fixtures/emails/android_gmail.eml @@ -0,0 +1,177 @@ +Delivered-To: reply@discourse.org +Return-Path: +MIME-Version: 1.0 +In-Reply-To: +References: + +Date: Fri, 28 Nov 2014 12:53:21 -0800 +Subject: Re: [Discourse Meta] [Lounge] Testing default email replies +From: Walter White +To: Discourse Meta +Content-Type: multipart/alternative; boundary=089e0149cfa485c6630508f173df + +--089e0149cfa485c6630508f173df +Content-Type: text/plain; charset=UTF-8 + +### this is a reply from Android 5 gmail + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. + +This is **bold** in Markdown. + +This is a link to http://example.com +On Nov 28, 2014 12:36 PM, "Arpit Jalan" wrote: + +> techAPJ +> November 28 +> +> Test reply. +> +> First paragraph. +> +> Second paragraph. +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> ------------------------------ +> Previous Replies codinghorror +> +> November 28 +> +> We're testing the latest GitHub email processing library which we are +> integrating now. +> +> https://github.com/github/email_reply_parser +> +> Go ahead and reply to this topic and I'll reply from various email clients +> for testing. +> ------------------------------ +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> +> To unsubscribe from these emails, visit your user preferences +> . +> + +--089e0149cfa485c6630508f173df +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +

### this is a reply from Android 5 gmail

+

The quick brown fox jumps over the lazy dog. The quick brown= + fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. = +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over= + the lazy dog. The quick brown fox jumps over the lazy dog.

+

This is **bold** in Markdown.

+

This is a link to http://exam= +ple.com

+
On Nov 28, 2014 12:36 PM, "Arpit Jalan"= +; <info@discourse.org> wrot= +e:
+ + + + + + + + + + + +
+ + + techAPJ
+ November 28 +
+

Test reply.

+ +

First paragraph.

+ +

Second paragraph.

+
+ + +
+

To respond, reply to this email or visit https:/= +/meta.discourse.org/t/testing-default-email-replies/22638/3 in your bro= +wser.

+
+
+

Previous Replies

+ + + + + + + + + + + +
+ + + codinghorror + November 28 +
+

We're testing the latest GitHub emai= +l processing library which we are integrating now.

+ +

https://github.com/github/email_reply_parser

+ +

Go ahead and reply to this topic and I&#= +39;ll reply from various email clients for testing.

+
+ + +
+ +
+

To respond, reply to this email or visit https://met= +a.discourse.org/t/testing-default-email-replies/22638/3 in your browser= +.

+
+
+

To unsubscribe from these emails, visit your user preferences.

+
+
+
+ +--089e0149cfa485c6630508f173df-- diff --git a/spec/fixtures/emails/gmail_web.eml b/spec/fixtures/emails/gmail_web.eml new file mode 100644 index 0000000000..8bb8383571 --- /dev/null +++ b/spec/fixtures/emails/gmail_web.eml @@ -0,0 +1,181 @@ +Delivered-To: reply@discourse.org +Return-Path: +MIME-Version: 1.0 +In-Reply-To: +References: + +Date: Fri, 28 Nov 2014 12:36:49 -0800 +Subject: Re: [Discourse Meta] [Lounge] Testing default email replies +From: Walter White +To: Discourse Meta +Content-Type: multipart/alternative; boundary=001a11c2e04e6544f30508f138ba + +--001a11c2e04e6544f30508f138ba +Content-Type: text/plain; charset=UTF-8 + +### This is a reply from standard GMail in Google Chrome. + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. + +Here's some **bold** text in Markdown. + +Here's a link http://example.com + +On Fri, Nov 28, 2014 at 12:35 PM, Arpit Jalan wrote: + +> techAPJ +> November 28 +> +> Test reply. +> +> First paragraph. +> +> Second paragraph. +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> ------------------------------ +> Previous Replies codinghorror +> +> November 28 +> +> We're testing the latest GitHub email processing library which we are +> integrating now. +> +> https://github.com/github/email_reply_parser +> +> Go ahead and reply to this topic and I'll reply from various email clients +> for testing. +> ------------------------------ +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> +> To unsubscribe from these emails, visit your user preferences +> . +> + +--001a11c2e04e6544f30508f138ba +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
### This is a reply from standard GMail in Google Chr= +ome.

The quick brown fox jumps over the lazy dog. = +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over= + the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown= + fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. = +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over= + the lazy dog.=C2=A0

Here's some **bold** text= + in Markdown.

Here's a link http://example.com
<= +br>
On Fri, Nov 28, 2014 at 12:35 PM, Arpit Jalan= + <info@discourse.org> wrote:
+ + + + + + + + + + + +
+ + + techAPJ
+ November 28 +
+

Test reply.

+ +

First paragraph.

+ +

Second paragraph.

+
+ + +
+

To respond, reply to this email or visit https:/= +/meta.discourse.org/t/testing-default-email-replies/22638/3 in your bro= +wser.

+
+
+

Previous Replies

+ + + + + + + + + + + +
+ + + codinghorror + November 28 +
+

We're testing the latest GitHub emai= +l processing library which we are integrating now.

+ +

https://github.com/github/email_reply_parser

+ +

Go ahead and reply to this topic and I&#= +39;ll reply from various email clients for testing.

+
+ + +
+ +
+

To respond, reply to this email or visit https://met= +a.discourse.org/t/testing-default-email-replies/22638/3 in your browser= +.

+
+
+

To unsubscribe from these emails, visit your user preferences.

+
+
+

+ +--001a11c2e04e6544f30508f138ba-- diff --git a/spec/fixtures/emails/ios_default.eml b/spec/fixtures/emails/ios_default.eml new file mode 100644 index 0000000000..8d4d58feb1 --- /dev/null +++ b/spec/fixtures/emails/ios_default.eml @@ -0,0 +1,136 @@ +Delivered-To: reply@discourse.org +Return-Path: +From: Walter White +Content-Type: multipart/alternative; + boundary=Apple-Mail-B41C7F8E-3639-49B0-A5D5-440E125A7105 +Content-Transfer-Encoding: 7bit +Mime-Version: 1.0 (1.0) +Subject: Re: [Discourse Meta] [Lounge] Testing default email replies +Date: Fri, 28 Nov 2014 12:41:41 -0800 +References: +In-Reply-To: +To: Discourse Meta +X-Mailer: iPhone Mail (12B436) + + +--Apple-Mail-B41C7F8E-3639-49B0-A5D5-440E125A7105 +Content-Type: text/plain; + charset=us-ascii +Content-Transfer-Encoding: quoted-printable + +### this is a reply from iOS default mail + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over t= +he lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fo= +x jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The q= +uick brown fox jumps over the lazy dog. The quick brown fox jumps over the l= +azy dog.=20 + +Here's some **bold** markdown text. + +Here's a link http://example.com + + +> On Nov 28, 2014, at 12:35 PM, Arpit Jalan wrote: +>=20 +>=20 +> techAPJ +> November 28 +> Test reply. +>=20 +> First paragraph. +>=20 +> Second paragraph. +>=20 +> To respond, reply to this email or visit https://meta.discourse.org/t/test= +ing-default-email-replies/22638/3 in your browser. +>=20 +> Previous Replies +>=20 +> codinghorror +> November 28 +> We're testing the latest GitHub email processing library which we are inte= +grating now. +>=20 +> https://github.com/github/email_reply_parser +>=20 +> Go ahead and reply to this topic and I'll reply from various email clients= + for testing. +>=20 +> To respond, reply to this email or visit https://meta.discourse.org/t/test= +ing-default-email-replies/22638/3 in your browser. +>=20 +> To unsubscribe from these emails, visit your user preferences. + +--Apple-Mail-B41C7F8E-3639-49B0-A5D5-440E125A7105 +Content-Type: text/html; + charset=utf-8 +Content-Transfer-Encoding: 7bit + +
### this is a reply from iOS default mail

The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 

Here's some **bold** markdown text.

Here's a link http://example.com


On Nov 28, 2014, at 12:35 PM, Arpit Jalan <info@discourse.org> wrote:

+ + + + + + + + + + + +
+ + + techAPJ
+ November 28 +
+

Test reply.

+ +

First paragraph.

+ +

Second paragraph.

+
+ + +
+

To respond, reply to this email or visit https://meta.discourse.org/t/testing-default-email-replies/22638/3 in your browser.

+
+
+

Previous Replies

+ + + + + + + + + + + +
+ + + codinghorror
+ November 28 +
+

We're testing the latest GitHub email processing library which we are integrating now.

+ +

https://github.com/github/email_reply_parser

+ +

Go ahead and reply to this topic and I'll reply from various email clients for testing.

+
+ + +
+ +
+

To respond, reply to this email or visit https://meta.discourse.org/t/testing-default-email-replies/22638/3 in your browser.

+
+
+

To unsubscribe from these emails, visit your user preferences.

+
+
+
+--Apple-Mail-B41C7F8E-3639-49B0-A5D5-440E125A7105-- diff --git a/spec/fixtures/emails/iphone_signature.eml b/spec/fixtures/emails/iphone_signature.eml new file mode 100644 index 0000000000..d314ad1f1e --- /dev/null +++ b/spec/fixtures/emails/iphone_signature.eml @@ -0,0 +1,29 @@ +Delivered-To: test@mail.com +Return-Path: +From: Walter White +Content-Type: multipart/alternative; + boundary=Apple-Mail-8E182EEF-9DBC-41DE-A593-DF2E5EBD3975 +Content-Transfer-Encoding: 7bit +Mime-Version: 1.0 (1.0) +Subject: Re: Signature in email replies! +Date: Thu, 23 Oct 2014 14:43:49 +0530 +References: <1234@mail.gmail.com> +In-Reply-To: <1234@mail.gmail.com> +To: Arpit Jalan +X-Mailer: iPhone Mail (12A405) + + +--Apple-Mail-8E182EEF-9DBC-41DE-A593-DF2E5EBD3975 +Content-Type: text/plain; + charset=us-ascii +Content-Transfer-Encoding: 7bit + +This post should not include signature. + +Sent from my iPhone + +> On 23-Oct-2014, at 9:45 am, Arpit Jalan wrote: +> +> Signature in email replies! + +--Apple-Mail-8E182EEF-9DBC-41DE-A593-DF2E5EBD3975 diff --git a/spec/fixtures/emails/newlines.eml b/spec/fixtures/emails/newlines.eml new file mode 100644 index 0000000000..cf03b9d18b --- /dev/null +++ b/spec/fixtures/emails/newlines.eml @@ -0,0 +1,84 @@ +In-Reply-To: +Date: Wed, 8 Oct 2014 10:36:19 +0530 +Delivered-To: walter.white@googlemail.com +Subject: Re: [Discourse] Welcome to Discourse +From: Walter White +To: Discourse +Content-Type: multipart/alternative; boundary=bcaec554078cc3d0c10504e24661 + +--bcaec554078cc3d0c10504e24661 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +This is my reply. +It is my best reply. +It will also be my *only* reply. + +On Wed, Oct 8, 2014 at 10:33 AM, ajalan +wrote: + +> ajalan +> +> October 8 +> +> Awesome! Thank You! [image: +1] +> +> To respond, reply to this email or visit +> http://discourse.techapj.com/t/welcome-to-discourse/8/2 +> +> in your browser. +> ------------------------------ +> Previous Replies system +> +> October 8 +> +> The first paragraph of this pinned topic will be visible as a welcome +> message to all new visitors on your homepage. It's important! +> +> *Edit this* into a brief description of your community: +> +> - Who is it for? +> - What can they find here? +> - Why should they come here? +> - Where can they read more (links, resources, etc)? +> +> You may want to close this topic via the wrench icon at the upper right, +> so that replies don't pile up on an announcement. +> ------------------------------ +> +> To respond, reply to this email or visit +> http://discourse.techapj.com/t/welcome-to-discourse/8/2 +> +> in your browser. +> +> To unsubscribe from these emails, visit your user preferences +> +> . +> + +--bcaec554078cc3d0c10504e24661 diff --git a/spec/fixtures/emails/previous_replies.eml b/spec/fixtures/emails/previous_replies.eml new file mode 100644 index 0000000000..3fd74482c0 --- /dev/null +++ b/spec/fixtures/emails/previous_replies.eml @@ -0,0 +1,180 @@ +Delivered-To: reply@discourse.org +MIME-Version: 1.0 +In-Reply-To: +References: + +Date: Fri, 28 Nov 2014 12:55:32 -0800 +Subject: Re: [Discourse Meta] [Lounge] Testing default email replies +From: Walter White +To: Discourse Meta +Content-Type: multipart/alternative; boundary=001a1137c9285318bb0508f17bc5 + +--001a1137c9285318bb0508f17bc5 +Content-Type: text/plain; charset=UTF-8 + +### this is a reply from iOS Gmail app + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy +dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps +over the lazy dog. + +This is **bold** text in Markdown. + +This is a link to http://example.com + +On Friday, November 28, 2014, Arpit Jalan wrote: + +> techAPJ +> November 28 +> +> Test reply. +> +> First paragraph. +> +> Second paragraph. +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> ------------------------------ +> Previous Replies codinghorror +> +> November 28 +> +> We're testing the latest GitHub email processing library which we are +> integrating now. +> +> https://github.com/github/email_reply_parser +> +> Go ahead and reply to this topic and I'll reply from various email clients +> for testing. +> ------------------------------ +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> +> To unsubscribe from these emails, visit your user preferences +> . +> + +--001a1137c9285318bb0508f17bc5 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +### this is a reply from iOS Gmail app

The quick brown f= +ox jumps over the lazy dog.=C2=A0The quick brown fox jumps over the lazy dog.=C2=A0The quic= +k brown fox jumps over the lazy dog.=C2=A0The quick brown fox jumps over th= +e lazy dog.=C2=A0The quick brown fox jumps over the lazy dog.=C2=A0The quic= +k brown fox jumps over the lazy dog.=C2=A0The quick brown fox jumps over th= +e lazy dog.=C2=A0

This is **bold** text in Markdown.

This is a link to http://example.com

On Friday, November 28, 2014, Arpit Jalan <
info@discourse.org> wrote:
+ + + + + + + + + + + +
+ + + techAPJ
+ November 28 +
+

Test reply.

+ +

First paragraph.

+ +

Second paragraph.

+
+ + +
+

To respond, reply to this email or visit https:/= +/meta.discourse.org/t/testing-default-email-replies/22638/3 in your bro= +wser.

+
+
+

Previous Replies

+ + + + + + + + + + + +
+ + + codinghorror + November 28 +
+

We're testing the latest GitHub emai= +l processing library which we are integrating now.

+ +

https://github.com/github/email_reply_parser

+ +

Go ahead and reply to this topic and I&#= +39;ll reply from various email clients for testing.

+
+ + +
+ +
+

To respond, reply to this email or visit https://met= +a.discourse.org/t/testing-default-email-replies/22638/3 in your browser= +.

+
+
+

To unsubscribe from these emails, visit your user preferences.

+
+
+
+ +--001a1137c9285318bb0508f17bc5-- diff --git a/spec/fixtures/emails/windows_8_metro.eml b/spec/fixtures/emails/windows_8_metro.eml new file mode 100644 index 0000000000..67d204af56 --- /dev/null +++ b/spec/fixtures/emails/windows_8_metro.eml @@ -0,0 +1,173 @@ +Delivered-To: reply@discourse.org +Return-Path: +MIME-Version: 1.0 +From: +To: + =?utf-8?Q?Discourse_Meta?= + +Subject: + =?utf-8?Q?Re:_[Discourse_Meta]_[Lounge]_Testing_default_email_replies?= +Importance: Normal +Date: Fri, 28 Nov 2014 21:29:10 +0000 +In-Reply-To: +References: + , +Content-Type: multipart/alternative; + boundary="_866E2678-BB4F-4DD8-BE18-81B04AD8D1BC_" + +--_866E2678-BB4F-4DD8-BE18-81B04AD8D1BC_ +Content-Transfer-Encoding: base64 +Content-Type: text/plain; charset="utf-8" + +IyMjIHJlcGx5IGZyb20gZGVmYXVsdCBtYWlsIGNsaWVudCBpbiBXaW5kb3dzIDguMSBNZXRybw0K +DQoNClRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWlj +ayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gg +anVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0 +aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cu +IFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBi +cm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVt +cHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUg +bGF6eSBkb2cuDQoNCg0KVGhpcyBpcyBhICoqYm9sZCoqIHdvcmQgaW4gTWFya2Rvd24NCg0KDQpU +aGlzIGlzIGEgbGluayBodHRwOi8vZXhhbXBsZS5jb20NCiANCg0KDQoNCg0KDQpGcm9tOiBBcnBp +dCBKYWxhbg0KU2VudDog4oCORnJpZGF54oCOLCDigI5Ob3ZlbWJlcuKAjiDigI4yOOKAjiwg4oCO +MjAxNCDigI4xMuKAjjrigI4zNeKAjiDigI5QTQ0KVG86IGplZmYgYXR3b29kDQoNCg0KDQoNCg0K +DQogdGVjaEFQSg0KTm92ZW1iZXIgMjggDQoNClRlc3QgcmVwbHkuDQoNCkZpcnN0IHBhcmFncmFw +aC4NCg0KU2Vjb25kIHBhcmFncmFwaC4NCg0KDQoNClRvIHJlc3BvbmQsIHJlcGx5IHRvIHRoaXMg +ZW1haWwgb3IgdmlzaXQgaHR0cHM6Ly9tZXRhLmRpc2NvdXJzZS5vcmcvdC90ZXN0aW5nLWRlZmF1 +bHQtZW1haWwtcmVwbGllcy8yMjYzOC8zIGluIHlvdXIgYnJvd3Nlci4NCg0KDQoNClByZXZpb3Vz +IFJlcGxpZXMNCg0KIGNvZGluZ2hvcnJvcg0KTm92ZW1iZXIgMjggDQoNCldlJ3JlIHRlc3Rpbmcg +dGhlIGxhdGVzdCBHaXRIdWIgZW1haWwgcHJvY2Vzc2luZyBsaWJyYXJ5IHdoaWNoIHdlIGFyZSBp +bnRlZ3JhdGluZyBub3cuDQoNCmh0dHBzOi8vZ2l0aHViLmNvbS9naXRodWIvZW1haWxfcmVwbHlf +cGFyc2VyDQoNCkdvIGFoZWFkIGFuZCByZXBseSB0byB0aGlzIHRvcGljIGFuZCBJJ2xsIHJlcGx5 +IGZyb20gdmFyaW91cyBlbWFpbCBjbGllbnRzIGZvciB0ZXN0aW5nLg0KDQoNCg0KDQoNClRvIHJl +c3BvbmQsIHJlcGx5IHRvIHRoaXMgZW1haWwgb3IgdmlzaXQgaHR0cHM6Ly9tZXRhLmRpc2NvdXJz +ZS5vcmcvdC90ZXN0aW5nLWRlZmF1bHQtZW1haWwtcmVwbGllcy8yMjYzOC8zIGluIHlvdXIgYnJv +d3Nlci4NCg0KDQpUbyB1bnN1YnNjcmliZSBmcm9tIHRoZXNlIGVtYWlscywgdmlzaXQgeW91ciB1 +c2VyIHByZWZlcmVuY2VzLg== + +--_866E2678-BB4F-4DD8-BE18-81B04AD8D1BC_ +Content-Transfer-Encoding: base64 +Content-Type: text/html; charset="utf-8" + +CjxodG1sPgo8aGVhZD4KPG1ldGEgbmFtZT0iZ2VuZXJhdG9yIiBjb250ZW50PSJXaW5kb3dzIE1h +aWwgMTcuNS45NjAwLjIwNjA1Ij4KPHN0eWxlIGRhdGEtZXh0ZXJuYWxzdHlsZT0idHJ1ZSI+PCEt +LQpwLk1zb0xpc3RQYXJhZ3JhcGgsIGxpLk1zb0xpc3RQYXJhZ3JhcGgsIGRpdi5Nc29MaXN0UGFy +YWdyYXBoIHsKbWFyZ2luLXRvcDowaW47Cm1hcmdpbi1yaWdodDowaW47Cm1hcmdpbi1ib3R0b206 +MGluOwptYXJnaW4tbGVmdDouNWluOwptYXJnaW4tYm90dG9tOi4wMDAxcHQ7Cn0KcC5Nc29Ob3Jt +YWwsIGxpLk1zb05vcm1hbCwgZGl2Lk1zb05vcm1hbCB7Cm1hcmdpbjowaW47Cm1hcmdpbi1ib3R0 +b206LjAwMDFwdDsKfQpwLk1zb0xpc3RQYXJhZ3JhcGhDeFNwRmlyc3QsIGxpLk1zb0xpc3RQYXJh +Z3JhcGhDeFNwRmlyc3QsIGRpdi5Nc29MaXN0UGFyYWdyYXBoQ3hTcEZpcnN0LCAKcC5Nc29MaXN0 +UGFyYWdyYXBoQ3hTcE1pZGRsZSwgbGkuTXNvTGlzdFBhcmFncmFwaEN4U3BNaWRkbGUsIGRpdi5N +c29MaXN0UGFyYWdyYXBoQ3hTcE1pZGRsZSwgCnAuTXNvTGlzdFBhcmFncmFwaEN4U3BMYXN0LCBs +aS5Nc29MaXN0UGFyYWdyYXBoQ3hTcExhc3QsIGRpdi5Nc29MaXN0UGFyYWdyYXBoQ3hTcExhc3Qg +ewptYXJnaW4tdG9wOjBpbjsKbWFyZ2luLXJpZ2h0OjBpbjsKbWFyZ2luLWJvdHRvbTowaW47Cm1h +cmdpbi1sZWZ0Oi41aW47Cm1hcmdpbi1ib3R0b206LjAwMDFwdDsKbGluZS1oZWlnaHQ6MTE1JTsK +fQotLT48L3N0eWxlPjwvaGVhZD4KPGJvZHkgZGlyPSJsdHIiPgo8ZGl2IGRhdGEtZXh0ZXJuYWxz +dHlsZT0iZmFsc2UiIGRpcj0ibHRyIiBzdHlsZT0iZm9udC1mYW1pbHk6ICdDYWxpYnJpJywgJ1Nl +Z29lIFVJJywgJ01laXJ5bycsICdNaWNyb3NvZnQgWWFIZWkgVUknLCAnTWljcm9zb2Z0IEpoZW5n +SGVpIFVJJywgJ01hbGd1biBHb3RoaWMnLCAnc2Fucy1zZXJpZic7Zm9udC1zaXplOjEycHQ7Ij48 +ZGl2IHN0eWxlPSJmb250LXNpemU6IDE0cHQ7Ij4jIyMgcmVwbHkgZnJvbSBkZWZhdWx0IG1haWwg +Y2xpZW50IGluIFdpbmRvd3MgOC4xIE1ldHJvPC9kaXY+PGRpdiBzdHlsZT0iZm9udC1zaXplOiAx +NHB0OyI+PGJyPjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6ZTogMTRwdDsiPlRoZSBxdWljayBi +cm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVt +cHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUg +bGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRo +ZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93 +biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMg +b3ZlciB0aGUgbGF6eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6 +eSBkb2cuIFRoZSBxdWljayBicm93biBmb3gganVtcHMgb3ZlciB0aGUgbGF6eSBkb2cuPC9kaXY+ +PGRpdiBzdHlsZT0iZm9udC1zaXplOiAxNHB0OyI+PGJyPjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQt +c2l6ZTogMTRwdDsiPlRoaXMgaXMgYSAqKmJvbGQqKiB3b3JkIGluIE1hcmtkb3duPC9kaXY+PGRp +diBzdHlsZT0iZm9udC1zaXplOiAxNHB0OyI+PGJyPjwvZGl2PjxkaXYgc3R5bGU9ImZvbnQtc2l6 +ZTogMTRwdDsiPlRoaXMgaXMgYSBsaW5rIDxhIGhyZWY9Imh0dHA6Ly9leGFtcGxlLmNvbSI+aHR0 +cDovL2V4YW1wbGUuY29tPC9hPjxicj4mbmJzcDs8L2Rpdj48ZGl2IHN0eWxlPSJmb250LXNpemU6 +IDE0cHQ7Ij48YnI+PC9kaXY+PGRpdiBzdHlsZT0icGFkZGluZy10b3A6IDVweDsgYm9yZGVyLXRv +cC1jb2xvcjogcmdiKDIyOSwgMjI5LCAyMjkpOyBib3JkZXItdG9wLXdpZHRoOiAxcHg7IGJvcmRl +ci10b3Atc3R5bGU6IHNvbGlkOyI+PGRpdj48Zm9udCBmYWNlPSIgJ0NhbGlicmknLCAnU2Vnb2Ug +VUknLCAnTWVpcnlvJywgJ01pY3Jvc29mdCBZYUhlaSBVSScsICdNaWNyb3NvZnQgSmhlbmdIZWkg +VUknLCAnTWFsZ3VuIEdvdGhpYycsICdzYW5zLXNlcmlmJyIgc3R5bGU9J2xpbmUtaGVpZ2h0OiAx +NXB0OyBsZXR0ZXItc3BhY2luZzogMC4wMmVtOyBmb250LWZhbWlseTogIkNhbGlicmkiLCAiU2Vn +b2UgVUkiLCAiTWVpcnlvIiwgIk1pY3Jvc29mdCBZYUhlaSBVSSIsICJNaWNyb3NvZnQgSmhlbmdI +ZWkgVUkiLCAiTWFsZ3VuIEdvdGhpYyIsICJzYW5zLXNlcmlmIjsgZm9udC1zaXplOiAxMnB0Oyc+ +PGI+RnJvbTo8L2I+Jm5ic3A7PGEgaHJlZj0ibWFpbHRvOmluZm9AZGlzY291cnNlLm9yZyIgdGFy +Z2V0PSJfcGFyZW50Ij5BcnBpdCBKYWxhbjwvYT48YnI+PGI+U2VudDo8L2I+Jm5ic3A74oCORnJp +ZGF54oCOLCDigI5Ob3ZlbWJlcuKAjiDigI4yOOKAjiwg4oCOMjAxNCDigI4xMuKAjjrigI4zNeKA +jiDigI5QTTxicj48Yj5Ubzo8L2I+Jm5ic3A7PGEgaHJlZj0ibWFpbHRvOmphdHdvb2RAY29kaW5n +aG9ycm9yLmNvbSIgdGFyZ2V0PSJfcGFyZW50Ij5qZWZmIGF0d29vZDwvYT48L2ZvbnQ+PC9kaXY+ +PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdiBkaXI9IiI+PGRpdj4KCjx0YWJsZSB0YWJpbmRleD0i +LTEiIHN0eWxlPSJtYXJnaW4tYm90dG9tOiAyNXB4OyIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0i +MCIgY2VsbHBhZGRpbmc9IjAiPgogIDx0Ym9keT4KICAgIDx0cj4KICAgICAgPHRkIHN0eWxlPSJ3 +aWR0aDogNTVweDsgdmVydGljYWwtYWxpZ246IHRvcDsiPgogICAgICAgIDxpbWcgd2lkdGg9IjQ1 +IiBoZWlnaHQ9IjQ1IiB0YWJpbmRleD0iLTEiIHN0eWxlPSJtYXgtd2lkdGg6IDEwMCU7IiBzcmM9 +Imh0dHBzOi8vbWV0YS1kaXNjb3Vyc2UuZ2xvYmFsLnNzbC5mYXN0bHkubmV0L3VzZXJfYXZhdGFy +L21ldGEuZGlzY291cnNlLm9yZy90ZWNoYXBqLzQ1LzMyODEucG5nIiBkYXRhLW1zLWltZ3NyYz0i +aHR0cHM6Ly9tZXRhLWRpc2NvdXJzZS5nbG9iYWwuc3NsLmZhc3RseS5uZXQvdXNlcl9hdmF0YXIv +bWV0YS5kaXNjb3Vyc2Uub3JnL3RlY2hhcGovNDUvMzI4MS5wbmciPgogICAgICA8L3RkPgogICAg +ICA8dGQ+CiAgICAgICAgPGEgc3R5bGU9J2NvbG9yOiByZ2IoNTksIDg5LCAxNTIpOyBmb250LWZh +bWlseTogImx1Y2lkYSBncmFuZGUiLHRhaG9tYSx2ZXJkYW5hLGFyaWFsLHNhbnMtc2VyaWY7IGZv +bnQtc2l6ZTogMTNweDsgZm9udC13ZWlnaHQ6IGJvbGQ7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsn +IGhyZWY9Imh0dHBzOi8vbWV0YS5kaXNjb3Vyc2Uub3JnL3VzZXJzL3RlY2hhcGoiIHRhcmdldD0i +X3BhcmVudCI+dGVjaEFQSjwvYT48YnI+CiAgICAgICAgPHNwYW4gc3R5bGU9J3RleHQtYWxpZ246 +IHJpZ2h0OyBjb2xvcjogcmdiKDE1MywgMTUzLCAxNTMpOyBwYWRkaW5nLXJpZ2h0OiA1cHg7IGZv +bnQtZmFtaWx5OiAibHVjaWRhIGdyYW5kZSIsdGFob21hLHZlcmRhbmEsYXJpYWwsc2Fucy1zZXJp +ZjsgZm9udC1zaXplOiAxMXB4Oyc+Tm92ZW1iZXIgMjg8L3NwYW4+CiAgICAgIDwvdGQ+CiAgICA8 +L3RyPgogICAgPHRyPgogICAgICA8dGQgc3R5bGU9InBhZGRpbmctdG9wOiA1cHg7IiBjb2xzcGFu +PSIyIj4KPHAgc3R5bGU9ImJvcmRlcjogMHB4IGJsYWNrOyBib3JkZXItaW1hZ2U6IG5vbmU7IG1h +cmdpbi10b3A6IDBweDsiPlRlc3QgcmVwbHkuPC9wPgoKPHAgc3R5bGU9ImJvcmRlcjogMHB4IGJs +YWNrOyBib3JkZXItaW1hZ2U6IG5vbmU7IG1hcmdpbi10b3A6IDBweDsiPkZpcnN0IHBhcmFncmFw +aC48L3A+Cgo8cCBzdHlsZT0iYm9yZGVyOiAwcHggYmxhY2s7IGJvcmRlci1pbWFnZTogbm9uZTsg +bWFyZ2luLXRvcDogMHB4OyI+U2Vjb25kIHBhcmFncmFwaC48L3A+CjwvdGQ+CiAgICA8L3RyPgog +IDwvdGJvZHk+CjwvdGFibGU+CgoKICA8ZGl2IHN0eWxlPSJjb2xvcjogcmdiKDEwMiwgMTAyLCAx +MDIpOyI+CiAgICA8cD5UbyByZXNwb25kLCByZXBseSB0byB0aGlzIGVtYWlsIG9yIHZpc2l0IDxh +IHN0eWxlPSJjb2xvcjogcmdiKDEwMiwgMTAyLCAxMDIpOyBmb250LXdlaWdodDogYm9sZDsgdGV4 +dC1kZWNvcmF0aW9uOiBub25lOyIgaHJlZj0iaHR0cHM6Ly9tZXRhLmRpc2NvdXJzZS5vcmcvdC90 +ZXN0aW5nLWRlZmF1bHQtZW1haWwtcmVwbGllcy8yMjYzOC8zIiB0YXJnZXQ9Il9wYXJlbnQiPmh0 +dHBzOi8vbWV0YS5kaXNjb3Vyc2Uub3JnL3QvdGVzdGluZy1kZWZhdWx0LWVtYWlsLXJlcGxpZXMv +MjI2MzgvMzwvYT4gaW4geW91ciBicm93c2VyLjwvcD4KICA8L2Rpdj4KICA8aHIgc3R5bGU9ImJv +cmRlcjogMXB4IGJsYWNrOyBib3JkZXItaW1hZ2U6IG5vbmU7IGhlaWdodDogMXB4OyBiYWNrZ3Jv +dW5kLWNvbG9yOiByZ2IoMjIxLCAyMjEsIDIyMSk7Ij4KICA8aDQ+UHJldmlvdXMgUmVwbGllczwv +aDQ+CgogIDx0YWJsZSB0YWJpbmRleD0iLTEiIHN0eWxlPSJtYXJnaW4tYm90dG9tOiAyNXB4OyIg +Ym9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiPgogIDx0Ym9keT4KICAg +IDx0cj4KICAgICAgPHRkIHN0eWxlPSJ3aWR0aDogNTVweDsgdmVydGljYWwtYWxpZ246IHRvcDsi +PgogICAgICAgIDxpbWcgd2lkdGg9IjQ1IiBoZWlnaHQ9IjQ1IiB0YWJpbmRleD0iLTEiIHN0eWxl +PSJtYXgtd2lkdGg6IDEwMCU7IiBzcmM9Imh0dHBzOi8vbWV0YS1kaXNjb3Vyc2UuZ2xvYmFsLnNz +bC5mYXN0bHkubmV0L3VzZXJfYXZhdGFyL21ldGEuZGlzY291cnNlLm9yZy9jb2Rpbmdob3Jyb3Iv +NDUvNTI5Ny5wbmciIGRhdGEtbXMtaW1nc3JjPSJodHRwczovL21ldGEtZGlzY291cnNlLmdsb2Jh +bC5zc2wuZmFzdGx5Lm5ldC91c2VyX2F2YXRhci9tZXRhLmRpc2NvdXJzZS5vcmcvY29kaW5naG9y +cm9yLzQ1LzUyOTcucG5nIj4KICAgICAgPC90ZD4KICAgICAgPHRkPgogICAgICAgIDxhIHN0eWxl +PSdjb2xvcjogcmdiKDU5LCA4OSwgMTUyKTsgZm9udC1mYW1pbHk6ICJsdWNpZGEgZ3JhbmRlIix0 +YWhvbWEsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmOyBmb250LXNpemU6IDEzcHg7IGZvbnQtd2Vp +Z2h0OiBib2xkOyB0ZXh0LWRlY29yYXRpb246IG5vbmU7JyBocmVmPSJodHRwczovL21ldGEuZGlz +Y291cnNlLm9yZy91c2Vycy9jb2Rpbmdob3Jyb3IiIHRhcmdldD0iX3BhcmVudCI+Y29kaW5naG9y +cm9yPC9hPjxicj4KICAgICAgICA8c3BhbiBzdHlsZT0ndGV4dC1hbGlnbjogcmlnaHQ7IGNvbG9y +OiByZ2IoMTUzLCAxNTMsIDE1Myk7IHBhZGRpbmctcmlnaHQ6IDVweDsgZm9udC1mYW1pbHk6ICJs +dWNpZGEgZ3JhbmRlIix0YWhvbWEsdmVyZGFuYSxhcmlhbCxzYW5zLXNlcmlmOyBmb250LXNpemU6 +IDExcHg7Jz5Ob3ZlbWJlciAyODwvc3Bhbj4KICAgICAgPC90ZD4KICAgIDwvdHI+CiAgICA8dHI+ +CiAgICAgIDx0ZCBzdHlsZT0icGFkZGluZy10b3A6IDVweDsiIGNvbHNwYW49IjIiPgo8cCBzdHls +ZT0iYm9yZGVyOiAwcHggYmxhY2s7IGJvcmRlci1pbWFnZTogbm9uZTsgbWFyZ2luLXRvcDogMHB4 +OyI+V2UncmUgdGVzdGluZyB0aGUgbGF0ZXN0IEdpdEh1YiBlbWFpbCBwcm9jZXNzaW5nIGxpYnJh +cnkgd2hpY2ggd2UgYXJlIGludGVncmF0aW5nIG5vdy48L3A+Cgo8cCBzdHlsZT0iYm9yZGVyOiAw +cHggYmxhY2s7IGJvcmRlci1pbWFnZTogbm9uZTsgbWFyZ2luLXRvcDogMHB4OyI+PGEgc3R5bGU9 +ImNvbG9yOiByZ2IoMCwgMTAyLCAxNTMpOyBmb250LXdlaWdodDogYm9sZDsgdGV4dC1kZWNvcmF0 +aW9uOiBub25lOyIgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL2dpdGh1Yi9lbWFpbF9yZXBseV9w +YXJzZXIiIHRhcmdldD0iX3BhcmVudCI+aHR0cHM6Ly9naXRodWIuY29tL2dpdGh1Yi9lbWFpbF9y +ZXBseV9wYXJzZXI8L2E+PC9wPgoKPHAgc3R5bGU9ImJvcmRlcjogMHB4IGJsYWNrOyBib3JkZXIt +aW1hZ2U6IG5vbmU7IG1hcmdpbi10b3A6IDBweDsiPkdvIGFoZWFkIGFuZCByZXBseSB0byB0aGlz +IHRvcGljIGFuZCBJJ2xsIHJlcGx5IGZyb20gdmFyaW91cyBlbWFpbCBjbGllbnRzIGZvciB0ZXN0 +aW5nLjwvcD4KPC90ZD4KICAgIDwvdHI+CiAgPC90Ym9keT4KPC90YWJsZT4KCgo8aHIgc3R5bGU9 +ImJvcmRlcjogMXB4IGJsYWNrOyBib3JkZXItaW1hZ2U6IG5vbmU7IGhlaWdodDogMXB4OyBiYWNr +Z3JvdW5kLWNvbG9yOiByZ2IoMjIxLCAyMjEsIDIyMSk7Ij4KCjxkaXYgc3R5bGU9ImNvbG9yOiBy +Z2IoMTAyLCAxMDIsIDEwMik7Ij4KPHA+VG8gcmVzcG9uZCwgcmVwbHkgdG8gdGhpcyBlbWFpbCBv +ciB2aXNpdCA8YSBzdHlsZT0iY29sb3I6IHJnYigxMDIsIDEwMiwgMTAyKTsgZm9udC13ZWlnaHQ6 +IGJvbGQ7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsiIGhyZWY9Imh0dHBzOi8vbWV0YS5kaXNjb3Vy +c2Uub3JnL3QvdGVzdGluZy1kZWZhdWx0LWVtYWlsLXJlcGxpZXMvMjI2MzgvMyIgdGFyZ2V0PSJf +cGFyZW50Ij5odHRwczovL21ldGEuZGlzY291cnNlLm9yZy90L3Rlc3RpbmctZGVmYXVsdC1lbWFp +bC1yZXBsaWVzLzIyNjM4LzM8L2E+IGluIHlvdXIgYnJvd3Nlci48L3A+CjwvZGl2Pgo8ZGl2IHN0 +eWxlPSJjb2xvcjogcmdiKDEwMiwgMTAyLCAxMDIpOyI+CjxwPlRvIHVuc3Vic2NyaWJlIGZyb20g +dGhlc2UgZW1haWxzLCB2aXNpdCB5b3VyIDxhIHN0eWxlPSJjb2xvcjogcmdiKDEwMiwgMTAyLCAx +MDIpOyBmb250LXdlaWdodDogYm9sZDsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyIgaHJlZj0iaHR0 +cHM6Ly9tZXRhLmRpc2NvdXJzZS5vcmcvbXkvcHJlZmVyZW5jZXMiIHRhcmdldD0iX3BhcmVudCI+ +dXNlciBwcmVmZXJlbmNlczwvYT4uPC9wPgo8L2Rpdj4KPC9kaXY+CjwvZGl2PjxkaXYgc3R5bGU9 +ImZvbnQtc2l6ZTogMTRwdDsiPjxicj48L2Rpdj48L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg== + +--_866E2678-BB4F-4DD8-BE18-81B04AD8D1BC_-- From 9defb6879bad42d61a88aab28ade69a3ac636331 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 1 Dec 2014 15:34:50 +1100 Subject: [PATCH 009/144] upgrade to rails master --- Gemfile | 17 ++++-- Gemfile.lock | 4 +- Gemfile_master.lock | 144 +++++++++++++++++++++++--------------------- 3 files changed, 92 insertions(+), 73 deletions(-) diff --git a/Gemfile b/Gemfile index cf663f22a9..08e62becf2 100644 --- a/Gemfile +++ b/Gemfile @@ -67,17 +67,19 @@ unless Bundler::Dependency::PLATFORM_MAP.include? :mri_21 end end -gem 'seed-fu', '~> 2.3.3' if rails_master? gem 'arel', git: 'https://github.com/rails/arel.git' gem 'rails', git: 'https://github.com/rails/rails.git' + gem 'rails-observers', git: 'https://github.com/SamSaffron/rails-observers.git' + gem 'seed-fu', git: 'https://github.com/SamSaffron/seed-fu.git', branch: 'discourse' else + gem 'seed-fu', '~> 2.3.3' gem 'rails' + gem 'rails-observers' end gem 'actionpack-action_caching' -gem 'rails-observers' # Rails 4.1.6+ will relax the mail gem version requirement to `~> 2.5, >= 2.5.4`. # However, mail gem 2.6.x currently does not work with discourse because of the @@ -144,8 +146,15 @@ gem 'omniauth-github-discourse', require: 'omniauth-github' gem 'omniauth-oauth2', require: false gem 'omniauth-google-oauth2' gem 'oj' -# while resolving https://groups.google.com/forum/#!topic/ruby-pg/5_ylGmog1S4 -gem 'pg', '0.15.1' + +if rails_master? + # native casting + gem 'pg', '0.18.0.pre20141117110243' +else + # while resolving https://groups.google.com/forum/#!topic/ruby-pg/5_ylGmog1S4 + gem 'pg', '0.15.1' +end + gem 'pry-rails', require: false gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock index 0f56e0cbc1..8c5c8a7b60 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,7 +99,7 @@ GEM fastimage (1.6.3) addressable (~> 2.3, >= 2.3.5) ffi (1.9.5) - flamegraph (0.0.8) + flamegraph (0.0.9) fast_stack fog (1.22.1) fog-brightbox @@ -273,7 +273,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) raindrops (0.13.0) - rake (10.3.2) + rake (10.4.0) rake-compiler (0.9.3) rake rb-fsevent (0.9.4) diff --git a/Gemfile_master.lock b/Gemfile_master.lock index c962d2baec..c3f6d3a39b 100644 --- a/Gemfile_master.lock +++ b/Gemfile_master.lock @@ -7,66 +7,26 @@ GIT activemodel (>= 3.0) GIT - remote: https://github.com/rails/arel.git - revision: 1fefe71b1872c0a83f09231164863cd8dbb57174 + remote: https://github.com/SamSaffron/rails-observers.git + revision: 7d2222d758603a004f6599f82a7068ffeb2d7ebf specs: - arel (6.0.0) + rails-observers (0.1.2) + activemodel (> 4.0) GIT - remote: https://github.com/rails/rails.git - revision: 2f8be7ebafcf7815f9f3ec7983789157525a60fa + remote: https://github.com/SamSaffron/seed-fu.git + revision: d93df3b6364ea938d87c5629bf950b0d1ffe037e + branch: discourse specs: - actionmailer (4.2.0.beta4) - actionpack (= 4.2.0.beta4) - actionview (= 4.2.0.beta4) - activejob (= 4.2.0.beta4) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.0.beta4) - actionview (= 4.2.0.beta4) - activesupport (= 4.2.0.beta4) - rack (~> 1.6.0.beta) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) - actionview (4.2.0.beta4) - activesupport (= 4.2.0.beta4) - builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) - activejob (4.2.0.beta4) - activesupport (= 4.2.0.beta4) - globalid (>= 0.3.0) - activemodel (4.2.0.beta4) - activesupport (= 4.2.0.beta4) - builder (~> 3.1) - activerecord (4.2.0.beta4) - activemodel (= 4.2.0.beta4) - activesupport (= 4.2.0.beta4) - arel (~> 6.0) - activesupport (4.2.0.beta4) - i18n (>= 0.7.0.beta1, < 0.8) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.1) - tzinfo (~> 1.1) - rails (4.2.0.beta4) - actionmailer (= 4.2.0.beta4) - actionpack (= 4.2.0.beta4) - actionview (= 4.2.0.beta4) - activejob (= 4.2.0.beta4) - activemodel (= 4.2.0.beta4) - activerecord (= 4.2.0.beta4) - activesupport (= 4.2.0.beta4) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.0.beta4) - sprockets-rails (~> 3.0.0.beta1) - railties (4.2.0.beta4) - actionpack (= 4.2.0.beta4) - activesupport (= 4.2.0.beta4) - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + seed-fu (2.3.3) + activerecord (>= 3.1) + activesupport (>= 3.1) + +GIT + remote: https://github.com/rails/arel.git + revision: 98fc25991137ee09b6800578117f8c1c322680f2 + specs: + arel (6.0.0) GIT remote: https://github.com/rails/sass-rails.git @@ -78,6 +38,61 @@ GIT sprockets (~> 2.12) sprockets-rails (>= 2.0, < 4.0) +PATH + remote: ../rails + specs: + actionmailer (5.0.0.alpha) + actionpack (= 5.0.0.alpha) + actionview (= 5.0.0.alpha) + activejob (= 5.0.0.alpha) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (5.0.0.alpha) + actionview (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + rack (~> 1.6.0.beta2) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + actionview (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.1) + activejob (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + globalid (>= 0.3.0) + activemodel (5.0.0.alpha) + activesupport (= 5.0.0.alpha) + builder (~> 3.1) + activerecord (5.0.0.alpha) + activemodel (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + arel (~> 6.0) + activesupport (5.0.0.alpha) + i18n (>= 0.7.0.beta1, < 0.8) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.1) + tzinfo (~> 1.1) + rails (5.0.0.alpha) + actionmailer (= 5.0.0.alpha) + actionpack (= 5.0.0.alpha) + actionview (= 5.0.0.alpha) + activejob (= 5.0.0.alpha) + activemodel (= 5.0.0.alpha) + activerecord (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + bundler (>= 1.3.0, < 2.0) + railties (= 5.0.0.alpha) + sprockets-rails + railties (5.0.0.alpha) + actionpack (= 5.0.0.alpha) + activesupport (= 5.0.0.alpha) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + PATH remote: vendor/gems/rails_multisite specs: @@ -150,7 +165,7 @@ GEM fastimage (1.6.3) addressable (~> 2.3, >= 2.3.5) ffi (1.9.5) - flamegraph (0.0.8) + flamegraph (0.0.9) fast_stack fog (1.22.1) fog-brightbox @@ -285,7 +300,7 @@ GEM openid-redis-store (0.0.2) redis ruby-openid - pg (0.15.1) + pg (0.18.0.pre20141117110243) polyglot (0.3.5) progress (3.0.1) pry (0.10.1) @@ -300,7 +315,7 @@ GEM rack (>= 1.1, < 2.0) qunit-rails (0.0.7) railties - rack (1.6.0.beta) + rack (1.6.0.beta2) rack-mini-profiler (0.9.2) rack (>= 1.1.3) rack-openid (1.3.1) @@ -318,8 +333,6 @@ GEM rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.1) loofah (~> 2.0) - rails-observers (0.1.2) - activemodel (~> 4.0) raindrops (0.13.0) rake (10.4.0) rake-compiler (0.9.3) @@ -373,9 +386,6 @@ GEM nokogiri (>= 1.4.4) nokogumbo (= 1.1.12) sass (3.2.19) - seed-fu (2.3.3) - activerecord (>= 3.1, < 4.2) - activesupport (>= 3.1, < 4.2) shoulda (3.5.0) shoulda-context (~> 1.0, >= 1.0.1) shoulda-matchers (>= 1.4.1, < 3.0) @@ -498,7 +508,7 @@ DEPENDENCIES omniauth-twitter onebox openid-redis-store - pg (= 0.15.1) + pg (= 0.18.0.pre20141117110243) pry-nav pry-rails puma @@ -506,7 +516,7 @@ DEPENDENCIES rack-mini-profiler rack-protection rails! - rails-observers + rails-observers! rails_multisite! rake rb-fsevent @@ -525,7 +535,7 @@ DEPENDENCIES sanitize sass sass-rails! - seed-fu (~> 2.3.3) + seed-fu! shoulda sidekiq simple-rss From 5352a7f53ca1cb588576ea7883ba8afb142cbe32 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Sun, 30 Nov 2014 21:25:54 -0800 Subject: [PATCH 010/144] Don't `use_route` See https://github.com/rails/rails/pull/17453 and https://github.com/rails/rails/pull/17725 --- .../spec/poll_plugin/poll_controller_spec.rb | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/plugins/poll/spec/poll_plugin/poll_controller_spec.rb b/plugins/poll/spec/poll_plugin/poll_controller_spec.rb index a621db5762..8f912d8492 100644 --- a/plugins/poll/spec/poll_plugin/poll_controller_spec.rb +++ b/plugins/poll/spec/poll_plugin/poll_controller_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe PollPlugin::PollController, type: :controller do + routes { PollPlugin::Engine.routes } + let(:topic) { create_topic(title: "Poll: Chitoge vs Onodera") } let!(:post) { create_post(topic: topic, raw: "Pick one.\n\n[poll]\n* Chitoge\n* Onodera\n[/poll]") } let(:user1) { Fabricate(:user) } @@ -9,43 +11,43 @@ describe PollPlugin::PollController, type: :controller do describe 'vote' do it "returns 403 if no user is logged in" do - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + xhr :put, :vote, post_id: post.id, option: "Chitoge" response.should be_forbidden end it "returns 400 if post_id or invalid option is not specified" do log_in_user user1 - xhr :put, :vote, use_route: :poll + xhr :put, :vote response.status.should eq(400) - xhr :put, :vote, post_id: post.id, use_route: :poll + xhr :put, :vote, post_id: post.id response.status.should eq(400) - xhr :put, :vote, option: "Chitoge", use_route: :poll + xhr :put, :vote, option: "Chitoge" response.status.should eq(400) - xhr :put, :vote, post_id: post.id, option: "Tsugumi", use_route: :poll + xhr :put, :vote, post_id: post.id, option: "Tsugumi" response.status.should eq(400) end it "returns 400 if post_id doesn't correspond to a poll post" do log_in_user user1 post2 = create_post(topic: topic, raw: "Generic reply") - xhr :put, :vote, post_id: post2.id, option: "Chitoge", use_route: :poll + xhr :put, :vote, post_id: post2.id, option: "Chitoge" end it "saves votes correctly" do MessageBus.expects(:publish).times(3) log_in_user user1 - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + xhr :put, :vote, post_id: post.id, option: "Chitoge" PollPlugin::Poll.new(post).get_vote(user1).should eq("Chitoge") log_in_user user2 - xhr :put, :vote, post_id: post.id, option: "Onodera", use_route: :poll + xhr :put, :vote, post_id: post.id, option: "Onodera" PollPlugin::Poll.new(post).get_vote(user2).should eq("Onodera") PollPlugin::Poll.new(post).details["Chitoge"].should eq(1) PollPlugin::Poll.new(post).details["Onodera"].should eq(1) - xhr :put, :vote, post_id: post.id, option: "Chitoge", use_route: :poll + xhr :put, :vote, post_id: post.id, option: "Chitoge" PollPlugin::Poll.new(post).get_vote(user2).should eq("Chitoge") PollPlugin::Poll.new(post).details["Chitoge"].should eq(2) @@ -57,21 +59,21 @@ describe PollPlugin::PollController, type: :controller do it "returns 400 if post_id doesn't correspond to a poll post" do log_in_user admin post2 = create_post(topic: topic, raw: "Generic reply") - xhr :put, :toggle_close, post_id: post2.id, use_route: :poll + xhr :put, :toggle_close, post_id: post2.id response.status.should eq(400) end it "returns 400 if the topic is locked" do log_in_user admin topic.update_attributes closed: true - xhr :put, :toggle_close, post_id: post.id, use_route: :poll + xhr :put, :toggle_close, post_id: post.id response.status.should eq(400) end it "raises Discourse::InvalidAccess is the user is not authorized" do log_in_user user1 expect do - xhr :put, :toggle_close, post_id: post.id, use_route: :poll + xhr :put, :toggle_close, post_id: post.id end.to raise_error(Discourse::InvalidAccess) end @@ -79,10 +81,10 @@ describe PollPlugin::PollController, type: :controller do I18n.stubs(:t).with('poll.prefix').returns("Poll ") I18n.stubs(:t).with('poll.closed_prefix').returns("Closed Poll ") log_in_user admin - xhr :put, :toggle_close, post_id: post.id, use_route: :poll + xhr :put, :toggle_close, post_id: post.id response.status.should eq(200) topic.reload.title.should == "Closed Poll : Chitoge vs Onodera" - xhr :put, :toggle_close, post_id: post.id, use_route: :poll + xhr :put, :toggle_close, post_id: post.id response.status.should eq(200) topic.reload.title.should == "Poll : Chitoge vs Onodera" end From a3a04e06b61c7f60943985aa5535a4486874caa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Mon, 1 Dec 2014 11:38:33 +0100 Subject: [PATCH 011/144] fix images in readme --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ae82fb76fc..006e797675 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ To learn more about the philosophy and goals of the project, [visit **discourse. ## Screenshots -[![](https://raw2.github.com/discourse/discourse-docimages/master/readme/boing-boing-latest-small2.png)](http://bbs.boingboing.net) -[![](https://raw2.github.com/discourse/discourse-docimages/master/readme/how-to-geek-profile-small2.png?breakcache=1)](http://discuss.howtogeek.com) -[![](https://raw2.github.com/discourse/discourse-docimages/master/readme/new-relic-categories-small2.png)](http://discuss.newrelic.com) -[![](https://raw2.github.com/discourse/discourse-docimages/master/readme/turtle-rock-topic-small2.jpg)](https://talk.turtlerockstudios.com/) -[![](https://raw.github.com/discourse/discourse-docimages/master/readme/nexus-7-mobile-discourse-small3.png)](http://discuss.atom.io) -[![](https://raw.github.com/discourse/discourse-docimages/master/readme/iphone-5s-mobile-discourse-small4.png)](http://discourse.soylent.me) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/boing-boing-latest-small2.png)](http://bbs.boingboing.net) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/how-to-geek-profile-small2.png)](http://discuss.howtogeek.com) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/new-relic-categories-small2.png)](http://discuss.newrelic.com) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/turtle-rock-topic-small2.jpg)](https://talk.turtlerockstudios.com/) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/nexus-7-mobile-discourse-small3.png)](http://discuss.atom.io) +[![](https://raw.githubusercontent.com/discourse/discourse-docimages/master/readme/iphone-5s-mobile-discourse-small4.png)](http://discourse.soylent.me) ## Development From c00c5e1024b467fe5c29b59ba5e5a89e91b1c3d4 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Mon, 1 Dec 2014 03:36:25 -0800 Subject: [PATCH 012/144] our previous mobile avatar tap fix was incorrect --- app/assets/stylesheets/mobile/topic-post.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/mobile/topic-post.scss b/app/assets/stylesheets/mobile/topic-post.scss index 5fbdddf577..cfd7cff339 100644 --- a/app/assets/stylesheets/mobile/topic-post.scss +++ b/app/assets/stylesheets/mobile/topic-post.scss @@ -450,17 +450,18 @@ span.highlighted { .topic-avatar { float: left; position: relative; + z-index:999; /* must render on top of topic-body + topic-meta-data, otherwise not tappable */ } .topic-meta-data { - margin-left: 60px; white-space: nowrap; position: absolute; - width: 80%; + width: 100%; left: 0px; .names { margin: 5px 0 0 5px; line-height: 17px; + padding-left: 60px; span { display: block; } From cc76087f59b5039ec60d5458345a18354fd24e0e Mon Sep 17 00:00:00 2001 From: James Kiesel Date: Sun, 30 Nov 2014 15:09:34 +1300 Subject: [PATCH 013/144] Add new private message button on topics list That'll teach me to wildly refactor things. --- .../discourse/controllers/user-topics-list.js.es6 | 2 +- app/assets/javascripts/discourse/routes/user.js.es6 | 6 +++--- .../discourse/templates/list/user_topics_list.hbs | 6 ++++++ app/assets/stylesheets/common/base/user.scss | 3 +++ app/serializers/user_serializer.rb | 7 +++++++ config/locales/client.en.yml | 1 + 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/user-topics-list.js.es6 b/app/assets/javascripts/discourse/controllers/user-topics-list.js.es6 index c39d34df95..58320d8c62 100644 --- a/app/assets/javascripts/discourse/controllers/user-topics-list.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-topics-list.js.es6 @@ -1,7 +1,7 @@ import ObjectController from 'discourse/controllers/object'; // Lists of topics on a user's page. -export default ObjectController.extend({ +export default ObjectController.extend(Discourse.HasCurrentUser, { needs: ["application"], hideCategory: false, showParticipants: false, diff --git a/app/assets/javascripts/discourse/routes/user.js.es6 b/app/assets/javascripts/discourse/routes/user.js.es6 index 910abb196f..ac4ddb49cf 100644 --- a/app/assets/javascripts/discourse/routes/user.js.es6 +++ b/app/assets/javascripts/discourse/routes/user.js.es6 @@ -15,11 +15,11 @@ export default Discourse.Route.extend({ Discourse.logout(); }, - composePrivateMessage: function() { - var user = this.modelFor('user'); + composePrivateMessage: function(user) { + var recipient = user ? user.username : ''; return this.controllerFor('composer').open({ action: Discourse.Composer.PRIVATE_MESSAGE, - usernames: user.get('username'), + usernames: recipient, archetypeId: 'private_message', draftKey: 'new_private_message' }); diff --git a/app/assets/javascripts/discourse/templates/list/user_topics_list.hbs b/app/assets/javascripts/discourse/templates/list/user_topics_list.hbs index ac54a240bf..f0270c6ad1 100644 --- a/app/assets/javascripts/discourse/templates/list/user_topics_list.hbs +++ b/app/assets/javascripts/discourse/templates/list/user_topics_list.hbs @@ -1,3 +1,9 @@ +{{#if currentUser.can_send_private_messages}} + +{{/if}} + {{basic-topic-list topicList=model hideCategory=hideCategory showParticipants=showParticipants diff --git a/app/assets/stylesheets/common/base/user.scss b/app/assets/stylesheets/common/base/user.scss index 8f8d35fded..1e77ac0b82 100644 --- a/app/assets/stylesheets/common/base/user.scss +++ b/app/assets/stylesheets/common/base/user.scss @@ -73,3 +73,6 @@ } } +.new-private-message { + margin-bottom: 15px; +} diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb index 1313db0b76..d7560c6c89 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/user_serializer.rb @@ -45,6 +45,7 @@ class UserSerializer < BasicUserSerializer :can_edit_email, :can_edit_name, :stats, + :can_send_private_messages, :can_send_private_message_to_user, :bio_excerpt, :trust_level, @@ -178,6 +179,12 @@ class UserSerializer < BasicUserSerializer UserAction.stats(object.id, scope) end + # Needed because 'send_private_message_to_user' will always return false + # when the current user is being serialized + def can_send_private_messages + scope.can_send_private_message?(Discourse.system_user) + end + def can_send_private_message_to_user scope.can_send_private_message?(object) end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 317d37e421..f026183e87 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -293,6 +293,7 @@ en: mute: "Mute" edit: "Edit Preferences" download_archive: "download archive of my posts" + new_private_message: "New Private Message" private_message: "Private Message" private_messages: "Messages" activity_stream: "Activity" From bdc92eec70f4c6a1d8766e4fe8d8d8f5405c47d8 Mon Sep 17 00:00:00 2001 From: Blake Erickson Date: Mon, 1 Dec 2014 06:03:25 -0700 Subject: [PATCH 014/144] Have log_out method return json. This commit helps improve the discourse_api experience so that we can check the json response if it was a success or not. This commit also checks that a 404 is sent instead of a 500 if a bad user_id is passed in. --- app/controllers/admin/users_controller.rb | 12 ++++++---- config/locales/client.en.yml | 1 + .../admin/users_controller_spec.rb | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index efd9b3be43..0688f38948 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -66,10 +66,14 @@ class Admin::UsersController < Admin::AdminController end def log_out - @user.auth_token = nil - @user.save! - MessageBus.publish "/logout", @user.id, user_ids: [@user.id] - render nothing: true + if @user + @user.auth_token = nil + @user.save! + MessageBus.publish "/logout", @user.id, user_ids: [@user.id] + render json: success_json + else + render json: {error: I18n.t('admin_js.admin.users.id_not_found')}, status: 404 + end end def refresh_browsers diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 317d37e421..083c4704c1 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1887,6 +1887,7 @@ en: create: 'Add Admin User' last_emailed: "Last Emailed" not_found: "Sorry, that username doesn't exist in our system." + id_not_found: "Sorry, that user id doesn't exist in our system." active: "Active" show_emails: "Show Emails" nav: diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 1740be819f..7a5566827e 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -360,6 +360,29 @@ describe Admin::UsersController do end end + context 'log_out' do + before do + @reg_user = Fabricate(:user) + end + + it 'returns JSON' do + xhr :put, :log_out, user_id: @reg_user.id + ::JSON.parse(response.body).should be_present + end + + it "returns success" do + xhr :put, :log_out, user_id: @reg_user.id + response.should be_success + json = ::JSON.parse(response.body) + json['success'].should == "OK" + end + + it "returns 404 when user_id does not exist" do + xhr :put, :log_out, user_id: 123123 + response.should_not be_success + end + end + context 'block' do before do @reg_user = Fabricate(:user) From e2fb5310d85cc52f760a644c4da3e0321f1c7818 Mon Sep 17 00:00:00 2001 From: Greg Kempe Date: Mon, 17 Nov 2014 16:46:58 +0200 Subject: [PATCH 015/144] Traverse symlinks to plugins in dev mode when compiling stylesheets When developing plugins it's useful to symlink the to the plugin directory from the discourse directory, since that means the two are separate git repos. However, Dir.glob doesn't by default traverse symlinks. This change means that the SASS compilation caching detects when any of a plugin's files have changed. --- lib/sass/discourse_stylesheets.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/sass/discourse_stylesheets.rb b/lib/sass/discourse_stylesheets.rb index 028def076e..ca0c5a9d63 100644 --- a/lib/sass/discourse_stylesheets.rb +++ b/lib/sass/discourse_stylesheets.rb @@ -56,10 +56,17 @@ class DiscourseStylesheets end def self.max_file_mtime - [ "#{Rails.root}/app/assets/stylesheets/**/*.*css", - "#{Rails.root}/plugins/**/*.*css", - "#{Rails.root}/plugins/**/plugin.rb" ].map do |pattern| - Dir.glob(pattern).map { |x| File.mtime(x) }.max + globs = ["#{Rails.root}/app/assets/stylesheets/**/*.*css"] + + for path in (Discourse.plugins || []).map { |plugin| File.dirname(plugin.path) } + globs += [ + "#{path}/plugin.rb", + "#{path}/**/*.*css", + ] + end + + globs.map do |pattern| + Dir.glob(pattern).map { |x| File.mtime(x) }.max end.compact.max.to_i end From 15c105eba5360c59c56cb548c4374b754b3577a4 Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Mon, 1 Dec 2014 23:51:14 +0530 Subject: [PATCH 016/144] Add test for email with inline reply --- spec/components/email/receiver_spec.rb | 47 ++++++++++++++++++++ spec/fixtures/emails/inline_reply.eml | 60 ++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 spec/fixtures/emails/inline_reply.eml diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb index a7e93873f2..9982060bdf 100644 --- a/spec/components/email/receiver_spec.rb +++ b/spec/components/email/receiver_spec.rb @@ -102,6 +102,53 @@ It will also be my *only* reply." ) end + it "handles inline reply" do + test_parse_body(fixture_file("emails/inline_reply.eml")). + should == ( +"On Wed, Oct 8, 2014 at 11:12 AM, techAPJ wrote: + +> techAPJ +> November 28 +> +> Test reply. +> +> First paragraph. +> +> Second paragraph. +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> ------------------------------ +> Previous Replies codinghorror +> +> November 28 +> +> We're testing the latest GitHub email processing library which we are +> integrating now. +> +> https://github.com/github/email_reply_parser +> +> Go ahead and reply to this topic and I'll reply from various email clients +> for testing. +> ------------------------------ +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> +> To unsubscribe from these emails, visit your user preferences +> . +> + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog." + ) + end + it "should not include previous replies" do test_parse_body(fixture_file("emails/previous_replies.eml")).should_not match /Previous Replies/ end diff --git a/spec/fixtures/emails/inline_reply.eml b/spec/fixtures/emails/inline_reply.eml new file mode 100644 index 0000000000..39625a225d --- /dev/null +++ b/spec/fixtures/emails/inline_reply.eml @@ -0,0 +1,60 @@ + +MIME-Version: 1.0 +In-Reply-To: +References: + <5434ced4ee0f9_663fb0b5f76070593b@discourse-app.mail> +Date: Mon, 1 Dec 2014 20:48:40 +0530 +Delivered-To: someone@googlemail.com +Subject: Re: [Discourse] [Meta] Testing reply via email +From: Walter White +To: Discourse +Content-Type: multipart/alternative; boundary=20cf30363f8522466905092920a6 + +--20cf30363f8522466905092920a6 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +On Wed, Oct 8, 2014 at 11:12 AM, techAPJ +wrote: + +> techAPJ +> November 28 +> +> Test reply. +> +> First paragraph. +> +> Second paragraph. +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> ------------------------------ +> Previous Replies codinghorror +> +> November 28 +> +> We're testing the latest GitHub email processing library which we are +> integrating now. +> +> https://github.com/github/email_reply_parser +> +> Go ahead and reply to this topic and I'll reply from various email clients +> for testing. +> ------------------------------ +> +> To respond, reply to this email or visit +> https://meta.discourse.org/t/testing-default-email-replies/22638/3 in +> your browser. +> +> To unsubscribe from these emails, visit your user preferences +> . +> + +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown +fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. +The quick brown fox jumps over the lazy dog. The quick brown fox jumps over +the lazy dog. The quick brown fox jumps over the lazy dog. + +--20cf30363f8522466905092920a6-- From b547be44b2bc1a54841a0ea17a7fbdb9bbac3939 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 1 Dec 2014 14:53:03 -0500 Subject: [PATCH 017/144] Better error message output --- .../discourse/routes/application.js.es6 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/discourse/routes/application.js.es6 b/app/assets/javascripts/discourse/routes/application.js.es6 index 794448f8d1..ca598b7748 100644 --- a/app/assets/javascripts/discourse/routes/application.js.es6 +++ b/app/assets/javascripts/discourse/routes/application.js.es6 @@ -27,10 +27,16 @@ var ApplicationRoute = Discourse.Route.extend({ } var exceptionController = this.controllerFor('exception'), - errorString = err.toString(); - if (err.statusText) { - errorString = err.statusText; - } + errorString = err.toString(), + stack = err.stack; + + // If we have a stack call `toString` on it. It gives us a better + // stack trace since `console.error` uses the stack track of this + // error callback rather than the original error. + if (stack) { errorString = stack.toString(); } + + if (err.statusText) { errorString = err.statusText; } + var c = window.console; if (c && c.error) { c.error(errorString); From 9bdac79ba697c91b1a0827d40af0cfa4a390fa83 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 1 Dec 2014 17:15:07 -0500 Subject: [PATCH 018/144] Make suspect report use <= 1 instead of = 0 --- lib/admin_user_index_query.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/admin_user_index_query.rb b/lib/admin_user_index_query.rb index f8ac8a8ca8..8af37f0861 100644 --- a/lib/admin_user_index_query.rb +++ b/lib/admin_user_index_query.rb @@ -43,7 +43,7 @@ class AdminUserIndexQuery where_conds = [] # One signal: no reading yet the user has bio text - where_conds << "user_stats.posts_read_count = 0 AND user_stats.topics_entered = 0" + where_conds << "user_stats.posts_read_count <= 1 AND user_stats.topics_entered <= 1" @query.activated .references(:user_stats) From f226e4efc0ab4a0ed2de497d3d8db808caa44b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 2 Dec 2014 02:16:30 +0100 Subject: [PATCH 019/144] FIX: don't error out when updating a topic with no changes --- app/controllers/topics_controller.rb | 4 ++-- spec/controllers/topics_controller_spec.rb | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 8e8d226d37..9e976f2124 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -123,8 +123,8 @@ class TopicsController < ApplicationController guardian.ensure_can_edit!(topic) changes = {} - changes[:title] = params[:title] if params[:title] - changes[:category_id] = params[:category_id] if params[:category_id] + changes[:title] = params[:title] if params[:title] && topic.title != params[:title] + changes[:category_id] = params[:category_id] if params[:category_id] && topic.category_id != params[:category_id].to_i success = true diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb index d8500e82d0..c8a05095de 100644 --- a/spec/controllers/topics_controller_spec.rb +++ b/spec/controllers/topics_controller_spec.rb @@ -783,6 +783,12 @@ describe TopicsController do expect(response).not_to be_success end + it "doesn't call the PostRevisor when there is no changes" do + PostRevisor.any_instance.expects(:revise!).never + xhr :put, :update, topic_id: @topic.id, slug: @topic.title, title: @topic.title, category_id: @topic.category_id + expect(response).to be_success + end + context "allow_uncategorized_topics is false" do before do SiteSetting.stubs(:allow_uncategorized_topics).returns(false) From e3bcd848b34fa5ee176f863f62f239c22c714969 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Mon, 1 Dec 2014 17:24:44 -0800 Subject: [PATCH 020/144] minor copyedit --- config/locales/client.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 083c4704c1..3a9a8f9fab 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -391,7 +391,7 @@ en: ok: "We will email you to confirm" invalid: "Please enter a valid email address" authenticated: "Your email has been authenticated by {{provider}}" - frequency: "We'll only email you if we haven't seen you recently and you haven't already seen the thing we're emailing you about." + frequency: "We'll only email you if we haven't seen you recently and you haven't read the thing we're emailing you about." name: title: "Name" From 0503599de707bc3d84c044a22351efb9779036b7 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Tue, 2 Dec 2014 00:19:42 -0800 Subject: [PATCH 021/144] suppress long category names on mobile --- app/assets/stylesheets/mobile/topic-list.scss | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/mobile/topic-list.scss b/app/assets/stylesheets/mobile/topic-list.scss index 726865574a..6d61c1f956 100644 --- a/app/assets/stylesheets/mobile/topic-list.scss +++ b/app/assets/stylesheets/mobile/topic-list.scss @@ -58,12 +58,14 @@ .topic-item-stats { margin-top: 8px; - } - - .topic-item-stats { .category, .num, .last-poster { float: left; } + .category a { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } .num .fa { color: scale-color($primary, $lightness: 50%); } @@ -261,9 +263,7 @@ tr.category-topic-link:nth-of-type(odd) { } ol.category-breadcrumb { - margin: 5px 10px 0 0; - } .category-dropdown-menu { @@ -274,10 +274,6 @@ ol.category-breadcrumb { line-height: 26px !important; margin-bottom: 0 !important; } - - div { - margin-bottom: 10px; - } } .top-lists { From 3fcde726567944f659a5e0c9b40d74fa2fb546f0 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Tue, 2 Dec 2014 00:41:51 -0800 Subject: [PATCH 022/144] bit shorter max width on mobile categories --- app/assets/stylesheets/mobile/topic-list.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/mobile/topic-list.scss b/app/assets/stylesheets/mobile/topic-list.scss index 6d61c1f956..c1ec6e5bc8 100644 --- a/app/assets/stylesheets/mobile/topic-list.scss +++ b/app/assets/stylesheets/mobile/topic-list.scss @@ -62,7 +62,7 @@ float: left; } .category a { - max-width: 200px; + max-width: 160px; overflow: hidden; text-overflow: ellipsis; } From 2ead3fca69e15f14d1102f0628b729c53dd59689 Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Tue, 2 Dec 2014 16:05:43 +0530 Subject: [PATCH 023/144] FIX: exportUsers action was deleted, so user export was failing --- .../admin/routes/admin-users-list.js.es6 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 app/assets/javascripts/admin/routes/admin-users-list.js.es6 diff --git a/app/assets/javascripts/admin/routes/admin-users-list.js.es6 b/app/assets/javascripts/admin/routes/admin-users-list.js.es6 new file mode 100644 index 0000000000..3a9c406b2c --- /dev/null +++ b/app/assets/javascripts/admin/routes/admin-users-list.js.es6 @@ -0,0 +1,15 @@ +export default Discourse.Route.extend({ + + actions: { + exportUsers: function() { + Discourse.ExportCsv.exportUserList().then(function(result) { + if (result.success) { + bootbox.alert(I18n.t("admin.export_csv.success")); + } else { + bootbox.alert(I18n.t("admin.export_csv.failed")); + } + }); + } + } + +}); From 121048662368ea9b0813cd892b655a2481222864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 2 Dec 2014 16:04:45 +0100 Subject: [PATCH 024/144] FIX: editing the 1st post of a private message wasn't working --- .../javascripts/discourse/models/composer.js | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index 164e3c604b..ad6d1c3a20 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -100,33 +100,29 @@ Discourse.Composer = Discourse.Model.extend({ hidePreview: Em.computed.not('showPreview'), - // Whether to disable the post button + // whether to disable the post button cantSubmitPost: function() { - - // Can't submit while loading + // can't submit while loading if (this.get('loading')) return true; - // Title is required when: - // - creating a new topic - // - editing the 1st post - // - creating a private message - + // title is required when + // - creating a new topic/private message + // - editing the 1st post if (this.get('canEditTitle') && !this.get('titleLengthValid')) return true; - // Need at least one user when sending a private message - if ( this.get('creatingPrivateMessage') && - this.get('targetUsernames') && - (this.get('targetUsernames').trim() + ',').indexOf(',') === 0) { - return true; - } - // reply is always required if (this.get('missingReplyCharacters') > 0) return true; - return this.get('canCategorize') && - !Discourse.SiteSettings.allow_uncategorized_topics && - !this.get('categoryId') && - !Discourse.User.currentProp('staff'); + if (this.get("privateMessage")) { + // need at least one user when sending a PM + return this.get('targetUsernames') && (this.get('targetUsernames').trim() + ',').indexOf(',') === 0; + } else { + // has a category? (when needed) + return this.get('canCategorize') && + !Discourse.SiteSettings.allow_uncategorized_topics && + !this.get('categoryId') && + !Discourse.User.currentProp('staff'); + } }.property('loading', 'canEditTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryId', 'missingReplyCharacters'), /** From 87667cfe17d7d31660241793cc009fd30994c415 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 2 Dec 2014 11:46:21 -0500 Subject: [PATCH 025/144] FIX: Editing a category definition topic was clearing its permissions --- app/assets/javascripts/discourse/models/site.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/models/site.js b/app/assets/javascripts/discourse/models/site.js index c66481c991..c8e09a9dce 100644 --- a/app/assets/javascripts/discourse/models/site.js +++ b/app/assets/javascripts/discourse/models/site.js @@ -66,7 +66,12 @@ Discourse.Site = Discourse.Model.extend({ updateCategory: function(newCategory) { var existingCategory = this.get('categories').findProperty('id', Em.get(newCategory, 'id')); - if (existingCategory) existingCategory.setProperties(newCategory); + if (existingCategory) { + // Don't update null permissions + if (newCategory.permission === null) { delete newCategory.permission; } + + existingCategory.setProperties(newCategory); + } } }); From 99928cac26120ddfc740845bd1deb156551f0c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 2 Dec 2014 18:15:32 +0100 Subject: [PATCH 026/144] FEATURE: use actual time in preference > email notifications' instruction --- .../javascripts/discourse/templates/user/preferences.hbs | 2 +- config/locales/client.en.yml | 5 ++++- config/site_settings.yml | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs index f5719294ba..7e7e099314 100644 --- a/app/assets/javascripts/discourse/templates/user/preferences.hbs +++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs @@ -181,7 +181,7 @@ {{preference-checkbox labelKey="user.email_always" checked=email_always}}
- {{i18n user.email.frequency}} + {{i18n user.email.frequency count=siteSettings.email_time_window_mins}}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 3a9a8f9fab..c8b8d963b5 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -391,7 +391,10 @@ en: ok: "We will email you to confirm" invalid: "Please enter a valid email address" authenticated: "Your email has been authenticated by {{provider}}" - frequency: "We'll only email you if we haven't seen you recently and you haven't read the thing we're emailing you about." + frequency: + zero: "We'll email you immediately if you haven't read the thing we're emailing you about." + one: "We'll only email you if we haven't seen you in the last minute and you haven't read the thing we're emailing you about." + other: "We'll only email you if we haven't seen you in the last {{count}} minutes and you haven't read the thing we're emailing you about." name: title: "Name" diff --git a/config/site_settings.yml b/config/site_settings.yml index 7bde8b1e45..2b6eb17b47 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -391,7 +391,9 @@ posting: type: list email: - email_time_window_mins: 10 + email_time_window_mins: + default: 10 + client: true email_posts_context: 5 digest_min_excerpt_length: 100 digest_topics: 20 From 461196f0893f703adf42a6045b7fbc750fe477e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 2 Dec 2014 18:52:56 +0100 Subject: [PATCH 027/144] FEATURE: 'delete user' button in the user card in the admin section --- .../discourse/controllers/user-card.js.es6 | 17 +++++++++-------- .../discourse/templates/user-card.hbs | 16 ++++++++++------ app/serializers/user_serializer.rb | 7 ++++++- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/user-card.js.es6 b/app/assets/javascripts/discourse/controllers/user-card.js.es6 index 90cfd46013..1557cc195b 100644 --- a/app/assets/javascripts/discourse/controllers/user-card.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-card.js.es6 @@ -13,23 +13,20 @@ export default ObjectController.extend({ postStream: Em.computed.alias('controllers.topic.postStream'), enoughPostsForFiltering: Em.computed.gte('participant.post_count', 2), viewingTopic: Em.computed.match('controllers.application.currentPath', /^topic\./), + viewingAdmin: Em.computed.match('controllers.application.currentPath', /^admin\./), showFilter: Em.computed.and('viewingTopic', 'postStream.hasNoFilters', 'enoughPostsForFiltering'), - - // showFilter: Em.computed.and('postStream.hasNoFilters', 'enoughPostsForFiltering'), showName: Discourse.computed.propertyNotEqual('user.name', 'user.username'), - hasUserFilters: Em.computed.gt('postStream.userFilters.length', 0), - isSuspended: Em.computed.notEmpty('user.suspend_reason'), - showBadges: Discourse.computed.setting('enable_badges'), + showMoreBadges: Em.computed.gt('moreBadgesCount', 0), + canDelete: Em.computed.not("user.deleteForbidden"), + showDelete: Em.computed.and("viewingAdmin", "showName", "canDelete"), moreBadgesCount: function() { return this.get('user.badge_count') - this.get('user.featured_user_badges.length'); }.property('user.badge_count', 'user.featured_user_badges.@each'), - showMoreBadges: Em.computed.gt('moreBadgesCount', 0), - hasCardBadgeImage: function() { var img = this.get('user.card_badge.image'); return img && img.indexOf('fa-') !== 0; @@ -77,7 +74,7 @@ export default ObjectController.extend({ self.set('cardTarget', target); Discourse.User.findByUsername(username).then(function (user) { - self.setProperties({ user: user, avatar: user, visible: true}); + self.setProperties({ user: Discourse.AdminUser.create(user), avatar: user, visible: true}); self.appEvents.trigger('usercard:shown'); }).finally(function(){ self.set('userLoading', null); @@ -101,6 +98,10 @@ export default ObjectController.extend({ postStream.cancelFilter(); postStream.refresh(); this.close(); + }, + + deleteUser: function(user) { + user.destroy({ deletePosts: true }); } } diff --git a/app/assets/javascripts/discourse/templates/user-card.hbs b/app/assets/javascripts/discourse/templates/user-card.hbs index b5dc6f39c5..c4326652fa 100644 --- a/app/assets/javascripts/discourse/templates/user-card.hbs +++ b/app/assets/javascripts/discourse/templates/user-card.hbs @@ -27,11 +27,15 @@ {{/if}} {{#if showFilter}} -
  • {{fa-icon "filter"}}{{i18n topic.filter_to username="username" post_count="participant.post_count"}}
  • +
  • {{fa-icon "filter"}}{{i18n topic.filter_to username="username" post_count="participant.post_count"}}
  • {{/if}} {{#if hasUserFilters}} -
  • {{fa-icon "times"}}{{i18n topic.filters.cancel}}
  • +
  • {{fa-icon "times"}}{{i18n topic.filters.cancel}}
  • + {{/if}} + + {{#if showDelete}} +
  • {{fa-icon "exclamation-triangle"}}{{i18n admin.user.delete}}
  • {{/if}} @@ -52,10 +56,10 @@ {{/if}} {{#if user}} - + {{/if}} {{#if showBadges}} diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb index 1313db0b76..0e1badaba9 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/user_serializer.rb @@ -66,7 +66,8 @@ class UserSerializer < BasicUserSerializer has_many :featured_user_badges, embed: :ids, serializer: UserBadgeSerializer, root: :user_badges has_one :card_badge, embed: :object, serializer: BadgeSerializer - staff_attributes :number_of_deleted_posts, + staff_attributes :post_count, + :number_of_deleted_posts, :number_of_flagged_posts, :number_of_flags_given, :number_of_suspensions, @@ -207,6 +208,10 @@ class UserSerializer < BasicUserSerializer ### STAFF ATTRIBUTES ### + def post_count + object.user_stat.try(:post_count) + end + def number_of_deleted_posts Post.with_deleted .where(user_id: object.id) From 67c4c90159428d700766ac610ca374d764cea6a7 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 2 Dec 2014 15:24:05 -0500 Subject: [PATCH 028/144] FIX: Clicking avatars broke for non-admins --- .../javascripts/discourse/controllers/user-card.js.es6 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/controllers/user-card.js.es6 b/app/assets/javascripts/discourse/controllers/user-card.js.es6 index 1557cc195b..2ea6b91e46 100644 --- a/app/assets/javascripts/discourse/controllers/user-card.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-card.js.es6 @@ -74,7 +74,14 @@ export default ObjectController.extend({ self.set('cardTarget', target); Discourse.User.findByUsername(username).then(function (user) { - self.setProperties({ user: Discourse.AdminUser.create(user), avatar: user, visible: true}); + + // A bit hacky. If viewing admin, wrap it in Discourse.AdminUser + // TODO: Restructure this to be cleaner + var wrapped = user; + if (self.get('viewingAdmin')) { + wrapped = Discourse.AdminUser.create(user); + } + self.setProperties({ user: wrapped, avatar: user, visible: true}); self.appEvents.trigger('usercard:shown'); }).finally(function(){ self.set('userLoading', null); From 008337b018a9c7ca4b9c52a251c2a680e42469dc Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 2 Dec 2014 15:30:57 -0500 Subject: [PATCH 029/144] FIX: Selecting one user in admin would select them all --- app/assets/javascripts/admin/templates/users-list-show.hbs | 4 ++-- app/assets/stylesheets/common/admin/admin_base.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/admin/templates/users-list-show.hbs b/app/assets/javascripts/admin/templates/users-list-show.hbs index 333e3f664a..69e02575bd 100644 --- a/app/assets/javascripts/admin/templates/users-list-show.hbs +++ b/app/assets/javascripts/admin/templates/users-list-show.hbs @@ -42,11 +42,11 @@ {{#each user in model}} - + {{#if controller.showApproval}} {{#if user.can_approve}} - {{input type="checkbox" checked=selected}} + {{input type="checkbox" checked=user.selected}} {{/if}} {{/if}} diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index 8ccc201cce..11650c5f98 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -10,7 +10,7 @@ th {border-top: 1px solid scale-color-diff();} td {border-bottom: 1px solid scale-color-diff(); border-top: 1px solid scale-color-diff();} tr:hover { background-color: darken($secondary, 2.5%); } - tr.selected { background-color: lighten($primary, 50%); } + tr.selected { background-color: lighten($primary, 80%); } .filters input { margin-bottom: 0; } } From c90668ae532971cd9a904900c7be970719c05099 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 2 Dec 2014 17:03:12 -0500 Subject: [PATCH 030/144] FIX: Better protection for invites scrolling --- .../javascripts/discourse/controllers/user-invited.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/controllers/user-invited.js.es6 b/app/assets/javascripts/discourse/controllers/user-invited.js.es6 index 4d5fea2f4e..7499b2e5a4 100644 --- a/app/assets/javascripts/discourse/controllers/user-invited.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-invited.js.es6 @@ -80,7 +80,7 @@ export default Ember.ObjectController.extend({ var self = this; var model = self.get('model'); - if(self.get('canLoadMore')) { + if (self.get('canLoadMore') && !self.get('invitesLoading')) { self.set('invitesLoading', true); Discourse.Invite.findInvitedBy(self.get('user'), self.get('searchTerm'), model.invites.length).then(function(invite_model) { self.set('invitesLoading', false); From ea37946d00f09de4d8f03e7893e329ceddb9991b Mon Sep 17 00:00:00 2001 From: Kris Aubuchon Date: Tue, 2 Dec 2014 17:10:14 -0500 Subject: [PATCH 031/144] a few very minor visual tweaks --- app/assets/stylesheets/common/base/_topic-list.scss | 2 +- app/assets/stylesheets/common/base/header.scss | 1 + app/assets/stylesheets/common/base/topic-post.scss | 3 +-- app/assets/stylesheets/mobile/discourse.scss | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/common/base/_topic-list.scss b/app/assets/stylesheets/common/base/_topic-list.scss index 29ee46e008..de9501cdf8 100644 --- a/app/assets/stylesheets/common/base/_topic-list.scss +++ b/app/assets/stylesheets/common/base/_topic-list.scss @@ -1,6 +1,6 @@ .show-more { position: absolute; - top: 5px; + top: 4px; width: 100%; } diff --git a/app/assets/stylesheets/common/base/header.scss b/app/assets/stylesheets/common/base/header.scss index 45b6311b3c..38b5ada1d4 100644 --- a/app/assets/stylesheets/common/base/header.scss +++ b/app/assets/stylesheets/common/base/header.scss @@ -266,6 +266,7 @@ .search-context { padding: 0 5px; + label { margin-bottom: 0; } } .searching { diff --git a/app/assets/stylesheets/common/base/topic-post.scss b/app/assets/stylesheets/common/base/topic-post.scss index 0626826bf3..d524b5e045 100644 --- a/app/assets/stylesheets/common/base/topic-post.scss +++ b/app/assets/stylesheets/common/base/topic-post.scss @@ -118,7 +118,7 @@ aside.quote { } .wiki .topic-body { - background-color: scale-color($wiki, $lightness: 95%); + background-color: dark-light-diff($wiki, $secondary, 95%, -50%); } .post-info { @@ -140,7 +140,6 @@ aside.quote { } } - pre { code { white-space: pre-wrap; diff --git a/app/assets/stylesheets/mobile/discourse.scss b/app/assets/stylesheets/mobile/discourse.scss index af61f9c35e..7cf2887525 100644 --- a/app/assets/stylesheets/mobile/discourse.scss +++ b/app/assets/stylesheets/mobile/discourse.scss @@ -91,7 +91,7 @@ blockquote { .topic-status { i { font-size: 20px; - color: darken($secondary, 60%); + color: dark-light-diff($secondary, $primary, 40%, -20%); } } } From 44c1a895b5b55c0e687c9f0cfb254da540057362 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Tue, 2 Dec 2014 21:25:43 -0800 Subject: [PATCH 032/144] move two user related "other" settings to "user" --- config/site_settings.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/config/site_settings.yml b/config/site_settings.yml index 2b6eb17b47..c076ba4254 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -285,6 +285,10 @@ users: default: false email_token_valid_hours: 24 email_token_grace_period_hours: 0 + purge_inactive_users_grace_period_days: 7 + public_user_custom_fields: + type: list + default: '' posting: min_post_length: @@ -792,10 +796,6 @@ uncategorized: notify_about_flags_after: 48 - public_user_custom_fields: - type: list - default: '' - enable_cdn_js_debugging: false show_create_topics_notice: @@ -807,7 +807,6 @@ uncategorized: default: true disable_edit_notifications: false - purge_inactive_users_grace_period_days: 7 company_full_name: 'My Unconfigured Forum Ltd.' company_short_name: 'Unconfigured Forum' From ea269ccfb215ecba7f11c28bbb70f76e6aa5db01 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Tue, 2 Dec 2014 21:36:25 -0800 Subject: [PATCH 033/144] rename purge_inactive to purge_unactivated --- app/jobs/scheduled/purge_inactive.rb | 2 +- app/models/user.rb | 10 +++------- config/locales/server.en.yml | 2 +- config/locales/server.es.yml | 2 +- config/locales/server.fi.yml | 2 +- config/locales/server.fr.yml | 2 +- config/locales/server.he.yml | 2 +- config/locales/server.ko.yml | 2 +- config/locales/server.pt_BR.yml | 2 +- config/locales/server.sq.yml | 2 +- config/locales/server.zh_CN.yml | 2 +- config/site_settings.yml | 2 +- spec/models/user_spec.rb | 6 +++--- 13 files changed, 17 insertions(+), 21 deletions(-) diff --git a/app/jobs/scheduled/purge_inactive.rb b/app/jobs/scheduled/purge_inactive.rb index ee5e30a43b..a6615f5fe2 100644 --- a/app/jobs/scheduled/purge_inactive.rb +++ b/app/jobs/scheduled/purge_inactive.rb @@ -3,7 +3,7 @@ module Jobs every 1.day def execute(args) - User.purge_inactive + User.purge_unactivated end end end diff --git a/app/models/user.rb b/app/models/user.rb index 8a846ee2d9..7fc88a0b6f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -791,16 +791,12 @@ class User < ActiveRecord::Base end end - # Delete inactive accounts that are over a week old - def self.purge_inactive + # Delete unactivated accounts (without verified email) that are over a week old + def self.purge_unactivated - # You might be wondering why this query matches on post_count = 0. The reason - # is a long time ago we had a bug where users could post before being activated - # and some sites still have those records which can't be purged. to_destroy = User.where(active: false) .joins('INNER JOIN user_stats AS us ON us.user_id = users.id') - .where("created_at < ?", SiteSetting.purge_inactive_users_grace_period_days.days.ago) - .where('us.post_count = 0') + .where("created_at < ?", SiteSetting.purge_unactivated_users_grace_period_days.days.ago) .where('NOT admin AND NOT moderator') .limit(100) diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 233d0a0739..be11d2e8f2 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -845,7 +845,7 @@ en: clean_up_uploads: "Remove orphan unreferenced uploads to prevent illegal hosting. WARNING: you may want to back up of your /uploads directory before enabling this setting." clean_orphan_uploads_grace_period_hours: "Grace period (in hours) before an orphan upload is removed." purge_deleted_uploads_grace_period_days: "Grace period (in days) before a deleted upload is erased." - purge_inactive_users_grace_period_days: "Grace period (in days) before a user who has not activated their account is deleted." + purge_unactivated_users_grace_period_days: "Grace period (in days) before a user who has not activated their account is deleted." enable_s3_uploads: "Place uploads on Amazon S3 storage. IMPORTANT: requires valid S3 credentials (both access key id & secret access key)." s3_use_iam_profile: 'Use AWS EC2 IAM role to retrieve keys. NOTE: enabling will override "s3 access key id" and "s3 secret access key" settings.' s3_upload_bucket: "The Amazon S3 bucket name that files will be uploaded into. WARNING: must be lowercase, no periods, no underscores." diff --git a/config/locales/server.es.yml b/config/locales/server.es.yml index 44121790b5..d2ff1c237f 100644 --- a/config/locales/server.es.yml +++ b/config/locales/server.es.yml @@ -749,7 +749,7 @@ es: clean_up_uploads: "Eliminar subidas huérfanas sin referencia para prevenir hosting ilegal. AVISO: antes de habilitar esta opción quizá quieres hacer un backup de tu directorio de /uploads" clean_orphan_uploads_grace_period_hours: "Período de gracia (en horas) antes de que una subida huérfana sea eliminada." purge_deleted_uploads_grace_period_days: "Período de gracia (en días) antes de que una subida eliminada sea borrada totalmente." - purge_inactive_users_grace_period_days: "Periodo de gracia (en días) durante los cuales un usuario que no haya activado su cuenta no será aún eliminado." + purge_unactivated_users_grace_period_days: "Periodo de gracia (en días) durante los cuales un usuario que no haya activado su cuenta no será aún eliminado." enable_s3_uploads: "Coloca los archivos subidos en el almacén Amazon S3. IMPORTANTE: requiere de credenciales de S3 validas. (ambas clave de acceso y clave de acceso secreta)." s3_use_iam_profile: 'Usar el rol de AWS EC2 IAM para descargar las llaves. NOTA: habilitando esta opción ignorará la "llave de acceso s3" y "la llave de acceso secreta s3".' s3_upload_bucket: "El nombre del bucket Amazon S3 donde se subirán los archivos. AVISO: debe ser en minúsculas, sin puntos ni guiones bajos." diff --git a/config/locales/server.fi.yml b/config/locales/server.fi.yml index d603543278..7192c3c767 100644 --- a/config/locales/server.fi.yml +++ b/config/locales/server.fi.yml @@ -733,7 +733,7 @@ fi: clean_up_uploads: "Poista orpoutuneet liitetiedostot, joita ei käytetä viesteissä, laittoman hostauksen estämiseksi. VAROITUS: kannattaa varmuuskopioida /uploads kansio ennen tämän asetuksen ottamista käyttöön." clean_orphan_uploads_grace_period_hours: "Varoaika (tunteina) kunnes orpoutuneet liitetiedostot poistetaan" purge_deleted_uploads_grace_period_days: "Varoaika (päivinä) kunnes poistettu liitetiedosto tuhotaan." - purge_inactive_users_grace_period_days: "Varoaika (päivinä) kunnes aktivoimaton käyttäjätili tuhotaan." + purge_unactivated_users_grace_period_days: "Varoaika (päivinä) kunnes aktivoimaton käyttäjätili tuhotaan." enable_s3_uploads: "Lataa liitetiedostot Amazon S3:een. Tärkeää: edellyttää toimivat S3 kirjautumistiedot (access key id ja secret access key)." s3_use_iam_profile: 'Käytä AWS EC2 IAM roolia avainten hakuun. HUOM: käyttöönotto korvaa "s3 access key id" ja "s3 secret access key" asetukset.' s3_access_key_id: "Amazon S3 access key id, jota käytetään kuvien sijoittamisessa." diff --git a/config/locales/server.fr.yml b/config/locales/server.fr.yml index 25928ab069..96256d502d 100644 --- a/config/locales/server.fr.yml +++ b/config/locales/server.fr.yml @@ -744,7 +744,7 @@ fr: clean_up_uploads: "Retirer les fichiers téléchargés orphelins pour prévenir les hébergements illégaux. ATTENTION: vous devriez faire une sauvegarde de votre répertoire /uploads avant d'activer ce paramètre." clean_orphan_uploads_grace_period_hours: "La période de grâce (en heures) avant qu'un fichier envoyé orphelin soit retiré." purge_deleted_uploads_grace_period_days: "La période de grâce (en jours) avant qu'un fichier envoyé et supprimé soit effacé." - purge_inactive_users_grace_period_days: "Période de grâce (en jours) avant qu'un utilisateur qui n'a pas activé son compte soit supprimé." + purge_unactivated_users_grace_period_days: "Période de grâce (en jours) avant qu'un utilisateur qui n'a pas activé son compte soit supprimé." enable_s3_uploads: "Placez les fichiers envoyés sur un stockage Amazon S3. IMPORTANT: nécessite un accès valide à S3 (l'identifiant et la clé secrète)." s3_use_iam_profile: 'Utiliser un role AWS EC2 IAM pour la récupération des clés. NOTE: si activé, surcharge les paramètres "s3 access key id" et "s3 secret access key".' s3_upload_bucket: "Le nom du bucket Amazon S3 qui contiendra les fichiers téléchargés. ATTENTION : doit être en minuscule, sans points et sans caractères de soulignement." diff --git a/config/locales/server.he.yml b/config/locales/server.he.yml index bd08cd1378..0c870d5586 100644 --- a/config/locales/server.he.yml +++ b/config/locales/server.he.yml @@ -726,7 +726,7 @@ he: clean_up_uploads: "הסירו העלאות יתומות וללא הפניה כדי למנוע אירוח בלתי חוקי של חומר. אזהרה: אתם עלולי לרצות לגבות את תיקיית ה-/uploads שלכם לפנו שתאפשרו הגדרה זו." clean_orphan_uploads_grace_period_hours: "Grace period (in hours) before an orphan upload is removed." purge_deleted_uploads_grace_period_days: "Grace period (in days) before a deleted upload is erased." - purge_inactive_users_grace_period_days: "תקופת המתנה (בימים) לפני שמשתמש שלא הפעיל את החשבון שלו יימחק." + purge_unactivated_users_grace_period_days: "תקופת המתנה (בימים) לפני שמשתמש שלא הפעיל את החשבון שלו יימחק." enable_s3_uploads: "אחסן העלאות (uploads) על תשתית של Amazon S3. חשוב: מצריך מפתח גישה + מפתח גישה סודי שיהיו חוקיים." s3_use_iam_profile: 'השתמש ב-AWS EC2 IAM role על מנת לאחזר מפתחות. שימו לב: איפשור של זה ידרוס את ההגדרות "S3 access key id" וכן את "s3 secret access key".' s3_access_key_id: "מפתח הגישה (access key id) של Amazon S3 שישמש להעלאת התמונות." diff --git a/config/locales/server.ko.yml b/config/locales/server.ko.yml index 01a1c6b9c6..56edfb3e29 100644 --- a/config/locales/server.ko.yml +++ b/config/locales/server.ko.yml @@ -691,7 +691,7 @@ ko: clean_up_uploads: "불법 호스팅을 막기 위해서 참조되지 않은 업로드 파일은 제거한다. 주의 : 이 설정을 활성화 하기 전에 `/uploads` 디렉토리를 백업하는 것이 좋다." clean_orphan_uploads_grace_period_hours: "참조되지 않은 업로드 파일을 제거하기 전 기간(시간)" purge_deleted_uploads_grace_period_days: "참조되지 않은 업로드 파일을 완전 삭제하지 전 기간(일)" - purge_inactive_users_grace_period_days: "활성화 되지 않은 사용자를 삭제하기 까지의 기간(일)" + purge_unactivated_users_grace_period_days: "활성화 되지 않은 사용자를 삭제하기 까지의 기간(일)" s3_access_key_id: "이미지를 업로드 할 때 사용할 Amazon S3의 access key id" s3_secret_access_key: "이미지를 업로드 할 때 사용할 Amazon S3의 secret access key" s3_region: "이미지를 업로드 할 때 사용할 Amazon S3 region" diff --git a/config/locales/server.pt_BR.yml b/config/locales/server.pt_BR.yml index f7d4538dc2..49e29d31d6 100644 --- a/config/locales/server.pt_BR.yml +++ b/config/locales/server.pt_BR.yml @@ -661,7 +661,7 @@ pt_BR: clean_up_uploads: "Remover envios sem referência para evitar hospedagem ilegal. AVISO: você pode querer fazer um backup do seu diretório de /uploads antes de habilitar essa configuração." clean_orphan_uploads_grace_period_hours: "Carência (em horas) antes de um upload órfão ser removido." purge_deleted_uploads_grace_period_days: "Carência (em dias) antes que um upload excluído seja apagado." - purge_inactive_users_grace_period_days: "Carência (em dias) antes de um usuário que não tenha ativado sua conta seja deletado." + purge_unactivated_users_grace_period_days: "Carência (em dias) antes de um usuário que não tenha ativado sua conta seja deletado." min_trust_to_create_topic: "O nível de confiança mínimo necessário para criar um novo tópico." min_trust_to_edit_wiki_post: "O nível de confiança mínimo necessário para editar uma postagem marcada como wiki." title_fancy_entities: "Converter caracteres ASCII comuns em entidades HTML nos títulos dos tópicos, ala SmartyPants http://daringfireball.net/projects/smartypants/" diff --git a/config/locales/server.sq.yml b/config/locales/server.sq.yml index 9418e3cccd..d1e69b1e1d 100644 --- a/config/locales/server.sq.yml +++ b/config/locales/server.sq.yml @@ -749,7 +749,7 @@ sq: clean_up_uploads: "Remove orphan unreferenced uploads to prevent illegal hosting. WARNING: you may want to back up of your /uploads directory before enabling this setting." clean_orphan_uploads_grace_period_hours: "Grace period (in hours) before an orphan upload is removed." purge_deleted_uploads_grace_period_days: "Grace period (in days) before a deleted upload is erased." - purge_inactive_users_grace_period_days: "Grace period (in days) before a user who has not activated their account is deleted." + purge_unactivated_users_grace_period_days: "Grace period (in days) before a user who has not activated their account is deleted." enable_s3_uploads: "Place uploads on Amazon S3 storage. IMPORTANT: requires valid S3 credentials (both access key id & secret access key)." s3_use_iam_profile: 'Use AWS EC2 IAM role to retrieve keys. NOTE: enabling will override "s3 access key id" and "s3 secret access key" settings.' s3_upload_bucket: "The Amazon S3 bucket name that files will be uploaded into. WARNING: must be lowercase, no periods, no underscores." diff --git a/config/locales/server.zh_CN.yml b/config/locales/server.zh_CN.yml index 237fae728d..6a04252c2f 100644 --- a/config/locales/server.zh_CN.yml +++ b/config/locales/server.zh_CN.yml @@ -719,7 +719,7 @@ zh_CN: clean_up_uploads: "移除孤立的已上传资料。警告:您可能想要在启用这个设定前备份一下 /uploads 目录。" clean_orphan_uploads_grace_period_hours: "删除孤立上传资料的宽限期(单位:小时)" purge_deleted_uploads_grace_period_days: "移除已删除的孤立上传资料的宽限期(单位:小时)" - purge_inactive_users_grace_period_days: "删除不活跃用户账户的宽限期(单位:天)。" + purge_unactivated_users_grace_period_days: "删除不活跃用户账户的宽限期(单位:天)。" enable_s3_uploads: "上传至 Amazon S3 存储的地址。重要:需要有效的 S3 验证资料(包括 access key id & secret access key)。" s3_use_iam_profile: '使用 AWS EC2 IAM 角色来获得 key。注意:启用这个会覆盖“S3 access key id”和“S3 secret access key” 设置。' s3_upload_bucket: "上传文件保存于 Amazon S3 的 bucket 名字。警告:必须为小写,无句点,无下划线。" diff --git a/config/site_settings.yml b/config/site_settings.yml index c076ba4254..97bf9a60af 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -285,7 +285,7 @@ users: default: false email_token_valid_hours: 24 email_token_grace_period_hours: 0 - purge_inactive_users_grace_period_days: 7 + purge_unactivated_users_grace_period_days: 7 public_user_custom_fields: type: list default: '' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d2d1d79afe..ce009f1cb5 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1155,13 +1155,13 @@ describe User do end end - describe "#purge_inactive" do + describe "#purge_unactivated" do let!(:user) { Fabricate(:user) } let!(:inactive) { Fabricate(:user, active: false) } let!(:inactive_old) { Fabricate(:user, active: false, created_at: 1.month.ago) } - it 'should only remove old, inactive users' do - User.purge_inactive + it 'should only remove old, unactivated users' do + User.purge_unactivated all_users = User.all all_users.include?(user).should == true all_users.include?(inactive).should == true From a05408ac9d34c96c530e65bf17d69d52e3b56324 Mon Sep 17 00:00:00 2001 From: Jeff Atwood Date: Tue, 2 Dec 2014 21:39:54 -0800 Subject: [PATCH 034/144] minor copyedit --- config/locales/server.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index be11d2e8f2..b98c507f12 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -47,7 +47,7 @@ en: via: "%{username} via %{site_name}" is_reserved: "is reserved" - purge_reason: "Automatically deleted due to being old and unverified" + purge_reason: "Automatically deleted as abandoned, unactivated account" disable_remote_images_download_reason: "Remote images download was disabled because there wasn't enough disk space available." errors: From f84bdfdde3be6d9d9a87cb3a0f3818d2fc3af84f Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Wed, 3 Dec 2014 13:12:05 +0530 Subject: [PATCH 035/144] FIX: if full user name is not provided, username should be present in email From header --- app/mailers/user_notifications.rb | 4 ++-- spec/mailers/user_notifications_spec.rb | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index 9192ea6e7c..218247690d 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -127,7 +127,7 @@ class UserNotifications < ActionMailer::Base title: post.topic.title, post: post, username: post.user.username, - from_alias: SiteSetting.enable_email_names ? post.user.name : post.user.username, + from_alias: (SiteSetting.enable_email_names && !post.user.name.empty?) ? post.user.name : post.user.username, allow_reply_by_email: true, use_site_subject: true, add_re_to_subject: true, @@ -173,7 +173,7 @@ class UserNotifications < ActionMailer::Base user_name = @notification.data_hash[:original_username] if @post && SiteSetting.enable_email_names - user_name = User.find_by(id: @post.user_id).name + user_name = User.find_by(id: @post.user_id).name if !User.find_by(id: @post.user_id).name.empty? end notification_type = opts[:notification_type] || Notification.types[@notification.notification_type].to_s diff --git a/spec/mailers/user_notifications_spec.rb b/spec/mailers/user_notifications_spec.rb index a8ddc4246d..fa03d5ac71 100644 --- a/spec/mailers/user_notifications_spec.rb +++ b/spec/mailers/user_notifications_spec.rb @@ -131,11 +131,11 @@ describe UserNotifications do end describe '.user_posted' do - let(:response_by_user) { Fabricate(:user, name: "John Doe") } + let(:response_by_user) { Fabricate(:user, name: "John Doe", username: "john") } let(:post) { Fabricate(:post) } let(:response) { Fabricate(:post, topic: post.topic, user: response_by_user)} let(:user) { Fabricate(:user) } - let(:notification) { Fabricate(:notification, user: user) } + let(:notification) { Fabricate(:notification, user: user, data: {original_username: response_by_user.username}.to_json) } it 'generates a correct email' do SiteSetting.stubs(:enable_email_names).returns(false) @@ -144,6 +144,9 @@ describe UserNotifications do # from should not include full user name if "show user full names" is disabled expect(mail[:from].display_names).to_not eql(['John Doe']) + # from should include username if "show user full names" is disabled + expect(mail[:from].display_names).to eql(['john']) + # subject should not include category name expect(mail.subject).not_to match(/Uncategorized/) @@ -160,18 +163,18 @@ describe UserNotifications do end describe '.user_private_message' do - let(:response_by_user) { Fabricate(:user, name: "John Doe") } + let(:response_by_user) { Fabricate(:user, name: "", username: "john") } let(:topic) { Fabricate(:private_message_topic) } let(:response) { Fabricate(:post, topic: topic, user: response_by_user)} let(:user) { Fabricate(:user) } - let(:notification) { Fabricate(:notification, user: user) } + let(:notification) { Fabricate(:notification, user: user, data: {original_username: response_by_user.username}.to_json) } it 'generates a correct email' do SiteSetting.stubs(:enable_email_names).returns(true) mail = UserNotifications.user_private_message(response.user, post: response, notification: notification) - # from should include full user name - expect(mail[:from].display_names).to eql(['John Doe']) + # from should include username if full user name is not provided + expect(mail[:from].display_names).to eql(['john']) # subject should include "[PM]" expect(mail.subject).to match("[PM]") From 7edb88a5a8f1d0d98537f1e7ecb36a04f8fd1199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 3 Dec 2014 11:51:49 +0100 Subject: [PATCH 036/144] FIX: change top score formula Adds more weight to `likes` (it's now the same weight as `post_count`) --- app/models/top_topic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/top_topic.rb b/app/models/top_topic.rb index cad2eebc97..9905a7b327 100644 --- a/app/models/top_topic.rb +++ b/app/models/top_topic.rb @@ -119,7 +119,7 @@ class TopTopic < ActiveRecord::Base WITH top AS ( SELECT CASE WHEN topics.created_at < :from THEN 0 - ELSE log(greatest(#{period}_views_count, 1)) + #{period}_likes_count + #{period}_posts_count * 2 + ELSE log(greatest(#{period}_views_count, 1)) + #{period}_likes_count * 2 + #{period}_posts_count * 2 END AS score, topic_id FROM top_topics From acc62f2ec2c10dc5a6295ceb19123b900774b81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 3 Dec 2014 12:47:28 +0100 Subject: [PATCH 037/144] SECURITY: prevent direct download of backups --- config/nginx.sample.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/nginx.sample.conf b/config/nginx.sample.conf index 39a02ef632..434a3ec88b 100644 --- a/config/nginx.sample.conf +++ b/config/nginx.sample.conf @@ -58,6 +58,11 @@ server { # further more etags are based on the file in nginx not sha of data # use dates, it solves the problem fine even cross server etag off; + + # prevent direct download of backups + location ^~ /backups/ { + internal; + } location / { root $public; From f9f54e2626ebe550908b694c46f0914fa6789853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 3 Dec 2014 13:00:02 +0100 Subject: [PATCH 038/144] refactor fix in 67c4c90159428d700766ac610ca374d764cea6a7 --- app/assets/javascripts/admin/models/admin_user.js | 4 +--- .../discourse/controllers/user-card.js.es6 | 13 +++---------- app/assets/javascripts/discourse/models/user.js | 3 +++ 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/admin/models/admin_user.js b/app/assets/javascripts/admin/models/admin_user.js index c89b540973..816690031b 100644 --- a/app/assets/javascripts/admin/models/admin_user.js +++ b/app/assets/javascripts/admin/models/admin_user.js @@ -298,9 +298,7 @@ Discourse.AdminUser = Discourse.User.extend({ }); }, - deleteForbidden: function() { - return (!this.get('can_be_deleted') || this.get('post_count') > 0); - }.property('post_count'), + deleteForbidden: Em.computed.not("canBeDeleted"), deleteExplanation: function() { if (this.get('deleteForbidden')) { diff --git a/app/assets/javascripts/discourse/controllers/user-card.js.es6 b/app/assets/javascripts/discourse/controllers/user-card.js.es6 index 2ea6b91e46..369bf7c81a 100644 --- a/app/assets/javascripts/discourse/controllers/user-card.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-card.js.es6 @@ -20,8 +20,7 @@ export default ObjectController.extend({ isSuspended: Em.computed.notEmpty('user.suspend_reason'), showBadges: Discourse.computed.setting('enable_badges'), showMoreBadges: Em.computed.gt('moreBadgesCount', 0), - canDelete: Em.computed.not("user.deleteForbidden"), - showDelete: Em.computed.and("viewingAdmin", "showName", "canDelete"), + showDelete: Em.computed.and("viewingAdmin", "showName", "user.canBeDeleted"), moreBadgesCount: function() { return this.get('user.badge_count') - this.get('user.featured_user_badges.length'); @@ -74,14 +73,8 @@ export default ObjectController.extend({ self.set('cardTarget', target); Discourse.User.findByUsername(username).then(function (user) { - - // A bit hacky. If viewing admin, wrap it in Discourse.AdminUser - // TODO: Restructure this to be cleaner - var wrapped = user; - if (self.get('viewingAdmin')) { - wrapped = Discourse.AdminUser.create(user); - } - self.setProperties({ user: wrapped, avatar: user, visible: true}); + user = Discourse.User.create(user); + self.setProperties({ user: user, avatar: user, visible: true}); self.appEvents.trigger('usercard:shown'); }).finally(function(){ self.set('userLoading', null); diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index 7088433927..47e36a415e 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -11,6 +11,9 @@ Discourse.User = Discourse.Model.extend({ hasPMs: Em.computed.gt("private_messages_stats.all", 0), hasStartedPMs: Em.computed.gt("private_messages_stats.mine", 0), hasUnreadPMs: Em.computed.gt("private_messages_stats.unread", 0), + hasPosted: Em.computed.gt("post_count", 0), + hasNotPosted: Em.computed.not("hasPosted"), + canBeDeleted: Em.computed.and("can_be_deleted", "hasNotPosted"), /** The user's stream From 0f0a329e7cca1e0361132d559b68026569b8698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 3 Dec 2014 14:55:43 +0100 Subject: [PATCH 039/144] FIX: private message button wasn't adding the recipient (cc @gdpelican) --- app/assets/javascripts/discourse/routes/application.js.es6 | 2 +- app/assets/javascripts/discourse/routes/user.js.es6 | 2 +- app/assets/javascripts/discourse/templates/user/user.hbs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/routes/application.js.es6 b/app/assets/javascripts/discourse/routes/application.js.es6 index ca598b7748..83f8a53a7e 100644 --- a/app/assets/javascripts/discourse/routes/application.js.es6 +++ b/app/assets/javascripts/discourse/routes/application.js.es6 @@ -15,7 +15,7 @@ var ApplicationRoute = Discourse.Route.extend({ composePrivateMessage: function(user) { var self = this; this.transitionTo('userActivity', user).then(function () { - self.controllerFor('user-activity').send('composePrivateMessage'); + self.controllerFor('user-activity').send('composePrivateMessage', user); }); }, diff --git a/app/assets/javascripts/discourse/routes/user.js.es6 b/app/assets/javascripts/discourse/routes/user.js.es6 index ac4ddb49cf..e72b26d9b7 100644 --- a/app/assets/javascripts/discourse/routes/user.js.es6 +++ b/app/assets/javascripts/discourse/routes/user.js.es6 @@ -16,7 +16,7 @@ export default Discourse.Route.extend({ }, composePrivateMessage: function(user) { - var recipient = user ? user.username : ''; + var recipient = user ? user.get('username') : ''; return this.controllerFor('composer').open({ action: Discourse.Composer.PRIVATE_MESSAGE, usernames: recipient, diff --git a/app/assets/javascripts/discourse/templates/user/user.hbs b/app/assets/javascripts/discourse/templates/user/user.hbs index 3f8323efe4..a12eb5946d 100644 --- a/app/assets/javascripts/discourse/templates/user/user.hbs +++ b/app/assets/javascripts/discourse/templates/user/user.hbs @@ -39,7 +39,7 @@