Improving feed queries, switching API to doorkeeper authentication

This commit is contained in:
Eugen Rochko 2016-03-11 16:47:36 +01:00
parent b919f39b31
commit 447cfef62d
12 changed files with 50 additions and 11 deletions

View File

@ -30,7 +30,12 @@ gem 'rails_autolink'
gem 'doorkeeper' gem 'doorkeeper'
gem 'rabl' gem 'rabl'
gem 'oj' gem 'oj'
gem 'hiredis'
gem 'redis', '~>3.2' gem 'redis', '~>3.2'
gem 'fast_blank'
gem 'htmlentities'
gem 'message_bus'
gem 'onebox'
group :development, :test do group :development, :test do
gem 'rspec-rails' gem 'rspec-rails'
@ -51,6 +56,7 @@ group :development do
gem 'rubocop', require: false gem 'rubocop', require: false
gem 'better_errors' gem 'better_errors'
gem 'binding_of_caller' gem 'binding_of_caller'
gem 'rack-mini-profiler'
end end
group :production do group :production do

View File

@ -85,6 +85,7 @@ GEM
erubis (2.7.0) erubis (2.7.0)
execjs (2.6.0) execjs (2.6.0)
fabrication (2.14.1) fabrication (2.14.1)
fast_blank (1.0.0)
font-awesome-sass (4.5.0) font-awesome-sass (4.5.0)
sass (>= 3.2) sass (>= 3.2)
fuubar (2.0.0) fuubar (2.0.0)
@ -105,11 +106,13 @@ GEM
html2haml (>= 1.0.1) html2haml (>= 1.0.1)
railties (>= 4.0.1) railties (>= 4.0.1)
hashdiff (0.3.0) hashdiff (0.3.0)
hiredis (0.6.1)
html2haml (2.0.0) html2haml (2.0.0)
erubis (~> 2.7.0) erubis (~> 2.7.0)
haml (~> 4.0.0) haml (~> 4.0.0)
nokogiri (~> 1.6.0) nokogiri (~> 1.6.0)
ruby_parser (~> 3.5) ruby_parser (~> 3.5)
htmlentities (4.3.4)
http (1.0.2) http (1.0.2)
addressable (~> 2.3) addressable (~> 2.3)
http-cookie (~> 1.0) http-cookie (~> 1.0)
@ -133,15 +136,26 @@ GEM
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.6.3) mail (2.6.3)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
message_bus (1.1.1)
rack (>= 1.1.3)
redis
method_source (0.8.2) method_source (0.8.2)
mime-types (2.99) mime-types (2.99)
mimemagic (0.3.0) mimemagic (0.3.0)
mini_portile2 (2.0.0) mini_portile2 (2.0.0)
minitest (5.8.4) minitest (5.8.4)
moneta (0.8.0)
multi_json (1.11.2) multi_json (1.11.2)
mustache (1.0.2)
nokogiri (1.6.7.2) nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2) mini_portile2 (~> 2.0.0.rc2)
oj (2.14.5) 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) orm_adapter (0.5.0)
ostatus2 (0.1.1) ostatus2 (0.1.1)
addressable (~> 2.4) addressable (~> 2.4)
@ -171,6 +185,8 @@ GEM
rabl (0.12.0) rabl (0.12.0)
activesupport (>= 2.3.14) activesupport (>= 2.3.14)
rack (1.6.4) rack (1.6.4)
rack-mini-profiler (0.9.9.2)
rack (>= 1.2.0)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.2.5.1) rails (4.2.5.1)
@ -309,15 +325,20 @@ DEPENDENCIES
doorkeeper doorkeeper
dotenv-rails dotenv-rails
fabrication fabrication
fast_blank
font-awesome-sass font-awesome-sass
fuubar fuubar
goldfinger goldfinger
haml-rails haml-rails
hiredis
htmlentities
http http
jbuilder (~> 2.0) jbuilder (~> 2.0)
jquery-rails jquery-rails
message_bus
nokogiri nokogiri
oj oj
onebox
ostatus2 ostatus2
paperclip (~> 4.3) paperclip (~> 4.3)
paranoia (~> 2.0) paranoia (~> 2.0)
@ -326,6 +347,7 @@ DEPENDENCIES
puma puma
quiet_assets quiet_assets
rabl rabl
rack-mini-profiler
rails (= 4.2.5.1) rails (= 4.2.5.1)
rails_12factor rails_12factor
rails_autolink rails_autolink

