module Rodauth

  1. lib/rodauth.rb
  2. lib/rodauth/features/account_expiration.rb
  3. lib/rodauth/features/base.rb
  4. lib/rodauth/features/change_login.rb
  5. lib/rodauth/features/change_password.rb
  6. lib/rodauth/features/change_password_notify.rb
  7. lib/rodauth/features/close_account.rb
  8. lib/rodauth/features/confirm_password.rb
  9. lib/rodauth/features/create_account.rb
  10. lib/rodauth/features/disallow_common_passwords.rb
  11. lib/rodauth/features/disallow_password_reuse.rb
  12. lib/rodauth/features/email_auth.rb
  13. lib/rodauth/features/email_base.rb
  14. lib/rodauth/features/http_basic_auth.rb
  15. lib/rodauth/features/jwt.rb
  16. lib/rodauth/features/lockout.rb
  17. lib/rodauth/features/login.rb
  18. lib/rodauth/features/login_password_requirements_base.rb
  19. lib/rodauth/features/logout.rb
  20. lib/rodauth/features/otp.rb
  21. lib/rodauth/features/password_complexity.rb
  22. lib/rodauth/features/password_expiration.rb
  23. lib/rodauth/features/password_grace_period.rb
  24. lib/rodauth/features/recovery_codes.rb
  25. lib/rodauth/features/remember.rb
  26. lib/rodauth/features/reset_password.rb
  27. lib/rodauth/features/session_expiration.rb
  28. lib/rodauth/features/single_session.rb
  29. lib/rodauth/features/sms_codes.rb
  30. lib/rodauth/features/two_factor_base.rb
  31. lib/rodauth/features/update_password_hash.rb
  32. lib/rodauth/features/verify_account.rb
  33. lib/rodauth/features/verify_account_grace_period.rb
  34. lib/rodauth/features/verify_change_login.rb
  35. lib/rodauth/features/verify_login_change.rb
  36. lib/rodauth/migrations.rb
  37. lib/rodauth/version.rb
  38. show all

Methods

Public Class

  1. configure
  2. create_database_authentication_functions
  3. create_database_previous_password_check_functions
  4. drop_database_authentication_functions
  5. drop_database_previous_password_check_functions
  6. load_dependencies
  7. new
  8. version

Public Instance

  1. _account_from_email_auth_key
  2. _account_from_login
  3. _account_from_reset_password_key
  4. _account_from_session
  5. _account_from_unlock_key
  6. _account_from_verify_account_key
  7. _account_from_verify_login_change_key
  8. _email_auth_request
  9. _json_response_body
  10. _login
  11. _new_account
  12. _otp
  13. _otp_add_key
  14. _otp_key
  15. _otp_tmp_key
  16. _recovery_codes
  17. _sms
  18. _two_factor_auth_required_redirect
  19. _update_login
  20. _view
  21. _view_opts
  22. account_activity_ds
  23. account_ds
  24. account_expired?
  25. account_expired_at
  26. account_from_email_auth_key
  27. account_from_key
  28. account_from_login
  29. account_from_reset_password_key
  30. account_from_session
  31. account_from_unlock_key
  32. account_from_verify_account_key
  33. account_from_verify_login_change_key
  34. account_id
  35. account_in_unverified_grace_period?
  36. account_initial_status_value
  37. account_lockouts_ds
  38. account_login_failures_ds
  39. account_model
  40. account_password_hash_column
  41. account_session_status_filter
  42. active_remember_key_ds
  43. add_previous_password_hash
  44. add_recovery_code
  45. add_recovery_codes
  46. add_remember_key
  47. after_change_login
  48. after_change_password
  49. after_close_account
  50. after_confirm_password
  51. after_create_account
  52. after_login
  53. after_login_entered_during_multi_phase_login
  54. after_login_failure
  55. after_logout
  56. after_reset_password
  57. allow_resending_verify_account_email?
  58. already_logged_in
  59. auth_class_eval
  60. authenticated?
  61. before_change_login_route
  62. before_change_password_route
  63. before_login_attempt
  64. before_logout
  65. before_otp_authentication_route
  66. before_reset_password
  67. before_reset_password_request
  68. before_rodauth
  69. before_unlock_account
  70. before_unlock_account_request
  71. before_view_recovery_codes
  72. button
  73. button_opts
  74. can_add_recovery_codes?
  75. catch_error
  76. change_login
  77. change_login_notice_flash
  78. change_login_requires_password?
  79. change_password_requires_password?
  80. check_account_expiration
  81. check_already_logged_in
  82. check_password_change_allowed
  83. check_session_expiration
  84. check_single_session
  85. clear_cached_otp
  86. clear_invalid_login_attempts
  87. clear_remembered_session_key
  88. clear_session
  89. close_account
  90. close_account_requires_password?
  91. confirm_password
  92. confirm_password_redirect
  93. convert_session_key
  94. convert_timestamp
  95. create_account_autologin?
  96. create_account_link
  97. create_account_notice_flash
  98. create_account_set_password?
  99. create_email
  100. create_email_auth_email
  101. create_email_auth_key
  102. create_email_to
  103. create_password_changed_email
  104. create_reset_password_email
  105. create_reset_password_key
  106. create_unlock_account_email
  107. create_verify_account_email
  108. create_verify_account_key
  109. create_verify_login_change_email
  110. create_verify_login_change_key
  111. csrf_tag
  112. currently_active_session?
  113. db
  114. delete_account
  115. delete_account_on_close?
  116. disable_remember_login
  117. email_auth_ds
  118. email_auth_email_body
  119. email_auth_email_link
  120. email_auth_email_recently_sent?
  121. email_auth_key_insert_hash
  122. email_auth_request_form
  123. email_from
  124. email_to
  125. expire_session
  126. features
  127. field_error
  128. flash
  129. force_email_auth?
  130. forget_login
  131. function_name
  132. generate_email_auth_key_value
  133. generate_remember_key_value
  134. generate_reset_password_key_value
  135. generate_unlock_account_key
  136. generate_verify_account_key_value
  137. generate_verify_login_change_key_value
  138. get_activity_timestamp
  139. get_email_auth_email_last_sent
  140. get_email_auth_key
  141. get_password_changed_at
  142. get_password_hash
  143. get_password_reset_key
  144. get_remember_key
  145. get_reset_password_email_last_sent
  146. get_unlock_account_email_last_sent
  147. get_unlock_account_key
  148. get_verify_account_email_last_sent
  149. get_verify_account_key
  150. get_verify_login_change_login_and_key
  151. include_success_messages?
  152. invalid_login_attempted
  153. invalid_previous_password_message
  154. json_request?
  155. json_response
  156. jwt_payload
  157. jwt_secret
  158. jwt_session_hash
  159. jwt_token
  160. last_account_activity_at
  161. last_account_login_at
  162. load_memory
  163. loaded_templates
  164. locked_out?
  165. logged_in_via_remember_key?
  166. login_confirm_label
  167. login_does_not_meet_requirements_message
  168. login_failed_reset_password_request_form
  169. login_form_footer
  170. login_hidden_field
  171. login_meets_email_requirements?
  172. login_meets_length_requirements?
  173. login_meets_requirements?
  174. login_required
  175. login_too_long_message
  176. login_too_short_message
  177. logout
  178. modifications_require_password?
  179. new_account
  180. new_recovery_code
  181. no_longer_active_session
  182. only_json?
  183. open_account?
  184. otp_add_key
  185. otp_auth_form_footer
  186. otp_exists?
  187. otp_issuer
  188. otp_key_ds
  189. otp_locked_out?
  190. otp_lockout_error_flash
  191. otp_lockout_redirect
  192. otp_new_secret
  193. otp_provisioning_name
  194. otp_provisioning_uri
  195. otp_qr_code
  196. otp_record_authentication_failure
  197. otp_remove
  198. otp_remove_auth_failures
  199. otp_tmp_key
  200. otp_update_last_use
  201. otp_valid_code?
  202. otp_valid_key?
  203. param
  204. param_or_nil
  205. password_changed_email_body
  206. password_confirm_label
  207. password_does_not_contain_null_byte?
  208. password_does_not_meet_requirements_message
  209. password_doesnt_match_previous_password?
  210. password_expiration_ds
  211. password_expired?
  212. password_has_enough_character_groups?
  213. password_has_no_invalid_pattern?
  214. password_hash
  215. password_hash_cost
  216. password_hash_ds
  217. password_match?
  218. password_meets_length_requirements?
  219. password_meets_requirements?
  220. password_not_in_dictionary?
  221. password_not_one_of_the_most_common?
  222. password_not_too_many_repeating_characters?
  223. password_one_of_most_common?
  224. password_recently_entered?
  225. password_reset_ds
  226. password_too_many_repeating_characters_message
  227. password_too_short_message
  228. post_configure
  229. previous_password_ds
  230. raises_uniqueness_violation?
  231. random_key
  232. recovery_code_match?
  233. recovery_codes_ds
  234. recovery_codes_primary?
  235. recovery_codes_remove
  236. redirect
  237. remember_key_ds
  238. remember_login
  239. remove_email_auth_key
  240. remove_lockout_metadata
  241. remove_remember_key
  242. remove_reset_password_key
  243. remove_verify_account_key
  244. remove_verify_login_change_key
  245. render
  246. request
  247. require_account
  248. require_account_session
  249. require_authentication
  250. require_current_password
  251. require_login
  252. require_otp_setup
  253. require_sms_available
  254. require_sms_not_setup
  255. require_sms_setup
  256. require_two_factor_authenticated
  257. require_two_factor_not_authenticated
  258. require_two_factor_setup
  259. reset_password_email_body
  260. reset_password_email_link
  261. reset_password_email_recently_sent?
  262. reset_password_key_insert_hash
  263. reset_password_request_link
  264. reset_single_session_key
  265. response
  266. retry_on_uniqueness_violation
  267. return_json_response
  268. route!
  269. save_account
  270. send_email_auth_email
  271. send_password_changed_email
  272. send_reset_password_email
  273. send_unlock_account_email
  274. send_verify_account_email
  275. send_verify_login_change_email
  276. session
  277. session_expiration_redirect
  278. session_jwt
  279. session_value
  280. set_deadline_value
  281. set_deadline_values?
  282. set_email_auth_email_last_sent
  283. set_error_flash
  284. set_expired
  285. set_field_error
  286. set_http_basic_auth_error_response
  287. set_jwt
  288. set_jwt_token
  289. set_last_password_entry
  290. set_new_account_password
  291. set_notice_flash
  292. set_notice_now_flash
  293. set_password
  294. set_redirect_error_flash
  295. set_redirect_error_status
  296. set_reset_password_email_last_sent
  297. set_response_error_status
  298. set_session_value
  299. set_title
  300. set_unlock_account_email_last_sent
  301. set_verify_account_email_last_sent
  302. setup_account_verification
  303. show_lockout_page
  304. single_session_ds
  305. skip_login_field_on_login?
  306. skip_password_field_on_login?
  307. skip_status_checks?
  308. sms_auth_message
  309. sms_available?
  310. sms_code
  311. sms_code_issued_at
  312. sms_code_match?
  313. sms_codes_primary?
  314. sms_confirm
  315. sms_confirm_failure
  316. sms_confirm_message
  317. sms_confirmation_match?
  318. sms_current_auth?
  319. sms_disable
  320. sms_ds
  321. sms_failures
  322. sms_locked_out?
  323. sms_needs_confirmation?
  324. sms_new_auth_code
  325. sms_new_confirm_code
  326. sms_normalize_phone
  327. sms_phone
  328. sms_record_failure
  329. sms_remove_failures
  330. sms_send
  331. sms_send_auth_code
  332. sms_send_confirm_code
  333. sms_set_code
  334. sms_setup
  335. sms_setup?
  336. sms_valid_phone?
  337. split_token
  338. template_path
  339. throw_basic_auth_error
  340. throw_error
  341. throw_error_status
  342. timing_safe_eql?
  343. token_link
  344. transaction
  345. two_factor_auth_fallback_redirect
  346. two_factor_auth_required_redirect
  347. two_factor_authenticate
  348. two_factor_authenticated?
  349. two_factor_authentication_setup?
  350. two_factor_modifications_require_password?
  351. two_factor_need_setup_redirect
  352. two_factor_password_match?
  353. two_factor_remove
  354. two_factor_remove_auth_failures
  355. two_factor_remove_session
  356. two_factor_update_session
  357. unique_constraint_violation_class
  358. unlock_account
  359. unlock_account_email_body
  360. unlock_account_email_link
  361. unlock_account_email_recently_sent?
  362. update_account
  363. update_activity
  364. update_hash_ds
  365. update_last_activity
  366. update_last_login
  367. update_login
  368. update_password_changed_at
  369. update_password_hash?
  370. update_session
  371. update_single_session_key
  372. update_sms
  373. use_database_authentication_functions?
  374. use_date_arithmetic?
  375. use_jwt?
  376. use_multi_phase_login?
  377. use_request_specific_csrf_tokens?
  378. uses_two_factor_authentication?
  379. valid_jwt?
  380. verified_account?
  381. verify_account
  382. verify_account_check_already_logged_in
  383. verify_account_ds
  384. verify_account_email_body
  385. verify_account_email_link
  386. verify_account_email_recently_sent?
  387. verify_account_email_resend
  388. verify_account_key_insert_hash
  389. verify_account_resend_link
  390. verify_login_change
  391. verify_login_change_ds
  392. verify_login_change_email_body
  393. verify_login_change_email_link
  394. verify_login_change_key_insert_hash
  395. verify_login_change_old_login
  396. view

