class Chef::UserV1

Constants

SUPPORTED_API_VERSIONS

Public Class Methods

from_hash(user_hash) click to toggle source

Class Methods

# File lib/chef/user_v1.rb, line 260
def self.from_hash(user_hash)
  user = Chef::UserV1.new
  user.username user_hash["username"]
  user.display_name user_hash["display_name"] if user_hash.key?("display_name")
  user.first_name user_hash["first_name"] if user_hash.key?("first_name")
  user.middle_name user_hash["middle_name"] if user_hash.key?("middle_name")
  user.last_name user_hash["last_name"] if user_hash.key?("last_name")
  user.email user_hash["email"] if user_hash.key?("email")
  user.password user_hash["password"] if user_hash.key?("password")
  user.public_key user_hash["public_key"] if user_hash.key?("public_key")
  user.private_key user_hash["private_key"] if user_hash.key?("private_key")
  user.create_key user_hash["create_key"] if user_hash.key?("create_key")
  user
end
from_json(json) click to toggle source
# File lib/chef/user_v1.rb, line 275
def self.from_json(json)
  Chef::UserV1.from_hash(Chef::JSONCompat.from_json(json))
end
list(inflate = false) click to toggle source
# File lib/chef/user_v1.rb, line 279
def self.list(inflate = false)
  response = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("users")
  users = if response.is_a?(Array)
            # EC 11 / CS 12 V0, V1
            #   GET /organizations/<org>/users
            transform_list_response(response)
          else
            # OSC 11
            #  GET /users
            # EC 11 / CS 12 V0, V1
            #  GET /users
            response # OSC
          end

  if inflate
    users.inject({}) do |user_map, (name, _url)|
      user_map[name] = Chef::UserV1.load(name)
      user_map
    end
  else
    users
  end
end
load(username) click to toggle source
# File lib/chef/user_v1.rb, line 303
def self.load(username)
  # will default to the current API version (Chef::Authenticator::DEFAULT_SERVER_API_VERSION)
  response = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("users/#{username}")
  Chef::UserV1.from_hash(response)
end
new() click to toggle source
# File lib/chef/user_v1.rb, line 44
def initialize
  @username = nil
  @display_name = nil
  @first_name = nil
  @middle_name = nil
  @last_name = nil
  @email = nil
  @password = nil
  @public_key = nil
  @private_key = nil
  @create_key = nil
end

Private Class Methods

transform_list_response(response) click to toggle source

Gross. Transforms an API response in the form of:

{ “user” => { “username” => USERNAME }}, …

into the form { “USERNAME” => “URI” }

# File lib/chef/user_v1.rb, line 313
def self.transform_list_response(response)
  new_response = Hash.new
  response.each do |u|
    name = u["user"]["username"]
    new_response[name] = Chef::Config[:chef_server_url] + "/users/#{name}"
  end
  new_response
end

Public Instance Methods

chef_root_rest_v0() click to toggle source
# File lib/chef/user_v1.rb, line 57
def chef_root_rest_v0
  @chef_root_rest_v0 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root], { api_version: "0" })
end
chef_root_rest_v1() click to toggle source
# File lib/chef/user_v1.rb, line 61
def chef_root_rest_v1
  @chef_root_rest_v1 ||= Chef::ServerAPI.new(Chef::Config[:chef_server_root], { api_version: "1" })
end
create() click to toggle source
# File lib/chef/user_v1.rb, line 142
def create
  # try v1, fail back to v0 if v1 not supported
  begin
    payload = {
      username: @username,
      display_name: @display_name,
      first_name: @first_name,
      last_name: @last_name,
      email: @email,
      password: @password,
    }
    payload[:public_key] = @public_key unless @public_key.nil?
    payload[:create_key] = @create_key unless @create_key.nil?
    payload[:middle_name] = @middle_name unless @middle_name.nil?
    raise Chef::Exceptions::InvalidUserAttribute, "You cannot set both public_key and create_key for create." if !@create_key.nil? && !@public_key.nil?
    new_user = chef_root_rest_v1.post("users", payload)

    # get the private_key out of the chef_key hash if it exists
    if new_user["chef_key"]
      if new_user["chef_key"]["private_key"]
        new_user["private_key"] = new_user["chef_key"]["private_key"]
      end
      new_user["public_key"] = new_user["chef_key"]["public_key"]
      new_user.delete("chef_key")
    end
  rescue Net::HTTPClientException => e
    # rescue API V0 if 406 and the server supports V0
    supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
    raise e unless supported_versions && supported_versions.include?(0)
    payload = {
      username: @username,
      display_name: @display_name,
      first_name: @first_name,
      last_name: @last_name,
      email: @email,
      password: @password,
    }
    payload[:middle_name] = @middle_name unless @middle_name.nil?
    payload[:public_key] = @public_key unless @public_key.nil?
    # under API V0, the server will create a key pair if public_key isn't passed
    new_user = chef_root_rest_v0.post("users", payload)
  end

  Chef::UserV1.from_hash(to_h.merge(new_user))
