graphql-auth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/README.md +110 -0
- data/app/graphql/mutations/forgot_password.rb +22 -0
- data/app/graphql/mutations/reset_password.rb +46 -0
- data/app/graphql/mutations/sign_in.rb +49 -0
- data/app/graphql/mutations/sign_up.rb +46 -0
- data/app/graphql/mutations/update_account.rb +45 -0
- data/app/graphql/mutations/validate_token.rb +24 -0
- data/app/graphql/types/error.rb +13 -0
- data/app/graphql/types/graphql_auth.rb +15 -0
- data/app/graphql/types/user.rb +9 -0
- data/app/helpers/graphql/auth_helper.rb +30 -0
- data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/lib/generators/graphql_auth/install_generator.rb +11 -0
- data/lib/generators/graphql_auth/templates/initializer.rb +15 -0
- data/lib/graphql-auth.rb +19 -0
- data/lib/graphql-auth/configuration.rb +31 -0
- data/lib/graphql-auth/engine.rb +7 -0
- data/lib/graphql-auth/jwt_manager.rb +48 -0
- data/lib/graphql-auth/reset_password.rb +14 -0
- metadata +135 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: f94c2a56e51599f277494d890c6b754e7f34933d
         | 
| 4 | 
            +
              data.tar.gz: 8b2c569822bd5f09286f68bb240449ecb50ae600
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: a3f06d11726fb5538b0cf38b620e4ac7ef59d981412a98730d2baa0fb1faf6cb579f1d9600c5100422e4c26f6f838aa470e223eabc8a8432c1c3589a00c5cb9a
         | 
| 7 | 
            +
              data.tar.gz: 9d5ff6f5d125b4afb3673834097aaf287bae87e836c2b4a8cbb483fb7f0491b9cc5cda71f029c4bb2b7f95b3d462d9b709c267ce1519061e1c5e1e2ab1a83a1d
         | 
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,110 @@ | |
| 1 | 
            +
            # GraphQL Auth
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/graphql-auth`. To experiment with that code, run `bin/console` for an interactive prompt.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Installation
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Add this line to your application's Gemfile:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ```ruby
         | 
| 10 | 
            +
            gem 'graphql-auth'
         | 
| 11 | 
            +
            ```
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            And then execute:
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                $ bundle
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            Or install it yourself as:
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                $ gem install graphql-auth
         | 
| 20 | 
            +
                
         | 
| 21 | 
            +
            Then run the installer to create `graphql_auth.rb` file in your initializers folder.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ```
         | 
| 24 | 
            +
            rails g graphql_auth:install
         | 
| 25 | 
            +
            ```
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Make sure to read all configurations present inside the file and fill them with your own configs.
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            ## Usage
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            Make 'JWT_SECRET_KEY' and 'APP_URL' available to ENV
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            ```
         | 
| 34 | 
            +
            JWT_SECRET_KEY=
         | 
| 35 | 
            +
            APP_URL=
         | 
| 36 | 
            +
            ```
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            Make sure the `Authorization` header is allowed in your api
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            ```
         | 
| 41 | 
            +
            Rails.application.config.middleware.insert_before 0, Rack::Cors do
         | 
| 42 | 
            +
              allow do
         | 
| 43 | 
            +
                origins '*'
         | 
| 44 | 
            +
                resource '*',
         | 
| 45 | 
            +
                         headers: %w(Authorization),
         | 
| 46 | 
            +
                         methods: :any,
         | 
| 47 | 
            +
                         expose: %w(Authorization),
         | 
| 48 | 
            +
                         max_age: 600
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| 51 | 
            +
            ``` 
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            Make sure to include `Graphql::AuthHelper` in your `GraphqlController`. A context method returning the current_user will be available
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            ```
         | 
| 56 | 
            +
            class GraphqlController < ActionController::API
         | 
| 57 | 
            +
              
         | 
| 58 | 
            +
              include Graphql::AuthHelper
         | 
| 59 | 
            +
              
         | 
