]> cat aescling's git repositories - mastodon.git/commitdiff
Allow users to update their Account in the API (#1179)
authorDavid Celis <me@davidcel.is>
Sun, 9 Apr 2017 16:33:40 +0000 (09:33 -0700)
committerEugen <eugen@zeonfederated.com>
Sun, 9 Apr 2017 16:33:40 +0000 (18:33 +0200)
* Allow users to update their Account in the API

It would be nice for API clients to be able to allow users to update
their accounts without having to wrap Mastodon in a web view. This patch
adds an API endpoint to let users submit a PATCH for their account.

Signed-off-by: David Celis <me@davidcel.is>
* Add /api/v1/accounts/update_credentials to the API docs

Signed-off-by: David Celis <me@davidcel.is>
app/controllers/api/v1/accounts_controller.rb
config/routes.rb
docs/Using-the-API/API.md
spec/controllers/api/v1/accounts_controller_spec.rb

index 454873116a289eee8bfb312b85b7370695135b2a..bb7cda0355c5390ad236adf883cfb853355417f1 100644 (file)
@@ -1,10 +1,11 @@
 # frozen_string_literal: true
 
 class Api::V1::AccountsController < ApiController
-  before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
+  before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute, :update_credentials]
   before_action -> { doorkeeper_authorize! :follow }, only: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
+  before_action -> { doorkeeper_authorize! :write }, only: [:update_credentials]
   before_action :require_user!, except: [:show, :following, :followers, :statuses]
-  before_action :set_account, except: [:verify_credentials, :suggestions, :search]
+  before_action :set_account, except: [:verify_credentials, :update_credentials, :suggestions, :search]
 
   respond_to :json
 
@@ -15,6 +16,14 @@ class Api::V1::AccountsController < ApiController
     render action: :show
   end
 
+  def update_credentials
+    @account = current_user.account
+
+    @account.update_attributes!(account_params)
+
+    render action: :show
+  end
+
   def following
     results   = Follow.where(account: @account).paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
     accounts  = Account.where(id: results.map(&:target_account_id)).map { |a| [a.id, a] }.to_h
@@ -135,4 +144,8 @@ class Api::V1::AccountsController < ApiController
   def statuses_pagination_params(core_params)
     params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
   end
+
+  def account_params
+    @account_params ||= params.permit(:display_name, :note, :avatar, :header)
+  end
 end
index b0a13aa78a58b1f62fe5563883992f6889bb11e2..9adcdb862b72f13250db86ab38ac77cbbe62d33d 100644 (file)
@@ -163,6 +163,7 @@ Rails.application.routes.draw do
         collection do
           get :relationships
           get :verify_credentials
+          patch :update_credentials
           get :search
         end
 
index 8a648b6d098bb408ffa682d77c198296b2205782..2b7081470d44554b640ea27a305d87bd4889a911 100644 (file)
@@ -85,6 +85,17 @@ Returns an [Account](#account).
 
 Returns the authenticated user's [Account](#account).
 
+#### Updating the current user:
+
+    PATCH /api/v1/accounts/update_credentials
+
+Form data:
+
+- `display_name`: The name to display in the user's profile
+- `note`: A new biography for the user
+- `avatar`: A base64 encoded image to display as the user's avatar (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
+- `header`: A base64 encoded image to display as the user's header image (e.g. `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUoAAADrCAYAAAA...`)
+
 #### Getting an account's followers:
 
     GET /api/v1/accounts/:id/followers
index 5d36b01591d3e29e6ca2b5571c16344e0109299f..98c87bf16fcf7f6c29da545a67642f125ebda0ee 100644 (file)
@@ -24,6 +24,39 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
     end
   end
 
+  describe 'PATCH #update_credentials' do
+    it 'returns http success' do
+      expect(user.account.avatar).not_to exist
+      expect(user.account.header).not_to exist
+
+      avatar = File.read(Rails.root.join('app', 'assets', 'images', 'logo.png'))
+      header = File.read(Rails.root.join('app', 'assets', 'images', 'mastodon-getting-started.png'))
+      params = {
+        display_name: "Alice Isn't Dead",
+        note: "Hi!\n\nToot toot!",
+        avatar: "data:image/png;base64,#{Base64.encode64(avatar)}",
+        header: "data:image/png;base64,#{Base64.encode64(header)}"
+      }
+      patch :update_credentials, params: params
+      expect(response).to have_http_status(:success)
+
+      user.reload
+
+      expect(user.account.display_name).to eq("Alice Isn't Dead")
+      expect(user.account.note).to eq("Hi!\n\nToot toot!")
+      expect(user.account.avatar).to exist
+      expect(user.account.header).to exist
+    end
+
+    it 'respects Account validations' do
+      note = "This is too long. " * 10
+      error = { error: 'The account could not be updated: Note is too long (maximum is 160 characters)' }.to_json
+      patch :update_credentials, params: { note: note }
+      expect(response).to have_http_status(:unprocessable_entity)
+      expect(response.body).to eq(error)
+    end
+  end
+
   describe 'GET #statuses' do
     it 'returns http success' do
       get :statuses, params: { id: user.account.id }