enable mod_userdir

diff of `rails routes`:

12,13d11
<                              GET      /newest/:user(.:format)                        home#newest_by_user
<                              GET      /newest/:user/page/:page(.:format)             home#newest_by_user
32d29
<                 user_threads GET      /threads/:user(.:format)                       comments#user_threads
120,122c117,132
<                            u GET      /u(.:format)                                   users#tree
<                         user GET      /u/:username(.:format)                         users#show
<                user_standing GET      /u/:username/standing(.:format)                users#standing
---
>                   users_tree GET      /users(.:format)                               users#tree
>                         user GET      /~:username(.:format)                          users#show
>                user_standing GET      /~:username/standing(.:format)                 users#standing
>                              GET      /~:user/stories(/page/:page)(.:format)         home#newest_by_user
>                 user_threads GET      /~:user/threads(.:format)                      comments#user_threads
>                     user_ban POST     /~:username/ban(.:format)                      users#ban
>                   user_unban POST     /~:username/unban(.:format)                    users#unban
>          user_disable_invite POST     /~:username/disable_invitation(.:format)       users#disable_invitation
>           user_enable_invite POST     /~:username/enable_invitation(.:format)        users#enable_invitation
>                            u GET      /u(.:format)                                   redirect(302, /users)
>                              GET      /u/:username(.:format)                         redirect(302, /~%{username})
>                              GET      /@:username(.:format)                          redirect(302, /~%{username})
>                              GET      /u/:username/standing(.:format)                redirect(302, ~%{username}/standing)
>                              GET      /newest/:user(.:format)                        redirect(302, ~%{user}/stories)
>                              GET      /newest/:user(/page/:page)(.:format)           redirect(302, ~%{user}/stories/page/%{page})
>                              GET      /threads/:user(.:format)                       redirect(302, ~%{user}/threads)
125,128d134
<                     user_ban POST     /users/:username/ban(.:format)                 users#ban
<                   user_unban POST     /users/:username/unban(.:format)               users#unban
<          user_disable_invite POST     /users/:username/disable_invitation(.:format)  users#disable_invitation
<           user_enable_invite POST     /users/:username/enable_invitation(.:format)   users#enable_invitation
This commit is contained in:
Peter Bhat Harkins 2023-08-29 07:45:28 -05:00
parent f66f01c9fd
commit 9fff6ae927
30 changed files with 181 additions and 143 deletions

View File

