commit: d4fe6cd2bfee50cfcde5de5c3f58240552e9c71d
parent: ea6c930c04762bef00b42dad16a17b71b8acc93b
Author: David Celis <me@davidcel.is>
Date: Sun, 9 Apr 2017 09:33:40 -0700
Allow users to update their Account in the API (#1179)
* 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>
Diffstat:
4 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
@@ -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
diff --git a/config/routes.rb b/config/routes.rb
@@ -163,6 +163,7 @@ Rails.application.routes.draw do
collection do
get :relationships
get :verify_credentials
+ patch :update_credentials
get :search
end
diff --git a/docs/Using-the-API/API.md b/docs/Using-the-API/API.md
@@ -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
diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb
@@ -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 }