+ # Change UUID to a new (unused) uuid and transfer all owned/linked
+ # objects accordingly.
+ def update_uuid
+ @object.update_uuid(new_uuid: params[:new_uuid])
+ show
+ end
+
+ def merge
+ if !Thread.current[:api_client].andand.is_trusted
+ return send_error("supplied API token is not from a trusted client", status: 403)
+ end
+
+ dst_auth = ApiClientAuthorization.validate(token: params[:new_user_token])
+ if !dst_auth
+ return send_error("invalid new_user_token", status: 401)
+ end
+ if !dst_auth.api_client.andand.is_trusted
+ return send_error("supplied new_user_token is not from a trusted client", status: 403)
+ end
+ dst_user = dst_auth.user
+
+ if current_user.uuid == dst_user.uuid
+ return send_error("cannot merge user to self", status: 422)
+ end
+
+ if !dst_user.can?(write: params[:new_owner_uuid])
+ return send_error("new_owner_uuid is not writable", status: 403)
+ end
+
+ redirect = params[:redirect_to_new_user]
+ if !redirect
+ return send_error("merge with redirect_to_new_user=false is not yet supported", status: 422)
+ end
+
+ @object = current_user
+ act_as_system_user do
+ @object.merge(new_owner_uuid: params[:new_owner_uuid], redirect_to_user_uuid: redirect && dst_user.uuid)
+ end
+ show
+ end
+
+ protected
+
+ def self._setup_requires_parameters
+ {
+ user: {
+ type: 'object', required: false
+ },
+ openid_prefix: {
+ type: 'string', required: false
+ },
+ repo_name: {
+ type: 'string', required: false
+ },
+ vm_uuid: {
+ type: 'string', required: false
+ },
+ send_notification_email: {
+ type: 'boolean', required: false, default: false
+ },
+ }
+ end
+
+ def self._update_uuid_requires_parameters
+ {
+ new_uuid: {
+ type: 'string', required: true,
+ },
+ }
+ end
+
+ def apply_filters(model_class=nil)
+ return super if @read_users.any?(&:is_admin)
+ if params[:uuid] != current_user.andand.uuid
+ # Non-admin index/show returns very basic information about readable users.
+ safe_attrs = ["uuid", "is_active", "email", "first_name", "last_name", "username"]
+ if @select
+ @select = @select & safe_attrs
+ else
+ @select = safe_attrs
+ end
+ @filters += [['is_active', '=', true]]
+ end
+ super
+ end