end
create_key(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 95
def create_key(arg = nil)
  set_or_return(:create_key, arg,
                kind_of: [TrueClass, FalseClass])
end
destroy() click to toggle source
# File lib/chef/user_v1.rb, line 137
def destroy
  # will default to the current API version (Chef::Authenticator::DEFAULT_SERVER_API_VERSION)
  Chef::ServerAPI.new(Chef::Config[:chef_server_url]).delete("users/#{@username}")
end
display_name(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 70
def display_name(arg = nil)
  set_or_return(:display_name,
                arg, kind_of: String)
end
email(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 90
def email(arg = nil)
  set_or_return(:email,
                arg, kind_of: String)
end
first_name(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 75
def first_name(arg = nil)
  set_or_return(:first_name,
                arg, kind_of: String)
end
last_name(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 85
def last_name(arg = nil)
  set_or_return(:last_name,
                arg, kind_of: String)
end
middle_name(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 80
def middle_name(arg = nil)
  set_or_return(:middle_name,
                arg, kind_of: String)
end
password(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 110
def password(arg = nil)
  set_or_return(:password,
                arg, kind_of: String)
end
private_key(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 105
def private_key(arg = nil)
  set_or_return(:private_key,
                arg, kind_of: String)
end
public_key(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 100
def public_key(arg = nil)
  set_or_return(:public_key,
                arg, kind_of: String)
end
reregister() click to toggle source

Note: remove after API v0 no longer supported by client (and knife command).

# File lib/chef/user_v1.rb, line 232
def reregister
  begin
    payload = to_h.merge({ "private_key" => true })
    reregistered_self = chef_root_rest_v0.put("users/#{username}", payload)
    private_key(reregistered_self["private_key"])
  # only V0 supported for reregister
  rescue Net::HTTPClientException => e
    # if there was a 406 related to versioning, give error explaining that
    # only API version 0 is supported for reregister command
    if e.response.code == "406" && e.response["x-ops-server-api-version"]
      version_header = Chef::JSONCompat.from_json(e.response["x-ops-server-api-version"])
      min_version = version_header["min_version"]
      max_version = version_header["max_version"]
      error_msg = reregister_only_v0_supported_error_msg(max_version, min_version)
      raise Chef::Exceptions::OnlyApiVersion0SupportedForAction.new(error_msg)
    else
      raise e
    end
  end
  self
end
save(new_key = false) click to toggle source
# File lib/chef/user_v1.rb, line 221
def save(new_key = false)
  create
rescue Net::HTTPClientException => e
  if e.response.code == "409"
    update(new_key)
  else
    raise e
  end
end
to_h() click to toggle source
# File lib/chef/user_v1.rb, line 115
def to_h
  result = {
    "username" => @username,
  }
  result["display_name"] = @display_name unless @display_name.nil?
  result["first_name"] = @first_name unless @first_name.nil?
  result["middle_name"] = @middle_name unless @middle_name.nil?
  result["last_name"] = @last_name unless @last_name.nil?
  result["email"] = @email unless @email.nil?
  result["password"] = @password unless @password.nil?
  result["public_key"] = @public_key unless @public_key.nil?
  result["private_key"] = @private_key unless @private_key.nil?
  result["create_key"] = @create_key unless @create_key.nil?
  result
end
Also aliased as: to_hash
to_hash()
Alias for: to_h
to_json(*a) click to toggle source
# File lib/chef/user_v1.rb, line 133
def to_json(*a)
  Chef::JSONCompat.to_json(to_h, *a)
end
to_s() click to toggle source
# File lib/chef/user_v1.rb, line 254
def to_s
  "user[#{@username}]"
end
update(new_key = false) click to toggle source
# File lib/chef/user_v1.rb, line 188
def update(new_key = false)
  begin
    payload = { username: username }
    payload[:display_name] = display_name unless display_name.nil?
    payload[:first_name] = first_name unless first_name.nil?
    payload[:middle_name] = middle_name unless middle_name.nil?
    payload[:last_name] = last_name unless last_name.nil?
    payload[:email] = email unless email.nil?
    payload[:password] = password unless password.nil?

    # API V1 will fail if these key fields are defined, and try V0 below if relevant 400 is returned
    payload[:public_key] = public_key unless public_key.nil?
    payload[:private_key] = new_key if new_key

    updated_user = chef_root_rest_v1.put("users/#{username}", payload)
  rescue Net::HTTPClientException => e
    if e.response.code == "400"
      # if a 400 is returned but the error message matches the error related to private / public key fields, try V0
      # else, raise the 400
      error = Chef::JSONCompat.from_json(e.response.body)["error"].first
      error_match = /Since Server API v1, all keys must be updated via the keys endpoint/.match(error)
      if error_match.nil?
        raise e
      end
    else # for other types of errors, test for API versioning errors right away
      supported_versions = server_client_api_version_intersection(e, SUPPORTED_API_VERSIONS)
      raise e unless supported_versions && supported_versions.include?(0)
    end
    updated_user = chef_root_rest_v0.put("users/#{username}", payload)
  end
  Chef::UserV1.from_hash(to_h.merge(updated_user))
end
username(arg = nil) click to toggle source
# File lib/chef/user_v1.rb, line 65
def username(arg = nil)
  set_or_return(:username, arg,
                regex: /^[a-z0-9\-_]+$/)
end