From d7dc84439c60069a0cb9eeca81dc61c297a8667b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 29 Dec 2016 16:54:54 +0100 Subject: [PATCH] Add ability to use remote follow function on other sites --- app/assets/stylesheets/accounts.scss | 58 +++++++++++++++++++ app/assets/stylesheets/application.scss | 11 ++-- app/assets/stylesheets/forms.scss | 2 +- .../authorize_follow_controller.rb | 24 ++++++++ app/helpers/authorize_follow_helper.rb | 2 + app/views/accounts/_grid_card.html.haml | 2 +- app/views/authorize_follow/error.html.haml | 3 + app/views/authorize_follow/new.html.haml | 21 +++++++ .../oauth/authorizations/error.html.haml | 5 +- app/views/oauth/authorizations/new.html.haml | 39 +++++++------ app/views/oauth/authorizations/show.html.haml | 5 +- app/views/xrd/webfinger.json.rabl | 3 +- app/views/xrd/webfinger.xml.ruby | 1 + config/application.rb | 2 +- config/locales/en.yml | 5 ++ config/routes.rb | 4 ++ .../authorize_follow_controller_spec.rb | 6 ++ spec/helpers/authorize_follow_helper_spec.rb | 5 ++ 18 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 app/controllers/authorize_follow_controller.rb create mode 100644 app/helpers/authorize_follow_helper.rb create mode 100644 app/views/authorize_follow/error.html.haml create mode 100644 app/views/authorize_follow/new.html.haml create mode 100644 spec/controllers/authorize_follow_controller_spec.rb create mode 100644 spec/helpers/authorize_follow_helper_spec.rb diff --git a/app/assets/stylesheets/accounts.scss b/app/assets/stylesheets/accounts.scss index 7f33f178d..5d0963307 100644 --- a/app/assets/stylesheets/accounts.scss +++ b/app/assets/stylesheets/accounts.scss @@ -324,3 +324,61 @@ padding-bottom: 25px; cursor: default; } + +.account-card { + padding: 14px 10px; + background: #fff; + border-radius: 4px; + text-align: left; + box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); + + .detailed-status__display-name { + display: block; + overflow: hidden; + margin-bottom: 15px; + + & > div { + float: left; + margin-right: 10px; + width: 48px; + height: 48px; + } + + .avatar { + display: block; + border-radius: 4px; + } + + .display-name { + display: block; + max-width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + cursor: default; + + strong { + font-weight: 500; + color: #282c37; + } + + span { + font-size: 14px; + color: #9baec8; + } + } + + &:hover { + .display-name { + strong { + text-decoration: none; + } + } + } + } + + .account__header__content { + font-size: 14px; + color: #282c37; + } +} diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index d05ca3795..e4c550b81 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -214,11 +214,13 @@ body { .footer { text-align: center; margin-top: 30px; + font-size: 12px; + color: darken(#d9e1e8, 25%); .domain { - font-size: 12px; - font-weight: 400; - font-family: 'Roboto Mono', monospace; + //font-size: 12px; + font-weight: 500; + //font-family: 'Roboto Mono', monospace; a { color: inherit; @@ -227,13 +229,12 @@ body { } .powered-by { - font-size: 12px; font-weight: 400; - color: darken(#d9e1e8, 25%); a { color: inherit; text-decoration: underline; + font-weight: 500; &:hover { text-decoration: none; diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss index cf9b4fba6..e6d2e85a2 100644 --- a/app/assets/stylesheets/forms.scss +++ b/app/assets/stylesheets/forms.scss @@ -185,7 +185,7 @@ code { } } -.oauth-prompt { +.oauth-prompt, .follow-prompt { margin-bottom: 30px; text-align: center; color: #9baec8; diff --git a/app/controllers/authorize_follow_controller.rb b/app/controllers/authorize_follow_controller.rb new file mode 100644 index 000000000..a276250a4 --- /dev/null +++ b/app/controllers/authorize_follow_controller.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class AuthorizeFollowController < ApplicationController + layout 'public' + + before_action :authenticate_user! + + def new + @account = FollowRemoteAccountService.new.call(params[:acct]) + render :error if @account.nil? + end + + def create + @account = FollowService.new.call(current_account, params[:acct]).try(:target_account) + + if @account.nil? + render :error + else + redirect_to web_url("accounts/#{@account.id}") + end + rescue ActiveRecord::RecordNotFound, Mastodon::NotPermitted + render :error + end +end diff --git a/app/helpers/authorize_follow_helper.rb b/app/helpers/authorize_follow_helper.rb new file mode 100644 index 000000000..43659ccfa --- /dev/null +++ b/app/helpers/authorize_follow_helper.rb @@ -0,0 +1,2 @@ +module AuthorizeFollowHelper +end diff --git a/app/views/accounts/_grid_card.html.haml b/app/views/accounts/_grid_card.html.haml index dfd7a9f5e..dfdb23161 100644 --- a/app/views/accounts/_grid_card.html.haml +++ b/app/views/accounts/_grid_card.html.haml @@ -1,6 +1,6 @@ .account-grid-card .account-grid-card__header - .avatar= image_tag account.avatar.url( :original) + .avatar= image_tag account.avatar.url(:original) .name = link_to TagManager.instance.url_for(account) do %span.display_name= display_name(account) diff --git a/app/views/authorize_follow/error.html.haml b/app/views/authorize_follow/error.html.haml new file mode 100644 index 000000000..88d33b68d --- /dev/null +++ b/app/views/authorize_follow/error.html.haml @@ -0,0 +1,3 @@ +.form-container + .flash-message#error_explanation + = t('authorize_follow.error') diff --git a/app/views/authorize_follow/new.html.haml b/app/views/authorize_follow/new.html.haml new file mode 100644 index 000000000..7368b834a --- /dev/null +++ b/app/views/authorize_follow/new.html.haml @@ -0,0 +1,21 @@ +- content_for :page_title do + = t('authorize_follow.title', acct: @account.acct) + +.form-container + .follow-prompt + %h2= t('authorize_follow.prompt_html', self: current_account.username) + + .account-card + .detailed-status__display-name + %div + = image_tag @account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar' + + %span.display-name + %strong= display_name(@account) + %span= "@#{@account.acct}" + + .account__header__content= Formatter.instance.simplified_format(@account) + + = form_tag authorize_follow_path, method: :post, class: 'simple_form' do + = hidden_field_tag :acct, @account.acct + = button_tag t('authorize_follow.follow'), type: :submit diff --git a/app/views/oauth/authorizations/error.html.haml b/app/views/oauth/authorizations/error.html.haml index ee72d9740..408ca2b86 100644 --- a/app/views/oauth/authorizations/error.html.haml +++ b/app/views/oauth/authorizations/error.html.haml @@ -1,2 +1,3 @@ -.flash-message#error_explanation - = @pre_auth.error_response.body[:error_description] +.form-container + .flash-message#error_explanation + = @pre_auth.error_response.body[:error_description] diff --git a/app/views/oauth/authorizations/new.html.haml b/app/views/oauth/authorizations/new.html.haml index f058e2cce..1f951c272 100644 --- a/app/views/oauth/authorizations/new.html.haml +++ b/app/views/oauth/authorizations/new.html.haml @@ -1,25 +1,26 @@ - content_for :page_title do = t('doorkeeper.authorizations.new.title') -.oauth-prompt - %h2= t('doorkeeper.authorizations.new.prompt', client_name: @pre_auth.client.name) +.form-container + .oauth-prompt + %h2= t('doorkeeper.authorizations.new.prompt', client_name: @pre_auth.client.name) - %p - = t('doorkeeper.authorizations.new.able_to') - = @pre_auth.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.map { |s| "#{s}"}.to_sentence.html_safe + %p + = t('doorkeeper.authorizations.new.able_to') + = @pre_auth.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.map { |s| "#{s}"}.to_sentence.html_safe -= form_tag oauth_authorization_path, method: :post, class: 'simple_form' do - = hidden_field_tag :client_id, @pre_auth.client.uid - = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri - = hidden_field_tag :state, @pre_auth.state - = hidden_field_tag :response_type, @pre_auth.response_type - = hidden_field_tag :scope, @pre_auth.scope - = button_tag t('doorkeeper.authorizations.buttons.authorize'), type: :submit + = form_tag oauth_authorization_path, method: :post, class: 'simple_form' do + = hidden_field_tag :client_id, @pre_auth.client.uid + = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri + = hidden_field_tag :state, @pre_auth.state + = hidden_field_tag :response_type, @pre_auth.response_type + = hidden_field_tag :scope, @pre_auth.scope + = button_tag t('doorkeeper.authorizations.buttons.authorize'), type: :submit -= form_tag oauth_authorization_path, method: :delete, class: 'simple_form' do - = hidden_field_tag :client_id, @pre_auth.client.uid - = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri - = hidden_field_tag :state, @pre_auth.state - = hidden_field_tag :response_type, @pre_auth.response_type - = hidden_field_tag :scope, @pre_auth.scope - = button_tag t('doorkeeper.authorizations.buttons.deny'), type: :submit, class: 'negative' + = form_tag oauth_authorization_path, method: :delete, class: 'simple_form' do + = hidden_field_tag :client_id, @pre_auth.client.uid + = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri + = hidden_field_tag :state, @pre_auth.state + = hidden_field_tag :response_type, @pre_auth.response_type + = hidden_field_tag :scope, @pre_auth.scope + = button_tag t('doorkeeper.authorizations.buttons.deny'), type: :submit, class: 'negative' diff --git a/app/views/oauth/authorizations/show.html.haml b/app/views/oauth/authorizations/show.html.haml index 897a15cee..b56667f35 100644 --- a/app/views/oauth/authorizations/show.html.haml +++ b/app/views/oauth/authorizations/show.html.haml @@ -1,2 +1,3 @@ -.flash-message - %code= params[:code] +.form-container + .flash-message + %code= params[:code] diff --git a/app/views/xrd/webfinger.json.rabl b/app/views/xrd/webfinger.json.rabl index 0de17ac19..e637ed9d3 100644 --- a/app/views/xrd/webfinger.json.rabl +++ b/app/views/xrd/webfinger.json.rabl @@ -11,6 +11,7 @@ node(:links) do { rel: 'http://webfinger.net/rel/profile-page', type: 'text/html', href: TagManager.instance.url_for(@account) }, { rel: 'http://schemas.google.com/g/2010#updates-from', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }, { rel: 'salmon', href: api_salmon_url(@account.id) }, - { rel: 'magic-public-key', href: "data:application/magic-public-key,#{@magic_key}" } + { rel: 'magic-public-key', href: "data:application/magic-public-key,#{@magic_key}" }, + { rel: 'http://ostatus.org/schema/1.0/subscribe', template: "#{authorize_follow_url}?acct={uri}" }, ] end diff --git a/app/views/xrd/webfinger.xml.ruby b/app/views/xrd/webfinger.xml.ruby index ee5b5fc9d..80ac71d27 100644 --- a/app/views/xrd/webfinger.xml.ruby +++ b/app/views/xrd/webfinger.xml.ruby @@ -6,5 +6,6 @@ Nokogiri::XML::Builder.new do |xml| xml.Link(rel: 'http://schemas.google.com/g/2010#updates-from', type: 'application/atom+xml', href: account_url(@account, format: 'atom')) xml.Link(rel: 'salmon', href: api_salmon_url(@account.id)) xml.Link(rel: 'magic-public-key', href: "data:application/magic-public-key,#{@magic_key}") + xml.Link(rel: 'http://ostatus.org/schema/1.0/subscribe', template: "#{authorize_follow_url}?acct={uri}") end end.to_xml diff --git a/config/application.rb b/config/application.rb index 091f9c535..79ace8521 100644 --- a/config/application.rb +++ b/config/application.rb @@ -45,7 +45,7 @@ module Mastodon config.browserify_rails.commandline_options = '--transform [ babelify --presets [ es2015 react ] ] --extension=".jsx"' config.to_prepare do - Doorkeeper::AuthorizationsController.layout 'auth' + Doorkeeper::AuthorizationsController.layout 'public' end config.action_dispatch.default_headers = { diff --git a/config/locales/en.yml b/config/locales/en.yml index 760078862..f57c72026 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -26,6 +26,11 @@ en: resend_confirmation: Resend confirmation instructions reset_password: Reset password set_new_password: Set new password + authorize_follow: + error: Unfortunately, there was an error looking up the remote account + follow: Follow + prompt_html: 'You (%{self}) have requested to follow:' + title: Follow %{acct} datetime: distance_in_words: about_x_hours: "%{count}h" diff --git a/config/routes.rb b/config/routes.rb index 985d6583d..1468d426b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,6 +48,10 @@ Rails.application.routes.draw do resources :media, only: [:show] resources :tags, only: [:show] + # Remote follow + get :authorize_follow, to: 'authorize_follow#new' + post :authorize_follow, to: 'authorize_follow#create' + namespace :admin do resources :pubsubhubbub, only: [:index] resources :domain_blocks, only: [:index, :create] diff --git a/spec/controllers/authorize_follow_controller_spec.rb b/spec/controllers/authorize_follow_controller_spec.rb new file mode 100644 index 000000000..954efd53e --- /dev/null +++ b/spec/controllers/authorize_follow_controller_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' + +RSpec.describe AuthorizeFollowController, type: :controller do + describe 'GET #new' + describe 'POST #create' +end diff --git a/spec/helpers/authorize_follow_helper_spec.rb b/spec/helpers/authorize_follow_helper_spec.rb new file mode 100644 index 000000000..ba5b0a70b --- /dev/null +++ b/spec/helpers/authorize_follow_helper_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe AuthorizeFollowHelper, type: :helper do + +end