users_controller.rb |
|
---|---|
class UsersController < ApplicationController
before_filter :find_user, :only => [:show, :edit, :update, :feed, :following, :followers]
def index
@title = "users"
set_params_page
begin
@authors = Author.search(params)
rescue RegexpError
flash[:error] = "Please enter a valid search term"
redirect_to users_path and return
end
unless @authors.empty?
@authors = @authors.paginate(:page => params[:page], :per_page => params[:per_page])
set_pagination_buttons(@authors, :search => params[:search])
end
end
def show
if @user.nil?
render :file => "#{Rails.root}/public/404", :status => 404
elsif @user.username != params[:id] # case difference
@title = @user.username
redirect_to user_path(@user)
else
set_params_page
@title = @user.username
@author = @user.author
@updates = @user.updates
@updates = @updates.paginate(:page => params[:page], :per_page => params[:per_page])
set_pagination_buttons(@updates)
headers['Link'] = "<#{user_xrd_path(@user.author)}>; rel=\"lrdd\"; type=\"application/xrd+xml\""
respond_to do |format|
format.json {
render :json => @updates.map{ |u| UpdateJsonDecorator.decorate(u) }
}
format.html
end
end
end
def edit |
|
While it might be cool to edit other people’s profiles, we probably shouldn’t let you do that. We’re no fun. |
if @user == current_user
render :edit
else
redirect_to user_path(params[:id])
end
end
def update
if @user == current_user
response = @user.edit_user_profile(params)
if response == true
unless @user.email.blank? || @user.email_confirmed
Notifier.send_confirm_email_notification(@user.email, @user.create_token)
flash[:notice] = "A link to confirm your updated email address has been sent to #{@user.email}."
else
flash[:notice] = "Profile saved!"
end
redirect_to user_path(params[:id])
else
flash[:error] = "Profile could not be saved: #{response}"
render :edit
end
else
redirect_to user_path(params[:id])
end
end
def new
params[:username] = session[:nickname]
@user = User.new
end
def create
params[:author] = Author.create_from_session!(session, params, root_url)
@user = User.new :email => params[:email],
:author => params[:author],
:username => params[:username],
:password => params[:password]
if @user.save
Authorization.create_from_session!(session, @user)
flash[:notice] = "Thanks! You're all signed up with #{@user.username} for your username."
session[:user_id] = @user.id
redirect_to root_path
else
render :new
end
end |
This is pretty much the same thing as /feeds/your_feed_id.atom, but we wanted to have a really nice URL for it, and not just the ugly one. |
def feed
if @user
redirect_to feed_path(@user.feed, :format => :atom)
else
render :file => "#{Rails.root}/public/404", :status => 404
end
end |
Who do you think is a really neat person? This page will show it to the world, so pick wisely! |
def following
if @user.nil?
render :file => "#{Rails.root}/public/404", :status => 404 |
If the username’s case entered in the URL is different than the case specified by that user, redirect to the case that the user prefers |
elsif @user.username != params[:id]
redirect_to following_path(@user.username)
else
set_params_page
@feeds = @user.following
@feeds = @feeds.paginate(:page => params[:page], :per_page => params[:per_page], :order => :id.desc)
set_pagination_buttons(@feeds)
@authors = @feeds.map{|f| f.author}
if @user == current_user
title = "You're following"
else
title = "@#{@user.username} is following"
end
respond_to do |format|
format.html { render "users/list", :locals => {:title => title, :list_class => "friends"} }
format.json { render :json => @authors }
end
end
end |
This shows off how cool you are: I hope you’ve got the biggest number of followers. Only one way to find out… |
def followers
if @user.nil?
render :file => "#{Rails.root}/public/404", :status => 404 |
If the username’s case entered in the URL is different than the case specified by that user, redirect to the case that the user prefers |
elsif @user.username != params[:id]
redirect_to followers_path(@user.username)
else
set_params_page
@feeds = @user.followers
@feeds = @feeds.paginate(:page => params[:page], :per_page => params[:per_page], :order => :id.desc)
set_pagination_buttons(@feeds)
@authors = @feeds.map{|f| f.author} |
build title |
if @user == current_user
title = "Your followers"
else
title = "@#{@user.username}'s followers"
end
render "users/list", :locals => {:title => title, :list_class => "followers"}
end
end |
If we can’t find a user in mongo or the token is expired give them some information and redirect. Once an email has been confirmed there is no reason to leave the token set so let’s nil it out. The reset token method runs save so we don’t need to do that anymore |
def confirm_email
user = User.first(:perishable_token => params[:token])
if user.nil?
flash[:error] = "Can't find User Account for this link."
redirect_to root_path
elsif user.token_expired?
flash[:error] = "Your link is no longer valid, please request a new one."
redirect_to root_path
else
user.email_confirmed = true
user.reset_perishable_token |
Register a session for the user |
session[:user_id] = user.id
flash[:notice] = "Email successfully confirmed."
redirect_to root_path
end
end |
Passwords can be reset by unauthenticated users by navigating to the forgot password and page and submitting the email address they provided. |
def forgot_password_new
render "login/forgot_password"
end |
We’ve got a pretty solid forgotten password implementation. It’s simple: the email address is looked up, if no user is found an error is provided. If a user is found a token is generated and an email is sent to the user with the url to reset their password. Users are then redirected to the confirmation page to prevent repost issues |
def forgot_password_create
unless params[:email] =~ /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
flash[:error] = "You didn't enter a correct email address. Please check your email and try again."
return render "login/forgot_password"
end
user = User.first(:email => params[:email])
if user.nil?
flash[:error] = "Your account could not be found, please check your email and try again."
render "login/forgot_password"
else
Notifier.send_forgot_password_notification(user.email, user.create_token) |
Redirect to try to avoid repost issues |
session[:fp_email] = user.email
redirect_to forgot_password_confirm_path
end
end |
Forgot password confirmation screen, displays email address that the email was sent to |
def forgot_password_confirm
@email = session.delete(:fp_email)
render "login/forgot_password_confirm"
end
def reset_password_new
if not logged_in?
redirect_to forgot_password_path
else
render "login/password_reset"
end
end |
Submitted passwords are checked for length and confirmation. Once the password has been reset the user is redirected to / |
def reset_password_create
user = nil
if params[:token]
user = User.first(:perishable_token => params[:token])
if user and user.token_expired?
user = nil
end
end
unless user.nil? |
XXX: yes, this is a code smell |
if params[:password].size == 0
flash[:error] = "Password must be present"
redirect_to reset_password_path(params[:token])
return
end
if params[:password] != params[:password_confirm]
flash[:error] = "Passwords do not match"
redirect_to reset_password_path(params[:token])
return
end |
TODO: This may be unreachable, since we don’t allow password reset without an email… look into this and remove this code if so. |
if user.email.nil?
if params[:email].empty?
flash[:error] = "Email must be provided"
redirect_to reset_password_path(params[:token])
return
else
user.email = params[:email]
end
end
user.password = params[:password]
user.save
flash[:notice] = "Password successfully set"
redirect_to root_path
else
redirect_to forgot_password_path
end
end |
Public reset password page, accessible via a valid token. Tokens are only valid for 2 days and are unique to that user. The user is found using the token and the reset password page is rendered |
def reset_password_with_token
user = User.first(:perishable_token => params[:token])
if user.nil? || user.token_expired?
flash[:error] = "Your link is no longer valid, please request a new one."
redirect_to forgot_password_path
else
@token = params[:token]
@user = user
render "login/password_reset"
end
end
private
def find_user
if @user = User.find_by_case_insensitive_username(params[:id])
@user = UserDecorator.decorate(@user)
end
end
end |