This repository has been archived by the owner on Dec 21, 2023. It is now read-only.
forked from mastodon/mastodon
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add REST API for creating an account (mastodon#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
- Loading branch information
Showing
18 changed files
with
171 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
class AppSignUpService < BaseService | ||
def call(app, params) | ||
return unless allowed_registrations? | ||
|
||
user_params = params.slice(:email, :password, :agreement) | ||
account_params = params.slice(:username) | ||
user = User.create!(user_params.merge(created_by_application: app, password_confirmation: user_params[:password], account_attributes: account_params)) | ||
|
||
Doorkeeper::AccessToken.create!(application: app, | ||
resource_owner_id: user.id, | ||
scopes: app.scopes, | ||
expires_in: Doorkeeper.configuration.access_token_expires_in, | ||
use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?) | ||
end | ||
|
||
private | ||
|
||
def allowed_registrations? | ||
Setting.open_registrations && !Rails.configuration.x.single_user_mode | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
db/migrate/20181219235220_add_created_by_application_id_to_users.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class AddCreatedByApplicationIdToUsers < ActiveRecord::Migration[5.2] | ||
disable_ddl_transaction! | ||
|
||
def change | ||
add_reference :users, :created_by_application, foreign_key: { to_table: 'oauth_applications', on_delete: :nullify }, index: false | ||
add_index :users, :created_by_application_id, algorithm: :concurrently | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,40 @@ | |
end | ||
end | ||
|
||
describe 'POST #create' do | ||
let(:app) { Fabricate(:application) } | ||
let(:token) { Doorkeeper::AccessToken.find_or_create_for(app, nil, 'read write', nil, false) } | ||
let(:agreement) { nil } | ||
|
||
before do | ||
post :create, params: { username: 'test', password: '12345678', email: '[email protected]', agreement: agreement } | ||
end | ||
|
||
context 'given truthy agreement' do | ||
let(:agreement) { 'true' } | ||
|
||
it 'returns http success' do | ||
expect(response).to have_http_status(200) | ||
end | ||
|
||
it 'returns a new access token as JSON' do | ||
expect(body_as_json[:access_token]).to_not be_blank | ||
end | ||
|
||
it 'creates a user' do | ||
user = User.find_by(email: '[email protected]') | ||
expect(user).to_not be_nil | ||
expect(user.created_by_application_id).to eq app.id | ||
end | ||
end | ||
|
||
context 'given no agreement' do | ||
it 'returns http unprocessable entity' do | ||
expect(response).to have_http_status(422) | ||
end | ||
end | ||
end | ||
|
||
describe 'GET #show' do | ||
let(:scopes) { 'read:accounts' } | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,19 +106,19 @@ | |
end | ||
|
||
it 'should allow a non-blacklisted user to be created' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
|
||
expect(user.valid?).to be_truthy | ||
end | ||
|
||
it 'should not allow a blacklisted user to be created' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
|
||
expect(user.valid?).to be_falsey | ||
end | ||
|
||
it 'should not allow a subdomain blacklisted user to be created' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
|
||
expect(user.valid?).to be_falsey | ||
end | ||
|
@@ -210,17 +210,17 @@ | |
end | ||
|
||
it 'should not allow a user to be created unless they are whitelisted' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
expect(user.valid?).to be_falsey | ||
end | ||
|
||
it 'should allow a user to be created if they are whitelisted' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
expect(user.valid?).to be_truthy | ||
end | ||
|
||
it 'should not allow a user with a whitelisted top domain as subdomain in their email address to be created' do | ||
user = User.new(email: '[email protected]', account: account, password: password) | ||
user = User.new(email: '[email protected]', account: account, password: password, agreement: true) | ||
expect(user.valid?).to be_falsey | ||
end | ||
|
||
|
@@ -242,7 +242,7 @@ | |
|
||
it_behaves_like 'Settings-extended' do | ||
def create! | ||
User.create!(account: Fabricate(:account), email: '[email protected]', password: 'abcd1234') | ||
User.create!(account: Fabricate(:account), email: '[email protected]', password: 'abcd1234', agreement: true) | ||
end | ||
|
||
def fabricate | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
require 'rails_helper' | ||
|
||
RSpec.describe AppSignUpService, type: :service do | ||
let(:app) { Fabricate(:application, scopes: 'read write') } | ||
let(:good_params) { { username: 'alice', password: '12345678', email: '[email protected]', agreement: true } } | ||
|
||
subject { described_class.new } | ||
|
||
describe '#call' do | ||
it 'returns nil when registrations are closed' do | ||
Setting.open_registrations = false | ||
expect(subject.call(app, good_params)).to be_nil | ||
end | ||
|
||
it 'raises an error when params are missing' do | ||
expect { subject.call(app, {}) }.to raise_error ActiveRecord::RecordInvalid | ||
end | ||
|
||
it 'creates an unconfirmed user with access token' do | ||
access_token = subject.call(app, good_params) | ||
expect(access_token).to_not be_nil | ||
user = User.find_by(id: access_token.resource_owner_id) | ||
expect(user).to_not be_nil | ||
expect(user.confirmed?).to be false | ||
end | ||
|
||
it 'creates access token with the app\'s scopes' do | ||
access_token = subject.call(app, good_params) | ||
expect(access_token).to_not be_nil | ||
expect(access_token.scopes.to_s).to eq 'read write' | ||
end | ||
|
||
it 'creates an account' do | ||
access_token = subject.call(app, good_params) | ||
expect(access_token).to_not be_nil | ||
user = User.find_by(id: access_token.resource_owner_id) | ||
expect(user).to_not be_nil | ||
expect(user.account).to_not be_nil | ||
end | ||
end | ||
end |