fix rails_ujs links that POST (#1136)

This commit is contained in:
Peter Bhat Harkins 2022-11-08 23:09:06 -06:00
parent 6261204ad9
commit 2c688838a4
8 changed files with 71 additions and 45 deletions

View File

@ -7,16 +7,9 @@
"use strict";
const parentSelector = (target, selector) => {
let parent = target;
while (!parent.matches(selector)) {
parent = parent.parentElement;
if (parent === null) {
throw new Error(`Did not match a parent of ${target} with the selector ${selector}`);
}
}
return parent;
};
const csrfToken = () => {
return document.querySelector('meta[name="csrf-token"]').getAttribute('content');
}
function on(eventTypes, selector, callback) {
eventTypes.split(/ /).forEach( (eventType) => {
@ -32,6 +25,17 @@ const onPageLoad = (callback) => {
document.addEventListener('DOMContentLoaded', callback);
};
const parentSelector = (target, selector) => {
let parent = target;
while (!parent.matches(selector)) {
parent = parent.parentElement;
if (parent === null) {
throw new Error(`Did not match a parent of ${target} with the selector ${selector}`);
}
}
return parent;
};
const replace = (oldElement, newHTMLString) => {
const placeHolder = document.createElement('div');
placeHolder.insertAdjacentHTML('afterBegin', newHTMLString);
@ -53,10 +57,9 @@ const slideDownJS = (element) => {
};
const fetchWithCSRF = (url, params) => {
let csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
params = params || {};
params['headers'] = params['headers'] || new Headers;
params['headers'].append('X-CSRF-Token', csrfToken);
params['headers'].append('X-CSRF-Token', csrfToken());
return fetch(url, params);
}
@ -465,6 +468,11 @@ onPageLoad(() => {
Lobster.curUser = document.body.getAttribute('data-username'); // hack
autosize(document.querySelectorAll('textarea'));
// replace csrf token in forms that may be fragment caches with page token
for (const i of document.querySelectorAll('form input[name="authenticity_token"]')) {
i.value = csrfToken();
}
// Global Functions
on('click', '.markdown_help_label', (event) => {

View File

@ -381,6 +381,17 @@ textarea:focus {
textarea::placeholder {
color: var(--color-fg-contrast-7-5);
}
.link_post {
display: inline;
}
input[type="submit"].link_post {
background: none;
border: none;
padding: 0;
color: var(--color-fg-link);
text-decoration: underline;
cursor: pointer;
}
input[type="submit"]:focus,
button:focus {
@ -525,8 +536,9 @@ header#nav nav.links {
display: flex;
width: 100%
}
header#nav a, header#subnav a {
header#nav a, header#subnav a, header#subnav input[type="submit"] {
color: var(--color-fg-contrast-6);
font-weight: bold;
margin: 0 0.25rem;
text-decoration: none;
}
@ -1546,7 +1558,7 @@ div.flash-success h2 {
}
/* pushover */
.pushover_button {
input[type="submit"].link_post.pushover_button {
box-sizing: border-box;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAJQCeAPHNVUx7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wEPAh02ee0QVwAAACZpVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVAgb24gYSBNYWOV5F9bAAABqElEQVQ4y62TvUtbURjGf+fek2vQpMF2ED9QkfpR6VLaDoIEF0UKWQRBQ+yQP6GDU0Xw4y/obOgg6dDSJVS61MlBcXFQB6M1BsF+IES9NnrzcRy8xpvrBwH7bOflfc553+d5jsCF9tiRDwgBEaDXLi8B80AiGQ2Yzn7hIo8Cce5HOBkNfLo6aA7ydAVkgLjdez3BrS8rRbBJEmyU+AyBVVDE1i1SJ6psEmHvfOLktj0SjL/2snKQx8wpNg+LBJt0RjoN+j6bqOvN/ZotWAldtYK5gWpmV84YbPUw2ePlb7bI73+Kep+OLFONkGarXcK7l16+7+V57BW8qJMs7Ob5k4VQm4fVXzlyquyGiHRYBcC+WWQxnSP63AAgtn7O0FNJ9xOd0W+nbkF7pbsytXxOQw30N0t2MgX6Wzy8qtMJL5zy81jdsETaIXnjLL7trkLqGl+2svxI5/mwZt1l6ZJmJ6yEGqkYbveQOioQ2yiz7TbMa0DCWRnuMPBXaXzcsJx23YWEZmc7fJkqxdgzg8xZka/bFhVE2hSuKL+nMswko4GJ//KZxEO/8wVmfpjJTWeCTQAAAABJRU5ErkJggg==) 2px 2px no-repeat, linear-gradient(var(--color-fg-gradient-lit), var(--color-fg-gradient-shadowed));
border: 1px solid var(--color-box-border);

View File

@ -41,6 +41,16 @@ module ApplicationHelper
link_to text, path, options
end
def link_post button_label, link, options={}
options.reverse_merge class_name: nil, confirm: nil
render partial: 'helpers/link_post', locals: {
button_label: button_label,
link: link,
class_name: options[:class_name],
confirm: options[:confirm],
}
end
def page_numbers_for_pagination(max, cur)
if max <= MAX_PAGES
return (1 .. max).to_a

View File

@ -0,0 +1,4 @@
<%= form_tag url_for(link), class: 'link_post' do %>
<%# redundant class on the submit_tag because the form_tag isn't printed if nested in another form %>
<%= submit_tag button_label, class: "link_post #{class_name}", data: { confirm: confirm } %>
<% end %>

View File

@ -23,21 +23,18 @@
<% end %></td>
<td><%= raw ir.markeddown_memo %></td>
<td><%= form_with url: send_invitation_for_request_path do |f| %>
<%= f.hidden_field "code", :value => ir.code %>
<%= f.submit "Send Invitation", :data => { :confirm => "Are " <<
"you sure you want to invite this person and remove this request?" } %>
<%= f.hidden_field "code", :value => ir.code %>
<%= f.submit "Send Invitation" %>
<% end %></td>
<td><%= form_with url: delete_invitation_request_path do |f| %>
<%= f.hidden_field "code", :value => ir.code %>
<%= f.submit "Delete", :data => { :confirm => "Are you sure " <<
"you want to delete this request?" } %>
<%= f.hidden_field "code", :value => ir.code %>
<%= f.submit "Delete" %>
<% end %>
</tr>
<% end %>
<% if @invitation_requests.length == 0 %>
<tr>
<td colspan=<%= @user.is_moderator?? 5 : 4 %> align="center"><span
class="na">No invitation requests</span></td>
<td colspan=<%= @user.is_moderator?? 5 : 4 %> align="center"><span class="na">No invitation requests</span></td>
</tr>
<% end %>
</table>

View File

@ -1,9 +1,7 @@
<% content_for :subnav do %>
<a href="/u/<%= @user.username %>">Public Profile</a>
<a href="/filters">Filtered Tags</a> |
<%= link_to "Logout", { :controller => "login", :action => "logout" },
:data => { :confirm => "Are you sure you want to logout?" },
:method => "post" %>
<%= link_post 'Logout', logout_path, confirm: 'Are you sure you want to logout?' %>
<% end %>
<div class="box wide">
@ -77,9 +75,8 @@
raw("<a href=\"https://gravatar.com/\">Gravatar</a>:"),
:class => "required" %>
<span>
Your avatar will be cached from the Gravatar icon for your e-mail
address above.
(<%= link_to "Expire cache", "/avatars/expire", :method => :post %>)
Your avatar will be cached from the Gravatar icon for your e-mail address above.
<%= link_post "Expire cache", "/avatars/expire" %>
</span>
</div>
@ -89,13 +86,12 @@
raw("<a href=\"https://pushover.net/\">Pushover</a>:"),
:class => "required" %>
<span>
<%= link_to((@edit_user.pushover_user_key.present??
"Manage Pushover Subscription" : "Subscribe With Pushover"),
"/settings/pushover_auth", :class => "pushover_button",
:method => :post) %>
<span class="hint indent">
For optional comment and message notifications below
</span>
<%= link_post((@edit_user.pushover_user_key.present? ?
"Manage Pushover Subscription" : "Subscribe With Pushover"),
"/settings/pushover_auth", class_name: "pushover_button") %>
<span class="hint indent">
For optional comment and message notifications below
</span>
</span>
</div>
<% end %>
@ -110,8 +106,7 @@
Linked to
<strong><a href="https://github.com/<%= h(@edit_user.github_username)
%>"><%= h(@edit_user.github_username) %></a></strong>
(<%= link_to "Disconnect", "/settings/github_disconnect",
:method => :post %>)
<%= link_post "Disconnect", "/settings/github_disconnect" %>
<% else %>
<a href="/settings/github_auth">Connect</a>
<% end %>
@ -129,8 +124,7 @@
Linked to
<strong><a href="https://twitter.com/<%= h(@edit_user.twitter_username)
%>">@<%= h(@edit_user.twitter_username) %></a></strong>
(<%= link_to "Disconnect", "/settings/twitter_disconnect",
:method => :post %>)
<%= link_post "Disconnect", "/settings/twitter_disconnect" %>
<% else %>
<a href="/settings/twitter_auth">Connect</a>
<% end %>

View File

@ -1,5 +1,5 @@
<div class="box" id="story_box">
<%= form_with model: @story, url: story_path(@story.short_id), method: :put, id: 'edit_story' do |f| %>
<%= form_with model: @story, id: 'edit_story' do |f| %>
<%= render :partial => "stories/form", :locals => { :story => @story,
:f => f } %>
@ -42,14 +42,15 @@
<% if @story.is_gone? && @story.is_undeletable_by_user?(@user) %>
&nbsp; | &nbsp;
<%= f.submit "Undelete", formaction: story_undelete_path(@story.short_id),
:data => { :confirm => "Are you sure you want to undelete this story?" } %>
:data => { :confirm => "Undelete this story?" } %>
<% elsif !@story.is_gone? %>
&nbsp; | &nbsp;
<% if @story.user_id != @user.id && @user.is_moderator? %>
<%= f.submit "Delete", formaction: story_destroy_path(@story.short_id), :class => "deletion" %>
<%= f.submit "Delete", formaction: story_destroy_path(@story.short_id),
:class => "deletion", :data => { :confirm => "Delete this story?" } %>
<% else %>
<%= f.submit "Delete", formaction: story_destroy_path(@story.short_id),
:class => "deletion", :data => { :confirm => "Are you sure you want to delete this story?" } %>
:class => "deletion", :data => { :confirm => "Delete this story?" } %>
<% end %>
<% end %>

View File

@ -85,8 +85,8 @@ Rails.application.routes.draw do
post "upvote"
post "flag"
post "unvote"
put "destroy"
put "undelete"
patch "destroy"
patch "undelete"
post "hide"
post "unhide"
post "save"