From 92e11ae295220c261fc4528eca29c6cbf90e1e2c Mon Sep 17 00:00:00 2001 From: Steve Hobbs Date: Mon, 13 Mar 2023 12:34:46 +0000 Subject: [PATCH] [SDK-4014] User Authentication Method management API support (#450) --- .circleci/config.yml | 2 +- lib/auth0/api/v2/users.rb | 116 +++++++++++++++ spec/lib/auth0/api/v2/users_spec.rb | 218 ++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b5b36cd2..745104cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,6 @@ version: 2.1 orbs: - ship: auth0/ship@dev:alpha + ship: auth0/ship@0 codecov: codecov/codecov@3 matrix_ruby_versions: &matrix_ruby_versions diff --git a/lib/auth0/api/v2/users.rb b/lib/auth0/api/v2/users.rb index c5f64c1c..cc96d6a3 100644 --- a/lib/auth0/api/v2/users.rb +++ b/lib/auth0/api/v2/users.rb @@ -329,6 +329,122 @@ def get_user_organizations(user_id) get "#{users_path}/#{user_id}/organizations" end + # Get the available authentication methods for a user. + # + # @param user_id [string] The user ID of the authentication methods to get + # @param options [hash] A hash of options for getting permissions + # * :per_page [integer] The amount of permissions per page. (optional) + # * :page [integer] The page number. Zero based. (optional) + # * :include_totals [boolean] True if a query summary must be included in the result. (optional) + # @return [json] The user's authentication methods + # @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods + def user_authentication_methods(user_id, options = {}) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + + request_params = { + per_page: options.fetch(:per_page, nil), + page: options.fetch(:page, nil), + include_totals: options.fetch(:include_totals, nil) + } + + get "#{users_path}/#{user_id}/authentication-methods", request_params + end + alias get_user_authentication_methods user_authentication_methods + + # Get a specific authentication method for a user. + # + # @param user_id [string] The user ID of the authentication methods to get + # @param authentication_method_id [string] The ID of the authentication method + # @return [json] The user authentication method + # @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods_by_authentication_method_id + def user_authentication_method(user_id, authentication_method_id) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply a valid authentication_method_id' if authentication_method_id.to_s.empty? + + get "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}" + end + alias get_user_authentication_method user_authentication_method + + # Create an authentication method for a user + # + # @param user_id [string] The user ID of the authentication methods to get + # @param body [hash] The post body content + # * :type [string] "phone" or "email" or "totp" or "webauthn-roaming" + # * :name [string] A human-readable label to identify the authentication method (optional) + # * :totp_secret [string] Base32 encoded secret for TOTP generation (optional) + # * :phone_number [string] Applies to phone authentication methods only. The destination phone number used to send verification codes via text and voice (optional) + # * :email [string] Applies to email authentication methods only. The email address used to send verification messages (optional) + # * :preferred_authentication_method [string] Preferred phone authentication method (optional) + # * :key_id [string] Applies to email webauthn authenticators only. The id of the credential (optional) + # * :public_key [string] Applies to email webauthn authenticators only. The public key (optional) + # * :relying_party_identifier [string] Applies to email webauthn authenticators only. The relying party identifier (optional) + # @see https://auth0.com/docs/api/management/v2#!/Users/post_authentication_methods + def post_user_authentication_method(user_id, body) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty? + + post "#{users_path}/#{user_id}/authentication-methods", body + end + alias create_user_authentication_method post_user_authentication_method + + # Updates all authentication methods by replacing them with the given ones + # + # @param user_id [string] The user ID of the authentication methods to get + # @param body [hash array] The mehods to update + # * :type [string] "phone" or "email" or "totp" or "webauthn-roaming" + # * :name [string] A human-readable label to identify the authentication method (optional) + # * :totp_secret [string] Base32 encoded secret for TOTP generation (optional) + # * :phone_number [string] Applies to phone authentication methods only. The destination phone number used to send verification codes via text and voice (optional) + # * :email [string] Applies to email authentication methods only. The email address used to send verification messages (optional) + # * :preferred_authentication_method [string] Preferred phone authentication method (optional) + # @see https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods + def put_all_user_authentication_methods(user_id, body) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty? + + put "#{users_path}/#{user_id}/authentication-methods", body + end + alias update_all_user_authentication_methods put_all_user_authentication_methods + + # Updates a user authentication method + # + # @param user_id [string] The user ID of the authentication methods to get + # @param body [hash array] The mehods to update + # * :name [string] A human-readable label to identify the authentication method (optional) + # * :preferred_authentication_method [string] Preferred phone authentication method (optional) + # @see https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods + def patch_user_authentication_method(user_id, authentication_method_id, body) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply an authentication_method_id' if authentication_method_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply a body' if body.to_s.empty? + + patch "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}", body + end + alias update_user_authentication_method patch_user_authentication_method + + # Deletes all of the user's authentication methods + # + # @param user_id [string] The user ID + # @see https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods + def delete_user_authentication_methods(user_id) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + + delete "#{users_path}/#{user_id}/authentication-methods" + end + + + # Deletes the user's authentication method specified by authentication_method_id + # + # @param user_id [string] The user ID + # @param authentication_method_id [string] The ID of the authentication method + # @see https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods_by_authentication_method_id + def delete_user_authentication_method(user_id, authentication_method_id) + raise Auth0::MissingUserId, 'Must supply a valid user_id' if user_id.to_s.empty? + raise Auth0::MissingParameter, 'Must supply an authentication_method_id' if authentication_method_id.to_s.empty? + + delete "#{users_path}/#{user_id}/authentication-methods/#{authentication_method_id}" + end + private # Users API path diff --git a/spec/lib/auth0/api/v2/users_spec.rb b/spec/lib/auth0/api/v2/users_spec.rb index 3f4194da..93ae939b 100644 --- a/spec/lib/auth0/api/v2/users_spec.rb +++ b/spec/lib/auth0/api/v2/users_spec.rb @@ -583,4 +583,222 @@ end.not_to raise_error end end + + context '.get_user_authentication_methods' do + it 'is expected to respond to user_authentication_methods method' do + expect(@instance).to respond_to(:user_authentication_methods) + end + + it 'is expected to respond to get_user_authentication_methods method' do + expect(@instance).to respond_to(:get_user_authentication_methods) + end + + it 'is expected to raise an exception when the user ID is empty' do + expect { @instance.user_authentication_methods(nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to get user authentication methods' do + expect(@instance).to receive(:get).with( + '/api/v2/users/USER_ID/authentication-methods', { + per_page: nil, + page: nil, + include_totals: nil + } + ) + + expect do + @instance.user_authentication_methods('USER_ID') + end.not_to raise_error + end + + it 'is expected to get user authentication methods with paging' do + expect(@instance).to receive(:get).with( + '/api/v2/users/USER_ID/authentication-methods', { + per_page: 1, + page: 2, + include_totals: true + } + ) + + expect do + @instance.user_authentication_methods('USER_ID', per_page: 1, page: 2, include_totals: true) + end.not_to raise_error + end + end + + context '.get_user_authentication_method' do + it 'is expected to respond to get_user_authentication_method' do + expect(@instance).to respond_to :user_authentication_method + end + + it 'is expected to respond to get_user_authentication_method' do + expect(@instance).to respond_to :get_user_authentication_method + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.user_authentication_method(nil, nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to raise an exception for a missing authentication method ID' do + expect { @instance.user_authentication_method('USER_ID', nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to GET a user authentication method' do + expect(@instance).to receive(:get).with( + '/api/v2/users/USER_ID/authentication-methods/AUTH_METHOD_ID' + ) + + expect do + @instance.user_authentication_method('USER_ID', 'AUTH_METHOD_ID') + end.not_to raise_error + + end + end + + context '.create_user_authentication_method' do + it 'is expected to respond to create_user_authentication_method' do + expect(@instance).to respond_to :create_user_authentication_method + end + + it 'is expected to respond to post_user_authentication_method' do + expect(@instance).to respond_to :post_user_authentication_method + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.create_user_authentication_method(nil, nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to raise an exception for a missing body' do + expect { @instance.create_user_authentication_method('USER_ID', nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to send the body to the endpoint' do + body = { + type: 'phone' + } + + expect(@instance).to receive(:post).with( + '/api/v2/users/USER_ID/authentication-methods', + body + ) + + expect do + @instance.create_user_authentication_method 'USER_ID', body + end.not_to raise_error + end + end + + context '.put_all_user_authentication_methods' do + it 'is expected to respond to put_all_user_authentication_methods' do + expect(@instance).to respond_to(:put_all_user_authentication_methods) + end + + it 'is expected to respond to update_all_user_authentication_methods' do + expect(@instance).to respond_to(:update_all_user_authentication_methods) + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.put_all_user_authentication_methods(nil, nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to raise an exception for a missing body' do + expect { @instance.put_all_user_authentication_methods('USER_ID', nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to send the body to the endpoint' do + body = { + type: 'phone' + } + + expect(@instance).to receive(:put).with( + '/api/v2/users/USER_ID/authentication-methods', + [body] + ) + + expect do + @instance.put_all_user_authentication_methods 'USER_ID', [body] + end.to_not raise_error + end + end + + context '.patch_user_authentication_method' do + it 'is expected to respond to patch_user_authentication_method' do + expect(@instance).to respond_to(:patch_user_authentication_method) + end + + it 'is expected to respond to update_user_authentication_method' do + expect(@instance).to respond_to(:update_user_authentication_method) + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.patch_user_authentication_method(nil, nil, nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to raise an exception for a missing authentication_method_id' do + expect { @instance.patch_user_authentication_method('USER_ID', nil, nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to raise an exception for a missing body' do + expect { @instance.patch_user_authentication_method('USER_ID', 'AUTH_METHOD_ID', nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to send the body to the endpoint' do + body = { + name: 'auth method name' + } + + expect(@instance).to receive(:patch).with( + '/api/v2/users/USER_ID/authentication-methods/AUTH_METHOD_ID', + body + ) + + expect do + @instance.patch_user_authentication_method 'USER_ID', 'AUTH_METHOD_ID', body + end.to_not raise_error + end + end + + context '.delete_user_authentication_methods' do + it 'is expected to respond to delete_user_authentication_methods' do + expect(@instance).to respond_to(:delete_user_authentication_methods) + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.delete_user_authentication_methods(nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to call the endpoint' do + expect(@instance).to receive(:delete).with( + '/api/v2/users/USER_ID/authentication-methods' + ) + + expect do + @instance.delete_user_authentication_methods 'USER_ID' + end.to_not raise_error + end + end + + context '.delete_user_authentication_method' do + it 'is expected to respond to delete_user_authentication_method' do + expect(@instance).to respond_to(:delete_user_authentication_method) + end + + it 'is expected to raise an exception for a missing user ID' do + expect { @instance.delete_user_authentication_method(nil, nil) }.to raise_exception(Auth0::MissingUserId) + end + + it 'is expected to raise an exception for a missing authentication_method_id' do + expect { @instance.delete_user_authentication_method('USER_ID', nil) }.to raise_exception(Auth0::MissingParameter) + end + + it 'is expected to call the endpoint' do + expect(@instance).to receive(:delete).with( + '/api/v2/users/USER_ID/authentication-methods/AUTH_METHOD_ID' + ) + + expect do + @instance.delete_user_authentication_method 'USER_ID', 'AUTH_METHOD_ID' + end.to_not raise_error + end + end end