PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/sorcery/controller.rb

https://github.com/aryansliet/sorcery
Ruby | 197 lines | 145 code | 29 blank | 23 comment | 12 complexity | 25a876450d7f3d1cef8e01576b0c4756 MD5 | raw file
  1. module Sorcery
  2. module Controller
  3. def self.included(klass)
  4. klass.class_eval do
  5. include InstanceMethods
  6. Config.submodules.each do |mod|
  7. begin
  8. include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
  9. rescue NameError
  10. # don't stop on a missing submodule.
  11. end
  12. end
  13. end
  14. Config.update!
  15. Config.configure!
  16. end
  17. module InstanceMethods
  18. # To be used as before_filter.
  19. # Will trigger auto-login attempts via the call to logged_in?
  20. # If all attempts to auto-login fail, the failure callback will be called.
  21. def require_login
  22. if !logged_in?
  23. session[:return_to_url] = request.url if Config.save_return_to_url
  24. self.send(Config.not_authenticated_action)
  25. end
  26. end
  27. # Takes credentials and returns a user on successful authentication.
  28. # Runs hooks after login or failed login.
  29. def login(*credentials)
  30. user = user_class.authenticate(*credentials)
  31. if user
  32. return_to_url = session[:return_to_url]
  33. reset_session # protect from session fixation attacks
  34. session[:return_to_url] = return_to_url
  35. auto_login(user)
  36. after_login!(user, credentials)
  37. current_user
  38. else
  39. after_failed_login!(credentials)
  40. nil
  41. end
  42. end
  43. # Resets the session and runs hooks before and after.
  44. def logout
  45. if logged_in?
  46. before_logout!(current_user)
  47. reset_session
  48. after_logout!
  49. end
  50. end
  51. def logged_in?
  52. !!current_user
  53. end
  54. # attempts to auto-login from the sources defined (session, basic_auth, cookie, etc.)
  55. # returns the logged in user if found, false if not (using old restful-authentication trick, nil != false).
  56. def current_user
  57. @current_user ||= login_from_session || login_from_other_sources unless @current_user == false
  58. end
  59. def current_user=(user)
  60. @current_user = user
  61. end
  62. # used when a user tries to access a page while logged out, is asked to login,
  63. # and we want to return him back to the page he originally wanted.
  64. def redirect_back_or_to(url, flash_hash = {})
  65. redirect_to(session[:return_to_url] || url, :flash => flash_hash)
  66. end
  67. # The default action for denying non-authenticated users.
  68. # You can override this method in your controllers,
  69. # or provide a different method in the configuration.
  70. def not_authenticated
  71. redirect_to root_path
  72. end
  73. # login a user instance
  74. #
  75. # @param [<User-Model>] user the user instance.
  76. # @return - do not depend on the return value.
  77. def auto_login(user)
  78. session[:user_id] = user.id
  79. @current_user = user
  80. end
  81. # Overwrite Rails' handle unverified request
  82. def handle_unverified_request
  83. cookies[:remember_me_token] = nil
  84. @current_user = nil
  85. super # call the default behaviour which resets the session
  86. end
  87. protected
  88. # Tries all available sources (methods) until one doesn't return false.
  89. def login_from_other_sources
  90. result = nil
  91. Config.login_sources.find do |source|
  92. result = send(source)
  93. end
  94. result || false
  95. end
  96. def login_from_session
  97. @current_user = (user_class.find_by_id(session[:user_id]) if session[:user_id]) || false
  98. end
  99. def after_login!(user, credentials)
  100. Config.after_login.each {|c| self.send(c, user, credentials)}
  101. end
  102. def after_failed_login!(credentials)
  103. Config.after_failed_login.each {|c| self.send(c, credentials)}
  104. end
  105. def before_logout!(user)
  106. Config.before_logout.each {|c| self.send(c, user)}
  107. end
  108. def after_logout!
  109. Config.after_logout.each {|c| self.send(c)}
  110. end
  111. def user_class
  112. @user_class ||= Config.user_class.to_s.constantize
  113. end
  114. end
  115. module Config
  116. class << self
  117. attr_accessor :submodules,
  118. :user_class, # what class to use as the user class.
  119. :not_authenticated_action, # what controller action to call for non-authenticated users.
  120. :save_return_to_url, # when a non logged in user tries to enter a page that requires
  121. # login, save the URL he wanted to reach,
  122. # and send him there after login.
  123. :sinatra_cookie_secret, # used to sign cookies in Sinatra.
  124. :login_sources,
  125. :after_login,
  126. :after_failed_login,
  127. :before_logout,
  128. :after_logout
  129. def init!
  130. @defaults = {
  131. :@user_class => nil,
  132. :@submodules => [],
  133. :@not_authenticated_action => :not_authenticated,
  134. :@login_sources => [],
  135. :@after_login => [],
  136. :@after_failed_login => [],
  137. :@before_logout => [],
  138. :@after_logout => [],
  139. :@save_return_to_url => true,
  140. :@sinatra_cookie_secret => 'ch4ng3M3plz'
  141. }
  142. end
  143. # Resets all configuration options to their default values.
  144. def reset!
  145. @defaults.each do |k,v|
  146. instance_variable_set(k,v)
  147. end
  148. end
  149. def update!
  150. @defaults.each do |k,v|
  151. instance_variable_set(k,v) if !instance_variable_defined?(k)
  152. end
  153. end
  154. def user_config(&blk)
  155. block_given? ? @user_config = blk : @user_config
  156. end
  157. def configure(&blk)
  158. @configure_blk = blk
  159. end
  160. def configure!
  161. @configure_blk.call(self) if @configure_blk
  162. end
  163. end
  164. init!
  165. reset!
  166. end
  167. end
  168. end