Commit 6efe9c2f authored by Alexis Reigel's avatar Alexis Reigel

atom links with rss token instead of private token

parent c1b5c806
...@@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base ...@@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base
include EnforcesTwoFactorAuthentication include EnforcesTwoFactorAuthentication
before_action :authenticate_user_from_private_token! before_action :authenticate_user_from_private_token!
before_action :authenticate_user_from_rss_token!
before_action :authenticate_user! before_action :authenticate_user!
before_action :validate_user_service_ticket! before_action :validate_user_service_ticket!
before_action :check_password_expiration before_action :check_password_expiration
...@@ -72,13 +73,20 @@ class ApplicationController < ActionController::Base ...@@ -72,13 +73,20 @@ class ApplicationController < ActionController::Base
user = User.find_by_authentication_token(token) || User.find_by_personal_access_token(token) user = User.find_by_authentication_token(token) || User.find_by_personal_access_token(token)
if user && can?(user, :log_in) sessionless_sign_in(user)
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
# sign in token, you can simply remove store: false.
sign_in user, store: false
end end
# This filter handles authentication for atom request with an rss_token
def authenticate_user_from_rss_token!
return unless request.format.atom?
token = params[:rss_token].presence
return unless token.present?
user = User.find_by_rss_token(token)
sessionless_sign_in(user)
end end
def log_exception(exception) def log_exception(exception)
...@@ -282,4 +290,14 @@ class ApplicationController < ActionController::Base ...@@ -282,4 +290,14 @@ class ApplicationController < ActionController::Base
ensure ensure
Gitlab::I18n.reset_locale Gitlab::I18n.reset_locale
end end
def sessionless_sign_in(user)
if user && can?(user, :log_in)
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
# sign in token, you can simply remove store: false.
sign_in user, store: false
end
end
end end
module RssHelper module RssHelper
def rss_url_options def rss_url_options
{ format: :atom, private_token: current_user.try(:private_token) } { format: :atom, rss_token: current_user.try(:rss_token) }
end end
end end
...@@ -99,6 +99,42 @@ describe ApplicationController do ...@@ -99,6 +99,42 @@ describe ApplicationController do
end end
end end
describe '#authenticate_user_from_rss_token' do
describe "authenticating a user from an rss token" do
controller(described_class) do
def index
render text: 'authenticated'
end
end
context "when the 'rss_token' param is populated with the rss token" do
context 'when the request format is atom' do
it "logs the user in" do
get :index, rss_token: user.rss_token, format: :atom
expect(response).to have_http_status 200
expect(response.body).to eq 'authenticated'
end
end
context 'when the request format is not atom' do
it "doesn't log the user in" do
get :index, rss_token: user.rss_token
expect(response.status).not_to have_http_status 200
expect(response.body).not_to eq 'authenticated'
end
end
end
context "when the 'rss_token' param is populated with an invalid rss token" do
it "doesn't log the user" do
get :index, rss_token: "token"
expect(response.status).not_to eq 200
expect(response.body).not_to eq 'authenticated'
end
end
end
end
describe '#route_not_found' do describe '#route_not_found' do
it 'renders 404 if authenticated' do it 'renders 404 if authenticated' do
allow(controller).to receive(:current_user).and_return(user) allow(controller).to receive(:current_user).and_return(user)
......
...@@ -20,13 +20,20 @@ describe "Dashboard Issues Feed", feature: true do ...@@ -20,13 +20,20 @@ describe "Dashboard Issues Feed", feature: true do
expect(body).to have_selector('title', text: "#{user.name} issues") expect(body).to have_selector('title', text: "#{user.name} issues")
end end
it "renders atom feed via rss token" do
visit issues_dashboard_path(:atom, rss_token: user.rss_token)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed with url parameters" do it "renders atom feed with url parameters" do
visit issues_dashboard_path(:atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) visit issues_dashboard_path(:atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]') link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query) params = CGI.parse(URI.parse(link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened']) expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
end end
...@@ -35,7 +42,7 @@ describe "Dashboard Issues Feed", feature: true do ...@@ -35,7 +42,7 @@ describe "Dashboard Issues Feed", feature: true do
let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') } let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') }
it "renders issue fields" do it "renders issue fields" do
visit issues_dashboard_path(:atom, private_token: user.private_token) visit issues_dashboard_path(:atom, rss_token: user.rss_token)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]") entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
...@@ -58,7 +65,7 @@ describe "Dashboard Issues Feed", feature: true do ...@@ -58,7 +65,7 @@ describe "Dashboard Issues Feed", feature: true do
end end
it "renders issue label and milestone info" do it "renders issue label and milestone info" do
visit issues_dashboard_path(:atom, private_token: user.private_token) visit issues_dashboard_path(:atom, rss_token: user.rss_token)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]") entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
......
...@@ -11,6 +11,13 @@ describe "Dashboard Feed", feature: true do ...@@ -11,6 +11,13 @@ describe "Dashboard Feed", feature: true do
end end
end end
context "projects atom feed via rss token" do
it "renders projects atom feed" do
visit dashboard_projects_path(:atom, rss_token: user.rss_token)
expect(body).to have_selector('feed title')
end
end
context 'feed content' do context 'feed content' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:issue) { create(:issue, project: project, author: user, description: '') } let(:issue) { create(:issue, project: project, author: user, description: '') }
...@@ -20,7 +27,7 @@ describe "Dashboard Feed", feature: true do ...@@ -20,7 +27,7 @@ describe "Dashboard Feed", feature: true do
project.team << [user, :master] project.team << [user, :master]
issue_event(issue, user) issue_event(issue, user)
note_event(note, user) note_event(note, user)
visit dashboard_projects_path(:atom, private_token: user.private_token) visit dashboard_projects_path(:atom, rss_token: user.rss_token)
end end
it "has issue opened event" do it "has issue opened event" do
......
...@@ -43,25 +43,40 @@ describe 'Issues Feed', feature: true do ...@@ -43,25 +43,40 @@ describe 'Issues Feed', feature: true do
end end
end end
context 'when authenticated via rss token' do
it 'renders atom feed' do
visit namespace_project_issues_path(project.namespace, project, :atom,
rss_token: user.rss_token)
expect(response_headers['Content-Type']).
to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{project.name} issues")
expect(body).to have_selector('author email', text: issue.author_public_email)
expect(body).to have_selector('assignees assignee email', text: issue.assignees.first.public_email)
expect(body).to have_selector('assignee email', text: issue.assignees.first.public_email)
expect(body).to have_selector('entry summary', text: issue.title)
end
end
it "renders atom feed with url parameters for project issues" do it "renders atom feed with url parameters for project issues" do
visit namespace_project_issues_path(project.namespace, project, visit namespace_project_issues_path(project.namespace, project,
:atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]') link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query) params = CGI.parse(URI.parse(link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened']) expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
end end
it "renders atom feed with url parameters for group issues" do it "renders atom feed with url parameters for group issues" do
visit issues_group_path(group, :atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) visit issues_group_path(group, :atom, rss_token: user.rss_token, state: 'opened', assignee_id: user.id)
link = find('link[type="application/atom+xml"]') link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query) params = CGI.parse(URI.parse(link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('state' => ['opened']) expect(params).to include('state' => ['opened'])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
end end
......
...@@ -11,6 +11,13 @@ describe "User Feed", feature: true do ...@@ -11,6 +11,13 @@ describe "User Feed", feature: true do
end end
end end
context 'user atom feed via rss token' do
it "renders user atom feed" do
visit user_path(user, :atom, rss_token: user.rss_token)
expect(body).to have_selector('feed title')
end
end
context 'feed content' do context 'feed content' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:issue) do let(:issue) do
...@@ -40,7 +47,7 @@ describe "User Feed", feature: true do ...@@ -40,7 +47,7 @@ describe "User Feed", feature: true do
issue_event(issue, user) issue_event(issue, user)
note_event(note, user) note_event(note, user)
merge_request_event(merge_request, user) merge_request_event(merge_request, user)
visit user_path(user, :atom, private_token: user.private_token) visit user_path(user, :atom, rss_token: user.rss_token)
end end
it 'has issue opened event' do it 'has issue opened event' do
......
...@@ -6,6 +6,6 @@ RSpec.describe 'Dashboard Activity', feature: true do ...@@ -6,6 +6,6 @@ RSpec.describe 'Dashboard Activity', feature: true do
visit activity_dashboard_path visit activity_dashboard_path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
...@@ -62,6 +62,6 @@ RSpec.describe 'Dashboard Issues', feature: true do ...@@ -62,6 +62,6 @@ RSpec.describe 'Dashboard Issues', feature: true do
expect(page).to have_content(other_issue.title) expect(page).to have_content(other_issue.title)
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
...@@ -31,5 +31,5 @@ RSpec.describe 'Dashboard Projects', feature: true do ...@@ -31,5 +31,5 @@ RSpec.describe 'Dashboard Projects', feature: true do
end end
end end
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
...@@ -53,10 +53,10 @@ describe "Dashboard Issues filtering", feature: true, js: true do ...@@ -53,10 +53,10 @@ describe "Dashboard Issues filtering", feature: true, js: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => ['']) expect(params).to include('milestone_title' => [''])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
expect(auto_discovery_params).to include('private_token' => [user.private_token]) expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => ['']) expect(auto_discovery_params).to include('milestone_title' => [''])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end end
......
...@@ -11,8 +11,8 @@ feature 'Group activity page', feature: true do ...@@ -11,8 +11,8 @@ feature 'Group activity page', feature: true do
visit path visit path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -20,7 +20,7 @@ feature 'Group activity page', feature: true do ...@@ -20,7 +20,7 @@ feature 'Group activity page', feature: true do
visit path visit path
end end
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -12,15 +12,15 @@ feature 'Group issues page', feature: true do ...@@ -12,15 +12,15 @@ feature 'Group issues page', feature: true do
context 'when signed in' do context 'when signed in' do
let(:user) { user_in_group } let(:user) { user_in_group }
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
let(:user) { nil } let(:user) { nil }
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
......
...@@ -11,7 +11,7 @@ feature 'Group show page', feature: true do ...@@ -11,7 +11,7 @@ feature 'Group show page', feature: true do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -19,6 +19,6 @@ feature 'Group show page', feature: true do ...@@ -19,6 +19,6 @@ feature 'Group show page', feature: true do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -810,10 +810,10 @@ describe 'Filter issues', js: true, feature: true do ...@@ -810,10 +810,10 @@ describe 'Filter issues', js: true, feature: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => [milestone.title]) expect(params).to include('milestone_title' => [milestone.title])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
expect(auto_discovery_params).to include('private_token' => [user.private_token]) expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => [milestone.title]) expect(auto_discovery_params).to include('milestone_title' => [milestone.title])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end end
...@@ -825,10 +825,10 @@ describe 'Filter issues', js: true, feature: true do ...@@ -825,10 +825,10 @@ describe 'Filter issues', js: true, feature: true do
auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) auto_discovery_link = find('link[type="application/atom+xml"]', visible: false)
auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query) auto_discovery_params = CGI.parse(URI.parse(auto_discovery_link[:href]).query)
expect(params).to include('private_token' => [user.private_token]) expect(params).to include('rss_token' => [user.rss_token])
expect(params).to include('milestone_title' => [milestone.title]) expect(params).to include('milestone_title' => [milestone.title])
expect(params).to include('assignee_id' => [user.id.to_s]) expect(params).to include('assignee_id' => [user.id.to_s])
expect(auto_discovery_params).to include('private_token' => [user.private_token]) expect(auto_discovery_params).to include('rss_token' => [user.rss_token])
expect(auto_discovery_params).to include('milestone_title' => [milestone.title]) expect(auto_discovery_params).to include('milestone_title' => [milestone.title])
expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
end end
......
...@@ -16,7 +16,7 @@ feature 'Project Activity RSS' do ...@@ -16,7 +16,7 @@ feature 'Project Activity RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -24,6 +24,6 @@ feature 'Project Activity RSS' do ...@@ -24,6 +24,6 @@ feature 'Project Activity RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
end end
end end
...@@ -12,8 +12,8 @@ feature 'Project Commits RSS' do ...@@ -12,8 +12,8 @@ feature 'Project Commits RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -21,7 +21,7 @@ feature 'Project Commits RSS' do ...@@ -21,7 +21,7 @@ feature 'Project Commits RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -16,8 +16,8 @@ feature 'Project Issues RSS' do ...@@ -16,8 +16,8 @@ feature 'Project Issues RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -25,7 +25,7 @@ feature 'Project Issues RSS' do ...@@ -25,7 +25,7 @@ feature 'Project Issues RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -12,7 +12,7 @@ feature 'Project RSS' do ...@@ -12,7 +12,7 @@ feature 'Project RSS' do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -20,6 +20,6 @@ feature 'Project RSS' do ...@@ -20,6 +20,6 @@ feature 'Project RSS' do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -12,7 +12,7 @@ feature 'Project Tree RSS' do ...@@ -12,7 +12,7 @@ feature 'Project Tree RSS' do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed with current_user's private token" it_behaves_like "an autodiscoverable RSS feed with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -20,6 +20,6 @@ feature 'Project Tree RSS' do ...@@ -20,6 +20,6 @@ feature 'Project Tree RSS' do
visit path visit path
end end
it_behaves_like "an autodiscoverable RSS feed without a private token" it_behaves_like "an autodiscoverable RSS feed without an rss token"
end end
end end
...@@ -9,7 +9,7 @@ feature 'User RSS' do ...@@ -9,7 +9,7 @@ feature 'User RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button with current_user's private token" it_behaves_like "it has an RSS button with current_user's rss token"
end end
context 'when signed out' do context 'when signed out' do
...@@ -17,6 +17,6 @@ feature 'User RSS' do ...@@ -17,6 +17,6 @@ feature 'User RSS' do
visit path visit path
end end
it_behaves_like "it has an RSS button without a private token" it_behaves_like "it has an RSS button without an rss token"
end end
end end
...@@ -3,17 +3,17 @@ require 'spec_helper' ...@@ -3,17 +3,17 @@ require 'spec_helper'
describe RssHelper do describe RssHelper do
describe '#rss_url_options' do describe '#rss_url_options' do
context 'when signed in' do context 'when signed in' do
it "includes the current_user's private_token" do it "includes the current_user's rss_token" do
current_user = create(:user) current_user = create(:user)
allow(helper).to receive(:current_user).and_return(current_user) allow(helper).to receive(:current_user).and_return(current_user)
expect(helper.rss_url_options).to include private_token: current_user.private_token expect(helper.rss_url_options).to include rss_token: current_user.rss_token
end end
end end
context 'when signed out' do context 'when signed out' do
it "does not have a private_token" do it "does not have an rss_token" do
allow(helper).to receive(:current_user).and_return(nil) allow(helper).to receive(:current_user).and_return(nil)
expect(helper.rss_url_options[:private_token]).to be_nil expect(helper.rss_url_options[:rss_token]).to be_nil
end end
end end
end end
......
shared_examples "an autodiscoverable RSS feed with current_user's private token" do shared_examples "an autodiscoverable RSS feed with current_user's rss token" do
it "has an RSS autodiscovery link tag with current_user's private token" do it "has an RSS autodiscovery link tag with current_user's rss token" do
expect(page).to have_css("link[type*='atom+xml'][href*='private_token=#{Thread.current[:current_user].private_token}']", visible: false) expect(page).to have_css("link[type*='atom+xml'][href*='rss_token=#{Thread.current[:current_user].rss_token}']", visible: false)
end end
end end
shared_examples "it has an RSS button with current_user's private token" do shared_examples "it has an RSS button with current_user's rss token" do
it "shows the RSS button with current_user's private token" do it "shows the RSS button with current_user's rss token" do
expect(page).to have_css("a:has(.fa-rss)[href*='private_token=#{Thread.current[:current_user].private_token}']") expect(page).to have_css("a:has(.fa-rss)[href*='rss_token=#{Thread.current[:current_user].rss_token}']")
end end
end end
shared_examples "an autodiscoverable RSS feed without a private token" do shared_examples "an autodiscoverable RSS feed without an rss token" do
it "has an RSS autodiscovery link tag without a private token" do it "has an RSS autodiscovery link tag without an rss token" do
expect(page).to have_css("link[type*='atom+xml']:not([href*='private_token'])", visible: false) expect(page).to have_css("link[type*='atom+xml']:not([href*='rss_token'])", visible: false)
end end
end end
shared_examples "it has an RSS button without a private token" do shared_examples "it has an RSS button without an rss token" do
it "shows the RSS button without a private token" do it "shows the RSS button without an rss token" do
expect(page).to have_css("a:has(.fa-rss):not([href*='private_token'])") expect(page).to have_css("a:has(.fa-rss):not([href*='rss_token'])")
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment