1# frozen_string_literal: true
2
3module Users
4  class BuildService < BaseService
5    delegate :user_default_internal_regex_enabled?,
6             :user_default_internal_regex_instance,
7             to: :'Gitlab::CurrentSettings.current_application_settings'
8
9    def initialize(current_user, params = {})
10      @current_user = current_user
11      @params = params.dup
12      @identity_params = params.slice(*identity_attributes)
13    end
14
15    def execute
16      build_user
17      build_identity
18      update_canonical_email
19
20      user
21    end
22
23    private
24
25    attr_reader :identity_params, :user_params, :user
26
27    def identity_attributes
28      [:extern_uid, :provider]
29    end
30
31    def build_user
32      if admin?
33        admin_build_user
34      else
35        standard_build_user
36      end
37    end
38
39    def admin?
40      return false unless current_user
41
42      current_user.admin?
43    end
44
45    def admin_build_user
46      build_user_params_for_admin
47      init_user
48      password_reset
49    end
50
51    def standard_build_user
52      # current_user non admin or nil
53      validate_access!
54      build_user_params_for_non_admin
55      init_user
56    end
57
58    def build_user_params_for_admin
59      @user_params = params.slice(*admin_create_params)
60      @user_params.merge!(force_random_password: true, password_expires_at: nil) if params[:reset_password]
61    end
62
63    def init_user
64      assign_common_user_params
65
66      @user = User.new(user_params)
67    end
68
69    def assign_common_user_params
70      @user_params[:created_by_id] = current_user&.id
71      @user_params[:external] = user_external? if set_external_param?
72
73      @user_params.delete(:user_type) unless project_bot?
74    end
75
76    def set_external_param?
77      user_default_internal_regex_enabled? && !user_params.key?(:external)
78    end
79
80    def user_external?
81      user_default_internal_regex_instance.match(params[:email]).nil?
82    end
83
84    def project_bot?
85      user_params[:user_type]&.to_sym == :project_bot
86    end
87
88    def password_reset
89      @reset_token = user.generate_reset_token if params[:reset_password]
90
91      if user_params[:force_random_password]
92        random_password = User.random_password
93        @user.password = user.password_confirmation = random_password
94      end
95    end
96
97    def validate_access!
98      return if can_create_user?
99
100      raise Gitlab::Access::AccessDeniedError
101    end
102
103    def can_create_user?
104      current_user.nil? && Gitlab::CurrentSettings.allow_signup?
105    end
106
107    def build_user_params_for_non_admin
108      @user_params = params.slice(*signup_params)
109      @user_params[:skip_confirmation] = skip_user_confirmation_email_from_setting if assign_skip_confirmation_from_settings?
110      @user_params[:name] = fallback_name if use_fallback_name?
111    end
112
113    def assign_skip_confirmation_from_settings?
114      user_params[:skip_confirmation].nil?
115    end
116
117    def skip_user_confirmation_email_from_setting
118      !Gitlab::CurrentSettings.send_user_confirmation_email
119    end
120
121    def use_fallback_name?
122      user_params[:name].blank? && fallback_name.present?
123    end
124
125    def fallback_name
126      "#{user_params[:first_name]} #{user_params[:last_name]}"
127    end
128
129    def build_identity
130      return if identity_params.empty?
131
132      user.identities.build(identity_params)
133    end
134
135    def update_canonical_email
136      Users::UpdateCanonicalEmailService.new(user: user).execute
137    end
138
139    # Allowed params for creating a user (admins only)
140    def admin_create_params
141      [
142        :access_level,
143        :admin,
144        :avatar,
145        :bio,
146        :can_create_group,
147        :color_scheme_id,
148        :email,
149        :external,
150        :force_random_password,
151        :hide_no_password,
152        :hide_no_ssh_key,
153        :linkedin,
154        :name,
155        :password,
156        :password_automatically_set,
157        :password_expires_at,
158        :projects_limit,
159        :remember_me,
160        :skip_confirmation,
161        :skype,
162        :theme_id,
163        :twitter,
164        :username,
165        :website_url,
166        :private_profile,
167        :organization,
168        :location,
169        :public_email,
170        :user_type,
171        :note,
172        :view_diffs_file_by_file
173      ]
174    end
175
176    # Allowed params for user signup
177    def signup_params
178      [
179        :email,
180        :name,
181        :password,
182        :password_automatically_set,
183        :username,
184        :user_type,
185        :first_name,
186        :last_name
187      ]
188    end
189  end
190end
191
192Users::BuildService.prepend_mod_with('Users::BuildService')
193