From 964ae85d46f063a57532056e42b5e198f411f089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Geonizeli?= Date: Wed, 4 Aug 2021 23:06:28 -0300 Subject: [PATCH] add createUser mutation --- .rubocop.yml | 6 ++ Gemfile | 1 + Gemfile.lock | 3 + app/controllers/graphql_controller.rb | 2 +- app/graphql/inputs/user_attributes_input.rb | 9 +++ app/graphql/mutations/base_mutation.rb | 4 ++ app/graphql/mutations/create_user.rb | 16 +++++ app/graphql/types/mutation_type.rb | 7 +- app/models/user.rb | 1 + app/services/auth/authenticate.rb | 2 + .../inputs/user_attributes_input_spec.rb | 11 ++++ spec/graphql/mutations/create_user_spec.rb | 66 +++++++++++++++++++ 12 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 app/graphql/inputs/user_attributes_input.rb create mode 100644 app/graphql/mutations/create_user.rb create mode 100644 spec/graphql/inputs/user_attributes_input_spec.rb create mode 100644 spec/graphql/mutations/create_user_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index 81319d1..c96a2be 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,3 +10,9 @@ AllCops: Exclude: - db/schema.rb - bin/**/* + +RSpec/ExampleLength: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false diff --git a/Gemfile b/Gemfile index aade363..5a8db7b 100644 --- a/Gemfile +++ b/Gemfile @@ -48,4 +48,5 @@ end group :test do gem "shoulda-matchers", "~> 5.0" + gem "rspec-graphql_matchers", "~> 1.3" end diff --git a/Gemfile.lock b/Gemfile.lock index 083982b..bc77765 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -233,6 +233,8 @@ GEM rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) + rspec-graphql_matchers (1.3.0) + graphql (>= 1.8, < 2.0) rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) @@ -343,6 +345,7 @@ DEPENDENCIES puma (~> 5.0) pundit rails (~> 6.1.4) + rspec-graphql_matchers (~> 1.3) rspec-rails rubocop-rails rubocop-rspec diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 8f9e23c..b729732 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -9,8 +9,8 @@ class GraphqlController < ApplicationController query = params[:query] operation_name = params[:operationName] context = { - current_user: current_admin_user, # || current_auth.current_user, current_auth: current_auth, + current_user: current_admin_user, # || current_auth.current_user, } result = XStakeSchema.execute(query, variables: variables, context: context, operation_name: operation_name) render(json: result) diff --git a/app/graphql/inputs/user_attributes_input.rb b/app/graphql/inputs/user_attributes_input.rb new file mode 100644 index 0000000..61dc56a --- /dev/null +++ b/app/graphql/inputs/user_attributes_input.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +module Inputs + class UserAttributesInput < Types::BaseInputObject + graphql_name "UserAttributesInput" + + argument :first_name, String, required: true + argument :last_name, String, required: true + end +end diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb index a6576af..e589946 100644 --- a/app/graphql/mutations/base_mutation.rb +++ b/app/graphql/mutations/base_mutation.rb @@ -5,5 +5,9 @@ module Mutations field_class Types::BaseField input_object_class Types::BaseInputObject object_class Types::BaseObject + + field :errors, [String], + null: true, + description: "Errors encountered during execution of the mutation." end end diff --git a/app/graphql/mutations/create_user.rb b/app/graphql/mutations/create_user.rb new file mode 100644 index 0000000..c314e14 --- /dev/null +++ b/app/graphql/mutations/create_user.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +module Mutations + class CreateUser < BaseMutation + field :success, Boolean, null: false + + argument :user, Inputs::UserAttributesInput, required: true + + def resolve(user:) + User.create!({ **user, email: context[:current_auth].email }) + + { success: true } + rescue ActiveRecord::RecordInvalid => e + { success: false, errors: [e.message] } + end + end +end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 1c6dc93..7712f72 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -1,11 +1,6 @@ # frozen_string_literal: true module Types class MutationType < Types::BaseObject - # TODO: remove me - field :test_field, String, null: false, - description: "An example field added by the generator" - def test_field - "Hello World" - end + field :create_user, mutation: Mutations::CreateUser end end diff --git a/app/models/user.rb b/app/models/user.rb index 7073a2d..42f639c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,6 +19,7 @@ class User < ApplicationRecord has_many :documents, class_name: "UserDocument", dependent: :destroy validates :first_name, :last_name, :email, presence: true + validates :email, uniqueness: true def full_name "#{first_name} #{last_name}" diff --git a/app/services/auth/authenticate.rb b/app/services/auth/authenticate.rb index dce1225..b6d8838 100644 --- a/app/services/auth/authenticate.rb +++ b/app/services/auth/authenticate.rb @@ -8,6 +8,8 @@ module Auth end def profile + return nil if jwt_token.blank? + Auth0Client.find_profile(jwt_token) end end diff --git a/spec/graphql/inputs/user_attributes_input_spec.rb b/spec/graphql/inputs/user_attributes_input_spec.rb new file mode 100644 index 0000000..d3fe858 --- /dev/null +++ b/spec/graphql/inputs/user_attributes_input_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true +require "rails_helper" + +RSpec.describe(Inputs::UserAttributesInput) do + subject { described_class } + + describe "arguments" do + it { is_expected.to(accept_argument(:first_name).of_type("String!")) } + it { is_expected.to(accept_argument(:last_name).of_type("String!")) } + end +end diff --git a/spec/graphql/mutations/create_user_spec.rb b/spec/graphql/mutations/create_user_spec.rb new file mode 100644 index 0000000..ef8f711 --- /dev/null +++ b/spec/graphql/mutations/create_user_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true +require "rails_helper" + +RSpec.describe(Mutations::CreateUser) do + describe "#resolve" do + let(:mutation_string) do + <<~GQL + mutation($input: CreateUserInput!) { + createUser(input: $input) { + success + errors + } + } + GQL + end + + let(:context) do + { + current_auth: Auth::Profile.new({ + id: "_", + email: "user@example.com", + }), + } + end + + let(:variables) do + { + input: { user: { + firstName: "First Name", + lastName: "Last Name", + } }, + } + end + + context "when current_auth is not being used by any user" do + it "create a user to auth" do + result = XStakeSchema.execute( + mutation_string, + variables: variables, + context: context + ).to_h + + expect(result["data"]["createUser"]["success"]).to(eq(true)) + end + end + + context "when auth is being used by no users" do + it "returns error" do + User.create( + first_name: "First Name", + last_name: "Last Name", + email: "user@example.com" + ) + + result = XStakeSchema.execute( + mutation_string, + variables: variables, + context: context + ).to_h + + expect(result["data"]["createUser"]["success"]).to(eq(false)) + expect(result["data"]["createUser"]["errors"]).to(eq(["Validation failed: Email has already been taken"])) + end + end + end +end