about summary refs log tree commit diff
path: root/app/controllers
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2018-12-24 19:12:38 +0100
committerGitHub <noreply@github.com>2018-12-24 19:12:38 +0100
commit5d2fc6de321ac556ded72e5a8fa9fcf47d172e16 (patch)
tree10dea7eebcb32c29c202da5e8bd009d67b4258f7 /app/controllers
parentacf9358c5267ef94373dec9c370b83b33ada75a3 (diff)
Add REST API for creating an account (#9572)
* Add REST API for creating an account

The method is available to apps with a token obtained via the client
credentials grant. It creates a user and account records, as well as
an access token for the app that initiated the request. The user is
unconfirmed, and an e-mail is sent as usual.

The method returns the access token, which the app should save for
later. The REST API is not available to users with unconfirmed
accounts, so the app must be smart to wait for the user to click a
link in their e-mail inbox.

The method is rate-limited by IP to 5 requests per 30 minutes.

* Redirect users back to app from confirmation if they were created with an app

* Add tests

* Return 403 on the method if registrations are not open

* Require agreement param to be true in the API when creating an account
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/api/base_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts_controller.rb26
-rw-r--r--app/controllers/auth/confirmations_controller.rb10
-rw-r--r--app/controllers/auth/registrations_controller.rb1
4 files changed, 34 insertions, 5 deletions
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index ac8de5fc0..2bf8e82db 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -68,7 +68,7 @@ class Api::BaseController < ApplicationController
   end
 
   def require_user!
-    if current_user && !current_user.disabled?
+    if current_user && !current_user.disabled? && current_user.confirmed?
       set_user_activity
     elsif current_user
       render json: { error: 'Your login is currently disabled' }, status: 403
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index f711c4676..6e4084c4e 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -1,14 +1,16 @@
 # frozen_string_literal: true
 
 class Api::V1::AccountsController < Api::BaseController
-  before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :block, :unblock, :mute, :unmute]
   before_action -> { doorkeeper_authorize! :follow, :'write:follows' }, only: [:follow, :unfollow]
   before_action -> { doorkeeper_authorize! :follow, :'write:mutes' }, only: [:mute, :unmute]
   before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, only: [:block, :unblock]
+  before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
 
-  before_action :require_user!, except: [:show]
-  before_action :set_account
+  before_action :require_user!, except: [:show, :create]
+  before_action :set_account, except: [:create]
   before_action :check_account_suspension, only: [:show]
+  before_action :check_enabled_registrations, only: [:create]
 
   respond_to :json
 
@@ -16,6 +18,16 @@ class Api::V1::AccountsController < Api::BaseController
     render json: @account, serializer: REST::AccountSerializer
   end
 
+  def create
+    token    = AppSignUpService.new.call(doorkeeper_token.application, account_params)
+    response = Doorkeeper::OAuth::TokenResponse.new(token)
+
+    headers.merge!(response.headers)
+
+    self.response_body = Oj.dump(response.body)
+    self.status        = response.status
+  end
+
   def follow
     FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs))
 
@@ -62,4 +74,12 @@ class Api::V1::AccountsController < Api::BaseController
   def check_account_suspension
     gone if @account.suspended?
   end
+
+  def account_params
+    params.permit(:username, :email, :password, :agreement)
+  end
+
+  def check_enabled_registrations
+    forbidden if single_user_mode? || !Setting.open_registrations
+  end
 end
diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb
index 7af9cbe81..c28c7471c 100644
--- a/app/controllers/auth/confirmations_controller.rb
+++ b/app/controllers/auth/confirmations_controller.rb
@@ -6,9 +6,9 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
   before_action :set_body_classes
   before_action :set_user, only: [:finish_signup]
 
-  # GET/PATCH /users/:id/finish_signup
   def finish_signup
     return unless request.patch? && params[:user]
+
     if @user.update(user_params)
       @user.skip_reconfirmation!
       bypass_sign_in(@user)
@@ -31,4 +31,12 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
   def user_params
     params.require(:user).permit(:email)
   end
+
+  def after_confirmation_path_for(_resource_name, user)
+    if user.created_by_application && truthy_param?(:redirect_to_app)
+      user.created_by_application.redirect_uri
+    else
+      super
+    end
+  end
 end
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 088832be3..f2a832542 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -26,6 +26,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 
     resource.locale      = I18n.locale
     resource.invite_code = params[:invite_code] if resource.invite_code.blank?
+    resource.agreement   = true
 
     resource.build_account if resource.account.nil?
   end