From 87fc3c572b73211d43d869456fe5e6e26262ff72 Mon Sep 17 00:00:00 2001 From: taitus Date: Mon, 9 Oct 2023 10:04:14 +0200 Subject: [PATCH] Add security secret "last_sign_in" In order to comply with the security measure for the ENS: "[op.acc.5.r5.2] The user shall be informed of the last access made with his identity". We have added a new secret to display the last access made to the user on the "My account" page. --- .../account/sign_in_info_component.html.erb | 4 +++ .../account/sign_in_info_component.rb | 11 ++++++++ app/views/account/show.html.erb | 2 ++ config/locales/en/general.yml | 1 + config/locales/es/general.yml | 1 + config/secrets.yml.example | 14 +++++++--- .../account/sign_in_info_component_spec.rb | 26 +++++++++++++++++++ 7 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 app/components/account/sign_in_info_component.html.erb create mode 100644 app/components/account/sign_in_info_component.rb create mode 100644 spec/components/account/sign_in_info_component_spec.rb diff --git a/app/components/account/sign_in_info_component.html.erb b/app/components/account/sign_in_info_component.html.erb new file mode 100644 index 000000000..a794ab722 --- /dev/null +++ b/app/components/account/sign_in_info_component.html.erb @@ -0,0 +1,4 @@ +
+ <%= t("account.show.last_sign_in", last_sign_in_at: I18n.l(account.last_sign_in_at, format: :long), + last_sign_in_ip: account.last_sign_in_ip) %> +
diff --git a/app/components/account/sign_in_info_component.rb b/app/components/account/sign_in_info_component.rb new file mode 100644 index 000000000..aaa628129 --- /dev/null +++ b/app/components/account/sign_in_info_component.rb @@ -0,0 +1,11 @@ +class Account::SignInInfoComponent < ApplicationComponent + attr_reader :account + + def initialize(account) + @account = account + end + + def render? + Tenant.current_secrets.dig(:security, :last_sign_in) + end +end diff --git a/app/views/account/show.html.erb b/app/views/account/show.html.erb index 9623976de..8201e9471 100644 --- a/app/views/account/show.html.erb +++ b/app/views/account/show.html.erb @@ -10,6 +10,8 @@

<%= t("account.show.title") %>

+ <%= render Account::SignInInfoComponent.new(@account) %> + <%= form_for @account, as: :account, url: account_path do |f| %> <%= render "shared/errors", resource: @account %> diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 0be47b5a9..d26c065d8 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -1,6 +1,7 @@ en: account: show: + last_sign_in: "Last login: %{last_sign_in_at} from IP %{last_sign_in_ip}" change_credentials_link: Change my login details erase_account_link: Erase my account finish_verification: Complete verification diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index e40c5b43d..aefb5e56c 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -1,6 +1,7 @@ es: account: show: + last_sign_in: "Último acceso efectuado: %{last_sign_in_at} desde la IP %{last_sign_in_ip}" change_credentials_link: Cambiar mis datos de acceso erase_account_link: Darme de baja finish_verification: Finalizar verificación diff --git a/config/secrets.yml.example b/config/secrets.yml.example index d04c93778..a5aa854c4 100644 --- a/config/secrets.yml.example +++ b/config/secrets.yml.example @@ -19,6 +19,8 @@ development: http_basic_username: "dev" http_basic_password: "pass" multitenancy: false + security: + last_sign_in: false secret_key_base: 56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4 <<: *maps @@ -50,6 +52,8 @@ staging: managers_url: "" managers_application_key: "" multitenancy: false + security: + last_sign_in: false tenants: # If you've enabled multitenancy, you can overwrite secrets for a # specific tenant with: @@ -58,7 +62,7 @@ staging: # secret_key: my_secret_value # # Currently you can overwrite SMTP, SMS, manager, microsoft API, - # HTTP basic, twitter, facebook, google and wordpress settings. + # HTTP basic, twitter, facebook, google, wordpress and security settings. <<: *maps <<: *apis @@ -86,6 +90,8 @@ preproduction: managers_url: "" managers_application_key: "" multitenancy: false + security: + last_sign_in: false tenants: # If you've enabled multitenancy, you can overwrite secrets for a # specific tenant with: @@ -94,7 +100,7 @@ preproduction: # secret_key: my_secret_value # # Currently you can overwrite SMTP, SMS, manager, microsoft API, - # HTTP basic, twitter, facebook, google and wordpress settings. + # HTTP basic, twitter, facebook, google, wordpress and security settings. twitter_key: "" twitter_secret: "" facebook_key: "" @@ -127,6 +133,8 @@ production: managers_url: "" managers_application_key: "" multitenancy: false + security: + last_sign_in: false tenants: # If you've enabled multitenancy, you can overwrite secrets for a # specific tenant with: @@ -135,7 +143,7 @@ production: # secret_key: my_secret_value # # Currently you can overwrite SMTP, SMS, manager, microsoft API, - # HTTP basic, twitter, facebook, google and wordpress settings. + # HTTP basic, twitter, facebook, google, wordpress and security settings. twitter_key: "" twitter_secret: "" facebook_key: "" diff --git a/spec/components/account/sign_in_info_component_spec.rb b/spec/components/account/sign_in_info_component_spec.rb new file mode 100644 index 000000000..0e100d2d3 --- /dev/null +++ b/spec/components/account/sign_in_info_component_spec.rb @@ -0,0 +1,26 @@ +require "rails_helper" + +describe Account::SignInInfoComponent do + let(:account) { create(:user, last_sign_in_at: Date.current, last_sign_in_ip: "1.2.3.4") } + + context "Security secret for render last sign in is enabled" do + it "shows a sign in info" do + allow(Rails.application).to receive(:secrets).and_return(ActiveSupport::OrderedOptions.new.merge( + security: { last_sign_in: true } + )) + + render_inline Account::SignInInfoComponent.new(account) + + expect(page).to have_content "Last login:" + expect(page).to have_content "from IP" + end + end + + context "Security secret for render last sign in is disabled" do + it "does not show sign in info" do + render_inline Account::SignInInfoComponent.new(account) + + expect(page).not_to be_rendered + end + end +end