| 60 | 
            +
              def execute
         | 
| 61 | 
            +
                variables = ensure_hash(params[:variables])
         | 
| 62 | 
            +
                query = params[:query]
         | 
| 63 | 
            +
                operation_name = params[:operationName]
         | 
| 64 | 
            +
                result = ::GraphqlSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
         | 
| 65 | 
            +
                render json: result
         | 
| 66 | 
            +
                
         | 
| 67 | 
            +
                ...
         | 
| 68 | 
            +
            ```
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            Make sure to implement `GraphqlAuth` in your MutationType``to make auth mutations available
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            ```
         | 
| 73 | 
            +
            class Types::MutationType < Types::BaseObject
         | 
| 74 | 
            +
              implements GraphqlAuth
         | 
| 75 | 
            +
            end
         | 
| 76 | 
            +
            ```
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            ## Customization
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            If you can to customize any mutation, make sure to update the configurations
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            ```
         | 
| 83 | 
            +
            GraphQL::Auth.configure do |config|
         | 
| 84 | 
            +
              # config.token_lifespan = 4.hours
         | 
| 85 | 
            +
              # config.jwt_secret_key = ENV['JWT_SECRET_KEY']
         | 
| 86 | 
            +
              # config.app_url = ENV['APP_URL']
         | 
| 87 | 
            +
             | 
| 88 | 
            +
              config.sign_in_mutation = ::Mutations::CustomSignIn
         | 
| 89 | 
            +
              
         | 
