Commit 86443a7f authored by jplang's avatar jplang

Configurable session lifetime and timeout (#6597).

git-svn-id: https://svn.redmine.org/redmine/trunk@9797 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent d239f3d7
...@@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base ...@@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base
cookies.delete(:autologin) cookies.delete(:autologin)
end end
before_filter :user_setup, :check_if_login_required, :set_localization before_filter :session_expiration, :user_setup, :check_if_login_required, :set_localization
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
rescue_from ::Unauthorized, :with => :deny_access rescue_from ::Unauthorized, :with => :deny_access
...@@ -44,6 +44,38 @@ class ApplicationController < ActionController::Base ...@@ -44,6 +44,38 @@ class ApplicationController < ActionController::Base
include Redmine::MenuManager::MenuController include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper helper Redmine::MenuManager::MenuHelper
def session_expiration
if session[:user_id]
if session_expired? && !try_to_autologin
reset_session
flash[:error] = l(:error_session_expired)
redirect_to signin_url
else
session[:atime] = Time.now.utc.to_i
end
end
end
def session_expired?
if Setting.session_lifetime?
unless session[:ctime] && (Time.now.utc.to_i - session[:ctime].to_i <= Setting.session_lifetime.to_i * 60)
return true
end
end
if Setting.session_timeout?
unless session[:atime] && (Time.now.utc.to_i - session[:atime].to_i <= Setting.session_timeout.to_i * 60)
return true
end
end
false
end
def start_user_session(user)
session[:user_id] = user.id
session[:ctime] = Time.now.utc.to_i
session[:atime] = Time.now.utc.to_i
end
def user_setup def user_setup
# Check the settings cache for each request # Check the settings cache for each request
Setting.check_cache Setting.check_cache
...@@ -57,10 +89,7 @@ class ApplicationController < ActionController::Base ...@@ -57,10 +89,7 @@ class ApplicationController < ActionController::Base
if session[:user_id] if session[:user_id]
# existing session # existing session
(User.active.find(session[:user_id]) rescue nil) (User.active.find(session[:user_id]) rescue nil)
elsif cookies[:autologin] && Setting.autologin? elsif user = try_to_autologin
# auto-login feature starts a new session
user = User.try_to_autologin(cookies[:autologin])
session[:user_id] = user.id if user
user user
elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth? elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth?
# RSS key authentication does not start a session # RSS key authentication does not start a session
...@@ -78,12 +107,24 @@ class ApplicationController < ActionController::Base ...@@ -78,12 +107,24 @@ class ApplicationController < ActionController::Base
end end
end end
def try_to_autologin
if cookies[:autologin] && Setting.autologin?
# auto-login feature starts a new session
user = User.try_to_autologin(cookies[:autologin])
if user
reset_session
start_user_session(user)
end
user
end
end
# Sets the logged in user # Sets the logged in user
def logged_user=(user) def logged_user=(user)
reset_session reset_session
if user && user.is_a?(User) if user && user.is_a?(User)
User.current = user User.current = user
session[:user_id] = user.id start_user_session(user)
else else
User.current = User.anonymous User.current = User.anonymous
end end
......
...@@ -21,5 +21,16 @@ ...@@ -21,5 +21,16 @@
<p><%= setting_check_box :rest_api_enabled %></p> <p><%= setting_check_box :rest_api_enabled %></p>
</div> </div>
<fieldset class="box">
<legend><%= l(:label_session_expiration) %></legend>
<div class="tabular settings">
<p><%= setting_select :session_lifetime, [[l(:label_disabled), 0]] + [1, 7, 30, 60, 365].collect{|days| [l('datetime.distance_in_words.x_days', :count => days), (days * 60 * 24).to_s]} %></p>
<p><%= setting_select :session_timeout, [[l(:label_disabled), 0]] + [1, 2, 4, 8, 12, 24, 48].collect{|hours| [l('datetime.distance_in_words.x_hours', :count => hours), (hours * 60).to_s]} %></p>
</div>
<p><em class="info"><%= l(:text_session_expiration_settings) %></em></p>
</fieldset>
<%= submit_tag l(:button_save) %> <%= submit_tag l(:button_save) %>
<% end %> <% end %>
...@@ -49,6 +49,9 @@ ar: ...@@ -49,6 +49,9 @@ ar:
about_x_hours: about_x_hours:
one: "حوالي ساعة" one: "حوالي ساعة"
other: "ساعات %{count}حوالي " other: "ساعات %{count}حوالي "
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "يوم" one: "يوم"
other: "%{count} أيام" other: "%{count} أيام"
...@@ -1031,3 +1034,8 @@ ar: ...@@ -1031,3 +1034,8 @@ ar:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -50,6 +50,9 @@ bg: ...@@ -50,6 +50,9 @@ bg:
about_x_hours: about_x_hours:
one: "около 1 час" one: "около 1 час"
other: "около %{count} часа" other: "около %{count} часа"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 ден" one: "1 ден"
other: "%{count} дена" other: "%{count} дена"
...@@ -1028,3 +1031,8 @@ bg: ...@@ -1028,3 +1031,8 @@ bg:
description_date_range_interval: Изберете диапазон чрез задаване на начална и крайна дати description_date_range_interval: Изберете диапазон чрез задаване на начална и крайна дати
description_date_from: Въведете начална дата description_date_from: Въведете начална дата
description_date_to: Въведете крайна дата description_date_to: Въведете крайна дата
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -48,6 +48,9 @@ bs: ...@@ -48,6 +48,9 @@ bs:
about_x_hours: about_x_hours:
one: "oko 1 sahat" one: "oko 1 sahat"
other: "oko %{count} sahata" other: "oko %{count} sahata"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 dan" one: "1 dan"
other: "%{count} dana" other: "%{count} dana"
...@@ -1045,3 +1048,8 @@ bs: ...@@ -1045,3 +1048,8 @@ bs:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -52,6 +52,9 @@ ca: ...@@ -52,6 +52,9 @@ ca:
about_x_hours: about_x_hours:
one: "aproximadament 1 hora" one: "aproximadament 1 hora"
other: "aproximadament %{count} hores" other: "aproximadament %{count} hores"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 dia" one: "1 dia"
other: "%{count} dies" other: "%{count} dies"
...@@ -1033,3 +1036,8 @@ ca: ...@@ -1033,3 +1036,8 @@ ca:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -53,6 +53,9 @@ cs: ...@@ -53,6 +53,9 @@ cs:
about_x_hours: about_x_hours:
one: "asi 1 hodina" one: "asi 1 hodina"
other: "asi %{count} hodin" other: "asi %{count} hodin"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 den" one: "1 den"
other: "%{count} dnů" other: "%{count} dnů"
...@@ -1034,3 +1037,8 @@ cs: ...@@ -1034,3 +1037,8 @@ cs:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -51,6 +51,9 @@ da: ...@@ -51,6 +51,9 @@ da:
about_x_hours: about_x_hours:
one: "cirka en time" one: "cirka en time"
other: "cirka %{count} timer" other: "cirka %{count} timer"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "en dag" one: "en dag"
other: "%{count} dage" other: "%{count} dage"
...@@ -1048,3 +1051,8 @@ da: ...@@ -1048,3 +1051,8 @@ da:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -52,6 +52,9 @@ de: ...@@ -52,6 +52,9 @@ de:
about_x_hours: about_x_hours:
one: 'etwa 1 Stunde' one: 'etwa 1 Stunde'
other: 'etwa %{count} Stunden' other: 'etwa %{count} Stunden'
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: '1 Tag' one: '1 Tag'
other: '%{count} Tagen' other: '%{count} Tagen'
...@@ -1049,3 +1052,8 @@ de: ...@@ -1049,3 +1052,8 @@ de:
setting_unsubscribe: Erlaubt Benutzern das eigene Benutzerkonto zu löschen setting_unsubscribe: Erlaubt Benutzern das eigene Benutzerkonto zu löschen
button_delete_my_account: Mein Benutzerkonto löschen button_delete_my_account: Mein Benutzerkonto löschen
text_account_destroy_confirmation: Möchten Sie wirklich fortfahren?\nIhr Benutzerkonto wird für immer gelöscht und kann nicht wiederhergestellt werden. text_account_destroy_confirmation: Möchten Sie wirklich fortfahren?\nIhr Benutzerkonto wird für immer gelöscht und kann nicht wiederhergestellt werden.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -51,6 +51,9 @@ el: ...@@ -51,6 +51,9 @@ el:
about_x_hours: about_x_hours:
one: "περίπου 1 ώρα" one: "περίπου 1 ώρα"
other: "περίπου %{count} ώρες" other: "περίπου %{count} ώρες"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 ημέρα" one: "1 ημέρα"
other: "%{count} ημέρες" other: "%{count} ημέρες"
...@@ -1031,3 +1034,8 @@ el: ...@@ -1031,3 +1034,8 @@ el:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -48,6 +48,9 @@ en-GB: ...@@ -48,6 +48,9 @@ en-GB:
about_x_hours: about_x_hours:
one: "about 1 hour" one: "about 1 hour"
other: "about %{count} hours" other: "about %{count} hours"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 day" one: "1 day"
other: "%{count} days" other: "%{count} days"
...@@ -1033,3 +1036,8 @@ en-GB: ...@@ -1033,3 +1036,8 @@ en-GB:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -49,6 +49,9 @@ en: ...@@ -49,6 +49,9 @@ en:
about_x_hours: about_x_hours:
one: "about 1 hour" one: "about 1 hour"
other: "about %{count} hours" other: "about %{count} hours"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 day" one: "1 day"
other: "%{count} days" other: "%{count} days"
...@@ -194,6 +197,7 @@ en: ...@@ -194,6 +197,7 @@ en:
error_unable_delete_issue_status: 'Unable to delete issue status' error_unable_delete_issue_status: 'Unable to delete issue status'
error_unable_to_connect: "Unable to connect (%{value})" error_unable_to_connect: "Unable to connect (%{value})"
error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})" error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})"
error_session_expired: "Your session has expired. Please login again."
warning_attachments_not_saved: "%{count} file(s) could not be saved." warning_attachments_not_saved: "%{count} file(s) could not be saved."
mail_subject_lost_password: "Your %{value} password" mail_subject_lost_password: "Your %{value} password"
...@@ -385,6 +389,8 @@ en: ...@@ -385,6 +389,8 @@ en:
setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues
setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
setting_unsubscribe: Allow users to delete their own account setting_unsubscribe: Allow users to delete their own account
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
permission_add_project: Create project permission_add_project: Create project
permission_add_subprojects: Create subprojects permission_add_subprojects: Create subprojects
...@@ -847,6 +853,7 @@ en: ...@@ -847,6 +853,7 @@ en:
label_item_position: "%{position} of %{count}" label_item_position: "%{position} of %{count}"
label_completed_versions: Completed versions label_completed_versions: Completed versions
label_search_for_watchers: Search for watchers to add label_search_for_watchers: Search for watchers to add
label_session_expiration: Session expiration
button_login: Login button_login: Login
button_submit: Submit button_submit: Submit
...@@ -982,6 +989,7 @@ en: ...@@ -982,6 +989,7 @@ en:
text_issue_conflict_resolution_add_notes: "Add my notes and discard my other changes" text_issue_conflict_resolution_add_notes: "Add my notes and discard my other changes"
text_issue_conflict_resolution_cancel: "Discard all my changes and redisplay %{link}" text_issue_conflict_resolution_cancel: "Discard all my changes and redisplay %{link}"
text_account_destroy_confirmation: "Are you sure you want to proceed?\nYour account will be permanently deleted, with no way to reactivate it." text_account_destroy_confirmation: "Are you sure you want to proceed?\nYour account will be permanently deleted, with no way to reactivate it."
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
default_role_manager: Manager default_role_manager: Manager
default_role_developer: Developer default_role_developer: Developer
......
...@@ -79,6 +79,9 @@ es: ...@@ -79,6 +79,9 @@ es:
about_x_hours: about_x_hours:
one: "alrededor de 1 hora" one: "alrededor de 1 hora"
other: "alrededor de %{count} horas" other: "alrededor de %{count} horas"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 día" one: "1 día"
other: "%{count} días" other: "%{count} días"
...@@ -1068,3 +1071,8 @@ es: ...@@ -1068,3 +1071,8 @@ es:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -66,6 +66,9 @@ et: ...@@ -66,6 +66,9 @@ et:
about_x_hours: about_x_hours:
one: "umbes tund" one: "umbes tund"
other: "umbes %{count} tundi" other: "umbes %{count} tundi"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 päev" one: "1 päev"
other: "%{count} päeva" other: "%{count} päeva"
...@@ -1044,3 +1047,8 @@ et: ...@@ -1044,3 +1047,8 @@ et:
description_date_range_interval: "Vali vahemik algus- ja lõpukuupäeva abil" description_date_range_interval: "Vali vahemik algus- ja lõpukuupäeva abil"
description_date_from: "Sisesta alguskuupäev" description_date_from: "Sisesta alguskuupäev"
description_date_to: "Sisesta lõpukuupäev" description_date_to: "Sisesta lõpukuupäev"
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -52,6 +52,9 @@ eu: ...@@ -52,6 +52,9 @@ eu:
about_x_hours: about_x_hours:
one: "ordu 1 inguru" one: "ordu 1 inguru"
other: "%{count} ordu inguru" other: "%{count} ordu inguru"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "egun 1" one: "egun 1"
other: "%{count} egun" other: "%{count} egun"
...@@ -1034,3 +1037,8 @@ eu: ...@@ -1034,3 +1037,8 @@ eu:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -49,6 +49,9 @@ fa: ...@@ -49,6 +49,9 @@ fa:
about_x_hours: about_x_hours:
one: "نزدیک 1 ساعت" one: "نزدیک 1 ساعت"
other: "نزدیک %{count} ساعت" other: "نزدیک %{count} ساعت"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "1 روز" one: "1 روز"
other: "%{count} روز" other: "%{count} روز"
...@@ -1033,3 +1036,8 @@ fa: ...@@ -1033,3 +1036,8 @@ fa:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -94,6 +94,9 @@ fi: ...@@ -94,6 +94,9 @@ fi:
about_x_hours: about_x_hours:
one: "noin tunti" one: "noin tunti"
other: "noin %{count} tuntia" other: "noin %{count} tuntia"
x_hours:
one: "1 hour"
other: "%{count} hours"
x_days: x_days:
one: "päivä" one: "päivä"
other: "%{count} päivää" other: "%{count} päivää"
...@@ -1052,3 +1055,8 @@ fi: ...@@ -1052,3 +1055,8 @@ fi:
text_account_destroy_confirmation: |- text_account_destroy_confirmation: |-
Are you sure you want to proceed? Are you sure you want to proceed?
Your account will be permanently deleted, with no way to reactivate it. Your account will be permanently deleted, with no way to reactivate it.
error_session_expired: Your session has expired. Please login again.
text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
setting_session_lifetime: Session maximum lifetime
setting_session_timeout: Session inactivity timeout
label_session_expiration: Session expiration
...@@ -53,6 +53,9 @@ fr: ...@@ -53,6 +53,9 @@ fr:
about_x_hours: about_x_hours:
one: "environ une heure" one: "environ une heure"
other: "environ %{count} heures" other: "environ %{count} heures"
x_hours:
one: "une heure"
other: "%{count} heures"
x_days: x_days:
one: "un jour" one: "un jour"
other: "%{count} jours" other: "%{count} jours"
...@@ -201,6 +204,7 @@ fr: ...@@ -201,6 +204,7 @@ fr:
error_workflow_copy_target: 'Veuillez sélectionner les trackers et rôles cibles' error_workflow_copy_target: 'Veuillez sélectionner les trackers et rôles cibles'
error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu être mis à jour. error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu être mis à jour.
error_attachment_too_big: Ce fichier ne peut pas être attaché car il excède la taille maximale autorisée (%{max_size}) error_attachment_too_big: Ce fichier ne peut pas être attaché car il excède la taille maximale autorisée (%{max_size})
error_session_expired: "Votre session a expiré. Veuillez vous reconnecter."
warning_attachments_not_saved: "%{count} fichier(s) n'ont pas pu être sauvegardés." warning_attachments_not_saved: "%{count} fichier(s) n'ont pas pu être