diff --git a/Gemfile b/Gemfile index 49ec1888e..62a0e1478 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,12 @@ gem 'rails_autolink' gem 'doorkeeper' gem 'rabl' gem 'oj' +gem 'hiredis' gem 'redis', '~>3.2' +gem 'fast_blank' +gem 'htmlentities' +gem 'message_bus' +gem 'onebox' group :development, :test do gem 'rspec-rails' @@ -51,6 +56,7 @@ group :development do gem 'rubocop', require: false gem 'better_errors' gem 'binding_of_caller' + gem 'rack-mini-profiler' end group :production do diff --git a/Gemfile.lock b/Gemfile.lock index 6550ff101..d51b9fffd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -85,6 +85,7 @@ GEM erubis (2.7.0) execjs (2.6.0) fabrication (2.14.1) + fast_blank (1.0.0) font-awesome-sass (4.5.0) sass (>= 3.2) fuubar (2.0.0) @@ -105,11 +106,13 @@ GEM html2haml (>= 1.0.1) railties (>= 4.0.1) hashdiff (0.3.0) + hiredis (0.6.1) html2haml (2.0.0) erubis (~> 2.7.0) haml (~> 4.0.0) nokogiri (~> 1.6.0) ruby_parser (~> 3.5) + htmlentities (4.3.4) http (1.0.2) addressable (~> 2.3) http-cookie (~> 1.0) @@ -133,15 +136,26 @@ GEM nokogiri (>= 1.5.9) mail (2.6.3) mime-types (>= 1.16, < 3) + message_bus (1.1.1) + rack (>= 1.1.3) + redis method_source (0.8.2) mime-types (2.99) mimemagic (0.3.0) mini_portile2 (2.0.0) minitest (5.8.4) + moneta (0.8.0) multi_json (1.11.2) + mustache (1.0.2) nokogiri (1.6.7.2) mini_portile2 (~> 2.0.0.rc2) oj (2.14.5) + onebox (1.5.35) + htmlentities (~> 4.3.4) + moneta (~> 0.8) + multi_json (~> 1.11) + mustache + nokogiri (~> 1.6.6) orm_adapter (0.5.0) ostatus2 (0.1.1) addressable (~> 2.4) @@ -171,6 +185,8 @@ GEM rabl (0.12.0) activesupport (>= 2.3.14) rack (1.6.4) + rack-mini-profiler (0.9.9.2) + rack (>= 1.2.0) rack-test (0.6.3) rack (>= 1.0) rails (4.2.5.1) @@ -309,15 +325,20 @@ DEPENDENCIES doorkeeper dotenv-rails fabrication + fast_blank font-awesome-sass fuubar goldfinger haml-rails + hiredis + htmlentities http jbuilder (~> 2.0) jquery-rails + message_bus nokogiri oj + onebox ostatus2 paperclip (~> 4.3) paranoia (~> 2.0) @@ -326,6 +347,7 @@ DEPENDENCIES puma quiet_assets rabl + rack-mini-profiler rails (= 4.2.5.1) rails_12factor rails_autolink diff --git a/app/controllers/api/accounts_controller.rb b/app/controllers/api/accounts_controller.rb index fc4c9d681..ac16ed7c1 100644 --- a/app/controllers/api/accounts_controller.rb +++ b/app/controllers/api/accounts_controller.rb @@ -1,6 +1,6 @@ class Api::AccountsController < ApiController before_action :set_account - before_action :authenticate_user! + before_action :doorkeeper_authorize! respond_to :json def show diff --git a/app/controllers/api/follows_controller.rb b/app/controllers/api/follows_controller.rb index acf627a07..9ec4f46b8 100644 --- a/app/controllers/api/follows_controller.rb +++ b/app/controllers/api/follows_controller.rb @@ -1,5 +1,5 @@ class Api::FollowsController < ApiController - before_action :authenticate_user! + before_action :doorkeeper_authorize! respond_to :json def create diff --git a/app/controllers/api/statuses_controller.rb b/app/controllers/api/statuses_controller.rb index 04128537a..951f7113a 100644 --- a/app/controllers/api/statuses_controller.rb +++ b/app/controllers/api/statuses_controller.rb @@ -1,5 +1,5 @@ class Api::StatusesController < ApiController - before_action :authenticate_user! + before_action :doorkeeper_authorize! respond_to :json def show diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index d24f63f27..80d084328 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -4,7 +4,7 @@ class ApiController < ApplicationController protected def current_resource_owner - User.find(doorkeeper_token.user_id) if doorkeeper_token + User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token end def current_user diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index 2a59553ab..60955a0a7 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -23,8 +23,9 @@ module StreamEntriesHelper def linkify(status) mention_hash = {} status.mentions.each { |m| mention_hash[m.acct] = m } + coder = HTMLEntities.new - auto_link(CGI.escapeHTML(status.text), link: :urls, html: { target: '_blank', rel: 'nofollow' }).gsub(Account::MENTION_RE) do |m| + auto_link(coder.encode(status.text), link: :urls, html: { target: '_blank', rel: 'nofollow' }).gsub(Account::MENTION_RE) do |m| account = mention_hash[Account::MENTION_RE.match(m)[1]] "#{m.split('@').first}@#{account.acct}" end.html_safe diff --git a/app/models/feed.rb b/app/models/feed.rb index a063ad05b..0c0b8ae2c 100644 --- a/app/models/feed.rb +++ b/app/models/feed.rb @@ -11,7 +11,7 @@ class Feed # If we're after most recent items and none are there, we need to precompute the feed return PrecomputeFeedService.new.(@type, @account).take(limit) if unhydrated.empty? && offset == 0 - Status.where(id: unhydrated).each { |status| status_map[status.id.to_s] = status } + Status.where(id: unhydrated).with_includes.with_counters.each { |status| status_map[status.id.to_s] = status } return unhydrated.map { |id| status_map[id] } end diff --git a/app/models/status.rb b/app/models/status.rb index 7e0c334ec..4fedad107 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -14,6 +14,9 @@ class Status < ActiveRecord::Base validates :account, presence: true validates :uri, uniqueness: true, unless: 'local?' + scope :with_counters, -> { select('statuses.*, (select count(r.id) from statuses as r where r.reblog_of_id = statuses.id) as reblogs_count, (select count(f.id) from favourites as f where f.status_id = statuses.id) as favourites_count') } + scope :with_includes, -> { includes(:account, reblog: :account, thread: :account) } + def local? self.uri.nil? end diff --git a/app/services/precompute_feed_service.rb b/app/services/precompute_feed_service.rb index 89b034404..bcc757222 100644 --- a/app/services/precompute_feed_service.rb +++ b/app/services/precompute_feed_service.rb @@ -18,11 +18,11 @@ class PrecomputeFeedService < BaseService end def home(account) - Status.where(account: [account] + account.following) + Status.where(account: [account] + account.following).with_includes.with_counts end def mentions(account) - Status.where(id: Mention.where(account: account).pluck(:status_id)) + Status.where(id: Mention.where(account: account).pluck(:status_id)).with_includes.with_counts end def key(type, id) diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml index 38986cf1f..6323501cc 100644 --- a/app/views/stream_entries/_status.html.haml +++ b/app/views/stream_entries/_status.html.haml @@ -24,10 +24,10 @@ .header__right .counter-btn{ class: reblogged_by_me_class(status) } %i.fa.fa-retweet - %span.counter-number= status.reblog? ? status.reblog.reblogs.count : status.reblogs.count + %span.counter-number= status.reblog? ? status.reblog.reblogs.count : status.reblogs_count .counter-btn{ class: favourited_by_me_class(status) } %i.fa.fa-star - %span.counter-number= status.reblog? ? status.reblog.favourites.count : status.favourites.count + %span.counter-number= status.reblog? ? status.reblog.favourites.count : status.favourites_count .content = status.reblog? ? (status.reblog.local? ? linkify(status.reblog) : status.reblog.content.html_safe) : (status.local? ? linkify(status) : status.content.html_safe) diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 7418ba24d..22a379b66 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -7,6 +7,12 @@ Doorkeeper.configure do current_user || redirect_to(new_user_session_url) end + resource_owner_from_credentials do |routes| + request.params[:user] = { email: request.params[:username], password: request.params[:password] } + request.env["devise.allow_params_authentication"] = true + request.env["warden"].authenticate!(scope: :user) + end + # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below. # admin_authenticator do # # Put your admin authentication logic here. @@ -90,7 +96,8 @@ Doorkeeper.configure do # http://tools.ietf.org/html/rfc6819#section-4.4.2 # http://tools.ietf.org/html/rfc6819#section-4.4.3 # - # grant_flows %w(authorization_code client_credentials) + + grant_flows %w(authorization_code password client_credentials) # Under some circumstances you might want to have applications auto-approved, # so that the user skips the authorization step.