Constants

FEATURES = {}  
MAJOR = 1  

The major version of Rodauth, updated only for major changes that are likely to require modification to apps using Rodauth.

MINOR = 19  

The minor version of Rodauth, updated for new feature releases of Rodauth.

TINY = 0  

The patch version of Rodauth, updated only for bug fixes from the last feature release.

VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze  

The full version of Rodauth as a string

VERSION_NUMBER = MAJOR*10000 + MINOR*100 + TINY  

The full version of Rodauth as a number (1.17.0 => 11700)

Public Instance Aliases

account_session_value -> account_id
ignore_uniqueness_violation -> raises_uniqueness_violation?

If you just want to ignore uniqueness violations, this alias makes more sense.

logged_in? -> session_value
raised_uniqueness_violation -> raises_uniqueness_violation?

If you would like to operate/reraise the exception, this alias makes more sense.

Public Class methods

configure (app, opts={}, &block)
[show source]
# File lib/rodauth.rb, line 32
def self.configure(app, opts={}, &block)
  app.opts[:rodauth_json] = opts.fetch(:json, app.opts[:rodauth_json])
  app.opts[:rodauth_csrf] = opts.fetch(:csrf, app.opts[:rodauth_route_csrf])
  auth_class = (app.opts[:rodauths] ||= {})[opts[:name]] ||= Class.new(Auth)
  if !auth_class.roda_class
    auth_class.roda_class = app
  elsif auth_class.roda_class != app
    auth_class = app.opts[:rodauths][opts[:name]] = Class.new(auth_class)
    auth_class.roda_class = app
  end
  auth_class.configure(&block)
end
create_database_authentication_functions (db, opts={})
[show source]
# File lib/rodauth/migrations.rb, line 3
  def self.create_database_authentication_functions(db, opts={})
    table_name = opts[:table_name] || :account_password_hashes
    get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
    valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash 

    case db.database_type
    when :postgres
      search_path = opts[:search_path] || 'public, pg_temp'

      db.run <<END
CREATE OR REPLACE FUNCTION #{get_salt_name}(acct_id int8) RETURNS text AS $$
DECLARE salt text;
BEGIN
SELECT substr(password_hash, 0, 30) INTO salt 
FROM #{table_name}
WHERE acct_id = id;
RETURN salt;
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = #{search_path};
END

      db.run <<END
CREATE OR REPLACE FUNCTION #{valid_hash_name}(acct_id int8, hash text) RETURNS boolean AS $$
DECLARE valid boolean;
BEGIN
SELECT password_hash = hash INTO valid 
FROM #{table_name}
WHERE acct_id = id;
RETURN valid;
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = #{search_path};
END
    when :mysql
      db.run <<END
CREATE FUNCTION #{get_salt_name}(acct_id int8) RETURNS varchar(255)
SQL SECURITY DEFINER
READS SQL DATA
BEGIN
RETURN (SELECT substr(password_hash, 1, 30)
FROM #{table_name}
WHERE acct_id = id);
END;
END

      db.run <<END
CREATE FUNCTION #{valid_hash_name}(acct_id int8, hash varchar(255)) RETURNS tinyint(1)
SQL SECURITY DEFINER
READS SQL DATA
BEGIN
DECLARE valid tinyint(1);
DECLARE csr CURSOR FOR 
SELECT password_hash = hash
FROM #{table_name}
WHERE acct_id = id;
OPEN csr;
FETCH csr INTO valid;
CLOSE csr;
RETURN valid;
END;
END
    when :mssql
      db.run <<END
CREATE FUNCTION #{get_salt_name}(@account_id bigint) RETURNS nvarchar(255)
WITH EXECUTE AS OWNER
AS
BEGIN
DECLARE @salt nvarchar(255);
SELECT @salt = substring(password_hash, 0, 30)
FROM #{table_name}
WHERE id = @account_id;
RETURN @salt;
END;
END

      db.run <<END
CREATE FUNCTION #{valid_hash_name}(@account_id bigint, @hash nvarchar(255)) RETURNS bit
WITH EXECUTE AS OWNER
AS
BEGIN
DECLARE @valid bit;
DECLARE @ph nvarchar(255);
SELECT @ph = password_hash
FROM #{table_name}
WHERE id = @account_id;
IF(@hash = @ph)
  SET @valid = 1;
ELSE
  SET @valid = 0
RETURN @valid;
END;
END
    end
  end
create_database_previous_password_check_functions (db, opts={})
[show source]
# File lib/rodauth/migrations.rb, line 115
def self.create_database_previous_password_check_functions(db, opts={})
  create_database_authentication_functions(db, {:table_name=>:account_previous_password_hashes, :get_salt_name=>:rodauth_get_previous_salt, :valid_hash_name=>:rodauth_previous_password_hash_match}.merge(opts))
end
drop_database_authentication_functions (db, opts={})
[show source]
# File lib/rodauth/migrations.rb, line 101
def self.drop_database_authentication_functions(db, opts={})
  get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
  valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash 

  case db.database_type
  when :postgres
    db.run "DROP FUNCTION #{get_salt_name}(int8)"
    db.run "DROP FUNCTION #{valid_hash_name}(int8, text)"
  when :mysql, :mssql
    db.run "DROP FUNCTION #{get_salt_name}"
    db.run "DROP FUNCTION #{valid_hash_name}"
  end
end
drop_database_previous_password_check_functions (db, opts={})
[show source]
# File lib/rodauth/migrations.rb, line 119
def self.drop_database_previous_password_check_functions(db, opts={})
  drop_database_authentication_functions(db, {:get_salt_name=>:rodauth_get_previous_salt, :valid_hash_name=>:rodauth_previous_password_hash_match}.merge(opts))
end
load_dependencies (app, opts={})
[show source]
# File lib/rodauth.rb, line 5
def self.load_dependencies(app, opts={})
  json_opt = opts.fetch(:json, app.opts[:rodauth_json])
  if json_opt
    app.plugin :json
    app.plugin :json_parser
  end

  unless json_opt == :only
    require 'tilt/string'
    app.plugin :render

    case opts.fetch(:csrf, app.opts[:rodauth_route_csrf])
    when false
      # nothing
    when :route_csrf
      # :nocov:
      app.plugin :route_csrf
      # :nocov:
    else
      app.plugin :csrf
    end

    app.plugin :flash unless opts[:flash] == false
    app.plugin :h
  end
end
new (scope)
[show source]
# File lib/rodauth/features/base.rb, line 105
def initialize(scope)
  @scope = scope
end
version ()
[show source]
# File lib/rodauth/version.rb, line 20
def self.version
  VERSION
end

Public Instance methods

_account_from_email_auth_key (token)
[show source]
# File lib/rodauth/features/email_auth.rb, line 248
def _account_from_email_auth_key(token)
  account_from_key(token, account_open_status_value){|id| get_email_auth_key(id)}
end
_account_from_login (login)
[show source]
# File lib/rodauth/features/base.rb, line 427
def _account_from_login(login)
  ds = db[accounts_table].where(login_column=>login)
  ds = ds.select(*account_select) if account_select
  ds = ds.where(account_status_column=>[account_unverified_status_value, account_open_status_value]) unless skip_status_checks?
  ds.first
end
_account_from_reset_password_key (token)
[show source]
# File lib/rodauth/features/reset_password.rb, line 261
def _account_from_reset_password_key(token)
  account_from_key(token, account_open_status_value){|id| get_password_reset_key(id)}
end
_account_from_session ()
[show source]
# File lib/rodauth/features/base.rb, line 434
def _account_from_session
  ds = account_ds(session_value)
  ds = ds.where(account_session_status_filter) unless skip_status_checks?
  ds.first
end
_account_from_unlock_key (token)
[show source]
# File lib/rodauth/features/lockout.rb, line 301
def _account_from_unlock_key(token)
  account_from_key(token){|id| account_lockouts_ds(id).get(account_lockouts_key_column)}
end
_account_from_verify_account_key (token)
[show source]
# File lib/rodauth/features/verify_account.rb, line 308
def _account_from_verify_account_key(token)
  account_from_key(token, account_unverified_status_value){|id| get_verify_account_key(id)}
end
_account_from_verify_login_change_key (token)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 203
def _account_from_verify_login_change_key(token)
  account_from_key(token) do |id|
    @verify_login_change_new_login, key = get_verify_login_change_login_and_key(id)
    key
  end
end
_email_auth_request ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 186
def _email_auth_request
  if email_auth_email_recently_sent?
    set_redirect_error_flash email_auth_email_recently_sent_error_flash
    redirect email_auth_email_recently_sent_redirect
  end

  generate_email_auth_key_value
  transaction do
    before_email_auth_request
    create_email_auth_key
    send_email_auth_email
    after_email_auth_request
  end

  set_notice_flash email_auth_email_sent_notice_flash
end
_json_response_body (hash)
[show source]
# File lib/rodauth/features/jwt.rb, line 207
def _json_response_body(hash)
  request.send(:convert_to_json, hash)
end
_login ()
[show source]
# File lib/rodauth/features/login.rb, line 85
def _login
  transaction do
    before_login
    update_session
    after_login
  end
  set_notice_flash login_notice_flash
  redirect login_redirect
end
_new_account (login)
[show source]
# File lib/rodauth/features/create_account.rb, line 123
def _new_account(login)
  acc = {login_column=>login}
  unless skip_status_checks?
    acc[account_status_column] = account_initial_status_value
  end
  acc
end
_otp ()
[show source]
# File lib/rodauth/features/otp.rb, line 339
def _otp
  otp_class.new(otp_key, :issuer=>otp_issuer, :digits=>otp_digits, :interval=>otp_interval)
end
_otp_add_key (secret)
[show source]
# File lib/rodauth/features/otp.rb, line 329
def _otp_add_key(secret)
  # Uniqueness errors can't be handled here, as we can't be sure the secret provided
  # is the same as the current secret.
  otp_key_ds.insert(otp_keys_id_column=>session_value, otp_keys_column=>secret)
end
_otp_key ()
[show source]
# File lib/rodauth/features/otp.rb, line 335
def _otp_key
  otp_key_ds.get(otp_keys_column)
end
_otp_tmp_key (secret)
[show source]
# File lib/rodauth/features/otp.rb, line 325
def _otp_tmp_key(secret)
  @otp_key = secret
end
_recovery_codes ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 232
def _recovery_codes
  recovery_codes_ds.select_map(recovery_codes_column)
end
_sms ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 496
def _sms
  sms_ds.first
end
_two_factor_auth_required_redirect ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 144
def _two_factor_auth_required_redirect
  two_factor_auth_required_redirect || two_factor_auth_fallback_redirect || default_redirect
end
_update_login (login)
[show source]
# File lib/rodauth/features/change_login.rb, line 79
def _update_login(login)
  updated = nil
  raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
  if raised
    @login_requirement_message = 'already an account with this login'
  end
  updated && !raised
end
_view (meth, page)
[show source]
# File lib/rodauth/features/base.rb, line 555
def _view(meth, page)
  scope.send(meth, _view_opts(page))
end
_view_opts (page)
[show source]
# File lib/rodauth/features/base.rb, line 537
def _view_opts(page)
  auth_template_path = template_path(page)
  opts = template_opts.dup
  opts[:locals] = opts[:locals] ? opts[:locals].dup : {}
  opts[:locals][:rodauth] = self
  opts[:cache] = cache_templates
  opts[:cache_key] = :"rodauth_#{page}"

  scope.instance_exec do
    opts = find_template(parse_template_opts(page, opts))
    unless File.file?(template_path(opts))
      opts[:path] = auth_template_path
    end
  end

  opts
end
account_activity_ds (account_id)
[show source]
# File lib/rodauth/features/account_expiration.rb, line 103
def account_activity_ds(account_id)
  db[account_activity_table].
    where(account_activity_id_column=>account_id)
end
account_ds (id=account_id)
[show source]
# File lib/rodauth/features/base.rb, line 448
def account_ds(id=account_id)
  raise ArgumentError, "invalid account id passed to account_ds" unless id
  ds = db[accounts_table].where(account_id_column=>id)
  ds = ds.select(*account_select) if account_select
  ds