@ -1246,7 +1246,7 @@ ul.user_tree {
color: var(--color-fg-contrast-4-5);
}
/* /u/:username/standing */
/* /~:username/standing */
/* https://codepen.io/sosuke/pen/Pjoqqp */
.unwarned {
filter: invert(36%) sepia(52%) saturate(0%) hue-rotate(292deg) brightness(96%) contrast(85%);

View File

@ -44,8 +44,8 @@ class KeybaseProofsController < ApplicationController
@contacts = ["admin@#{Keybase.DOMAIN}"]
@prefill_url = "#{new_keybase_proof_url}?kb_username=%{kb_username}&" \
"kb_signature=%{sig_hash}&kb_ua=%{kb_ua}&username=%{username}"
@profile_url = "#{u_url}/%{username}"
@check_url = "#{u_url}/%{username}.json"
@profile_url = "/~%{username}"
@check_url = "/~%{username}.json"
@logo_black = "https://lobste.rs/small-black-logo.svg"
@logo_full = "https://lobste.rs/full-color.logo.svg"
@user_re = User.username_regex_s[1...-1]

View File

@ -30,6 +30,35 @@ module UsersHelper
end
end
def styled_user_link user, content = nil, css_classes = []
if content.is_a?(Story) && content.user_is_author?
css_classes.push 'user_is_author'
end
if content.is_a?(Comment) && content.story &&
content.story.user_is_author? && content.story.user_id == user.id
css_classes.push 'user_is_author'
end
if !user.is_active?
css_classes.push 'inactive_user'
end
if user.is_new?
css_classes.push 'new_user'
end
link_to(user.username, user, class: css_classes)
end
def user_karma(user)
if user.is_admin?
"(administrator)"
elsif user.is_moderator?
"(moderator"
else
"(#{user.karma})"
end
end
private
def user_is_moderator?

View File

@ -353,20 +353,6 @@ class Comment < ApplicationRecord
self.updated_at && (self.updated_at - self.created_at > 1.minute)
end
def html_class_for_user
c = []
if !self.user.is_active?
c.push "inactive_user"
elsif self.user.is_new?
c.push "new_user"
elsif self.story && self.story.user_is_author? &&
self.story.user_id == self.user_id
c.push "user_is_author"
end
c.join("")
end
def is_deletable_by_user?(user)
if user && user.is_moderator?
return true

View File

@ -478,19 +478,6 @@ class Story < ApplicationRecord
@hider_count ||= HiddenStory.where(:story_id => self.id).count
end
def html_class_for_user
c = []
if !self.user.is_active?
c.push "inactive_user"
elsif self.user.is_new?
c.push "new_user"
elsif self.user_is_author?
c.push "user_is_author"
end
c.join("")
end
def is_flaggable?
if self.created_at && self.score > FLAGGABLE_MIN_SCORE
Time.current - self.created_at <= FLAGGABLE_DAYS.days

View File

@ -7,8 +7,8 @@
<p>
Lobsters is a computing-focused community centered around link aggregation
and discussion, launched on July 3rd, 2012.
The administrator is <a href="/u/pushcx">Peter Bhat Harkins</a> ("pushcx"), contact him with any support issues.
Lobsters was created by <a href="/u/jcs">joshua stein</a>
The administrator is <a href="/~pushcx">Peter Bhat Harkins</a> ("pushcx"), contact him with any support issues.
Lobsters was created by <a href="/~jcs">joshua stein</a>
with careful design touches to encourage a healthy community:
</p>
@ -87,7 +87,7 @@
<h2 id="invitations">Invitation Tree</h2>
<p>
The full <a href="/u">user tree</a> is public and each user's profile
The full <%= link_to 'user tree', users_tree_path %> is public and each user's profile
shows who invited them. This provides some degree of accountability and
helps identify voting rings.
</p>
@ -113,7 +113,7 @@
</p>
<p>
The quickest way to receive an invitation is to talk to someone you <a href="/u">recognize from the site</a>.
The quickest way to receive an invitation is to talk to someone you <%= link_to 'recognize from the site', users_tree_path %>.
If you wrote a link that was posted, please reach out in <a href="/chat">chat</a>, we'd love to have you join the discussion.
Finally, if you can't find anyone you know in the invitation tree and didn't author something posted to the site,
<% if Rails.application.allow_invitation_requests? %>
@ -176,7 +176,7 @@
<h2 id="transparency">Transparency Policy</h2>
<p>
All <a href="/moderations">moderator actions</a> on this site are visible to
everyone and the identities of those moderators are <a href="/u?moderators=1">public</a>.
everyone and the identities of those moderators are <%= link_to 'public', moderators_path %>.
While the individual actions of a moderator may cause debate, there should be no question about if an action happened or who is responsible.
</p>

View File

@ -9,11 +9,11 @@
in <tt>#lobsters</tt>.
This channel was originally
<a href="/s/2hdoop">created</a> by
<a href="/u/kristof">@kristof</a> on freenode, and
<a href="/~kristof">@kristof</a> on freenode, and
<a href="https://lobste.rs/s/1z77ly/libera_chat#c_vwmpgx">stayed with the network</a> on 2021-05-19 after that domain was lost.
<a href="/u/pushcx">@pushcx</a>,
<a href="/u/355e3b">@355e3b</a> (<tt>c355e3b</tt> on IRC), and
<a href="/u/aleph">@aleph</a> (<tt>Church</tt> on IRC) are channel operators.
<a href="/~pushcx">@pushcx</a>,
<a href="/~355e3b">@355e3b</a> (<tt>c355e3b</tt> on IRC), and
<a href="/~aleph">@aleph</a> (<tt>Church</tt> on IRC) are channel operators.
</p>
<p>

View File

@ -49,13 +49,10 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
<% end %>
<% if (@user && @user.show_avatars?) || !@user %>
<a href="/u/<%= comment.user.username %>"><%=
avatar_img(comment.user, 16) %></a>
<%= link_to avatar_img(comment.user, 16), comment.user %>
<% end %>
<a href="/u/<%= comment.user.username %>"
class="<%= comment.html_class_for_user %>"><%=
comment.user.username %></a>
<%= styled_user_link comment.user, comment %>
<% if comment.hat %>
<%= comment.hat.to_html_label %>

View File

@ -81,13 +81,10 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
<% end %>
<% if (@user && @user.show_avatars?) || !@user %>
<a href="/u/<%= comment.user.username %>"><%=
avatar_img(comment.user, 16) %></a>
<%= link_to avatar_img(comment.user, 16), comment.user %>
<% end %>
<a href="/u/<%= comment.user.username %>"
class="<%= comment.html_class_for_user %>"><%=
comment.user.username %></a>
<%= styled_user_link comment.user, comment %>
<% if comment.hat %>
<%= comment.hat.to_html_label %>

View File

@ -21,8 +21,7 @@
<% @hat_groups.keys.sort_by{|a| a.downcase }.each do |hg| %>
<% @hat_groups[hg].sort_by{|hh| hh.user.username.downcase }.each do |hh| %>
<tr>
<td><a href="/u/<%= hh.user.username %>"><%= hh.user.username
%></a></td>
<td><%= styled_user_link hh.user %></td>
<td><%= hh.to_html_label %></td>
<td>
<% if hh.link.to_s.match(/^http/) %>

View File

@ -11,7 +11,7 @@
<p>
<div class="boxline">
<%= f.label :user_id, "User:", :class => "required" %>
<a href="/u/<%= hr.user.username %>"><%= hr.user.username %></a>
<%= styled_user_link hr.user %>
<%= time_ago_in_words(hr.created_at) %>
</div>

View File

@ -1,6 +1,6 @@
<div class="box wide">
<p>
If you don't know (or can't find) an <a href="/u/">existing user</a> from
If you don't know (or can't find) an <%= link_to 'existing_user', users_tree_path %> from
whom to request an invitation, you can make a public request for one. This
will display your name and memo to all other logged-in users who can then
send you an invitation if they recognize you.

