Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app/controllers/my_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class MyController < ApplicationController
:password,
:change_password,
:password_confirmation_dialog,
:security,
:notifications,
:non_working_times,
:working_hours,
Expand All @@ -68,6 +69,7 @@ class MyController < ApplicationController
menu_item :locale, only: [:locale]
menu_item :interface, only: [:interface]
menu_item :password, only: [:password]
menu_item :security, only: [:security]
menu_item :notifications, only: [:notifications]
menu_item :working_hours, only: %i[working_hours non_working_times]

Expand Down Expand Up @@ -101,6 +103,10 @@ def update_date_alerts

def interface; end

def security
@username = @user.login
end

# Manage user's password
def password
@username = @user.login
Expand All @@ -110,7 +116,7 @@ def password
# When making changes here, also check AccountController.change_password
def change_password
change_password_flow(user: @user, params:, update_legacy: false) do
redirect_to action: "password"
redirect_to action: "security"
Comment thread
HDinger marked this conversation as resolved.
end
end

Expand Down
75 changes: 75 additions & 0 deletions app/forms/my/password_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

class My::PasswordForm < ApplicationForm

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Can we have inline validation or show a meaningful error message:

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will exclude that into a separate ticket as it requires some more work and the freeze is coming ❄️

def initialize(user:, back_url: nil)
super()
@user = user
@back_url = back_url
end

form do |f|
f.fieldset_group(title: helpers.t(:label_change_password),
mt: 2) do |fg|
fg.hidden(name: :back_url, value: @back_url) if @back_url.present?
fg.hidden(name: :password_change_user, value: @user.login)

fg.text_field(
name: :password,
type: :password,
input_width: :medium,
label: User.human_attribute_name(:current_password),
required: true,
autocomplete: "current-password"
)

fg.text_field(
name: :new_password,
type: :password,
input_width: :medium,
label: User.human_attribute_name(:new_password),
required: true,
autocomplete: "new-password",
data: { "password-requirements-target": "passwordInput" }
)

fg.text_field(
name: :new_password_confirmation,
type: :password,
input_width: :medium,
label: User.human_attribute_name(:password_confirmation),
required: true,
autocomplete: "new-password"
)

fg.submit(name: :submit, label: helpers.t(:button_save), scheme: :primary)
end
end
end
1 change: 1 addition & 0 deletions app/forms/my/password_form/new_password_caption.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= helpers.render_password_complexity_hint %>
12 changes: 0 additions & 12 deletions app/helpers/password_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ def password_confirmation_form_for(record, options = {}, &)
form_for(record, options, &)
end

##
# Decorate the form_tag helper with the request-for-confirmation directive
# when the user is internally authenticated.
def password_confirmation_form_tag(url_for_options = {}, options = {}, &)
if password_confirmation_required?
options[:data] ||= {}
options[:data] = password_confirmation_data_attribute(options[:data])
end

form_tag(url_for_options, options, &)
end

def password_confirmation_data_attribute(with_data = {})
controller = with_data.fetch(:controller, "")

Expand Down
16 changes: 16 additions & 0 deletions app/views/my/_password.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<% if @user.change_password_allowed? %>
<%= error_messages_for "user" %>
<%=
settings_primer_form_with(
url: { action: :change_password },
method: :post,
autocomplete: "off",
data: {
turbo: false,
controller: "password-requirements"
}
) do |form|
render(My::PasswordForm.new(form, user: @user, back_url: params[:back_url]))
end
%>
<% end %>
89 changes: 0 additions & 89 deletions app/views/my/_password_form_fields.html.erb

This file was deleted.

20 changes: 4 additions & 16 deletions app/views/my/password.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,13 @@ See COPYRIGHT and LICENSE files for more details.

<%=
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title(test_selector: "change_password_header_title") { t(:button_change_password) }
header.with_title(test_selector: "change_password_header_title") { t(:label_change_password) }
header.with_breadcrumbs(
[{ href: my_account_path, text: t(:label_my_account) },
t(:button_change_password)]
{ href: my_security_path, text: t(:label_my_security) },
t(:label_change_password)]
)
end
%>