| 90 | 
            +
              ...
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            ```
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            ## Development
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `graphql-auth.gemspec`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            ## Contributing
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/o2web/graphql-auth. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            ## License
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            ## Code of Conduct
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            Everyone interacting in the GraphQL Auth project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/graphql-devise-auth/blob/master/CODE_OF_CONDUCT.md).
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #  forgotPassword(email: "email@example.com") {
         | 
| 5 | 
            +
            #     valid
         | 
| 6 | 
            +
            #   }
         | 
| 7 | 
            +
            # }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class Mutations::ForgotPassword < GraphQL::Schema::Mutation
         | 
| 10 | 
            +
              argument :email, String, required: true do
         | 
| 11 | 
            +
                description 'The email with forgotten password'
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              field :valid, Boolean, null: false
         | 
| 15 | 
            +
              
         | 
| 16 | 
            +
              def resolve(email:)
         | 
| 17 | 
            +
                user = User.find_by email: email
         | 
| 18 | 
            +
                user.send_reset_password_instructions if user.present?
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                { valid: true }
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #   resetPassword(resetPasswordToken: "token", password: "password", passwordConfirmation: "password") {
         | 
| 5 | 
            +
            #     valid
         | 
| 6 | 
            +
            #     errors {
         | 
| 7 | 
            +
            #       field
         | 
| 8 | 
            +
            #       message
         | 
| 9 | 
            +
            #     }
         | 
| 10 | 
            +
            #   }
         | 
| 11 | 
            +
            # }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            class Mutations::ResetPassword < GraphQL::Schema::Mutation
         | 
| 14 | 
            +
              argument :reset_password_token, String, required: true do
         | 
| 15 | 
            +
                description "Reset password token"
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              argument :password, String, required: true do
         | 
| 19 | 
            +
                description "New user's new password"
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              argument :password_confirmation, String, required: true do
         | 
| 23 | 
            +
                description "New user's new password confirmation"
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              field :valid, Boolean, null: false
         | 
| 27 | 
            +
              field :errors, [Types::Error], null: true
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              def resolve(args)
         | 
| 30 | 
            +
                user = User.reset_password_by_token args
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                if user.errors.any?
         | 
| 33 | 
            +
                  {
         | 
| 34 | 
            +
                    valid: false,
         | 
| 35 | 
            +
                    errors: user.errors.messages.map do |field, messages|
         | 
| 36 | 
            +
                      field = field == :reset_password_token ? :_error : field.to_s.camelize(:lower)
         | 
| 37 | 
            +
                      {
         | 
| 38 | 
            +
                        field: field,
         | 
| 39 | 
            +
                        message: messages.first.capitalize }
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  }
         | 
| 42 | 
            +
                else
         | 
| 43 | 
            +
                  { valid: true }
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #   signIn(email: "email@example.com", password: "password") {
         | 
| 5 | 
            +
            #     user {
         | 
| 6 | 
            +
            #       email
         | 
| 7 | 
            +
            #     }
         | 
| 8 | 
            +
            #     errors {
         | 
| 9 | 
            +
            #       field
         | 
| 10 | 
            +
            #       message
         | 
| 11 | 
            +
            #     }
         | 
| 12 | 
            +
            #   }
         | 
| 13 | 
            +
            # }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class Mutations::SignIn < GraphQL::Schema::Mutation
         | 
| 16 | 
            +
              argument :email, String, required: true do
         | 
| 17 | 
            +
                description "The user's email"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              argument :password, String, required: true do
         | 
| 21 | 
            +
                description "The user's password"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              field :user, Types::User, null: true
         | 
| 25 | 
            +
              field :errors, [Types::Error], null: true
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              def resolve(email:, password:)
         | 
| 28 | 
            +
                response = context[:response]
         | 
| 29 | 
            +
                user = User.find_by email: email
         | 
| 30 | 
            +
                valid_sign_in = user.present? && user.valid_password?(password)
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                if valid_sign_in
         | 
| 33 | 
            +
                  response.set_header 'Authorization', GraphQL::Auth::JwtManager.issue({ user: user.id }) # TODO use uuid
         | 
| 34 | 
            +
                  {
         | 
| 35 | 
            +
                    user: user
         | 
| 36 | 
            +
                  }
         | 
| 37 | 
            +
                else
         | 
| 38 | 
            +
                  {
         | 
| 39 | 
            +
                    errors: [
         | 
| 40 | 
            +
                      {
         | 
| 41 | 
            +
                        field: :_error,
         | 
| 42 | 
            +
                        message: I18n.t('devise.failure.invalid',
         | 
| 43 | 
            +
                                        authentication_keys: I18n.t('activerecord.attributes.user.email'))
         | 
| 44 | 
            +
                      }
         | 
| 45 | 
            +
                    ]
         | 
| 46 | 
            +
                  }
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #   signUp(email: "email@example.com", password: "password", passwordConfirmation: "password") {
         | 
| 5 | 
            +
            #     user {
         | 
| 6 | 
            +
            #       email
         | 
| 7 | 
            +
            #     }
         | 
| 8 | 
            +
            #     errors {
         | 
| 9 | 
            +
            #       field
         | 
| 10 | 
            +
            #       message
         | 
| 11 | 
            +
            #     }
         | 
| 12 | 
            +
            #   }
         | 
| 13 | 
            +
            # }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class Mutations::SignUp < GraphQL::Schema::Mutation
         | 
| 16 | 
            +
              argument :email, String, required: true do
         | 
| 17 | 
            +
                description "New user's email"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              argument :password, String, required: true do
         | 
| 21 | 
            +
                description "New user's password"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              argument :password_confirmation, String, required: true do
         | 
| 25 | 
            +
                description "New user's password confirmation"
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              field :user, Types::User, null: true
         | 
| 29 | 
            +
              field :errors, [Types::Error], null: true
         | 
| 30 | 
            +
              
         | 
| 31 | 
            +
              def resolve(args)
         | 
| 32 | 
            +
                response = context[:response]
         | 
| 33 | 
            +
                user = User.new args
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                if user.save
         | 
| 36 | 
            +
                  response.set_header 'Authorization', GraphQL::Auth::JwtManager.issue({ user: user.id }) # TODO use uuid
         | 
| 37 | 
            +
                  { user: user }
         | 
| 38 | 
            +
                else
         | 
| 39 | 
            +
                  {
         | 
| 40 | 
            +
                    errors: user.errors.messages.map do |field, messages|
         | 
| 41 | 
            +
                      { field: field.to_s.camelize(:lower), message: messages.first.capitalize }
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                  }
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #   updateAccount(current_password: "currentPassword", password: "newPassword", password_confirmation: "newPassword") {
         | 
| 5 | 
            +
            #     user {
         | 
| 6 | 
            +
            #       email
         | 
| 7 | 
            +
            #     }
         | 
| 8 | 
            +
            #     errors {
         | 
| 9 | 
            +
            #       field
         | 
| 10 | 
            +
            #       message
         | 
| 11 | 
            +
            #     }
         | 
| 12 | 
            +
            #   }
         | 
| 13 | 
            +
            # }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class Mutations::UpdateAccount < GraphQL::Schema::Mutation
         | 
| 16 | 
            +
              argument :current_password, String, required: true do
         | 
| 17 | 
            +
                description "User's current password"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
              argument :password, String, required: true do
         | 
| 21 | 
            +
                description "User's new password"
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
              
         | 
| 24 | 
            +
              argument :password_confirmation, String, required: true do
         | 
| 25 | 
            +
                description "User's new password confirmation"
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
              field :user, Types::User, null: true
         | 
| 29 | 
            +
              field :errors, [Types::Error], null: true
         | 
| 30 | 
            +
              
         | 
| 31 | 
            +
              def resolve(args)
         | 
| 32 | 
            +
                user = context[:current_user]
         | 
| 33 | 
            +
                user.update_with_password args
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                if user.errors.any?
         | 
| 36 | 
            +
                  {
         | 
| 37 | 
            +
                    errors: user.errors.messages.map do |field, messages|
         | 
| 38 | 
            +
                      { field: field.to_s.camelize(:lower), message: messages.first.capitalize }
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  }
         | 
| 41 | 
            +
                else
         | 
| 42 | 
            +
                  { user: user }
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # mutation {
         | 
| 4 | 
            +
            #   validateToken {
         | 
| 5 | 
            +
            #     valid
         | 
| 6 | 
            +
            #     user {
         | 
| 7 | 
            +
            #       email
         | 
| 8 | 
            +
            #     }
         | 
| 9 | 
            +
            #   }
         | 
| 10 | 
            +
            # }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class Mutations::ValidateToken < GraphQL::Schema::Mutation
         | 
| 13 | 
            +
              field :valid, Boolean, null: false
         | 
| 14 | 
            +
              field :user, Types::User, null: true
         | 
| 15 | 
            +
              
         | 
| 16 | 
            +
              def resolve()
         | 
| 17 | 
            +
                user = context[:current_user]
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                {
         | 
| 20 | 
            +
                  valid: user.present?,
         | 
| 21 | 
            +
                  user: user,
         | 
| 22 | 
            +
                }
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Types::Error < Types::BaseObject
         | 
| 4 | 
            +
              description 'Form error'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              field :field, String, null: false do
         | 
| 7 | 
            +
                description 'Field of the error'
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              field :message, String, null: false do
         | 
| 11 | 
            +
                description 'Error message'
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
            end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            # implements GraphQLAuth in in Types::MutationType to access auth mutations
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Types::GraphqlAuth
         | 
| 4 | 
            +
              include GraphQL::Schema::Interface
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              field :sign_in, mutation: GraphQL::Auth.configuration.sign_in_mutation
         | 
| 7 | 
            +
              field :sign_up, mutation: GraphQL::Auth.configuration.sign_up_mutation
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              field :forgot_password, mutation: GraphQL::Auth.configuration.forgot_password_mutation
         | 
| 10 | 
            +
              field :reset_password, mutation: GraphQL::Auth.configuration.reset_password_mutation
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              field :update_account, mutation: GraphQL::Auth.configuration.update_account_mutation
         | 
| 13 | 
            +
              
         | 
| 14 | 
            +
              field :validate_token, mutation: GraphQL::Auth.configuration.validate_token_mutation
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # include this helper in GraphqlController to use context method so that current_user will be available
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # ::GraphqlSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Graphql
         | 
| 6 | 
            +
              module AuthHelper
         | 
| 7 | 
            +
                def context
         | 
| 8 | 
            +
                  {
         | 
| 9 | 
            +
                    current_user: current_user,
         | 
| 10 | 
            +
                    response: response,
         | 
| 11 | 
            +
                  }
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              
         | 
| 14 | 
            +
                def current_user
         | 
| 15 | 
            +
                  return if request.headers['Authorization'].nil?
         | 
| 16 | 
            +
                  
         | 
| 17 | 
            +
                  decrypted_token = GraphQL::Auth::JwtManager.decode(request.headers['Authorization'])
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                  user_id = decrypted_token['user']
         | 
| 20 | 
            +
                  user = User.find_by id: user_id  # TODO use uuid
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # update token if user is found with token
         | 
| 23 | 
            +
                  response.set_header 'Authorization', GraphQL::Auth::JwtManager.issue({ user: user.id }) if user.present?
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  user
         | 
| 26 | 
            +
                rescue JWT::ExpiredSignature
         | 
| 27 | 
            +
                  nil
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,8 @@ | |
| 1 | 
            +
            <p>Hello <%= @resource.email %>!</p>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            <p>Someone has requested a link to change your password. You can do this through the link below.</p>
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            <p><%= link_to 'Change my password', GraphQL::Auth::ResetPassword.url(@token) %></p>
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            <p>If you didn't request this, please ignore this email.</p>
         | 
| 8 | 
            +
            <p>Your password won't change until you access the link above and create a new one.</p>
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            module GraphqlAuth
         | 
| 2 | 
            +
              module Generators
         | 
| 3 | 
            +
                class InstallGenerator < Rails::Generators::Base
         | 
| 4 | 
            +
                  source_root File.expand_path('../templates', __FILE__)
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def copy_configuration
         | 
| 7 | 
            +
                    template 'initializer.rb', 'config/initializers/graphql_auth.rb'
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            GraphQL::Auth.configure do |config|
         | 
| 2 | 
            +
              # config.token_lifespan = 4.hours
         | 
| 3 | 
            +
              # config.jwt_secret_key = ENV['JWT_SECRET_KEY']
         | 
| 4 | 
            +
              # config.app_url = ENV['APP_URL']
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              # config.sign_in_mutation = ::Mutations::SignIn
         | 
| 7 | 
            +
              # config.sign_up_mutation = ::Mutations::SignUp
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              # config.forgot_password_mutation = ::Mutations::ForgotPassword
         | 
| 10 | 
            +
              # config.reset_password_mutation = ::Mutations::ResetPassword
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              # config.update_account_mutation = ::Mutations::UpdateAccount
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # config.validate_token_mutation = ::Mutations::ValidateToken
         | 
| 15 | 
            +
            end
         | 
    
        data/lib/graphql-auth.rb
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            require 'graphql-auth/configuration'
         | 
| 2 | 
            +
            require 'graphql-auth/engine'
         | 
| 3 | 
            +
            require 'graphql-auth/reset_password'
         | 
| 4 | 
            +
            require 'graphql-auth/jwt_manager'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module GraphQL
         | 
| 7 | 
            +
              module Auth
         | 
| 8 | 
            +
                class << self
         | 
| 9 | 
            +
                  attr_accessor :configuration
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def self.configure
         | 
| 13 | 
            +
                  @configuration ||= Configuration.new
         | 
| 14 | 
            +
                  yield(configuration)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module GraphQL
         | 
| 2 | 
            +
              module Auth
         | 
| 3 | 
            +
                class Configuration
         | 
| 4 | 
            +
                  attr_accessor :token_lifespan,
         | 
| 5 | 
            +
                                :jwt_secret_key,
         | 
| 6 | 
            +
                                :app_url,
         | 
| 7 | 
            +
                                :sign_in_mutation,
         | 
| 8 | 
            +
                                :sign_up_mutation,
         | 
| 9 | 
            +
                                :forgot_password_mutation,
         | 
| 10 | 
            +
                                :reset_password_mutation,
         | 
| 11 | 
            +
                                :update_account_mutation,
         | 
| 12 | 
            +
                                :validate_token_mutation
         | 
| 13 | 
            +
                
         | 
| 14 | 
            +
                  def initialize
         | 
| 15 | 
            +
                    @token_lifespan = 4.hours
         | 
| 16 | 
            +
                    @jwt_secret_key = ENV['JWT_SECRET_KEY']
         | 
| 17 | 
            +
                    @app_url = ENV['APP_URL']
         | 
| 18 | 
            +
                    
         | 
| 19 | 
            +
                    @sign_in_mutation = ::Mutations::SignIn
         | 
| 20 | 
            +
                    @sign_up_mutation = ::Mutations::SignUp
         | 
| 21 | 
            +
                  
         | 
| 22 | 
            +
                    @forgot_password_mutation = ::Mutations::ForgotPassword
         | 
| 23 | 
            +
                    @reset_password_mutation = ::Mutations::ResetPassword
         | 
| 24 | 
            +
                  
         | 
| 25 | 
            +
                    @update_account_mutation = ::Mutations::UpdateAccount
         | 
| 26 | 
            +
                  
         | 
| 27 | 
            +
                    @validate_token_mutation = ::Mutations::ValidateToken
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'jwt'
         | 
| 2 | 
            +
            require 'graphql-auth'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module GraphQL
         | 
| 5 | 
            +
              module Auth
         | 
| 6 | 
            +
                class JwtManager
         | 
| 7 | 
            +
                  ALGORITHM = 'HS256'
         | 
| 8 | 
            +
                  TYPE = 'Bearer'
         | 
| 9 | 
            +
                  
         | 
| 10 | 
            +
                  class << self
         | 
| 11 | 
            +
                    def issue(payload)
         | 
| 12 | 
            +
                      token = JWT.encode payload.merge(expiration),
         | 
| 13 | 
            +
                                         auth_secret,
         | 
| 14 | 
            +
                                         ALGORITHM
         | 
| 15 | 
            +
                      set_type token
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
                
         | 
| 18 | 
            +
                    def decode(token)
         | 
| 19 | 
            +
                      token = extract_token token
         | 
| 20 | 
            +
                      decrypted_token = JWT.decode token,
         | 
| 21 | 
            +
                                                   auth_secret,
         | 
| 22 | 
            +
                                                   true,
         | 
| 23 | 
            +
                                                   { algorithm: ALGORITHM }
         | 
| 24 | 
            +
                      decrypted_token.first
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    private
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    def auth_secret
         | 
| 30 | 
            +
                      GraphQL::Auth.configuration.jwt_secret_key
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def set_type(token)
         | 
| 34 | 
            +
                      "#{TYPE} #{token}"
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def extract_token(token)
         | 
| 38 | 
            +
                      token.gsub "#{TYPE} ", ''
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                    
         | 
| 41 | 
            +
                    def expiration
         | 
| 42 | 
            +
                      exp = Time.now.to_i + GraphQL::Auth.configuration.token_lifespan
         | 
| 43 | 
            +
                      { exp: exp }
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            require 'jwt'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module GraphQL
         | 
| 4 | 
            +
              module Auth
         | 
| 5 | 
            +
                class ResetPassword
         | 
| 6 | 
            +
                  class << self
         | 
| 7 | 
            +
                    def url(token)
         | 
| 8 | 
            +
                      url = I18n.locale === :fr ? 'nouveau-mot-de-passe' : 'new-password'
         | 
| 9 | 
            +
                      "#{GraphQL::Auth.configuration.app_url}/#{I18n.locale}/#{url}/#{token}"
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,135 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: graphql-auth
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Guillaume Ferland
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2018-10-10 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: bundler
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '1.15'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.15'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rake
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '10.0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '10.0'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: graphql
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: 1.8.5
         | 
| 48 | 
            +
              type: :runtime
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: 1.8.5
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: devise
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - "~>"
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: 4.4.3
         | 
| 62 | 
            +
              type: :runtime
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - "~>"
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: 4.4.3
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: jwt
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - "~>"
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: 1.5.6
         | 
| 76 | 
            +
              type: :runtime
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - "~>"
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: 1.5.6
         | 
| 83 | 
            +
            description: GraphQL + JWT + Devise
         | 
| 84 | 
            +
            email:
         | 
| 85 | 
            +
            - ferland182@gmail.com
         | 
| 86 | 
            +
            executables: []
         | 
| 87 | 
            +
            extensions: []
         | 
| 88 | 
            +
            extra_rdoc_files: []
         | 
| 89 | 
            +
            files:
         | 
| 90 | 
            +
            - Gemfile
         | 
| 91 | 
            +
            - README.md
         | 
| 92 | 
            +
            - app/graphql/mutations/forgot_password.rb
         | 
| 93 | 
            +
            - app/graphql/mutations/reset_password.rb
         | 
| 94 | 
            +
            - app/graphql/mutations/sign_in.rb
         | 
| 95 | 
            +
            - app/graphql/mutations/sign_up.rb
         | 
| 96 | 
            +
            - app/graphql/mutations/update_account.rb
         | 
| 97 | 
            +
            - app/graphql/mutations/validate_token.rb
         | 
| 98 | 
            +
            - app/graphql/types/error.rb
         | 
| 99 | 
            +
            - app/graphql/types/graphql_auth.rb
         | 
| 100 | 
            +
            - app/graphql/types/user.rb
         | 
| 101 | 
            +
            - app/helpers/graphql/auth_helper.rb
         | 
| 102 | 
            +
            - app/views/devise/mailer/reset_password_instructions.html.erb
         | 
| 103 | 
            +
            - lib/generators/graphql_auth/install_generator.rb
         | 
| 104 | 
            +
            - lib/generators/graphql_auth/templates/initializer.rb
         | 
| 105 | 
            +
            - lib/graphql-auth.rb
         | 
| 106 | 
            +
            - lib/graphql-auth/configuration.rb
         | 
| 107 | 
            +
            - lib/graphql-auth/engine.rb
         | 
| 108 | 
            +
            - lib/graphql-auth/jwt_manager.rb
         | 
| 109 | 
            +
            - lib/graphql-auth/reset_password.rb
         | 
| 110 | 
            +
            homepage: https://github.com/o2web/graphql-auth
         | 
| 111 | 
            +
            licenses:
         | 
| 112 | 
            +
            - MIT
         | 
| 113 | 
            +
            metadata: {}
         | 
| 114 | 
            +
            post_install_message: 
         | 
| 115 | 
            +
            rdoc_options: []
         | 
| 116 | 
            +
            require_paths:
         | 
| 117 | 
            +
            - app
         | 
| 118 | 
            +
            - lib
         | 
| 119 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 120 | 
            +
              requirements:
         | 
| 121 | 
            +
              - - ">="
         | 
| 122 | 
            +
                - !ruby/object:Gem::Version
         | 
| 123 | 
            +
                  version: '0'
         | 
| 124 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 125 | 
            +
              requirements:
         | 
| 126 | 
            +
              - - ">="
         | 
| 127 | 
            +
                - !ruby/object:Gem::Version
         | 
| 128 | 
            +
                  version: '0'
         | 
| 129 | 
            +
            requirements: []
         | 
| 130 | 
            +
            rubyforge_project: 
         | 
| 131 | 
            +
            rubygems_version: 2.6.13
         | 
| 132 | 
            +
            signing_key: 
         | 
| 133 | 
            +
            specification_version: 4
         | 
| 134 | 
            +
            summary: GraphQL + JWT + Devise
         | 
| 135 | 
            +
            test_files: []
         |