View File

@ -36,7 +36,7 @@
<p>
Not a user yet?
Read about <a href="/about#invitations">how invitations work</a> and see if you know
<a href="/u">a current user</a> of the site.
<%= link_to 'a current user', users_tree_path %> of the site.
The <a href="/chat">chat room</a> does not require an invitation.
</p>
<% end %>

View File

@ -17,15 +17,13 @@
<div style="white-space:nowrap;">
<% if @direction == :in %>
<% if message.author %>
<a href="/u/<%= message.author.username %>"><%=
message.author.username %></a>
<%= styled_user_link message.author %>
<% else %>
<%= message.author_username %>
<% end %>
<%= message.hat.to_html_label if message.hat %>
<% else %>
<a href="/u/<%= message.recipient.username %>"><%=
message.recipient.username %></a>
<%= styled_user_link message.recipient %>
<% end %>
</div>
</td>

View File

@ -4,14 +4,13 @@
<h2>
From
<% if @message.author %>
<a href="/u/<%= @message.author.username %>"><%= @message.author.username %></a>
<%= styled_user_link @message.author %>
<% else %>
<%= @message.author_username %>
<% end %>
<%= @message.hat.to_html_label if @message.hat %>
to
<a href="/u/<%= @message.recipient.username %>"><%=
@message.recipient.username %></a>
<%= styled_user_link @message.recipient %>
<%= time_ago_in_words_label(@message.created_at) %>
</h2>
@ -57,6 +56,6 @@
<%= render partial: 'form', locals: { new_message: @new_message, replying: true } %>
<% else %>
For help with this message, contact <a href="/u?moderators=1">a moderator</a>.
For help with this message, contact <%= link_to 'a moderator', moderators_path %>.
<% end %>
</div>

