diff --git a/.gitignore b/.gitignore index 0cb6eeb..716e11a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,15 @@ /pkg/ /spec/reports/ /tmp/ +.DS_Store + +spec/dummy/db/*.sqlite3 +spec/dummy/db/*.sqlite3-journal +spec/dummy/log/*.log +spec/dummy/node_modules/ +spec/dummy/yarn-error.log +spec/dummy/storage/ +spec/dummy/tmp/ + +.rspec_status +.tool-versions \ No newline at end of file diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/.rspec_status b/.rspec_status new file mode 100644 index 0000000..e69de29 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9be74eb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +sudo: false +language: ruby +before_install: gem install bundler -v 1.17.2 +script: + - bundle exec rake db:test:prepare + - bundle exec rake +matrix: + include: + - gemfile: graphql-1.8.gemfile + env: GRAPHQL_RUBY_VERSION=1_8 CI=true + rvm: 2.6.1 + - gemfile: graphql-1.8.gemfile + env: GRAPHQL_RUBY_VERSION=1_8 CI=true + rvm: 2.5.3 + - gemfile: graphql-1.8.gemfile + env: GRAPHQL_RUBY_VERSION=1_8 CI=true + rvm: 2.4.5 \ No newline at end of file diff --git a/Gemfile b/Gemfile index 7ccca28..219f362 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,10 @@ -source "https://rubygems.org" +source 'https://rubygems.org' -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } +gem 'byebug' -# Specify your gem's dependencies in graphql-devise-auth.gemspec -gemspec +gem 'rails', '~> 5.2' + +gem 'graphql', '~> 1.8.4' + +# Specify your gem's dependencies in graphql-auth.gemspec +gemspec \ No newline at end of file diff --git a/README.md b/README.md index ca0ea07..c00dcf7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# GraphQL Auth +# GraphQL Auth + +[![Build Status](https://travis-ci.org/o2web/graphql-auth.svg?branch=master)](https://travis-ci.org/o2web/graphql-auth) [![Maintainability](https://api.codeclimate.com/v1/badges/7e2515bb59f0b205a603/maintainability)](https://codeclimate.com/github/o2web/graphql-auth/maintainability) 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. @@ -26,14 +28,14 @@ rails g graphql_auth:install Make sure to read all configurations present inside the file and fill them with your own configs. -## Devise gem +## Devise gem -Use Devise with a User model and skip all route + Use Devise with a User model and skip all route -``` -Rails.application.routes.draw do - devise_for :users, skip: :all -end + ``` +Rails.application.routes.draw do + devise_for :users, skip: :all +end ``` ## Usage diff --git a/Rakefile b/Rakefile index 43022f7..299de3d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,2 +1,18 @@ -require "bundler/gem_tasks" -task :default => :spec +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__) +load 'rails/tasks/engine.rake' + +require 'rake' +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = Dir.glob('spec/**/*_spec.rb') + t.rspec_opts = '--format documentation' +end + +task default: :spec \ No newline at end of file diff --git a/app/graphql/mutations/auth/forgot_password.rb b/app/graphql/mutations/auth/forgot_password.rb index a3a206a..9b96df1 100644 --- a/app/graphql/mutations/auth/forgot_password.rb +++ b/app/graphql/mutations/auth/forgot_password.rb @@ -1,12 +1,5 @@ # frozen_string_literal: true -# mutation { -# forgotPassword(email: "email@example.com") { -# valid -# success -# } -# } - class Mutations::Auth::ForgotPassword < GraphQL::Schema::Mutation argument :email, String, required: true do description 'The email with forgotten password' @@ -14,6 +7,7 @@ class Mutations::Auth::ForgotPassword < GraphQL::Schema::Mutation field :errors, [::Types::Auth::Error], null: false field :success, Boolean, null: false + field :valid, Boolean, null: false def resolve(email:) user = User.find_by email: email diff --git a/app/graphql/mutations/auth/reset_password.rb b/app/graphql/mutations/auth/reset_password.rb index bce360b..a1eb543 100644 --- a/app/graphql/mutations/auth/reset_password.rb +++ b/app/graphql/mutations/auth/reset_password.rb @@ -1,15 +1,5 @@ # frozen_string_literal: true -# mutation { -# resetPassword(resetPasswordToken: "token", password: "password", passwordConfirmation: "password") { -# success -# errors { -# field -# message -# } -# } -# } - class Mutations::Auth::ResetPassword < GraphQL::Schema::Mutation argument :reset_password_token, String, required: true do description "Reset password token" diff --git a/app/graphql/mutations/auth/sign_in.rb b/app/graphql/mutations/auth/sign_in.rb index 3dc9475..f6e5ebf 100644 --- a/app/graphql/mutations/auth/sign_in.rb +++ b/app/graphql/mutations/auth/sign_in.rb @@ -1,18 +1,5 @@ # frozen_string_literal: true -# mutation { -# signIn(email: "email@example.com", password: "password") { -# success -# user { -# email -# } -# errors { -# field -# message -# } -# } -# } - class Mutations::Auth::SignIn < GraphQL::Schema::Mutation include ::Graphql::TokenHelper diff --git a/app/graphql/mutations/auth/sign_up.rb b/app/graphql/mutations/auth/sign_up.rb index 411f20a..a62a837 100644 --- a/app/graphql/mutations/auth/sign_up.rb +++ b/app/graphql/mutations/auth/sign_up.rb @@ -1,18 +1,5 @@ # frozen_string_literal: true -# mutation { -# signUp(email: "email@example.com", password: "password", passwordConfirmation: "password") { -# success -# user { -# email -# } -# errors { -# field -# message -# } -# } -# } - class Mutations::Auth::SignUp < GraphQL::Schema::Mutation include ::Graphql::TokenHelper diff --git a/app/graphql/mutations/auth/update_account.rb b/app/graphql/mutations/auth/update_account.rb index 8b35c19..d5f3e56 100644 --- a/app/graphql/mutations/auth/update_account.rb +++ b/app/graphql/mutations/auth/update_account.rb @@ -1,18 +1,5 @@ # frozen_string_literal: true -# mutation { -# updateAccount(current_password: "currentPassword", password: "newPassword", password_confirmation: "newPassword") { -# success -# user { -# email -# } -# errors { -# field -# message -# } -# } -# } - class Mutations::Auth::UpdateAccount < GraphQL::Schema::Mutation argument :current_password, String, required: true do description "User's current password" @@ -32,6 +19,17 @@ class Mutations::Auth::UpdateAccount < GraphQL::Schema::Mutation def resolve(args) user = context[:current_user] + + if user.blank? + return { + errors: [ + { field: :_error, message: I18n.t('devise.failure.unauthenticated') } + ], + success: false, + user: nil + } + end + user.update_with_password args if user.errors.any? diff --git a/app/graphql/mutations/auth/validate_token.rb b/app/graphql/mutations/auth/validate_token.rb index 2fdec50..b38f006 100644 --- a/app/graphql/mutations/auth/validate_token.rb +++ b/app/graphql/mutations/auth/validate_token.rb @@ -1,15 +1,5 @@ # frozen_string_literal: true -# mutation { -# validateToken { -# success -# valid -# user { -# email -# } -# } -# } - class Mutations::Auth::ValidateToken < GraphQL::Schema::Mutation field :errors, [::Types::Auth::Error], null: false field :success, Boolean, null: false @@ -26,4 +16,4 @@ def resolve valid: user.present?, } end -end +end \ No newline at end of file diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..7964b4b --- /dev/null +++ b/bin/rails @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path('..', __dir__) +ENGINE_PATH = File.expand_path('../lib/graphql-auth/engine', __dir__) +APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' \ No newline at end of file diff --git a/lib/generators/graphql_auth/templates/add_refresh_token_to_user.rb b/db/migrate/20190108151146_add_refresh_token_to_user.rb similarity index 100% rename from lib/generators/graphql_auth/templates/add_refresh_token_to_user.rb rename to db/migrate/20190108151146_add_refresh_token_to_user.rb diff --git a/graphql-1.8.gemfile b/graphql-1.8.gemfile new file mode 100644 index 0000000..40f76c5 --- /dev/null +++ b/graphql-1.8.gemfile @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +gem 'byebug' +gem 'coveralls' + +gem 'rails', '~> 5.2' +gem 'graphql', '~> 1.8.4' + +gemspec \ No newline at end of file diff --git a/graphql-auth.gemspec b/graphql-auth.gemspec index 23aff56..9cccec0 100644 --- a/graphql-auth.gemspec +++ b/graphql-auth.gemspec @@ -1,24 +1,30 @@ -# coding: utf-8 +$:.push File.expand_path("lib", __dir__) + +require "graphql-auth/version" Gem::Specification.new do |spec| spec.name = 'graphql-auth' - spec.version = '0.2.2' + spec.version = GraphQL::Auth::VERSION spec.authors = ['Guillaume Ferland'] spec.email = ['ferland182@gmail.com'] - spec.platform = Gem::Platform::RUBY + spec.platform = Gem::Platform::RUBY spec.summary = %q{GraphQL + JWT + Devise} spec.description = %q{GraphQL + JWT + Devise} spec.homepage = 'https://github.com/o2web/graphql-auth' spec.license = 'MIT' - # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' - # to allow pushing to a single host or delete this section to allow pushing to any host. - spec.files = Dir['README.md', 'Gemfile', '{app,lib,vendor}/**/*'] - spec.require_paths = %w(app lib) + spec.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] - spec.add_development_dependency 'bundler', '~> 1.15' - spec.add_development_dependency 'rake', '~> 10.0' + spec.required_ruby_version = '>= 2.4.5' + + spec.add_dependency "rails", "~> 5.1" spec.add_dependency 'graphql', '~> 1.8' spec.add_dependency 'devise', '~> 4.4' spec.add_dependency 'jwt', '~> 1.5' -end + + spec.add_development_dependency 'sqlite3', '~> 1.3.6' + spec.add_development_dependency 'bundler', '~> 1.15' + spec.add_development_dependency 'rake', '~> 10.0' + spec.add_development_dependency 'rspec', '~> 3.0' + spec.add_development_dependency 'database_cleaner' +end \ No newline at end of file diff --git a/lib/generators/graphql_auth/install_generator.rb b/lib/generators/graphql_auth/install_generator.rb index bd674a2..8859a3a 100644 --- a/lib/generators/graphql_auth/install_generator.rb +++ b/lib/generators/graphql_auth/install_generator.rb @@ -4,8 +4,11 @@ class InstallGenerator < Rails::Generators::Base source_root File.expand_path('../templates', __FILE__) def copy_configuration - template 'initializer.rb', 'config/initializers/graphql_auth.rb' - template 'add_refresh_token_to_user.rb', "db/migrate/#{Time.now.strftime('%Y%m%d%H%M%S')}_add_refresh_token_to_user.rb" + template 'graphql_auth.rb.erb', 'config/initializers/graphql_auth.rb' + end + + def rake_db + rake("railties:install:migrations") end end end diff --git a/lib/generators/graphql_auth/templates/initializer.rb b/lib/generators/graphql_auth/templates/graphql_auth.rb.erb similarity index 99% rename from lib/generators/graphql_auth/templates/initializer.rb rename to lib/generators/graphql_auth/templates/graphql_auth.rb.erb index ab05327..e0f03ca 100644 --- a/lib/generators/graphql_auth/templates/initializer.rb +++ b/lib/generators/graphql_auth/templates/graphql_auth.rb.erb @@ -14,4 +14,4 @@ # config.update_account_mutation = ::Mutations::Auth::UpdateAccount # config.validate_token_mutation = ::Mutations::Auth::ValidateToken -end +end \ No newline at end of file diff --git a/lib/graphql-auth.rb b/lib/graphql-auth.rb index 377326b..b90bc53 100644 --- a/lib/graphql-auth.rb +++ b/lib/graphql-auth.rb @@ -1,4 +1,5 @@ require 'devise' +require 'graphql' require 'graphql-auth/configuration' require 'graphql-auth/engine' require 'graphql-auth/reset_password' diff --git a/lib/graphql-auth/engine.rb b/lib/graphql-auth/engine.rb index 1904355..d85710c 100644 --- a/lib/graphql-auth/engine.rb +++ b/lib/graphql-auth/engine.rb @@ -1,7 +1,9 @@ module GraphQL module Auth class Engine < ::Rails::Engine + isolate_namespace GraphQL::Auth + config.autoload_paths += Dir["#{config.root}/app/**/"] end end -end +end \ No newline at end of file diff --git a/lib/graphql-auth/version.rb b/lib/graphql-auth/version.rb new file mode 100644 index 0000000..689ecf9 --- /dev/null +++ b/lib/graphql-auth/version.rb @@ -0,0 +1,5 @@ +module GraphQL + module Auth + VERSION = '0.3.0' + end +end \ No newline at end of file diff --git a/spec/dummy/Rakefile b/spec/dummy/Rakefile new file mode 100644 index 0000000..e85f913 --- /dev/null +++ b/spec/dummy/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/spec/dummy/app/channels/application_cable/channel.rb b/spec/dummy/app/channels/application_cable/channel.rb new file mode 100644 index 0000000..d672697 --- /dev/null +++ b/spec/dummy/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/spec/dummy/app/channels/application_cable/connection.rb b/spec/dummy/app/channels/application_cable/connection.rb new file mode 100644 index 0000000..0ff5442 --- /dev/null +++ b/spec/dummy/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/spec/dummy/app/controllers/application_controller.rb b/spec/dummy/app/controllers/application_controller.rb new file mode 100644 index 0000000..4ac8823 --- /dev/null +++ b/spec/dummy/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::API +end diff --git a/spec/dummy/app/controllers/concerns/.keep b/spec/dummy/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/controllers/graphql_controller.rb b/spec/dummy/app/controllers/graphql_controller.rb new file mode 100644 index 0000000..ae04180 --- /dev/null +++ b/spec/dummy/app/controllers/graphql_controller.rb @@ -0,0 +1,43 @@ +class GraphqlController < ActionController::API + include Graphql::AuthHelper + + def execute + variables = ensure_hash(params[:variables]) + query = params[:query] + operation_name = params[:operationName] + result = GraphqlSchema.execute query, variables: variables, + context: context, + operation_name: operation_name + render json: result + rescue => error + raise error unless Rails.env.development? + handle_error_in_development error + end + + private + + # Handle form data, JSON body, or a blank value + def ensure_hash(ambiguous_param) + case ambiguous_param + when String + if ambiguous_param.present? + ensure_hash(JSON.parse(ambiguous_param)) + else + {} + end + when Hash, ActionController::Parameters + ambiguous_param + when nil + {} + else + raise ArgumentError, "Unexpected parameter: #{ambiguous_param}" + end + end + + def handle_error_in_development(e) + logger.error e.message + logger.error e.backtrace.join("\n") + + render json: { error: { message: e.message, backtrace: e.backtrace }, data: {} }, status: 500 + end +end \ No newline at end of file diff --git a/spec/dummy/app/graphql/graphql_schema.rb b/spec/dummy/app/graphql/graphql_schema.rb new file mode 100644 index 0000000..39d1556 --- /dev/null +++ b/spec/dummy/app/graphql/graphql_schema.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class GraphqlSchema < GraphQL::Schema + mutation Types::MutationType + query Types::QueryType +end + +GraphqlSchema.graphql_definition diff --git a/spec/dummy/app/graphql/types/.keep b/spec/dummy/app/graphql/types/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/graphql/types/base_enum.rb b/spec/dummy/app/graphql/types/base_enum.rb new file mode 100644 index 0000000..cf43fea --- /dev/null +++ b/spec/dummy/app/graphql/types/base_enum.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class BaseEnum < GraphQL::Schema::Enum + end +end diff --git a/spec/dummy/app/graphql/types/base_input_object.rb b/spec/dummy/app/graphql/types/base_input_object.rb new file mode 100644 index 0000000..aebed03 --- /dev/null +++ b/spec/dummy/app/graphql/types/base_input_object.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class BaseInputObject < GraphQL::Schema::InputObject + end +end diff --git a/spec/dummy/app/graphql/types/base_interface.rb b/spec/dummy/app/graphql/types/base_interface.rb new file mode 100644 index 0000000..3451a19 --- /dev/null +++ b/spec/dummy/app/graphql/types/base_interface.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Types + module BaseInterface + include GraphQL::Schema::Interface + end +end diff --git a/spec/dummy/app/graphql/types/base_object.rb b/spec/dummy/app/graphql/types/base_object.rb new file mode 100644 index 0000000..80bc9cb --- /dev/null +++ b/spec/dummy/app/graphql/types/base_object.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class BaseObject < GraphQL::Schema::Object + end +end diff --git a/spec/dummy/app/graphql/types/base_scalar.rb b/spec/dummy/app/graphql/types/base_scalar.rb new file mode 100644 index 0000000..719bc80 --- /dev/null +++ b/spec/dummy/app/graphql/types/base_scalar.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class BaseScalar < GraphQL::Schema::Scalar + end +end diff --git a/spec/dummy/app/graphql/types/base_union.rb b/spec/dummy/app/graphql/types/base_union.rb new file mode 100644 index 0000000..30a5668 --- /dev/null +++ b/spec/dummy/app/graphql/types/base_union.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class BaseUnion < GraphQL::Schema::Union + end +end diff --git a/spec/dummy/app/graphql/types/interfaces/active_record.rb b/spec/dummy/app/graphql/types/interfaces/active_record.rb new file mode 100644 index 0000000..75f181c --- /dev/null +++ b/spec/dummy/app/graphql/types/interfaces/active_record.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Types::Interfaces::ActiveRecord + include Types::Interfaces::Base + + field :id, ID, null: false +end diff --git a/spec/dummy/app/graphql/types/interfaces/base.rb b/spec/dummy/app/graphql/types/interfaces/base.rb new file mode 100644 index 0000000..4881f40 --- /dev/null +++ b/spec/dummy/app/graphql/types/interfaces/base.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Types::Interfaces::Base + include GraphQL::Schema::Interface +end diff --git a/spec/dummy/app/graphql/types/mutation_type.rb b/spec/dummy/app/graphql/types/mutation_type.rb new file mode 100644 index 0000000..8df5b0b --- /dev/null +++ b/spec/dummy/app/graphql/types/mutation_type.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Types + class MutationType < Types::BaseObject + implements ::Types::GraphqlAuth + end +end diff --git a/spec/dummy/app/graphql/types/query_type.rb b/spec/dummy/app/graphql/types/query_type.rb new file mode 100644 index 0000000..a5b775a --- /dev/null +++ b/spec/dummy/app/graphql/types/query_type.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module Types + class QueryType < Types::BaseObject + end +end diff --git a/spec/dummy/app/jobs/application_job.rb b/spec/dummy/app/jobs/application_job.rb new file mode 100644 index 0000000..a009ace --- /dev/null +++ b/spec/dummy/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/spec/dummy/app/mailers/application_mailer.rb b/spec/dummy/app/mailers/application_mailer.rb new file mode 100644 index 0000000..286b223 --- /dev/null +++ b/spec/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/spec/dummy/app/models/application_record.rb b/spec/dummy/app/models/application_record.rb new file mode 100644 index 0000000..10a4cba --- /dev/null +++ b/spec/dummy/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/spec/dummy/app/models/concerns/.keep b/spec/dummy/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/app/models/user.rb b/spec/dummy/app/models/user.rb new file mode 100644 index 0000000..22e7150 --- /dev/null +++ b/spec/dummy/app/models/user.rb @@ -0,0 +1,10 @@ +require 'devise' + +class User < ApplicationRecord + extend Devise::Models + + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :validatable +end diff --git a/spec/dummy/app/views/layouts/mailer.html.erb b/spec/dummy/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..cbd34d2 --- /dev/null +++ b/spec/dummy/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/spec/dummy/app/views/layouts/mailer.text.erb b/spec/dummy/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/spec/dummy/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/spec/dummy/bin/bundle b/spec/dummy/bin/bundle new file mode 100755 index 0000000..f19acf5 --- /dev/null +++ b/spec/dummy/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/spec/dummy/bin/rails b/spec/dummy/bin/rails new file mode 100755 index 0000000..0739660 --- /dev/null +++ b/spec/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/spec/dummy/bin/rake b/spec/dummy/bin/rake new file mode 100755 index 0000000..1724048 --- /dev/null +++ b/spec/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/spec/dummy/bin/setup b/spec/dummy/bin/setup new file mode 100755 index 0000000..94fd4d7 --- /dev/null +++ b/spec/dummy/bin/setup @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/spec/dummy/bin/update b/spec/dummy/bin/update new file mode 100755 index 0000000..58bfaed --- /dev/null +++ b/spec/dummy/bin/update @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/spec/dummy/bin/yarn b/spec/dummy/bin/yarn new file mode 100755 index 0000000..460dd56 --- /dev/null +++ b/spec/dummy/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + begin + exec "yarnpkg", *ARGV + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/spec/dummy/config.ru b/spec/dummy/config.ru new file mode 100644 index 0000000..f7ba0b5 --- /dev/null +++ b/spec/dummy/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb new file mode 100644 index 0000000..2cbcf67 --- /dev/null +++ b/spec/dummy/config/application.rb @@ -0,0 +1,18 @@ +require_relative 'boot' + +require 'rails/all' + +Bundler.require(*Rails.groups) +require 'graphql-auth' + +module Dummy + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.2 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. + end +end \ No newline at end of file diff --git a/spec/dummy/config/boot.rb b/spec/dummy/config/boot.rb new file mode 100644 index 0000000..bdb5f06 --- /dev/null +++ b/spec/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) \ No newline at end of file diff --git a/spec/dummy/config/cable.yml b/spec/dummy/config/cable.yml new file mode 100644 index 0000000..1cd0f83 --- /dev/null +++ b/spec/dummy/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: dummy_production diff --git a/spec/dummy/config/database.yml b/spec/dummy/config/database.yml new file mode 100644 index 0000000..0d02f24 --- /dev/null +++ b/spec/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/spec/dummy/config/environment.rb b/spec/dummy/config/environment.rb new file mode 100644 index 0000000..426333b --- /dev/null +++ b/spec/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/spec/dummy/config/environments/development.rb b/spec/dummy/config/environments/development.rb new file mode 100644 index 0000000..366e75a --- /dev/null +++ b/spec/dummy/config/environments/development.rb @@ -0,0 +1,61 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/spec/dummy/config/environments/production.rb b/spec/dummy/config/environments/production.rb new file mode 100644 index 0000000..9ea5ad2 --- /dev/null +++ b/spec/dummy/config/environments/production.rb @@ -0,0 +1,94 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_#{Rails.env}" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb new file mode 100644 index 0000000..0a38fd3 --- /dev/null +++ b/spec/dummy/config/environments/test.rb @@ -0,0 +1,46 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/spec/dummy/config/initializers/application_controller_renderer.rb b/spec/dummy/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000..89d2efa --- /dev/null +++ b/spec/dummy/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/spec/dummy/config/initializers/assets.rb b/spec/dummy/config/initializers/assets.rb new file mode 100644 index 0000000..4b828e8 --- /dev/null +++ b/spec/dummy/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/spec/dummy/config/initializers/backtrace_silencers.rb b/spec/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/spec/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/spec/dummy/config/initializers/content_security_policy.rb b/spec/dummy/config/initializers/content_security_policy.rb new file mode 100644 index 0000000..d3bcaa5 --- /dev/null +++ b/spec/dummy/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/spec/dummy/config/initializers/cookies_serializer.rb b/spec/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000..5a6a32d --- /dev/null +++ b/spec/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/spec/dummy/config/initializers/filter_parameter_logging.rb b/spec/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4a994e1 --- /dev/null +++ b/spec/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/spec/dummy/config/initializers/graphql_auth.rb b/spec/dummy/config/initializers/graphql_auth.rb new file mode 100644 index 0000000..e0f03ca --- /dev/null +++ b/spec/dummy/config/initializers/graphql_auth.rb @@ -0,0 +1,17 @@ +GraphQL::Auth.configure do |config| + # config.token_lifespan = 4.hours + # config.jwt_secret_key = ENV['JWT_SECRET_KEY'] + # config.app_url = ENV['APP_URL'] + + # config.user_type = ::Type::Auth::User + + # config.sign_in_mutation = ::Mutations::Auth::SignIn + # config.sign_up_mutation = ::Mutations::Auth::SignUp + + # config.forgot_password_mutation = ::Mutations::Auth::ForgotPassword + # config.reset_password_mutation = ::Mutations::Auth::ResetPassword + + # config.update_account_mutation = ::Mutations::Auth::UpdateAccount + + # config.validate_token_mutation = ::Mutations::Auth::ValidateToken +end \ No newline at end of file diff --git a/spec/dummy/config/initializers/inflections.rb b/spec/dummy/config/initializers/inflections.rb new file mode 100644 index 0000000..ac033bf --- /dev/null +++ b/spec/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/spec/dummy/config/initializers/mime_types.rb b/spec/dummy/config/initializers/mime_types.rb new file mode 100644 index 0000000..dc18996 --- /dev/null +++ b/spec/dummy/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/spec/dummy/config/initializers/wrap_parameters.rb b/spec/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..bbfc396 --- /dev/null +++ b/spec/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/spec/dummy/config/locales/en.yml b/spec/dummy/config/locales/en.yml new file mode 100644 index 0000000..decc5a8 --- /dev/null +++ b/spec/dummy/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/spec/dummy/config/puma.rb b/spec/dummy/config/puma.rb new file mode 100644 index 0000000..a5eccf8 --- /dev/null +++ b/spec/dummy/config/puma.rb @@ -0,0 +1,34 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/spec/dummy/config/routes.rb b/spec/dummy/config/routes.rb new file mode 100644 index 0000000..79de989 --- /dev/null +++ b/spec/dummy/config/routes.rb @@ -0,0 +1,5 @@ +Rails.application.routes.draw do + post '/graphql', to: 'graphql#execute' + + devise_for :users, skip: :all +end \ No newline at end of file diff --git a/spec/dummy/config/spring.rb b/spec/dummy/config/spring.rb new file mode 100644 index 0000000..9fa7863 --- /dev/null +++ b/spec/dummy/config/spring.rb @@ -0,0 +1,6 @@ +%w[ + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +].each { |path| Spring.watch(path) } diff --git a/spec/dummy/config/storage.yml b/spec/dummy/config/storage.yml new file mode 100644 index 0000000..d32f76e --- /dev/null +++ b/spec/dummy/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/spec/dummy/db/migrate/20190108110416_devise_create_users.rb b/spec/dummy/db/migrate/20190108110416_devise_create_users.rb new file mode 100644 index 0000000..e4fe133 --- /dev/null +++ b/spec/dummy/db/migrate/20190108110416_devise_create_users.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class DeviseCreateUsers < ActiveRecord::Migration[5.2] + def change + create_table :users do |t| + ## Database authenticatable + t.string :email, null: false, default: "" + t.string :encrypted_password, null: false, default: "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + # t.integer :sign_in_count, default: 0, null: false + # t.datetime :current_sign_in_at + # t.datetime :last_sign_in_at + # t.inet :current_sign_in_ip + # t.inet :last_sign_in_ip + + ## Confirmable + # t.string :confirmation_token + # t.datetime :confirmed_at + # t.datetime :confirmation_sent_at + # t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + + t.timestamps null: false + end + + add_index :users, :email, unique: true + add_index :users, :reset_password_token, unique: true + # add_index :users, :confirmation_token, unique: true + # add_index :users, :unlock_token, unique: true + end +end diff --git a/spec/dummy/db/migrate/20190214190814_create_active_storage_tables.active_storage.rb b/spec/dummy/db/migrate/20190214190814_create_active_storage_tables.active_storage.rb new file mode 100644 index 0000000..0b2ce25 --- /dev/null +++ b/spec/dummy/db/migrate/20190214190814_create_active_storage_tables.active_storage.rb @@ -0,0 +1,27 @@ +# This migration comes from active_storage (originally 20170806125915) +class CreateActiveStorageTables < ActiveRecord::Migration[5.2] + def change + create_table :active_storage_blobs do |t| + t.string :key, null: false + t.string :filename, null: false + t.string :content_type + t.text :metadata + t.bigint :byte_size, null: false + t.string :checksum, null: false + t.datetime :created_at, null: false + + t.index [ :key ], unique: true + end + + create_table :active_storage_attachments do |t| + t.string :name, null: false + t.references :record, null: false, polymorphic: true, index: false + t.references :blob, null: false + + t.datetime :created_at, null: false + + t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + end + end +end diff --git a/spec/dummy/db/migrate/20190214190815_add_refresh_token_to_user.graph_ql_auth.rb b/spec/dummy/db/migrate/20190214190815_add_refresh_token_to_user.graph_ql_auth.rb new file mode 100644 index 0000000..a442103 --- /dev/null +++ b/spec/dummy/db/migrate/20190214190815_add_refresh_token_to_user.graph_ql_auth.rb @@ -0,0 +1,6 @@ +# This migration comes from graph_ql_auth (originally 20190108151146) +class AddRefreshTokenToUser < ActiveRecord::Migration[5.2] + def change + add_column :users, :refresh_token, :string, default: nil + end +end diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb new file mode 100644 index 0000000..a50c04f --- /dev/null +++ b/spec/dummy/db/schema.rb @@ -0,0 +1,49 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2019_02_14_190815) do + + create_table "active_storage_attachments", force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.integer "record_id", null: false + t.integer "blob_id", null: false + t.datetime "created_at", null: false + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true + end + + create_table "active_storage_blobs", force: :cascade do |t| + t.string "key", null: false + t.string "filename", null: false + t.string "content_type" + t.text "metadata" + t.bigint "byte_size", null: false + t.string "checksum", null: false + t.datetime "created_at", null: false + t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true + end + + create_table "users", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "refresh_token" + t.index ["email"], name: "index_users_on_email", unique: true + t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + end + +end diff --git a/spec/dummy/db/seeds.rb b/spec/dummy/db/seeds.rb new file mode 100644 index 0000000..1beea2a --- /dev/null +++ b/spec/dummy/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) +# Character.create(name: 'Luke', movie: movies.first) diff --git a/spec/dummy/lib/assets/.keep b/spec/dummy/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/log/.keep b/spec/dummy/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/package.json b/spec/dummy/package.json new file mode 100644 index 0000000..caa2d7b --- /dev/null +++ b/spec/dummy/package.json @@ -0,0 +1,5 @@ +{ + "name": "dummy", + "private": true, + "dependencies": {} +} diff --git a/spec/dummy/public/404.html b/spec/dummy/public/404.html new file mode 100644 index 0000000..2be3af2 --- /dev/null +++ b/spec/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/422.html b/spec/dummy/public/422.html new file mode 100644 index 0000000..c08eac0 --- /dev/null +++ b/spec/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/500.html b/spec/dummy/public/500.html new file mode 100644 index 0000000..78a030a --- /dev/null +++ b/spec/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/dummy/public/apple-touch-icon-precomposed.png b/spec/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/public/apple-touch-icon.png b/spec/dummy/public/apple-touch-icon.png new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/public/favicon.ico b/spec/dummy/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/storage/.keep b/spec/dummy/storage/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/tmp/.keep b/spec/dummy/tmp/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/dummy/tmp/storage/.keep b/spec/dummy/tmp/storage/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixtures/response_mock.rb b/spec/fixtures/response_mock.rb new file mode 100644 index 0000000..3c48877 --- /dev/null +++ b/spec/fixtures/response_mock.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ResponseMock + attr_accessor :headers + + def initialize(headers:) + self.headers = headers + end + + def set_header(key, v) + headers[key] = v + end +end \ No newline at end of file diff --git a/spec/graphql/mutations/auth/forgot_password_spec.rb b/spec/graphql/mutations/auth/forgot_password_spec.rb new file mode 100644 index 0000000..c87b523 --- /dev/null +++ b/spec/graphql/mutations/auth/forgot_password_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::ForgotPassword, type: :request do + before do + User.create!(email: 'email@example.com', password: 'password') + end + + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation($email: String!) { + forgotPassword(email: $email) { + errors { + field + message + } + success + valid + } + } + GRAPHQL + end + + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) do + { + "email" => "email@example.com" + } + end + + let(:invalid_variables) do + { + "email" => "bademail@example.com" + } + end + + subject { result } + + context 'when valid parameters are given' do + before do + subject + end + + it 'sends a reset password instructions email' do + expect(ActionMailer::Base.deliveries.last[:To].value).to eq(User.last.email) + expect(ActionMailer::Base.deliveries.last[:Subject].value).to eq('Reset password instructions') + end + + it 'returns a success' do + expect(result['data']['forgotPassword']['errors']).to match_array([]) + expect(result['data']['forgotPassword']['success']).to be_truthy + expect(result['data']['forgotPassword']['valid']).to be_truthy + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'gives no clue about the failure' do + subject + expect(result['data']['forgotPassword']['errors']).to match_array([]) + expect(result['data']['forgotPassword']['success']).to be_truthy + expect(result['data']['forgotPassword']['valid']).to be_truthy + end + end +end diff --git a/spec/graphql/mutations/auth/reset_password_spec.rb b/spec/graphql/mutations/auth/reset_password_spec.rb new file mode 100644 index 0000000..26ae4e6 --- /dev/null +++ b/spec/graphql/mutations/auth/reset_password_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::ResetPassword, type: :request do + before do + user = User.create!( + email: 'email@example.com', + password: 'password' + ) + @reset_password_token = user.send_reset_password_instructions + end + + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation($resetPasswordToken: String!, $password: String!, $passwordConfirmation: String!) { + resetPassword(resetPasswordToken: $resetPasswordToken, password: $password, passwordConfirmation: $passwordConfirmation) { + success + errors { + field + message + } + } + } + GRAPHQL + end + + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) do + { + "resetPasswordToken" => @reset_password_token, + "password" => "password", + "passwordConfirmation" => "password" + } + end + + let(:invalid_variables) do + { + "resetPasswordToken" => '1234567890', + "password" => "password", + "passwordConfirmation" => "password" + } + end + + subject { result } + + context 'when valid parameters are given' do + it 'succeeds to reset the password' do + subject + expect(result['data']['resetPassword']['success']).to be_truthy + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'fails to reset the password' do + subject + expect(result['data']['resetPassword']['success']).to be_falsey + end + end +end diff --git a/spec/graphql/mutations/auth/sign_in_spec.rb b/spec/graphql/mutations/auth/sign_in_spec.rb new file mode 100644 index 0000000..4e66f8e --- /dev/null +++ b/spec/graphql/mutations/auth/sign_in_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::SignUp, type: :request do + before do + User.create!(email: 'email@example.com', password: 'password') + end + + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation($email: String!, $password: String!, $rememberMe: Boolean!) { + signIn(email: $email, password: $password, rememberMe: $rememberMe) { + success + user { + email + } + errors { + field + message + } + } + } + GRAPHQL + end + + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) do + { + "email" => "email@example.com", + "password" => "password", + "rememberMe" => false + } + end + + let(:invalid_variables) do + { + "email" => "email@example.com", + "password" => "password2", + "rememberMe" => false + } + end + + subject { result } + + context 'when valid parameters are given' do + it 'sign in the user' do + subject + expect(result['data']['signIn']['success']).to be_truthy + expect(result['data']['signIn']['user']['email']).to eq(User.last.email) + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'fails to sign in the user' do + subject + expect(result['data']['signIn']['success']).to be_falsey + expect(result['data']['signIn']['user']).to be_nil + expect(result['data']['signIn']['errors'].first['message']).to eq( + I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email')) + ) + end + end +end diff --git a/spec/graphql/mutations/auth/sign_up_spec.rb b/spec/graphql/mutations/auth/sign_up_spec.rb new file mode 100644 index 0000000..f719540 --- /dev/null +++ b/spec/graphql/mutations/auth/sign_up_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::SignUp, type: :request do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation($email: String!, $password: String!, $passwordConfirmation: String!) { + signUp(email: $email, password: $password, passwordConfirmation: $passwordConfirmation) { + success + user { + email + } + errors { + field + message + } + } + } + GRAPHQL + end + + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) do + { + "email" => "email@example.com", + "password" => "password", + "passwordConfirmation" => "password" + } + end + + let(:invalid_variables) do + { + "email" => "emailexample.com", + "password" => "password", + "passwordConfirmation" => "password2" + } + end + + subject { result } + + context 'when valid parameters are given' do + it 'sign up the user' do + subject + expect(result['data']['signUp']['success']).to be_truthy + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'fails to sign up the user' do + subject + expect(result['data']['signUp']['success']).to be_falsey + end + end +end diff --git a/spec/graphql/mutations/auth/update_account_spec.rb b/spec/graphql/mutations/auth/update_account_spec.rb new file mode 100644 index 0000000..40f3035 --- /dev/null +++ b/spec/graphql/mutations/auth/update_account_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::UpdateAccount, type: :request do + before do + @user = User.create!( + email: 'email@example.com', + password: 'password' + ) + end + + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation($currentPassword: String!, $password: String!, $passwordConfirmation: String!) { + updateAccount(currentPassword: $currentPassword, password: $password, passwordConfirmation: $passwordConfirmation) { + success + user { + email + } + errors { + field + message + } + } + } + GRAPHQL + end + + let(:context) do + { + current_user: @user, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) do + { + "currentPassword" => "password", + "password" => "newpassword", + "passwordConfirmation" => "newpassword" + } + end + + let(:invalid_variables) do + { + "currentPassword" => "badpassword", + "password" => "newpassword", + "passwordConfirmation" => "newpassword" + } + end + + subject { result } + + context 'when the user is logged in' do + let(:context) do + { + current_user: @user, + response: ResponseMock.new(headers: {}), + } + end + + context 'when valid parameters are given' do + it 'succeeds to update the account' do + subject + + expect(result['data']['updateAccount']['success']).to be_truthy + expect(result['data']['updateAccount']['user']['email']).to eq(@user.email) + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'fails to update the account' do + subject + expect(result['data']['updateAccount']['success']).to be_falsey + end + end + end + + context 'when the user not is logged in' do + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + context 'when valid parameters are given' do + it 'fails to update the account' do + subject + expect(result['data']['updateAccount']['success']).to be_falsey + end + end + + context 'when invalid parameters are given' do + let(:result) do + GraphqlSchema.execute( + query_string, + variables: invalid_variables, + context: context + ) + end + + it 'fails to update the account' do + subject + expect(result['data']['updateAccount']['success']).to be_falsey + end + end + end +end diff --git a/spec/graphql/mutations/auth/validate_token_spec.rb b/spec/graphql/mutations/auth/validate_token_spec.rb new file mode 100644 index 0000000..de4db0d --- /dev/null +++ b/spec/graphql/mutations/auth/validate_token_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Auth::ValidateToken, type: :request do + before do + @user = User.create!( + email: 'email@example.com', + password: 'password' + ) + end + + let(:result) do + GraphqlSchema.execute( + query_string, + variables: variables, + context: context + ) + end + + let(:query_string) do + <<-GRAPHQL + mutation { + validateToken { + success + valid + user { + email + } + } + } + GRAPHQL + end + + let(:context) do + { + current_user: @user, + response: ResponseMock.new(headers: {}), + } + end + + let(:variables) { {} } + + subject { result } + + context 'when user is logged in' do + it 'succeeds to validate the token' do + subject + + expect(result['data']['validateToken']['success']).to be_truthy + expect(result['data']['validateToken']['user']['email']).to eq(@user.email) + end + end + + context 'when user is not logged in' do + let(:context) do + { + current_user: nil, + response: ResponseMock.new(headers: {}), + } + end + + it 'fails to validate the token' do + subject + + expect(result['data']['validateToken']['success']).to be_falsey + expect(result['data']['validateToken']['user']).to be_nil + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..6bdc41e --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'bundler/setup' +require 'database_cleaner' + +# Configure Rails Environment +ENV['RAILS_ENV'] = 'test' + +require 'dummy/config/environment' +require 'fixtures/response_mock' + +ENV['GRAPHQL_RUBY_VERSION'] ||= '1_8' +ENV['JWT_SECRET_KEY'] ||= 'secret_test_key' + +if ENV['CI'] + require 'simplecov' + SimpleCov.add_filter('spec') + require 'coveralls' + Coveralls.wear! +end + +require 'graphql-auth' + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = '.rspec_status' + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + config.before(:suite) do + DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with(:truncation) + end + + config.around(:each) do |example| + DatabaseCleaner.cleaning do + example.run + end + end + + config.before do + Devise.mailer_sender = 'noreply@domain.com' + allow(GraphQL::Auth.configuration).to receive(:jwt_secret_key).and_return('jwt_secret_key') + end +end \ No newline at end of file