end
account_expired? ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 53
def account_expired?
  columns = [account_activity_last_activity_column, account_activity_last_login_column, account_activity_expired_column]
  last_activity, last_login, expired = account_activity_ds(account_id).get(columns)
  return true if expired
  timestamp = convert_timestamp(expire_account_on_last_activity? ? last_activity : last_login)
  return false unless timestamp
  timestamp < Time.now - expire_account_after
end
account_expired_at ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 34
def account_expired_at
  get_activity_timestamp(account_id, account_activity_expired_column)
end
account_from_email_auth_key (key)
[show source]
# File lib/rodauth/features/email_auth.rb, line 130
def account_from_email_auth_key(key)
  @account = _account_from_email_auth_key(key)
end
account_from_key (token, status_id=nil)
[show source]
# File lib/rodauth/features/email_base.rb, line 55
def account_from_key(token, status_id=nil)
  id, key = split_token(token)
  return unless id && key

  return unless actual = yield(id)

  return unless timing_safe_eql?(key, actual)

  ds = account_ds(id)
  ds = ds.where(account_status_column=>status_id) if status_id && !skip_status_checks?
  ds.first
end
account_from_login (login)
[show source]
# File lib/rodauth/features/base.rb, line 156
def account_from_login(login)
  @account = _account_from_login(login)
end
account_from_reset_password_key (key)
[show source]
# File lib/rodauth/features/password_expiration.rb, line 44
def account_from_reset_password_key(key)
  if a = super
    check_password_change_allowed
  end
  a
end
account_from_session ()
[show source]
# File lib/rodauth/features/base.rb, line 235
def account_from_session
  @account = _account_from_session
end
account_from_unlock_key (key)
[show source]
# File lib/rodauth/features/lockout.rb, line 210
def account_from_unlock_key(key)
  @account = _account_from_unlock_key(key)
end
account_from_verify_account_key (key)
[show source]
# File lib/rodauth/features/verify_account.rb, line 189
def account_from_verify_account_key(key)
  @account = _account_from_verify_account_key(key)
end
account_from_verify_login_change_key (key)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 113
def account_from_verify_login_change_key(key)
  @account = _account_from_verify_login_change_key(key)
end
account_id ()
[show source]
# File lib/rodauth/features/base.rb, line 146
def account_id
  account[account_id_column]
end
account_in_unverified_grace_period? ()
[show source]
# File lib/rodauth/features/verify_account_grace_period.rb, line 65
def account_in_unverified_grace_period?
  account[account_status_column] == account_unverified_status_value &&
    verify_account_grace_period &&
    !verify_account_ds.where(Sequel.date_add(verification_requested_at_column, :seconds=>verify_account_grace_period) > Sequel::CURRENT_TIMESTAMP).empty?
end
account_initial_status_value ()
[show source]
# File lib/rodauth/features/base.rb, line 231
def account_initial_status_value
  account_open_status_value
end
account_lockouts_ds (id=account_id)
[show source]
# File lib/rodauth/features/lockout.rb, line 297
def account_lockouts_ds(id=account_id)
  db[account_lockouts_table].where(account_lockouts_id_column=>id)
end
account_login_failures_ds ()
[show source]
# File lib/rodauth/features/lockout.rb, line 293
def account_login_failures_ds
  db[account_login_failures_table].where(account_login_failures_id_column=>account_id)
end
account_model (model)
[show source]
# File lib/rodauth/features/base.rb, line 94
def account_model(model)
  warn "account_model is deprecated, use db and accounts_table settings"
  db model.db
  accounts_table model.table_name
  account_select model.dataset.opts[:select]
end
account_password_hash_column ()

If the #account_password_hash_column is set, the password hash is verified in ruby, it will not use a database function to do so, it will check the password hash using bcrypt.

[show source]
# File lib/rodauth/features/base.rb, line 171
def account_password_hash_column
  nil
end
account_session_status_filter ()
[show source]
# File lib/rodauth/features/base.rb, line 440
def account_session_status_filter
  {account_status_column=>account_open_status_value}
end
active_remember_key_ds (id=account_id)
[show source]
# File lib/rodauth/features/remember.rb, line 197
def active_remember_key_ds(id=account_id)
  remember_key_ds(id).where(Sequel.expr(remember_deadline_column) > Sequel::CURRENT_TIMESTAMP)
end
add_previous_password_hash (hash)
[show source]
# File lib/rodauth/features/disallow_password_reuse.rb, line 24
def add_previous_password_hash(hash) 
  ds = previous_password_ds
  keep_before = ds.reverse(previous_password_id_column).
    limit(nil, previous_passwords_to_check).
    get(previous_password_id_column)

  ds.where(Sequel.expr(previous_password_id_column) <= keep_before).
    delete

  # This should never raise uniqueness violations, as it uses a serial primary key
  ds.insert(previous_password_account_id_column=>account_id, previous_password_hash_column=>hash)
end
add_recovery_code ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 213
def add_recovery_code
  # This should never raise uniqueness violations unless the recovery code is the same, and the odds of that
  # are 1/256**32 assuming a good random number generator.  Still, attempt to handle that case by retrying
  # on such a uniqueness violation.
  retry_on_uniqueness_violation do
    recovery_codes_ds.insert(recovery_codes_id_column=>session_value, recovery_codes_column=>new_recovery_code)
  end
end
add_recovery_codes (number)
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 203
def add_recovery_codes(number)
  return if number <= 0
  transaction do
    number.times do
      add_recovery_code
    end
  end
  remove_instance_variable(:@recovery_codes)
end
add_remember_key ()
[show source]
# File lib/rodauth/features/remember.rb, line 143
def add_remember_key
  hash = {remember_id_column=>account_id, remember_key_column=>remember_key_value}
  set_deadline_value(hash, remember_deadline_column, remember_deadline_interval)

  if e = raised_uniqueness_violation{remember_key_ds.insert(hash)}
    # If inserting into the remember key table causes a violation, we can pull the
    # existing row from the table.  If there is no invalid row, we can then reraise.
    raise e unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
  end
end
after_change_login ()
[show source]
# File lib/rodauth/features/verify_change_login.rb, line 12
def after_change_login
  super
  update_account(account_status_column=>account_unverified_status_value)
  setup_account_verification
  session[unverified_account_session_key] = true
end
after_change_password ()
[show source]
# File lib/rodauth/features/change_password_notify.rb, line 30
def after_change_password
  super
  send_password_changed_email
end
after_close_account ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 93
def after_close_account
  super if defined?(super)
  account_activity_ds(account_id).delete
end
after_confirm_password ()
[show source]
# File lib/rodauth/features/remember.rb, line 178
def after_confirm_password
  super
  clear_remembered_session_key
end
after_create_account ()
[show source]
# File lib/rodauth/features/disallow_password_reuse.rb, line 69
def after_create_account
  if account_password_hash_column
    add_previous_password_hash(password_hash(param(password_param)))
  end
  super if defined?(super)
end
after_login ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 205
def after_login
  # Remove the email auth key after any login, even if
  # it is a password login.  This is done to invalidate
  # the email login when a user has a password and requests
  # email authentication, but then remembers their password
  # and doesn't need the link.  At that point, the link
  # that allows login access to the account becomes a
  # security liability, and it is best to remove it.
  remove_email_auth_key
  super if defined?(super)
end
after_login_entered_during_multi_phase_login ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 158
def after_login_entered_during_multi_phase_login
  if force_email_auth?
    # If the account does not have a password hash, just send the
    # email link.
    _email_auth_request
    redirect email_auth_email_sent_redirect
  else
    # If the account has a password hash, allow password login, but
    # show form below to also login via email link.
    super
    @email_auth_request_form = email_auth_request_form
  end
end
after_login_failure ()
[show source]
# File lib/rodauth/features/lockout.rb, line 251
def after_login_failure
  invalid_login_attempted
  super
end
after_logout ()
[show source]
# File lib/rodauth/features/remember.rb, line 168
def after_logout
  forget_login
  super if defined?(super)
end
after_reset_password ()
[show source]
# File lib/rodauth/features/password_grace_period.rb, line 26
def after_reset_password
  super if defined?(super)
  @last_password_entry = Time.now.to_i
end
allow_resending_verify_account_email? ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 155
def allow_resending_verify_account_email?
  account[account_status_column] == account_unverified_status_value
end
already_logged_in ()
[show source]
# File lib/rodauth/features/base.rb, line 179
def already_logged_in
  nil
end
auth_class_eval (&block)
[show source]
# File lib/rodauth/features/base.rb, line 90
def auth_class_eval(&block)
  auth.class_eval(&block)
end
authenticated? ()
[show source]
# File lib/rodauth/features/base.rb, line 223
def authenticated?
  logged_in?
end
before_change_login_route ()
[show source]
# File lib/rodauth/features/verify_account_grace_period.rb, line 35
def before_change_login_route
  unless verified_account?
    set_redirect_error_flash unverified_change_login_error_flash
    redirect unverified_change_login_redirect
  end
  super if defined?(super)
end
before_change_password_route ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 89
def before_change_password_route
  check_password_change_allowed
  super
end
before_login_attempt ()
[show source]
# File lib/rodauth/features/lockout.rb, line 239
def before_login_attempt
  if locked_out?
    show_lockout_page
  end
  super
end
before_logout ()
[show source]
# File lib/rodauth/features/single_session.rb, line 71
def before_logout
  reset_single_session_key if request.post?
  super if defined?(super)
end
before_otp_authentication_route (&block)
[show source]
# File lib/rodauth/features/otp.rb, line 22
def before_otp_authentication_route(&block)
  warn "before_otp_authentication_route is deprecated, switch to before_otp_auth_route"
  before_otp_auth_route(&block)
end
before_reset_password ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 73
def before_reset_password
  check_account_expiration
  super if defined?(super)
end
before_reset_password_request ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 78
def before_reset_password_request
  check_account_expiration
  super if defined?(super)
end
before_rodauth ()
[show source]
# File lib/rodauth/features/jwt.rb, line 142
def before_rodauth
  if json_request?
    if jwt_check_accept? && (accept = request.env['HTTP_ACCEPT']) && accept !~ json_accept_regexp
      response.status = 406
      json_response[json_response_error_key] = json_not_accepted_error_message
      response['Content-Type'] ||= json_response_content_type
      response.write(request.send(:convert_to_json, json_response))
      request.halt
    end

    unless request.post?
      response.status = 405
      response.headers['Allow'] = 'POST'
      json_response[json_response_error_key] = json_non_post_error_message
      return_json_response
    end
  elsif only_json?
    response.status = json_response_error_status
    response.write non_json_request_error_message
    request.halt
  end

  super
end
before_unlock_account ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 83
def before_unlock_account
  check_account_expiration
  super if defined?(super)
end
before_unlock_account_request ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 88
def before_unlock_account_request
  check_account_expiration
  super if defined?(super)
end
before_view_recovery_codes ()
[show source]
# File lib/rodauth/features/jwt.rb, line 167
def before_view_recovery_codes
  super if defined?(super)
  if use_jwt?
    json_response[:codes] = recovery_codes
    json_response[json_response_success_key] ||= "" if include_success_messages?
  end
end
button (value, opts={})
[show source]
# File lib/rodauth/features/base.rb, line 260
def button(value, opts={})
  scope.render(button_opts(value, opts))
end
button_opts (value, opts)
[show source]
# File lib/rodauth/features/base.rb, line 251
def button_opts(value, opts)
  opts = Hash[template_opts].merge!(opts)
  opts[:locals] = {:value=>value, :opts=>opts}
  opts[:path] = template_path('button')
  opts[:cache] = cache_templates
  opts[:cache_key] = :rodauth_button
  opts
end
can_add_recovery_codes? ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 199
def can_add_recovery_codes?
  recovery_codes.length < recovery_codes_limit
end
catch_error (&block)
[show source]
# File lib/rodauth/features/base.rb, line 358
def catch_error(&block)
  catch(:rodauth_error, &block)
end
change_login (login)
[show source]
# File lib/rodauth/features/change_login.rb, line 64
def change_login(login)
  if account_ds.get(login_column).downcase == login.downcase
    @login_requirement_message = 'same as current login'
    return false
  end

  update_login(login)
end
change_login_notice_flash ()
[show source]
# File lib/rodauth/features/verify_change_login.rb, line 6
def change_login_notice_flash
  "#{super}. #{verify_account_email_sent_notice_flash}"
end
change_login_requires_password? ()
[show source]
# File lib/rodauth/features/change_login.rb, line 60
def change_login_requires_password?
  modifications_require_password?
end
change_password_requires_password? ()
[show source]
# File lib/rodauth/features/change_password.rb, line 65
def change_password_requires_password?
  modifications_require_password?
