Class | LoginController
In: | app/controllers/login_controller.rb
Parent: | ApplicationController

This controller takes care of security.

Copyright (c) 2006 Logica

### Methods

auto_complete_for_user_email change_password confirm_account index login logout lost_password new_cadmin redirect2page report_password_reset_attempt sign_up

### Constants

FLASH_CENTRAL_ADMIN_ALREADY_CREATED | = | 'You can only create the central admin if this user has not been created yet!'
FLASH_INVALID_PW | = | 'Invalid combination of username password!'
FLASH_NO_VALID_TOKEN | = | 'Not a valid token!'
FLASH_PASSWORD_ACTIVATED | = | 'New password activated!'
FLASH_LOST_PASSWORD_ABUSE | = | 'A notification was sent to the administrator reporting the abuse of your email address'
FLASH_CENTRAL_ADMIN_CREATED | = | 'Central admin user created!'
FLASH_PW_SENT | = | 'Password sent!'
FLASH_PW_CONFIRMATION_EMAIL_SENT | = | 'A confirmation email has been sent to your email address. Please confirm your account by clicking on the hyperlink in this email'
FLASH_EMAIL_NOT_FOUND | = | 'Email address not found!'
FLASH_UNOT_ADMIN | = | "You are not an admin user!"
FLASH_UNOT_CADMIN | = | "You are not the central administrator!"

### Public Instance methods

auto_complete_for_user_email()

[Source]

         # File app/controllers/login_controller.rb, line 238
    238:   def auto_complete_for_user_email
    239:     search = params[:user][:email]
    240:     logger.debug("search:" + search)
    241:     @users = User.find(:all, :conditions => ["email like ?", search + "%"], :order => "email ASC") unless search.blank?
    242:     if @users.length == 1
    243:       render :inline => "<ul class=\"autocomplete_list\"><li class=\"autocomplete_item\"><%= @users[0].email %></li></ul>"
    244:     else
    245:       render :inline => "<ul class=\"autocomplete_list\"></ul>"
    246:     end
    247:   end

change_password()

Action change_password allows a user to change the password

[Source]

         # File app/controllers/login_controller.rb, line 106
    106:   def  change_password
    107:     @user= User.find(session['user'].id)
    108:     if  request.get?
    109:     else
    110:       @user.errors.add(:password, "Can't be blank") if params[:user][:password].blank? # blank? returns true if its receiver is nil or an empty string
    111:       @user.change_password(User.new(params[:user]))
    112:       if  @user.save
    113:         flash['success'] = 'Password was succesfully changed'
    114:       else
    115:         @user= User.find(session['user'].id)
    116:       end
    117:     end
    118:   end

confirm_account()

Action confirm_account is used to confirm a new password send by email. Without confirmation anyone could reset passwords. The token used for confirmation is just the new password hashed twice. The new password is stored in the column `confirmation_token`. Action resend_password is used to request a new password.

[Source]

        # File app/controllers/login_controller.rb, line 87
    87:   def confirm_account
    88:     @user = User.find(params[:id])
    89:     if  @user.confirm_account(params[:tk])
    90:       if  @user.save
    91:         flash['success'] = FLASH_PASSWORD_ACTIVATED
    92:       else
    93:         raise "Failed to activate account for #{@user.email}"
    94:       end
    95:     else
    96:       flash['error'] = FLASH_NO_VALID_TOKEN
    97:     end
    98:     redirect_to :action => 'login'
    99:   end

index()

[Source]

         # File app/controllers/login_controller.rb, line 131
    131:   def     index
    132:     redirect_to :action => 'login'
    133:   end

login()

Action login checks if there is a cookie. With ‘posts’ we try to login using User.try_to_login. If the user wants to be remembered a cookie is created. ‘Gets’ can login the user if the user has a good cookie.

[Source]

         # File app/controllers/login_controller.rb, line 169
    169:   def login
    170:     @wikis = Wiki.find(:all, :conditions => ['obsolete_on is null'])
    171:     @login_message = AdminMessage.find_by_guid('Login').text
    172:     if request.get?
    173:       if  cookies[:epfwiki_id] && User.exists?(cookies[:epfwiki_id])
    174:         logger.info("Found cookie and user with id " + cookies[:epfwiki_id])
    175:         @user = User.find(cookies[:epfwiki_id])
    176:         token = cookies[:epfwiki_token]
    177:         if @user.confirm_account(token)
    178:           logger.info("Token good, refresh cookies and login user")
    179:           create_cookie(@user) # refresh van cookie
    180:           @user.update_attributes({:http_user_agent => request.env['HTTP_USER_AGENT'], :ip_address => request.env['REMOTE_ADDR'] , :last_logon => Time.now, :logon_count => @user.logon_count + 1, :logon_using_cookie_count => @user.logon_using_cookie_count + 1})
    181:           session['user'] = @user
    182:           redirect2page
    183:         else
    184:           logger.info("An account was found but the token was not correct #{request.env.inspect}")
    185:           expire_cookie
    186:           session['user'] = nil
    187:           @user = User.new
    188:         end
    189:       else
    190:         logger.debug("Cookie not found, or user not found with id in cookie: #{cookies.inspect}, cookies['epfwiki_id']: #{cookies['epfwiki_id']}, User.exists?(cookies[:epfwiki_id]): #{User.exists?(cookies[:epfwiki_id])}")
    191:         expire_cookie # if it exists, it is invalid
    192:         @cadmin = User.find_central_admin
    193:         if  @cadmin
    194:                   logger.debug('Cadmin found, displaying the login form')
    195:           session['user'] = nil
    196:           @user = User.new
    197:         else
    198:           logger.debug('Cadmin not found, displaying form to create cadmin user')
    199:           redirect_to :action => 'new_cadmin'
    200:         end
    201:       end
    202:     else
    203:       @user = User.new(params[:user])
    204:       @logged_in_user = @user.try_to_login
    205:       if @logged_in_user
    206:         logger.info("Login succesfull")
    207:         session['user'] = @logged_in_user
    208:         if @user.remember_me == "0" # remember_me = 0, do not remember_me is 1
    209:           create_cookie(@logged_in_user)
    210:         end
    211:         @logged_in_user.update_attributes({:http_user_agent => request.env['HTTP_USER_AGENT'], :ip_address => request.env['REMOTE_ADDR'] , :last_logon => Time.now, :logon_count => @logged_in_user.logon_count + 1})
    212:         redirect2page
    213:       else
    214:         @user = User.new
    215:         flash['notice'] = FLASH_INVALID_PW
    216:         logger.info("Invalid combination of username password for #{@user.email}")
    217:       end
    218:     end
    219:   end

