Merge branch '30349-create-users-build-service' into 'master'
Implement Users::BuildService Closes #30349 See merge request !10675
This commit is contained in:
commit
819b715357
|
@ -60,7 +60,7 @@ class RegistrationsController < Devise::RegistrationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource
|
def resource
|
||||||
@resource ||= Users::CreateService.new(current_user, sign_up_params).build
|
@resource ||= Users::BuildService.new(current_user, sign_up_params).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def devise_mapping
|
def devise_mapping
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
module Users
|
||||||
|
# Service for building a new user.
|
||||||
|
class BuildService < BaseService
|
||||||
|
def initialize(current_user, params = {})
|
||||||
|
@current_user = current_user
|
||||||
|
@params = params.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
raise Gitlab::Access::AccessDeniedError unless can_create_user?
|
||||||
|
|
||||||
|
user = User.new(build_user_params)
|
||||||
|
|
||||||
|
if current_user&.admin?
|
||||||
|
if params[:reset_password]
|
||||||
|
user.generate_reset_token
|
||||||
|
params[:force_random_password] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:force_random_password]
|
||||||
|
random_password = Devise.friendly_token.first(Devise.password_length.min)
|
||||||
|
user.password = user.password_confirmation = random_password
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
identity_attrs = params.slice(:extern_uid, :provider)
|
||||||
|
|
||||||
|
if identity_attrs.any?
|
||||||
|
user.identities.build(identity_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def can_create_user?
|
||||||
|
(current_user.nil? && current_application_settings.signup_enabled?) || current_user&.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Allowed params for creating a user (admins only)
|
||||||
|
def admin_create_params
|
||||||
|
[
|
||||||
|
:access_level,
|
||||||
|
:admin,
|
||||||
|
:avatar,
|
||||||
|
:bio,
|
||||||
|
:can_create_group,
|
||||||
|
:color_scheme_id,
|
||||||
|
:email,
|
||||||
|
:external,
|
||||||
|
:force_random_password,
|
||||||
|
:hide_no_password,
|
||||||
|
:hide_no_ssh_key,
|
||||||
|
:key_id,
|
||||||
|
:linkedin,
|
||||||
|
:name,
|
||||||
|
:password,
|
||||||
|
:password_automatically_set,
|
||||||
|
:password_expires_at,
|
||||||
|
:projects_limit,
|
||||||
|
:remember_me,
|
||||||
|
:skip_confirmation,
|
||||||
|
:skype,
|
||||||
|
:theme_id,
|
||||||
|
:twitter,
|
||||||
|
:username,
|
||||||
|
:website_url
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Allowed params for user signup
|
||||||
|
def signup_params
|
||||||
|
[
|
||||||
|
:email,
|
||||||
|
:email_confirmation,
|
||||||
|
:password_automatically_set,
|
||||||
|
:name,
|
||||||
|
:password,
|
||||||
|
:username
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_user_params
|
||||||
|
if current_user&.admin?
|
||||||
|
user_params = params.slice(*admin_create_params)
|
||||||
|
user_params[:created_by_id] = current_user&.id
|
||||||
|
|
||||||
|
if params[:reset_password]
|
||||||
|
user_params.merge!(force_random_password: true, password_expires_at: nil)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
user_params = params.slice(*signup_params)
|
||||||
|
user_params[:skip_confirmation] = !current_application_settings.send_user_confirmation_email
|
||||||
|
end
|
||||||
|
|
||||||
|
user_params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,34 +6,10 @@ module Users
|
||||||
@params = params.dup
|
@params = params.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
def build
|
|
||||||
raise Gitlab::Access::AccessDeniedError unless can_create_user?
|
|
||||||
|
|
||||||
user = User.new(build_user_params)
|
|
||||||
|
|
||||||
if current_user&.admin?
|
|
||||||
if params[:reset_password]
|
|
||||||
@reset_token = user.generate_reset_token
|
|
||||||
params[:force_random_password] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if params[:force_random_password]
|
|
||||||
random_password = Devise.friendly_token.first(Devise.password_length.min)
|
|
||||||
user.password = user.password_confirmation = random_password
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
identity_attrs = params.slice(:extern_uid, :provider)
|
|
||||||
|
|
||||||
if identity_attrs.any?
|
|
||||||
user.identities.build(identity_attrs)
|
|
||||||
end
|
|
||||||
|
|
||||||
user
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
user = build
|
user = Users::BuildService.new(current_user, params).execute
|
||||||
|
|
||||||
|
@reset_token = user.generate_reset_token if user.recently_sent_password_reset?
|
||||||
|
|
||||||
if user.save
|
if user.save
|
||||||
log_info("User \"#{user.name}\" (#{user.email}) was created")
|
log_info("User \"#{user.name}\" (#{user.email}) was created")
|
||||||
|
@ -43,70 +19,5 @@ module Users
|
||||||
|
|
||||||
user
|
user
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def can_create_user?
|
|
||||||
(current_user.nil? && current_application_settings.signup_enabled?) || current_user&.admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Allowed params for creating a user (admins only)
|
|
||||||
def admin_create_params
|
|
||||||
[
|
|
||||||
:access_level,
|
|
||||||
:admin,
|
|
||||||
:avatar,
|
|
||||||
:bio,
|
|
||||||
:can_create_group,
|
|
||||||
:color_scheme_id,
|
|
||||||
:email,
|
|
||||||
:external,
|
|
||||||
:force_random_password,
|
|
||||||
:password_automatically_set,
|
|
||||||
:hide_no_password,
|
|
||||||
:hide_no_ssh_key,
|
|
||||||
:key_id,
|
|
||||||
:linkedin,
|
|
||||||
:name,
|
|
||||||
:password,
|
|
||||||
:password_expires_at,
|
|
||||||
:projects_limit,
|
|
||||||
:remember_me,
|
|
||||||
:skip_confirmation,
|
|
||||||
:skype,
|
|
||||||
:theme_id,
|
|
||||||
:twitter,
|
|
||||||
:username,
|
|
||||||
:website_url
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Allowed params for user signup
|
|
||||||
def signup_params
|
|
||||||
[
|
|
||||||
:email,
|
|
||||||
:email_confirmation,
|
|
||||||
:password_automatically_set,
|
|
||||||
:name,
|
|
||||||
:password,
|
|
||||||
:username
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_user_params
|
|
||||||
if current_user&.admin?
|
|
||||||
user_params = params.slice(*admin_create_params)
|
|
||||||
user_params[:created_by_id] = current_user&.id
|
|
||||||
|
|
||||||
if params[:reset_password]
|
|
||||||
user_params.merge!(force_random_password: true, password_expires_at: nil)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
user_params = params.slice(*signup_params)
|
|
||||||
user_params[:skip_confirmation] = !current_application_settings.send_user_confirmation_email
|
|
||||||
end
|
|
||||||
|
|
||||||
user_params
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Implement Users::BuildService
|
||||||
|
merge_request: 30349
|
||||||
|
author: George Andrinopoulos
|
|
@ -148,7 +148,7 @@ module Gitlab
|
||||||
|
|
||||||
def build_new_user
|
def build_new_user
|
||||||
user_params = user_attributes.merge(extern_uid: auth_hash.uid, provider: auth_hash.provider, skip_confirmation: true)
|
user_params = user_attributes.merge(extern_uid: auth_hash.uid, provider: auth_hash.provider, skip_confirmation: true)
|
||||||
Users::CreateService.new(nil, user_params).build
|
Users::BuildService.new(nil, user_params).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_attributes
|
def user_attributes
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Users::BuildService, services: true do
|
||||||
|
describe '#execute' do
|
||||||
|
let(:params) do
|
||||||
|
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass' }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an admin user' do
|
||||||
|
let(:admin_user) { create(:admin) }
|
||||||
|
let(:service) { described_class.new(admin_user, params) }
|
||||||
|
|
||||||
|
it 'returns a valid user' do
|
||||||
|
expect(service.execute).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with non admin user' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:service) { described_class.new(user, params) }
|
||||||
|
|
||||||
|
it 'raises AccessDeniedError exception' do
|
||||||
|
expect { service.execute }.to raise_error Gitlab::Access::AccessDeniedError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with nil user' do
|
||||||
|
let(:service) { described_class.new(nil, params) }
|
||||||
|
|
||||||
|
it 'returns a valid user' do
|
||||||
|
expect(service.execute).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when "send_user_confirmation_email" application setting is true' do
|
||||||
|
before do
|
||||||
|
stub_application_setting(send_user_confirmation_email: true, signup_enabled?: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not confirm the user' do
|
||||||
|
expect(service.execute).not_to be_confirmed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when "send_user_confirmation_email" application setting is false' do
|
||||||
|
before do
|
||||||
|
stub_application_setting(send_user_confirmation_email: false, signup_enabled?: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'confirms the user' do
|
||||||
|
expect(service.execute).to be_confirmed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,38 +1,6 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Users::CreateService, services: true do
|
describe Users::CreateService, services: true do
|
||||||
describe '#build' do
|
|
||||||
let(:params) do
|
|
||||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass' }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with an admin user' do
|
|
||||||
let(:admin_user) { create(:admin) }
|
|
||||||
let(:service) { described_class.new(admin_user, params) }
|
|
||||||
|
|
||||||
it 'returns a valid user' do
|
|
||||||
expect(service.build).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with non admin user' do
|
|
||||||
let(:user) { create(:user) }
|
|
||||||
let(:service) { described_class.new(user, params) }
|
|
||||||
|
|
||||||
it 'raises AccessDeniedError exception' do
|
|
||||||
expect { service.build }.to raise_error Gitlab::Access::AccessDeniedError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with nil user' do
|
|
||||||
let(:service) { described_class.new(nil, params) }
|
|
||||||
|
|
||||||
it 'returns a valid user' do
|
|
||||||
expect(service.build).to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#execute' do
|
describe '#execute' do
|
||||||
let(:admin_user) { create(:admin) }
|
let(:admin_user) { create(:admin) }
|
||||||
|
|
||||||
|
@ -185,40 +153,18 @@ describe Users::CreateService, services: true do
|
||||||
end
|
end
|
||||||
let(:service) { described_class.new(nil, params) }
|
let(:service) { described_class.new(nil, params) }
|
||||||
|
|
||||||
context 'when "send_user_confirmation_email" application setting is true' do
|
it 'persists the given attributes' do
|
||||||
before do
|
user = service.execute
|
||||||
current_application_settings = double(:current_application_settings, send_user_confirmation_email: true, signup_enabled?: true)
|
user.reload
|
||||||
allow(service).to receive(:current_application_settings).and_return(current_application_settings)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not confirm the user' do
|
expect(user).to have_attributes(
|
||||||
expect(service.execute).not_to be_confirmed
|
name: params[:name],
|
||||||
end
|
username: params[:username],
|
||||||
end
|
email: params[:email],
|
||||||
|
password: params[:password],
|
||||||
context 'when "send_user_confirmation_email" application setting is false' do
|
created_by_id: nil,
|
||||||
before do
|
admin: false
|
||||||
current_application_settings = double(:current_application_settings, send_user_confirmation_email: false, signup_enabled?: true)
|
)
|
||||||
allow(service).to receive(:current_application_settings).and_return(current_application_settings)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'confirms the user' do
|
|
||||||
expect(service.execute).to be_confirmed
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'persists the given attributes' do
|
|
||||||
user = service.execute
|
|
||||||
user.reload
|
|
||||||
|
|
||||||
expect(user).to have_attributes(
|
|
||||||
name: params[:name],
|
|
||||||
username: params[:username],
|
|
||||||
email: params[:email],
|
|
||||||
password: params[:password],
|
|
||||||
created_by_id: nil,
|
|
||||||
admin: false
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue