add an invitiation request queue

the user tree is pretty big to look through now, so let users submit
a request for an invitation, which logged-in users can browse and
instantly send invites to
This commit is contained in:
joshua stein 2013-10-18 15:49:20 -05:00
parent 3aa412087a
commit 66f433176a
10 changed files with 238 additions and 6 deletions

View file

@ -1,5 +1,27 @@
class InvitationsController < ApplicationController
before_filter :require_logged_in_user
before_filter :require_logged_in_user,
:except => [ :build, :create_by_request, :confirm_email ]
def build
end
def index
@invitation_requests = InvitationRequest.where(:is_verified => true)
end
def confirm_email
if !(ir = InvitationRequest.find_by_code(params[:code].to_s))
flash[:error] = "Invalid or expired invitation request"
return redirect_to "/invitations/request"
end
ir.is_verified = true
ir.save!
flash[:success] = "Your invitiation request has been validated and " <<
"will now be shown to other logged-in users."
return redirect_to "/invitations/request"
end
def create
i = Invitation.new
@ -26,4 +48,45 @@ class InvitationsController < ApplicationController
return redirect_to "/settings"
end
end
def create_by_request
ir = InvitationRequest.new
ir.name = params[:name]
ir.email = params[:email]
ir.memo = params[:memo]
ir.ip_address = request.remote_ip
if ir.save
flash[:success] = "You have been e-mailed a confirmation to " <<
params[:email].to_s << "."
return redirect_to "/invitations/request"
else
render :action => :build
end
end
def send_for_request
if !(ir = InvitationRequest.find_by_code(params[:code].to_s))
flash[:error] = "Invalid or expired invitation request"
return redirect_to "/invitations"
end
if ir.save
i = Invitation.new
i.user_id = @user.id
i.email = ir.email
if i.save
i.send_email
ir.destroy
flash[:success] = "Successfully e-mailed invitation to " <<
ir.name.to_s << "."
end
return redirect_to "/invitations"
else
render :action => :build
end
end
end

View file

@ -0,0 +1,14 @@
class InvitationRequestMailer < ActionMailer::Base
default :from => "#{Rails.application.name} " <<
"<nobody@#{Rails.application.domain}>"
def invitation_request(invitation_request)
@invitation_request = invitation_request
mail(
:to => invitation_request.email,
subject: "[#{Rails.application.name}] Confirm your invitation " <<
"request to " << Rails.application.name
)
end
end

View file

@ -0,0 +1,25 @@
class InvitationRequest < ActiveRecord::Base
attr_accessible nil
validates :name, :presence => true
validates :email, :format => { :with => /\A[^@ ]+@[^@ ]+\.[^@ ]+\Z/ }
before_validation :create_code
after_create :send_email
def create_code
(1...10).each do |tries|
if tries == 10
raise "too many hash collisions"
end
if !InvitationRequest.find_by_code(self.code = Utils.random_str(15))
break
end
end
end
def send_email
InvitationRequestMailer.invitation_request(self).deliver
end
end

View file

@ -0,0 +1,15 @@
Hello <%= @invitation_request.email %>,
Someone at <%= @invitation_request.ip_address %> has submitted an invitiation request to
<%= Rails.application.name %>.
Name: <%= @invitation_request.name %>
E-mail: <%= @invitation_request.email %> (won't be displayed to other users)
Memo: <%= @invitation_request.memo %>
If this is you, visit the URL below to confirm your request and
display it to other logged-in users.
<%= root_url %>invitations/confirm/<%= @invitation_request.code %>
If this is not you, you can delete this message.

View file

@ -0,0 +1,39 @@
<div class="box wide">
<div class="legend">
Request an Invitation
</div>
<p>
If you don't know (or can't find) an <a href="/u/">existing user</a> from
which to request an invitiation, 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.
</p>
<p>
Your e-mail address must be valid and confirmed by visiting a URL e-mailed to
you before your request will be displayed. Your e-mail address will not be
shown to any other users.
</p>
<%= form_tag create_invitation_by_request_url do %>
<p>
<%= label_tag :name, "Name:" %>
<%= text_field_tag :name, "", :size => 30 %>
<br />
<%= label_tag :email, "E-mail Address:" %>
<%= text_field_tag :email, "", :size => 30 %>
<br />
<%= label_tag :memo, "Memo:" %>
<%= text_field_tag :memo, "", :size => 75 %>
<br />
<label></label>
<span class="na">URL to your website, Github account, etc.</span>
</p>
<p>
<%= submit_tag "Request Invitiation" %>
</p>
<% end %>
</div>

