diff options
Diffstat (limited to 'spec/unit/user_spec.rb')
-rw-r--r-- | spec/unit/user_spec.rb | 508 |
1 files changed, 100 insertions, 408 deletions
diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb index 5222c951b3..777a4e6ef0 100644 --- a/spec/unit/user_spec.rb +++ b/spec/unit/user_spec.rb @@ -16,6 +16,11 @@ # limitations under the License. # +# DEPRECATION NOTE +# This code only remains to support users still operating with +# Open Source Chef Server 11 and should be removed once support +# for OSC 11 ends. New development should occur in user_spec.rb. + require 'spec_helper' require 'chef/user' @@ -26,141 +31,98 @@ describe Chef::User do @user = Chef::User.new end - shared_examples_for "string fields with no contraints" do - it "should let you set the public key" do - expect(@user.send(method, "some_string")).to eq("some_string") - end - - it "should return the current public key" do - @user.send(method, "some_string") - expect(@user.send(method)).to eq("some_string") - end - - it "should throw an ArgumentError if you feed it something lame" do - expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError) - end - end - - shared_examples_for "boolean fields with no constraints" do - it "should let you set the field" do - expect(@user.send(method, true)).to eq(true) - end - - it "should return the current field value" do - @user.send(method, true) - expect(@user.send(method)).to eq(true) - end - - it "should return the false value when false" do - @user.send(method, false) - expect(@user.send(method)).to eq(false) - end - - it "should throw an ArgumentError if you feed it anything but true or false" do - expect { @user.send(method, Hash.new) }.to raise_error(ArgumentError) - end - end - describe "initialize" do it "should be a Chef::User" do expect(@user).to be_a_kind_of(Chef::User) end end - describe "username" do - it "should let you set the username to a string" do - expect(@user.username("ops_master")).to eq("ops_master") + describe "name" do + it "should let you set the name to a string" do + expect(@user.name("ops_master")).to eq("ops_master") end - it "should return the current username" do - @user.username "ops_master" - expect(@user.username).to eq("ops_master") + it "should return the current name" do + @user.name "ops_master" + expect(@user.name).to eq("ops_master") end # It is not feasible to check all invalid characters. Here are a few # that we probably care about. it "should not accept invalid characters" do # capital letters - expect { @user.username "Bar" }.to raise_error(ArgumentError) + expect { @user.name "Bar" }.to raise_error(ArgumentError) # slashes - expect { @user.username "foo/bar" }.to raise_error(ArgumentError) + expect { @user.name "foo/bar" }.to raise_error(ArgumentError) # ? - expect { @user.username "foo?" }.to raise_error(ArgumentError) + expect { @user.name "foo?" }.to raise_error(ArgumentError) # & - expect { @user.username "foo&" }.to raise_error(ArgumentError) + expect { @user.name "foo&" }.to raise_error(ArgumentError) end it "should not accept spaces" do - expect { @user.username "ops master" }.to raise_error(ArgumentError) + expect { @user.name "ops master" }.to raise_error(ArgumentError) end it "should throw an ArgumentError if you feed it anything but a string" do - expect { @user.username Hash.new }.to raise_error(ArgumentError) + expect { @user.name Hash.new }.to raise_error(ArgumentError) end end - describe "boolean fields" do - describe "create_key" do - it_should_behave_like "boolean fields with no constraints" do - let(:method) { :create_key } - end + describe "admin" do + it "should let you set the admin bit" do + expect(@user.admin(true)).to eq(true) end - end - describe "string fields" do - describe "public_key" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :public_key } - end + it "should return the current admin value" do + @user.admin true + expect(@user.admin).to eq(true) end - describe "private_key" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :private_key } - end + it "should default to false" do + expect(@user.admin).to eq(false) end - describe "display_name" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :display_name } - end + it "should throw an ArgumentError if you feed it anything but true or false" do + expect { @user.name Hash.new }.to raise_error(ArgumentError) end + end - describe "first_name" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :first_name } - end + describe "public_key" do + it "should let you set the public key" do + expect(@user.public_key("super public")).to eq("super public") end - describe "middle_name" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :middle_name } - end + it "should return the current public key" do + @user.public_key("super public") + expect(@user.public_key).to eq("super public") end - describe "last_name" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :last_name } - end + it "should throw an ArgumentError if you feed it something lame" do + expect { @user.public_key Hash.new }.to raise_error(ArgumentError) end + end - describe "email" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :email } - end + describe "private_key" do + it "should let you set the private key" do + expect(@user.private_key("super private")).to eq("super private") end - describe "password" do - it_should_behave_like "string fields with no contraints" do - let(:method) { :password } - end + it "should return the private key" do + @user.private_key("super private") + expect(@user.private_key).to eq("super private") + end + + it "should throw an ArgumentError if you feed it something lame" do + expect { @user.private_key Hash.new }.to raise_error(ArgumentError) end end describe "when serializing to JSON" do before(:each) do - @user.username("black") + @user.name("black") + @user.public_key("crowes") @json = @user.to_json end @@ -168,62 +130,16 @@ describe Chef::User do expect(@json).to match(/^\{.+\}$/) end - it "includes the username value" do - expect(@json).to include(%q{"username":"black"}) - end - - it "includes the display name when present" do - @user.display_name("get_displayed") - expect(@user.to_json).to include(%{"display_name":"get_displayed"}) - end - - it "does not include the display name if not present" do - expect(@json).not_to include("display_name") - end - - it "includes the first name when present" do - @user.first_name("char") - expect(@user.to_json).to include(%{"first_name":"char"}) - end - - it "does not include the first name if not present" do - expect(@json).not_to include("first_name") - end - - it "includes the middle name when present" do - @user.middle_name("man") - expect(@user.to_json).to include(%{"middle_name":"man"}) - end - - it "does not include the middle name if not present" do - expect(@json).not_to include("middle_name") - end - - it "includes the last name when present" do - @user.last_name("der") - expect(@user.to_json).to include(%{"last_name":"der"}) - end - - it "does not include the last name if not present" do - expect(@json).not_to include("last_name") - end - - it "includes the email when present" do - @user.email("charmander@pokemon.poke") - expect(@user.to_json).to include(%{"email":"charmander@pokemon.poke"}) - end - - it "does not include the email if not present" do - expect(@json).not_to include("email") + it "includes the name value" do + expect(@json).to include(%q{"name":"black"}) end - it "includes the public key when present" do - @user.public_key("crowes") - expect(@user.to_json).to include(%{"public_key":"crowes"}) + it "includes the public key value" do + expect(@json).to include(%{"public_key":"crowes"}) end - it "does not include the public key if not present" do - expect(@json).not_to include("public_key") + it "includes the 'admin' flag" do + expect(@json).to include(%q{"admin":false}) end it "includes the private key when present" do @@ -251,18 +167,11 @@ describe Chef::User do describe "when deserializing from JSON" do before(:each) do - user = { - "username" => "mr_spinks", - "display_name" => "displayed", - "first_name" => "char", - "middle_name" => "man", - "last_name" => "der", - "email" => "charmander@pokemon.poke", - "password" => "password", + user = { "name" => "mr_spinks", "public_key" => "turtles", "private_key" => "pandas", - "create_key" => false - } + "password" => "password", + "admin" => true } @user = Chef::User.from_json(Chef::JSONCompat.to_json(user)) end @@ -270,277 +179,34 @@ describe Chef::User do expect(@user).to be_a_kind_of(Chef::User) end - it "preserves the username" do - expect(@user.username).to eq("mr_spinks") - end - - it "preserves the display name if present" do - expect(@user.display_name).to eq("displayed") + it "preserves the name" do + expect(@user.name).to eq("mr_spinks") end - it "preserves the first name if present" do - expect(@user.first_name).to eq("char") - end - - it "preserves the middle name if present" do - expect(@user.middle_name).to eq("man") + it "preserves the public key" do + expect(@user.public_key).to eq("turtles") end - it "preserves the last name if present" do - expect(@user.last_name).to eq("der") + it "preserves the admin status" do + expect(@user.admin).to be_truthy end - it "preserves the email if present" do - expect(@user.email).to eq("charmander@pokemon.poke") + it "includes the private key if present" do + expect(@user.private_key).to eq("pandas") end it "includes the password if present" do expect(@user.password).to eq("password") end - it "preserves the public key if present" do - expect(@user.public_key).to eq("turtles") - end - - it "includes the private key if present" do - expect(@user.private_key).to eq("pandas") - end - - it "includes the create key status if not nil" do - expect(@user.create_key).to be_falsey - end end - describe "Versioned API Interactions" do - let(:response_406) { OpenStruct.new(:code => '406') } - let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) } - - before (:each) do - @user = Chef::User.new - allow(@user).to receive(:chef_root_rest_v0).and_return(double('chef rest root v0 object')) - allow(@user).to receive(:chef_root_rest_v1).and_return(double('chef rest root v1 object')) - end - - describe "update" do - before do - # populate all fields that are valid between V0 and V1 - @user.username "some_username" - @user.display_name "some_display_name" - @user.first_name "some_first_name" - @user.middle_name "some_middle_name" - @user.last_name "some_last_name" - @user.email "some_email" - @user.password "some_password" - end - - let(:payload) { - { - :username => "some_username", - :display_name => "some_display_name", - :first_name => "some_first_name", - :middle_name => "some_middle_name", - :last_name => "some_last_name", - :email => "some_email", - :password => "some_password" - } - } - - context "when server API V1 is valid on the Chef Server receiving the request" do - context "when the user submits valid data" do - it "properly updates the user" do - expect(@user.chef_root_rest_v1).to receive(:put).with("users/some_username", payload).and_return({}) - @user.update - end - end - end - - context "when server API V1 is not valid on the Chef Server receiving the request" do - let(:payload) { - { - :username => "some_username", - :display_name => "some_display_name", - :first_name => "some_first_name", - :middle_name => "some_middle_name", - :last_name => "some_last_name", - :email => "some_email", - :password => "some_password", - :public_key => "some_public_key" - } - } - - before do - @user.public_key "some_public_key" - allow(@user.chef_root_rest_v1).to receive(:put) - end - - context "when the server returns a 400" do - let(:response_400) { OpenStruct.new(:code => '400') } - let(:exception_400) { Net::HTTPServerException.new("400 Bad Request", response_400) } - - context "when the 400 was due to public / private key fields no longer being supported" do - let(:response_body_400) { '{"error":["Since Server API v1, all keys must be updated via the keys endpoint. "]}' } - - before do - allow(response_400).to receive(:body).and_return(response_body_400) - allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400) - end - - it "proceeds with the V0 PUT since it can handle public / private key fields" do - expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({}) - @user.update - end - - it "does not call server_client_api_version_intersection, since we know to proceed with V0 in this case" do - expect(@user).to_not receive(:server_client_api_version_intersection) - allow(@user.chef_root_rest_v0).to receive(:put).and_return({}) - @user.update - end - end # when the 400 was due to public / private key fields - - context "when the 400 was NOT due to public / private key fields no longer being supported" do - let(:response_body_400) { '{"error":["Some other error. "]}' } - - before do - allow(response_400).to receive(:body).and_return(response_body_400) - allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_400) - end - - it "will not proceed with the V0 PUT since the original bad request was not key related" do - expect(@user.chef_root_rest_v0).to_not receive(:put).with("users/some_username", payload) - expect { @user.update }.to raise_error(exception_400) - end - - it "raises the original error" do - expect { @user.update }.to raise_error(exception_400) - end - - end - end # when the server returns a 400 - - context "when the server returns a 406" do - # from spec/support/shared/unit/api_versioning.rb - it_should_behave_like "version handling" do - let(:object) { @user } - let(:method) { :update } - let(:http_verb) { :put } - let(:rest_v1) { @user.chef_root_rest_v1 } - end - - context "when the server supports API V0" do - before do - allow(@user).to receive(:server_client_api_version_intersection).and_return([0]) - allow(@user.chef_root_rest_v1).to receive(:put).and_raise(exception_406) - end - - it "properly updates the user" do - expect(@user.chef_root_rest_v0).to receive(:put).with("users/some_username", payload).and_return({}) - @user.update - end - end # when the server supports API V0 - end # when the server returns a 406 - - end # when server API V1 is not valid on the Chef Server receiving the request - end # update - - describe "create" do - let(:payload) { - { - :username => "some_username", - :display_name => "some_display_name", - :first_name => "some_first_name", - :last_name => "some_last_name", - :email => "some_email", - :password => "some_password" - } - } - before do - @user.username "some_username" - @user.display_name "some_display_name" - @user.first_name "some_first_name" - @user.last_name "some_last_name" - @user.email "some_email" - @user.password "some_password" - end - - # from spec/support/shared/unit/user_and_client_shared.rb - it_should_behave_like "user or client create" do - let(:object) { @user } - let(:error) { Chef::Exceptions::InvalidUserAttribute } - let(:rest_v0) { @user.chef_root_rest_v0 } - let(:rest_v1) { @user.chef_root_rest_v1 } - let(:url) { "users" } - end - - context "when handling API V1" do - it "creates a new user via the API with a middle_name when it exists" do - @user.middle_name "some_middle_name" - expect(@user.chef_root_rest_v1).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({}) - @user.create - end - end # when server API V1 is valid on the Chef Server receiving the request - - context "when API V1 is not supported by the server" do - # from spec/support/shared/unit/api_versioning.rb - it_should_behave_like "version handling" do - let(:object) { @user } - let(:method) { :create } - let(:http_verb) { :post } - let(:rest_v1) { @user.chef_root_rest_v1 } - end - end - - context "when handling API V0" do - before do - allow(@user).to receive(:server_client_api_version_intersection).and_return([0]) - allow(@user.chef_root_rest_v1).to receive(:post).and_raise(exception_406) - end - - it "creates a new user via the API with a middle_name when it exists" do - @user.middle_name "some_middle_name" - expect(@user.chef_root_rest_v0).to receive(:post).with("users", payload.merge({:middle_name => "some_middle_name"})).and_return({}) - @user.create - end - end # when server API V1 is not valid on the Chef Server receiving the request - - end # create - - # DEPRECATION - # This can be removed after API V0 support is gone - describe "reregister" do - let(:payload) { - { - "username" => "some_username", - } - } - - before do - @user.username "some_username" - end - - context "when server API V0 is valid on the Chef Server receiving the request" do - it "creates a new object via the API" do - expect(@user.chef_root_rest_v0).to receive(:put).with("users/#{@user.username}", payload.merge({"private_key" => true})).and_return({}) - @user.reregister - end - end # when server API V0 is valid on the Chef Server receiving the request - - context "when server API V0 is not supported by the Chef Server" do - # from spec/support/shared/unit/api_versioning.rb - it_should_behave_like "user and client reregister" do - let(:object) { @user } - let(:rest_v0) { @user.chef_root_rest_v0 } - end - end # when server API V0 is not supported by the Chef Server - end # reregister - - end # Versioned API Interactions - describe "API Interactions" do before (:each) do @user = Chef::User.new - @user.username "foobar" - @http_client = double("Chef::REST mock") - allow(Chef::REST).to receive(:new).and_return(@http_client) + @user.name "foobar" + @http_client = double("Chef::ServerAPI mock") + allow(Chef::ServerAPI).to receive(:new).and_return(@http_client) end describe "list" do @@ -552,31 +218,57 @@ describe Chef::User do @osc_inflated_response = { "admin" => @user } end + it "lists all clients on an OSC server" do + allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response) + expect(Chef::User.list).to eq(@osc_response) + end + + it "inflate all clients on an OSC server" do + allow(@http_client).to receive(:get_rest).with("users").and_return(@osc_response) + expect(Chef::User.list(true)).to eq(@osc_inflated_response) + end + it "lists all clients on an OHC/OPC server" do - allow(@http_client).to receive(:get).with("users").and_return(@ohc_response) + allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response) # We expect that Chef::User.list will give a consistent response # so OHC API responses should be transformed to OSC-style output. expect(Chef::User.list).to eq(@osc_response) end it "inflate all clients on an OHC/OPC server" do - allow(@http_client).to receive(:get).with("users").and_return(@ohc_response) + allow(@http_client).to receive(:get_rest).with("users").and_return(@ohc_response) expect(Chef::User.list(true)).to eq(@osc_inflated_response) end end + describe "create" do + it "creates a new user via the API" do + @user.password "password" + expect(@http_client).to receive(:post_rest).with("users", {:name => "foobar", :admin => false, :password => "password"}).and_return({}) + @user.create + end + end + describe "read" do it "loads a named user from the API" do - expect(@http_client).to receive(:get).with("users/foobar").and_return({"username" => "foobar", "admin" => true, "public_key" => "pubkey"}) + expect(@http_client).to receive(:get_rest).with("users/foobar").and_return({"name" => "foobar", "admin" => true, "public_key" => "pubkey"}) user = Chef::User.load("foobar") - expect(user.username).to eq("foobar") + expect(user.name).to eq("foobar") + expect(user.admin).to eq(true) expect(user.public_key).to eq("pubkey") end end + describe "update" do + it "updates an existing user on via the API" do + expect(@http_client).to receive(:put_rest).with("users/foobar", {:name => "foobar", :admin => false}).and_return({}) + @user.update + end + end + describe "destroy" do it "deletes the specified user via the API" do - expect(@http_client).to receive(:delete).with("users/foobar") + expect(@http_client).to receive(:delete_rest).with("users/foobar") @user.destroy end end |