<%= error_messages_for "user" %>
<%= styled_form_tag(
{ action: :change_password },
{ autocomplete: "off", class: "form -wide-labels" }
) do %>
<%= back_url_hidden_field_tag %>
<%= hidden_field_tag :password_change_user, @user.login %>
<section class="form--section">
<%= render partial: "my/password_form_fields",
locals: { show_user_name: !!(defined? show_user_name) ? show_user_name : nil,
input_size: :middle } %>
</section>
<%= styled_button_tag t(:button_save), class: "-primary -with-icon icon-checkmark" %>
<% end %>
<%= render "my/password" %>
43 changes: 43 additions & 0 deletions app/views/my/security.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) the OpenProject GmbH

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.

OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

See COPYRIGHT and LICENSE files for more details.

++#%>
<% html_title t(:label_my_account), t(:label_my_security) %>

<%=
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { t(:label_my_security) }
header.with_breadcrumbs(
[{ href: my_account_path, text: t(:label_my_account) },
t(:label_my_security)]
)
end
%>

<%= render "my/password" %>

<%= call_hook(:view_my_security_2fa_section, user: @user, cookies:) %>
9 changes: 4 additions & 5 deletions config/initializers/menus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,10 @@
{ controller: "/my", action: "interface" },
caption: :label_interface,
icon: "device-desktop"
menu.push :password,
{ controller: "/my", action: "password" },
caption: :button_change_password,
if: ->(_) { User.current.change_password_allowed? },
icon: "lock"
menu.push :security,
{ controller: "/my", action: "security" },
caption: :label_my_security,
icon: "shield-lock"
menu.push :access_tokens,
{ controller: "/my/access_tokens", action: "index" },
caption: I18n.t("my_account.access_tokens.access_tokens"),
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4043,6 +4043,7 @@
label_send_invitation: Send invitation
label_calculated_value: "Calculated value"
label_change_parent: "Change parent"
label_change_password: "Change password"

Check failure on line 4046 in config/locales/en.yml

View workflow job for this annotation

GitHub Actions / yamllint

[yamllint] config/locales/en.yml#L4046

[error] wrong ordering of key "label_change_password" in mapping (key-ordering)
Raw output
config/locales/en.yml:4046:3: [error] wrong ordering of key "label_change_password" in mapping (key-ordering)
label_change_plural: "Changes"
label_change_properties: "Change properties"
label_change_status: "Change status"
Expand Down Expand Up @@ -4330,6 +4331,7 @@
label_my_account_data: "My account data"
label_my_avatar: "My avatar"
label_my_queries: "My custom queries"
label_my_security: "Security"

Check failure on line 4334 in config/locales/en.yml

View workflow job for this annotation

GitHub Actions / yamllint

[yamllint] config/locales/en.yml#L4334

[error] wrong ordering of key "label_my_security" in mapping (key-ordering)
Raw output
config/locales/en.yml:4334:3: [error] wrong ordering of key "label_my_security" in mapping (key-ordering)
label_name: "Name"
label_never: "Never"
label_new: "New"
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@
end

scope controller: "my" do
get "/my/security", action: "security", as: "my_security"
get "/my/password", action: "password"
get "/my/password_confirmation_dialog", action: "password_confirmation_dialog"
post "/my/change_password", action: "change_password"
Expand Down
11 changes: 0 additions & 11 deletions frontend/src/global_styles/content/modules/_2fa.sass
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,6 @@
margin-bottom: 10px


Comment thread
HDinger marked this conversation as resolved.
// Add some paddings to action links
.mobile-otp--two-factor-device-row td.buttons
form:not(:last-child):after
content: ","
padding: 0 1px

.mobile-otp--two-factor-device-row.-default
.mobile-otp--device-text
font-weight: var(--base-text-weight-bold)


// Backup codes display
.two-factor-authentication--backup-codes
// Avoid stretching the columns too much
Expand Down
Loading
Loading