]> source.dussan.org Git - redmine.git/commitdiff
Enables API access to /my/account for updating user account data (#31399).
authorGo MAEDA <maeda@farend.jp>
Sun, 16 Jun 2019 09:34:49 +0000 (09:34 +0000)
committerGo MAEDA <maeda@farend.jp>
Sun, 16 Jun 2019 09:34:49 +0000 (09:34 +0000)
Patch by Jens Krämer.

git-svn-id: http://svn.redmine.org/redmine/trunk@18257 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/my_controller.rb
app/views/my/account.api.rsb [new file with mode: 0644]
app/views/my/account.html.erb
config/routes.rb
test/functional/my_controller_test.rb
test/integration/api_test/my_test.rb [new file with mode: 0644]
test/integration/routing/my_test.rb
test/integration/sudo_mode_test.rb

index 58763f0c3622c3b70952902e749aee3112e61faa..606fd5cb343effa4a9935d6666bbcd737d56f359 100644 (file)
@@ -23,7 +23,9 @@ class MyController < ApplicationController
   # let user change user's password when user has to
   skip_before_action :check_password_change, :only => :password
 
-  require_sudo_mode :account, only: :post
+  accept_api_auth :account
+
+  require_sudo_mode :account, only: :put
   require_sudo_mode :reset_rss_key, :reset_api_key, :show_api_key, :destroy
 
   helper :issues
@@ -49,15 +51,25 @@ class MyController < ApplicationController
   def account
     @user = User.current
     @pref = @user.pref
-    if request.post?
+    if request.put?
       @user.safe_attributes = params[:user]
       @user.pref.safe_attributes = params[:pref]
       if @user.save
         @user.pref.save
         set_language_if_valid @user.language
-        flash[:notice] = l(:notice_account_updated)
-        redirect_to my_account_path
+        respond_to do |format|
+          format.html {
+            flash[:notice] = l(:notice_account_updated)
+            redirect_to my_account_path
+          }
+          format.api  { render_api_ok }
+        end
         return
+      else
+        respond_to do |format|
+          format.html { render :action => :account }
+          format.api  { render_validation_errors(@user) }
+        end
       end
     end
   end
diff --git a/app/views/my/account.api.rsb b/app/views/my/account.api.rsb
new file mode 100644 (file)
index 0000000..c1cac2b
--- /dev/null
@@ -0,0 +1,13 @@
+api.user do
+  api.id         @user.id
+  api.login      @user.login
+  api.admin      @user.admin?
+  api.firstname  @user.firstname
+  api.lastname   @user.lastname
+  api.mail       @user.mail
+  api.created_on @user.created_on
+  api.last_login_on @user.last_login_on
+  api.api_key    @user.api_key
+
+  render_api_custom_values @user.visible_custom_field_values, api
+end
index 63402c977ea1111074d9c5384f9adc4e409857a9..87b2d7cbdd6b71edd7972b6d49cd1be171e4f636 100644 (file)
@@ -14,7 +14,7 @@
 <%= labelled_form_for :user, @user,
                      :url => { :action => "account" },
                      :html => { :id => 'my_account_form',
-                                :method => :post, :multipart => true } do |f| %>
+                                :method => :put, :multipart => true } do |f| %>
 <div class="splitcontent">
 <div class="splitcontentleft">
 <fieldset class="box tabular">
index 5ac2575c3a86010833507ec9a28326b0dc383938..c6d172ee4aa02116939a59569206c2e6b5afb1e0 100644 (file)
@@ -72,7 +72,7 @@ Rails.application.routes.draw do
   match '/imports/:id/mapping', :to => 'imports#mapping', :via => [:get, :post], :as => 'import_mapping'
   match '/imports/:id/run', :to => 'imports#run', :via => [:get, :post], :as => 'import_run'
 
-  match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post]
+  match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :put]
   match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post]
   match 'my/page', :controller => 'my', :action => 'page', :via => :get
   post 'my/page', :to => 'my#update_page'
index 1295767f25f237ef1d3884dcfb4afedd8a26ffac..069cfdc336d162ba4abc12250bb8b373bb55483e 100644 (file)
@@ -382,7 +382,7 @@ class MyControllerTest < Redmine::ControllerTest
   end
 
   def test_update_account