View File

@ -27,8 +27,7 @@
<%= link_to("Category: #{mod.category.category}", mod.category) %>
<% elsif mod.user_id %>
<% if mod.user %>
<a href="/u/<%= mod.user.username %>">User
<%= mod.user.username %></a>
<%= link_to "User #{mod.user.username}", mod.user %>
<% else %>
User <%= mod.user_id %> (Deleted)
<% end %>

View File

@ -1,5 +1,5 @@
<% content_for :subnav do %>
<a href="/u/<%= @user.username %>">Public Profile</a>
<%= link_to 'Public Profile', @user %>
<a href="/filters">Filtered Tags</a> |
<%= link_post 'Logout', logout_path, confirm: 'Are you sure you want to logout?' %>
<% end %>
@ -311,7 +311,7 @@
<li>
Your comments with negative scores will be deleted, and you can check "disown comments"
below if you want all of your stories and comments to change to list
<a href="/u/inactive-user">inactive-user</a> instead of your username.
<a href="/~inactive-user">inactive-user</a> instead of your username.
</li>
</ul>

View File

@ -6,8 +6,8 @@
<% else %>
<p>
Signup is currently by invitation only to combat spam and increase
accountability. If you know <a href="/u/">a current user</a> of the site,
ask them for an invitation, or
accountability. If you know <%= link_to 'a current user', users_tree_path %>
of the site, ask them for an invitation, or
<% if Rails.application.allow_invitation_requests? %>
<a href="/invitations/request">request one publicly</a>.
<% else %>

View File

@ -14,8 +14,7 @@
<p>
<%= f.label :invitation, "Invited By:", :class => "required" %>
<span class="d">
<a href="/u/<%= @invitation.user.username %>" target="_blank"><%=
@invitation.user.username %></a>
<%= link_to @invitation.user.username, user_path(@invitation.user), target: '_blank' %>
</span>
</p>
<% end %>

View File

@ -66,16 +66,14 @@ class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
<% end %>
<span class="byline">
<% if (@user && @user.show_avatars?) || !@user %>
<a href="/u/<%= ms.user.username %>"><%=
avatar_img(ms.user, 16) %></a>
<%= link_to avatar_img(ms.user, 16), ms.user %>
<% end %>
<% if ms.user_is_author? %>
<span> authored by </span>
<% else %>
<span> via </span>
<% end %>
<a href="/u/<%= ms.user.username %>" class="u-author h-card <%=
ms.html_class_for_user %>"><%= ms.user.username %></a>
<%= styled_user_link ms.user, story, ['u-author', 'h-card'] %>
<%= time_ago_in_words_label(ms.created_at) %>
<% if ms.is_editable_by_user?(@user) %>
@ -98,8 +96,7 @@ class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
<div class="byline">
<% if (@user && @user.show_avatars?) || !@user %>
<a href="/u/<%= story.user.username %>"><%=
avatar_img(story.user, 16) %></a>
<%= link_to avatar_img(story.user, 16), story.user %>
<% end %>
<% if story.previewing %>
<% if story.user_is_author? %>
@ -107,8 +104,8 @@ class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
<% else %>
<span> via </span>
<% end %>
<a class="u-author h-card <%= story.html_class_for_user %>"><%=
story.user.username %></a>
<%= styled_user_link story.user, story, ['u-author', 'h-card'] %>
<span> just now </span>
<% else %>
<% if story.user_is_author? %>
@ -116,8 +113,7 @@ class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
<% else %>
<span> via </span>
<% end %>
<a href="/u/<%= story.user.username %>" class="u-author h-card <%=
story.html_class_for_user %>"><%= story.user.username %></a>
<%= styled_user_link story.user, story, ['u-author', 'h-card'] %>
<%= time_ago_in_words_label(story.created_at) %>