View file

@ -0,0 +1,40 @@
<div class="box wide">
<div class="legend">
Requested Invitations
</div>
<p>
These persons have requested invitations and confirmed their e-mail
addresses. If you recognize anyone, feel free to send them an invitation and
remove their request. Spam will be cleared out by a moderator.
</p>
<table class="data" width="100%" cellspacing=0>
<tr>
<th width="20%">Date/Time</th>
<th width="15%">Name</th>
<th width="50%">Memo</th>
<th width="15%"></th>
</tr>
<% bit = 0 %>
<% @invitation_requests.each do |ir| %>
<tr class="row<%= bit %>">
<td><%= ir.created_at.strftime("%Y-%m-%d %H:%M:%S") %></td>
<td><%= ir.name %></td>
<td><%= ir.memo %></td>
<td><%= form_tag send_invitation_for_request_url, :confirm => "Are " <<
"you sure you want to invite this person and remove this request?" do %>
<%= hidden_field_tag "code", ir.code %>
<%= submit_tag "Send Invitiation" %>
<% end %></td>
</tr>
<% bit = (bit == 1 ? 0 : 1) %>
<% end %>
<% if @invitation_requests.count == 0 %>
<tr>
<td colspan=4 align="center"><span class="na">No invitation
requests</span></td>
</tr>
<% end %>
</table>
</div>

View file

@ -24,9 +24,10 @@
</p>
<p>
Not a user yet? 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.
Not a user yet? Signup is 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 <a href="/invitations/request">request one
publicly</a>.
</p>
<% end %>
</div>

View file

@ -1,7 +1,7 @@
Lobsters::Application.routes.draw do
root :to => "home#index",
:protocol => (Rails.env == "production" ? "https://" : "http://")
get "/rss" => "home#index", :format => "rss"
get "/hottest.json" => "home#index", :format => "json"
@ -77,6 +77,13 @@ Lobsters::Application.routes.draw do
post "/filters" => "filters#update"
post "/invitations" => "invitations#create"
get "/invitations" => "invitations#index"
get "/invitations/request" => "invitations#build"
post "/invitations/create_by_request" => "invitations#create_by_request",
:as => "create_invitation_by_request"
get "/invitations/confirm/:code" => "invitations#confirm_email"
post "/invitations/send_for_request" => "invitations#send_for_request",
:as => "send_invitation_for_request"
get "/invitations/:invitation_code" => "signup#invited"
get "/moderations" => "moderations#index"

View file

@ -0,0 +1,17 @@
class AddInvitationRequests < ActiveRecord::Migration
def up
create_table :invitation_requests do |t|
t.string :code
t.boolean :is_verified, :default => false
t.string :email
t.string :name
t.text :memo
t.string :ip_address
t.timestamps
end
end
def down
drop_table :invitation_requests
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130622021035) do
ActiveRecord::Schema.define(:version => 20131018201413) do
create_table "comments", :force => true do |t|
t.datetime "created_at", :null => false
@ -35,6 +35,17 @@ ActiveRecord::Schema.define(:version => 20130622021035) do
add_index "comments", ["story_id", "short_id"], :name => "story_id_short_id"
add_index "comments", ["thread_id"], :name => "thread_id"
create_table "invitation_requests", :force => true do |t|
t.string "code"
t.boolean "is_verified", :default => false
t.string "email"
t.string "name"
t.text "memo"
t.string "ip_address"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "invitations", :force => true do |t|
t.integer "user_id"
t.string "email"