-    post :account, :params => {
+    put :account, :params => {
         :user => {
           :firstname => "Joe",
           :login => "root",
@@ -407,7 +407,7 @@ class MyControllerTest < Redmine::ControllerTest
 
   def test_update_account_should_send_security_notification
     ActionMailer::Base.deliveries.clear
-    post :account, :params => {
+    put :account, :params => {
         :user => {
           :mail => 'foobar@example.com'
 
diff --git a/test/integration/api_test/my_test.rb b/test/integration/api_test/my_test.rb
new file mode 100644 (file)
index 0000000..92a54f3
--- /dev/null
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2017  Jean-Philippe Lang
+#
+# 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.
+
+require File.expand_path('../../../test_helper', __FILE__)
+
+class Redmine::ApiTest::MyTest < Redmine::ApiTest::Base
+  fixtures :users, :email_addresses, :members, :member_roles, :roles, :projects
+
+  test "GET /my/account.json should return user" do
+    assert Setting.rest_api_enabled?
+    get '/my/account.json', :headers => credentials('dlopper', 'foo')
+
+    assert_response :success
+    assert_equal 'application/json', response.content_type
+    json = ActiveSupport::JSON.decode(response.body)
+    assert json.key?('user')
+    assert_equal 'dlopper', json['user']['login']
+  end
+
+  test "PUT /my/account.xml with valid parameters should update the user" do
+    put '/my/account.xml',
+      :params => {
+        :user => {
+          :firstname => 'Dave', :lastname => 'Renamed',
+          :mail => 'dave@somenet.foo'
+        }
+      },
+      :headers => credentials('dlopper', 'foo')
+    assert_response :no_content
+    assert_equal '', @response.body
+
+    assert user = User.find_by_lastname('Renamed')
+    assert_equal 'Dave', user.firstname
+    assert_equal 'Renamed', user.lastname
+    assert_equal 'dave@somenet.foo', user.mail
+    refute user.admin?
+  end
+
+  test "PUT /my/account.json with valid parameters should update the user" do
+    put '/my/account.xml',
+      :params => {
+        :user => {
+          :firstname => 'Dave', :lastname => 'Renamed',
+          :mail => 'dave@somenet.foo'
+        }
+      },
+      :headers => credentials('dlopper', 'foo')
+    assert_response :no_content
+    assert_equal '', @response.body
+
+    assert user = User.find_by_lastname('Renamed')
+    assert_equal 'Dave', user.firstname
+    assert_equal 'Renamed', user.lastname
+    assert_equal 'dave@somenet.foo', user.mail
+    refute user.admin?
+
+  end
+
+  test "PUT /my/account.xml with invalid parameters" do
+    put '/my/account.xml',
+      :params => {
+        :user => {
+          :login => 'dlopper', :firstname => '', :lastname => 'Lastname'
+        }
+      },
+      :headers => credentials('dlopper', 'foo')
+
+    assert_response :unprocessable_entity
+    assert_equal 'application/xml', @response.content_type
+    assert_select 'errors error', :text => "First name cannot be blank"
+  end
+
+  test "PUT /my/account.json with invalid parameters" do
+    put '/my/account.json',
+      :params => {
+        :user => {
+          :login => 'dlopper', :firstname => '', :lastname => 'Lastname'
+        }
+      },
+      :headers => credentials('dlopper', 'foo')
+
+    assert_response :unprocessable_entity
+    assert_equal 'application/json', @response.content_type
+    json = ActiveSupport::JSON.decode(response.body)
+    assert_kind_of Hash, json
+    assert json.has_key?('errors')
+    assert_kind_of Array, json['errors']
+  end
+end
+
index ce98f70b5ae8d947e00ed55f033fbc5a676a4c2f..8b70ae7e4f4b7298ff5cb554b7848fb967043be1 100644 (file)
@@ -22,7 +22,7 @@ require File.expand_path('../../../test_helper', __FILE__)
 class RoutingMyTest < Redmine::RoutingTest
   def test_my
     should_route 'GET /my/account' => 'my#account'
-    should_route 'POST /my/account' => 'my#account'
+    should_route 'PUT /my/account' => 'my#account'
 
     should_route 'GET /my/account/destroy' => 'my#destroy'
     should_route 'POST /my/account/destroy' => 'my#destroy'
index b7d9cb5d77145dcb164ebe65b54db396f46e7224..a2ff7cd09c679661305cc091fa8fc20e295de5b0 100644 (file)
@@ -149,7 +149,7 @@ class SudoModeTest < Redmine::IntegrationTest
     expire_sudo_mode!
     get '/my/account'
     assert_response :success
-    post '/my/account', :params => {user: { mail: 'newmail@test.com' }}
+    put '/my/account', :params => {user: { mail: 'newmail@test.com' }}
     assert_response :success
     assert_select 'h2', 'Confirm your password to continue'
     assert_select 'form[action="/my/account"]'
@@ -157,7 +157,7 @@ class SudoModeTest < Redmine::IntegrationTest
     assert_select '#flash_error', 0
 
     # wrong password
-    post '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'wrong'}
+    put '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'wrong'}
     assert_response :success
     assert_select 'h2', 'Confirm your password to continue'
     assert_select 'form[action="/my/account"]'
@@ -165,12 +165,12 @@ class SudoModeTest < Redmine::IntegrationTest
     assert_select '#flash_error'
 
     # correct password
-    post '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'jsmith'}
+    put '/my/account', :params => {user: { mail: 'newmail@test.com' }, sudo_password: 'jsmith'}
     assert_redirected_to '/my/account'
     assert_equal 'newmail@test.com', User.find_by_login('jsmith').mail
 
     # sudo mode should now be active and not require password again
-    post '/my/account', :params => {user: { mail: 'even.newer.mail@test.com' }}
+    put '/my/account', :params => {user: { mail: 'even.newer.mail@test.com' }}
     assert_redirected_to '/my/account'
     assert_equal 'even.newer.mail@test.com', User.find_by_login('jsmith').mail
   end