View File

@ -3,7 +3,7 @@
<li>
<a href="<%= story.url %>" target="_blank"><%= story.title %></a>
<%= story.user_is_author? ? "authored by" : "via" %>
<a href="/u/<%= story.user.username %>" class="<%= story.html_class_for_user %>"><%= story.user.username %></a>
<%= styled_user_link story.user, story %>
<%= time_ago_in_words_label(story.created_at) %>
<span>
|

View File

@ -1,8 +1,8 @@
<p>
Invitations are unlimited, but persons you invite will be associated with your
account in the <a href="/u">user tree</a> and you may be responsible for them
if they cause problems. Please use your discretion when inviting persons you
don't personally know.
Invitations are unlimited, but persons you invite will be associated with your account
in the <%= link_to 'user tree', users_tree_path %>
and you may be responsible for them if they cause problems.
Please use your discretion when inviting persons you don't personally know.
</p>
<%= form_with url: invitations_path, method: :post do |f| %>

View File

@ -6,20 +6,8 @@
<ul class="user_tree">
<% @users.each do |user| %>
<li>
<a href="/u/<%= user.username %>"
<% if !user.is_active? %>
class="inactive_user"
<% elsif user.is_new? %>
class="new_user"
<% end %>
><%= user.username %></a>
<% if user.is_admin? %>
(administrator)
<% elsif user.is_moderator? %>
(moderator)
<% else %>
(<%= user.karma %>)
<% end %>
<%= styled_user_link(user) %>
<%= user_karma(user) %>
</li>
<% end %>
</ul>

View File

@ -39,9 +39,8 @@
<span class="d">
<%= time_ago_in_words_label(@showing_user.created_at) %>
<% if @showing_user.invited_by_user %>
by <a href="/u#<%= @showing_user.username %>">invitation</a> from
<%= link_to @showing_user.invited_by_user.try(:username),
@showing_user.invited_by_user %>
by <%= link_to 'invitation', users_tree_path(anchor: @showing_user.username) %> from
<%= link_to @showing_user.invited_by_user.try(:username), @showing_user.invited_by_user %>
<% end %>
</span>
<br>
@ -215,14 +214,14 @@
<% @showing_user.votes_for_others.limit(15).each do |v| %><tr>
<td><%= v.vote == 1 ? '+' : v.reason %></td>
<% if v.comment_id %>
<td><a href="/u/<%= v.comment.user.try(:username) %>"><%= v.comment.user.try(:username) %></a></td>
<td><a href="/~<%= v.comment.user.try(:username) %>"><%= v.comment.user.try(:username) %></a></td>
<td>
<%= v.story.title %>
<a href="<%= v.comment.short_id_url %>">comment</a>:<br>
<%= v.comment.comment.split[0..10].join(' ') %>
</td>
<% elsif v.story_id && !v.comment_id %>
<td><a href="/u/<%= v.story.user.try(:username) %>"><%= v.story.user.try(:username) %></a></td>
<td><a href="/~<%= v.story.user.try(:username) %>"><%= v.story.user.try(:username) %></a></td>
<td><a href="<%= v.story.short_id_url %>"><%= v.story.title %></a></td>
<% end %>
</p>

View File

@ -4,9 +4,10 @@
<% if @newest %>
<p>
Newest users:
<%= raw @newest.map{|u| "<a href=\"##{u.username}\" class=\"" <<
(u.is_new?? "new_user" : "") << "\">#{u.username}</a> " <<
"(#{u.karma})" }.join(", ") %>
<% @newest.each do |user| %>
<%= styled_user_link user %>
<%= user_karma(user) %><%= ',' if user != @newest.last %>
<% end %>
</p>
<% end %>
@ -18,20 +19,9 @@
<% while subtree %>
<% if (user = subtree.pop) %>
<li class="<%= user.invited_by_user_id ? "" : "noparent" %>">
<a name="<%= user.username %>" href="/u/<%= user.username %>"
<% if !user.is_active? %>
class="inactive_user"
<% elsif user.is_new? %>
class="new_user"
<% end %>
><%= user.username %></a>
<% if user.is_admin? %>
(administrator)
<% elsif user.is_moderator? %>
(moderator)
<% else %>
(<%= user.karma %>)
<% end %>
<%= styled_user_link user %>
<%= user_karma(user) %>
<% if (children = @users_by_parent[user.id]) %>
<% # drill down deeper in the tree %>
<% ancestors << subtree %>