end
check_account_expiration ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 62
def check_account_expiration
  if account_expired?
    set_expired unless account_expired_at
    set_redirect_error_flash account_expiration_error_flash
    redirect account_expiration_redirect
  end
  update_last_login
end
check_already_logged_in ()
[show source]
# File lib/rodauth/features/base.rb, line 175
def check_already_logged_in
  already_logged_in if logged_in?
end
check_password_change_allowed ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 29
def check_password_change_allowed
  if password_changed_at = get_password_changed_at
    if password_changed_at > Time.now - allow_password_change_after
      set_redirect_error_flash password_not_changeable_yet_error_flash
      redirect password_not_changeable_yet_redirect
    end
  end
end
check_session_expiration ()
[show source]
# File lib/rodauth/features/session_expiration.rb, line 14
def check_session_expiration
  return unless logged_in?

  unless session.has_key?(session_last_activity_session_key) && session.has_key?(session_created_session_key)
    if session_expiration_default
      expire_session
    end

    return
  end

  time = Time.now.to_i

  if session[session_last_activity_session_key] + session_inactivity_timeout < time
    expire_session
  end
  set_session_value(session_last_activity_session_key, time)

  if session[session_created_session_key] + max_session_lifetime < time
    expire_session
  end
end
check_single_session ()
[show source]
# File lib/rodauth/features/single_session.rb, line 41
def check_single_session
  if logged_in? && !currently_active_session?
    no_longer_active_session
  end
end
clear_cached_otp ()
[show source]
# File lib/rodauth/features/otp.rb, line 308
def clear_cached_otp
  remove_instance_variable(:@otp) if defined?(@otp)
end
clear_invalid_login_attempts ()
[show source]
# File lib/rodauth/features/lockout.rb, line 160
def clear_invalid_login_attempts
  unlock_account
end
clear_remembered_session_key ()
[show source]
# File lib/rodauth/features/remember.rb, line 158
def clear_remembered_session_key
  session.delete(remembered_session_key)
end
clear_session ()
[show source]
# File lib/rodauth/features/base.rb, line 183
def clear_session
  if scope.respond_to?(:clear_session)
    scope.clear_session
  else
    session.clear
  end
end
close_account ()
[show source]
# File lib/rodauth/features/close_account.rb, line 61
def close_account
  unless skip_status_checks?
    update_account(account_status_column=>account_closed_status_value)
  end

  unless account_password_hash_column
    password_hash_ds.delete
  end
end
close_account_requires_password? ()
[show source]
# File lib/rodauth/features/close_account.rb, line 57
def close_account_requires_password?
  modifications_require_password?
end
confirm_password ()
[show source]
# File lib/rodauth/features/confirm_password.rb, line 44
def confirm_password
  nil
end
confirm_password_redirect ()
[show source]
# File lib/rodauth/features/confirm_password.rb, line 48
def confirm_password_redirect
  session.delete(confirm_password_redirect_session_key) || default_redirect
end
convert_session_key (key)
[show source]
# File lib/rodauth/features/base.rb, line 337
def convert_session_key(key)
  scope.opts[:sessions_convert_symbols] ? key.to_s : key
end
convert_timestamp (timestamp)

This is needed for jdbc/sqlite, which returns timestamp columns as strings

[show source]
# File lib/rodauth/features/base.rb, line 460
def convert_timestamp(timestamp)
  timestamp = db.to_application_timestamp(timestamp) if timestamp.is_a?(String)
  timestamp
end
create_account_autologin? ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 213
def create_account_autologin?
  false
end
create_account_notice_flash ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 175
def create_account_notice_flash
  verify_account_email_sent_notice_flash
end
create_account_set_password? ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 225
def create_account_set_password?
  return false if verify_account_set_password?
  super
end
create_email (subject, body)
[show source]
# File lib/rodauth/features/email_base.rb, line 26
def create_email(subject, body)
  create_email_to(email_to, subject, body)
end
create_email_auth_email ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 226
def create_email_auth_email
  create_email(email_auth_email_subject, email_auth_email_body)
end
create_email_auth_key ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 101
def create_email_auth_key
  transaction do
    if email_auth_key_value = get_email_auth_key(account_id)
      set_email_auth_email_last_sent
      @email_auth_key_value = email_auth_key_value
    elsif e = raised_uniqueness_violation{email_auth_ds.insert(email_auth_key_insert_hash)}
      # If inserting into the email auth table causes a violation, we can pull the
      # existing email auth key from the table, or reraise.
      raise e unless @email_auth_key_value = get_email_auth_key(account_id)
    end
  end
end
create_email_to (to, subject, body)
[show source]
# File lib/rodauth/features/email_base.rb, line 30
def create_email_to(to, subject, body)
  m = Mail.new
  m.from = email_from
  m.to = to
  m.subject = "#{email_subject_prefix}#{subject}"
  m.body = body
  m
end
create_password_changed_email ()
[show source]
# File lib/rodauth/features/change_password_notify.rb, line 22
def create_password_changed_email
  create_email(password_changed_email_subject, password_changed_email_body)
end
create_reset_password_email ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 235
def create_reset_password_email
  create_email(reset_password_email_subject, reset_password_email_body)
end
create_reset_password_key ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 156
def create_reset_password_key
  transaction do
    if reset_password_key_value = get_password_reset_key(account_id)
      set_reset_password_email_last_sent
      @reset_password_key_value = reset_password_key_value
    elsif e = raised_uniqueness_violation{password_reset_ds.insert(reset_password_key_insert_hash)}
      # If inserting into the reset password table causes a violation, we can pull the
      # existing reset password key from the table, or reraise.
      raise e unless @reset_password_key_value = get_password_reset_key(account_id)
    end
  end
end
create_unlock_account_email ()
[show source]
# File lib/rodauth/features/lockout.rb, line 277
def create_unlock_account_email
  create_email(unlock_account_email_subject, unlock_account_email_body)
end
create_verify_account_email ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 296
def create_verify_account_email
  create_email(verify_account_email_subject, verify_account_email_body)
end
create_verify_account_key ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 279
def create_verify_account_key
  ds = verify_account_ds
  transaction do
    if ds.empty?
      if e = raised_uniqueness_violation{ds.insert(verify_account_key_insert_hash)}
        # If inserting into the verify account table causes a violation, we can pull the
        # key from the verify account table, or reraise.
        raise e unless @verify_account_key_value = get_verify_account_key(account_id)
      end
    end
  end
end
create_verify_login_change_email (login)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 191
def create_verify_login_change_email(login)
  create_email_to(login, verify_login_change_email_subject, verify_login_change_email_body)
end
create_verify_login_change_key (login)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 169
def create_verify_login_change_key(login)
  ds = verify_login_change_ds
  transaction do
    ds.where((Sequel::CURRENT_TIMESTAMP > verify_login_change_deadline_column) | ~Sequel.expr(verify_login_change_login_column=>login)).delete
    if e = raised_uniqueness_violation{ds.insert(verify_login_change_key_insert_hash(login))}
      old_login, key = get_verify_login_change_login_and_key(account_id)
      # If inserting into the verify login change table causes a violation, we can pull the
      # key from the verify login change table if the logins match, or reraise.
      @verify_login_change_key_value = if old_login.downcase == login.downcase
        key
      end
      raise e unless @verify_login_change_key_value
    end
  end
end
csrf_tag (path=request.path)
[show source]
# File lib/rodauth/features/base.rb, line 239
def csrf_tag(path=request.path)
  return unless scope.respond_to?(:csrf_tag)

  if use_request_specific_csrf_tokens?
    # :nocov:
    scope.csrf_tag(path)
    # :nocov:
  else
    scope.csrf_tag
  end
end
currently_active_session? ()
[show source]
# File lib/rodauth/features/single_session.rb, line 25
def currently_active_session?
  single_session_key = session[single_session_session_key]
  current_key = single_session_ds.get(single_session_key_column)
  if single_session_key.nil?
    unless current_key
      # No row exists for this user, indicating the feature has never
      # been used, so it is OK to treat the current session as a new
      # session.
      update_single_session_key
    end
    true
  elsif current_key
    timing_safe_eql?(single_session_key, current_key)
  end
end
db ()
[show source]
# File lib/rodauth/features/base.rb, line 164
def db
  Sequel::DATABASES.first
end
delete_account ()
[show source]
# File lib/rodauth/features/close_account.rb, line 71
def delete_account
  account_ds.delete
end
delete_account_on_close? ()
[show source]
# File lib/rodauth/features/close_account.rb, line 75
def delete_account_on_close?
  skip_status_checks?
end
disable_remember_login ()
[show source]
# File lib/rodauth/features/remember.rb, line 139
def disable_remember_login
  remove_remember_key
end
email_auth_ds (id=account_id)
[show source]
# File lib/rodauth/features/email_auth.rb, line 244
def email_auth_ds(id=account_id)
  db[email_auth_table].where(email_auth_id_column=>id)
end
email_auth_email_body ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 230
def email_auth_email_body
  render('email-auth-email')
end
email_auth_email_recently_sent? ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 182
def email_auth_email_recently_sent?
  (email_last_sent = get_email_auth_email_last_sent) && (Time.now - email_last_sent < email_auth_skip_resend_email_within)
end
email_auth_key_insert_hash ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 238
def email_auth_key_insert_hash
  hash = {email_auth_id_column=>account_id, email_auth_key_column=>email_auth_key_value}
  set_deadline_value(hash, email_auth_deadline_column, email_auth_deadline_interval)
  hash
end
email_auth_request_form ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 154
def email_auth_request_form
  render('email-auth-request-form')
end
email_from ()
[show source]
# File lib/rodauth/features/email_base.rb, line 39
def email_from
  "webmaster@#{request.host}"
end
email_to ()
[show source]
# File lib/rodauth/features/email_base.rb, line 43
def email_to
  account[login_column]
end
expire_session ()
[show source]
# File lib/rodauth/features/session_expiration.rb, line 37
def expire_session
  clear_session
  set_redirect_error_flash session_expiration_error_flash
  redirect session_expiration_redirect
end
features ()
[show source]
# File lib/rodauth/features/base.rb, line 109
def features
  self.class.features
end
field_error (field)
[show source]
# File lib/rodauth/features/base.rb, line 141
def field_error(field)
  return nil unless @field_errors
  @field_errors[field]
end
flash ()
[show source]
# File lib/rodauth/features/base.rb, line 125
def flash
  scope.flash
end
force_email_auth? ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 176
def force_email_auth?
  get_password_hash.nil?
end
forget_login ()
[show source]
# File lib/rodauth/features/remember.rb, line 124
def forget_login
  ::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, remember_cookie_options)
end
function_name (name)
[show source]
# File lib/rodauth/features/base.rb, line 403
def function_name(name)
  if db.database_type == :mssql
    # :nocov:
    "dbo.#{name}"
    # :nocov:
  else
    name
  end
end
generate_email_auth_key_value ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 222
def generate_email_auth_key_value
  @email_auth_key_value = random_key
end
generate_remember_key_value ()
[show source]
# File lib/rodauth/features/remember.rb, line 185
def generate_remember_key_value
  @remember_key_value = random_key
end
generate_reset_password_key_value ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 231
def generate_reset_password_key_value
  @reset_password_key_value = random_key
end
generate_unlock_account_key ()
[show source]
# File lib/rodauth/features/lockout.rb, line 261
def generate_unlock_account_key
  random_key
end
generate_verify_account_key_value ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 275
def generate_verify_account_key_value
  @verify_account_key_value = random_key
end
generate_verify_login_change_key_value ()
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 165
def generate_verify_login_change_key_value
  @verify_login_change_key_value = random_key
end
get_activity_timestamp (account_id, column)
[show source]
# File lib/rodauth/features/account_expiration.rb, line 108
def get_activity_timestamp(account_id, column)
  convert_timestamp(account_activity_ds(account_id).get(column))
end
get_email_auth_email_last_sent ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 118
def get_email_auth_email_last_sent
  if column = email_auth_email_last_sent_column
    if ts = email_auth_ds.get(column)
      convert_timestamp(ts)
    end
  end
end
get_email_auth_key (id)
[show source]
# File lib/rodauth/features/email_auth.rb, line 142
def get_email_auth_key(id)
  ds = email_auth_ds(id)
  ds.where(Sequel::CURRENT_TIMESTAMP > email_auth_deadline_column).delete
  ds.get(email_auth_key_column)
end
get_password_changed_at ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 25
def get_password_changed_at
  convert_timestamp(password_expiration_ds.get(password_expiration_changed_at_column))
end
get_password_hash ()

Get the password hash for the user. When using database authentication functions, note that only the salt is returned.

[show source]
# File lib/rodauth/features/base.rb, line 415
def get_password_hash
  if account_password_hash_column
    account[account_password_hash_column]
  elsif use_database_authentication_functions?
    db.get(Sequel.function(function_name(:rodauth_get_salt), account_id))
  else
    # :nocov:
    password_hash_ds.get(password_hash_column)
    # :nocov:
  end
