update authentication system to Devise
This commit is contained in:
@ -1,11 +1,14 @@
|
||||
class ApplicationController < ActionController::Base
|
||||
skip_before_filter :verify_authenticity_token
|
||||
# include all helpers for controllers
|
||||
helper :all
|
||||
# include these helper methods for views
|
||||
helper_method :current_user_session, :current_user, :logged_in?, :is_admin?, :get_header_value, :to_bytes
|
||||
protect_from_forgery
|
||||
before_filter :allow_cross_domain_access, :set_variables
|
||||
before_filter :configure_permitted_parameters, if: :devise_controller?
|
||||
after_filter :remove_headers
|
||||
before_filter :authenticate_user_from_token!
|
||||
|
||||
# responds with blank
|
||||
def respond_with_blank
|
||||
@ -44,6 +47,9 @@ class ApplicationController < ActionController::Base
|
||||
params[:sum] = '1440' if params[:sum] == 'daily'
|
||||
end
|
||||
|
||||
# change default devise sign_in page
|
||||
def after_sign_in_path_for(resource); channels_path; end
|
||||
|
||||
# get the locale, but don't fail if header value doesn't exist
|
||||
def get_locale
|
||||
locale = get_header_value('HTTP_ACCEPT_LANGUAGE')
|
||||
@ -59,8 +65,30 @@ class ApplicationController < ActionController::Base
|
||||
return locale
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:login, :email, :password, :password_confirmation, :remember_me) }
|
||||
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :email, :password, :remember_me) }
|
||||
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:login, :email, :password, :password_confirmation, :time_zone, :password_current) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# authenticates user based on token from users#api_login
|
||||
def authenticate_user_from_token!
|
||||
# exit if no login or token
|
||||
return false if params[:login].blank? || params[:token].blank?
|
||||
|
||||
# get the user by login or email
|
||||
user = User.find_by_login_or_email(params[:login])
|
||||
|
||||
# safe compare, avoids timing attacks
|
||||
if user.present? && Devise.secure_compare(user.authentication_token, params[:token])
|
||||
sign_in user, store: false
|
||||
end
|
||||
end
|
||||
|
||||
# remove headers if necessary
|
||||
def remove_headers
|
||||
response.headers.delete_if {|key| true} if params[:headers] == 'false'
|
||||
@ -80,7 +108,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# check that user's email address matches admin
|
||||
def is_admin?
|
||||
current_user && ADMIN_EMAILS.include?(current_user.email)
|
||||
current_user.present? && ADMIN_EMAILS.include?(current_user.email)
|
||||
end
|
||||
|
||||
def set_admin_menu
|
||||
@ -104,16 +132,6 @@ class ApplicationController < ActionController::Base
|
||||
def set_plugins_menu; @menu = 'plugins'; end
|
||||
def set_devices_menu; @menu = 'devices'; end
|
||||
|
||||
def current_user_session
|
||||
return @current_user_session if defined?(@current_user_session)
|
||||
@current_user_session = UserSession.find
|
||||
end
|
||||
|
||||
def current_user
|
||||
return @current_user if defined?(@current_user)
|
||||
@current_user = current_user_session && current_user_session.record
|
||||
end
|
||||
|
||||
def require_user
|
||||
logger.info "Require User"
|
||||
if current_user.nil?
|
||||
@ -273,9 +291,6 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# options: days = how many days ago, start = start date, end = end date, offset = timezone offset
|
||||
def get_date_range(params)
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
|
||||
# allow more past data if necessary
|
||||
get_old_data = (params[:results].present? || params[:start].present? || params[:days].present?) ? true : false
|
||||
|
||||
@ -290,8 +305,6 @@ class ApplicationController < ActionController::Base
|
||||
return date_range
|
||||
end
|
||||
|
||||
|
||||
|
||||
def set_time_zone(params)
|
||||
# set timezone correctly
|
||||
if params[:offset]
|
||||
|
@ -35,20 +35,20 @@ class ChannelsController < ApplicationController
|
||||
|
||||
# get channels by ids
|
||||
if params[:channel_ids].present?
|
||||
flash[:notice] = t(:selected_channels)
|
||||
@header = t(:selected_channels)
|
||||
@channels = Channel.public_viewable.by_array(params[:channel_ids]).order('ranking desc, updated_at DESC').paginate :page => params[:page]
|
||||
# get channels that match a user
|
||||
elsif params[:username].present?
|
||||
flash[:notice] = "#{t(:user).capitalize}: #{params[:username]}"
|
||||
@header = "#{t(:user).capitalize}: #{params[:username]}"
|
||||
searched_user = User.find_by_login(params[:username])
|
||||
@channels = searched_user.channels.public_viewable.active.order('ranking desc, updated_at DESC').paginate :page => params[:page] if searched_user.present?
|
||||
# get channels that match a tag
|
||||
elsif params[:tag].present?
|
||||
flash[:notice] = "#{t(:tag).capitalize}: #{params[:tag]}"
|
||||
@header = "#{t(:tag).capitalize}: #{params[:tag]}"
|
||||
@channels = Channel.public_viewable.active.order('ranking desc, updated_at DESC').with_tag(params[:tag]).paginate :page => params[:page]
|
||||
# normal channel list
|
||||
else
|
||||
flash[:notice] = t(:featured_channels)
|
||||
@header = t(:featured_channels)
|
||||
respond_with_error(:error_resource_not_found) and return if params[:page] == '0'
|
||||
@channels = Channel.public_viewable.active.order('ranking desc, updated_at DESC').paginate :page => params[:page]
|
||||
end
|
||||
|
@ -16,7 +16,7 @@ class CommentsController < ApplicationController
|
||||
@comment.body = params[:comment][:body].gsub(/<\/?[^>]*>/, '').gsub(/\n/, '<br />')
|
||||
# save comment
|
||||
if @comment.save
|
||||
flash[:success] = "Thanks for adding a comment!"
|
||||
flash[:notice] = "Thanks for adding a comment!"
|
||||
else
|
||||
flash[:error] = "Comment can't be blank!"
|
||||
end
|
||||
@ -45,3 +45,4 @@ class CommentsController < ApplicationController
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
|
22
app/controllers/registrations_controller.rb
Normal file
22
app/controllers/registrations_controller.rb
Normal file
@ -0,0 +1,22 @@
|
||||
class RegistrationsController < Devise::RegistrationsController
|
||||
include KeyUtilities
|
||||
after_filter :add_api_key, :only => :create
|
||||
|
||||
# use defaults from devise
|
||||
def new; super; end
|
||||
def new; super; end
|
||||
def create; super; end
|
||||
|
||||
private
|
||||
|
||||
# adds an api key to the new user
|
||||
def add_api_key
|
||||
@user = current_user
|
||||
if @user.present?
|
||||
@user.api_key = generate_api_key(16, 'user')
|
||||
@user.save
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
32
app/controllers/sessions_controller.rb
Normal file
32
app/controllers/sessions_controller.rb
Normal file
@ -0,0 +1,32 @@
|
||||
class SessionsController < Devise::SessionsController
|
||||
after_filter :log_failed_login, :only => :new
|
||||
|
||||
# don't modify default devise controllers
|
||||
def create; super; end
|
||||
def new; super; end
|
||||
|
||||
private
|
||||
|
||||
# logs failed login attempts
|
||||
def log_failed_login
|
||||
if failed_login?
|
||||
# log to failedlogins
|
||||
failed = Failedlogin.new
|
||||
failed.login = params['user']['login']
|
||||
failed.password = params['user']['password']
|
||||
failed.ip_address = get_header_value('X_REAL_IP')
|
||||
failed.save
|
||||
|
||||
# prevent timing and brute force password attacks
|
||||
sleep 1
|
||||
end
|
||||
end
|
||||
|
||||
# true if a login fails
|
||||
def failed_login?
|
||||
options = env["warden.options"]
|
||||
return (options.present? && options[:action] == "unauthenticated")
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,55 +0,0 @@
|
||||
class UserSessionsController < ApplicationController
|
||||
before_filter :require_no_user, :only => [:new, :create]
|
||||
before_filter :require_user, :only => :destroy
|
||||
|
||||
def new
|
||||
@title = t(:signin)
|
||||
@user_session = UserSession.new
|
||||
@mail_message = session[:mail_message] if !session[:mail_message].nil?
|
||||
end
|
||||
|
||||
def show
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
if params[:userlogin].length > 0
|
||||
render :text => ''
|
||||
else
|
||||
@user_session = UserSession.new(params[:user_session])
|
||||
|
||||
# remember user_id if checkbox is checked
|
||||
if params[:user_session][:remember_id] == '1'
|
||||
cookies['user_id'] = { :value => params[:user_session][:login], :expires => 1.month.from_now }
|
||||
else
|
||||
cookies.delete 'user_id'
|
||||
end
|
||||
|
||||
if @user_session.save
|
||||
# if link_back, redirect back
|
||||
redirect_to session[:link_back] and return if session[:link_back]
|
||||
redirect_to channels_path and return
|
||||
else
|
||||
# log to failedlogins
|
||||
failed = Failedlogin.new
|
||||
failed.login = params[:user_session][:login]
|
||||
failed.password = params[:user_session][:password]
|
||||
failed.ip_address = get_header_value('X_REAL_IP')
|
||||
failed.save
|
||||
|
||||
# prevent timing and brute force password attacks
|
||||
sleep 1
|
||||
@failed = true
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
session[:link_back] = nil
|
||||
current_user_session.destroy
|
||||
reset_session
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
@ -1,7 +1,27 @@
|
||||
class UsersController < ApplicationController
|
||||
include KeyUtilities
|
||||
before_filter :require_no_user, :only => [:new, :create, :forgot_password]
|
||||
before_filter :require_user, :only => [:show, :edit, :update, :change_password, :edit_profile]
|
||||
skip_before_filter :verify_authenticity_token, :only => [:api_login]
|
||||
before_filter :require_user, :only => [:show, :edit, :update, :edit_profile]
|
||||
|
||||
# allow login via api
|
||||
def api_login
|
||||
# get the user by login or email
|
||||
user = User.find_by_login_or_email(params[:login])
|
||||
|
||||
# exit if no user or invalid password
|
||||
respond_with_error(:error_auth_required) and return if user.blank? || !user.valid_password?(params[:password])
|
||||
|
||||
# save new authentication token
|
||||
user.authentication_token = Devise.friendly_token
|
||||
user.save
|
||||
|
||||
# output the user with token
|
||||
respond_to do |format|
|
||||
format.json { render :json => user.as_json(User.private_options_plus(:authentication_token)) }
|
||||
format.xml { render :xml => user.to_xml(User.private_options_plus(:authentication_token)) }
|
||||
format.any { render :text => user.authentication_token }
|
||||
end
|
||||
end
|
||||
|
||||
# generates a new api key
|
||||
def new_api_key
|
||||
@ -34,8 +54,8 @@ class UsersController < ApplicationController
|
||||
|
||||
# if a json or xml request
|
||||
if request.format == :json || request.format == :xml
|
||||
# authenticate the user if api key matches the target user
|
||||
authenticated = (User.find_by_api_key(get_apikey) == @user)
|
||||
# authenticate the user if the user is logged in (can be via token) or api key matches the target user
|
||||
authenticated = (current_user == @user) || (User.find_by_api_key(get_apikey) == @user)
|
||||
# set options correctly
|
||||
options = authenticated ? User.private_options : User.public_options(@user)
|
||||
end
|
||||
@ -75,27 +95,6 @@ class UsersController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@title = t(:signup)
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
def create
|
||||
@user = User.new(user_params)
|
||||
@user.api_key = generate_api_key(16, 'user')
|
||||
|
||||
# save user
|
||||
if @user.valid?
|
||||
|
||||
if @user.save
|
||||
redirect_back_or_default channels_path and return
|
||||
end
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def show
|
||||
@menu = 'account'
|
||||
@user = @current_user
|
||||
@ -106,48 +105,18 @@ class UsersController < ApplicationController
|
||||
@user = @current_user
|
||||
end
|
||||
|
||||
# displays forgot password page
|
||||
def forgot_password
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
# this action is called from an email link when a password reset is requested
|
||||
def reset_password
|
||||
# if user has been logged in (due to previous form submission)
|
||||
if !current_user.nil?
|
||||
@user = current_user
|
||||
@user.errors.add(:base, t(:password_problem))
|
||||
@valid_link = true
|
||||
else
|
||||
@user = User.find_by_id(params[:id])
|
||||
# make sure tokens match and password reset is within last 10 minutes
|
||||
if @user.perishable_token == params[:token] && @user.updated_at > 600.seconds.ago
|
||||
@valid_link = true
|
||||
# log the user in
|
||||
@user_session = UserSession.new(@user)
|
||||
@user_session.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# do the actual password change
|
||||
def change_password
|
||||
@user = current_user
|
||||
# if no password entered, redirect
|
||||
redirect_to reset_password_path and return if params[:user][:password].empty?
|
||||
# check current password and update
|
||||
if @user.update_attributes(user_params)
|
||||
redirect_to account_path
|
||||
else
|
||||
redirect_to reset_password_path
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@menu = 'account'
|
||||
@user = @current_user # makes our views "cleaner" and more consistent
|
||||
|
||||
# delete password and confirmation from params if not present
|
||||
params[:user].delete(:password) if params[:user][:password].blank?
|
||||
|
||||
# check current password and update
|
||||
if @user.valid_password?(params[:password_current]) && @user.update_attributes(user_params)
|
||||
if @user.valid_password?(params[:user][:password_current]) && @user.update_attributes(user_params)
|
||||
# sign the user back in, since devise will log the user out on update
|
||||
sign_in(current_user, :bypass => true)
|
||||
flash[:notice] = t('devise.registrations.updated')
|
||||
redirect_to account_path
|
||||
else
|
||||
@user.errors.add(:base, t(:password_incorrect))
|
||||
|
Reference in New Issue
Block a user