View File

@ -1,6 +1,6 @@
class Api::AccountsController < ApiController class Api::AccountsController < ApiController
before_action :set_account before_action :set_account
before_action :authenticate_user! before_action :doorkeeper_authorize!
respond_to :json respond_to :json
def show def show

View File

@ -1,5 +1,5 @@
class Api::FollowsController < ApiController class Api::FollowsController < ApiController
before_action :authenticate_user! before_action :doorkeeper_authorize!
respond_to :json respond_to :json
def create def create

View File

@ -1,5 +1,5 @@
class Api::StatusesController < ApiController class Api::StatusesController < ApiController
before_action :authenticate_user! before_action :doorkeeper_authorize!
respond_to :json respond_to :json
def show def show

View File

@ -4,7 +4,7 @@ class ApiController < ApplicationController
protected protected
def current_resource_owner def current_resource_owner
User.find(doorkeeper_token.user_id) if doorkeeper_token User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end end
def current_user def current_user

View File

@ -23,8 +23,9 @@ module StreamEntriesHelper
def linkify(status) def linkify(status)
mention_hash = {} mention_hash = {}
status.mentions.each { |m| mention_hash[m.acct] = m } 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]] account = mention_hash[Account::MENTION_RE.match(m)[1]]
"#{m.split('@').first}<a href=\"#{url_for_target(account)}\" class=\"mention\">@<span>#{account.acct}</span></a>" "#{m.split('@').first}<a href=\"#{url_for_target(account)}\" class=\"mention\">@<span>#{account.acct}</span></a>"
end.html_safe end.html_safe

View File

@ -11,7 +11,7 @@ class Feed
# If we're after most recent items and none are there, we need to precompute the 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 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] } return unhydrated.map { |id| status_map[id] }
end end

View File

@ -14,6 +14,9 @@ class Status < ActiveRecord::Base
validates :account, presence: true validates :account, presence: true
validates :uri, uniqueness: true, unless: 'local?' 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? def local?
self.uri.nil? self.uri.nil?
end end

View File

@ -18,11 +18,11 @@ class PrecomputeFeedService < BaseService
end end
def home(account) def home(account)
Status.where(account: [account] + account.following) Status.where(account: [account] + account.following).with_includes.with_counts
end end
def mentions(account) 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 end
def key(type, id) def key(type, id)

View File

@ -24,10 +24,10 @@
.header__right .header__right
.counter-btn{ class: reblogged_by_me_class(status) } .counter-btn{ class: reblogged_by_me_class(status) }
%i.fa.fa-retweet %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) } .counter-btn{ class: favourited_by_me_class(status) }
%i.fa.fa-star %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 .content
= status.reblog? ? (status.reblog.local? ? linkify(status.reblog) : status.reblog.content.html_safe) : (status.local? ? linkify(status) : status.content.html_safe) = status.reblog? ? (status.reblog.local? ? linkify(status.reblog) : status.reblog.content.html_safe) : (status.local? ? linkify(status) : status.content.html_safe)

View File

@ -7,6 +7,12 @@ Doorkeeper.configure do
current_user || redirect_to(new_user_session_url) current_user || redirect_to(new_user_session_url)
end 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. # 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 # admin_authenticator do
# # Put your admin authentication logic here. # # 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.2
# http://tools.ietf.org/html/rfc6819#section-4.4.3 # 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, # Under some circumstances you might want to have applications auto-approved,
# so that the user skips the authorization step. # so that the user skips the authorization step.