end
get_password_reset_key (id)
[show source]
# File lib/rodauth/features/reset_password.rb, line 185
def get_password_reset_key(id)
  ds = password_reset_ds(id)
  ds.where(Sequel::CURRENT_TIMESTAMP > reset_password_deadline_column).delete
  ds.get(reset_password_key_column)
end
get_remember_key ()
[show source]
# File lib/rodauth/features/remember.rb, line 128
def get_remember_key
  unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
   generate_remember_key_value
   transaction do
     remove_remember_key
     add_remember_key
   end
  end
  nil
end
get_reset_password_email_last_sent ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 203
def get_reset_password_email_last_sent
  if column = reset_password_email_last_sent_column
    if ts = password_reset_ds.get(column)
      convert_timestamp(ts)
    end
  end
end
get_unlock_account_email_last_sent ()
[show source]
# File lib/rodauth/features/lockout.rb, line 223
def get_unlock_account_email_last_sent
  if column = account_lockouts_email_last_sent_column
    if ts = account_lockouts_ds.get(column)
      convert_timestamp(ts)
    end
  end
end
get_unlock_account_key ()
[show source]
# File lib/rodauth/features/lockout.rb, line 206
def get_unlock_account_key
  account_lockouts_ds.get(account_lockouts_key_column)
end
get_verify_account_email_last_sent ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 234
def get_verify_account_email_last_sent
  if column = verify_account_email_last_sent_column
    if ts = verify_account_ds.get(column)
      convert_timestamp(ts)
    end
  end
end
get_verify_account_key (id)
[show source]
# File lib/rodauth/features/verify_account.rb, line 205
def get_verify_account_key(id)
  verify_account_ds(id).get(verify_account_key_column)
end
get_verify_login_change_login_and_key (id)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 125
def get_verify_login_change_login_and_key(id)
  verify_login_change_ds(id).get([verify_login_change_login_column, verify_login_change_key_column])
end
include_success_messages? ()
[show source]
# File lib/rodauth/features/jwt.rb, line 187
def include_success_messages?
  !json_response_success_key.nil?
end
invalid_login_attempted ()
[show source]
# File lib/rodauth/features/lockout.rb, line 164
def invalid_login_attempted
  ds = account_login_failures_ds.
      where(account_login_failures_id_column=>account_id)

  number = if db.database_type == :postgres
    ds.returning(account_login_failures_number_column).
      with_sql(:update_sql, account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1).
      single_value
  else
    # :nocov:
    if ds.update(account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1) > 0
      ds.get(account_login_failures_number_column)
    end
    # :nocov:
  end

  unless number
    # Ignoring the violation is safe here.  It may allow slightly more than max_invalid_logins invalid logins before
    # lockout, but allowing a few extra is OK if the race is lost.
    ignore_uniqueness_violation{account_login_failures_ds.insert(account_login_failures_id_column=>account_id)}
    number = 1
  end

  if number >= max_invalid_logins
    @unlock_account_key_value = generate_unlock_account_key
    hash = {account_lockouts_id_column=>account_id, account_lockouts_key_column=>unlock_account_key_value}
    set_deadline_value(hash, account_lockouts_deadline_column, account_lockouts_deadline_interval)

    if e = raised_uniqueness_violation{account_lockouts_ds.insert(hash)}
      # If inserting into the lockout table raises a violation, we should just be able to pull the already inserted
      # key out of it.  If that doesn't return a valid key, we should reraise the error.
      raise e unless @unlock_account_key_value = account_lockouts_ds.get(account_lockouts_key_column)

      after_account_lockout
      show_lockout_page
    else
      after_account_lockout
      e
    end
  end
end
invalid_previous_password_message ()
[show source]
# File lib/rodauth/features/change_password.rb, line 69
def invalid_previous_password_message
  invalid_password_message
end
json_request? ()
[show source]
# File lib/rodauth/features/jwt.rb, line 103
def json_request?
  return @json_request if defined?(@json_request)
  @json_request = request.content_type =~ json_request_content_type_regexp
end
json_response ()
[show source]
# File lib/rodauth/features/jwt.rb, line 197
def json_response
  @json_response ||= {}
end
jwt_payload ()
[show source]
# File lib/rodauth/features/jwt.rb, line 175
def jwt_payload
  return @jwt_payload if defined?(@jwt_payload)
  @jwt_payload = JWT.decode(jwt_token, jwt_secret, true, jwt_decode_opts.merge(:algorithm=>jwt_algorithm))[0]
rescue JWT::DecodeError
  @jwt_payload = false
end
jwt_secret ()
[show source]
# File lib/rodauth/features/jwt.rb, line 108
def jwt_secret
  raise ArgumentError, "jwt_secret not set"
end
jwt_session_hash ()
[show source]
# File lib/rodauth/features/jwt.rb, line 112
def jwt_session_hash
  jwt_session_key ? {jwt_session_key=>session} : session
end
jwt_token ()
[show source]
# File lib/rodauth/features/jwt.rb, line 120
def jwt_token
  return @jwt_token if defined?(@jwt_token)

  if (v = request.env['HTTP_AUTHORIZATION']) && v !~ jwt_authorization_ignore
    @jwt_token = v.sub(jwt_authorization_remove, '')
  end
end
last_account_activity_at ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 26
def last_account_activity_at
  get_activity_timestamp(session_value, account_activity_last_activity_column)
end
last_account_login_at ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 30
def last_account_login_at
  get_activity_timestamp(session_value, account_activity_last_login_column)
end
load_memory ()
[show source]
# File lib/rodauth/features/remember.rb, line 84
def load_memory
  return if session[session_key]
  return unless cookie = request.cookies[remember_cookie_key]
  id, key = cookie.split('_', 2)
  return unless id && key

  unless (actual = active_remember_key_ds(id).get(remember_key_column)) && timing_safe_eql?(key, actual)
    forget_login
    return
  end

  session[session_key] = id
  account = account_from_session
  session.delete(session_key)

  unless account
    remove_remember_key(id)
    forget_login
    return 
  end

  before_load_memory
  update_session

  set_session_value(remembered_session_key, true)
  if extend_remember_deadline?
    active_remember_key_ds(id).update(remember_deadline_column=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, remember_period))
    remember_login
  end
  after_load_memory
end
loaded_templates ()
[show source]
# File lib/rodauth/features/base.rb, line 465
def loaded_templates
  []
end
locked_out? ()
[show source]
# File lib/rodauth/features/lockout.rb, line 141
def locked_out?
  if t = convert_timestamp(account_lockouts_ds.get(account_lockouts_deadline_column))
    if Time.now < t
      true
    else
      unlock_account
      false
    end
  else
    false
  end
end
logged_in_via_remember_key? ()
[show source]
# File lib/rodauth/features/remember.rb, line 162
def logged_in_via_remember_key?
  !!session[remembered_session_key]
end
login_confirm_label ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 34
def login_confirm_label
  "Confirm #{login_label}"
end
login_does_not_meet_requirements_message ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 79
def login_does_not_meet_requirements_message
  "invalid login#{", #{login_requirement_message}" if login_requirement_message}"
end
login_failed_reset_password_request_form ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 239
def login_failed_reset_password_request_form
  render("reset-password-request")
end
login_hidden_field ()
[show source]
# File lib/rodauth/features/login.rb, line 79
def login_hidden_field
  "<input type='hidden' name=\"#{login_param}\" value=\"#{scope.h param(login_param)}\" />"