View File

@ -14,8 +14,6 @@ Rails.application.routes.draw do
get "/active/page/:page" => "home#active"
get "/newest" => "home#newest"
get "/newest/page/:page" => "home#newest"
get "/newest/:user" => "home#newest_by_user"
get "/newest/:user/page/:page" => "home#newest_by_user"
get "/recent" => "home#recent"
get "/recent/page/:page" => "home#recent"
get "/hidden" => "home#hidden"
@ -37,7 +35,6 @@ Rails.application.routes.draw do
get "/top/:length/page/:page" => "home#top"
get "/threads" => "comments#user_threads"
get "/threads/:user" => "comments#user_threads", :as => "user_threads"
get "/replies" => "replies#all"
get "/replies/page/:page" => "replies#all"
@ -133,20 +130,32 @@ Rails.application.routes.draw do
get "/s/:id/(:title)" => "stories#show"
get "/u" => "users#tree"
get "/u/:username" => "users#show", :as => "user"
get "/u/:username/standing" => "users#standing", :as => "user_standing"
get "/users" => "users#tree", :as => "users_tree"
get "/~:username" => "users#show", :as => "user"
get "/~:username/standing" => "users#standing", :as => "user_standing"
get "/~:user/stories(/page/:page)" => "home#newest_by_user"
get "/~:user/threads" => "comments#user_threads", :as => "user_threads"
post "/~:username/ban" => "users#ban", :as => "user_ban"
post "/~:username/unban" => "users#unban", :as => "user_unban"
post "/~:username/disable_invitation" => "users#disable_invitation",
:as => "user_disable_invite"
post "/~:username/enable_invitation" => "users#enable_invitation",
:as => "user_enable_invite"
# 2023-07 redirect /u to /~username and /users (for tree)
get "/u", to: redirect("/users", status: 302)
get "/u/:username", to: redirect("/~%{username}", status: 302)
# we don't do /@alice but easy mistake with comments autolinking @alice
get "/@:username", to: redirect("/~%{username}", status: 302)
get "/u/:username/standing", to: redirect("~%{username}/standing", status: 302)
get "/newest/:user", to: redirect("~%{user}/stories", status: 302)
get "/newest/:user(/page/:page)", to: redirect("~%{user}/stories/page/%{page}", status: 302)
get "/threads/:user", to: redirect("~%{user}/threads", status: 302)
get "/avatars/:username_size.png" => "avatars#show"
post "/avatars/expire" => "avatars#expire"
post "/users/:username/ban" => "users#ban", :as => "user_ban"
post "/users/:username/unban" => "users#unban", :as => "user_unban"
post "/users/:username/disable_invitation" => "users#disable_invitation",
:as => "user_disable_invite"
post "/users/:username/enable_invitation" => "users#enable_invitation",
:as => "user_enable_invite"
get "/settings" => "settings#index"
post "/settings" => "settings#update"
post "/settings/delete_account" => "settings#delete_account",

View File

@ -51,7 +51,7 @@ class Markdowner
if User.exists?(:username => user[1..-1])
link = CommonMarker::Node.new(:link)
link.url = Rails.application.root_url + "u/#{user[1..-1]}"
link.url = Rails.application.root_url + "~#{user[1..-1]}"
node.insert_after(link)
link_text = CommonMarker::Node.new(:text)

View File