logout()

destroy the session and cookie redirect to login

[Source]

         # File app/controllers/login_controller.rb, line 222
    222:   def logout
    223:     session['user'] = nil
    224:     flash[:notice] = "Logged out"
    225:     redirect_to :action => "login"
    226:     expire_cookie
    227:   end

lost_password()

Generate a new password for a user and sends it in a email. The new password is activated after the user confirms it. The old passwords remains active, otherwise any user can disable accounts!

[Source]

         # File app/controllers/login_controller.rb, line 138
    138:   def lost_password
    139:     if  request.get?
    140:       @user = User.new
    141:     else
    142:       @user = User.new(params[:user])
    143:       logger.info('Finding user with email: ' + @user.email.downcase)
    144:       @user_by_email = User.find_by_email(@user.email.downcase)
    145:       if  @user_by_email
    146:         @user_by_email.set_new_pw
    147:         if  @user_by_email.save
    148:           urls = [url_for(:controller => 'login', :action => 'confirm_account', :id => @user_by_email.id, :tk => @user_by_email.token_new)]
    149:           urls << url_for(:constroller => 'login', :action => 'report_password_reset_attempt', :id => @user_by_email.id, :tk => @user_by_email.token_new)
    150:           Notifier::deliver_lost_password(@user_by_email, urls)
    151:           #Notifier::deliver_env_to(User.find_central_admin,
    152:           #                         session.instance_variable_get("@data"),
    153:           #params,
    154:           #request.env)
    155:           flash['success'] = FLASH_PW_SENT
    156:           redirect_to :action => "login"
    157:         else
    158:           logger.error(@user_by_email.errors.full_messages.join(', '))
    159:         end
    160:       else
    161:         @user.email = ""
    162:         flash['notice'] = FLASH_EMAIL_NOT_FOUND
    163:       end
    164:     end
    165:   end

new_cadmin()

Is be used to create the first user, the central admin account

[Source]

        # File app/controllers/login_controller.rb, line 39
    39:   def new_cadmin
    40:     if  User.count > 0
    41:       flash['error'] = FLASH_CENTRAL_ADMIN_ALREADY_CREATED
    42:       redirect_to :action => 'login'
    43:     else
    44:       if request.get?
    45:         @user = User.new
    46:       else
    47:         @user = User.new_cadmin(params[:user])
    48:         if  @user.save
    49:           flash['success'] = FLASH_CENTRAL_ADMIN_CREATED
    50:           redirect_to :action => 'login'
    51:         else
    52:           render :action => 'new_cadmin'
    53:         end
    54:       end
    55:     end
    56:   end

redirect2page()

[Source]

         # File app/controllers/login_controller.rb, line 229
    229:   def redirect2page
    230:     if session["return_to"]
    231:       redirect_to(session["return_to"])
    232:       session["return_to"] = nil
    233:     else
    234:       redirect_to :controller => "users", :action => "account"
    235:     end
    236:   end

report_password_reset_attempt()

With action report_password_reset_attempt users can report that they received a new password that they didn‘t request.

[Source]

         # File app/controllers/login_controller.rb, line 121
    121:   def report_password_reset_attempt
    122:     @user = User.find(params[:id])
    123:     Notifier::deliver_env_to(User.find_central_admin,
    124:                              session.instance_variable_get("@data"),
    125:     params,
    126:     request.env)
    127:     flash['notice'] = ::MSG_LOST_PASSWORD_ABUSE
    128:     redirect_to :controller => 'users', :action => 'show'
    129:   end

sign_up()

Action sign_up creates the account or displays the form to create the account. Passwords can be generated or supplied by the user. If passwords are supplied by the user the account needs to be confirmed, see confirm_account

[Source]

        # File app/controllers/login_controller.rb, line 62
    62:   def sign_up
    63:     if request.get?
    64:       @user = User.new
    65:     else
    66:       @user = User.new_signup(params[:user])
    67:       if @user.save
    68:         if ENV['EPFWIKI_GENERATE_PASSWORDS'] == '1'
    69:           flash['success'] =  FLASH_PW_SENT
    70:         else
    71:           flash['success'] =  FLASH_PW_CONFIRMATION_EMAIL_SENT
    72:         end
    73:         Notifier::deliver_welcome_pw_confirmationlink(@user, request.host + (request.port == 80 ? '' : ':' + request.port.to_s))
    74:         redirect_to :action => "login"
    75:       else
    76:         logger.info("Failed to save user on signup #{@user.inspect}")
    77:         @user.email = @user.email.gsub(@user.email_extension,"") if @user.email && @user.email_extension
    78:         @user.password = ""
    79:         @user.password_confirmation = ""
    80:       end
    81:     end
    82:   end

[Validate]