end
login_meets_email_requirements? (login)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 103
def login_meets_email_requirements?(login)
  return true unless require_email_address_logins?
  if login =~ /\A[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+\z/
    return true
  end
  @login_requirement_message = 'not a valid email address'
  return false
end
login_meets_length_requirements? (login)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 91
def login_meets_length_requirements?(login)
  if login_minimum_length > login.length
    @login_requirement_message = login_too_short_message
    false
  elsif login_maximum_length < login.length
    @login_requirement_message = login_too_long_message
    false
  else
    true
  end
end
login_meets_requirements? (login)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 42
def login_meets_requirements?(login)
  login_meets_length_requirements?(login) && \
    login_meets_email_requirements?(login)
end
login_required ()
[show source]
# File lib/rodauth/features/base.rb, line 191
def login_required
  set_redirect_error_status(login_required_error_status)
  set_redirect_error_flash require_login_error_flash
  redirect require_login_redirect
end
login_too_long_message ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 83
def login_too_long_message
  "maximum #{login_maximum_length} characters"
end
login_too_short_message ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 87
def login_too_short_message
  "minimum #{login_minimum_length} characters"
end
logout ()
[show source]
# File lib/rodauth/features/logout.rb, line 33
def logout
  clear_session
end
modifications_require_password? ()
[show source]
# File lib/rodauth/features/password_grace_period.rb, line 7
def modifications_require_password?
  return false unless super
  !password_recently_entered?
end
new_account (login)
[show source]
# File lib/rodauth/features/create_account.rb, line 102
def new_account(login)
  @account = _new_account(login)
end
new_recovery_code ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 224
def new_recovery_code
  random_key
end
no_longer_active_session ()
[show source]
# File lib/rodauth/features/single_session.rb, line 47
def no_longer_active_session
  clear_session
  set_redirect_error_flash single_session_error_flash
  redirect single_session_redirect
end
only_json? ()
[show source]
# File lib/rodauth/features/base.rb, line 273
def only_json?
  scope.class.opts[:rodauth_json] == :only
end
open_account? ()
[show source]
# File lib/rodauth/features/base.rb, line 160
def open_account?
  skip_status_checks? || account[account_status_column] == account_open_status_value 
end
otp_add_key ()
[show source]
# File lib/rodauth/features/otp.rb, line 267
def otp_add_key
  _otp_add_key(otp_key)
  super if defined?(super)
end
otp_exists? ()
[show source]
# File lib/rodauth/features/otp.rb, line 248
def otp_exists?
  !otp_key.nil?
end
otp_issuer ()
[show source]
# File lib/rodauth/features/otp.rb, line 294
def otp_issuer
  request.host
end
otp_key_ds ()
[show source]
# File lib/rodauth/features/otp.rb, line 343
def otp_key_ds
  db[otp_keys_table].where(otp_keys_id_column=>session_value)
end
otp_locked_out? ()
[show source]
# File lib/rodauth/features/otp.rb, line 286
def otp_locked_out?
  otp_key_ds.get(otp_keys_failures_column) >= otp_auth_failures_limit
end
otp_lockout_error_flash ()
[show source]
# File lib/rodauth/features/otp.rb, line 236
def otp_lockout_error_flash
  "Authentication code use locked out due to numerous failures.#{super if defined?(super)}"
end
otp_lockout_redirect ()
[show source]
# File lib/rodauth/features/otp.rb, line 231
def otp_lockout_redirect
  return super if defined?(super)
  default_redirect
end
otp_new_secret ()
[show source]
# File lib/rodauth/features/otp.rb, line 321
def otp_new_secret
  ROTP::Base32.random_base32
end
otp_provisioning_name ()
[show source]
# File lib/rodauth/features/otp.rb, line 298
def otp_provisioning_name
  account[login_column]
end
otp_provisioning_uri ()
[show source]
# File lib/rodauth/features/otp.rb, line 290
def otp_provisioning_uri
  otp.provisioning_uri(otp_provisioning_name)
end
otp_qr_code ()
[show source]
# File lib/rodauth/features/otp.rb, line 302
def otp_qr_code
  RQRCode::QRCode.new(otp_provisioning_uri).as_svg(:module_size=>8)
end
otp_record_authentication_failure ()
[show source]
# File lib/rodauth/features/otp.rb, line 278
def otp_record_authentication_failure
  otp_key_ds.update(otp_keys_failures_column=>Sequel.identifier(otp_keys_failures_column) + 1)
end
otp_remove ()
[show source]
# File lib/rodauth/features/otp.rb, line 262
def otp_remove
  otp_key_ds.delete
  super if defined?(super)
end
otp_remove_auth_failures ()
[show source]
# File lib/rodauth/features/otp.rb, line 282
def otp_remove_auth_failures
  otp_key_ds.update(otp_keys_failures_column=>0)
end
otp_tmp_key (secret)
[show source]
# File lib/rodauth/features/otp.rb, line 312
def otp_tmp_key(secret)
  _otp_tmp_key(secret)
  clear_cached_otp
end
otp_update_last_use ()
[show source]
# File lib/rodauth/features/otp.rb, line 272
def otp_update_last_use
  otp_key_ds.
    where(Sequel.date_add(otp_keys_last_use_column, :seconds=>(otp_interval||30)) < Sequel::CURRENT_TIMESTAMP).
    update(otp_keys_last_use_column=>Sequel::CURRENT_TIMESTAMP) == 1
end
otp_valid_code? (ot_pass)
[show source]
# File lib/rodauth/features/otp.rb, line 252
def otp_valid_code?(ot_pass)
  return false unless otp_exists?
  ot_pass = ot_pass.gsub(/\s+/, '')
  if drift = otp_drift
    otp.verify_with_drift(ot_pass, drift)
  else
    otp.verify(ot_pass)
  end
end
otp_valid_key? (secret)
[show source]
# File lib/rodauth/features/otp.rb, line 317
def otp_valid_key?(secret)
  secret =~ /\A[a-z2-7]{16}\z/
end
param (key)

Return a string for the parameter name. This will be an empty string if the parameter doesn't exist.

[show source]
# File lib/rodauth/features/base.rb, line 304
def param(key)
  param_or_nil(key).to_s
end
param_or_nil (key)

Return a string for the parameter name, or nil if there is no parameter with that name.

[show source]
# File lib/rodauth/features/base.rb, line 310
def param_or_nil(key)
  value = request.params[key]
  value.to_s unless value.nil?
end
password_changed_email_body ()
[show source]
# File lib/rodauth/features/change_password_notify.rb, line 26
def password_changed_email_body
  render('password-changed-email')
end
password_confirm_label ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 38
def password_confirm_label
  "Confirm #{password_label}"
end
password_does_not_contain_null_byte? (password)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 118
def password_does_not_contain_null_byte?(password)
  return true unless password.include?("\0")
  @password_requirement_message = 'contains null byte'
  false
end
password_does_not_meet_requirements_message ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 71
def password_does_not_meet_requirements_message
  "invalid password, does not meet requirements#{" (#{password_requirement_message})" if password_requirement_message}"
end
password_doesnt_match_previous_password? (password)
[show source]
# File lib/rodauth/features/disallow_password_reuse.rb, line 44
def password_doesnt_match_previous_password?(password)
  match = if use_database_authentication_functions?
    salts = previous_password_ds.
      select_map([previous_password_id_column, Sequel.function(function_name(:rodauth_get_previous_salt), previous_password_id_column).as(:salt)])
    return true if salts.empty?

    salts.any? do |hash_id, salt|
      db.get(Sequel.function(function_name(:rodauth_previous_password_hash_match), hash_id, BCrypt::Engine.hash_secret(password, salt)))
    end
  else
    # :nocov:
    previous_password_ds.select_map(previous_password_hash_column).any?{|hash| BCrypt::Password.new(hash) == password}
    # :nocov:
  end

  return true unless match
  @password_requirement_message = password_same_as_previous_password_message
  false
end
password_expiration_ds ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 106
def password_expiration_ds
  db[password_expiration_table].where(password_expiration_id_column=>account_id)
end
password_expired? ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 67
def password_expired?
  if password_changed_at = session[password_changed_at_session_key]
    return password_changed_at + require_password_change_after < Time.now.to_i
  end

  account_from_session
  if password_changed_at = get_password_changed_at
    set_session_value(password_changed_at_session_key, password_changed_at.to_i)
    password_changed_at + require_password_change_after < Time.now
  else
    set_session_value(password_changed_at_session_key, password_expiration_default ? 0 : 2147483647)
    password_expiration_default
  end
end
password_has_enough_character_groups? (password)
[show source]
# File lib/rodauth/features/password_complexity.rb, line 54
def password_has_enough_character_groups?(password)
  return true if password.length > password_max_length_for_groups_check
  return true if password_character_groups.select{|re| password =~ re}.length >= password_min_groups
  @password_requirement_message = password_not_enough_character_groups_message
  false
end
password_has_no_invalid_pattern? (password)
[show source]
# File lib/rodauth/features/password_complexity.rb, line 61
def password_has_no_invalid_pattern?(password)
  return true unless password_invalid_pattern
  return true if password !~ password_invalid_pattern
  @password_requirement_message = password_invalid_pattern_message
  false
end
password_hash (password)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 136
def password_hash(password)
  BCrypt::Password.create(password, :cost=>password_hash_cost)
end
password_hash_cost ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 125
def password_hash_cost
  BCrypt::Engine::MIN_COST
end
password_hash_ds ()
[show source]
# File lib/rodauth/features/base.rb, line 455
def password_hash_ds
  db[password_hash_table].where(password_hash_id_column=>account_id)
end
password_match? (password)
[show source]
# File lib/rodauth/features/base.rb, line 287
def password_match?(password)
  if hash = get_password_hash
    if account_password_hash_column || !use_database_authentication_functions?
      BCrypt::Password.new(hash) == password
    else
      db.get(Sequel.function(function_name(:rodauth_valid_password_hash), account_id, BCrypt::Engine.hash_secret(password, hash)))
    end 
  end
end
password_meets_length_requirements? (password)
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 112
def password_meets_length_requirements?(password)
  return true if password_minimum_length <= password.length
  @password_requirement_message = password_too_short_message
  false
end
password_meets_requirements? (password)
[show source]
# File lib/rodauth/features/disallow_common_passwords.rb, line 12
def password_meets_requirements?(password)
  super && password_not_one_of_the_most_common?(password)
end
password_not_in_dictionary? (password)
[show source]
# File lib/rodauth/features/password_complexity.rb, line 79
def password_not_in_dictionary?(password)
  return true unless dict = password_dictionary
  return true unless password =~ /\A(?:\d*)([A-Za-z!@$+|][A-Za-z!@$+|0134578]+[A-Za-z!@$+|])(?:\d*)\z/
  word = $1.downcase.tr('!@$+|0134578', 'iastloleastb')
  return true if !dict.include?(word)
  @password_requirement_message = password_in_dictionary_message
  false
end
password_not_one_of_the_most_common? (password)
[show source]
# File lib/rodauth/features/disallow_common_passwords.rb, line 32
def password_not_one_of_the_most_common?(password)
  return true unless password_one_of_most_common?(password)
  @password_requirement_message = password_is_one_of_the_most_common_message
  false
end
password_not_too_many_repeating_characters? (password)
[show source]
# File lib/rodauth/features/password_complexity.rb, line 68
def password_not_too_many_repeating_characters?(password)
  return true if password_max_repeating_characters < 2
  return true if password !~ /(.)(\1){#{password_max_repeating_characters-1}}/ 
  @password_requirement_message = password_too_many_repeating_characters_message
  false
end
password_one_of_most_common? (password)
[show source]
# File lib/rodauth/features/disallow_common_passwords.rb, line 26
def password_one_of_most_common?(password)
  most_common_passwords.include?(password)
end
password_recently_entered? ()
[show source]
# File lib/rodauth/features/password_grace_period.rb, line 36
def password_recently_entered?
  return false unless last_password_entry = session[last_password_entry_session_key]
  last_password_entry + password_grace_period > Time.now.to_i
end
password_reset_ds (id=account_id)
[show source]
# File lib/rodauth/features/reset_password.rb, line 257
def password_reset_ds(id=account_id)
  db[reset_password_table].where(reset_password_id_column=>id)
end
password_too_many_repeating_characters_message ()
[show source]
# File lib/rodauth/features/password_complexity.rb, line 75
def password_too_many_repeating_characters_message
  "contains #{password_max_repeating_characters} or more of the same character in a row"
end
password_too_short_message ()
[show source]
# File lib/rodauth/features/login_password_requirements_base.rb, line 75
def password_too_short_message
  "minimum #{password_minimum_length} characters"
end
post_configure ()
[show source]
# File lib/rodauth/features/base.rb, line 277
def post_configure
  require 'bcrypt' if require_bcrypt?
  db.extension :date_arithmetic if use_date_arithmetic?
  route_hash= {}
  self.class.routes.each do |meth|
    route_hash["/#{send("#{meth.to_s.sub(/\Ahandle_/, '')}_route")}"] = meth
  end
  self.class.route_hash = route_hash.freeze
end
previous_password_ds ()
[show source]
# File lib/rodauth/features/disallow_password_reuse.rb, line 76
def previous_password_ds
  db[previous_password_hash_table].where(previous_password_account_id_column=>account_id)
end
raises_uniqueness_violation? (&block)

In cases where retrying on uniqueness violations cannot work, this will detect whether a uniqueness violation is raised by the block and return the exception if so. This method should be used if you don't care about the exception itself.

[show source]
# File lib/rodauth/features/base.rb, line 484
def raises_uniqueness_violation?(&block)
  transaction(:savepoint=>:only, &block)
  false
rescue unique_constraint_violation_class => e
  e
end
random_key ()
[show source]
# File lib/rodauth/features/base.rb, line 326
def random_key
  SecureRandom.urlsafe_base64(32)
end
recovery_code_match? (code)
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 186
def recovery_code_match?(code)
  recovery_codes.each do |s|
    if timing_safe_eql?(code, s)
      recovery_codes_ds.where(recovery_codes_column=>code).delete
      if recovery_codes_primary?
        add_recovery_code
      end
      return true
    end
  end
  false
end
recovery_codes_ds ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 236
def recovery_codes_ds
  db[recovery_codes_table].where(recovery_codes_id_column=>session_value)
end
recovery_codes_primary? ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 228
def recovery_codes_primary?
  (features & [:otp, :sms_codes]).empty?
end
recovery_codes_remove ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 182
def recovery_codes_remove
  recovery_codes_ds.delete
end
redirect (path)
[show source]
# File lib/rodauth/features/base.rb, line 317
def redirect(path)
  request.redirect(path)
end
remember_key_ds (id=account_id)
[show source]
# File lib/rodauth/features/remember.rb, line 193
def remember_key_ds(id=account_id)
  db[remember_table].where(remember_id_column=>id)
end
remember_login ()
[show source]
# File lib/rodauth/features/remember.rb, line 116
def remember_login
  get_remember_key
  opts = Hash[remember_cookie_options]
  opts[:value] = "#{account_id}_#{remember_key_value}"
  opts[:expires] = convert_timestamp(active_remember_key_ds.get(remember_deadline_column))
  ::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
end
remove_email_auth_key ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 126
def remove_email_auth_key
  email_auth_ds.delete
end
remove_lockout_metadata ()
[show source]
# File lib/rodauth/features/lockout.rb, line 265
def remove_lockout_metadata
  account_login_failures_ds.delete
  account_lockouts_ds.delete
end
remove_remember_key (id=account_id)
[show source]
# File lib/rodauth/features/remember.rb, line 154
def remove_remember_key(id=account_id)
  remember_key_ds(id).delete
end
remove_reset_password_key ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 169
def remove_reset_password_key
  password_reset_ds.delete
end
remove_verify_account_key ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 159
def remove_verify_account_key
  verify_account_ds.delete
end
remove_verify_login_change_key ()
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 101
def remove_verify_login_change_key
  verify_login_change_ds.delete
end
render (page)
[show source]
# File lib/rodauth/features/base.rb, line 269
def render(page)
  _view(:render, page)
end
request ()
[show source]
# File lib/rodauth/features/base.rb, line 113
def request
  scope.request
end
require_account ()
[show source]
# File lib/rodauth/features/base.rb, line 346
def require_account
  require_authentication
  require_account_session
end
require_account_session ()
[show source]
# File lib/rodauth/features/base.rb, line 351
def require_account_session
  unless account_from_session
    clear_session
    login_required
  end
end
require_authentication ()
[show source]
# File lib/rodauth/features/base.rb, line 227
def require_authentication
  require_login
end
require_current_password ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 60
def require_current_password
  if authenticated? && password_expired? && password_change_needed_redirect != request.path_info
    set_redirect_error_flash password_expiration_error_flash
    redirect password_change_needed_redirect
  end
end
require_login ()
[show source]
# File lib/rodauth/features/base.rb, line 219
def require_login
  login_required unless logged_in?
end
require_otp_setup ()
[show source]
# File lib/rodauth/features/otp.rb, line 240
def require_otp_setup
  unless otp_exists?
    set_redirect_error_status(two_factor_not_setup_error_status)
    set_redirect_error_flash two_factor_not_setup_error_flash
    redirect two_factor_need_setup_redirect
  end
end
require_sms_available ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 355
def require_sms_available
  require_sms_setup

  if sms_locked_out?
    set_redirect_error_status(lockout_error_status)
    set_redirect_error_flash sms_lockout_error_flash
    redirect sms_lockout_redirect
  end
end
require_sms_not_setup ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 347
def require_sms_not_setup
  if sms_setup?
    set_redirect_error_status(sms_already_setup_error_status)
    set_redirect_error_flash sms_already_setup_error_flash
    redirect sms_already_setup_redirect
  end
end
require_sms_setup ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 339
def require_sms_setup
  unless sms_setup?
    set_redirect_error_status(two_factor_not_setup_error_status)
    set_redirect_error_flash sms_not_setup_error_flash
    redirect sms_needs_setup_redirect
  end
end
require_two_factor_authenticated ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 77
def require_two_factor_authenticated
  unless two_factor_authenticated?
    set_redirect_error_status(two_factor_need_authentication_error_status)
    set_redirect_error_flash two_factor_need_authentication_error_flash
    redirect _two_factor_auth_required_redirect
  end
end
require_two_factor_not_authenticated ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 69
def require_two_factor_not_authenticated
  if two_factor_authenticated?
    set_redirect_error_status(two_factor_already_authenticated_error_status)
    set_redirect_error_flash two_factor_already_authenticated_error_flash
    redirect two_factor_already_authenticated_redirect
  end
end
require_two_factor_setup ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 58
def require_two_factor_setup
  # Avoid database query if already authenticated via 2nd factor
  return if two_factor_authenticated?

  return if uses_two_factor_authentication?

  set_redirect_error_status(two_factor_not_setup_error_status)
  set_redirect_error_flash two_factor_not_setup_error_flash
  redirect two_factor_need_setup_redirect
end
reset_password_email_body ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 243
def reset_password_email_body
  render('reset-password-email')
end
reset_password_email_recently_sent? ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 213
def reset_password_email_recently_sent?
  (email_last_sent = get_reset_password_email_last_sent) && (Time.now - email_last_sent < reset_password_skip_resend_email_within)
end
reset_password_key_insert_hash ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 251
def reset_password_key_insert_hash
  hash = {reset_password_id_column=>account_id, reset_password_key_column=>reset_password_key_value}
  set_deadline_value(hash, reset_password_deadline_column, reset_password_deadline_interval)
  hash
end
reset_single_session_key ()
[show source]
# File lib/rodauth/features/single_session.rb, line 19
def reset_single_session_key
  if logged_in?
    single_session_ds.update(single_session_key_column=>random_key)
  end
end
response ()
[show source]
# File lib/rodauth/features/base.rb, line 117
def response
  scope.response
end
retry_on_uniqueness_violation (&block)

This is used to avoid race conditions when using the pattern of inserting when an update affects no rows. In such cases, if a row is inserted between the update and the insert, the insert will fail with a uniqueness error, but retrying will work. It is possible for it to fail again, but only if the row is deleted before the update and readded before the insert, which is very unlikely to happen. In such cases, raising an exception is acceptable.

[show source]
# File lib/rodauth/features/base.rb, line 475
def retry_on_uniqueness_violation(&block)
  if raises_uniqueness_violation?(&block)
    yield
  end
end
return_json_response ()
[show source]
# File lib/rodauth/features/jwt.rb, line 211
def return_json_response
  response.status ||= json_response_error_status if json_response[json_response_error_key]
  set_jwt
  response['Content-Type'] ||= json_response_content_type
  response.write(_json_response_body(json_response))
  request.halt
end
route! ()
[show source]
# File lib/rodauth/features/base.rb, line 129
def route!
  if meth = self.class.route_hash[request.remaining_path]
    send(meth)
  end

  nil
end
save_account ()
[show source]
# File lib/rodauth/features/create_account.rb, line 106
def save_account
  id = nil
  raised = raises_uniqueness_violation?{id = db[accounts_table].insert(account)}

  if raised
    @login_requirement_message = 'already an account with this login'
  end

  if id
    account[account_id_column] = id
  end

  id && !raised
end
send_email_auth_email ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 134
def send_email_auth_email
  create_email_auth_email.deliver!
end
send_password_changed_email ()
[show source]
# File lib/rodauth/features/change_password_notify.rb, line 18
def send_password_changed_email
  create_password_changed_email.deliver!
end
send_reset_password_email ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 177
def send_reset_password_email
  create_reset_password_email.deliver!
end
send_unlock_account_email ()
[show source]
# File lib/rodauth/features/lockout.rb, line 214
def send_unlock_account_email
  @unlock_account_key_value = get_unlock_account_key
  create_unlock_account_email.deliver!
end
send_verify_account_email ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 197
def send_verify_account_email
  create_verify_account_email.deliver!
end
send_verify_login_change_email (login)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 117
def send_verify_login_change_email(login)
  create_verify_login_change_email(login).deliver!
end
session ()
[show source]
# File lib/rodauth/features/base.rb, line 121
def session
  scope.session
end
session_expiration_redirect ()
[show source]
# File lib/rodauth/features/session_expiration.rb, line 43
def session_expiration_redirect
  require_login_redirect
end
session_jwt ()
[show source]
# File lib/rodauth/features/jwt.rb, line 116
def session_jwt
  JWT.encode(jwt_session_hash, jwt_secret, jwt_algorithm)
end
session_value ()
[show source]
# File lib/rodauth/features/base.rb, line 151
def session_value
  session[session_key]
end
set_deadline_value (hash, column, interval)

This is needed on MySQL, which doesn't support non constant defaults other than CURRENT_TIMESTAMP.

[show source]
# File lib/rodauth/features/base.rb, line 511
def set_deadline_value(hash, column, interval)
  if set_deadline_values?
    # :nocov:
    hash[column] = Sequel.date_add(Sequel::CURRENT_TIMESTAMP, interval)
    # :nocov:
  end
end
set_deadline_values? ()
[show source]
# File lib/rodauth/features/base.rb, line 384
def set_deadline_values?
  db.database_type == :mysql
end
set_email_auth_email_last_sent ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 114
def set_email_auth_email_last_sent
   email_auth_ds.update(email_auth_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if email_auth_email_last_sent_column
end
set_error_flash (message)
[show source]
# File lib/rodauth/features/base.rb, line 203
def set_error_flash(message)
  flash.now[flash_error_key] = message
end
set_expired ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 48
def set_expired
  update_activity(account_id, account_activity_expired_column)
  after_account_expiration
end
set_field_error (field, error)
[show source]
# File lib/rodauth/features/base.rb, line 137
def set_field_error(field, error)
  (@field_errors ||= {})[field] = error
end
set_http_basic_auth_error_response ()
[show source]
# File lib/rodauth/features/http_basic_auth.rb, line 53
def set_http_basic_auth_error_response
  response.status = 401
  response.headers["WWW-Authenticate"] = "Basic realm=\"#{http_basic_auth_realm}\""
end
set_jwt ()
[show source]
# File lib/rodauth/features/jwt.rb, line 219
def set_jwt
  set_jwt_token(session_jwt)
end
set_jwt_token (token)
[show source]
# File lib/rodauth/features/jwt.rb, line 128
def set_jwt_token(token)
  response.headers['Authorization'] = token
end
set_last_password_entry ()
[show source]
# File lib/rodauth/features/password_grace_period.rb, line 41
def set_last_password_entry
  session[last_password_entry_session_key] = Time.now.to_i
end
set_new_account_password (password)
[show source]
# File lib/rodauth/features/create_account.rb, line 98
def set_new_account_password(password)
  account[account_password_hash_column] = password_hash(password)
end
set_notice_flash (message)
[show source]
# File lib/rodauth/features/base.rb, line 211
def set_notice_flash(message)
  flash[flash_notice_key] = message
end
set_notice_now_flash (message)
[show source]
# File lib/rodauth/features/base.rb, line 215
def set_notice_now_flash(message)
  flash.now[flash_notice_key] = message
end
set_password (password)
[show source]
# File lib/rodauth/features/disallow_password_reuse.rb, line 18
def set_password(password)
  hash = super
  add_previous_password_hash(hash)
  hash
end
set_redirect_error_flash (message)
[show source]
# File lib/rodauth/features/base.rb, line 207
def set_redirect_error_flash(message)
  flash[flash_error_key] = message
end
set_redirect_error_status (status)

Don't set an error status when redirecting in an error case, as a redirect status is needed.

[show source]
# File lib/rodauth/features/base.rb, line 363
def set_redirect_error_status(status)
end
set_reset_password_email_last_sent ()
[show source]
# File lib/rodauth/features/reset_password.rb, line 199
def set_reset_password_email_last_sent
   password_reset_ds.update(reset_password_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if reset_password_email_last_sent_column
end
set_response_error_status (status)
[show source]
# File lib/rodauth/features/base.rb, line 366
def set_response_error_status(status)
  response.status = status
end
set_session_value (key, value)
[show source]
# File lib/rodauth/features/base.rb, line 519
def set_session_value(key, value)
  session[key] = value
end
set_title (title)
[show source]
# File lib/rodauth/features/base.rb, line 197
def set_title(title)
  if title_instance_variable
    scope.instance_variable_set(title_instance_variable, title)
  end
end
set_unlock_account_email_last_sent ()
[show source]
# File lib/rodauth/features/lockout.rb, line 231
def set_unlock_account_email_last_sent
  account_lockouts_ds.update(account_lockouts_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if account_lockouts_email_last_sent_column
end
set_verify_account_email_last_sent ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 230
def set_verify_account_email_last_sent
   verify_account_ds.update(verify_account_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if verify_account_email_last_sent_column
end
setup_account_verification ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 265
def setup_account_verification
  generate_verify_account_key_value
  create_verify_account_key
  send_verify_account_email
end
show_lockout_page ()
[show source]
# File lib/rodauth/features/lockout.rb, line 270
def show_lockout_page
  set_response_error_status lockout_error_status
  set_error_flash login_lockout_error_flash
  response.write unlock_account_request_view
  request.halt
end
single_session_ds ()
[show source]
# File lib/rodauth/features/single_session.rb, line 81
def single_session_ds
  db[single_session_table].
    where(single_session_id_column=>session_value)
end
skip_login_field_on_login? ()
[show source]
# File lib/rodauth/features/login.rb, line 69
def skip_login_field_on_login?
  return false unless use_multi_phase_login?
  @valid_login_entered
end
skip_password_field_on_login? ()
[show source]
# File lib/rodauth/features/login.rb, line 74
def skip_password_field_on_login?
  return false unless use_multi_phase_login?
  @valid_login_entered != true
end
skip_status_checks? ()
[show source]
# File lib/rodauth/features/close_account.rb, line 79
def skip_status_checks?
  false
end
sms_auth_message (code)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 416
def sms_auth_message(code)
  "SMS authentication code for #{request.host} is #{code}"
end
sms_available? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 458
def sms_available?
  sms && !sms_needs_confirmation? && !sms_locked_out?
end
sms_code ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 437
def sms_code
  sms[sms_code_column]
end
sms_code_issued_at ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 441
def sms_code_issued_at
  convert_timestamp(sms[sms_issued_at_column])
end
sms_code_match? (code)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 365
def sms_code_match?(code)
  return false unless sms_current_auth?
  timing_safe_eql?(code, sms_code)
end
sms_codes_primary? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 472
def sms_codes_primary?
  !features.include?(:otp)
end
sms_confirm ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 163
def sms_confirm
  super if defined?(super)
  add_recovery_codes(recovery_codes_limit - recovery_codes.length)
end
sms_confirm_failure ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 380
def sms_confirm_failure
  sms_ds.delete
end
sms_confirm_message (code)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 420
def sms_confirm_message(code)
  "SMS confirmation code for #{request.host} is #{code}"
end
sms_confirmation_match? (code)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 370
def sms_confirmation_match?(code)
  sms_needs_confirmation? && sms_code_match?(code)
end
sms_current_auth? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 466
def sms_current_auth?
  sms_code && sms_code_issued_at + sms_code_allowed_seconds > Time.now
end
sms_disable ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 175
def sms_disable
  super if defined?(super)
  unless recovery_codes_primary?
    recovery_codes_remove
  end
end
sms_ds ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 500
def sms_ds
  db[sms_codes_table].where(sms_id_column=>session_value)
end
sms_failures ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 445
def sms_failures
  sms[sms_failures_column]
end
sms_locked_out? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 462
def sms_locked_out?
  sms_failures >= sms_failure_limit
end
sms_needs_confirmation? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 454
def sms_needs_confirmation?
  sms && sms_failures.nil?
end
sms_new_auth_code ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 480
def sms_new_auth_code
  SecureRandom.random_number(10**sms_auth_code_length).to_s.rjust(sms_auth_code_length, "0")
end
sms_new_confirm_code ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 484
def sms_new_confirm_code
  SecureRandom.random_number(10**sms_confirm_code_length).to_s.rjust(sms_confirm_code_length, "0")
end
sms_normalize_phone (phone)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 476
def sms_normalize_phone(phone)
  phone.to_s.gsub(/\D+/, '')
end
sms_phone ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 433
def sms_phone
  sms[sms_phone_column]
end
sms_record_failure ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 428
def sms_record_failure
  update_sms(sms_failures_column=>Sequel.expr(sms_failures_column)+1)
  sms[sms_failures_column] = sms_ds.get(sms_failures_column)
end
sms_remove_failures ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 391
def sms_remove_failures
  update_sms(sms_failures_column => 0, sms_code_column => nil)
end
sms_send (phone, message)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 488
def sms_send(phone, message)
  raise NotImplementedError, "sms_send needs to be defined in the Rodauth configuration for SMS sending to work"
end
sms_send_auth_code ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 400
def sms_send_auth_code
  code = sms_new_auth_code
  sms_set_code(code)
  sms_send(sms_phone, sms_auth_message(code))
end
sms_send_confirm_code ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 406
def sms_send_confirm_code
  code = sms_new_confirm_code
  sms_set_code(code)
  sms_send(sms_phone, sms_confirm_message(code))
end
sms_set_code (code)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 424
def sms_set_code(code)
 update_sms(sms_code_column=>code, sms_issued_at_column=>Sequel::CURRENT_TIMESTAMP)
end
sms_setup (phone_number)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 384
def sms_setup(phone_number)
  # Cannot handle uniqueness violation here, as the phone number given may not match the
  # one in the table.
  sms_ds.insert(sms_id_column=>session_value, sms_phone_column=>phone_number)
  remove_instance_variable(:@sms) if instance_variable_defined?(:@sms)
end
sms_setup? ()
[show source]
# File lib/rodauth/features/sms_codes.rb, line 449
def sms_setup?
  return false unless sms
  !sms_needs_confirmation?
end
sms_valid_phone? (phone)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 412
def sms_valid_phone?(phone)
  phone.length >= sms_phone_min_length
end
split_token (token)
[show source]
# File lib/rodauth/features/email_base.rb, line 47
def split_token(token)
  token.split(token_separator, 2)
end
template_path (page)
[show source]
# File lib/rodauth/features/base.rb, line 444
def template_path(page)
  File.join(File.dirname(__FILE__), '../../../templates', "#{page}.str")
end
throw_basic_auth_error (*args)
[show source]
# File lib/rodauth/features/http_basic_auth.rb, line 58
def throw_basic_auth_error(*args)
  set_http_basic_auth_error_response
  throw_error(*args) 
end
throw_error (field, error)
[show source]
# File lib/rodauth/features/base.rb, line 370
def throw_error(field, error)
  set_field_error(field, error)
  throw :rodauth_error
end
throw_error_status (status, field, error)
[show source]
# File lib/rodauth/features/base.rb, line 375
def throw_error_status(status, field, error)
  set_response_error_status(status)
  throw_error(field, error)
end
timing_safe_eql? (provided, actual)
[show source]
# File lib/rodauth/features/base.rb, line 341
def timing_safe_eql?(provided, actual)
  provided = provided.to_s
  Rack::Utils.secure_compare(provided.ljust(actual.length), actual) && provided.length == actual.length
end
transaction (opts={}, &block)
[show source]
# File lib/rodauth/features/base.rb, line 321
def transaction(opts={}, &block)
  db.transaction(opts, &block)
end
two_factor_auth_fallback_redirect ()
[show source]
# File lib/rodauth/features/recovery_codes.rb, line 133
def two_factor_auth_fallback_redirect
  recovery_auth_redirect
end
two_factor_auth_required_redirect ()
[show source]
# File lib/rodauth/features/otp.rb, line 213
def two_factor_auth_required_redirect
  "#{prefix}/#{otp_auth_route}"
end
two_factor_authenticate (type)
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 126
def two_factor_authenticate(type)
  two_factor_update_session(type)
  two_factor_remove_auth_failures
  after_two_factor_authentication
  set_notice_flash two_factor_auth_notice_flash
  redirect two_factor_auth_redirect
end
two_factor_authenticated? ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 101
def two_factor_authenticated?
  !!session[two_factor_session_key]
end
two_factor_authentication_setup? ()
[show source]
# File lib/rodauth/features/otp.rb, line 205
def two_factor_authentication_setup?
  super || otp_exists?
end
two_factor_modifications_require_password? ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 34
def two_factor_modifications_require_password?
  modifications_require_password?
end
two_factor_need_setup_redirect ()
[show source]
# File lib/rodauth/features/otp.rb, line 209
def two_factor_need_setup_redirect
  "#{prefix}/#{otp_setup_route}"
end
two_factor_password_match? (password)
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 93
def two_factor_password_match?(password)
  if two_factor_modifications_require_password?
    password_match?(password)
  else
    true
  end
end
two_factor_remove ()
[show source]
# File lib/rodauth/features/otp.rb, line 217
def two_factor_remove
  super
  otp_remove
end
two_factor_remove_auth_failures ()
[show source]
# File lib/rodauth/features/otp.rb, line 222
def two_factor_remove_auth_failures
  super
  otp_remove_auth_failures
end
two_factor_remove_session ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 134
def two_factor_remove_session
  session.delete(two_factor_session_key)
  session[two_factor_setup_session_key] = false
end
two_factor_update_session (type)
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 139
def two_factor_update_session(type)
  session[two_factor_session_key] = type
  session[two_factor_setup_session_key] = true
end
unique_constraint_violation_class ()

Work around jdbc/sqlite issue where it only raises ConstraintViolation and not UniqueConstraintViolation.

[show source]
# File lib/rodauth/features/base.rb, line 493
def unique_constraint_violation_class
  if db.adapter_scheme == :jdbc && db.database_type == :sqlite
    # :nocov:
    Sequel::ConstraintViolation
    # :nocov:
  else
    Sequel::UniqueConstraintViolation
  end
end
unlock_account ()
[show source]
# File lib/rodauth/features/lockout.rb, line 154
def unlock_account
  transaction do
    remove_lockout_metadata
  end
end
unlock_account_email_body ()
[show source]
# File lib/rodauth/features/lockout.rb, line 281
def unlock_account_email_body
  render('unlock-account-email')
end
unlock_account_email_recently_sent? ()
[show source]
# File lib/rodauth/features/lockout.rb, line 285
def unlock_account_email_recently_sent?
  (email_last_sent = get_unlock_account_email_last_sent) && (Time.now - email_last_sent < unlock_account_skip_resend_email_within)
end
update_account (values, ds=account_ds)
[show source]
# File lib/rodauth/features/base.rb, line 533
def update_account(values, ds=account_ds)
  update_hash_ds(account, ds, values)
end
update_activity (account_id, *columns)
[show source]
# File lib/rodauth/features/account_expiration.rb, line 112
def update_activity(account_id, *columns)
  ds = account_activity_ds(account_id)
  hash = {}
  columns.each do |c|
    hash[c] = Sequel::CURRENT_TIMESTAMP
  end
  if ds.update(hash) == 0
    hash[account_activity_id_column] = account_id
    hash[account_activity_last_activity_column] ||= Sequel::CURRENT_TIMESTAMP
    hash[account_activity_last_login_column] ||= Sequel::CURRENT_TIMESTAMP
    # It is safe to ignore uniqueness violations here, as a concurrent insert would also use current timestamps.
    ignore_uniqueness_violation{ds.insert(hash)}
  end
end
update_hash_ds (hash, ds, values)
[show source]
# File lib/rodauth/features/base.rb, line 523
def update_hash_ds(hash, ds, values)
  num = ds.update(values)
  if num == 1
    values.each do |k, v|
      account[k] = v == Sequel::CURRENT_TIMESTAMP ? Time.now : v
    end
  end
  num
end
update_last_activity ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 42
def update_last_activity
  if session_value
    update_activity(session_value, account_activity_last_activity_column)
  end
end
update_last_login ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 38
def update_last_login
  update_activity(account_id, account_activity_last_login_column, account_activity_last_activity_column)
end
update_login (login)
[show source]
# File lib/rodauth/features/change_login.rb, line 75
def update_login(login)
  _update_login(login)
end
update_password_changed_at ()
[show source]
# File lib/rodauth/features/password_expiration.rb, line 51
def update_password_changed_at
  ds = password_expiration_ds
  if ds.update(password_expiration_changed_at_column=>Sequel::CURRENT_TIMESTAMP) == 0
    # Ignoring the violation is safe here, since a concurrent insert would also set it to the
    # current timestamp.
    ignore_uniqueness_violation{ds.insert(password_expiration_id_column=>account_id)}
  end
end
update_password_hash? ()
[show source]
# File lib/rodauth/features/update_password_hash.rb, line 16
def update_password_hash?
  password_hash_cost != @current_password_hash_cost
end
update_session ()
[show source]
# File lib/rodauth/features/account_expiration.rb, line 98
def update_session
  check_account_expiration
  super
end
update_single_session_key ()
[show source]
# File lib/rodauth/features/single_session.rb, line 53
def update_single_session_key
  key = random_key
  set_session_value(single_session_session_key, key)
  if single_session_ds.update(single_session_key_column=>key) == 0
    # Don't handle uniqueness violations here.  While we could get the stored key from the
    # database, it could lead to two sessions sharing the same key, which this feature is
    # designed to prevent.
    single_session_ds.insert(single_session_id_column=>session_value, single_session_key_column=>key)
  end
end
update_sms (values)
[show source]
# File lib/rodauth/features/sms_codes.rb, line 492
def update_sms(values)
  update_hash_ds(sms, sms_ds, values)
end
use_database_authentication_functions? ()
[show source]
# File lib/rodauth/features/base.rb, line 388
def use_database_authentication_functions?
  case db.database_type
  when :postgres, :mysql, :mssql
    true
  else
    # :nocov:
    false
    # :nocov:
  end
end
use_date_arithmetic? ()
[show source]
# File lib/rodauth/features/base.rb, line 380
def use_date_arithmetic?
  set_deadline_values?
end
use_jwt? ()
[show source]
# File lib/rodauth/features/jwt.rb, line 132
def use_jwt?
  jwt_token || only_json? || json_request?
end
use_multi_phase_login? ()
[show source]
# File lib/rodauth/features/email_auth.rb, line 172
def use_multi_phase_login?
  true
end
use_request_specific_csrf_tokens? ()
[show source]
# File lib/rodauth/features/base.rb, line 399
def use_request_specific_csrf_tokens?
  scope.opts[:rodauth_csrf] == :route_csrf && scope.use_request_specific_csrf_tokens?
end
uses_two_factor_authentication? ()
[show source]
# File lib/rodauth/features/two_factor_base.rb, line 109
def uses_two_factor_authentication?
  return false unless logged_in?
  session[two_factor_setup_session_key] = two_factor_authentication_setup? unless session.has_key?(two_factor_setup_session_key)
  session[two_factor_setup_session_key]
end
valid_jwt? ()
[show source]
# File lib/rodauth/features/jwt.rb, line 136
def valid_jwt?
  !!(jwt_token && jwt_payload)
end
verified_account? ()
[show source]
# File lib/rodauth/features/verify_account_grace_period.rb, line 16
def verified_account?
  logged_in? && !session[unverified_account_session_key]
end
verify_account ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 163
def verify_account
  update_account(account_status_column=>account_open_status_value) == 1
end
verify_account_check_already_logged_in ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 271
def verify_account_check_already_logged_in
  check_already_logged_in
end
verify_account_ds (id=account_id)
[show source]
# File lib/rodauth/features/verify_account.rb, line 304
def verify_account_ds(id=account_id)
  db[verify_account_table].where(verify_account_id_column=>id)
end
verify_account_email_body ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 300
def verify_account_email_body
  render('verify-account-email')
end
verify_account_email_recently_sent? ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 244
def verify_account_email_recently_sent?
  (email_last_sent = get_verify_account_email_last_sent) && (Time.now - email_last_sent < verify_account_skip_resend_email_within)
end
verify_account_email_resend ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 167
def verify_account_email_resend
  if @verify_account_key_value = get_verify_account_key(account_id)
    set_verify_account_email_last_sent
    send_verify_account_email
    true
  end
end
verify_account_key_insert_hash ()
[show source]
# File lib/rodauth/features/verify_account.rb, line 292
def verify_account_key_insert_hash
  {verify_account_id_column=>account_id, verify_account_key_column=>verify_account_key_value}
end
verify_login_change ()
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 105
def verify_login_change
  unless res = _update_login(verify_login_change_new_login)
    remove_verify_login_change_key
  end

  res
end
verify_login_change_ds (id=account_id)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 199
def verify_login_change_ds(id=account_id)
  db[verify_login_change_table].where(verify_login_change_id_column=>id)
end
verify_login_change_email_body ()
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 195
def verify_login_change_email_body
  render('verify-login-change-email')
end
verify_login_change_key_insert_hash (login)
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 185
def verify_login_change_key_insert_hash(login)
  hash = {verify_login_change_id_column=>account_id, verify_login_change_key_column=>verify_login_change_key_value, verify_login_change_login_column=>login}
  set_deadline_value(hash, verify_login_change_deadline_column, verify_login_change_deadline_interval)
  hash
end
verify_login_change_old_login ()
[show source]
# File lib/rodauth/features/verify_login_change.rb, line 133
def verify_login_change_old_login
  account_ds.get(login_column)
end
view (page, title)
[show source]
# File lib/rodauth/features/base.rb, line 264
def view(page, title)
  set_title(title)
  _view(:view, page)
end