@ -10,7 +10,7 @@ describe Markdowner do
create(:user, :username => "blahblah")
expect(Markdowner.to_html("hi @blahblah test"))
.to eq("<p>hi <a href=\"https://lobste.rs/u/blahblah\" rel=\"ugc\">" +
.to eq("<p>hi <a href=\"https://lobste.rs/~blahblah\" rel=\"ugc\">" +
"@blahblah</a> test</p>\n")
expect(Markdowner.to_html("hi @flimflam test"))
@ -46,8 +46,8 @@ describe Markdowner do
.to eq("<p><a href=\"//example.com\" rel=\"ugc\">" +
"ex</a></p>\n")
expect(Markdowner.to_html("[ex](/u/abc)"))
.to eq("<p><a href=\"/u/abc\">ex</a></p>\n")
expect(Markdowner.to_html("[ex](/~abc)"))
.to eq("<p><a href=\"/~abc\">ex</a></p>\n")
end
context "when images are not allowed" do

View File

@ -5,7 +5,7 @@ describe 'users controller' do
it 'displays the username' do
user = create(:user)
get "/u/#{user.username}"
get "/~#{user.username}"
expect(response.body).to include(user.username)
end
@ -29,7 +29,7 @@ describe 'users controller' do
it "displays to the user" do
sign_in bad_user
get "/u/#{bad_user.username}/standing"
get "/~#{bad_user.username}/standing"
expect(response.body).to include("flags")
expect(response.body).to include("You")
end
@ -38,12 +38,12 @@ describe 'users controller' do
user2 = create(:user)
sign_in user2
get "/u/#{bad_user.username}/standing"
get "/~#{bad_user.username}/standing"
expect(response.status).to eq(302)
end
it "doesn't display to logged-out users" do
get "/u/#{bad_user.username}/standing"
get "/~#{bad_user.username}/standing"
expect(response.status).to eq(302)
end
@ -51,7 +51,7 @@ describe 'users controller' do
mod = create(:user, :moderator)
sign_in mod
get "/u/#{bad_user.username}/standing"
get "/~#{bad_user.username}/standing"
expect(response.body).to include("flags")
end
end

66
spec/routing/user_spec.rb Normal file
View File

@ -0,0 +1,66 @@
require 'rails_helper'
# rubocop:disable RSpec/MultipleDescribes
describe 'user routing' do
it 'users#tree' do
assert_routing(
'/users',
controller: 'users', action: 'tree'
)
end
it 'users#show' do
assert_routing(
'/~alice',
controller: 'users', action: 'show', username: 'alice'
)
end
it 'home#stories' do
assert_routing(
'/~alice/stories',
controller: 'home', action: 'newest_by_user', user: 'alice'
)
assert_routing(
'/~alice/stories/page/2',
controller: 'home', action: 'newest_by_user', user: 'alice', page: '2'
)
end
it 'comments#user_threads' do
assert_routing(
'/~alice/threads',
controller: 'comments', action: 'user_threads', user: 'alice'
)
end
end
# odd Rails limitation: you can redirect from routes but not test those from routing tests
describe 'user redirects', type: :request do
it 'old-style to tilde' do
expect(get('/u/alice')).to redirect_to('/~alice')
end
it 'user tree' do
expect(get('/u')).to redirect_to('/users')
end
it 'newest stories' do
expect(get('/newest/alice')).to redirect_to('/~alice/stories')
expect(get('/newest/alice/page/2')).to redirect_to('/~alice/stories/page/2')
end
it 'threads' do
expect(get('/threads/alice')).to redirect_to('/~alice/threads')
end
# 2023-07: I'm deploying with 302 redirects so I don't have to worry about 301s getting
# indefinitely cached in case of error, but after some time to build confidence, it's appropriate
# to 301. I'm putting a time bomb test in here to remind me to finalize.
it 'is temporarily temporary' do
expect(get('/u/alice')).to eq(302)
expect(Time.zone.today).to be_before(Date.new(2024, 1, 1))
end
end
# rubocop:enable RSpec/MultipleDescribes