From bb97427a401a1efe41dd9e5d3b212641ac0e058a Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 26 Oct 2018 11:13:19 -0500 Subject: [PATCH 01/77] We use npm ci only during build test --- script/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/test.sh b/script/test.sh index 882f7b2d..285ab5a9 100755 --- a/script/test.sh +++ b/script/test.sh @@ -1,2 +1,2 @@ #!/bin/bash -npm ci --unsafe-perm && rake db:create db:structure:load db:migrate && RAILS_ENV=test rake db:create db:structure:load test:prepare && rake spec && npm run ci-build-all && npx jest \ No newline at end of file +npm ci && rake db:create db:structure:load db:migrate && RAILS_ENV=test rake db:create db:structure:load test:prepare && rake spec && npm run build-all && npx jest From db9493725ec58b0cb59b99c42d58bacd35f5233e Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 2 Nov 2018 15:58:09 -0500 Subject: [PATCH 02/77] FIXED PROBLEM! --- config/environments/ci.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/ci.rb b/config/environments/ci.rb index 33e72132..565b75ca 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -57,4 +57,4 @@ Commitchange::Application.configure do ActiveRecord::Base.logger = nil end -end \ No newline at end of file +end From 3ed8a501e6c4f0db6697a809f3fb941dc0686b0b Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 2 Nov 2018 16:06:27 -0500 Subject: [PATCH 03/77] WWWWWHHHE --- script/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/test.sh b/script/test.sh index 285ab5a9..38faac5c 100755 --- a/script/test.sh +++ b/script/test.sh @@ -1,2 +1,2 @@ #!/bin/bash -npm ci && rake db:create db:structure:load db:migrate && RAILS_ENV=test rake db:create db:structure:load test:prepare && rake spec && npm run build-all && npx jest +npm ci && rake db:create db:structure:load db:migrate && RAILS_ENV=test rake db:create db:structure:load test:prepare && rake spec && npm run build-all && npx jest \ No newline at end of file From 168584682881671100df1a27529c1be18f5126df Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 2 Nov 2018 16:23:34 -0500 Subject: [PATCH 04/77] LESS LOGGING --- config/environments/ci.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/environments/ci.rb b/config/environments/ci.rb index 565b75ca..ab04be03 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -1,5 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Commitchange::Application.configure do +<<<<<<< HEAD # Settings specified here will take precedence over those in config/application.rb # In the development environment your application's code is reloaded on From c743fac9761657d22fd325a6405cac873da349ff Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 8 Nov 2018 15:39:21 -0600 Subject: [PATCH 05/77] Finally worky? --- config/environments/ci.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/environments/ci.rb b/config/environments/ci.rb index ab04be03..8787f611 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -1,6 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Commitchange::Application.configure do -<<<<<<< HEAD # Settings specified here will take precedence over those in config/application.rb # In the development environment your application's code is reloaded on @@ -57,5 +56,4 @@ Commitchange::Application.configure do config.after_initialize do ActiveRecord::Base.logger = nil end - end From 3291392c80b17389f22f8f3132a8a2f60c1bc933 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 8 Nov 2018 16:29:53 -0600 Subject: [PATCH 06/77] Boot update --- config/boot.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config/boot.rb b/config/boot.rb index 3a9aadeb..c6ea5a03 100755 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,8 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require 'rubygems' - +# # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) -require 'bootsnap/setup' +require 'bootsnap/setup' \ No newline at end of file From 4ea0d48a0137176821a93ab7685c2e18d65b65fb Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 8 Nov 2018 16:37:48 -0600 Subject: [PATCH 07/77] Update inflections --- config/initializers/inflections.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index e42d263f..787a1c49 100755 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,16 +1,17 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| +# 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 do |inflect| +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.acronym 'RESTful' # end From 6fa8bd5a627b1934e7fabf21268f0d295dd5aed1 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 8 Nov 2018 16:40:50 -0600 Subject: [PATCH 08/77] Fix wrap params --- config/initializers/wrap_parameters.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 521563e8..97b340a1 100755 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,15 +1,15 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # 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] + wrap_parameters format: [:json] if respond_to?(:wrap_parameters) end -# Disable root element in JSON by default. +# To enable root element in JSON for ActiveRecord objects. ActiveSupport.on_load(:active_record) do - self.include_root_in_json = false + self.include_root_in_json = true end From ca176965293af8c1d6f7cb70876fd06bdb2ce7a7 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 8 Nov 2018 18:29:00 -0600 Subject: [PATCH 09/77] Initial Update to ruby 4.2 --- Gemfile | 11 +- Gemfile.lock | 404 +++++++++--------- .../campaign_gift_options_controller.rb | 40 +- app/controllers/campaigns_controller.rb | 13 +- app/models/nonprofit.rb | 3 +- bin/bundle | 3 + bin/rails | 4 + bin/rake | 4 + config/boot.rb | 5 +- config/environment.rb | 2 +- config/environments/ci.rb | 2 +- config/environments/development.rb | 19 +- config/environments/production.rb | 123 +++--- config/environments/staging.rb | 2 +- config/environments/test.rb | 73 ++-- config/initializers/assets.rb | 8 + config/initializers/cookies_serializer.rb | 3 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/inflections.rb | 1 - config/initializers/log_rage.rb | 2 +- config/initializers/mime_types.rb | 2 - config/initializers/secret_token.rb | 2 +- config/initializers/session_store.rb | 8 +- config/initializers/timeout.rb | 12 +- config/routes.rb | 58 +-- config/secrets.yml | 22 + db/structure.sql | 2 +- lib/create/create_campaign.rb | 28 ++ lib/email.rb | 2 +- .../api/resource/templates/spec.rb.erb | 2 +- spec/api/houdini/nonprofit_spec.rb | 14 +- .../controllers/campaign_gift_options_spec.rb | 8 +- spec/controllers/campaigns_spec.rb | 25 +- spec/controllers/event_discounts_spec.rb | 6 +- spec/controllers/events_spec.rb | 16 +- .../controllers/nonprofits/activities_spec.rb | 2 +- .../nonprofits/custom_field_masters_spec.rb | 2 +- .../nonprofits/custom_fields_joins_spec.rb | 4 +- spec/controllers/nonprofits/donations_spec.rb | 6 +- spec/controllers/nonprofits/payments_spec.rb | 6 +- spec/controllers/nonprofits/payouts_spec.rb | 2 +- .../nonprofits/recurring_donations_spec.rb | 6 +- .../controllers/nonprofits/supporters_spec.rb | 10 +- spec/controllers/nonprofits/tag_joins_spec.rb | 4 +- .../nonprofits/tag_masters_spec.rb | 2 +- spec/controllers/nonprofits_spec.rb | 35 +- spec/controllers/profiles_spec.rb | 2 +- spec/controllers/recurring_donations_spec.rb | 10 +- spec/controllers/roles_spec.rb | 2 +- spec/controllers/ticket_levels_spec.rb | 10 +- spec/lib/create/create_campaign_spec.rb | 8 + spec/lib/query/query_donations_spec.rb | 2 +- 52 files changed, 559 insertions(+), 487 deletions(-) create mode 100755 bin/bundle create mode 100755 bin/rails create mode 100755 bin/rake create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/secrets.yml create mode 100644 spec/lib/create/create_campaign_spec.rb diff --git a/Gemfile b/Gemfile index abe7d29a..647c0c7f 100755 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' ruby '2.3.7' gem 'rake' -gem 'rails', '3.2.22.5' +gem 'rails', '~> 4.1' gem 'rails_12factor' # https://stripe.com/docs/api gem 'stripe' @@ -26,8 +26,7 @@ gem 'test-unit', '~> 3.0' gem 'hamster' gem 'aws-ses' -gem 'aws-sdk' - +gem 'aws-sdk', '~> 1' # for blocking ip addressses gem 'rack-attack' @@ -91,7 +90,7 @@ gem 'table_print' gem 'bunny', '>= 2.6.3' -gem 'rails-i18n', '~> 3.0.0' # For 3.x +gem 'rails-i18n', '~> 4.0' # For 3.x gem 'i18n-js' gem 'countries' @@ -125,7 +124,7 @@ end # Gems used for asset compilation gem 'sass', '3.2.19' -gem 'sass-rails', '3.2.6' +gem 'sass-rails' gem 'uglifier' # make logging less terrible in rails @@ -137,7 +136,7 @@ gem 'dry-validation' # used only for config validation gem 'foreman' gem 'grape', '~> 1.1.0' -gem 'grape-entity', git: 'https://github.com/ruby-grape/grape-entity.git', ref: '0e04aa561373b510c2486282979085eaef2ae663' +gem 'grape-entity' gem 'grape-swagger' gem 'grape-swagger-entity' gem 'grape_url_validator' diff --git a/Gemfile.lock b/Gemfile.lock index 113acbf7..aa61483f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -13,9 +13,9 @@ GIT revision: 0e04aa561373b510c2486282979085eaef2ae663 ref: 0e04aa561373b510c2486282979085eaef2ae663 specs: - grape-entity (0.7.1) - activesupport (>= 3.0.0) - multi_json (>= 1.3.2) + qx (0.1.1) + activerecord (>= 3.0) + colorize (~> 0.8) PATH remote: gems/grape_devise @@ -42,100 +42,108 @@ GEM remote: https://rubygems.org/ specs: action_mailer_matchers (1.0.0) - actionmailer (3.2.22.5) - actionpack (= 3.2.22.5) - mail (~> 2.5.4) - actionpack (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.5) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) - activemodel (3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) - activerecord (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activeresource (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - activesupport (3.2.22.5) + actionmailer (4.1.16) + actionpack (= 4.1.16) + actionview (= 4.1.16) + mail (~> 2.5, >= 2.5.4) + actionpack (4.1.16) + actionview (= 4.1.16) + activesupport (= 4.1.16) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + activemodel (4.0.0) + activesupport (= 4.0.0) + builder (~> 3.1.0) + activerecord (4.0.0) + activemodel (= 4.0.0) + activerecord-deprecated_finders (~> 1.0.2) + activesupport (= 4.0.0) + arel (~> 4.0.0) + activerecord-deprecated_finders (1.0.4) + activesupport (4.0.0) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) addressable (2.3.8) amq-protocol (2.2.0) andand (1.3.3) - arel (3.0.3) - aws-sdk (1.66.0) - aws-sdk-v1 (= 1.66.0) - aws-sdk-v1 (1.66.0) + arel (5.0.1.20140414130214) + aws-eventstream (1.0.1) + aws-partitions (1.110.0) + aws-sdk (1.67.0) + aws-sdk-v1 (= 1.67.0) + aws-sdk-core (3.37.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-kms (1.11.0) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sigv4 (~> 1.0) + aws-sdk-s3 (1.23.1) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) + aws-sdk-v1 (1.67.0) json (~> 1.4) - nokogiri (>= 1.4.4) + nokogiri (~> 1) aws-ses (0.6.0) builder mail (> 2.2.5) mime-types xml-simple + aws-sigv4 (1.0.3) axiom-types (0.1.1) descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) - bcrypt (3.1.11) - binding_of_caller (0.7.2) + bcrypt (3.1.12) + binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - bootsnap (1.1.7) + bootsnap (1.3.2) msgpack (~> 1.0) - browserify-rails (0.9.3) - sprockets (~> 2.2) - builder (3.0.4) - bunny (2.7.1) - amq-protocol (>= 2.2.0) - carrierwave (0.10.0) - activemodel (>= 3.2.0) - activesupport (>= 3.2.0) - json (>= 1.7) + browserify-rails (1.1.0) + railties (>= 4.0.0, < 5.0) + builder (3.2.3) + bunny (2.12.0) + amq-protocol (~> 2.3, >= 2.3.0) + carrierwave (1.2.3) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) mime-types (>= 1.16) - carrierwave-aws (0.5.0) - aws-sdk (~> 1.58) - carrierwave (~> 0.7) + carrierwave-aws (1.3.0) + aws-sdk-s3 (~> 1.0) + carrierwave (>= 0.7, < 2.0) chronic (0.10.2) coderay (1.1.2) coercible (1.0.0) descendants_tracker (~> 0.0.1) colorize (0.8.1) - concurrent-ruby (1.0.5) + concurrent-ruby (1.1.4) config (1.7.0) activesupport (>= 3.0) deep_merge (~> 1.2.1) dry-validation (>= 0.10.4) - countries (2.1.2) + countries (2.1.4) i18n_data (~> 0.8.0) money (~> 6.9) sixarm_ruby_unaccent (~> 1.1) unicode_utils (~> 1.4) - crack (0.4.2) + crack (0.4.3) safe_yaml (~> 1.0.0) - css_parser (1.3.6) + css_parser (1.6.0) addressable - dalli (2.7.6) + dalli (2.7.9) dante (0.2.0) - database_cleaner (1.6.1) + database_cleaner (1.7.0) debase (0.2.2) debase-ruby_core_source (>= 0.10.2) debase-ruby_core_source (0.10.3) - debug_inspector (0.0.2) + debug_inspector (0.0.3) deep_merge (1.2.1) - delayed_job (4.1.2) - activesupport (>= 3.0, < 5.1) - delayed_job_active_record (4.1.1) - activerecord (>= 3.0, < 5.1) + delayed_job (4.1.5) + activesupport (>= 3.0, < 5.3) + delayed_job_active_record (4.1.3) + activerecord (>= 3.0, < 5.3) delayed_job (>= 3.0, < 5) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) @@ -146,65 +154,65 @@ GEM responders thread_safe (~> 0.1) warden (~> 1.2.3) - devise-async (0.9.0) - devise (~> 3.2) - diff-lcs (1.2.5) + devise-async (0.10.2) + devise (>= 3.2, < 4.0) + diff-lcs (1.3) docile (1.3.1) - domain_name (0.5.20160615) + domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) - dotenv (2.0.1) - dotenv-rails (2.0.1) - dotenv (= 2.0.1) + dotenv (2.5.0) + dotenv-rails (2.5.0) + dotenv (= 2.5.0) + railties (>= 3.2, < 6.0) dry-configurable (0.7.0) concurrent-ruby (~> 1.0) dry-container (0.6.0) concurrent-ruby (~> 1.0) dry-configurable (~> 0.1, >= 0.1.3) - dry-core (0.4.5) + dry-core (0.4.7) concurrent-ruby (~> 1.0) - dry-equalizer (0.2.0) + dry-equalizer (0.2.1) + dry-inflector (0.1.2) dry-logic (0.4.2) dry-container (~> 0.2, >= 0.2.6) dry-core (~> 0.2) dry-equalizer (~> 0.2) - dry-types (0.12.2) + dry-types (0.13.2) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1) dry-container (~> 0.3) - dry-core (~> 0.2, >= 0.2.1) + dry-core (~> 0.4, >= 0.4.4) dry-equalizer (~> 0.2) + dry-inflector (~> 0.1, >= 0.1.2) dry-logic (~> 0.4, >= 0.4.2) - inflecto (~> 0.0.0, >= 0.0.2) - dry-validation (0.11.1) + dry-validation (0.12.2) concurrent-ruby (~> 1.0) dry-configurable (~> 0.1, >= 0.1.3) dry-core (~> 0.2, >= 0.2.1) dry-equalizer (~> 0.2) dry-logic (~> 0.4, >= 0.4.0) - dry-types (~> 0.12.0) + dry-types (~> 0.13.1) equalizer (0.0.11) erubis (2.7.0) - execjs (2.5.2) - factory_bot (4.8.2) + execjs (2.7.0) + factory_bot (4.11.1) activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) + factory_bot_rails (4.11.1) + factory_bot (~> 4.11.1) railties (>= 3.0.0) - faraday (0.9.1) + faraday (0.11.0) multipart-post (>= 1.2, < 3) faraday_middleware (0.9.1) faraday (>= 0.7.4, < 0.10) font_assets (0.1.14) rack - foreman (0.84.0) + foreman (0.85.0) thor (~> 0.19.1) - fullcontact (0.9.0) - faraday (~> 0.9.0) - faraday_middleware (>= 0.9) + fullcontact (0.18.0) + faraday (~> 0.11.0) + faraday_middleware (>= 0.10) hashie (>= 2.0, < 4.0) - plissken - geocoder (1.2.11) - get_process_mem (0.2.1) + geocoder (1.5.0) + get_process_mem (0.2.3) grape (1.1.0) activesupport builder @@ -212,11 +220,14 @@ GEM rack (>= 1.3.0) rack-accept virtus (>= 1.0.0) - grape-swagger (0.28.0) + grape-entity (0.7.1) + activesupport (>= 4.0) + multi_json (>= 1.3.2) + grape-swagger (0.31.1) grape (>= 0.16.2) - grape-swagger-entity (0.2.3) + grape-swagger-entity (0.3.0) grape-entity (>= 0.5.0) - grape-swagger (>= 0.20.4) + grape-swagger (>= 0.31.0) grape_logging (1.8.0) grape rack @@ -224,36 +235,34 @@ GEM grape (>= 0.12.0) hamster (3.0.0) concurrent-ruby (~> 1.0) - hashie (3.4.1) - heroku-deflater (0.5.3) + hashdiff (0.3.7) + hashie (3.6.0) + heroku-deflater (0.6.3) rack (>= 1.4.5) - hike (1.2.3) - http-cookie (1.0.2) + http-cookie (1.0.3) domain_name (~> 0.5) - httparty (0.13.3) - json (~> 1.8) + httparty (0.16.2) multi_xml (>= 0.5.2) i18n (0.9.5) concurrent-ruby (~> 1.0) - i18n-js (3.0.2) - i18n (~> 0.6, >= 0.6.6) + i18n-js (3.1.0) + i18n (>= 0.6.6, < 2) i18n_data (0.8.0) ice_nine (0.11.2) - inflecto (0.0.2) - journey (1.0.4) + jmespath (1.4.0) json (1.8.6) - kdtree (0.3) - lograge (0.3.6) - actionpack (>= 3) - activesupport (>= 3) - railties (>= 3) - mail (2.5.5) - mime-types (~> 1.16) - treetop (~> 1.4.8) + kdtree (0.4) + lograge (0.10.0) + actionpack (>= 4) + activesupport (>= 4) + railties (>= 4) + request_store (~> 1.0) + mail (2.7.1) + mini_mime (>= 0.1.1) mail_view (2.0.4) tilt memcachier (0.0.2) - method_source (0.9.0) + method_source (0.9.1) mime-types (1.25.1) mini_magick (4.9.5) mini_portile2 (2.1.0) @@ -261,7 +270,7 @@ GEM i18n (>= 0.6.4, < 1.0) msgpack (1.2.0) multi_json (1.13.1) - multi_xml (0.5.5) + multi_xml (0.6.0) multipart-post (2.0.0) mustermann (1.0.3) mustermann-grape (1.0.0) @@ -271,47 +280,46 @@ GEM kdtree require_all netrc (0.11.0) - nokogiri (1.6.8.1) - mini_portile2 (~> 2.1.0) + nokogiri (1.8.5) + mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) - parallel (1.6.1) - pg (0.18.3) - plissken (0.2.0) - symbolize (~> 4.2) + parallel (1.12.1) + pg (0.21.0) polyglot (0.3.5) power_assert (1.1.1) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) - puma (3.11.2) + public_suffix (3.0.3) + puma (3.12.0) puma_worker_killer (0.1.0) get_process_mem (~> 0.2) puma (>= 2.7, < 4) - rabl (0.11.6) + rabl (0.14.0) activesupport (>= 2.3.14) - rack (1.4.7) + rack (1.5.5) rack-accept (0.4.5) rack (>= 0.4) - rack-attack (4.2.0) - rack - rack-cache (1.7.2) - rack (>= 0.4) - rack-ssl (1.3.4) + rack-attack (5.4.2) + rack (>= 1.0, < 3) + rack-ssl (1.4.1) rack rack-test (0.6.3) rack (>= 1.0) - rack-timeout (0.4.2) - rails (3.2.22.5) - actionmailer (= 3.2.22.5) - actionpack (= 3.2.22.5) - activerecord (= 3.2.22.5) - activeresource (= 3.2.22.5) - activesupport (= 3.2.22.5) - bundler (~> 1.0) - railties (= 3.2.22.5) - rails-i18n (3.0.1) - i18n (~> 0.5) - rails (>= 3.0.0, < 4.0.0) + rack-timeout (0.5.1) + rails (4.1.16) + actionmailer (= 4.1.16) + actionpack (= 4.1.16) + actionview (= 4.1.16) + activemodel (= 4.1.16) + activerecord (= 4.1.16) + activesupport (= 4.1.16) + bundler (>= 1.3.0, < 2.0) + railties (= 4.1.16) + sprockets-rails (~> 2.0) + rails-i18n (4.0.9) + i18n (~> 0.7) + railties (~> 4.0) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -322,90 +330,86 @@ GEM activesupport (= 3.2.22.5) rack-ssl (~> 1.3.2) rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) - rake (12.3.1) - rdoc (3.12.2) - json (~> 1.4) - require_all (1.3.2) + thor (>= 0.18.1, < 2.0) + rake (12.3.2) + request_store (1.4.1) + rack (>= 1.4) + require_all (2.0.0) responders (1.1.2) railties (>= 3.2, < 4.2) - rest-client (1.8.0) + rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 3.0) - netrc (~> 0.7) - roadie (3.0.4) - css_parser (~> 1.3.4) - nokogiri (~> 1.6.0) - roadie-rails (1.0.5) - railties (>= 3.0, < 4.3) - roadie (~> 3.0) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.1) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) + roadie (3.4.0) + css_parser (~> 1.4) + nokogiri (~> 1.5) + roadie-rails (1.3.0) + railties (>= 3.0, < 5.3) + roadie (~> 3.1) + rspec (3.8.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-rails (3.5.0) + rspec-support (~> 3.8.0) + rspec-rails (3.8.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-support (~> 3.5.0) - rspec-support (3.5.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) ruby-debug-ide (0.6.1) rake (>= 0.8.1) ruby-prof (0.15.9) safe_yaml (1.0.4) sass (3.2.19) - sass-rails (3.2.6) - railties (~> 3.2.0) - sass (>= 3.1.10) - tilt (~> 1.3) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) sixarm_ruby_unaccent (1.2.0) - sprockets (2.2.3) - hike (~> 1.2) - multi_json (~> 1.0) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - stripe (1.49.0) - rest-client (>= 1.4, < 3.0) - symbolize (4.5.2) - activemodel (>= 3.2, < 5) - activesupport (>= 3.2, < 5) - i18n - table_print (1.5.4) - test-unit (3.2.7) + sprockets (3.7.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (2.3.3) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) + stripe (1.58.0) + rest-client (>= 1.4, < 4.0) + table_print (1.5.6) + test-unit (3.2.8) power_assert thor (0.19.4) thread_safe (0.3.6) - tilt (1.4.1) - timecop (0.7.3) - traceroute (0.5.0) + tilt (2.0.9) + timecop (0.9.1) + traceroute (0.8.0) rails (>= 3.0.0) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) - tzinfo (0.3.54) - uglifier (2.7.1) - execjs (>= 0.3.0) - json (>= 1.8.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.19) + execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext - unf_ext (0.0.7.2) + unf_ext (0.0.7.5) unicode_utils (1.4.0) virtus (1.0.5) axiom-types (~> 0.1) @@ -414,9 +418,10 @@ GEM equalizer (~> 0.0, >= 0.0.9) warden (1.2.7) rack (>= 1.0) - webmock (1.21.0) + webmock (3.4.2) addressable (>= 2.3.6) crack (>= 0.3.2) + hashdiff xml-simple (1.1.5) PLATFORMS @@ -451,7 +456,7 @@ DEPENDENCIES fullcontact geocoder grape (~> 1.1.0) - grape-entity! + grape-entity grape-swagger grape-swagger-entity grape_devise! @@ -475,9 +480,10 @@ DEPENDENCIES qx! rabl rack-attack + rack-ssl rack-timeout - rails (= 3.2.22.5) - rails-i18n (~> 3.0.0) + rails (~> 4.1) + rails-i18n (~> 4.0) rails_12factor rake roadie-rails @@ -486,7 +492,7 @@ DEPENDENCIES ruby-debug-ide ruby-prof (= 0.15.9) sass (= 3.2.19) - sass-rails (= 3.2.6) + sass-rails simplecov (~> 0.16.1) sprockets stripe diff --git a/app/controllers/campaigns/campaign_gift_options_controller.rb b/app/controllers/campaigns/campaign_gift_options_controller.rb index e413855f..83e5da31 100644 --- a/app/controllers/campaigns/campaign_gift_options_controller.rb +++ b/app/controllers/campaigns/campaign_gift_options_controller.rb @@ -2,9 +2,9 @@ module Campaigns; class CampaignGiftOptionsController < ApplicationController include Controllers::CampaignHelper - before_filter :authenticate_campaign_editor!, only: [:index] + before_filter :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order, :report] - def index + def report respond_to do |format| format.json do render json: QueryCampaignGifts.report_metrics(current_campaign.id) @@ -12,4 +12,40 @@ module Campaigns; class CampaignGiftOptionsController < ApplicationController end end + + + def index + @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') + render json: {data: @gift_options} + end + + def show + render json: {data: current_campaign.campaign_gift_options.find(params[:id])} + end + + def create + campaign = current_campaign + json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), + 'Gift option successfully created!' + end + + def update + @campaign = current_campaign + gift_option = @campaign.campaign_gift_options.find params[:id] + json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' + end + + # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order + # Pass in {data: [{id: 1, order: 1}]} + def update_order + updated_gift_options = UpdateOrder.with_data('campaign_gift_options', params[:data]) + render json: updated_gift_options + end + + def destroy + @campaign = current_campaign + + render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id])} + end + end; end diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index 861370a7..03e95d51 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -57,18 +57,7 @@ class CampaignsController < ApplicationController end def create - Time.use_zone(current_nonprofit.timezone || 'UTC') do - params[:campaign][:end_datetime] = Chronic.parse(params[:campaign][:end_datetime]) if params[:campaign][:end_datetime].present? - end - - if !params[:campaign][:parent_campaign_id] - campaign = current_nonprofit.campaigns.create params[:campaign] - json_saved campaign, 'Campaign created! Well done.' - else - profile_id = params[:campaign][:profile_id] - Profile.find(profile_id).update_attributes params[:profile] - render json: CreatePeerToPeerCampaign.create(params[:campaign], profile_id) - end + render json: CreateCampaign.create(params, current_nonprofit) end def update diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index 421b59b1..f7280036 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -73,7 +73,8 @@ class Nonprofit < ActiveRecord::Base has_many :email_settings has_many :cards, as: :holder - has_one :bank_account, dependent: :destroy, conditions: "COALESCE(deleted, false) = false" + has_one :bank_account, -> { where("COALESCE(deleted, false) = false") }, + dependent: :destroy has_one :billing_subscription, dependent: :destroy has_one :billing_plan, through: :billing_subscription has_one :miscellaneous_np_info diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 00000000..66e9889e --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 00000000..728cd85a --- /dev/null +++ b/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 00000000..17240489 --- /dev/null +++ b/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/config/boot.rb b/config/boot.rb index c6ea5a03..b1a8cf10 100755 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,7 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -# # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' require 'bootsnap/setup' \ No newline at end of file diff --git a/config/environment.rb b/config/environment.rb index 8b283da0..32a0ed66 100755 --- a/config/environment.rb +++ b/config/environment.rb @@ -298,4 +298,4 @@ end Settings.reload! # Initialize the rails application -Commitchange::Application.initialize! +Rails.application.initialize! diff --git a/config/environments/ci.rb b/config/environments/ci.rb index 8787f611..dc55b812 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.configure do +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 diff --git a/config/environments/development.rb b/config/environments/development.rb index 775ab196..eb0ad2c7 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -5,7 +5,7 @@ CarrierWave.configure do |config| config.ignore_download_errors = false end -Commitchange::Application.configure do +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 @@ -14,9 +14,8 @@ Commitchange::Application.configure do config.cache_classes = false config.cache_store = Settings.default.cache_store.to_sym - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - + # Do not eager load code on boot. + config.eager_load = false # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false @@ -26,11 +25,12 @@ Commitchange::Application.configure do # config.action_mailer.default_url_options = { host: 'commitchange.com' } config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } - config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username - config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password + config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username + config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password config.action_mailer.default_url_options = { host: Settings.mailer.host } - + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false # Print deprecation notices to the Rails logger config.active_support.deprecation = :log @@ -40,9 +40,8 @@ Commitchange::Application.configure do # Raise exception on mass assignment protection for Active Record models config.active_record.mass_assignment_sanitizer = :strict - # Log the query plan for queries taking more than this (works) - # with SQLite, MySQL, and PostgreSQL) - config.active_record.auto_explain_threshold_in_seconds = 0.5 + # Raise an error on page load if there are pending migrations + config.active_record.migration_error = :page_load # Do not compress assets config.assets.compress = false diff --git a/config/environments/production.rb b/config/environments/production.rb index 8de071ba..b93a877c 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,89 +1,78 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.configure do - # Settings specified here will take precedence over those in config/application.rb +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 - config.cache_store = Settings.default.cache_store.to_sym + # Code is not reloaded between requests. + config.cache_classes = true - # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false - config.action_controller.perform_caching = 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 - # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = true + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true - # Compress JavaScripts and CSS - config.assets.compress = true + # Enable Rack::Cache to put a simple HTTP cache in front of your application + # Add `rack-cache` to your Gemfile before enabling this. + # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. + # config.action_dispatch.rack_cache = true - # Generate digests for assets URLs - config.assets.digest = true + # Disable Rails's static asset server (Apache or nginx will already do this). + config.serve_static_assets = false + + # 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 - # Defaults to nil and saved in location specified by config.assets.prefix - # config.assets.manifest = YOUR_PATH + # Generate digests for assets URLs. + config.assets.digest = true - # 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 + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true + # 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 - # See everything in the log (default is :info) - config.log_level = :debug + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true - # Prepend all log lines with the following tags - # config.log_tags = [ :subdomain, :uuid ] + # Set to :debug to see everything in the log. + config.log_level = :info - # Use a different logger for distributed setups - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :uuid ] - # Use a different cache store in production - # config.cache_store = :mem_cache_store + # Use a different logger for distributed setups. + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) - # Enable serving of images, stylesheets, and JavaScripts from an asset server + # Use a different cache store in production. + # config.cache_store = :mem_cache_store - cdn_url= URI(Settings.cdn.url) - cdn_url = cdn_url.to_s - config.action_controller.asset_host = cdn_url - config.action_mailer.asset_host = cdn_url - config.font_assets.origin = '*' + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = "http://assets.example.com" - # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # 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 - # Disable delivery errors, bad email addresses will be ignored - # config.action_mailer.raise_delivery_errors = false - config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym - config.action_mailer.default_url_options = { host: Settings.mailer.host } - # Precompile all "page" files, it needs to be set here so the proper env is setup - config.assets.precompile << Proc.new do |path| - if path =~ /.*page\.(css|js)/ - puts "Compiling asset: " + path - true - else - false - end - end + # 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 - # Enable threaded mode - # config.threadsafe! + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation can not be found) - config.i18n.fallbacks = true + # Disable automatic flushing of the log to improve performance. + # config.autoflush_log = false - # 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 - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - # config.active_record.auto_explain_threshold_in_seconds = 0.5 - - config.assets.compile = false - - config.threadsafe! - config.dependency_loading = true if $rails_rake_task - # Compress json - # config.middleware.use Rack::Deflater + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false end diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 19c31c8d..d9717aaa 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.configure do +Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb # Code is not reloaded between requests diff --git a/config/environments/test.rb b/config/environments/test.rb index 64bf4084..48544a21 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,55 +1,42 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.configure do - # Settings specified here will take precedence over those in config/application.rb +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 + # 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 - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = 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 - # Show full error reports and disable caching + # Configure static asset server for tests with Cache-Control for performance. + config.serve_static_assets = true + config.static_cache_control = 'public, max-age=3600' + + # Show full error reports and disable caching. config.consider_all_requests_local = true - # config.action_controller.perform_caching = false + config.action_controller.perform_caching = false - # Don't care if the mailer can't send - config.action_mailer.delivery_method = :test - config.action_mailer.raise_delivery_errors = false - config.action_mailer.default_url_options = { host: 'localhost:8080' } - - # Print deprecation notices to the Rails logger - config.active_support.deprecation = :log - - # Only use best-standards-support built into browsers - config.action_dispatch.best_standards_support = :builtin - - # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict - - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - config.active_record.auto_explain_threshold_in_seconds = 0.5 - - # Do not compress assets - config.assets.compress = false - - # Expands the lines which load the assets - config.assets.debug = true - - config.log_level = :none + # 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 - config.cache_store = :memory_store - config.threadsafe! - config.after_initialize do - ActiveRecord::Base.logger = nil - ActionController::Base.logger = nil - ActionMailer::Base.logger = nil - end + # 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 + config.action_mailer.default_url_options = {host: 'houdiniproject.test'} + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 00000000..d2f4ec33 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,8 @@ +# 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' + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. +# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 00000000..7a06a89f --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of file diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 00000000..4a994e1e --- /dev/null +++ b/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/config/initializers/inflections.rb b/config/initializers/inflections.rb index 787a1c49..ac033bf9 100755 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,4 +1,3 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/config/initializers/log_rage.rb b/config/initializers/log_rage.rb index 5e8470d6..f76666a7 100644 --- a/config/initializers/log_rage.rb +++ b/config/initializers/log_rage.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.configure do +Rails.application.configure do if (Rails.env != 'test') diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 2f890f79..dc189968 100755 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,6 +1,4 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # 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 -# Mime::Type.register_alias "text/html", :iphone diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index fb63eadd..10dc8dd1 100755 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -5,4 +5,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -Commitchange::Application.config.secret_token = ENV.fetch('SECRET_TOKEN') +Rails.application.config.secret_token = ENV.fetch('SECRET_TOKEN') diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 9c08e52a..0fa3b506 100755 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,9 +1,3 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. -Commitchange::Application.config.session_store ActionDispatch::Session::CacheStore, :expire_after => 4.hours - -# Use the database for sessions instead of the cookie-based default, -# which shouldn't be used to store highly confidential information -# (create the session table with "rails generate session_migration") -# Commitchange::Application.config.session_store :active_record_store +Rails.application.config.session_store :cookie_store, key: '_commitchange_session' diff --git a/config/initializers/timeout.rb b/config/initializers/timeout.rb index 41aab386..e1cc5c7c 100644 --- a/config/initializers/timeout.rb +++ b/config/initializers/timeout.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -timeout = Integer(ENV['WEB_TIMEOUT'] || 15) -if ENV['RAILS_ENV'] == 'development' || ENV['IDE_PROCESS_DISPATCHER'] - timeout = 10000 -end - -Rack::Timeout.timeout = timeout # seconds \ No newline at end of file +# timeout = Integer(ENV['WEB_TIMEOUT'] || 15) +# if ENV['RAILS_ENV'] == 'development' || ENV['IDE_PROCESS_DISPATCHER'] +# timeout = 10000 +# end +# +# Rack::Timeout.timeout = timeout # seconds \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 0de6178e..b56dd437 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Commitchange::Application.routes.draw do +Rails.application.routes.draw do mount Houdini::API => '/api' if Rails.env == 'development' @@ -196,47 +196,47 @@ Commitchange::Application.routes.draw do :confirmations => 'users/confirmations' } devise_scope :user do - match '/sign_in' => 'users/sessions#new' - match '/signup' => 'devise/registrations#new' - post '/confirm' => 'users/confirmations#confirm' - match '/users/is_confirmed' => 'users/confirmations#is_confirmed' - match '/users/exists' => 'users/confirmations#exists' - post '/users/confirm_auth', action: :confirm_auth, controller: 'users/sessions' + match '/sign_in' => 'users/sessions#new', via: [:get, :post] + match '/signup' => 'devise/registrations#new', via: [:get, :post] + post '/confirm' => 'users/confirmations#confirm', via: [:get] + match '/users/is_confirmed' => 'users/confirmations#is_confirmed', via: [:get, :post] + match '/users/exists' => 'users/confirmations#exists', via: [:get] + post '/users/confirm_auth', action: :confirm_auth, controller: 'users/sessions', via: [:get, :post] end # Super admin - match '/admin' => 'super_admins#index', :as => 'admin' - match '/admin/search-nonprofits' => 'super_admins#search_nonprofits' - match '/admin/search-profiles' => 'super_admins#search_profiles' - match '/admin/search-fullcontact' => 'super_admins#search_fullcontact' - match '/admin/recurring-donations-without-cards' => 'super_admins#recurring_donations_without_cards' - match '/admin/export_supporters_with_rds' => 'super_admins#export_supporters_with_rds' - match '/admin/resend_user_confirmation' => 'super_admins#resend_user_confirmation' + match '/admin' => 'super_admins#index', :as => 'admin', via: [:get, :post] + match '/admin/search-nonprofits' => 'super_admins#search_nonprofits', via: [:get, :post] + match '/admin/search-profiles' => 'super_admins#search_profiles', via: [:get, :post] + match '/admin/search-fullcontact' => 'super_admins#search_fullcontact', via: [:get, :post] + match '/admin/recurring-donations-without-cards' => 'super_admins#recurring_donations_without_cards', via: [:get, :post] + match '/admin/export_supporters_with_rds' => 'super_admins#export_supporters_with_rds', via: [:get, :post] + match '/admin/resend_user_confirmation' => 'super_admins#resend_user_confirmation', via: [:get, :post] # Events - match '/events' => 'events#index' - match '/events/:event_slug' => 'events#show' + match '/events' => 'events#index', via: [:get] + match '/events/:event_slug' => 'events#show', via: [:get, :post] # Nonprofits - match ':state_code/:city/:name' => 'nonprofits#show', :as => :nonprofit_location - match ':state_code/:city/:name/donate' => 'nonprofits#donate', :as => :nonprofit_donation - match ':state_code/:city/:name/button' => 'nonprofits/button#guided' + match ':state_code/:city/:name' => 'nonprofits#show', :as => :nonprofit_location, via: [:get, :post] + match ':state_code/:city/:name/donate' => 'nonprofits#donate', :as => :nonprofit_donation, via: [:get, :post] + match ':state_code/:city/:name/button' => 'nonprofits/button#guided', via: [:get, :post] # Campaigns - match ':state_code/:city/:name/campaigns' => 'campaigns#index' - match ':state_code/:city/:name/campaigns/:campaign_slug' => 'campaigns#show', :as => :campaign_loc - match ':state_code/:city/:name/campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', :as => :campaign_loc - match '/peer-to-peer' => 'campaigns#peer_to_peer' + match ':state_code/:city/:name/campaigns' => 'campaigns#index', via: [:get, :post] + match ':state_code/:city/:name/campaigns/:campaign_slug' => 'campaigns#show', via: [:get, :post] + match ':state_code/:city/:name/campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', via: [:get, :post] + match '/peer-to-peer' => 'campaigns#peer_to_peer', via: [:get, :post] # Events - match ':state_code/:city/:name/events' => 'events#index' - match ':state_code/:city/:name/events/:event_slug' => 'events#show' - match ':state_code/:city/:name/events/:event_slug/stats' => 'events#stats' - match ':state_code/:city/:name/events/:event_slug/tickets' => 'tickets#index' + match ':state_code/:city/:name/events' => 'events#index', via: [:get, :post] + match ':state_code/:city/:name/events/:event_slug' => 'events#show', via: [:get, :post] + match ':state_code/:city/:name/events/:event_slug/stats' => 'events#stats', via: [:get, :post] + match ':state_code/:city/:name/events/:event_slug/tickets' => 'tickets#index', via: [:get, :post] # get '/events' => 'events#index' # Dashboard - match ':state_code/:city/:name/dashboard' => 'nonprofits#dashboard', as: :np_dashboard + match ':state_code/:city/:name/dashboard' => 'nonprofits#dashboard', as: :np_dashboard, via: [:get, :post] # Misc get '/pages/wp-plugin', to: redirect('/help/wordpress-plugin') #temporary, until WP plugin updated @@ -248,7 +248,7 @@ Commitchange::Application.routes.draw do get '/maps/specific-npo-supporters' => 'maps#specific_npo_supporters' # Mailchimp Landing - match '/mailchimp-landing' => 'nonprofits/nonprofit_keys#mailchimp_landing' + match '/mailchimp-landing' => 'nonprofits/nonprofit_keys#mailchimp_landing', via: [:get, :post] # Webhooks post '/webhooks/stripe_subscription_payment' => 'webhooks#subscription_payment' diff --git a/config/secrets.yml b/config/secrets.yml new file mode 100644 index 00000000..499f969f --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,22 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rake secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +development: + secret_key_base: 2d40128da31b5d45c2db72181b23eb1d2ca216517e033921a07febee5350179627b4ea75f898b71e2641df86ceed0e45a8a052731a1ce8420fe07d0f3840688d + +test: + secret_key_base: e0cdefb8725ea588ef3d2786bbfe5b79c2394f9c2203662c246a5fbdf20aeb3ecf4ae81f27d276139c661ad7091fc0060621edba2837d55b0fe7726a2de359c6 + +# Do not keep production secrets in the repository, +# instead read values from the environment. +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/db/structure.sql b/db/structure.sql index 0587bd47..416ee5e2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -3,7 +3,7 @@ -- -- Dumped from database version 9.6.5 --- Dumped by pg_dump version 9.6.11 +-- Dumped by pg_dump version 9.6.10 SET statement_timeout = 0; SET lock_timeout = 0; diff --git a/lib/create/create_campaign.rb b/lib/create/create_campaign.rb index b9b7dd03..7233d661 100644 --- a/lib/create/create_campaign.rb +++ b/lib/create/create_campaign.rb @@ -2,4 +2,32 @@ module CreateCampaign CAMPAIGN_NAME_LENGTH_LIMIT = 60 + + # @return [Object] a json object for historical purposes + def self.create(params, nonprofit) + Time.use_zone(nonprofit.timezone || 'UTC') do + params[:campaign][:end_datetime] = Chronic.parse(params[:campaign][:end_datetime]) if params[:campaign][:end_datetime].present? + end + + if !params[:campaign][:parent_campaign_id] + campaign = nonprofit.campaigns.create params[:campaign] + + #do notifications + user = campaign.profile.user + Role.create(name: :campaign_editor, user_id: user.id, host: self) + CampaignMailer.delay.creation_followup(self) + NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, self.nonprofit_id) + + return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty? + return campaign.as_json + #json_saved campaign, 'Campaign created! Well done.' + else + profile_id = params[:campaign][:profile_id] + Profile.find(profile_id).update_attributes params[:profile] + return CreatePeerToPeerCampaign.create(params[:campaign], profile_id) + end + end + + + end \ No newline at end of file diff --git a/lib/email.rb b/lib/email.rb index 4b34cb5d..d255f6e6 100644 --- a/lib/email.rb +++ b/lib/email.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Email - Regex ||= /^[^ ]+@[^ ]+\.[^ ]+/i + Regex ||= /\A[^ ]+@[^ ]+\.[^ ]+/i #PsqlRegex ||= '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$' end diff --git a/lib/generators/api/resource/templates/spec.rb.erb b/lib/generators/api/resource/templates/spec.rb.erb index c47d73e6..66d129b1 100644 --- a/lib/generators/api/resource/templates/spec.rb.erb +++ b/lib/generators/api/resource/templates/spec.rb.erb @@ -2,7 +2,7 @@ require 'rails_helper' describe Houdini::V1::<%= name.camelcase %>, :type => :request do - describe :get do + describe 'get', :get do end end \ No newline at end of file diff --git a/spec/api/houdini/nonprofit_spec.rb b/spec/api/houdini/nonprofit_spec.rb index daddc8ba..75ab3a7d 100644 --- a/spec/api/houdini/nonprofit_spec.rb +++ b/spec/api/houdini/nonprofit_spec.rb @@ -1,18 +1,18 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' -describe Houdini::V1::Nonprofit, :type => :controller do - describe :get do +describe Houdini::V1::Nonprofit, :type => :request do + describe 'get' do end - describe :post do - around {|e| + describe 'post' do + around(:each) do |example| @old_bp =Settings.default_bp - e.run + example.run Settings.default_bp = @old_bp - } + end def expect_validation_errors(actual, input) expected_errors = input.with_indifferent_access[:errors] expect(actual["errors"]).to match_array expected_errors @@ -47,7 +47,7 @@ describe Houdini::V1::Nonprofit, :type => :controller do }.with_indifferent_access } describe 'authorization' do - around {|e| + around(:each) {|e| Rails.configuration.action_controller.allow_forgery_protection = true e.run Rails.configuration.action_controller.allow_forgery_protection = false diff --git a/spec/controllers/campaign_gift_options_spec.rb b/spec/controllers/campaign_gift_options_spec.rb index d2878734..84d20f4f 100644 --- a/spec/controllers/campaign_gift_options_spec.rb +++ b/spec/controllers/campaign_gift_options_spec.rb @@ -11,14 +11,14 @@ describe CampaignGiftOptionsController, :type => :controller do end describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end describe 'destroy' do - include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end describe 'update_order' do - include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end end @@ -28,7 +28,7 @@ describe CampaignGiftOptionsController, :type => :controller do end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" end end end diff --git a/spec/controllers/campaigns_spec.rb b/spec/controllers/campaigns_spec.rb index a7cf07f8..0841b4b6 100644 --- a/spec/controllers/campaigns_spec.rb +++ b/spec/controllers/campaigns_spec.rb @@ -15,15 +15,15 @@ describe CampaignsController, :type => :controller do end describe 'duplicate' do - include_context :open_to_confirmed_users, :post, :duplicate, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_confirmed_users, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_campaign end describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_campaign end describe 'soft_delete' do - include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_campaign end end @@ -33,33 +33,34 @@ describe CampaignsController, :type => :controller do end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_campaign end describe 'activities' do - include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_campaign end describe 'metrics' do - include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_campaign end describe 'timeline' do - include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, id: :__our_campaign end describe 'totals' do - include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, id: :__our_campaign end describe 'peer_to_peer' do include_context :open_to_all, :get, :peer_to_peer, nonprofit_id: :__our_np end + end + end - - - - + describe 'routes' do + it "routes campaigns#index" do + expect(:get => "/nonprofits/5/campaigns/4").to(route_to(:controller => "campaigns", :action => "show", nonprofit_id: "5", id: "4")) end end end \ No newline at end of file diff --git a/spec/controllers/event_discounts_spec.rb b/spec/controllers/event_discounts_spec.rb index 37cfcaba..4a723b8f 100644 --- a/spec/controllers/event_discounts_spec.rb +++ b/spec/controllers/event_discounts_spec.rb @@ -11,11 +11,11 @@ describe EventDiscountsController, :type => :controller do end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end @@ -23,7 +23,7 @@ describe EventDiscountsController, :type => :controller do describe 'open to all' do describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" end end end diff --git a/spec/controllers/events_spec.rb b/spec/controllers/events_spec.rb index 7bef9f29..09e4f6b0 100644 --- a/spec/controllers/events_spec.rb +++ b/spec/controllers/events_spec.rb @@ -6,19 +6,19 @@ describe EventsController, :type => :controller do describe 'authorization' do include_context :shared_user_context describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, id: :__our_event end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_event end describe 'duplicate' do - include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_event end describe 'soft_delete' do - include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_event end describe 'stats' do - include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, id: :__our_event end describe 'name_and_id' do @@ -36,14 +36,14 @@ describe EventsController, :type => :controller do end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_event end describe 'activities' do - include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np + include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_event end describe 'metrics' do - include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np + include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_event end diff --git a/spec/controllers/nonprofits/activities_spec.rb b/spec/controllers/nonprofits/activities_spec.rb index 3b59f248..34800fcd 100644 --- a/spec/controllers/nonprofits/activities_spec.rb +++ b/spec/controllers/nonprofits/activities_spec.rb @@ -7,7 +7,7 @@ describe Nonprofits::ActivitiesController, :type => :controller do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'get' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :index, id: :__our_np end end end diff --git a/spec/controllers/nonprofits/custom_field_masters_spec.rb b/spec/controllers/nonprofits/custom_field_masters_spec.rb index dcdb1f63..a7bf7953 100644 --- a/spec/controllers/nonprofits/custom_field_masters_spec.rb +++ b/spec/controllers/nonprofits/custom_field_masters_spec.rb @@ -14,7 +14,7 @@ describe Nonprofits::CustomFieldMastersController, :type => :controller do end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end end \ No newline at end of file diff --git a/spec/controllers/nonprofits/custom_fields_joins_spec.rb b/spec/controllers/nonprofits/custom_fields_joins_spec.rb index c6c02cc3..5a8fd8c1 100644 --- a/spec/controllers/nonprofits/custom_fields_joins_spec.rb +++ b/spec/controllers/nonprofits/custom_fields_joins_spec.rb @@ -10,11 +10,11 @@ describe Nonprofits::CustomFieldJoinsController, :type => :controller do end describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: "1" end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" end end end \ No newline at end of file diff --git a/spec/controllers/nonprofits/donations_spec.rb b/spec/controllers/nonprofits/donations_spec.rb index 24e45032..f2cdb4f7 100644 --- a/spec/controllers/nonprofits/donations_spec.rb +++ b/spec/controllers/nonprofits/donations_spec.rb @@ -9,14 +9,14 @@ describe Nonprofits::DonationsController, :type => :controller do describe 'rejects unauthenticated users' do describe 'index' do include_context :shared_user_context - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, id: "1" end describe 'update' do include_context :shared_user_context - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" end @@ -27,7 +27,7 @@ describe Nonprofits::DonationsController, :type => :controller do end describe 'follow up' do - include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np + include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np, id: "1" end end end diff --git a/spec/controllers/nonprofits/payments_spec.rb b/spec/controllers/nonprofits/payments_spec.rb index a23537d8..7750b6df 100644 --- a/spec/controllers/nonprofits/payments_spec.rb +++ b/spec/controllers/nonprofits/payments_spec.rb @@ -14,15 +14,15 @@ describe Nonprofits::PaymentsController, :type => :controller do end describe 'show payments' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' end describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' end describe 'destroy payment' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end end \ No newline at end of file diff --git a/spec/controllers/nonprofits/payouts_spec.rb b/spec/controllers/nonprofits/payouts_spec.rb index 677b4625..82a5fc96 100644 --- a/spec/controllers/nonprofits/payouts_spec.rb +++ b/spec/controllers/nonprofits/payouts_spec.rb @@ -14,7 +14,7 @@ describe Nonprofits::PayoutsController, :type => :controller do end describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' end diff --git a/spec/controllers/nonprofits/recurring_donations_spec.rb b/spec/controllers/nonprofits/recurring_donations_spec.rb index a218a1f4..4ad14e70 100644 --- a/spec/controllers/nonprofits/recurring_donations_spec.rb +++ b/spec/controllers/nonprofits/recurring_donations_spec.rb @@ -14,15 +14,15 @@ describe Nonprofits::RecurringDonationsController, :type => :controller do end describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' end diff --git a/spec/controllers/nonprofits/supporters_spec.rb b/spec/controllers/nonprofits/supporters_spec.rb index 0c3e473c..ac544e24 100644 --- a/spec/controllers/nonprofits/supporters_spec.rb +++ b/spec/controllers/nonprofits/supporters_spec.rb @@ -14,23 +14,23 @@ describe Nonprofits::SupportersController, :type => :controller do end describe 'show' do - include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' end describe 'email_address' do - include_context :open_to_np_associate, :get, :email_address, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :email_address, nonprofit_id: :__our_np, id: '1' end describe 'full_contact' do - include_context :open_to_np_associate, :get, :full_contact, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :full_contact, nonprofit_id: :__our_np, id: '1' end describe 'info_card' do - include_context :open_to_np_associate, :get, :info_card, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :info_card, nonprofit_id: :__our_np, id: '1' end describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' end describe 'bulk_delete' do diff --git a/spec/controllers/nonprofits/tag_joins_spec.rb b/spec/controllers/nonprofits/tag_joins_spec.rb index 927fef46..1f996909 100644 --- a/spec/controllers/nonprofits/tag_joins_spec.rb +++ b/spec/controllers/nonprofits/tag_joins_spec.rb @@ -10,11 +10,11 @@ describe Nonprofits::TagJoinsController, :type => :controller do end describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end diff --git a/spec/controllers/nonprofits/tag_masters_spec.rb b/spec/controllers/nonprofits/tag_masters_spec.rb index 5ad258a6..999f4072 100644 --- a/spec/controllers/nonprofits/tag_masters_spec.rb +++ b/spec/controllers/nonprofits/tag_masters_spec.rb @@ -15,7 +15,7 @@ describe Nonprofits::TagMastersController, :type => :controller do end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end end diff --git a/spec/controllers/nonprofits_spec.rb b/spec/controllers/nonprofits_spec.rb index ec4099c3..67b6fe6f 100644 --- a/spec/controllers/nonprofits_spec.rb +++ b/spec/controllers/nonprofits_spec.rb @@ -7,54 +7,47 @@ describe NonprofitsController, :type => :controller do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'update' do - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :update, id: :__our_np end describe 'dashboard' do - include_context :open_to_np_associate, :get, :dashboard, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :dashboard, id: :__our_np end describe 'dashboard_metrics' do - include_context :open_to_np_associate, :get, :dashboard_metrics, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :dashboard_metrics, id: :__our_np end describe 'verify_identity' do - include_context :open_to_np_associate, :put, :verify_identity, nonprofit_id: :__our_np + include_context :open_to_np_associate, :put, :verify_identity, id: :__our_np end describe 'recurring_donation_stats' do - include_context :open_to_np_associate, :get, :recurring_donation_stats, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :recurring_donation_stats, id: :__our_np end describe 'profile_todos' do - include_context :open_to_np_associate, :get, :profile_todos, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :profile_todos, id: :__our_np end describe 'dashboard_todos' do - include_context :open_to_np_associate, :get, :dashboard_todos, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :dashboard_todos, id: :__our_np end describe 'payment_history' do - include_context :open_to_np_associate, :get, :payment_history, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :payment_history, id: :__our_np end describe 'destroy' do - include_context :open_to_super_admin, :delete, :destroy + include_context :open_to_super_admin, :delete, :destroy, id: :__our_np end - - - - - - - end describe 'open to all' do describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np + include_context :open_to_all, :get, :show, id: :__our_np end describe 'create' do @@ -62,19 +55,19 @@ describe NonprofitsController, :type => :controller do end describe 'btn' do - include_context :open_to_all, :get, :btn, nonprofit_id: :__our_np + include_context :open_to_all, :get, :btn, id: :__our_np end describe 'supporter_form' do - include_context :open_to_all, :get, :supporter_form, nonprofit_id: :__our_np + include_context :open_to_all, :get, :supporter_form, id: :__our_np end describe 'custom_supporter' do - include_context :open_to_all, :post, :custom_supporter, nonprofit_id: :__our_np + include_context :open_to_all, :post, :custom_supporter, id: :__our_np end describe 'donate' do - include_context :open_to_all, :get, :donate, nonprofit_id: :__our_np + include_context :open_to_all, :get, :donate, id: :__our_np end describe 'search' do diff --git a/spec/controllers/profiles_spec.rb b/spec/controllers/profiles_spec.rb index 181fa3a1..764f08b5 100644 --- a/spec/controllers/profiles_spec.rb +++ b/spec/controllers/profiles_spec.rb @@ -21,7 +21,7 @@ describe ProfilesController, :type => :controller do describe 'open to all' do describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np + include_context :open_to_all, :get, :show, id: :__our_np end end end diff --git a/spec/controllers/recurring_donations_spec.rb b/spec/controllers/recurring_donations_spec.rb index 5876b6e0..122a04cc 100644 --- a/spec/controllers/recurring_donations_spec.rb +++ b/spec/controllers/recurring_donations_spec.rb @@ -7,22 +7,20 @@ describe RecurringDonationsController, :type => :controller do include_context :shared_user_context describe 'open to all (note: edit token is checked inside methods)' do describe 'edit' do - include_context :open_to_all, :get, :edit, nonprofit_id: :__our_np + include_context :open_to_all, :get, :edit, nonprofit_id: :__our_np, id: '1' end describe 'destroy' do - include_context :open_to_all, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_all, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end describe 'update' do - include_context :open_to_all, :put, :update, nonprofit_id: :__our_np + include_context :open_to_all, :put, :update, nonprofit_id: :__our_np, id: '1' end describe 'update_amount' do - include_context :open_to_all, :put, :update_amount, nonprofit_id: :__our_np + include_context :open_to_all, :put, :update_amount, nonprofit_id: :__our_np, id: '1' end - - end end end \ No newline at end of file diff --git a/spec/controllers/roles_spec.rb b/spec/controllers/roles_spec.rb index cfc87a30..6b746d62 100644 --- a/spec/controllers/roles_spec.rb +++ b/spec/controllers/roles_spec.rb @@ -11,7 +11,7 @@ describe RolesController, :type => :controller do end describe 'destroy' do - include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np + include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end diff --git a/spec/controllers/ticket_levels_spec.rb b/spec/controllers/ticket_levels_spec.rb index 53687df7..d9b5cd6f 100644 --- a/spec/controllers/ticket_levels_spec.rb +++ b/spec/controllers/ticket_levels_spec.rb @@ -7,27 +7,27 @@ describe TicketLevelsController, :type => :controller do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end describe 'update_order' do include_context :open_to_event_editor, :put, :update_order, nonprofit_id: :__our_np, event_id: :__our_event end describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" end end describe 'open to all' do describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event end end end diff --git a/spec/lib/create/create_campaign_spec.rb b/spec/lib/create/create_campaign_spec.rb new file mode 100644 index 00000000..a44170a5 --- /dev/null +++ b/spec/lib/create/create_campaign_spec.rb @@ -0,0 +1,8 @@ +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later +require 'rails_helper' + +describe CreateCampaign do + it 'is untested' do + pending 'add tests here' + end +end \ No newline at end of file diff --git a/spec/lib/query/query_donations_spec.rb b/spec/lib/query/query_donations_spec.rb index 3741b275..34088427 100644 --- a/spec/lib/query/query_donations_spec.rb +++ b/spec/lib/query/query_donations_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe QueryDonations do - describe :campaign_export do + describe 'campaign_export' do let(:nonprofit) {force_create(:nonprofit)} let(:supporter) {force_create(:supporter)} From 881e42cc0b7c9c2559e463534cc9d331f6dd93db Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Wed, 16 Jan 2019 14:33:21 -0600 Subject: [PATCH 10/77] Correct rubocop warning --- spec/factories/billing_plans.rb | 4 ++-- spec/factories/campaign_gift_options.rb | 2 +- spec/factories/cards.rb | 8 ++++---- spec/factories/custom_field_joins.rb | 10 +++++----- spec/factories/custom_field_masters.rb | 4 ++-- spec/factories/events.rb | 14 +++++++------- spec/factories/nonprofits.rb | 12 ++++++------ spec/factories/payment_imports.rb | 4 ++-- spec/factories/supporters.rb | 2 +- spec/factories/tag_joins.rb | 8 ++++---- spec/factories/users.rb | 2 +- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/spec/factories/billing_plans.rb b/spec/factories/billing_plans.rb index 05ffea0c..a86c08ac 100644 --- a/spec/factories/billing_plans.rb +++ b/spec/factories/billing_plans.rb @@ -1,8 +1,8 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :billing_plan do - amount 0 - name 'Default Plan' + amount { 0 } + name { 'Default Plan' } trait :default do end diff --git a/spec/factories/campaign_gift_options.rb b/spec/factories/campaign_gift_options.rb index 31efecee..48f8e08b 100644 --- a/spec/factories/campaign_gift_options.rb +++ b/spec/factories/campaign_gift_options.rb @@ -3,6 +3,6 @@ FactoryBot.define do factory :campaign_gift_option do sequence(:name) {|i| "name_#{i}"} campaign - amount_one_time 200 + amount_one_time { 200 } end end diff --git a/spec/factories/cards.rb b/spec/factories/cards.rb index a26d490b..5dd70c97 100644 --- a/spec/factories/cards.rb +++ b/spec/factories/cards.rb @@ -3,14 +3,14 @@ FactoryBot.define do factory :card do factory :active_card_1 do - name 'card 1' + name { 'card 1' } end factory :active_card_2 do - name 'card 1' + name { 'card 1' } end factory :inactive_card do - name 'card 1' - inactive true + name { 'card 1' } + inactive { true } end diff --git a/spec/factories/custom_field_joins.rb b/spec/factories/custom_field_joins.rb index cbaab8f2..ae2c56c1 100644 --- a/spec/factories/custom_field_joins.rb +++ b/spec/factories/custom_field_joins.rb @@ -1,11 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :custom_field_join do - custom_field_master_id 1 - supporter_id 4 - created_at DateTime.now - updated_at DateTime.now - value 'value' + custom_field_master_id { 1 } + supporter_id { 4 } + created_at { DateTime.now } + updated_at { DateTime.now } + value { 'value' } trait :value_from_id do after(:create) do |cfj| diff --git a/spec/factories/custom_field_masters.rb b/spec/factories/custom_field_masters.rb index b8b45d84..cc1848ef 100644 --- a/spec/factories/custom_field_masters.rb +++ b/spec/factories/custom_field_masters.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :custom_field_master do - nonprofit "" - name "MyString" + nonprofit { "" } + name { "MyString" } end end diff --git a/spec/factories/events.rb b/spec/factories/events.rb index b5307176..50557398 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -1,13 +1,13 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :event do - name "The event of Wonders" - start_datetime DateTime.new(2025, 5, 11, 4,5,6) - end_datetime DateTime.new(2025, 5, 11, 5,1,7) - address "100 N Appleton St" - city "Appleton" - state_code "WI" - slug "event-of-wonders" + name { "The event of Wonders" } + start_datetime { DateTime.new(2025, 5, 11, 4,5,6) } + end_datetime { DateTime.new(2025, 5, 11, 5,1,7) } + address { "100 N Appleton St" } + city { "Appleton" } + state_code { "WI" } + slug { "event-of-wonders" } nonprofit profile end diff --git a/spec/factories/nonprofits.rb b/spec/factories/nonprofits.rb index c555f9a0..d32be4de 100644 --- a/spec/factories/nonprofits.rb +++ b/spec/factories/nonprofits.rb @@ -1,12 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :nonprofit do - name "spec_nonprofit_full" - city 'Albuquerque' - state_code 'NM' - zip_code 55555 - email "example@email.com" - slug 'sluggy-sluggo' + name { "spec_nonprofit_full" } + city { 'Albuquerque' } + state_code { 'NM' } + zip_code { 55555 } + email { "example@email.com" } + slug { 'sluggy-sluggo' } factory :nonprofit_with_cards do diff --git a/spec/factories/payment_imports.rb b/spec/factories/payment_imports.rb index 6dd38917..b42c0cce 100644 --- a/spec/factories/payment_imports.rb +++ b/spec/factories/payment_imports.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :payment_import do - user "" - nonprofit "" + user { "" } + nonprofit { "" } end end diff --git a/spec/factories/supporters.rb b/spec/factories/supporters.rb index 7a7c665e..2b119a5c 100644 --- a/spec/factories/supporters.rb +++ b/spec/factories/supporters.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :supporter do - name "Fake Supporter Name" + name { "Fake Supporter Name" } nonprofit trait :has_a_card do diff --git a/spec/factories/tag_joins.rb b/spec/factories/tag_joins.rb index 626dcd9e..9bee566a 100644 --- a/spec/factories/tag_joins.rb +++ b/spec/factories/tag_joins.rb @@ -1,9 +1,9 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later FactoryBot.define do factory :tag_join do - tag_master_id 1 - supporter_id 4 - created_at DateTime.now - updated_at DateTime.now + tag_master_id { 1 } + supporter_id { 4 } + created_at { DateTime.now } + updated_at { DateTime.now } end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index c3f28efc..2ba069e4 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -2,6 +2,6 @@ FactoryBot.define do factory :user do sequence(:email) {|i| "user#{i}@example.string.com"} - password "whocares" + password { "whocares" } end end From a5903d9daf50d8961d18b2d60dbddb4873c5ea7f Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Wed, 16 Jan 2019 14:38:59 -0600 Subject: [PATCH 11/77] Correct blocklist name WIP --- config/environments/test.rb | 4 ++-- config/initializers/block_ips.rb | 2 +- spec/controllers/events_spec.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/environments/test.rb b/config/environments/test.rb index 48544a21..728e452a 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,11 +1,11 @@ -Rails.application.configure do +Commitchange::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 + config.cache_classes = false # 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 diff --git a/config/initializers/block_ips.rb b/config/initializers/block_ips.rb index 5e547e78..ed9f52f0 100644 --- a/config/initializers/block_ips.rb +++ b/config/initializers/block_ips.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Rack::Attack.blacklist('block charge abusers') do |req| +Rack::Attack.blocklist('block charge abusers') do |req| ['54.159.242.229', '54.161.246.233', '54.211.94.199' diff --git a/spec/controllers/events_spec.rb b/spec/controllers/events_spec.rb index 09e4f6b0..5d832eb6 100644 --- a/spec/controllers/events_spec.rb +++ b/spec/controllers/events_spec.rb @@ -15,7 +15,7 @@ describe EventsController, :type => :controller do include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_event end describe 'soft_delete' do - include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, event_id: :__our_event end describe 'stats' do include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, id: :__our_event From 30accb5e7922579a23eb8742fa96b1e6b4723f1a Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 25 Jan 2019 16:22:05 -0600 Subject: [PATCH 12/77] Add solargraph --- Gemfile | 1 + Gemfile.lock | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/Gemfile b/Gemfile index 647c0c7f..cd0d63c9 100755 --- a/Gemfile +++ b/Gemfile @@ -116,6 +116,7 @@ group :development, :ci, :test do gem 'factory_bot_rails' gem 'action_mailer_matchers' gem 'simplecov', '~> 0.16.1', require: false + gem 'solargraph' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index aa61483f..947a66ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,6 +67,7 @@ GEM amq-protocol (2.2.0) andand (1.3.3) arel (5.0.1.20140414130214) + ast (2.4.0) aws-eventstream (1.0.1) aws-partitions (1.110.0) aws-sdk (1.67.0) @@ -96,6 +97,7 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) + backport (0.3.0) bcrypt (3.1.12) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) @@ -239,6 +241,7 @@ GEM hashie (3.6.0) heroku-deflater (0.6.3) rack (>= 1.4.5) + htmlentities (4.3.4) http-cookie (1.0.3) domain_name (~> 0.5) httparty (0.16.2) @@ -249,9 +252,11 @@ GEM i18n (>= 0.6.6, < 2) i18n_data (0.8.0) ice_nine (0.11.2) + jaro_winkler (1.5.2) jmespath (1.4.0) json (1.8.6) kdtree (0.4) + kramdown (1.17.0) lograge (0.10.0) actionpack (>= 4) activesupport (>= 4) @@ -284,6 +289,8 @@ GEM mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) parallel (1.12.1) + parser (2.6.0.0) + ast (~> 2.4.0) pg (0.21.0) polyglot (0.3.5) power_assert (1.1.1) @@ -331,6 +338,7 @@ GEM rack-ssl (~> 1.3.2) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) + rainbow (3.0.0) rake (12.3.2) request_store (1.4.1) rack (>= 1.4) @@ -341,6 +349,8 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) + reverse_markdown (1.1.0) + nokogiri roadie (3.4.0) css_parser (~> 1.4) nokogiri (~> 1.5) @@ -368,9 +378,18 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.0) + rubocop (0.63.1) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.5, != 2.5.1.1) + powerpack (~> 0.1) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 1.4.0) ruby-debug-ide (0.6.1) rake (>= 0.8.1) ruby-prof (0.15.9) + ruby-progressbar (1.10.0) safe_yaml (1.0.4) sass (3.2.19) sass-rails (5.0.7) @@ -385,6 +404,17 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.2) sixarm_ruby_unaccent (1.2.0) + solargraph (0.31.1) + backport (~> 0.3) + htmlentities (~> 4.3, >= 4.3.4) + jaro_winkler (~> 1.5) + kramdown (~> 1.16) + parser (~> 2.3) + reverse_markdown (~> 1.0, >= 1.0.5) + rubocop (~> 0.52) + thor (~> 0.19, >= 0.19.4) + tilt (~> 2.0) + yard (~> 0.9) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -410,6 +440,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.5) + unicode-display_width (1.4.1) unicode_utils (1.4.0) virtus (1.0.5) axiom-types (~> 0.1) @@ -423,6 +454,7 @@ GEM crack (>= 0.3.2) hashdiff xml-simple (1.1.5) + yard (0.9.18) PLATFORMS ruby @@ -494,6 +526,7 @@ DEPENDENCIES sass (= 3.2.19) sass-rails simplecov (~> 0.16.1) + solargraph sprockets stripe stripe-ruby-mock (~> 2.4.1)! From 3d27e97feea4a8aff664e8657de4ae0cdcdc065d Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 13:27:19 -0600 Subject: [PATCH 13/77] Fix bug where checking payment providers were validated improperly in rails 4.1 --- app/models/donation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/donation.rb b/app/models/donation.rb index d014f737..43f995c9 100644 --- a/app/models/donation.rb +++ b/app/models/donation.rb @@ -25,7 +25,7 @@ class Donation < ActiveRecord::Base validates :supporter, presence: true validates :nonprofit, presence: true validates_associated :charges - validates :payment_provider, inclusion: { in: %(credit_card sepa) }, allow_blank: true + validates :payment_provider, inclusion: { in: ["credit_card", "sepa"]}, allow_blank: true has_many :charges has_many :campaign_gifts, dependent: :destroy From 3f23b3df8e9cd67ca2446d76e4c42c621855112e Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 14:07:34 -0600 Subject: [PATCH 14/77] Turn delivery errors off in test environment --- config/environments/test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/environments/test.rb b/config/environments/test.rb index 728e452a..fb680fe0 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -30,6 +30,7 @@ Commitchange::Application.configure do # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test + config.action_mailer.raise_delivery_errors = false # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr From 5f7b284c4f08252136e3fe8c34ff34d0a33a8a1f Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 14:12:43 -0600 Subject: [PATCH 15/77] Fix bug where delete_card_for_ticket spec was failing --- spec/controllers/tickets_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/tickets_spec.rb b/spec/controllers/tickets_spec.rb index 6bda138d..b6b05885 100644 --- a/spec/controllers/tickets_spec.rb +++ b/spec/controllers/tickets_spec.rb @@ -19,7 +19,7 @@ describe TicketsController, :type => :controller do end describe 'delete_card_for_ticket' do - include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event, id: 11111 end From b4ebaa81024e843b870ff7fc94e5f75359700b0b Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 14:17:10 -0600 Subject: [PATCH 16/77] Fix routing bugs in TicketsController spec --- spec/controllers/tickets_spec.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/spec/controllers/tickets_spec.rb b/spec/controllers/tickets_spec.rb index b6b05885..23faaa04 100644 --- a/spec/controllers/tickets_spec.rb +++ b/spec/controllers/tickets_spec.rb @@ -6,32 +6,31 @@ describe TicketsController, :type => :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do - describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event - end + describe 'index' do - include_context :open_to_event_editor, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event end + describe 'update' do + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 + end describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end describe 'delete_card_for_ticket' do include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event, id: 11111 end - - end describe 'open to all' do describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event end describe 'add_note' do - include_context :open_to_all, :put, :add_note, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_all, :put, :add_note, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end end From cb1c5f2f8c54806e15229d072509e22d5daabebd Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 14:28:15 -0600 Subject: [PATCH 17/77] Fix route bugs for nonprofits_controller --- config/routes.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index b56dd437..ca533d11 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -121,11 +121,11 @@ Rails.application.routes.draw do resources(:nonprofits, {only: [:show, :create, :update, :destroy]}) do post(:onboard, {on: :collection}) - get(:profile_todos) - get(:recurring_donation_stats) + get(:profile_todos, {on: :member}) + get(:recurring_donation_stats, {on: :member}) get(:search, {on: :collection}) - get(:dashboard_todos) - put(:verify_identity) + get(:dashboard_todos, {on: :member}) + put(:verify_identity, {on: :member}) resources(:roles, {only: [:create, :destroy]}) From 568835c9bfa9ee3ff46415e4aba6c8f417977586 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 14:53:50 -0600 Subject: [PATCH 18/77] Fix a numb of invalid routes in Rails 4 --- config/routes.rb | 6 +++--- spec/controllers/nonprofits/activities_spec.rb | 2 +- spec/controllers/nonprofits/custom_fields_joins_spec.rb | 6 +++--- spec/controllers/nonprofits/tag_joins_spec.rb | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index ca533d11..b9265366 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -90,9 +90,9 @@ Rails.application.routes.draw do put :bulk_delete, on: :collection post :merge, on: :collection get :merge_data, on: :collection - get :info_card - get :email_address - get :full_contact + get :info_card, on: :member + get :email_address, on: :member + get :full_contact, on: :member get :index_metrics, on: :collection end diff --git a/spec/controllers/nonprofits/activities_spec.rb b/spec/controllers/nonprofits/activities_spec.rb index 34800fcd..ec3dd383 100644 --- a/spec/controllers/nonprofits/activities_spec.rb +++ b/spec/controllers/nonprofits/activities_spec.rb @@ -7,7 +7,7 @@ describe Nonprofits::ActivitiesController, :type => :controller do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'get' do - include_context :open_to_np_associate, :get, :index, id: :__our_np + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1111 end end end diff --git a/spec/controllers/nonprofits/custom_fields_joins_spec.rb b/spec/controllers/nonprofits/custom_fields_joins_spec.rb index 5a8fd8c1..ab3a4e2d 100644 --- a/spec/controllers/nonprofits/custom_fields_joins_spec.rb +++ b/spec/controllers/nonprofits/custom_fields_joins_spec.rb @@ -5,8 +5,8 @@ require 'controllers/support/shared_user_context' describe Nonprofits::CustomFieldJoinsController, :type => :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do - describe 'index ' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + describe 'index' do + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1 end describe 'modify' do @@ -14,7 +14,7 @@ describe Nonprofits::CustomFieldJoinsController, :type => :controller do end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1" + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1", supporter_id: 1 end end end \ No newline at end of file diff --git a/spec/controllers/nonprofits/tag_joins_spec.rb b/spec/controllers/nonprofits/tag_joins_spec.rb index 1f996909..a9ff6327 100644 --- a/spec/controllers/nonprofits/tag_joins_spec.rb +++ b/spec/controllers/nonprofits/tag_joins_spec.rb @@ -6,7 +6,7 @@ describe Nonprofits::TagJoinsController, :type => :controller do describe 'authorization' do include_context :shared_user_context describe 'index' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1 end describe 'modify' do @@ -14,7 +14,7 @@ describe Nonprofits::TagJoinsController, :type => :controller do end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 2 end From 438ecf16c8b8002cc9b369c28a3bb3888626a054 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 15:02:42 -0600 Subject: [PATCH 19/77] Correct spec for campaign_gift_options --- spec/controllers/campaigns/campaign_gift_options_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/campaigns/campaign_gift_options_spec.rb b/spec/controllers/campaigns/campaign_gift_options_spec.rb index 9627d7fc..58221ca4 100644 --- a/spec/controllers/campaigns/campaign_gift_options_spec.rb +++ b/spec/controllers/campaigns/campaign_gift_options_spec.rb @@ -5,9 +5,9 @@ require 'controllers/support/shared_user_context' describe Campaigns::CampaignGiftOptionsController, :type => :controller do describe 'authorization' do include_context :shared_user_context - describe 'reject unauthorized users' do + describe 'accept all' do describe 'index' do - include_context :open_to_campaign_editor, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end end From 964aadbfb17582a1f0b862ade81e30f59ef5b9f6 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 15:33:41 -0600 Subject: [PATCH 20/77] Correct bug in maintenance_spec.tb --- app/controllers/users/sessions_controller.rb | 2 +- spec/requests/maintenance_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index d9a4ad10..4ffebf7e 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Users::SessionsController < Devise::SessionsController layout 'layouts/apified', only: :new - + respond_to :json, only: :new def new @theme = 'minimal' diff --git a/spec/requests/maintenance_spec.rb b/spec/requests/maintenance_spec.rb index 407558bc..0a79ef56 100644 --- a/spec/requests/maintenance_spec.rb +++ b/spec/requests/maintenance_spec.rb @@ -85,7 +85,7 @@ describe 'Maintenance Mode' do it 'allows sign_in.json' do get(:new, {maintenance_token: "#{token}", format: 'json'}) - expect(response.code).to eq '406' + expect(response.code).to eq '200' end end end From cc24183cb958be96b976bae4c7fc85004b707e26 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 15:52:37 -0600 Subject: [PATCH 21/77] Fix some quirky test issues with non-reloaded entities --- spec/lib/update/update_charges_spec.rb | 5 +++++ spec/lib/update/update_payouts_spec.rb | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/spec/lib/update/update_charges_spec.rb b/spec/lib/update/update_charges_spec.rb index 96807c27..6b4606ea 100644 --- a/spec/lib/update/update_charges_spec.rb +++ b/spec/lib/update/update_charges_spec.rb @@ -23,6 +23,11 @@ describe UpdateCharges do let!(:refunds) { [force_create(:refund, charge: charges.last, payment: reverse_payment_for_refund, disbursed: true)]} before(:each) { UpdateCharges.reverse_disburse_all_with_payments([payment_to_reverse.id, payment_to_reverse_2.id, payment_to_reverse_with_refund.id, reverse_payment_for_refund.id]) + + payment_to_reverse.reload + payment_to_reverse_2.reload + payment_to_reverse_with_refund.reload + payment_to_ignore.reload } it 'reverses payments it should' do diff --git a/spec/lib/update/update_payouts_spec.rb b/spec/lib/update/update_payouts_spec.rb index 3ba466d6..27346611 100644 --- a/spec/lib/update/update_payouts_spec.rb +++ b/spec/lib/update/update_payouts_spec.rb @@ -65,6 +65,11 @@ describe UpdatePayouts do payout.payments.push(payment_to_reverse_with_refund) payout.payments.push(reverse_payment_for_refund) UpdatePayouts.reverse_with_stripe(payout.id, bad_status, bad_failure_message) + payment_to_reverse.reload + payment_to_reverse_2.reload + payment_to_reverse_with_refund.reload + reverse_payment_for_refund.reload + payment_to_ignore.reload } it 'reverses proper payments' do From a05f8582de425ccf780bd8e16f2010cb62059c14 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 16:03:08 -0600 Subject: [PATCH 22/77] Remove deprecated '.to_time_in_current_zone' usage --- spec/lib/update/update_donation_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/lib/update/update_donation_spec.rb b/spec/lib/update/update_donation_spec.rb index 16ab3eba..19bd7d4d 100644 --- a/spec/lib/update/update_donation_spec.rb +++ b/spec/lib/update/update_donation_spec.rb @@ -285,7 +285,7 @@ describe UpdateDonation do expect(Payment.count).to eq 1 - expected_offsite_payment= offsite_payment.attributes.merge({check_number:new_check_number, date: new_date.to_time_in_current_zone, gross_amount: new_amount, updated_at: Time.now}).with_indifferent_access + expected_offsite_payment= offsite_payment.attributes.merge({check_number:new_check_number, date: new_date.in_time_zone, gross_amount: new_amount, updated_at: Time.now}).with_indifferent_access offsite_payment.reload expect(offsite_payment.attributes).to eq expected_offsite_payment @@ -351,7 +351,7 @@ describe UpdateDonation do result = UpdateDonation.update_payment(donation.id, blank_data) expected_donation = donation.attributes.merge({ - date: new_date.to_time_in_current_zone, + date: new_date.in_time_zone, amount: new_amount, designation: '', @@ -367,13 +367,13 @@ describe UpdateDonation do donation.reload expect(donation.attributes).to eq expected_donation - expected_p1 = payment.attributes.merge({towards: '', updated_at: Time.now, date: new_date.to_time_in_current_zone, gross_amount: new_amount, fee_total: new_fee, net_amount: new_amount-new_fee}).with_indifferent_access + expected_p1 = payment.attributes.merge({towards: '', updated_at: Time.now, date: new_date.in_time_zone, gross_amount: new_amount, fee_total: new_fee, net_amount: new_amount-new_fee}).with_indifferent_access payment.reload expect(payment.attributes).to eq expected_p1 expect(Payment.count).to eq 1 - expected_offsite_payment= offsite_payment.attributes.merge({check_number:'', date: new_date.to_time_in_current_zone, gross_amount: new_amount, updated_at: Time.now}).with_indifferent_access + expected_offsite_payment= offsite_payment.attributes.merge({check_number:'', date: new_date.in_time_zone, gross_amount: new_amount, updated_at: Time.now}).with_indifferent_access offsite_payment.reload expect(offsite_payment.attributes).to eq expected_offsite_payment From dd53f11be94b188e5ab5acc5e1f68b59b5152398 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 16:28:22 -0600 Subject: [PATCH 23/77] Fix wrap parameters bug --- config/initializers/wrap_parameters.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 97b340a1..91d9a5eb 100755 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -11,5 +11,5 @@ end # To enable root element in JSON for ActiveRecord objects. ActiveSupport.on_load(:active_record) do - self.include_root_in_json = true + self.include_root_in_json = false end From d90d2b35059528aad3837b9ee563c2763ffd7715 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 16:33:39 -0600 Subject: [PATCH 24/77] Make CreateCampaign fail in pending --- spec/lib/create/create_campaign_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/lib/create/create_campaign_spec.rb b/spec/lib/create/create_campaign_spec.rb index a44170a5..94163ccb 100644 --- a/spec/lib/create/create_campaign_spec.rb +++ b/spec/lib/create/create_campaign_spec.rb @@ -4,5 +4,6 @@ require 'rails_helper' describe CreateCampaign do it 'is untested' do pending 'add tests here' + fail end end \ No newline at end of file From 07298a8cd04324ebe5890650fbd5477fde6afce8 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Mon, 28 Jan 2019 17:18:02 -0600 Subject: [PATCH 25/77] Rails v4.2 --- Gemfile | 4 +-- Gemfile.lock | 74 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/Gemfile b/Gemfile index cd0d63c9..2ad39ee4 100755 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' ruby '2.3.7' gem 'rake' -gem 'rails', '~> 4.1' +gem 'rails', '~> 4.2.8' gem 'rails_12factor' # https://stripe.com/docs/api gem 'stripe' @@ -72,7 +72,7 @@ gem 'httparty' # User authentication # https://github.com/plataformatec/devise -gem 'devise' +gem 'devise', '~> 3.5.0' gem 'devise-async' # http://www.rubygeocoder.com/ diff --git a/Gemfile.lock b/Gemfile.lock index 947a66ab..6968910b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -42,14 +42,16 @@ GEM remote: https://rubygems.org/ specs: action_mailer_matchers (1.0.0) - actionmailer (4.1.16) - actionpack (= 4.1.16) - actionview (= 4.1.16) + actionmailer (4.2.11) + actionpack (= 4.2.11) + actionview (= 4.2.11) + activejob (= 4.2.11) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.16) - actionview (= 4.1.16) - activesupport (= 4.1.16) - rack (~> 1.5.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.11) + actionview (= 4.2.11) + activesupport (= 4.2.11) + rack (~> 1.6) rack-test (~> 0.6.2) activemodel (4.0.0) activesupport (= 4.0.0) @@ -66,7 +68,7 @@ GEM addressable (2.3.8) amq-protocol (2.2.0) andand (1.3.3) - arel (5.0.1.20140414130214) + arel (6.0.4) ast (2.4.0) aws-eventstream (1.0.1) aws-partitions (1.110.0) @@ -132,6 +134,7 @@ GEM unicode_utils (~> 1.4) crack (0.4.3) safe_yaml (~> 1.0.0) + crass (1.0.4) css_parser (1.6.0) addressable dalli (2.7.9) @@ -203,8 +206,8 @@ GEM railties (>= 3.0.0) faraday (0.11.0) multipart-post (>= 1.2, < 3) - faraday_middleware (0.9.1) - faraday (>= 0.7.4, < 0.10) + faraday_middleware (0.13.0) + faraday (>= 0.7.4, < 1.0) font_assets (0.1.14) rack foreman (0.85.0) @@ -215,6 +218,8 @@ GEM hashie (>= 2.0, < 4.0) geocoder (1.5.0) get_process_mem (0.2.3) + globalid (0.4.2) + activesupport (>= 4.2.0) grape (1.1.0) activesupport builder @@ -262,6 +267,9 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) + loofah (2.2.3) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) mail_view (2.0.4) @@ -304,7 +312,7 @@ GEM puma (>= 2.7, < 4) rabl (0.14.0) activesupport (>= 2.3.14) - rack (1.5.5) + rack (1.6.11) rack-accept (0.4.5) rack (>= 0.4) rack-attack (5.4.2) @@ -314,16 +322,25 @@ GEM rack-test (0.6.3) rack (>= 1.0) rack-timeout (0.5.1) - rails (4.1.16) - actionmailer (= 4.1.16) - actionpack (= 4.1.16) - actionview (= 4.1.16) - activemodel (= 4.1.16) - activerecord (= 4.1.16) - activesupport (= 4.1.16) + rails (4.2.11) + actionmailer (= 4.2.11) + actionpack (= 4.2.11) + actionview (= 4.2.11) + activejob (= 4.2.11) + activemodel (= 4.2.11) + activerecord (= 4.2.11) + activesupport (= 4.2.11) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.16) - sprockets-rails (~> 2.0) + railties (= 4.2.11) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.9) + activesupport (>= 4.2.0, < 5.0) + nokogiri (~> 1.6) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) rails-i18n (4.0.9) i18n (~> 0.7) railties (~> 4.0) @@ -343,8 +360,9 @@ GEM request_store (1.4.1) rack (>= 1.4) require_all (2.0.0) - responders (1.1.2) - railties (>= 3.2, < 4.2) + responders (2.4.1) + actionpack (>= 4.2.0, < 6.0) + railties (>= 4.2.0, < 6.0) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) @@ -418,10 +436,10 @@ GEM sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (2.3.3) - actionpack (>= 3.0) - activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) stripe (1.58.0) rest-client (>= 1.4, < 4.0) table_print (1.5.6) @@ -477,7 +495,7 @@ DEPENDENCIES database_cleaner debase delayed_job_active_record - devise + devise (~> 3.5.0) devise-async dotenv-rails dry-validation @@ -514,7 +532,7 @@ DEPENDENCIES rack-attack rack-ssl rack-timeout - rails (~> 4.1) + rails (~> 4.2.8) rails-i18n (~> 4.0) rails_12factor rake From 938821ed5f173db0c9db8acd3bd45e48ecbc78b4 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Tue, 29 Jan 2019 14:13:52 -0600 Subject: [PATCH 26/77] Initial rails 4.2 --- Gemfile | 6 +- Gemfile.lock | 77 ++++++++++++------- bin/rails | 2 +- bin/setup | 29 +++++++ config/application.rb | 4 +- config/environments/development.rb | 6 ++ config/environments/production.rb | 8 +- config/environments/test.rb | 10 ++- config/initializers/assets.rb | 3 + config/initializers/cookies_serializer.rb | 2 +- config/routes.rb | 2 +- spec/controllers/nonprofits/donations_spec.rb | 19 ++--- 12 files changed, 116 insertions(+), 52 deletions(-) create mode 100755 bin/setup diff --git a/Gemfile b/Gemfile index 2ad39ee4..0704c524 100755 --- a/Gemfile +++ b/Gemfile @@ -30,9 +30,6 @@ gem 'aws-sdk', '~> 1' # for blocking ip addressses gem 'rack-attack' -# For modularizing javascript -# https://github.com/browserify-rails/browserify-rails -gem 'browserify-rails' gem 'sprockets' # for serving fonts on cdn @@ -75,6 +72,9 @@ gem 'httparty' gem 'devise', '~> 3.5.0' gem 'devise-async' +# https://github.com/airbrake/airbrake +gem 'airbrake', '~> 8.0.1' + # http://www.rubygeocoder.com/ gem 'geocoder' # for adding latitude and longitude to location-based tables diff --git a/Gemfile.lock b/Gemfile.lock index 6968910b..a63ce2f5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -53,20 +53,36 @@ GEM activesupport (= 4.2.11) rack (~> 1.6) rack-test (~> 0.6.2) - activemodel (4.0.0) - activesupport (= 4.0.0) - builder (~> 3.1.0) - activerecord (4.0.0) - activemodel (= 4.0.0) - activerecord-deprecated_finders (~> 1.0.2) - activesupport (= 4.0.0) - arel (~> 4.0.0) - activerecord-deprecated_finders (1.0.4) - activesupport (4.0.0) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) - addressable (2.3.8) - amq-protocol (2.2.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.11) + activesupport (= 4.2.11) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.11) + activesupport (= 4.2.11) + globalid (>= 0.3.0) + activemodel (4.2.11) + activesupport (= 4.2.11) + builder (~> 3.1) + activerecord (4.2.11) + activemodel (= 4.2.11) + activesupport (= 4.2.11) + arel (~> 6.0) + activesupport (4.2.11) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + airbrake (8.0.1) + airbrake-ruby (~> 3.0) + airbrake-ruby (3.1.0) + tdigest (= 0.1.1) + amq-protocol (2.3.0) andand (1.3.3) arel (6.0.4) ast (2.4.0) @@ -105,8 +121,6 @@ GEM debug_inspector (>= 0.0.1) bootsnap (1.3.2) msgpack (~> 1.0) - browserify-rails (1.1.0) - railties (>= 4.0.0, < 5.0) builder (3.2.3) bunny (2.12.0) amq-protocol (~> 2.3, >= 2.3.0) @@ -276,12 +290,16 @@ GEM tilt memcachier (0.0.2) method_source (0.9.1) - mime-types (1.25.1) - mini_magick (4.9.5) - mini_portile2 (2.1.0) - money (6.10.0) - i18n (>= 0.6.4, < 1.0) - msgpack (1.2.0) + mime-types (3.2.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2018.0812) + mini_magick (4.9.2) + mini_mime (1.0.1) + mini_portile2 (2.4.0) + minitest (5.11.3) + money (6.13.1) + i18n (>= 0.6.4, <= 2) + msgpack (1.2.4) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) @@ -293,10 +311,10 @@ GEM kdtree require_all netrc (0.11.0) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) + nokogiri (1.10.1) + mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) - parallel (1.12.1) + parallel (1.13.0) parser (2.6.0.0) ast (~> 2.4.0) pg (0.21.0) @@ -357,6 +375,7 @@ GEM thor (>= 0.18.1, < 2.0) rainbow (3.0.0) rake (12.3.2) + rbtree (0.4.2) request_store (1.4.1) rack (>= 1.4) require_all (2.0.0) @@ -422,7 +441,7 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.2) sixarm_ruby_unaccent (1.2.0) - solargraph (0.31.1) + solargraph (0.31.2) backport (~> 0.3) htmlentities (~> 4.3, >= 4.3.4) jaro_winkler (~> 1.5) @@ -443,6 +462,8 @@ GEM stripe (1.58.0) rest-client (>= 1.4, < 4.0) table_print (1.5.6) + tdigest (0.1.1) + rbtree (~> 0.4.2) test-unit (3.2.8) power_assert thor (0.19.4) @@ -479,11 +500,11 @@ PLATFORMS DEPENDENCIES action_mailer_matchers - aws-sdk + airbrake (~> 8.0.1) + aws-sdk (~> 1) aws-ses binding_of_caller bootsnap - browserify-rails bunny (>= 2.6.3) carrierwave carrierwave-aws diff --git a/bin/rails b/bin/rails index 728cd85a..5191e692 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../../config/application', __FILE__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/setup b/bin/setup new file mode 100755 index 00000000..acdb2c13 --- /dev/null +++ b/bin/setup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +Dir.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 || bundle install" + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # system "cp config/database.yml.sample config/database.yml" + # end + + puts "\n== Preparing database ==" + system "bin/rake db:setup" + + puts "\n== Removing old logs and tempfiles ==" + system "rm -f log/*" + system "rm -rf tmp/cache" + + puts "\n== Restarting application server ==" + system "touch tmp/restart.txt" +end diff --git a/config/application.rb b/config/application.rb index 32ee9cec..5e3539ca 100755 --- a/config/application.rb +++ b/config/application.rb @@ -79,9 +79,11 @@ module Commitchange config.i18n.enforce_available_locales = false + config.active_record.raise_in_transactional_callbacks = true + # Add trailing slashes to all routes # config.action_controller.default_url_options = {:trailing_slash => true} # - config.browserify_rails.commandline_options = "-t [ babelify --presets es2015 ]" + # config.browserify_rails.commandline_options = "-t [ babelify --presets es2015 ]" end end diff --git a/config/environments/development.rb b/config/environments/development.rb index eb0ad2c7..58af5b4a 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -49,6 +49,12 @@ Rails.application.configure do # Expands the lines which load the assets config.assets.debug = true + config.assets.digest = true + # Adds additional error checking when serving assets at runtime. + # Checks for improperly declared sprockets dependencies. + # Raises helpful error messages. + config.assets.raise_runtime_errors = true + config.log_level = :debug config.dependency_loading = true if $rails_rake_task diff --git a/config/environments/production.rb b/config/environments/production.rb index b93a877c..de874dbf 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -19,8 +19,9 @@ Rails.application.configure do # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. # config.action_dispatch.rack_cache = true - # Disable Rails's static asset server (Apache or nginx will already do this). - config.serve_static_assets = false + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier @@ -67,9 +68,6 @@ Rails.application.configure do # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify - # Disable automatic flushing of the log to improve performance. - # config.autoflush_log = false - # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new diff --git a/config/environments/test.rb b/config/environments/test.rb index fb680fe0..370aecb7 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -5,15 +5,15 @@ Commitchange::Application.configure do # 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 = false + 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 static asset server for tests with Cache-Control for performance. - config.serve_static_assets = true + # Configure static file server for tests with Cache-Control for performance. + config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. @@ -32,6 +32,10 @@ Commitchange::Application.configure do config.action_mailer.delivery_method = :test config.action_mailer.raise_delivery_errors = false + # Randomize the order test cases are executed. + config.active_support.test_order = :random + + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d2f4ec33..01ef3e66 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -3,6 +3,9 @@ # 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 + # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. # Rails.application.config.assets.precompile += %w( search.js ) diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7a06a89f..7f70458d 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,3 @@ # Be sure to restart your server when you modify this file. -Rails.application.config.action_dispatch.cookies_serializer = :json \ No newline at end of file +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/routes.rb b/config/routes.rb index b9265366..32c60eb3 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -103,7 +103,7 @@ Rails.application.routes.draw do resource(:miscellaneous_np_info, {only: [:show, :update]}) namespace(:button) do - root({to: :advanced}) + root({action: :advanced}) get(:basic) get(:guided) get(:advanced) diff --git a/spec/controllers/nonprofits/donations_spec.rb b/spec/controllers/nonprofits/donations_spec.rb index f2cdb4f7..79614910 100644 --- a/spec/controllers/nonprofits/donations_spec.rb +++ b/spec/controllers/nonprofits/donations_spec.rb @@ -32,18 +32,19 @@ describe Nonprofits::DonationsController, :type => :controller do end end -describe 'Nonprofits::DonationsController::create_offsite', :type => :request do +describe '.create_offsite', :type => :request do describe 'create_offsite' do include_context :shared_donation_charge_context - include_context :new_controller_user_context + include_context :general_shared_user_context + require 'support/contexts/general_shared_user_context.rb' - it 'reject non-campaign editors (and np authorized folks)' do - run_authorization_tests({method: :post, action: "/nonprofits/#{nonprofit.id}/donations/create_offsite", - successful_users: roles__open_to_campaign_editor}) do |_| - {nonprofit_id: nonprofit.id, - donation: {campaign_id: campaign.id}} - end - end + # it 'reject non-campaign editors (and np authorized folks)', :type => :request do + # run_authorization_tests({method: :post, action: "/nonprofits/#{nonprofit.id}/donations/create_offsite", + # successful_users: roles__open_to_campaign_editor}) do |_| + # {nonprofit_id: nonprofit.id, + # donation: {campaign_id: campaign.id}} + # end + # end #include_context :open_to_np_associate, :post, :create_offsite, nonprofit_id: :__our_np end end \ No newline at end of file From 133986cf40ac39b92ffdb1592119866944302425 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Tue, 29 Jan 2019 15:25:34 -0600 Subject: [PATCH 27/77] Update to Ruby 2.4 --- .ruby-version | 2 +- Gemfile | 2 +- docker/build/Dockerfile | 2 +- docker/debug/Dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ruby-version b/.ruby-version index 00355e29..59aa62c1 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.7 +2.4.5 diff --git a/Gemfile b/Gemfile index 0704c524..65b26f6b 100755 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -ruby '2.3.7' +ruby '2.4.5' gem 'rake' gem 'rails', '~> 4.2.8' gem 'rails_12factor' diff --git a/docker/build/Dockerfile b/docker/build/Dockerfile index 0440e52f..6ae5cf0a 100644 --- a/docker/build/Dockerfile +++ b/docker/build/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.3.7-stretch +FROM ruby:2.4.5-stretch ARG USER RUN mkdir /myapp COPY script/build/debian/prebuild.sh myapp/script/build/debian/prebuild.sh diff --git a/docker/debug/Dockerfile b/docker/debug/Dockerfile index e9c3469c..c9e5c3c6 100644 --- a/docker/debug/Dockerfile +++ b/docker/debug/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.3.7-stretch +FROM ruby:2.4.5-stretch ARG USER RUN mkdir /myapp COPY script/build/debian/prebuild.sh myapp/script/build/debian/prebuild.sh From 69cb2cbc5c89650d3b53aec2e2947e913210faa8 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Thu, 31 Jan 2019 17:11:34 -0600 Subject: [PATCH 28/77] Rails 5.0 builds --- Gemfile | 15 +++-- Gemfile.lock | 163 ++++++++++++++++++++++++--------------------------- 2 files changed, 85 insertions(+), 93 deletions(-) diff --git a/Gemfile b/Gemfile index 65b26f6b..b53407da 100755 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' ruby '2.4.5' gem 'rake' -gem 'rails', '~> 4.2.8' +gem 'rails', '= 5.0.0' gem 'rails_12factor' # https://stripe.com/docs/api gem 'stripe' @@ -69,7 +69,7 @@ gem 'httparty' # User authentication # https://github.com/plataformatec/devise -gem 'devise', '~> 3.5.0' +gem 'devise', '~> 4.4' gem 'devise-async' # https://github.com/airbrake/airbrake @@ -90,7 +90,7 @@ gem 'table_print' gem 'bunny', '>= 2.6.3' -gem 'rails-i18n', '~> 4.0' # For 3.x +gem 'rails-i18n' gem 'i18n-js' gem 'countries' @@ -136,10 +136,15 @@ gem 'dry-validation' # used only for config validation gem 'foreman' -gem 'grape', '~> 1.1.0' +gem 'grape' gem 'grape-entity' gem 'grape-swagger' gem 'grape-swagger-entity' gem 'grape_url_validator' gem 'grape_logging' -gem 'grape_devise', path: 'gems/grape_devise' +gem 'grape_devise' +#gem 'grape_devise', git: 'https://github.com/ericschultz/grape_devise.git' + +#gem 'protected_attributes' + +gem 'rack-ssl' diff --git a/Gemfile.lock b/Gemfile.lock index a63ce2f5..7b153a83 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,23 +8,6 @@ GIT multi_json (~> 1.0) stripe (>= 1.31.0, <= 1.58.0) -GIT - remote: https://github.com/ruby-grape/grape-entity.git - revision: 0e04aa561373b510c2486282979085eaef2ae663 - ref: 0e04aa561373b510c2486282979085eaef2ae663 - specs: - qx (0.1.1) - activerecord (>= 3.0) - colorize (~> 0.8) - -PATH - remote: gems/grape_devise - specs: - grape_devise (0.1.1) - devise (>= 2.2.8, < 5) - grape (> 0.7) - rails (> 3.2, < 6) - PATH remote: gems/ruby-param-validation specs: @@ -42,39 +25,42 @@ GEM remote: https://rubygems.org/ specs: action_mailer_matchers (1.0.0) - actionmailer (4.2.11) - actionpack (= 4.2.11) - actionview (= 4.2.11) - activejob (= 4.2.11) + actioncable (5.0.0) + actionpack (= 5.0.0) + nio4r (~> 1.2) + websocket-driver (~> 0.6.1) + actionmailer (5.0.0) + actionpack (= 5.0.0) + actionview (= 5.0.0) + activejob (= 5.0.0) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.11) - actionview (= 4.2.11) - activesupport (= 4.2.11) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.0.0) + actionview (= 5.0.0) + activesupport (= 5.0.0) + rack (~> 2.0) + rack-test (~> 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.11) - activesupport (= 4.2.11) + actionview (5.0.0) + activesupport (= 5.0.0) builder (~> 3.1) erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (4.2.11) - activesupport (= 4.2.11) - globalid (>= 0.3.0) - activemodel (4.2.11) - activesupport (= 4.2.11) - builder (~> 3.1) - activerecord (4.2.11) - activemodel (= 4.2.11) - activesupport (= 4.2.11) - arel (~> 6.0) - activesupport (4.2.11) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (5.0.0) + activesupport (= 5.0.0) + globalid (>= 0.3.6) + activemodel (5.0.0) + activesupport (= 5.0.0) + activerecord (5.0.0) + activemodel (= 5.0.0) + activesupport (= 5.0.0) + arel (~> 7.0) + activesupport (5.0.0) + concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) @@ -84,7 +70,7 @@ GEM tdigest (= 0.1.1) amq-protocol (2.3.0) andand (1.3.3) - arel (6.0.4) + arel (7.1.4) ast (2.4.0) aws-eventstream (1.0.1) aws-partitions (1.110.0) @@ -166,15 +152,15 @@ GEM delayed_job (>= 3.0, < 5) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (3.5.10) + devise (4.5.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 3.2.6, < 5) + railties (>= 4.1.0, < 6.0) responders - thread_safe (~> 0.1) warden (~> 1.2.3) - devise-async (0.10.2) - devise (>= 3.2, < 4.0) + devise-async (1.0.0) + activejob (>= 5.0) + devise (>= 4.0) diff-lcs (1.3) docile (1.3.1) domain_name (0.5.20180417) @@ -311,6 +297,7 @@ GEM kdtree require_all netrc (0.11.0) + nio4r (1.2.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) @@ -318,9 +305,9 @@ GEM parser (2.6.0.0) ast (~> 2.4.0) pg (0.21.0) - polyglot (0.3.5) - power_assert (1.1.1) - pry (0.11.3) + power_assert (1.1.3) + powerpack (0.1.2) + pry (0.12.0) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) @@ -330,7 +317,7 @@ GEM puma (>= 2.7, < 4) rabl (0.14.0) activesupport (>= 2.3.14) - rack (1.6.11) + rack (2.0.6) rack-accept (0.4.5) rack (>= 0.4) rack-attack (5.4.2) @@ -340,37 +327,35 @@ GEM rack-test (0.6.3) rack (>= 1.0) rack-timeout (0.5.1) - rails (4.2.11) - actionmailer (= 4.2.11) - actionpack (= 4.2.11) - actionview (= 4.2.11) - activejob (= 4.2.11) - activemodel (= 4.2.11) - activerecord (= 4.2.11) - activesupport (= 4.2.11) + rails (5.0.0) + actioncable (= 5.0.0) + actionmailer (= 5.0.0) + actionpack (= 5.0.0) + actionview (= 5.0.0) + activejob (= 5.0.0) + activemodel (= 5.0.0) + activerecord (= 5.0.0) + activesupport (= 5.0.0) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.11) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) + railties (= 5.0.0) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - rails-i18n (4.0.9) - i18n (~> 0.7) - railties (~> 4.0) + rails-i18n (5.1.3) + i18n (>= 0.7, < 2) + railties (>= 5.0, < 6) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_serve_static_assets (0.0.4) - rails_stdout_logging (0.0.3) - railties (3.2.22.5) - actionpack (= 3.2.22.5) - activesupport (= 3.2.22.5) - rack-ssl (~> 1.3.2) + rails_serve_static_assets (0.0.5) + rails_stdout_logging (0.0.5) + railties (5.0.0) + actionpack (= 5.0.0) + activesupport (= 5.0.0) + method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (3.0.0) @@ -486,12 +471,15 @@ GEM coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) equalizer (~> 0.0, >= 0.0.9) - warden (1.2.7) - rack (>= 1.0) + warden (1.2.8) + rack (>= 2.0.6) webmock (3.4.2) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) xml-simple (1.1.5) yard (0.9.18) @@ -516,7 +504,7 @@ DEPENDENCIES database_cleaner debase delayed_job_active_record - devise (~> 3.5.0) + devise (~> 4.4) devise-async dotenv-rails dry-validation @@ -526,11 +514,10 @@ DEPENDENCIES foreman fullcontact geocoder - grape (~> 1.1.0) + grape grape-entity grape-swagger grape-swagger-entity - grape_devise! grape_logging grape_url_validator hamster @@ -544,7 +531,7 @@ DEPENDENCIES nearest_time_zone parallel param_validation! - pg + pg (~> 0.11) pry puma puma_worker_killer @@ -553,8 +540,8 @@ DEPENDENCIES rack-attack rack-ssl rack-timeout - rails (~> 4.2.8) - rails-i18n (~> 4.0) + rails (= 5.0.0) + rails-i18n rails_12factor rake roadie-rails @@ -577,7 +564,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 2.3.7p456 + ruby 2.4.5p335 BUNDLED WITH 1.17.3 From e19ee9c63861ae8dee9f950adee7fbbba9e726fd Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 11:54:16 -0600 Subject: [PATCH 29/77] Initial to rails v5 upgrade --- Gemfile | 2 +- Gemfile.lock | 82 +++++++------- bin/rails | 2 +- bin/setup | 29 ++--- bin/update | 29 +++++ config/application.rb | 7 +- config/environment.rb | 4 +- config/environments/development.rb | 88 +++++++++------ config/environments/production.rb | 36 +++++-- config/environments/test.rb | 16 +-- .../application_controller_renderer.rb | 8 ++ config/initializers/cookies_serializer.rb | 2 + config/initializers/locale.rb | 1 + config/initializers/new_framework_defaults.rb | 25 +++++ config/initializers/wrap_parameters.rb | 7 +- config/puma.rb | 100 ++++-------------- config/spring.rb | 6 ++ 17 files changed, 252 insertions(+), 192 deletions(-) create mode 100755 bin/update create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/new_framework_defaults.rb create mode 100644 config/spring.rb diff --git a/Gemfile b/Gemfile index b53407da..71864899 100755 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' ruby '2.4.5' gem 'rake' -gem 'rails', '= 5.0.0' +gem 'rails', '= 5.0.7.1' gem 'rails_12factor' # https://stripe.com/docs/api gem 'stripe' diff --git a/Gemfile.lock b/Gemfile.lock index 7b153a83..3ab3b542 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,41 +25,41 @@ GEM remote: https://rubygems.org/ specs: action_mailer_matchers (1.0.0) - actioncable (5.0.0) - actionpack (= 5.0.0) - nio4r (~> 1.2) + actioncable (5.0.7.1) + actionpack (= 5.0.7.1) + nio4r (>= 1.2, < 3.0) websocket-driver (~> 0.6.1) - actionmailer (5.0.0) - actionpack (= 5.0.0) - actionview (= 5.0.0) - activejob (= 5.0.0) + actionmailer (5.0.7.1) + actionpack (= 5.0.7.1) + actionview (= 5.0.7.1) + activejob (= 5.0.7.1) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.0.0) - actionview (= 5.0.0) - activesupport (= 5.0.0) + actionpack (5.0.7.1) + actionview (= 5.0.7.1) + activesupport (= 5.0.7.1) rack (~> 2.0) rack-test (~> 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.0) - activesupport (= 5.0.0) + actionview (5.0.7.1) + activesupport (= 5.0.7.1) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (5.0.0) - activesupport (= 5.0.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.0.7.1) + activesupport (= 5.0.7.1) globalid (>= 0.3.6) - activemodel (5.0.0) - activesupport (= 5.0.0) - activerecord (5.0.0) - activemodel (= 5.0.0) - activesupport (= 5.0.0) + activemodel (5.0.7.1) + activesupport (= 5.0.7.1) + activerecord (5.0.7.1) + activemodel (= 5.0.7.1) + activesupport (= 5.0.7.1) arel (~> 7.0) - activesupport (5.0.0) + activesupport (5.0.7.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) + i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.5.2) @@ -251,7 +251,7 @@ GEM domain_name (~> 0.5) httparty (0.16.2) multi_xml (>= 0.5.2) - i18n (0.9.5) + i18n (1.5.3) concurrent-ruby (~> 1.0) i18n-js (3.1.0) i18n (>= 0.6.6, < 2) @@ -275,7 +275,7 @@ GEM mail_view (2.0.4) tilt memcachier (0.0.2) - method_source (0.9.1) + method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) @@ -285,7 +285,7 @@ GEM minitest (5.11.3) money (6.13.1) i18n (>= 0.6.4, <= 2) - msgpack (1.2.4) + msgpack (1.2.6) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) @@ -297,7 +297,7 @@ GEM kdtree require_all netrc (0.11.0) - nio4r (1.2.1) + nio4r (2.3.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) @@ -327,17 +327,17 @@ GEM rack-test (0.6.3) rack (>= 1.0) rack-timeout (0.5.1) - rails (5.0.0) - actioncable (= 5.0.0) - actionmailer (= 5.0.0) - actionpack (= 5.0.0) - actionview (= 5.0.0) - activejob (= 5.0.0) - activemodel (= 5.0.0) - activerecord (= 5.0.0) - activesupport (= 5.0.0) - bundler (>= 1.3.0, < 2.0) - railties (= 5.0.0) + rails (5.0.7.1) + actioncable (= 5.0.7.1) + actionmailer (= 5.0.7.1) + actionpack (= 5.0.7.1) + actionview (= 5.0.7.1) + activejob (= 5.0.7.1) + activemodel (= 5.0.7.1) + activerecord (= 5.0.7.1) + activesupport (= 5.0.7.1) + bundler (>= 1.3.0) + railties (= 5.0.7.1) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) @@ -352,9 +352,9 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (5.0.0) - actionpack (= 5.0.0) - activesupport (= 5.0.0) + railties (5.0.7.1) + actionpack (= 5.0.7.1) + activesupport (= 5.0.7.1) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) @@ -540,7 +540,7 @@ DEPENDENCIES rack-attack rack-ssl rack-timeout - rails (= 5.0.0) + rails (= 5.0.7.1) rails-i18n rails_12factor rake diff --git a/bin/rails b/bin/rails index 5191e692..07396602 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/setup b/bin/setup index acdb2c13..e620b4da 100755 --- a/bin/setup +++ b/bin/setup @@ -1,29 +1,34 @@ #!/usr/bin/env ruby require 'pathname' +require 'fileutils' +include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) -Dir.chdir APP_ROOT do +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: + # Add necessary setup steps to this file. - puts "== Installing dependencies ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system "bin/rake db:setup" + system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" + system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" + system! 'bin/rails restart' end diff --git a/bin/update b/bin/update new file mode 100755 index 00000000..a8e4462f --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +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') + + 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/config/application.rb b/config/application.rb index 5e3539ca..4d592adc 100755 --- a/config/application.rb +++ b/config/application.rb @@ -1,9 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require File.expand_path('../boot', __FILE__) +require_relative 'boot' require 'rails/all' -Bundler.require *Rails.groups(:assets) if defined?(Bundler) +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + #require File.expand_path('lib/htp') # Hamster Table Print diff --git a/config/environment.rb b/config/environment.rb index 32a0ed66..85fd23e6 100755 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -# Load the rails application -require File.expand_path('../application', __FILE__) +# Load the Rails application +require_relative 'application' Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 diff --git a/config/environments/development.rb b/config/environments/development.rb index 58af5b4a..ab9d88d3 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -6,61 +6,81 @@ CarrierWave.configure do |config| end Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb + # 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 - config.cache_store = Settings.default.cache_store.to_sym + # 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 and disable caching - config.consider_all_requests_local = true - config.action_controller.perform_caching = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + 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=172800' + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end # You can uncomment the following to test our real AWS email server on localhost: - # config.action_mailer.delivery_method = :aws_ses - # config.action_mailer.default_url_options = { host: 'commitchange.com' } - config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym - config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } - config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username - config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password + # config.action_mailer.delivery_method = :aws_ses + # config.action_mailer.default_url_options = { host: 'commitchange.com' } + config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym + config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } + config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username + config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password + + config.action_mailer.default_url_options = { host: Settings.mailer.host } - config.action_mailer.default_url_options = { host: Settings.mailer.host } # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false - # Print deprecation notices to the Rails logger - config.active_support.deprecation = :log - # Only use best-standards-support built into browsers - config.action_dispatch.best_standards_support = :builtin + config.action_mailer.perform_caching = false - # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log - # Raise an error on page load if there are pending migrations + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - # Do not compress assets - config.assets.compress = false + # 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 - # Expands the lines which load the assets - config.assets.debug = true + # Suppress logger output for asset requests. + config.assets.quiet = true - config.assets.digest = true - # Adds additional error checking when serving assets at runtime. + # Adds additional error checking when serving assets at runtime. # Checks for improperly declared sprockets dependencies. # Raises helpful error messages. config.assets.raise_runtime_errors = true - config.log_level = :debug + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true - config.dependency_loading = true if $rails_rake_task - # Turn this on if you want to mess with code inside /node_modules - # config.browserify_rails.evaluate_node_modules = 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 - config.middleware.use I18n::JS::Middleware + config.log_level = :debug + + config.dependency_loading = true if $rails_rake_task + + config.middleware.use I18n::JS::Middleware end diff --git a/config/environments/production.rb b/config/environments/production.rb index de874dbf..d730f187 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -19,9 +19,9 @@ Rails.application.configure do # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. # config.action_dispatch.rack_cache = true - # Disable serving static files from the `/public` folder by default since + # Disable serving static files from thne `/public` folder by default since # Apache or NGINX already handles this. - config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier @@ -35,27 +35,31 @@ Rails.application.configure do # `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 + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for Nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true + config.force_ssl = true # Set to :debug to see everything in the log. config.log_level = :info # Prepend all log lines with the following tags. - # config.log_tags = [ :subdomain, :uuid ] - - # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + config.log_tags = [ :request_id ] # Use a different cache store in production. # config.cache_store = :mem_cache_store - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = "http://assets.example.com" + # 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 = "commitchange_#{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. @@ -71,6 +75,16 @@ Rails.application.configure do # 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/config/environments/test.rb b/config/environments/test.rb index 370aecb7..139c6164 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -12,9 +12,11 @@ Commitchange::Application.configure do # preloads Rails for running tests, you may have to set it to true. config.eager_load = false - # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + # 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=3600' + } # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -26,19 +28,19 @@ Commitchange::Application.configure do # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + 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 config.action_mailer.raise_delivery_errors = false - # Randomize the order test cases are executed. - config.active_support.test_order = :random - - # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr + # Randomize the order test cases are executed. + config.active_support.test_order = :random config.action_mailer.default_url_options = {host: 'houdiniproject.test'} diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 00000000..89d2efab --- /dev/null +++ b/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/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7f70458d..5a6a32d3 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +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/config/initializers/locale.rb b/config/initializers/locale.rb index 12686aa0..44eafa22 100644 --- a/config/initializers/locale.rb +++ b/config/initializers/locale.rb @@ -1,2 +1,3 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later I18n.available_locales = Settings.available_locales +Rails.application.config.i18n.fallbacks = [I18n.default_locale] diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb new file mode 100644 index 00000000..cbf423a8 --- /dev/null +++ b/config/initializers/new_framework_defaults.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +Rails.application.config.action_controller.raise_on_unfiltered_parameters = true + +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = false + +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = false + +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = false + +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = false + +# Do not halt callback chains when a callback returns false. Previous versions had true. +ActiveSupport.halt_callback_chains_on_return_false = true diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 91d9a5eb..ed7b7187 100755 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,4 +1,3 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which @@ -6,10 +5,10 @@ # 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] if respond_to?(:wrap_parameters) + wrap_parameters format: [:json] end -# To enable root element in JSON for ActiveRecord objects. +To enable root element in JSON for ActiveRecord objects. ActiveSupport.on_load(:active_record) do - self.include_root_in_json = false + self.include_root_in_json = true end diff --git a/config/puma.rb b/config/puma.rb index e12f2abf..5695f3af 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,88 +1,34 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -workers Integer(ENV['WEB_CONCURRENCY'] || 1) -threads 1,1 #not threadsafe yet + +# 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 }.to_i +threads threads_count, threads_count + preload_app! if ENV['RAILS_ENV'] != 'development' rackup DefaultRackup -port ENV['PORT'] || 5000 -environment ENV['RAILS_ENV'] || 'development' +port ENV.fetch("PORT") { 5000 } +environment ENV.fetch('RAILS_ENV'{ 'development' } + +workers ENV['WEB_CONCURRENCY'].fetch { 1 } on_worker_boot do - ActiveSupport.on_load(:active_record) do - config = ActiveRecord::Base.configurations[Rails.env] || - Rails.application.config.database_configuration[Rails.env] - config['pool'] = ENV['RAILS_MAX_THREADS'] || 1 - ActiveRecord::Base.establish_connection - end - + # ActiveSupport.on_load(:active_record) do + # config = ActiveRecord::Base.configurations[Rails.env] || + # Rails.application.config.database_configuration[Rails.env] + # config['pool'] = ENV['RAILS_MAX_THREADS'] || 1 + # ActiveRecord::Base.establish_connection + # end + ActiveRecord::Base.establish_connection if defined?(ActiveRecord) end -# rackup DefaultRackup -# port ENV['PORT'] || 8080 -# environment ENV['RAILS_ENV'] || 'development' -# tag 'commitchange' -# # workers 2 -# daemonize -# -# # Read environment -# require 'dotenv' -# Dotenv.load ".env" -# @env = ENV['RAILS_ENV'] -# # || 'development' -# Dotenv.load ".env.#{@env}" -# puts ENV['PORT'] -# puts "----------------------- #{@env} -----------------------------------" -# @dir = ENV['PUMADIR'] || ENV['PWD'] -# @port = ENV['PORT'] || 10525 -# -# workers Integer(ENV['WEB_CONCURRENCY'] || 1) -# threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 1) -# preload_app! if ENV['RAILS_ENV'] != 'development' -# -# if heroku? -# threads threads_count, threads_count -# else -# threads 1, threads_count -# end -# -# environment @env || 'development' -# #environment 'production' -# -# before_fork do -# require 'puma_worker_killer' -# PumaWorkerKiller.enable_rolling_restart # Default is every 6 hours -# end -# -# tmp_dir = File.expand_path("./tmp", @dir) -# log_dir = File.expand_path("./log", @dir) -# -# if @port -# port @port -# else -# bind "unix://#{tmp_dir}/sockets/puma.sock" -# end -# -# unless heroku? -# # Pid files -# pidfile "#{tmp_dir}/pids/puma.pid" -# state_path "#{tmp_dir}/pids/puma.state" -# -# # Logging -# -# if ENV['LOG_TO_FILES'] -# puts "log to files #{log_dir}/puma.[stdout|stderr].#{@env}.log" -# stdout_redirect "#{log_dir}/puma.stdout.#{@env}.log", "#{log_dir}/puma.stderr.#{@env}.log", true -# end -# end -# on_worker_boot do -# ActiveSupport.on_load(:active_record) do -# config = ActiveRecord::Base.configurations[Rails.env] || -# Rails.application.config.database_configuration[Rails.env] -# config['pool'] = ENV['RAILS_MAX_THREADS'] || 1 -# ActiveRecord::Base.establish_connection -# end -# end - +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 00000000..c9119b40 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } From 66e4d26d22c3074c3cc767dead2bad8b9e09a5a6 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 12:58:54 -0600 Subject: [PATCH 30/77] Config cleanup --- config/application.rb | 4 +--- config/initializers/devise_async.rb | 2 +- config/initializers/wrap_parameters.rb | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/config/application.rb b/config/application.rb index 4d592adc..91784071 100755 --- a/config/application.rb +++ b/config/application.rb @@ -56,7 +56,7 @@ module Commitchange # This will create an empty whitelist of attributes available for mass-assignment for all models # in your app. As such, your models will need to explicitly whitelist or blacklist accessible # parameters by using an attr_accessible or attr_protected declaration. - config.active_record.whitelist_attributes = true + #config.active_record.whitelist_attributes = true # Enable the asset pipeline config.assets.enabled = true @@ -82,8 +82,6 @@ module Commitchange config.i18n.enforce_available_locales = false - config.active_record.raise_in_transactional_callbacks = true - # Add trailing slashes to all routes # config.action_controller.default_url_options = {:trailing_slash => true} # diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb index 9d71516a..42d81a4e 100644 --- a/config/initializers/devise_async.rb +++ b/config/initializers/devise_async.rb @@ -1,2 +1,2 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Devise::Async.backend = :delayed_job +#Devise::Async.backend = :delayed_job diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index ed7b7187..c72a9676 100755 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -8,7 +8,7 @@ ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] end -To enable root element in JSON for ActiveRecord objects. +# To enable root element in JSON for ActiveRecord objects. ActiveSupport.on_load(:active_record) do self.include_root_in_json = true end From 4071455dee2a37eb28fcec6f497b4a1ef2567bc1 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 13:29:14 -0600 Subject: [PATCH 31/77] rails_12factor is unneeded in Rails5 --- Gemfile | 1 - Gemfile.lock | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 71864899..0be6acd4 100755 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,6 @@ source 'https://rubygems.org' ruby '2.4.5' gem 'rake' gem 'rails', '= 5.0.7.1' -gem 'rails_12factor' # https://stripe.com/docs/api gem 'stripe' diff --git a/Gemfile.lock b/Gemfile.lock index 3ab3b542..5a900acc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,6 +8,14 @@ GIT multi_json (~> 1.0) stripe (>= 1.31.0, <= 1.58.0) +PATH + remote: gems/grape_devise + specs: + grape_devise (0.1.1) + devise (>= 2.2.8, < 5) + grape (> 0.7) + rails (> 3.2, < 6) + PATH remote: gems/ruby-param-validation specs: @@ -322,8 +330,6 @@ GEM rack (>= 0.4) rack-attack (5.4.2) rack (>= 1.0, < 3) - rack-ssl (1.4.1) - rack rack-test (0.6.3) rack (>= 1.0) rack-timeout (0.5.1) @@ -347,11 +353,6 @@ GEM rails-i18n (5.1.3) i18n (>= 0.7, < 2) railties (>= 5.0, < 6) - rails_12factor (0.0.3) - rails_serve_static_assets - rails_stdout_logging - rails_serve_static_assets (0.0.5) - rails_stdout_logging (0.0.5) railties (5.0.7.1) actionpack (= 5.0.7.1) activesupport (= 5.0.7.1) @@ -518,6 +519,7 @@ DEPENDENCIES grape-entity grape-swagger grape-swagger-entity + grape_devise! grape_logging grape_url_validator hamster @@ -538,11 +540,9 @@ DEPENDENCIES qx! rabl rack-attack - rack-ssl rack-timeout rails (= 5.0.7.1) rails-i18n - rails_12factor rake roadie-rails rspec From d3535c0b80ea295c75ccb374ce6ce1de144cc029 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 13:40:24 -0600 Subject: [PATCH 32/77] Models now inherit from ApplicationRecord --- app/models/activity.rb | 2 +- app/models/application_record.rb | 5 +++++ app/models/bank_account.rb | 2 +- app/models/billing_plan.rb | 2 +- app/models/billing_subscription.rb | 2 +- app/models/campaign.rb | 2 +- app/models/campaign_gift.rb | 2 +- app/models/campaign_gift_option.rb | 2 +- app/models/card.rb | 2 +- app/models/charge.rb | 2 +- app/models/comment.rb | 2 +- app/models/coupon.rb | 2 +- app/models/custom_field_join.rb | 2 +- app/models/custom_field_master.rb | 2 +- app/models/direct_debit_detail.rb | 2 +- app/models/dispute.rb | 2 +- app/models/donation.rb | 2 +- app/models/email_draft.rb | 2 +- app/models/email_list.rb | 2 +- app/models/email_setting.rb | 2 +- app/models/event.rb | 2 +- app/models/event_discount.rb | 2 +- app/models/export.rb | 2 +- app/models/full_contact_info.rb | 2 +- app/models/full_contact_org.rb | 2 +- app/models/full_contact_photo.rb | 2 +- app/models/full_contact_social_profile.rb | 2 +- app/models/full_contact_topic.rb | 2 +- app/models/image_attachment.rb | 2 +- app/models/import.rb | 2 +- app/models/miscellaneous_np_info.rb | 2 +- app/models/nonprofit.rb | 2 +- app/models/nonprofit_account.rb | 2 +- app/models/offsite_payment.rb | 2 +- app/models/payment.rb | 2 +- app/models/payment_import.rb | 2 +- app/models/payment_payout.rb | 2 +- app/models/payout.rb | 2 +- app/models/profile.rb | 2 +- app/models/recurring_donation.rb | 2 +- app/models/refund.rb | 2 +- app/models/role.rb | 2 +- app/models/source_token.rb | 2 +- app/models/supporter.rb | 2 +- app/models/supporter_email.rb | 2 +- app/models/supporter_note.rb | 2 +- app/models/tag_join.rb | 2 +- app/models/tag_master.rb | 2 +- app/models/ticket.rb | 2 +- app/models/ticket_level.rb | 2 +- app/models/tracking.rb | 2 +- app/models/user.rb | 2 +- 52 files changed, 56 insertions(+), 51 deletions(-) create mode 100644 app/models/application_record.rb diff --git a/app/models/activity.rb b/app/models/activity.rb index c98f0888..20a763bf 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Activity < ActiveRecord::Base +class Activity < ApplicationRecord end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 00000000..52fec221 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,5 @@ +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later + +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end \ No newline at end of file diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb index 92265f4f..c618467a 100644 --- a/app/models/bank_account.rb +++ b/app/models/bank_account.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class BankAccount < ActiveRecord::Base +class BankAccount < ApplicationRecord attr_accessible \ :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") diff --git a/app/models/billing_plan.rb b/app/models/billing_plan.rb index 552a273d..217bb747 100644 --- a/app/models/billing_plan.rb +++ b/app/models/billing_plan.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class BillingPlan < ActiveRecord::Base +class BillingPlan < ApplicationRecord Names = ['Starter', 'Fundraising', 'Supporter Management'] DefaultAmounts = [0, 9900, 29900] # in pennies diff --git a/app/models/billing_subscription.rb b/app/models/billing_subscription.rb index 5e67bfea..9d33ee48 100644 --- a/app/models/billing_subscription.rb +++ b/app/models/billing_subscription.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class BillingSubscription < ActiveRecord::Base +class BillingSubscription < ApplicationRecord attr_accessible \ :nonprofit_id, :nonprofit, diff --git a/app/models/campaign.rb b/app/models/campaign.rb index d4037873..c104e0af 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Campaign < ActiveRecord::Base +class Campaign < ApplicationRecord attr_accessible \ :name, diff --git a/app/models/campaign_gift.rb b/app/models/campaign_gift.rb index be8e76ba..273cf9f2 100644 --- a/app/models/campaign_gift.rb +++ b/app/models/campaign_gift.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class CampaignGift < ActiveRecord::Base +class CampaignGift < ApplicationRecord attr_accessible \ :donation_id, diff --git a/app/models/campaign_gift_option.rb b/app/models/campaign_gift_option.rb index f69129c4..7c07e901 100644 --- a/app/models/campaign_gift_option.rb +++ b/app/models/campaign_gift_option.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class CampaignGiftOption < ActiveRecord::Base +class CampaignGiftOption < ApplicationRecord attr_accessible \ :amount_one_time, #int (cents) diff --git a/app/models/card.rb b/app/models/card.rb index d7b806f8..b63a09fe 100755 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Card < ActiveRecord::Base +class Card < ApplicationRecord attr_accessible \ :cardholders_name, # str (name associated with this card) diff --git a/app/models/charge.rb b/app/models/charge.rb index d2ce3f47..7b300efa 100644 --- a/app/models/charge.rb +++ b/app/models/charge.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # A Charge represents a potential debit to a nonprofit's account on a credit card donation action. -class Charge < ActiveRecord::Base +class Charge < ApplicationRecord attr_accessible \ :amount, diff --git a/app/models/comment.rb b/app/models/comment.rb index e0491d49..6f4b9e52 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Comment < ActiveRecord::Base +class Comment < ApplicationRecord attr_accessible \ :host_id, :host_type, #parent: Event, Campaign, nil diff --git a/app/models/coupon.rb b/app/models/coupon.rb index 1377d548..08d93729 100644 --- a/app/models/coupon.rb +++ b/app/models/coupon.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Coupon < ActiveRecord::Base +class Coupon < ApplicationRecord attr_accessible \ :name, :victim_np_id, diff --git a/app/models/custom_field_join.rb b/app/models/custom_field_join.rb index c38e9331..0d96a378 100644 --- a/app/models/custom_field_join.rb +++ b/app/models/custom_field_join.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class CustomFieldJoin < ActiveRecord::Base +class CustomFieldJoin < ApplicationRecord attr_accessible \ :supporter, :supporter_id, diff --git a/app/models/custom_field_master.rb b/app/models/custom_field_master.rb index ef6bb85c..56f4398a 100644 --- a/app/models/custom_field_master.rb +++ b/app/models/custom_field_master.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class CustomFieldMaster < ActiveRecord::Base +class CustomFieldMaster < ApplicationRecord attr_accessible \ :nonprofit, :nonprofit_id, diff --git a/app/models/direct_debit_detail.rb b/app/models/direct_debit_detail.rb index ba8fbe67..d4dbfdcb 100644 --- a/app/models/direct_debit_detail.rb +++ b/app/models/direct_debit_detail.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class DirectDebitDetail < ActiveRecord::Base +class DirectDebitDetail < ApplicationRecord attr_accessible :iban, :account_holder_name, :bic, :supporter_id, :holder has_many :donations diff --git a/app/models/dispute.rb b/app/models/dispute.rb index 722768b3..e8b912e4 100644 --- a/app/models/dispute.rb +++ b/app/models/dispute.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Dispute < ActiveRecord::Base +class Dispute < ApplicationRecord Reasons = [:unrecognized, :duplicate, :fraudulent, :subscription_canceled, :product_unacceptable, :product_not_received, :unrecognized, :credit_not_processed, :goods_services_returned_or_refused, :goods_services_cancelled, :incorrect_account_details, :insufficient_funds, :bank_cannot_process, :debit_not_authorized, :general] diff --git a/app/models/donation.rb b/app/models/donation.rb index 43f995c9..1c7053d8 100644 --- a/app/models/donation.rb +++ b/app/models/donation.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Donation < ActiveRecord::Base +class Donation < ApplicationRecord attr_accessible \ :date, # datetime (when this donation was made) diff --git a/app/models/email_draft.rb b/app/models/email_draft.rb index 9614c13c..cc4951b0 100644 --- a/app/models/email_draft.rb +++ b/app/models/email_draft.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class EmailDraft < ActiveRecord::Base +class EmailDraft < ApplicationRecord attr_accessible \ :nonprofit, :nonprofit_id, diff --git a/app/models/email_list.rb b/app/models/email_list.rb index ea64e773..4f8fccf1 100644 --- a/app/models/email_list.rb +++ b/app/models/email_list.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class EmailList < ActiveRecord::Base +class EmailList < ApplicationRecord attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master belongs_to :nonprofit belongs_to :tag_master diff --git a/app/models/email_setting.rb b/app/models/email_setting.rb index c4f8bf2e..0171f071 100644 --- a/app/models/email_setting.rb +++ b/app/models/email_setting.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class EmailSetting < ActiveRecord::Base +class EmailSetting < ApplicationRecord attr_accessible \ :user_id, :user, diff --git a/app/models/event.rb b/app/models/event.rb index 4face493..37c631f7 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Event < ActiveRecord::Base +class Event < ApplicationRecord attr_accessible \ :deleted, #bool for soft-delete diff --git a/app/models/event_discount.rb b/app/models/event_discount.rb index 7e6a69a0..2888ecaa 100644 --- a/app/models/event_discount.rb +++ b/app/models/event_discount.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class EventDiscount < ActiveRecord::Base +class EventDiscount < ApplicationRecord attr_accessible \ :code, :event_id, diff --git a/app/models/export.rb b/app/models/export.rb index e49d5609..ee4717a4 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Export < ActiveRecord::Base +class Export < ApplicationRecord STATUS = %w[queued started completed failed].freeze attr_accessible :exception, :nonprofit, :status, :user, :export_type, :parameters, :ended, :url, :user_id, :nonprofit_id diff --git a/app/models/full_contact_info.rb b/app/models/full_contact_info.rb index 712579fa..7862d89d 100644 --- a/app/models/full_contact_info.rb +++ b/app/models/full_contact_info.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class FullContactInfo < ActiveRecord::Base +class FullContactInfo < ApplicationRecord attr_accessible \ :email, :full_name, diff --git a/app/models/full_contact_org.rb b/app/models/full_contact_org.rb index a8b4ce1b..05acfc9c 100644 --- a/app/models/full_contact_org.rb +++ b/app/models/full_contact_org.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class FullContactOrg < ActiveRecord::Base +class FullContactOrg < ApplicationRecord attr_accessible \ :name, diff --git a/app/models/full_contact_photo.rb b/app/models/full_contact_photo.rb index 258a764f..b96a5bb7 100644 --- a/app/models/full_contact_photo.rb +++ b/app/models/full_contact_photo.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class FullContactPhoto < ActiveRecord::Base +class FullContactPhoto < ApplicationRecord attr_accessible \ :full_contact_info, :full_contact_info_id, diff --git a/app/models/full_contact_social_profile.rb b/app/models/full_contact_social_profile.rb index 047160ea..b98a4dd3 100644 --- a/app/models/full_contact_social_profile.rb +++ b/app/models/full_contact_social_profile.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class FullContactSocialProfile < ActiveRecord::Base +class FullContactSocialProfile < ApplicationRecord attr_accessible \ :full_contact_info, :full_contact_info_id, diff --git a/app/models/full_contact_topic.rb b/app/models/full_contact_topic.rb index 475f9c27..0839097b 100644 --- a/app/models/full_contact_topic.rb +++ b/app/models/full_contact_topic.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class FullContactTopic < ActiveRecord::Base +class FullContactTopic < ApplicationRecord attr_accessible \ :provider, diff --git a/app/models/image_attachment.rb b/app/models/image_attachment.rb index d6afb9a4..642ba68c 100644 --- a/app/models/image_attachment.rb +++ b/app/models/image_attachment.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class ImageAttachment < ActiveRecord::Base +class ImageAttachment < ApplicationRecord attr_accessible :parent_id, :file mount_uploader :file, ImageAttachmentUploader diff --git a/app/models/import.rb b/app/models/import.rb index b4e3f681..66a06071 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Import < ActiveRecord::Base +class Import < ApplicationRecord attr_accessible \ :user_id, :user, diff --git a/app/models/miscellaneous_np_info.rb b/app/models/miscellaneous_np_info.rb index 2b15029a..a9ba9179 100644 --- a/app/models/miscellaneous_np_info.rb +++ b/app/models/miscellaneous_np_info.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class MiscellaneousNpInfo < ActiveRecord::Base +class MiscellaneousNpInfo < ApplicationRecord attr_accessible \ :donate_again_url, diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index f7280036..b2bda8d4 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Nonprofit < ActiveRecord::Base +class Nonprofit < ApplicationRecord Categories = ["Public Benefit", "Human Services", "Education", "Civic Duty", "Human Rights", "Animals", "Environment", "Health", "Arts, Culture, Humanities", "International", "Children", "Religion", "LGBTQ", "Women's Rights", "Disaster Relief", "Veterans"] diff --git a/app/models/nonprofit_account.rb b/app/models/nonprofit_account.rb index a3bff211..b5ee62d0 100644 --- a/app/models/nonprofit_account.rb +++ b/app/models/nonprofit_account.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class NonprofitAccount < ActiveRecord::Base +class NonprofitAccount < ApplicationRecord attr_accessible \ :stripe_account_id, #str diff --git a/app/models/offsite_payment.rb b/app/models/offsite_payment.rb index 4e4cf03a..9a729ed2 100644 --- a/app/models/offsite_payment.rb +++ b/app/models/offsite_payment.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class OffsitePayment < ActiveRecord::Base +class OffsitePayment < ApplicationRecord attr_accessible :gross_amount, :kind, :date, :check_number belongs_to :payment, dependent: :destroy diff --git a/app/models/payment.rb b/app/models/payment.rb index e916a588..4e622d7b 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -3,7 +3,7 @@ # If connected to a charge, this represents money potentially debited to the nonprofit's account # If connected to an offsite_payment, this is money the nonprofit is recording for convenience. -class Payment < ActiveRecord::Base +class Payment < ApplicationRecord attr_accessible \ :towards, diff --git a/app/models/payment_import.rb b/app/models/payment_import.rb index ebe96e11..fea614a5 100644 --- a/app/models/payment_import.rb +++ b/app/models/payment_import.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class PaymentImport < ActiveRecord::Base +class PaymentImport < ApplicationRecord attr_accessible :nonprofit, :user has_and_belongs_to_many :donations belongs_to :nonprofit diff --git a/app/models/payment_payout.rb b/app/models/payment_payout.rb index a7a840d1..3c686763 100644 --- a/app/models/payment_payout.rb +++ b/app/models/payment_payout.rb @@ -11,7 +11,7 @@ # It's also nice to keep a historical records of fees for individual donations # since our fees will continue to change as our transaction volume increases -class PaymentPayout < ActiveRecord::Base +class PaymentPayout < ApplicationRecord attr_accessible \ :payment_id, :payment, diff --git a/app/models/payout.rb b/app/models/payout.rb index aa53c033..58fd8542 100644 --- a/app/models/payout.rb +++ b/app/models/payout.rb @@ -4,7 +4,7 @@ # # These are tied to Stripe transfers -class Payout < ActiveRecord::Base +class Payout < ApplicationRecord attr_accessible \ :scheduled, # bool (whether this was made automatically at the beginning of the month) diff --git a/app/models/profile.rb b/app/models/profile.rb index 5ff2f392..d9e17c0d 100755 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Profile < ActiveRecord::Base +class Profile < ApplicationRecord attr_accessible \ :registered, # bool diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index 1a088b1e..3e018bbe 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class RecurringDonation < ActiveRecord::Base +class RecurringDonation < ApplicationRecord attr_accessible \ :amount, # int (cents) diff --git a/app/models/refund.rb b/app/models/refund.rb index f7fff991..25e7cf8b 100644 --- a/app/models/refund.rb +++ b/app/models/refund.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Refund < ActiveRecord::Base +class Refund < ApplicationRecord Reasons = [:duplicate, :fraudulent, :requested_by_customer] diff --git a/app/models/role.rb b/app/models/role.rb index 2c8401bf..8bbd5263 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Role < ActiveRecord::Base +class Role < ApplicationRecord Names = [ :super_admin, # global access diff --git a/app/models/source_token.rb b/app/models/source_token.rb index 2d785ce1..1d6ca55f 100644 --- a/app/models/source_token.rb +++ b/app/models/source_token.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class SourceToken < ActiveRecord::Base +class SourceToken < ApplicationRecord self.primary_key = :token attr_accessible :expiration, :token, :max_uses, :total_uses belongs_to :tokenizable, :polymorphic => true diff --git a/app/models/supporter.rb b/app/models/supporter.rb index 8d5a89de..05674b16 100644 --- a/app/models/supporter.rb +++ b/app/models/supporter.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Supporter < ActiveRecord::Base +class Supporter < ApplicationRecord attr_accessible \ :search_vectors, diff --git a/app/models/supporter_email.rb b/app/models/supporter_email.rb index 5ac0d8d9..0e9b2e53 100644 --- a/app/models/supporter_email.rb +++ b/app/models/supporter_email.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class SupporterEmail < ActiveRecord::Base +class SupporterEmail < ApplicationRecord attr_accessible \ :to, :from, diff --git a/app/models/supporter_note.rb b/app/models/supporter_note.rb index dd920f07..ff7d29f9 100644 --- a/app/models/supporter_note.rb +++ b/app/models/supporter_note.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class SupporterNote < ActiveRecord::Base +class SupporterNote < ApplicationRecord attr_accessible \ :content, diff --git a/app/models/tag_join.rb b/app/models/tag_join.rb index 5f0e402a..d531ddb9 100644 --- a/app/models/tag_join.rb +++ b/app/models/tag_join.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class TagJoin < ActiveRecord::Base +class TagJoin < ApplicationRecord attr_accessible \ :supporter, :supporter_id, diff --git a/app/models/tag_master.rb b/app/models/tag_master.rb index 6e9f0ffd..836bdbfb 100644 --- a/app/models/tag_master.rb +++ b/app/models/tag_master.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class TagMaster < ActiveRecord::Base +class TagMaster < ApplicationRecord attr_accessible \ :nonprofit, :nonprofit_id, diff --git a/app/models/ticket.rb b/app/models/ticket.rb index e805ad89..9e56fd2b 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Ticket < ActiveRecord::Base +class Ticket < ApplicationRecord attr_accessible :note, :event_discount, :event_discount_id diff --git a/app/models/ticket_level.rb b/app/models/ticket_level.rb index 9d628782..130157e0 100644 --- a/app/models/ticket_level.rb +++ b/app/models/ticket_level.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class TicketLevel < ActiveRecord::Base +class TicketLevel < ApplicationRecord attr_accessible \ :amount, #integer diff --git a/app/models/tracking.rb b/app/models/tracking.rb index d3a175c7..a730989f 100644 --- a/app/models/tracking.rb +++ b/app/models/tracking.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class Tracking < ActiveRecord::Base +class Tracking < ApplicationRecord attr_accessible :utm_campaign, :utm_content, :utm_medium, :utm_source belongs_to :donation diff --git a/app/models/user.rb b/app/models/user.rb index 32f1e674..dffee4cb 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -class User < ActiveRecord::Base +class User < ApplicationRecord attr_accessible \ :email, # str: balidated with Devise From a12e4099adff23dbafdb6fe8af18a704289c361b Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 13:42:44 -0600 Subject: [PATCH 33/77] Add ApplicationJob --- app/jobs/application_job.rb | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 app/jobs/application_job.rb diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 00000000..cd5fb472 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,4 @@ +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later + +class ApplicationJob < ActiveJob::Base +end From a7e5baae2c8e780e3e4c759fa0668b487c7ed94f Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 1 Feb 2019 13:45:36 -0600 Subject: [PATCH 34/77] Tests are random by default so we don't need to say it --- config/environments/test.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/environments/test.rb b/config/environments/test.rb index 139c6164..20bd8332 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -39,9 +39,6 @@ Commitchange::Application.configure do # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Randomize the order test cases are executed. - config.active_support.test_order = :random - config.action_mailer.default_url_options = {host: 'houdiniproject.test'} # Raises error for missing translations From f2c32fffca27e0f0fdbc9a172cf68137b3148583 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 21 Jun 2019 17:12:54 -0500 Subject: [PATCH 35/77] Initially comment out attr_accessible --- app/models/bank_account.rb | 25 +++--- app/models/billing_plan.rb | 15 ++-- app/models/billing_subscription.rb | 11 +-- app/models/campaign.rb | 71 +++++++++-------- app/models/campaign_gift.rb | 11 +-- app/models/campaign_gift_option.rb | 23 +++--- app/models/card.rb | 23 +++--- app/models/charge.rb | 11 +-- app/models/comment.rb | 9 ++- app/models/custom_field_join.rb | 9 ++- app/models/dispute.rb | 15 ++-- app/models/donation.rb | 39 ++++----- app/models/email_draft.rb | 14 ++-- app/models/email_setting.rb | 17 ++-- app/models/event.rb | 65 +++++++-------- app/models/event_discount.rb | 11 +-- app/models/full_contact_info.rb | 29 +++---- app/models/full_contact_org.rb | 19 ++--- app/models/full_contact_photo.rb | 13 +-- app/models/full_contact_social_profile.rb | 17 ++-- app/models/full_contact_topic.rb | 9 ++- app/models/import.rb | 15 ++-- app/models/miscellaneous_np_info.rb | 7 +- app/models/nonprofit.rb | 97 ++++++++++++----------- app/models/nonprofit_account.rb | 7 +- app/models/payment.rb | 15 ++-- app/models/payment_payout.rb | 11 +-- app/models/payout.rb | 29 +++---- app/models/profile.rb | 35 ++++---- app/models/recurring_donation.rb | 31 ++++---- app/models/refund.rb | 21 ++--- app/models/role.rb | 9 ++- app/models/supporter.rb | 55 ++++++------- app/models/supporter_email.rb | 19 ++--- app/models/supporter_note.rb | 7 +- app/models/tag_join.rb | 7 +- app/models/tag_master.rb | 11 +-- app/models/ticket_level.rb | 23 +++--- app/models/user.rb | 47 +++++------ 39 files changed, 470 insertions(+), 432 deletions(-) diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb index c618467a..b7eedb59 100644 --- a/app/models/bank_account.rb +++ b/app/models/bank_account.rb @@ -1,18 +1,19 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BankAccount < ApplicationRecord - attr_accessible \ - :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") - :confirmation_token, # str (randomly generated private token for email confirmation) - :account_number, # str (last digits only) - :bank_name, # str - :pending_verification, # bool (whether this bank account is still awaiting email confirmation) - :status, # str - :email, # str (contact email associated with the user who created this bank account) - :deleted, # bool (soft delete flag) - :stripe_bank_account_token, # str - :stripe_bank_account_id, # str - :nonprofit_id, :nonprofit + #TODO + # attr_accessible \ + # :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") + # :confirmation_token, # str (randomly generated private token for email confirmation) + # :account_number, # str (last digits only) + # :bank_name, # str + # :pending_verification, # bool (whether this bank account is still awaiting email confirmation) + # :status, # str + # :email, # str (contact email associated with the user who created this bank account) + # :deleted, # bool (soft delete flag) + # :stripe_bank_account_token, # str + # :stripe_bank_account_id, # str + # :nonprofit_id, :nonprofit #validates :stripe_bank_account_token, presence: true, uniqueness: true # validates :stripe_bank_account_id, presence: true, uniqueness: true diff --git a/app/models/billing_plan.rb b/app/models/billing_plan.rb index 217bb747..b5468646 100644 --- a/app/models/billing_plan.rb +++ b/app/models/billing_plan.rb @@ -3,13 +3,14 @@ class BillingPlan < ApplicationRecord Names = ['Starter', 'Fundraising', 'Supporter Management'] DefaultAmounts = [0, 9900, 29900] # in pennies - attr_accessible \ - :name, #str: readable name - :tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) - :amount, #int (cents) - :stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription - :interval, #str ('monthly', 'annual') - :percentage_fee # 0.038 + #TODO + # attr_accessible \ + # :name, #str: readable name + # :tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) + # :amount, #int (cents) + # :stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription + # :interval, #str ('monthly', 'annual') + # :percentage_fee # 0.038 has_many :billing_subscriptions diff --git a/app/models/billing_subscription.rb b/app/models/billing_subscription.rb index 9d33ee48..85b5679e 100644 --- a/app/models/billing_subscription.rb +++ b/app/models/billing_subscription.rb @@ -1,11 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BillingSubscription < ApplicationRecord - attr_accessible \ - :nonprofit_id, :nonprofit, - :billing_plan_id, :billing_plan, - :stripe_subscription_id, - :status # trialing, active, past_due, canceled, or unpaid + #TODO + # attr_accessible \ + # :nonprofit_id, :nonprofit, + # :billing_plan_id, :billing_plan, + # :stripe_subscription_id, + # :status # trialing, active, past_due, canceled, or unpaid attr_accessor :stripe_plan_id, :manual belongs_to :nonprofit diff --git a/app/models/campaign.rb b/app/models/campaign.rb index c104e0af..5aaa9162 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -1,41 +1,42 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Campaign < ApplicationRecord - attr_accessible \ - :name, - :tagline, - :slug, # str: url name - :total_supporters, - :goal_amount, - :nonprofit_id, - :profile_id, - :main_image, - :remove_main_image, # for carrierwave - :background_image, - :remove_background_image, #bool carrierwave - :banner_image, - :remove_banner_image, - :published, - :video_url, #str - :vimeo_video_id, - :youtube_video_id, - :summary, - :recurring_fund, # bool: whether this is a recurring campaign - :body, - :goal_amount_dollars, #accessor: translated into goal_amount (cents) - :show_total_raised, # bool - :show_total_count, # bool - :hide_activity_feed, # bool - :end_datetime, - :deleted, #bool (soft delete) - :hide_goal, # bool - :hide_thermometer, #bool - :hide_title, # bool - :receipt_message, # text - :hide_custom_amounts, # boolean - :parent_campaign_id, - :reason_for_supporting, - :default_reason_for_supporting + #TODO + # attr_accessible \ + # :name, + # :tagline, + # :slug, # str: url name + # :total_supporters, + # :goal_amount, + # :nonprofit_id, + # :profile_id, + # :main_image, + # :remove_main_image, # for carrierwave + # :background_image, + # :remove_background_image, #bool carrierwave + # :banner_image, + # :remove_banner_image, + # :published, + # :video_url, #str + # :vimeo_video_id, + # :youtube_video_id, + # :summary, + # :recurring_fund, # bool: whether this is a recurring campaign + # :body, + # :goal_amount_dollars, #accessor: translated into goal_amount (cents) + # :show_total_raised, # bool + # :show_total_count, # bool + # :hide_activity_feed, # bool + # :end_datetime, + # :deleted, #bool (soft delete) + # :hide_goal, # bool + # :hide_thermometer, #bool + # :hide_title, # bool + # :receipt_message, # text + # :hide_custom_amounts, # boolean + # :parent_campaign_id, + # :reason_for_supporting, + # :default_reason_for_supporting validate :end_datetime_cannot_be_in_past, :on => :create validates :profile, :presence => true diff --git a/app/models/campaign_gift.rb b/app/models/campaign_gift.rb index 273cf9f2..d08a59da 100644 --- a/app/models/campaign_gift.rb +++ b/app/models/campaign_gift.rb @@ -1,11 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGift < ApplicationRecord - attr_accessible \ - :donation_id, - :donation, - :campaign_gift_option, - :campaign_gift_option_id + #TODO + # attr_accessible \ + # :donation_id, + # :donation, + # :campaign_gift_option, + # :campaign_gift_option_id belongs_to :donation belongs_to :campaign_gift_option diff --git a/app/models/campaign_gift_option.rb b/app/models/campaign_gift_option.rb index 7c07e901..187010d1 100644 --- a/app/models/campaign_gift_option.rb +++ b/app/models/campaign_gift_option.rb @@ -1,17 +1,18 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGiftOption < ApplicationRecord - attr_accessible \ - :amount_one_time, #int (cents) - :amount_recurring, #int (cents) - :amount_dollars, #str, gets converted to amount - :description, # text - :name, # str - :campaign, #assocation - :quantity, #int (optional) - :to_ship, #boolean - :order, #int (optional) - :hide_contributions #boolean (optional) + #TODO + # attr_accessible \ + # :amount_one_time, #int (cents) + # :amount_recurring, #int (cents) + # :amount_dollars, #str, gets converted to amount + # :description, # text + # :name, # str + # :campaign, #assocation + # :quantity, #int (optional) + # :to_ship, #boolean + # :order, #int (optional) + # :hide_contributions #boolean (optional) belongs_to :campaign has_many :campaign_gifts diff --git a/app/models/card.rb b/app/models/card.rb index b63a09fe..0c71e983 100755 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -1,17 +1,18 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Card < ApplicationRecord - attr_accessible \ - :cardholders_name, # str (name associated with this card) - :email, # str (cache the email associated with this card) - :name, # str (readable card name, eg. Visa *1234) - :failure_message, # accessor for temporarily storing the stripe decline message - :status, # str - :stripe_card_token, # str - :stripe_card_id, # str - :stripe_customer_id, # str - :holder, :holder_id, :holder_type, # polymorphic cardholder association - :inactive # a card is inactive. This is currently only meaningful for nonprofit cards + #TODO + # attr_accessible \ + # :cardholders_name, # str (name associated with this card) + # :email, # str (cache the email associated with this card) + # :name, # str (readable card name, eg. Visa *1234) + # :failure_message, # accessor for temporarily storing the stripe decline message + # :status, # str + # :stripe_card_token, # str + # :stripe_card_id, # str + # :stripe_customer_id, # str + # :holder, :holder_id, :holder_type, # polymorphic cardholder association + # :inactive # a card is inactive. This is currently only meaningful for nonprofit cards attr_accessor :failure_message diff --git a/app/models/charge.rb b/app/models/charge.rb index 7b300efa..42d7161d 100644 --- a/app/models/charge.rb +++ b/app/models/charge.rb @@ -3,11 +3,12 @@ class Charge < ApplicationRecord - attr_accessible \ - :amount, - :fee, - :stripe_charge_id, - :status + #TODO + # attr_accessible \ + # :amount, + # :fee, + # :stripe_charge_id, + # :status has_one :campaign, through: :donation diff --git a/app/models/comment.rb b/app/models/comment.rb index 6f4b9e52..8efbcc7b 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,10 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Comment < ApplicationRecord - attr_accessible \ - :host_id, :host_type, #parent: Event, Campaign, nil - :profile_id, - :body + #TODO + # attr_accessible \ + # :host_id, :host_type, #parent: Event, Campaign, nil + # :profile_id, + # :body validates :profile, :presence => true validates :body, :presence => true, :length => {:maximum => 200} diff --git a/app/models/custom_field_join.rb b/app/models/custom_field_join.rb index 0d96a378..fb915709 100644 --- a/app/models/custom_field_join.rb +++ b/app/models/custom_field_join.rb @@ -1,10 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CustomFieldJoin < ApplicationRecord - attr_accessible \ - :supporter, :supporter_id, - :custom_field_master, :custom_field_master_id, - :value + #TODO + # attr_accessible \ + # :supporter, :supporter_id, + # :custom_field_master, :custom_field_master_id, + # :value validates :custom_field_master, presence: true diff --git a/app/models/dispute.rb b/app/models/dispute.rb index e8b912e4..78bd2754 100644 --- a/app/models/dispute.rb +++ b/app/models/dispute.rb @@ -3,14 +3,15 @@ class Dispute < ApplicationRecord Reasons = [:unrecognized, :duplicate, :fraudulent, :subscription_canceled, :product_unacceptable, :product_not_received, :unrecognized, :credit_not_processed, :goods_services_returned_or_refused, :goods_services_cancelled, :incorrect_account_details, :insufficient_funds, :bank_cannot_process, :debit_not_authorized, :general] - Statuses = [:needs_response, :under_review, :won, :lost, :lost_and_paid] - attr_accessible \ - :gross_amount, # int - :charge_id, :charge, - :payment_id, :payment, - :status, - :reason + Statuses = [:needs_response, :under_review, :won, :lost, :lost_and_paid] + #TODO + # attr_accessible \ + # :gross_amount, # int + # :charge_id, :charge, + # :payment_id, :payment, + # :status, + # :reason belongs_to :charge belongs_to :payment diff --git a/app/models/donation.rb b/app/models/donation.rb index 1c7053d8..b830b8b6 100644 --- a/app/models/donation.rb +++ b/app/models/donation.rb @@ -1,25 +1,26 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Donation < ApplicationRecord - attr_accessible \ - :date, # datetime (when this donation was made) - :amount, # int (in cents) - :recurring, # bool - :anonymous, # bool - :email, # str (cached email of the donor) - :designation, # text - :dedication, # text - :comment, # text - :origin_url, # text - :nonprofit_id, :nonprofit, - :card_id, :card, # Card with which any charges were made - :supporter_id, :supporter, - :profile_id, :profile, - :campaign_id, :campaign, - :payment_id, :payment, - :event_id, :event, - :direct_debit_detail_id, :direct_debit_detail, - :payment_provider + #TODO + # attr_accessible \ + # :date, # datetime (when this donation was made) + # :amount, # int (in cents) + # :recurring, # bool + # :anonymous, # bool + # :email, # str (cached email of the donor) + # :designation, # text + # :dedication, # text + # :comment, # text + # :origin_url, # text + # :nonprofit_id, :nonprofit, + # :card_id, :card, # Card with which any charges were made + # :supporter_id, :supporter, + # :profile_id, :profile, + # :campaign_id, :campaign, + # :payment_id, :payment, + # :event_id, :event, + # :direct_debit_detail_id, :direct_debit_detail, + # :payment_provider validates :amount, presence: true, numericality: { only_integer: true } validates :supporter, presence: true diff --git a/app/models/email_draft.rb b/app/models/email_draft.rb index cc4951b0..7de0e030 100644 --- a/app/models/email_draft.rb +++ b/app/models/email_draft.rb @@ -1,12 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailDraft < ApplicationRecord - - attr_accessible \ - :nonprofit, :nonprofit_id, - :name, - :deleted, - :value, - :created_at + #TODO + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :value, + # :created_at belongs_to :nonprofit diff --git a/app/models/email_setting.rb b/app/models/email_setting.rb index 0171f071..d81db281 100644 --- a/app/models/email_setting.rb +++ b/app/models/email_setting.rb @@ -1,14 +1,15 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailSetting < ApplicationRecord - attr_accessible \ - :user_id, :user, - :nonprofit_id, :nonprofit, - :notify_payments, - :notify_campaigns, - :notify_events, - :notify_payouts, - :notify_recurring_donations + #TODO + # attr_accessible \ + # :user_id, :user, + # :nonprofit_id, :nonprofit, + # :notify_payments, + # :notify_campaigns, + # :notify_events, + # :notify_payouts, + # :notify_recurring_donations belongs_to :nonprofit belongs_to :user diff --git a/app/models/event.rb b/app/models/event.rb index 37c631f7..0e88dc03 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,38 +1,39 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Event < ApplicationRecord - attr_accessible \ - :deleted, #bool for soft-delete - :name, # str - :tagline, # str - :summary, # text - :body, # text (html) - :end_datetime, - :start_datetime, - :latitude, # float - :longitude, # float - :location, # str - :city, # str - :state_code, # str - :address, # str - :zip_code, # str - :main_image, # str - :remove_main_image, # for carrierwave - :background_image, # str - :remove_background_image, # bool carrierwave - :published, # bool - :slug, # str - :directions, # text - :venue_name, # str - :profile_id, # creator - :ticket_levels_attributes, - :show_total_raised, # bool - :show_total_count, # bool - :hide_activity_feed, # bool - :nonprofit_id, # host - :hide_title, # bool - :organizer_email, # string - :receipt_message # text + #TODO + # attr_accessible \ + # :deleted, #bool for soft-delete + # :name, # str + # :tagline, # str + # :summary, # text + # :body, # text (html) + # :end_datetime, + # :start_datetime, + # :latitude, # float + # :longitude, # float + # :location, # str + # :city, # str + # :state_code, # str + # :address, # str + # :zip_code, # str + # :main_image, # str + # :remove_main_image, # for carrierwave + # :background_image, # str + # :remove_background_image, # bool carrierwave + # :published, # bool + # :slug, # str + # :directions, # text + # :venue_name, # str + # :profile_id, # creator + # :ticket_levels_attributes, + # :show_total_raised, # bool + # :show_total_count, # bool + # :hide_activity_feed, # bool + # :nonprofit_id, # host + # :hide_title, # bool + # :organizer_email, # string + # :receipt_message # text validates :name, :presence => true validates :end_datetime, :presence => true diff --git a/app/models/event_discount.rb b/app/models/event_discount.rb index 2888ecaa..d09d5c9b 100644 --- a/app/models/event_discount.rb +++ b/app/models/event_discount.rb @@ -1,10 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventDiscount < ApplicationRecord - attr_accessible \ - :code, - :event_id, - :name, - :percent + #TODO + # attr_accessible \ + # :code, + # :event_id, + # :name, + # :percent belongs_to :event has_many :tickets diff --git a/app/models/full_contact_info.rb b/app/models/full_contact_info.rb index 7862d89d..2035a618 100644 --- a/app/models/full_contact_info.rb +++ b/app/models/full_contact_info.rb @@ -1,19 +1,20 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactInfo < ApplicationRecord - attr_accessible \ - :email, - :full_name, - :gender, - :city, - :county, - :state_code, - :country, - :continent, - :age, - :age_range, - :location_general, - :supporter_id, :supporter, - :websites + #TODO + # attr_accessible \ + # :email, + # :full_name, + # :gender, + # :city, + # :county, + # :state_code, + # :country, + # :continent, + # :age, + # :age_range, + # :location_general, + # :supporter_id, :supporter, + # :websites has_many :full_contact_photos has_many :full_contact_social_profiles diff --git a/app/models/full_contact_org.rb b/app/models/full_contact_org.rb index 05acfc9c..2f0b0a43 100644 --- a/app/models/full_contact_org.rb +++ b/app/models/full_contact_org.rb @@ -1,15 +1,16 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactOrg < ApplicationRecord - attr_accessible \ - :name, - :is_primary, - :name, - :start_date, - :end_date, - :title, - :current, - :full_contact_info_id, :full_contact_info + #TODO + # attr_accessible \ + # :name, + # :is_primary, + # :name, + # :start_date, + # :end_date, + # :title, + # :current, + # :full_contact_info_id, :full_contact_info belongs_to :full_contact_info diff --git a/app/models/full_contact_photo.rb b/app/models/full_contact_photo.rb index b96a5bb7..181b92fe 100644 --- a/app/models/full_contact_photo.rb +++ b/app/models/full_contact_photo.rb @@ -1,11 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactPhoto < ApplicationRecord - attr_accessible \ - :full_contact_info, - :full_contact_info_id, - :type_id, # i.e. twitter, linkedin, facebook - :is_primary, #bool - :url #string + #TODO + # attr_accessible \ + # :full_contact_info, + # :full_contact_info_id, + # :type_id, # i.e. twitter, linkedin, facebook + # :is_primary, #bool + # :url #string belongs_to :full_contact_info diff --git a/app/models/full_contact_social_profile.rb b/app/models/full_contact_social_profile.rb index b98a4dd3..b85511dd 100644 --- a/app/models/full_contact_social_profile.rb +++ b/app/models/full_contact_social_profile.rb @@ -1,13 +1,14 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactSocialProfile < ApplicationRecord - attr_accessible \ - :full_contact_info, - :full_contact_info_id, - :type_id, # i.e. twitter, linkedin, facebook - :username, #string - :uid, # string - :bio, #string - :url #string + #TODO + # attr_accessible \ + # :full_contact_info, + # :full_contact_info_id, + # :type_id, # i.e. twitter, linkedin, facebook + # :username, #string + # :uid, # string + # :bio, #string + # :url #string belongs_to :full_contact_info diff --git a/app/models/full_contact_topic.rb b/app/models/full_contact_topic.rb index 0839097b..5dcdbf97 100644 --- a/app/models/full_contact_topic.rb +++ b/app/models/full_contact_topic.rb @@ -1,10 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactTopic < ApplicationRecord - attr_accessible \ - :provider, - :value, - :full_contact_info_id, :full_contact_info + #TODO + # attr_accessible \ + # :provider, + # :value, + # :full_contact_info_id, :full_contact_info belongs_to :full_contact_info diff --git a/app/models/import.rb b/app/models/import.rb index 66a06071..4c056f1e 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -1,13 +1,14 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Import < ApplicationRecord - attr_accessible \ - :user_id, :user, - :email, # email of the user who ma - :nonprofit_id, :nonprofit, - :row_count, - :imported_count, - :date + #TODO + # attr_accessible \ + # :user_id, :user, + # :email, # email of the user who ma + # :nonprofit_id, :nonprofit, + # :row_count, + # :imported_count, + # :date has_many :supporters belongs_to :nonprofit diff --git a/app/models/miscellaneous_np_info.rb b/app/models/miscellaneous_np_info.rb index a9ba9179..240d6478 100644 --- a/app/models/miscellaneous_np_info.rb +++ b/app/models/miscellaneous_np_info.rb @@ -1,9 +1,10 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class MiscellaneousNpInfo < ApplicationRecord - attr_accessible \ - :donate_again_url, - :change_amount_message + #TODO + # attr_accessible \ + # :donate_again_url, + # :change_amount_message belongs_to :nonprofit end diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index b2bda8d4..f03781f1 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -3,54 +3,55 @@ class Nonprofit < ApplicationRecord Categories = ["Public Benefit", "Human Services", "Education", "Civic Duty", "Human Rights", "Animals", "Environment", "Health", "Arts, Culture, Humanities", "International", "Children", "Religion", "LGBTQ", "Women's Rights", "Disaster Relief", "Veterans"] - attr_accessible \ - :name, # str - :stripe_account_id, # str - :summary, # text: paragraph-sized organization summary - :tagline, # str - :email, # str: public organization contact email - :phone, # str: public org contact phone - :main_image, # str: url of featured image - first image in profile carousel - :second_image, # str: url of 2nd image in carousel - :third_image, # str: url of 3rd image in carousel - :background_image, # str: url of large profile background - :remove_background_image, #bool carrierwave - :logo, # str: small logo image url for searching - :zip_code, # int - :website, # str: their own website url - :categories, # text [str]: see the constant Categories - :achievements, # text [str]: highlights about this org - :full_description, # text - :state_code, # str: two-letter state code (eg. CA) - :statement, # str: bank statement for donations towards the nonprofit - :city, # str - :slug, # str - :city_slug, #str - :state_code_slug, #str - :ein, # str: employee identification number - :published, # boolean; whether to display this profile - :vetted, # bool: Whether a super admin (one of CommitChange's employees) have approved this org - :verification_status, # str (either 'pending', 'unverified', 'escalated', 'verified' -- whether the org has submitted the identity verification form and it has been approved) - :latitude, # float: geocoder gem - :longitude, # float: geocoder gem - :timezone, # str - :address, # text - :thank_you_note, # text - :referrer, # str - :no_anon, # bool: whether to allow anonymous donations - :roles_attributes, - :brand_font, #string (lowercase key eg. 'helvetica') - :brand_color, #string (hex color value) - :hide_activity_feed, # bool - :tracking_script, - :facebook, #string (url) - :twitter, #string (url) - :youtube, #string (url) - :instagram, #string (url) - :blog, #string (url) - :card_failure_message_top, # text - :card_failure_message_bottom, # text - :autocomplete_supporter_address # boolean + #TODO + # attr_accessible \ + # :name, # str + # :stripe_account_id, # str + # :summary, # text: paragraph-sized organization summary + # :tagline, # str + # :email, # str: public organization contact email + # :phone, # str: public org contact phone + # :main_image, # str: url of featured image - first image in profile carousel + # :second_image, # str: url of 2nd image in carousel + # :third_image, # str: url of 3rd image in carousel + # :background_image, # str: url of large profile background + # :remove_background_image, #bool carrierwave + # :logo, # str: small logo image url for searching + # :zip_code, # int + # :website, # str: their own website url + # :categories, # text [str]: see the constant Categories + # :achievements, # text [str]: highlights about this org + # :full_description, # text + # :state_code, # str: two-letter state code (eg. CA) + # :statement, # str: bank statement for donations towards the nonprofit + # :city, # str + # :slug, # str + # :city_slug, #str + # :state_code_slug, #str + # :ein, # str: employee identification number + # :published, # boolean; whether to display this profile + # :vetted, # bool: Whether a super admin (one of CommitChange's employees) have approved this org + # :verification_status, # str (either 'pending', 'unverified', 'escalated', 'verified' -- whether the org has submitted the identity verification form and it has been approved) + # :latitude, # float: geocoder gem + # :longitude, # float: geocoder gem + # :timezone, # str + # :address, # text + # :thank_you_note, # text + # :referrer, # str + # :no_anon, # bool: whether to allow anonymous donations + # :roles_attributes, + # :brand_font, #string (lowercase key eg. 'helvetica') + # :brand_color, #string (hex color value) + # :hide_activity_feed, # bool + # :tracking_script, + # :facebook, #string (url) + # :twitter, #string (url) + # :youtube, #string (url) + # :instagram, #string (url) + # :blog, #string (url) + # :card_failure_message_top, # text + # :card_failure_message_bottom, # text + # :autocomplete_supporter_address # boolean has_many :payouts has_many :charges diff --git a/app/models/nonprofit_account.rb b/app/models/nonprofit_account.rb index b5ee62d0..b4f67ffe 100644 --- a/app/models/nonprofit_account.rb +++ b/app/models/nonprofit_account.rb @@ -1,9 +1,10 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NonprofitAccount < ApplicationRecord - attr_accessible \ - :stripe_account_id, #str - :nonprofit, :nonprofit_id #int + #TODO + # attr_accessible \ + # :stripe_account_id, #str + # :nonprofit, :nonprofit_id #int belongs_to :nonprofit diff --git a/app/models/payment.rb b/app/models/payment.rb index 4e622d7b..be3d68e8 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -5,13 +5,14 @@ class Payment < ApplicationRecord - attr_accessible \ - :towards, - :gross_amount, - :refund_total, - :fee_total, - :kind, - :date +#TODO +# attr_accessible \ +# :towards, +# :gross_amount, +# :refund_total, +# :fee_total, +# :kind, +# :date belongs_to :supporter belongs_to :nonprofit diff --git a/app/models/payment_payout.rb b/app/models/payment_payout.rb index 3c686763..b3b01465 100644 --- a/app/models/payment_payout.rb +++ b/app/models/payment_payout.rb @@ -13,11 +13,12 @@ class PaymentPayout < ApplicationRecord - attr_accessible \ - :payment_id, :payment, - :charge_id, :charge, # deprecated - :payout_id, :payout, - :total_fees # int (cents) + #TODO + # attr_accessible \ + # :payment_id, :payment, + # :charge_id, :charge, # deprecated + # :payout_id, :payout, + # :total_fees # int (cents) belongs_to :charge # deprecated belongs_to :payment diff --git a/app/models/payout.rb b/app/models/payout.rb index 58fd8542..6529ea1d 100644 --- a/app/models/payout.rb +++ b/app/models/payout.rb @@ -6,20 +6,21 @@ class Payout < ApplicationRecord - attr_accessible \ - :scheduled, # bool (whether this was made automatically at the beginning of the month) - :count, # int (number of donations for this payout) - :ach_fee, # int (in cents, the total fee for the payout itself) - :gross_amount, # int (in cents, total amount before fees) - :fee_total, # int (in cents, total amount of fees) - :net_amount, # int (in cents, total amount after fees for this payout) - :email, # str (cache of user email who issued this) - :user_ip, # str (ip address of the user who made this payout) - :status, # str ('pending', 'paid', 'canceled', or 'failed') - :failure_message, # str - :bank_name, # str: cache of the nonprofit's bank name - :stripe_transfer_id, # str - :nonprofit_id, :nonprofit + #TODO + # attr_accessible \ + # :scheduled, # bool (whether this was made automatically at the beginning of the month) + # :count, # int (number of donations for this payout) + # :ach_fee, # int (in cents, the total fee for the payout itself) + # :gross_amount, # int (in cents, total amount before fees) + # :fee_total, # int (in cents, total amount of fees) + # :net_amount, # int (in cents, total amount after fees for this payout) + # :email, # str (cache of user email who issued this) + # :user_ip, # str (ip address of the user who made this payout) + # :status, # str ('pending', 'paid', 'canceled', or 'failed') + # :failure_message, # str + # :bank_name, # str: cache of the nonprofit's bank name + # :stripe_transfer_id, # str + # :nonprofit_id, :nonprofit belongs_to :nonprofit has_one :bank_account, through: :nonprofit diff --git a/app/models/profile.rb b/app/models/profile.rb index d9e17c0d..be081dd6 100755 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -1,23 +1,24 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Profile < ApplicationRecord - attr_accessible \ - :registered, # bool - :mini_bio, - :first_name, # str - :last_name, # str - :name, - :phone, # str - :address, # str - :email, # str - :city, # str - :state_code, # str (eg. CA) - :zip_code, # str - :privacy_settings, # text [str]: XXX deprecated - :picture, # str: either their social network pic or a stored pic on S3 - :anonymous, # bool: negates all privacy_settings - :city_state, - :user_id + #TODO + # attr_accessible \ + # :registered, # bool + # :mini_bio, + # :first_name, # str + # :last_name, # str + # :name, + # :phone, # str + # :address, # str + # :email, # str + # :city, # str + # :state_code, # str (eg. CA) + # :zip_code, # str + # :privacy_settings, # text [str]: XXX deprecated + # :picture, # str: either their social network pic or a stored pic on S3 + # :anonymous, # bool: negates all privacy_settings + # :city_state, + # :user_id validates :email, format: {with: Email::Regex}, allow_blank: true diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index 3e018bbe..55e585fd 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -1,21 +1,22 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RecurringDonation < ApplicationRecord - attr_accessible \ - :amount, # int (cents) - :active, # bool (whether this recurring donation should still be paid) - :paydate, # int (fixed date of the month for monthly recurring donations) - :interval, # int (interval of time, ie the '3' in '3 months') - :time_unit, # str ('month', 'day', 'week', or 'year') - :start_date, # date (when to start this recurring donation) - :end_date, # date (when to deactivate this recurring donation) - :n_failures, # int (how many times the charge has failed) - :edit_token, # str / uuid to validate the editing page, linked from their email client - :cancelled_by, # str email of user/supporter who made the cancellation - :cancelled_at, # datetime of user/supporter who made the cancellation - :donation_id, :donation, - :nonprofit_id, :nonprofit, - :supporter_id #used because things are messed up in the datamodel + #TODO: + # attr_accessible \ + # :amount, # int (cents) + # :active, # bool (whether this recurring donation should still be paid) + # :paydate, # int (fixed date of the month for monthly recurring donations) + # :interval, # int (interval of time, ie the '3' in '3 months') + # :time_unit, # str ('month', 'day', 'week', or 'year') + # :start_date, # date (when to start this recurring donation) + # :end_date, # date (when to deactivate this recurring donation) + # :n_failures, # int (how many times the charge has failed) + # :edit_token, # str / uuid to validate the editing page, linked from their email client + # :cancelled_by, # str email of user/supporter who made the cancellation + # :cancelled_at, # datetime of user/supporter who made the cancellation + # :donation_id, :donation, + # :nonprofit_id, :nonprofit, + # :supporter_id #used because things are messed up in the datamodel scope :active, -> {where(active: true)} scope :inactive, -> {where(active: [false,nil])} diff --git a/app/models/refund.rb b/app/models/refund.rb index 25e7cf8b..ef37db60 100644 --- a/app/models/refund.rb +++ b/app/models/refund.rb @@ -3,16 +3,17 @@ class Refund < ApplicationRecord Reasons = [:duplicate, :fraudulent, :requested_by_customer] - attr_accessible \ - :amount, # int - :comment, # text - :reason, # str ('duplicate', 'fraudulent', or 'requested_by_customer') - :stripe_refund_id, - :disbursed, # boolean (whether this refund has been counted in a payout) - :failure_message, # str (accessor for storing the Stripe error message) - :user_id, :user, # user who made this refund - :payment_id, :payment, # negative payment that records this refund - :charge_id, :charge + # TODO: + # attr_accessible \ + # :amount, # int + # :comment, # text + # :reason, # str ('duplicate', 'fraudulent', or 'requested_by_customer') + # :stripe_refund_id, + # :disbursed, # boolean (whether this refund has been counted in a payout) + # :failure_message, # str (accessor for storing the Stripe error message) + # :user_id, :user, # user who made this refund + # :payment_id, :payment, # negative payment that records this refund + # :charge_id, :charge attr_accessor :failure_message diff --git a/app/models/role.rb b/app/models/role.rb index 8bbd5263..215e24af 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -10,10 +10,11 @@ class Role < ApplicationRecord :event_editor # // ] - attr_accessible \ - :name, - :user_id, :user, - :host, :host_id, :host_type # nil, "Nonprofit", "Campaign", "Event" + # TODO: + # attr_accessible \ + # :name, + # :user_id, :user, + # :host, :host_id, :host_type # nil, "Nonprofit", "Campaign", "Event" belongs_to :user belongs_to :host, polymorphic: true diff --git a/app/models/supporter.rb b/app/models/supporter.rb index 05674b16..cdb087a2 100644 --- a/app/models/supporter.rb +++ b/app/models/supporter.rb @@ -1,33 +1,34 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Supporter < ApplicationRecord - attr_accessible \ - :search_vectors, - :profile_id, :profile, - :nonprofit_id, :nonprofit, - :full_contact_info, :full_contact_info_id, - :import_id, :import, - :name, - :first_name, - :last_name, - :email, - :address, - :city, - :state_code, - :country, - :phone, - :organization, - :latitude, - :locale, - :longitude, - :zip_code, - :total_raised, - :notes, - :fields, - :anonymous, - :deleted, # bool (flag for soft delete) - :email_unsubscribe_uuid, #string - :is_unsubscribed_from_emails #bool + #TODO + # attr_accessible \ + # :search_vectors, + # :profile_id, :profile, + # :nonprofit_id, :nonprofit, + # :full_contact_info, :full_contact_info_id, + # :import_id, :import, + # :name, + # :first_name, + # :last_name, + # :email, + # :address, + # :city, + # :state_code, + # :country, + # :phone, + # :organization, + # :latitude, + # :locale, + # :longitude, + # :zip_code, + # :total_raised, + # :notes, + # :fields, + # :anonymous, + # :deleted, # bool (flag for soft delete) + # :email_unsubscribe_uuid, #string + # :is_unsubscribed_from_emails #bool belongs_to :profile belongs_to :nonprofit diff --git a/app/models/supporter_email.rb b/app/models/supporter_email.rb index 0e9b2e53..3cd856f9 100644 --- a/app/models/supporter_email.rb +++ b/app/models/supporter_email.rb @@ -1,14 +1,15 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SupporterEmail < ApplicationRecord - attr_accessible \ - :to, - :from, - :subject, - :body, - :recipient_count, - :supporter_id, :supporter, - :nonprofit_id, - :gmail_thread_id + # TODO + # attr_accessible \ + # :to, + # :from, + # :subject, + # :body, + # :recipient_count, + # :supporter_id, :supporter, + # :nonprofit_id, + # :gmail_thread_id belongs_to :supporter validates_presence_of :nonprofit_id diff --git a/app/models/supporter_note.rb b/app/models/supporter_note.rb index ff7d29f9..8701dd2b 100644 --- a/app/models/supporter_note.rb +++ b/app/models/supporter_note.rb @@ -1,9 +1,10 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SupporterNote < ApplicationRecord - attr_accessible \ - :content, - :supporter_id, :supporter + #TODO + # attr_accessible \ + # :content, + # :supporter_id, :supporter belongs_to :supporter has_many :activities, as: :attachment, dependent: :destroy diff --git a/app/models/tag_join.rb b/app/models/tag_join.rb index d531ddb9..45ee10c5 100644 --- a/app/models/tag_join.rb +++ b/app/models/tag_join.rb @@ -1,9 +1,10 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TagJoin < ApplicationRecord - attr_accessible \ - :supporter, :supporter_id, - :tag_master, :tag_master_id + #TODO + # attr_accessible \ + # :supporter, :supporter_id, + # :tag_master, :tag_master_id validates :tag_master, presence: true diff --git a/app/models/tag_master.rb b/app/models/tag_master.rb index 836bdbfb..9bac71ce 100644 --- a/app/models/tag_master.rb +++ b/app/models/tag_master.rb @@ -1,11 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TagMaster < ApplicationRecord - attr_accessible \ - :nonprofit, :nonprofit_id, - :name, - :deleted, - :created_at + #TODO: + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :created_at validates :name, presence: true validate :no_dupes, on: :create diff --git a/app/models/ticket_level.rb b/app/models/ticket_level.rb index 130157e0..d9d7942d 100644 --- a/app/models/ticket_level.rb +++ b/app/models/ticket_level.rb @@ -1,17 +1,18 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TicketLevel < ApplicationRecord - attr_accessible \ - :amount, #integer - :amount_dollars, #accessor, string - :name, #string - :description, #text - :quantity, #integer - :deleted, #bool for soft delete - :event_id, - :admin_only, #bool, only admins can create tickets for this level - :limit, #int: for limiting the number of tickets to be sold - :order #int: order in which to be displayed + #TODO + # attr_accessible \ + # :amount, #integer + # :amount_dollars, #accessor, string + # :name, #string + # :description, #text + # :quantity, #integer + # :deleted, #bool for soft delete + # :event_id, + # :admin_only, #bool, only admins can create tickets for this level + # :limit, #int: for limiting the number of tickets to be sold + # :order #int: order in which to be displayed attr_accessor :amount_dollars diff --git a/app/models/user.rb b/app/models/user.rb index dffee4cb..31b0aba1 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,29 +1,30 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class User < ApplicationRecord - attr_accessible \ - :email, # str: balidated with Devise - :password, # str: hashed with bcrypt - :phone, # str - :location, - :city, - :state_code, - :password_confirmation, # accessor: used on registration - :remember_me, # bool: don't sign user out for a while - :provider, # str: OAuth provider - :uid, # str: OAuth user ID - :pending_password, # bool: User registered with oauth and did not set a password - :name, # str: created with oauth - :auto_generated, # bool: flag whether a password was auto-generated for this account - :referer, # str: ID of the user who referred this account - :latitude, - :longitude, - :reset_password_token, - :reset_password_sent_at, - :picture, # str: url for fb or twitter pic - :current_password, # accessor: for updating pass - :profile_attributes, - :phone + #TODO: + # attr_accessible \ + # :email, # str: balidated with Devise + # :password, # str: hashed with bcrypt + # :phone, # str + # :location, + # :city, + # :state_code, + # :password_confirmation, # accessor: used on registration + # :remember_me, # bool: don't sign user out for a while + # :provider, # str: OAuth provider + # :uid, # str: OAuth user ID + # :pending_password, # bool: User registered with oauth and did not set a password + # :name, # str: created with oauth + # :auto_generated, # bool: flag whether a password was auto-generated for this account + # :referer, # str: ID of the user who referred this account + # :latitude, + # :longitude, + # :reset_password_token, + # :reset_password_sent_at, + # :picture, # str: url for fb or twitter pic + # :current_password, # accessor: for updating pass + # :profile_attributes, + # :phone geocoded_by :location From 8db525c2b85a286448bc8269550bc6c18a638eea Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 21 Jun 2019 17:14:27 -0500 Subject: [PATCH 36/77] Comment out mass assignment sanitizer --- Gemfile.lock | 8 -------- config/environments/development.rb | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5a900acc..7620cb74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,10 +72,6 @@ GEM tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) - airbrake (8.0.1) - airbrake-ruby (~> 3.0) - airbrake-ruby (3.1.0) - tdigest (= 0.1.1) amq-protocol (2.3.0) andand (1.3.3) arel (7.1.4) @@ -361,7 +357,6 @@ GEM thor (>= 0.18.1, < 2.0) rainbow (3.0.0) rake (12.3.2) - rbtree (0.4.2) request_store (1.4.1) rack (>= 1.4) require_all (2.0.0) @@ -448,8 +443,6 @@ GEM stripe (1.58.0) rest-client (>= 1.4, < 4.0) table_print (1.5.6) - tdigest (0.1.1) - rbtree (~> 0.4.2) test-unit (3.2.8) power_assert thor (0.19.4) @@ -489,7 +482,6 @@ PLATFORMS DEPENDENCIES action_mailer_matchers - airbrake (~> 8.0.1) aws-sdk (~> 1) aws-ses binding_of_caller diff --git a/config/environments/development.rb b/config/environments/development.rb index ab9d88d3..8c42eb73 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -52,7 +52,7 @@ Rails.application.configure do config.active_support.deprecation = :log # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + # config.active_record.mass_assignment_sanitizer = :strict # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load From 28df345478b82fc0c0670c7a9d59c2efab03e6c0 Mon Sep 17 00:00:00 2001 From: Eric Schultz Date: Fri, 21 Jun 2019 17:15:07 -0500 Subject: [PATCH 37/77] Comment out quiet_assets --- config/initializers/quiet_assets.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/config/initializers/quiet_assets.rb b/config/initializers/quiet_assets.rb index 98f72a62..7bb65cb7 100644 --- a/config/initializers/quiet_assets.rb +++ b/config/initializers/quiet_assets.rb @@ -1,14 +1,14 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later if Rails.env.development? - Rails.application.assets.logger = Logger.new('/dev/null') - Rails::Rack::Logger.class_eval do - def call_with_quiet_assets(env) - previous_level = Rails.logger.level - Rails.logger.level = Logger::ERROR if env['PATH_INFO'] =~ %r{^/assets/} - call_without_quiet_assets(env) - ensure - Rails.logger.level = previous_level - end - alias_method_chain :call, :quiet_assets - end + # Rails.application.assets.logger = Logger.new('/dev/null') + # Rails::Rack::Logger.class_eval do + # def call_with_quiet_assets(env) + # previous_level = Rails.logger.level + # Rails.logger.level = Logger::ERROR if env['PATH_INFO'] =~ %r{^/assets/} + # call_without_quiet_assets(env) + # ensure + # Rails.logger.level = previous_level + # end + # alias_method_chain :call, :quiet_assets + # end end From d9895890a0aff13185aa2df7ecd40e87661cdf11 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 09:50:34 +0200 Subject: [PATCH 38/77] chore: create uniq db for continous integration --- config/database.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.yml b/config/database.yml index 50c799fe..a36d1ef2 100755 --- a/config/database.yml +++ b/config/database.yml @@ -33,7 +33,7 @@ test: ci: adapter: postgresql encoding: unicode - database: commitchange_development + database: commitchange_ci pool: 5 username: admin password: password From 34b4604c7a7a18a7a6f12f825c8fd8695d416668 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 09:51:00 +0200 Subject: [PATCH 39/77] fix: Puma server config syntax --- config/puma.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/puma.rb b/config/puma.rb index 5695f3af..b93dad33 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -13,9 +13,9 @@ preload_app! if ENV['RAILS_ENV'] != 'development' rackup DefaultRackup port ENV.fetch("PORT") { 5000 } -environment ENV.fetch('RAILS_ENV'{ 'development' } +environment ENV.fetch('RAILS_ENV'){ 'development' } -workers ENV['WEB_CONCURRENCY'].fetch { 1 } +workers Integer(ENV['WEB_CONCURRENCY'] || 1) From dd64ee5159931516b9e6a1be9169a49e98c67dfb Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 09:53:59 +0200 Subject: [PATCH 40/77] feat: replace deprecated before_filter with before_action --- app/controllers/activities_controller.rb | 2 +- app/controllers/application_controller.rb | 2 +- app/controllers/aws_presigned_posts_controller.rb | 2 +- app/controllers/billing_subscriptions_controller.rb | 2 +- app/controllers/campaign_gift_options_controller.rb | 2 +- .../campaigns/campaign_gift_options_controller.rb | 2 +- app/controllers/campaigns/donations_controller.rb | 2 +- app/controllers/campaigns/supporters_controller.rb | 2 +- app/controllers/campaigns_controller.rb | 6 +++--- app/controllers/cards_controller.rb | 2 +- app/controllers/email_settings_controller.rb | 2 +- app/controllers/emails_controller.rb | 2 +- app/controllers/event_discounts_controller.rb | 2 +- app/controllers/events_controller.rb | 4 ++-- app/controllers/image_attachments_controller.rb | 2 +- app/controllers/maps_controller.rb | 4 ++-- app/controllers/nonprofits/activities_controller.rb | 2 +- app/controllers/nonprofits/bank_accounts_controller.rb | 2 +- app/controllers/nonprofits/button_controller.rb | 2 +- app/controllers/nonprofits/cards_controller.rb | 2 +- app/controllers/nonprofits/charges_controller.rb | 2 +- app/controllers/nonprofits/custom_field_joins_controller.rb | 2 +- .../nonprofits/custom_field_masters_controller.rb | 2 +- app/controllers/nonprofits/donations_controller.rb | 4 ++-- app/controllers/nonprofits/email_lists_controller.rb | 2 +- app/controllers/nonprofits/imports_controller.rb | 2 +- .../nonprofits/miscellaneous_np_infos_controller.rb | 2 +- app/controllers/nonprofits/nonprofit_keys_controller.rb | 2 +- app/controllers/nonprofits/payments_controller.rb | 2 +- app/controllers/nonprofits/payouts_controller.rb | 4 ++-- .../nonprofits/recurring_donations_controller.rb | 2 +- app/controllers/nonprofits/refunds_controller.rb | 2 +- app/controllers/nonprofits/reports_controller.rb | 2 +- app/controllers/nonprofits/supporter_emails_controller.rb | 2 +- app/controllers/nonprofits/supporter_notes_controller.rb | 2 +- app/controllers/nonprofits/supporters_controller.rb | 4 ++-- app/controllers/nonprofits/tag_joins_controller.rb | 2 +- app/controllers/nonprofits/tag_masters_controller.rb | 2 +- app/controllers/nonprofits_controller.rb | 4 ++-- app/controllers/profiles_controller.rb | 2 +- app/controllers/roles_controller.rb | 2 +- app/controllers/settings_controller.rb | 2 +- app/controllers/super_admins_controller.rb | 2 +- app/controllers/ticket_levels_controller.rb | 2 +- app/controllers/tickets_controller.rb | 4 ++-- 45 files changed, 54 insertions(+), 54 deletions(-) diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index 07dd5f2c..c2028140 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ActivitiesController < ApplicationController - before_filter :authenticate_user!, only: [:create] + before_action :authenticate_user!, only: [:create] def create json_saved Activity.create(params[:activity]) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 76f75165..09be7bba 100755 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ApplicationController < ActionController::Base - before_filter :set_locale, :redirect_to_maintenance + before_action :set_locale, :redirect_to_maintenance protect_from_forgery diff --git a/app/controllers/aws_presigned_posts_controller.rb b/app/controllers/aws_presigned_posts_controller.rb index bdea0839..a6855266 100644 --- a/app/controllers/aws_presigned_posts_controller.rb +++ b/app/controllers/aws_presigned_posts_controller.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AwsPresignedPostsController < ApplicationController - before_filter :authenticate_user! + before_action :authenticate_user! # post /presigned_posts # Create some keys using the AWS gem so the user can do direct-to-S3 uploads diff --git a/app/controllers/billing_subscriptions_controller.rb b/app/controllers/billing_subscriptions_controller.rb index 1f63fb4b..cee634ed 100644 --- a/app/controllers/billing_subscriptions_controller.rb +++ b/app/controllers/billing_subscriptions_controller.rb @@ -2,7 +2,7 @@ class BillingSubscriptionsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! def create_trial render JsonResp.new(params){|params| diff --git a/app/controllers/campaign_gift_options_controller.rb b/app/controllers/campaign_gift_options_controller.rb index 47b21367..044aab0b 100644 --- a/app/controllers/campaign_gift_options_controller.rb +++ b/app/controllers/campaign_gift_options_controller.rb @@ -2,7 +2,7 @@ class CampaignGiftOptionsController < ApplicationController include Controllers::CampaignHelper - before_filter :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order] + before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order] def index @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') diff --git a/app/controllers/campaigns/campaign_gift_options_controller.rb b/app/controllers/campaigns/campaign_gift_options_controller.rb index 83e5da31..eba8451d 100644 --- a/app/controllers/campaigns/campaign_gift_options_controller.rb +++ b/app/controllers/campaigns/campaign_gift_options_controller.rb @@ -2,7 +2,7 @@ module Campaigns; class CampaignGiftOptionsController < ApplicationController include Controllers::CampaignHelper - before_filter :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order, :report] + before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order, :report] def report respond_to do |format| diff --git a/app/controllers/campaigns/donations_controller.rb b/app/controllers/campaigns/donations_controller.rb index 44cb27a1..a53c0f3d 100644 --- a/app/controllers/campaigns/donations_controller.rb +++ b/app/controllers/campaigns/donations_controller.rb @@ -3,7 +3,7 @@ module Campaigns class DonationsController < ApplicationController include Controllers::CampaignHelper - before_filter :authenticate_campaign_editor!, only: [:index] + before_action :authenticate_campaign_editor!, only: [:index] def index respond_to do |format| diff --git a/app/controllers/campaigns/supporters_controller.rb b/app/controllers/campaigns/supporters_controller.rb index 9796e687..5f77ffd0 100644 --- a/app/controllers/campaigns/supporters_controller.rb +++ b/app/controllers/campaigns/supporters_controller.rb @@ -3,7 +3,7 @@ module Campaigns class SupportersController < ApplicationController include Controllers::CampaignHelper - before_filter :authenticate_campaign_editor!, only: [:index] + before_action :authenticate_campaign_editor!, only: [:index] def index @panels_layout = true diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index 03e95d51..a6d34d21 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -3,9 +3,9 @@ class CampaignsController < ApplicationController include Controllers::CampaignHelper helper_method :current_campaign_editor? - before_filter :authenticate_confirmed_user!, only: [:create, :name_and_id, :duplicate] - before_filter :authenticate_campaign_editor!, only: [:update, :soft_delete] - before_filter :check_nonprofit_status, only: [:index, :show] + before_action :authenticate_confirmed_user!, only: [:create, :name_and_id, :duplicate] + before_action :authenticate_campaign_editor!, only: [:update, :soft_delete] + before_action :check_nonprofit_status, only: [:index, :show] def index @nonprofit = current_nonprofit diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index 4e84fd1e..bcd7c72b 100755 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CardsController < ApplicationController - before_filter :authenticate_user!, :except => [:create] + before_action :authenticate_user!, :except => [:create] # post /cards def create diff --git a/app/controllers/email_settings_controller.rb b/app/controllers/email_settings_controller.rb index 5eaf43fa..1c94c8b2 100644 --- a/app/controllers/email_settings_controller.rb +++ b/app/controllers/email_settings_controller.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailSettingsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index user = current_role?(:super_admin) ? User.find(params[:user_id]) : current_user diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb index 7ece89da..60c2b324 100644 --- a/app/controllers/emails_controller.rb +++ b/app/controllers/emails_controller.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailsController < ApplicationController - before_filter :authenticate_user! + before_action :authenticate_user! def create email = params[:email] diff --git a/app/controllers/event_discounts_controller.rb b/app/controllers/event_discounts_controller.rb index 21a4bbf5..167637c2 100644 --- a/app/controllers/event_discounts_controller.rb +++ b/app/controllers/event_discounts_controller.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventDiscountsController < ApplicationController include Controllers::EventHelper - before_filter :authenticate_event_editor!, :except => [:index] + before_action :authenticate_event_editor!, :except => [:index] def create params[:event_discount][:event_id] = current_event.id diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 6710adca..b0c82467 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -3,8 +3,8 @@ class EventsController < ApplicationController include Controllers::EventHelper helper_method :current_event_editor? - before_filter :authenticate_nonprofit_user!, only: :name_and_id - before_filter :authenticate_event_editor!, only: [:update, :soft_delete, :stats, :create, :duplicate] + before_action :authenticate_nonprofit_user!, only: :name_and_id + before_action :authenticate_event_editor!, only: [:update, :soft_delete, :stats, :create, :duplicate] def index diff --git a/app/controllers/image_attachments_controller.rb b/app/controllers/image_attachments_controller.rb index aa378f5d..9f47cbbd 100644 --- a/app/controllers/image_attachments_controller.rb +++ b/app/controllers/image_attachments_controller.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ImageAttachmentsController < ApplicationController - before_filter :authenticate_confirmed_user! + before_action :authenticate_confirmed_user! def create # must return json with a link attr # http://editor.froala.com/server-integrations/php-image-upload diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 8fe38819..1e5df927 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -2,8 +2,8 @@ class MapsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_super_associate!, only: :all_supporters - before_filter :authenticate_nonprofit_user!, only: [:all_npo_supporters, :specific_npo_supporters] + before_action :authenticate_super_associate!, only: :all_supporters + before_action :authenticate_nonprofit_user!, only: [:all_npo_supporters, :specific_npo_supporters] # used on admin/nonprofits_map and front page def all_npos diff --git a/app/controllers/nonprofits/activities_controller.rb b/app/controllers/nonprofits/activities_controller.rb index 6824e8a7..87696c3a 100644 --- a/app/controllers/nonprofits/activities_controller.rb +++ b/app/controllers/nonprofits/activities_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class ActivitiesController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! # get /nonprofits/:nonprofit_id/supporters/:supporter_id/activities def index diff --git a/app/controllers/nonprofits/bank_accounts_controller.rb b/app/controllers/nonprofits/bank_accounts_controller.rb index c68ef006..9073c33d 100644 --- a/app/controllers/nonprofits/bank_accounts_controller.rb +++ b/app/controllers/nonprofits/bank_accounts_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class BankAccountsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! # post /nonprofits/:nonprofit_id/bank_account # must pass in the user's password as params[:password] diff --git a/app/controllers/nonprofits/button_controller.rb b/app/controllers/nonprofits/button_controller.rb index 83a6765e..a2258b36 100644 --- a/app/controllers/nonprofits/button_controller.rb +++ b/app/controllers/nonprofits/button_controller.rb @@ -4,7 +4,7 @@ class ButtonController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_user! + before_action :authenticate_user! def send_code diff --git a/app/controllers/nonprofits/cards_controller.rb b/app/controllers/nonprofits/cards_controller.rb index fc0e377b..1ee6fdee 100644 --- a/app/controllers/nonprofits/cards_controller.rb +++ b/app/controllers/nonprofits/cards_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class CardsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def edit @nonprofit = current_nonprofit diff --git a/app/controllers/nonprofits/charges_controller.rb b/app/controllers/nonprofits/charges_controller.rb index e3d87a6c..25ee872d 100644 --- a/app/controllers/nonprofits/charges_controller.rb +++ b/app/controllers/nonprofits/charges_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class ChargesController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user!, only: :index + before_action :authenticate_nonprofit_user!, only: :index # get /nonprofit/:nonprofit_id/charges def index diff --git a/app/controllers/nonprofits/custom_field_joins_controller.rb b/app/controllers/nonprofits/custom_field_joins_controller.rb index 9c1a7fe2..2c36cfaa 100644 --- a/app/controllers/nonprofits/custom_field_joins_controller.rb +++ b/app/controllers/nonprofits/custom_field_joins_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class CustomFieldJoinsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index @custom_field_joins = current_nonprofit diff --git a/app/controllers/nonprofits/custom_field_masters_controller.rb b/app/controllers/nonprofits/custom_field_masters_controller.rb index f4e75a14..17fad57b 100644 --- a/app/controllers/nonprofits/custom_field_masters_controller.rb +++ b/app/controllers/nonprofits/custom_field_masters_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class CustomFieldMastersController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index @custom_field_masters = current_nonprofit diff --git a/app/controllers/nonprofits/donations_controller.rb b/app/controllers/nonprofits/donations_controller.rb index 4599788b..80cd72f0 100644 --- a/app/controllers/nonprofits/donations_controller.rb +++ b/app/controllers/nonprofits/donations_controller.rb @@ -3,8 +3,8 @@ module Nonprofits class DonationsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user!, only: [:index, :update] - before_filter :authenticate_campaign_editor!, only: [:create_offsite] + before_action :authenticate_nonprofit_user!, only: [:index, :update] + before_action :authenticate_campaign_editor!, only: [:create_offsite] # get /nonprofit/:nonprofit_id/donations def index diff --git a/app/controllers/nonprofits/email_lists_controller.rb b/app/controllers/nonprofits/email_lists_controller.rb index 1f3a5af0..25a0d8fb 100644 --- a/app/controllers/nonprofits/email_lists_controller.rb +++ b/app/controllers/nonprofits/email_lists_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class EmailListsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index render_json{ Qx.fetch(:email_lists, nonprofit_id: params[:nonprofit_id]) } diff --git a/app/controllers/nonprofits/imports_controller.rb b/app/controllers/nonprofits/imports_controller.rb index b942bfc0..9498680a 100644 --- a/app/controllers/nonprofits/imports_controller.rb +++ b/app/controllers/nonprofits/imports_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class ImportsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! # post /nonprofits/:nonprofit_id/imports def create render_json{ diff --git a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb index e0e7df41..639c4bc0 100644 --- a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb +++ b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb @@ -4,7 +4,7 @@ module Nonprofits include Controllers::NonprofitHelper helper_method :current_nonprofit_user? - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def show respond_to do |format| diff --git a/app/controllers/nonprofits/nonprofit_keys_controller.rb b/app/controllers/nonprofits/nonprofit_keys_controller.rb index efde5950..7a247fe5 100644 --- a/app/controllers/nonprofits/nonprofit_keys_controller.rb +++ b/app/controllers/nonprofits/nonprofit_keys_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class NonprofitKeysController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! # get /nonprofits/:nonprofit_id/nonprofit_keys # pass in the :select query param, which is the name of the column of the specific token you want diff --git a/app/controllers/nonprofits/payments_controller.rb b/app/controllers/nonprofits/payments_controller.rb index 62a96bc5..f54701cc 100644 --- a/app/controllers/nonprofits/payments_controller.rb +++ b/app/controllers/nonprofits/payments_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class PaymentsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! # get /nonprofit/:nonprofit_id/payments diff --git a/app/controllers/nonprofits/payouts_controller.rb b/app/controllers/nonprofits/payouts_controller.rb index 5b0e0b55..b9bbff0f 100644 --- a/app/controllers/nonprofits/payouts_controller.rb +++ b/app/controllers/nonprofits/payouts_controller.rb @@ -3,8 +3,8 @@ module Nonprofits class PayoutsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_admin!, only: :create - before_filter :authenticate_nonprofit_user!, only: [:index, :show] + before_action :authenticate_nonprofit_admin!, only: :create + before_action :authenticate_nonprofit_user!, only: [:index, :show] def create payout = InsertPayout.with_stripe(current_nonprofit.id, { diff --git a/app/controllers/nonprofits/recurring_donations_controller.rb b/app/controllers/nonprofits/recurring_donations_controller.rb index 9aa4260e..c35ea796 100644 --- a/app/controllers/nonprofits/recurring_donations_controller.rb +++ b/app/controllers/nonprofits/recurring_donations_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class RecurringDonationsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user!, except: [:create] + before_action :authenticate_nonprofit_user!, except: [:create] # get /nonprofits/:nonprofit_id/recurring_donations def index diff --git a/app/controllers/nonprofits/refunds_controller.rb b/app/controllers/nonprofits/refunds_controller.rb index aecd77a5..a06f1290 100644 --- a/app/controllers/nonprofits/refunds_controller.rb +++ b/app/controllers/nonprofits/refunds_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class RefundsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! # post /charges/:charge_id/refunds def create diff --git a/app/controllers/nonprofits/reports_controller.rb b/app/controllers/nonprofits/reports_controller.rb index fd7e0346..9dd6ca5c 100644 --- a/app/controllers/nonprofits/reports_controller.rb +++ b/app/controllers/nonprofits/reports_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class ReportsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def end_of_year respond_to do |format| diff --git a/app/controllers/nonprofits/supporter_emails_controller.rb b/app/controllers/nonprofits/supporter_emails_controller.rb index 724e53be..fcd39683 100644 --- a/app/controllers/nonprofits/supporter_emails_controller.rb +++ b/app/controllers/nonprofits/supporter_emails_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class SupporterEmailsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def create if params[:selecting_all] diff --git a/app/controllers/nonprofits/supporter_notes_controller.rb b/app/controllers/nonprofits/supporter_notes_controller.rb index 554e4827..3073033b 100644 --- a/app/controllers/nonprofits/supporter_notes_controller.rb +++ b/app/controllers/nonprofits/supporter_notes_controller.rb @@ -3,7 +3,7 @@ module Nonprofits class SupporterNotesController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user!, except: [:create] + before_action :authenticate_nonprofit_user!, except: [:create] # post /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes def create diff --git a/app/controllers/nonprofits/supporters_controller.rb b/app/controllers/nonprofits/supporters_controller.rb index 380564cc..a81fbe9a 100644 --- a/app/controllers/nonprofits/supporters_controller.rb +++ b/app/controllers/nonprofits/supporters_controller.rb @@ -3,8 +3,8 @@ module Nonprofits class SupportersController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user!, except: [:new, :create] - #before_filter(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} + before_action :authenticate_nonprofit_user!, except: [:new, :create] + #before_action(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} # get /nonprofit/:nonprofit_id/supporters def index diff --git a/app/controllers/nonprofits/tag_joins_controller.rb b/app/controllers/nonprofits/tag_joins_controller.rb index 2552120c..f499f65c 100644 --- a/app/controllers/nonprofits/tag_joins_controller.rb +++ b/app/controllers/nonprofits/tag_joins_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class TagJoinsController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index render_json do diff --git a/app/controllers/nonprofits/tag_masters_controller.rb b/app/controllers/nonprofits/tag_masters_controller.rb index cd0132da..6abc8a7a 100644 --- a/app/controllers/nonprofits/tag_masters_controller.rb +++ b/app/controllers/nonprofits/tag_masters_controller.rb @@ -2,7 +2,7 @@ module Nonprofits class TagMastersController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def index render json: {data: diff --git a/app/controllers/nonprofits_controller.rb b/app/controllers/nonprofits_controller.rb index d33e46a4..93893eb3 100755 --- a/app/controllers/nonprofits_controller.rb +++ b/app/controllers/nonprofits_controller.rb @@ -3,8 +3,8 @@ include Controllers::NonprofitHelper helper_method :current_nonprofit_user? - before_filter :authenticate_nonprofit_user!, only: [:dashboard, :dashboard_metrics, :dashboard_todos, :payment_history, :profile_todos, :recurring_donation_stats, :update, :verify_identity] - before_filter :authenticate_super_admin!, only: [:destroy] + before_action :authenticate_nonprofit_user!, only: [:dashboard, :dashboard_metrics, :dashboard_todos, :payment_history, :profile_todos, :recurring_donation_stats, :update, :verify_identity] + before_action :authenticate_super_admin!, only: [:destroy] # get /nonprofits/:id # get /:state_code/:city/:name diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index d219c4e2..f171f546 100755 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -3,7 +3,7 @@ class ProfilesController < ApplicationController helper_method :authenticate_profile_owner! - before_filter :authenticate_profile_owner!, only: [:update, :fundraisers, :donations_history] + before_action :authenticate_profile_owner!, only: [:update, :fundraisers, :donations_history] # get /profiles/:id # public profile diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 5dbe31ea..ff211e3b 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -2,7 +2,7 @@ class RolesController < ApplicationController include Controllers::NonprofitHelper - before_filter :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! def create role = Role.create_for_nonprofit(params[:role][:name].to_sym, params[:role][:email], FetchNonprofit.with_params(params)) diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index da64cf2b..a0e60553 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -3,7 +3,7 @@ class SettingsController < ApplicationController include Controllers::NonprofitHelper helper_method :current_nonprofit_user? - before_filter :authenticate_user! + before_action :authenticate_user! def index if current_role?(:super_admin) && params[:nonprofit_id] diff --git a/app/controllers/super_admins_controller.rb b/app/controllers/super_admins_controller.rb index 3d20b636..84ed07a5 100644 --- a/app/controllers/super_admins_controller.rb +++ b/app/controllers/super_admins_controller.rb @@ -2,7 +2,7 @@ class SuperAdminsController < ApplicationController layout "layouts/page" - before_filter :authenticate_super_associate! + before_action :authenticate_super_associate! def index end diff --git a/app/controllers/ticket_levels_controller.rb b/app/controllers/ticket_levels_controller.rb index e0082a0e..3e12ff56 100644 --- a/app/controllers/ticket_levels_controller.rb +++ b/app/controllers/ticket_levels_controller.rb @@ -2,7 +2,7 @@ class TicketLevelsController < ApplicationController include Controllers::EventHelper - before_filter :authenticate_event_editor!, :except => [:index, :show] + before_action :authenticate_event_editor!, :except => [:index, :show] def index ev_id = current_event.id diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 1a8b1569..407961b0 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -3,8 +3,8 @@ class TicketsController < ApplicationController include Controllers::EventHelper helper_method :current_event_admin?, :current_event_editor? - before_filter :authenticate_event_editor!, :except => [:create, :add_note] - before_filter :authenticate_nonprofit_user!, only: [:delete_card_for_ticket] + before_action :authenticate_event_editor!, :except => [:create, :add_note] + before_action :authenticate_nonprofit_user!, only: [:delete_card_for_ticket] # post /nonprofits/:nonprofit_id/events/:event_id/tickets def create From 35c2f5a640f25c07736d7effd092f39550716e5d Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 10:52:26 +0200 Subject: [PATCH 41/77] test(setup): update Devise controller helpers --- gems/grape_devise/spec/spec_helper.rb | 4 ++-- spec/rails_helper.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/grape_devise/spec/spec_helper.rb b/gems/grape_devise/spec/spec_helper.rb index dbd0a052..89343208 100644 --- a/gems/grape_devise/spec/spec_helper.rb +++ b/gems/grape_devise/spec/spec_helper.rb @@ -32,5 +32,5 @@ RSpec.configure do |config| config.include Capybara::DSL, type: :request config.include FactoryGirl::Syntax::Methods - config.include Devise::TestHelpers, :type => :controller -end \ No newline at end of file + config.include Devise::Test::ControllerHelpers, type: :controller +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 1f9a9a41..701227cb 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -59,6 +59,6 @@ RSpec.configure do |config| config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") - config.include Devise::TestHelpers, :type => :controller + config.include Devise::Test::ControllerHelpers, type: :controller config.include RSpec::Rails::RequestExampleGroup, type: :request, file_path: /spec\/api/ end From 11d72b97d508e741123f9780752b72b0eea3c2e8 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 10:52:53 +0200 Subject: [PATCH 42/77] fix(gemfile): add missing rack-ssl dependency --- Gemfile | 1 + Gemfile.lock | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Gemfile b/Gemfile index 0be6acd4..d996a91c 100755 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,7 @@ gem 'parallel' gem 'puma' gem 'bootsnap', require: false gem 'rack-timeout' +gem 'rack-ssl' gem 'puma_worker_killer' gem 'test-unit', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 7620cb74..f1fc81c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -326,6 +326,8 @@ GEM rack (>= 0.4) rack-attack (5.4.2) rack (>= 1.0, < 3) + rack-ssl (1.4.1) + rack rack-test (0.6.3) rack (>= 1.0) rack-timeout (0.5.1) @@ -532,6 +534,7 @@ DEPENDENCIES qx! rabl rack-attack + rack-ssl rack-timeout rails (= 5.0.7.1) rails-i18n From c3c1311e2f41b7f539a510ef88a1ceb420d2966b Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 10:53:47 +0200 Subject: [PATCH 43/77] test(shared_user_context): move to ActionDistpach From ActionController::TestResponse, to use the new IntegrationTest from rails 5. --- spec/controllers/support/shared_user_context.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/support/shared_user_context.rb b/spec/controllers/support/shared_user_context.rb index 7517f4a1..d36579c1 100644 --- a/spec/controllers/support/shared_user_context.rb +++ b/spec/controllers/support/shared_user_context.rb @@ -93,7 +93,7 @@ RSpec.shared_context :shared_user_context do sign_in user_to_signin if user_to_signin # allows us to run the helpers but ignore what the controller action does # - expect_any_instance_of(described_class).to receive(action).and_return(ActionController::TestResponse.new(200)) + expect_any_instance_of(described_class).to receive(action).and_return(ActionDispatch::IntegrationTest.new(200)) expect_any_instance_of(described_class).to receive(:render).and_return(nil) send(method, action, *args) expect(response.status).to eq 200 @@ -596,4 +596,4 @@ RSpec.shared_context :open_to_profile_owner do |method, action, *args| it 'accepts profile user' do accept(user_with_profile, method, action, *fixed_args) end -end \ No newline at end of file +end From 57125774efd3b18079f461ab7b0a3fe731f4069d Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 11:18:45 +0200 Subject: [PATCH 44/77] test(params): fix HttpPositionalArguments Automatic run with `bundle exec rubocop --rails --only HttpPositionalArguments --auto-correct` --- spec/controllers/campaigns_spec.rb | 4 ++-- spec/requests/maintenance_spec.rb | 8 ++++---- spec/requests/nonprofits/direct_debit_details_spec.rb | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/controllers/campaigns_spec.rb b/spec/controllers/campaigns_spec.rb index 0841b4b6..4673e8b0 100644 --- a/spec/controllers/campaigns_spec.rb +++ b/spec/controllers/campaigns_spec.rb @@ -60,7 +60,7 @@ describe CampaignsController, :type => :controller do describe 'routes' do it "routes campaigns#index" do - expect(:get => "/nonprofits/5/campaigns/4").to(route_to(:controller => "campaigns", :action => "show", nonprofit_id: "5", id: "4")) + expect(get: "/nonprofits/5/campaigns/4").to(route_to(controller: "campaigns", action: "show", nonprofit_id: "5", id: "4")) end end -end \ No newline at end of file +end diff --git a/spec/requests/maintenance_spec.rb b/spec/requests/maintenance_spec.rb index 0a79ef56..fa563ea9 100644 --- a/spec/requests/maintenance_spec.rb +++ b/spec/requests/maintenance_spec.rb @@ -60,7 +60,7 @@ describe 'Maintenance Mode' do end it 'redirects sign_in if the token is wrong' do - get(:new, {maintenance_token: "#{token}3"}) + get(:new, params: { maintenance_token: "#{token}3" }) expect(response.code).to eq "302" expect(response.location).to eq page end @@ -73,18 +73,18 @@ describe 'Maintenance Mode' do it 'redirects sign_in if the token is passed in wrong param' do - get(:new, {maintnancerwrwer_token: "#{token}"}) + get(:new, params: { maintnancerwrwer_token: "#{token}" }) expect(response.code).to eq "302" expect(response.location).to eq page end it 'allows sign_in if the token is passed' do - get(:new, {maintenance_token: "#{token}"}) + get(:new, params: { maintenance_token: "#{token}" }) expect(response.code).to eq '200' end it 'allows sign_in.json' do - get(:new, {maintenance_token: "#{token}", format: 'json'}) + get(:new, params: { maintenance_token: "#{token}", format: 'json' }) expect(response.code).to eq '200' end end diff --git a/spec/requests/nonprofits/direct_debit_details_spec.rb b/spec/requests/nonprofits/direct_debit_details_spec.rb index 4114ad37..35e13b46 100644 --- a/spec/requests/nonprofits/direct_debit_details_spec.rb +++ b/spec/requests/nonprofits/direct_debit_details_spec.rb @@ -18,21 +18,21 @@ describe DirectDebitDetailsController, type: :request do describe 'requires params' do it 'is valid when sepa_params, donation_id and supporter_id are present' do - post "/sepa", valid_params + post "/sepa", params: valid_params assert_response 200 assert_equal nil, JSON.parse(@response.body)["errors"] end it 'is not valid without sepa_params' do - post "/sepa", valid_params.except(:sepa_params) + post "/sepa", params: valid_params.except(:sepa_params) assert_response 422 assert_equal ["sepa_params required"], JSON.parse(@response.body)["errors"] end it 'is not valid without supporter_id' do - post "/sepa", valid_params.except(:supporter_id) + post "/sepa", params: valid_params.except(:supporter_id) assert_response 422 assert_equal ["supporter_id required"], JSON.parse(@response.body)["errors"] From fb638f0c26d9ff5947cbab2ee9e7d239f557dea8 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 13 Jul 2019 11:19:53 +0200 Subject: [PATCH 45/77] test(shared_user_context): fix positional args warning Using positional arguments in functional tests has been deprecated --- spec/controllers/support/shared_user_context.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/controllers/support/shared_user_context.rb b/spec/controllers/support/shared_user_context.rb index d36579c1..c94e0deb 100644 --- a/spec/controllers/support/shared_user_context.rb +++ b/spec/controllers/support/shared_user_context.rb @@ -95,18 +95,22 @@ RSpec.shared_context :shared_user_context do # expect_any_instance_of(described_class).to receive(action).and_return(ActionDispatch::IntegrationTest.new(200)) expect_any_instance_of(described_class).to receive(:render).and_return(nil) - send(method, action, *args) + send(method, action, reduce_params(*args)) expect(response.status).to eq 200 end def reject(user_to_signin, method, action, *args) sign_in user_to_signin if user_to_signin - send(method, action, *args) + send(method, action, reduce_params(*args)) expect(response.status).to eq 302 end alias_method :redirects_to, :reject + def reduce_params(*args) + { params: args.reduce({}, :merge) } + end + def fix_args( *args) replacements = { __our_np: nonprofit.id, From d4f6e2d91d4fc60a5bd6d326bdac095793fb832d Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:06:03 +0200 Subject: [PATCH 46/77] test(donation_context): fix any_instance deprecation warning Changed from the old syntax to the new allow_any_instance_of according to the documentation. https://www.rubydoc.info/github/rspec/rspec-mocks/RSpec/Mocks/ExampleMethods%3aallow_any_instance_of --- spec/support/contexts/shared_rd_donation_value_context.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/support/contexts/shared_rd_donation_value_context.rb b/spec/support/contexts/shared_rd_donation_value_context.rb index 6a95a85c..8a30d2c5 100644 --- a/spec/support/contexts/shared_rd_donation_value_context.rb +++ b/spec/support/contexts/shared_rd_donation_value_context.rb @@ -19,7 +19,7 @@ RSpec.shared_context :shared_rd_donation_value_context do let(:default_edit_token) {'7903e34c-10fe-11e8-9ead-d302c690bee4'} before(:each){ - Event.any_instance.stub(:geocode).and_return([1,1]) + allow_any_instance_of(Event).to_receive(:geocode).and_return([1,1]) } @@ -495,4 +495,4 @@ RSpec.shared_context :shared_rd_donation_value_context do def nil_or_true(item) item.nil? || item end -end \ No newline at end of file +end From e08d7836c663bc9ca995ccb71b6ed697cd1fce35 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:07:15 +0200 Subject: [PATCH 47/77] test(nonprofit): fix xhr deprecation warnings `xhr` and `xml_http_request` are deprecated, changed to new syntax --- spec/api/houdini/nonprofit_spec.rb | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/spec/api/houdini/nonprofit_spec.rb b/spec/api/houdini/nonprofit_spec.rb index 75ab3a7d..396cf775 100644 --- a/spec/api/houdini/nonprofit_spec.rb +++ b/spec/api/houdini/nonprofit_spec.rb @@ -52,15 +52,16 @@ describe Houdini::V1::Nonprofit, :type => :request do e.run Rails.configuration.action_controller.allow_forgery_protection = false } - it 'rejects csrf' do - xhr :post, '/api/v1/nonprofit' + it 'rejects csrf' do + post '/api/v1/nonprofit', params: {}, xhr: true expect(response.code).to eq "401" end end + it 'validates nothing' do input = {} - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "400" expect_validation_errors(JSON.parse(response.body), create_errors("nonprofit", "user")) end @@ -72,7 +73,7 @@ describe Houdini::V1::Nonprofit, :type => :request do phone: "notphone", url: "" }} - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "400" expected = create_errors("user") expected[:errors].push(h(params:["nonprofit[email]"], messages: gr_e("regexp"))) @@ -92,7 +93,7 @@ describe Houdini::V1::Nonprofit, :type => :request do password_confirmation: 'doesn\'t match' } } - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "400" expect(JSON.parse(response.body)['errors']).to include(h(params:["user[password]", "user[password_confirmation]"], messages: gr_e("is_equal_to"))) @@ -107,7 +108,7 @@ describe Houdini::V1::Nonprofit, :type => :request do expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new) - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "400" expect_validation_errors(JSON.parse(response.body), { @@ -128,7 +129,7 @@ describe Houdini::V1::Nonprofit, :type => :request do user: {name: "Name", email: "em@em.com", password: "12345678", password_confirmation: "12345678"} } - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "400" expect_validation_errors(JSON.parse(response.body), { @@ -155,7 +156,7 @@ describe Houdini::V1::Nonprofit, :type => :request do #expect(Houdini::V1::Nonprofit).to receive(:sign_in) - xhr :post, '/api/v1/nonprofit', input + post '/api/v1/nonprofit', params: input, xhr: true expect(response.code).to eq "201" our_np = Nonprofit.all[1] @@ -211,4 +212,4 @@ end def gr_e(*keys) keys.map {|i| I18n.translate("grape.errors.messages." + i, locale: 'en')} -end \ No newline at end of file +end From 812d54608030aa539c74f59531b984d3c2bd996d Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:48:23 +0200 Subject: [PATCH 48/77] fix(app): fixnum is deprecated Use Integer, since Fixnum and Bigint now belong to the same class in Ruby 2.4+ --- gems/ruby-qx/lib/qx.rb | 2 +- lib/qexpr.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/ruby-qx/lib/qx.rb b/gems/ruby-qx/lib/qx.rb index 1db46b59..5434c1e8 100644 --- a/gems/ruby-qx/lib/qx.rb +++ b/gems/ruby-qx/lib/qx.rb @@ -455,7 +455,7 @@ class Qx # Quote a string for use in sql to prevent injection or weird errors # Always use this for all values! # Just uses double-dollar quoting universally. Should be generally safe and easy. - # Will return an unquoted value it it's a Fixnum + # Will return an unquoted value it it's a Integer def self.quote(val) if val.is_a?(Qx) val.parse diff --git a/lib/qexpr.rb b/lib/qexpr.rb index f66b14ee..e0948527 100644 --- a/lib/qexpr.rb +++ b/lib/qexpr.rb @@ -207,9 +207,9 @@ class Qexpr # Quote a string for use in sql to prevent injection or weird errors # Always use this for all values! # Just uses double-dollar quoting universally. Should be generally safe and easy. - # Will return an unquoted value it it's a Fixnum + # Will return an unquoted value it it's a Integer def self.quote(val) - if val.is_a?(Fixnum) || (val.is_a?(String) && val =~ /^\$Q\$.+\$Q\$$/) # is a valid num or already quoted + if val.is_a?(Integer) || (val.is_a?(String) && val =~ /^\$Q\$.+\$Q\$$/) # is a valid num or already quoted val elsif val == nil "NULL" From 4992253540b0f729f05f6b23c1295e437c37141a Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:49:01 +0200 Subject: [PATCH 49/77] fix(constants): explicit require for constants --- app/models/recurring_donation.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index 55e585fd..c6002b96 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -1,4 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later +require_dependency 'lib/timespan' + class RecurringDonation < ApplicationRecord #TODO: From 22bf0713f90b73c8aa73b4922ace0f1598991cef Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:49:40 +0200 Subject: [PATCH 50/77] fix(campaign): add explicit source for payments relation --- app/models/campaign.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 5aaa9162..137381c1 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -57,7 +57,7 @@ class Campaign < ApplicationRecord has_many :donations has_many :charges, through: :donations - has_many :payments, through: :donations + has_many :payments, { through: :donations, source: "payment" } has_many :campaign_gift_options has_many :campaign_gifts, through: :campaign_gift_options has_many :supporters, :through => :donations From a20bd477ce2d8addd9bee8aaa17f5d1a9b00ca5c Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 10:50:27 +0200 Subject: [PATCH 51/77] fix(static_controller): return body nil when 500 Fix deprecation warning from nothing. --- app/controllers/static_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index e0587fb0..6598e0f2 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -14,7 +14,7 @@ class StaticController < ApplicationController if result send_file(temp_file, :type => "application/gzip") else - render :nothing => true, :status => 500 + render body: nil, status: 500 end elsif (ccs_method == 'github') git_hash = File.read("#{Rails.root}/CCS_HASH") From 33862bab25650de2074720b01dbb86423a0b64d9 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 11:25:00 +0200 Subject: [PATCH 52/77] test(support): fix any_instance deprecation warning Changed from the old syntax to the new allow_any_instance_of according to the documentation. https://www.rubydoc.info/github/rspec/rspec-mocks/RSpec/Mocks/ExampleMethods%3aallow_any_instance_of --- spec/lib/update/update_tickets_spec.rb | 2 +- spec/support/contexts/shared_donation_charge_context.rb | 6 +++--- spec/support/contexts/shared_rd_donation_value_context.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/lib/update/update_tickets_spec.rb b/spec/lib/update/update_tickets_spec.rb index 7c8df4e1..da844a6e 100644 --- a/spec/lib/update/update_tickets_spec.rb +++ b/spec/lib/update/update_tickets_spec.rb @@ -5,7 +5,7 @@ describe UpdateTickets do let(:ticket) { - Event.any_instance.stub(:geocode).and_return([1,1]) + allow_any_instance_of(Event).to receive(:geocode).and_return([1,1]) create(:ticket, :has_card, :has_event) } diff --git a/spec/support/contexts/shared_donation_charge_context.rb b/spec/support/contexts/shared_donation_charge_context.rb index 2e0d2a63..1e2d1037 100644 --- a/spec/support/contexts/shared_donation_charge_context.rb +++ b/spec/support/contexts/shared_donation_charge_context.rb @@ -17,11 +17,11 @@ RSpec.shared_context :shared_donation_charge_context do let(:campaign) {force_create(:campaign, nonprofit: nonprofit, goal_amount: 500)} let(:other_campaign) {force_create(:campaign, nonprofit: other_nonprofit)} let(:event) { - Event.any_instance.stub(:geocode).and_return([1,1]) + allow_any_instance_of(Event).to receive(:geocode).and_return([1,1]) force_create(:event, nonprofit: nonprofit) } let(:other_event) { - Event.any_instance.stub(:geocode).and_return([1,1]) + allow_any_instance_of(Event).to receive(:geocode).and_return([1,1]) force_create(:event, nonprofit: other_nonprofit) } let(:event_discount) {force_create(:event_discount, event: event, percent: 20)} @@ -46,4 +46,4 @@ RSpec.shared_context :shared_donation_charge_context do StripeMock.stop end } -end \ No newline at end of file +end diff --git a/spec/support/contexts/shared_rd_donation_value_context.rb b/spec/support/contexts/shared_rd_donation_value_context.rb index 8a30d2c5..a8889e82 100644 --- a/spec/support/contexts/shared_rd_donation_value_context.rb +++ b/spec/support/contexts/shared_rd_donation_value_context.rb @@ -19,7 +19,7 @@ RSpec.shared_context :shared_rd_donation_value_context do let(:default_edit_token) {'7903e34c-10fe-11e8-9ead-d302c690bee4'} before(:each){ - allow_any_instance_of(Event).to_receive(:geocode).and_return([1,1]) + allow_any_instance_of(Event).to receive(:geocode).and_return([1,1]) } From d153de8d1f5b99d1bb2c5195bf19a2b86f69a6f3 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sun, 14 Jul 2019 11:29:19 +0200 Subject: [PATCH 53/77] fix(dependency): Remove require dependency for timespan constants --- app/models/recurring_donation.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index c6002b96..8833b076 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -1,5 +1,4 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require_dependency 'lib/timespan' class RecurringDonation < ApplicationRecord From eb7c11d849bae3b787ad2c3245852ff61678ed08 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 20 Jul 2019 15:07:19 +0200 Subject: [PATCH 54/77] chore(gems): update rails and ruby version to latest --- Gemfile | 4 +- Gemfile.lock | 112 ++++++++++-------- config/initializers/new_framework_defaults.rb | 25 ---- 3 files changed, 62 insertions(+), 79 deletions(-) delete mode 100644 config/initializers/new_framework_defaults.rb diff --git a/Gemfile b/Gemfile index d996a91c..76758641 100755 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,8 @@ source 'https://rubygems.org' -ruby '2.4.5' +ruby '2.5.1' gem 'rake' -gem 'rails', '= 5.0.7.1' +gem 'rails', '= 5.2.3' # https://stripe.com/docs/api gem 'stripe' diff --git a/Gemfile.lock b/Gemfile.lock index f1fc81c7..702689c3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -33,39 +33,43 @@ GEM remote: https://rubygems.org/ specs: action_mailer_matchers (1.0.0) - actioncable (5.0.7.1) - actionpack (= 5.0.7.1) - nio4r (>= 1.2, < 3.0) - websocket-driver (~> 0.6.1) - actionmailer (5.0.7.1) - actionpack (= 5.0.7.1) - actionview (= 5.0.7.1) - activejob (= 5.0.7.1) + actioncable (5.2.3) + actionpack (= 5.2.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.0.7.1) - actionview (= 5.0.7.1) - activesupport (= 5.0.7.1) + actionpack (5.2.3) + actionview (= 5.2.3) + activesupport (= 5.2.3) rack (~> 2.0) - rack-test (~> 0.6.3) + rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.7.1) - activesupport (= 5.0.7.1) + actionview (5.2.3) + activesupport (= 5.2.3) builder (~> 3.1) - erubis (~> 2.7.0) + erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.0.7.1) - activesupport (= 5.0.7.1) + activejob (5.2.3) + activesupport (= 5.2.3) globalid (>= 0.3.6) - activemodel (5.0.7.1) - activesupport (= 5.0.7.1) - activerecord (5.0.7.1) - activemodel (= 5.0.7.1) - activesupport (= 5.0.7.1) - arel (~> 7.0) - activesupport (5.0.7.1) + activemodel (5.2.3) + activesupport (= 5.2.3) + activerecord (5.2.3) + activemodel (= 5.2.3) + activesupport (= 5.2.3) + arel (>= 9.0) + activestorage (5.2.3) + actionpack (= 5.2.3) + activerecord (= 5.2.3) + marcel (~> 0.3.1) + activesupport (5.2.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -74,7 +78,7 @@ GEM public_suffix (>= 2.0.2, < 4.0) amq-protocol (2.3.0) andand (1.3.3) - arel (7.1.4) + arel (9.0.0) ast (2.4.0) aws-eventstream (1.0.1) aws-partitions (1.110.0) @@ -126,7 +130,7 @@ GEM coercible (1.0.0) descendants_tracker (~> 0.0.1) colorize (0.8.1) - concurrent-ruby (1.1.4) + concurrent-ruby (1.1.5) config (1.7.0) activesupport (>= 3.0) deep_merge (~> 1.2.1) @@ -201,7 +205,7 @@ GEM dry-logic (~> 0.4, >= 0.4.0) dry-types (~> 0.13.1) equalizer (0.0.11) - erubis (2.7.0) + erubi (1.8.0) execjs (2.7.0) factory_bot (4.11.1) activesupport (>= 3.0.0) @@ -255,7 +259,7 @@ GEM domain_name (~> 0.5) httparty (0.16.2) multi_xml (>= 0.5.2) - i18n (1.5.3) + i18n (1.6.0) concurrent-ruby (~> 1.0) i18n-js (3.1.0) i18n (>= 0.6.6, < 2) @@ -278,13 +282,16 @@ GEM mini_mime (>= 0.1.1) mail_view (2.0.4) tilt + marcel (0.3.3) + mimemagic (~> 0.3.2) memcachier (0.0.2) method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) + mimemagic (0.3.3) mini_magick (4.9.2) - mini_mime (1.0.1) + mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.11.3) money (6.13.1) @@ -301,8 +308,8 @@ GEM kdtree require_all netrc (0.11.0) - nio4r (2.3.1) - nokogiri (1.10.1) + nio4r (2.4.0) + nokogiri (1.10.3) mini_portile2 (~> 2.4.0) orm_adapter (0.5.0) parallel (1.13.0) @@ -321,27 +328,28 @@ GEM puma (>= 2.7, < 4) rabl (0.14.0) activesupport (>= 2.3.14) - rack (2.0.6) + rack (2.0.7) rack-accept (0.4.5) rack (>= 0.4) rack-attack (5.4.2) rack (>= 1.0, < 3) rack-ssl (1.4.1) rack - rack-test (0.6.3) - rack (>= 1.0) + rack-test (1.1.0) + rack (>= 1.0, < 3) rack-timeout (0.5.1) - rails (5.0.7.1) - actioncable (= 5.0.7.1) - actionmailer (= 5.0.7.1) - actionpack (= 5.0.7.1) - actionview (= 5.0.7.1) - activejob (= 5.0.7.1) - activemodel (= 5.0.7.1) - activerecord (= 5.0.7.1) - activesupport (= 5.0.7.1) + rails (5.2.3) + actioncable (= 5.2.3) + actionmailer (= 5.2.3) + actionpack (= 5.2.3) + actionview (= 5.2.3) + activejob (= 5.2.3) + activemodel (= 5.2.3) + activerecord (= 5.2.3) + activestorage (= 5.2.3) + activesupport (= 5.2.3) bundler (>= 1.3.0) - railties (= 5.0.7.1) + railties (= 5.2.3) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) @@ -351,12 +359,12 @@ GEM rails-i18n (5.1.3) i18n (>= 0.7, < 2) railties (>= 5.0, < 6) - railties (5.0.7.1) - actionpack (= 5.0.7.1) - activesupport (= 5.0.7.1) + railties (5.2.3) + actionpack (= 5.2.3) + activesupport (= 5.2.3) method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (12.3.2) request_store (1.4.1) @@ -473,9 +481,9 @@ GEM addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff - websocket-driver (0.6.5) + websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) + websocket-extensions (0.1.4) xml-simple (1.1.5) yard (0.9.18) @@ -536,7 +544,7 @@ DEPENDENCIES rack-attack rack-ssl rack-timeout - rails (= 5.0.7.1) + rails (= 5.2.3) rails-i18n rake roadie-rails @@ -559,7 +567,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 2.4.5p335 + ruby 2.5.1p57 BUNDLED WITH 1.17.3 diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb deleted file mode 100644 index cbf423a8..00000000 --- a/config/initializers/new_framework_defaults.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file contains migration options to ease your Rails 5.0 upgrade. -# -# Once upgraded flip defaults one by one to migrate to the new default. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. - -Rails.application.config.action_controller.raise_on_unfiltered_parameters = true - -# Enable per-form CSRF tokens. Previous versions had false. -Rails.application.config.action_controller.per_form_csrf_tokens = false - -# Enable origin-checking CSRF mitigation. Previous versions had false. -Rails.application.config.action_controller.forgery_protection_origin_check = false - -# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. -# Previous versions had false. -ActiveSupport.to_time_preserves_timezone = false - -# Require `belongs_to` associations by default. Previous versions had false. -Rails.application.config.active_record.belongs_to_required_by_default = false - -# Do not halt callback chains when a callback returns false. Previous versions had true. -ActiveSupport.halt_callback_chains_on_return_false = true From 9f6ea912240706097825e665d3d3adb66b4a7fc0 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 20 Jul 2019 15:10:32 +0200 Subject: [PATCH 55/77] fix(direct_debit_detail): use class_name string value --- app/models/direct_debit_detail.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/direct_debit_detail.rb b/app/models/direct_debit_detail.rb index d4dbfdcb..85b83947 100644 --- a/app/models/direct_debit_detail.rb +++ b/app/models/direct_debit_detail.rb @@ -4,5 +4,5 @@ class DirectDebitDetail < ApplicationRecord has_many :donations has_many :charges - belongs_to :holder, class_name: Supporter + belongs_to :holder, class_name: Supporter.class_name end From 84f8a583ba8b21397f4da56833f36cf63fdebe8a Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Tue, 23 Jul 2019 21:20:54 +0200 Subject: [PATCH 56/77] test(shared_user_ctx): add conditional specs for types of methods --- app/controllers/nonprofits_controller.rb | 2 +- .../support/shared_user_context.rb | 22 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/controllers/nonprofits_controller.rb b/app/controllers/nonprofits_controller.rb index 93893eb3..55aa04ab 100755 --- a/app/controllers/nonprofits_controller.rb +++ b/app/controllers/nonprofits_controller.rb @@ -30,7 +30,7 @@ respond_to do |format| format.html - format.json {render json: @nonprofit} + format.json {@nonprofit} end end diff --git a/spec/controllers/support/shared_user_context.rb b/spec/controllers/support/shared_user_context.rb index c94e0deb..3abe31f6 100644 --- a/spec/controllers/support/shared_user_context.rb +++ b/spec/controllers/support/shared_user_context.rb @@ -90,13 +90,21 @@ RSpec.shared_context :shared_user_context do end def accept(user_to_signin, method, action, *args) + without_json_response = [:cancellation, :all_npos].include?(action) + request.accept = "application/json" unless without_json_response sign_in user_to_signin if user_to_signin # allows us to run the helpers but ignore what the controller action does - # - expect_any_instance_of(described_class).to receive(action).and_return(ActionDispatch::IntegrationTest.new(200)) - expect_any_instance_of(described_class).to receive(:render).and_return(nil) - send(method, action, reduce_params(*args)) - expect(response.status).to eq 200 + + if without_json_response + expect_any_instance_of(described_class).to receive(action).and_return(ActionDispatch::IntegrationTest.new(200)) + expect_any_instance_of(described_class).to receive(:render).and_return(nil) + send(method, action, reduce_params(*args)) + expect(response.status).to eq 200 + else + expect_any_instance_of(described_class).to receive(action).and_return(ActionDispatch::IntegrationTest.new(204)) + send(method, action, reduce_params(*args)) + expect(response.status).to eq 204 + end end def reject(user_to_signin, method, action, *args) @@ -111,7 +119,7 @@ RSpec.shared_context :shared_user_context do { params: args.reduce({}, :merge) } end - def fix_args( *args) + def fix_args(*args) replacements = { __our_np: nonprofit.id, __our_campaign: campaign.id, @@ -198,7 +206,7 @@ end RSpec.shared_context :open_to_np_associate do |method, action, *args| include_context :shared_user_context let(:fixed_args){ - fix_args( *args) + fix_args(*args) } it 'rejects no user' do From df29d446aeb8e4804d91992cb0efb86e1fc635cc Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Tue, 23 Jul 2019 21:22:00 +0200 Subject: [PATCH 57/77] chore(models): comment out attr_accessible Needs to be changed to strong params in controllers of each model. --- app/models/coupon.rb | 12 ++++++------ app/models/custom_field_master.rb | 10 +++++----- app/models/direct_debit_detail.rb | 2 +- app/models/email_list.rb | 2 +- app/models/export.rb | 2 +- app/models/offsite_payment.rb | 2 +- app/models/payment_import.rb | 2 +- app/models/source_token.rb | 2 +- app/models/ticket.rb | 2 +- app/models/tracking.rb | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/models/coupon.rb b/app/models/coupon.rb index 08d93729..5b8b5f7c 100644 --- a/app/models/coupon.rb +++ b/app/models/coupon.rb @@ -1,12 +1,12 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Coupon < ApplicationRecord - attr_accessible \ - :name, - :victim_np_id, - :paid, # boolean - :nonprofit, :nonprofit_id + # attr_accessible \ + # :name, + # :victim_np_id, + # :paid, # boolean + # :nonprofit, :nonprofit_id scope :unpaid, -> {where(paid: [nil,false])} validates_presence_of :name, :nonprofit_id, :victim_np_id -end \ No newline at end of file +end diff --git a/app/models/custom_field_master.rb b/app/models/custom_field_master.rb index 56f4398a..b528b373 100644 --- a/app/models/custom_field_master.rb +++ b/app/models/custom_field_master.rb @@ -1,11 +1,11 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CustomFieldMaster < ApplicationRecord - attr_accessible \ - :nonprofit, :nonprofit_id, - :name, - :deleted, - :created_at + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :created_at validates :name, presence: true validate :no_dupes, on: :create diff --git a/app/models/direct_debit_detail.rb b/app/models/direct_debit_detail.rb index 85b83947..a8e96676 100644 --- a/app/models/direct_debit_detail.rb +++ b/app/models/direct_debit_detail.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class DirectDebitDetail < ApplicationRecord - attr_accessible :iban, :account_holder_name, :bic, :supporter_id, :holder + # attr_accessible :iban, :account_holder_name, :bic, :supporter_id, :holder has_many :donations has_many :charges diff --git a/app/models/email_list.rb b/app/models/email_list.rb index 4f8fccf1..f60af7d0 100644 --- a/app/models/email_list.rb +++ b/app/models/email_list.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailList < ApplicationRecord - attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master + # attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master belongs_to :nonprofit belongs_to :tag_master end diff --git a/app/models/export.rb b/app/models/export.rb index ee4717a4..83f066c2 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -2,7 +2,7 @@ class Export < ApplicationRecord STATUS = %w[queued started completed failed].freeze - attr_accessible :exception, :nonprofit, :status, :user, :export_type, :parameters, :ended, :url, :user_id, :nonprofit_id + # attr_accessible :exception, :nonprofit, :status, :user, :export_type, :parameters, :ended, :url, :user_id, :nonprofit_id belongs_to :nonprofit belongs_to :user diff --git a/app/models/offsite_payment.rb b/app/models/offsite_payment.rb index 9a729ed2..798ef1c9 100644 --- a/app/models/offsite_payment.rb +++ b/app/models/offsite_payment.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class OffsitePayment < ApplicationRecord - attr_accessible :gross_amount, :kind, :date, :check_number + # attr_accessible :gross_amount, :kind, :date, :check_number belongs_to :payment, dependent: :destroy belongs_to :donation belongs_to :nonprofit diff --git a/app/models/payment_import.rb b/app/models/payment_import.rb index fea614a5..5980928f 100644 --- a/app/models/payment_import.rb +++ b/app/models/payment_import.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class PaymentImport < ApplicationRecord - attr_accessible :nonprofit, :user + # attr_accessible :nonprofit, :user has_and_belongs_to_many :donations belongs_to :nonprofit belongs_to :user diff --git a/app/models/source_token.rb b/app/models/source_token.rb index 1d6ca55f..159d682f 100644 --- a/app/models/source_token.rb +++ b/app/models/source_token.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SourceToken < ApplicationRecord self.primary_key = :token - attr_accessible :expiration, :token, :max_uses, :total_uses + # attr_accessible :expiration, :token, :max_uses, :total_uses belongs_to :tokenizable, :polymorphic => true belongs_to :event end diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 9e56fd2b..ee5ad133 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -1,7 +1,7 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Ticket < ApplicationRecord - attr_accessible :note, :event_discount, :event_discount_id + # attr_accessible :note, :event_discount, :event_discount_id belongs_to :event_discount belongs_to :supporter diff --git a/app/models/tracking.rb b/app/models/tracking.rb index a730989f..0903b3e3 100644 --- a/app/models/tracking.rb +++ b/app/models/tracking.rb @@ -1,6 +1,6 @@ # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Tracking < ApplicationRecord - attr_accessible :utm_campaign, :utm_content, :utm_medium, :utm_source + # attr_accessible :utm_campaign, :utm_content, :utm_medium, :utm_source belongs_to :donation end From 28a0793377e9a70dcbff2e44f24147f6da6839bd Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Tue, 23 Jul 2019 21:23:14 +0200 Subject: [PATCH 58/77] feat(campaigns): return expected api response --- lib/create/create_peer_to_peer_campaign.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/create/create_peer_to_peer_campaign.rb b/lib/create/create_peer_to_peer_campaign.rb index 854ca4db..032de0ab 100644 --- a/lib/create/create_peer_to_peer_campaign.rb +++ b/lib/create/create_peer_to_peer_campaign.rb @@ -28,6 +28,6 @@ module CreatePeerToPeerCampaign return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty? - campaign.as_json + campaign.as_json['campaign'] end end From cf5792d4e5888fc6cdb8f8f6290907dad85f5353 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 27 Jul 2019 14:39:40 +0200 Subject: [PATCH 59/77] feat(gems): update Gemfile --- Gemfile | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 76758641..0a5dda0f 100755 --- a/Gemfile +++ b/Gemfile @@ -37,8 +37,10 @@ gem 'sprockets' gem 'font_assets', '~> 0.1.14' # Database (postgres) -gem 'pg' # Postgresql + +gem 'pg', '~> 0.11' gem 'qx', path: 'gems/ruby-qx' + gem 'dalli' gem 'memcachier' @@ -72,9 +74,6 @@ gem 'httparty' gem 'devise', '~> 4.4' gem 'devise-async' -# https://github.com/airbrake/airbrake -gem 'airbrake', '~> 8.0.1' - # http://www.rubygeocoder.com/ gem 'geocoder' # for adding latitude and longitude to location-based tables @@ -142,9 +141,4 @@ gem 'grape-swagger' gem 'grape-swagger-entity' gem 'grape_url_validator' gem 'grape_logging' -gem 'grape_devise' -#gem 'grape_devise', git: 'https://github.com/ericschultz/grape_devise.git' - -#gem 'protected_attributes' - -gem 'rack-ssl' +gem 'grape_devise', path: 'gems/grape_devise' From 1c28460ad7d2da2d2c9a200733960148ebf6f7f7 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Sat, 27 Jul 2019 14:40:08 +0200 Subject: [PATCH 60/77] feat(api): use active support reloader instead of callback --- config/initializers/reload_api.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/initializers/reload_api.rb b/config/initializers/reload_api.rb index 2de95e95..41e476bc 100644 --- a/config/initializers/reload_api.rb +++ b/config/initializers/reload_api.rb @@ -5,7 +5,7 @@ if Rails.env.development? api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do Rails.application.reload_routes! end - ActionDispatch::Callbacks.to_prepare do + ActiveSupport::Reloader.to_prepare do api_reloader.execute_if_updated end -end \ No newline at end of file +end From 7c1f78e7d67f550617dd2a2881c1936026b99197 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Mon, 29 Jul 2019 20:11:14 +0200 Subject: [PATCH 61/77] docs(getting_started): add newest version of ruby --- .ruby-version | 2 +- docs/GETTING_STARTED.MD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index 59aa62c1..73462a5a 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.4.5 +2.5.1 diff --git a/docs/GETTING_STARTED.MD b/docs/GETTING_STARTED.MD index a5c822e1..370eb8e4 100644 --- a/docs/GETTING_STARTED.MD +++ b/docs/GETTING_STARTED.MD @@ -6,7 +6,7 @@ You'll need to have in your Mac the following dependencies installed, if you don't want to use the provided Docker containers. -* Ruby `2.4.5` +* Ruby `2.5.1` * Rails `5.0.7.1` * Node `11.12.0` From da68bca689000980649c00e400497a7bb9bc2e5f Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Mon, 29 Jul 2019 20:40:30 +0200 Subject: [PATCH 62/77] docs(getting_started): add known bug for Qx gem at rake db setup --- docs/GETTING_STARTED.MD | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/GETTING_STARTED.MD b/docs/GETTING_STARTED.MD index 370eb8e4..33a26757 100644 --- a/docs/GETTING_STARTED.MD +++ b/docs/GETTING_STARTED.MD @@ -44,6 +44,16 @@ The last secrets you'll need are related to AWS. You can learn how to [create an Run `rake db:setup` to run all the db tasks within one command. This will create the dbs for each environment, load the `structure.sql`, run pending migrations and will also run the seed functionality. +------- + +**Known problems** +If you encounter `database doesnt exist in rake db create` after running both `rake db:setup` and `rake db:create`, you'll need to comment out the lines these lines at `pg_type_map.rb` +``` +Qx.config(type_map: PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection)) +Qx.execute("SET TIME ZONE utc") +``` + + ### How to run You'll need 2 consoles to run the project. One for the rails env and another one to run the asset pipeline through [webpack](https://webpack.js.org) , since it's *not incorporated yet* into the rails asset pipeline. From 04a5eb039fd2b41e65912c11466e9ed146523103 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Mon, 29 Jul 2019 20:44:35 +0200 Subject: [PATCH 63/77] feat(pg_type_map): add validation for Qx to run if database exists --- config/initializers/pg_type_map.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config/initializers/pg_type_map.rb b/config/initializers/pg_type_map.rb index 9f4c07f8..1072e823 100644 --- a/config/initializers/pg_type_map.rb +++ b/config/initializers/pg_type_map.rb @@ -2,6 +2,12 @@ require 'active_record' require 'qx' require 'pg' -Qx.config(type_map: PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection)) -Qx.execute("SET TIME ZONE utc") +def database_exists? + ActiveRecord::Base.connection +rescue ActiveRecord::NoDatabaseError + false +else + Qx.config(type_map: PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection)) + Qx.execute("SET TIME ZONE utc") +end From f0fd393be485d18fa8bf2c4b7ddb9afe18a2bee5 Mon Sep 17 00:00:00 2001 From: Luis Castro Date: Tue, 30 Jul 2019 23:29:24 +0200 Subject: [PATCH 64/77] style(format): run rubocop format autocorrect --- Gemfile | 50 +- Rakefile | 4 +- app/api/houdini/api.rb | 4 +- app/api/houdini/v1/api.rb | 36 +- app/api/houdini/v1/base_api.rb | 6 +- app/api/houdini/v1/entities/nonprofit.rb | 4 +- .../houdini/v1/entities/validation_error.rb | 8 +- .../houdini/v1/entities/validation_errors.rb | 6 +- .../houdini/v1/helpers/application_helper.rb | 18 +- app/api/houdini/v1/helpers/rescue_helper.rb | 21 +- app/api/houdini/v1/nonprofit.rb | 139 ++-- app/api/houdini/v1/validations.rb | 4 +- app/api/houdini/v1/validators/is_equal_to.rb | 6 +- app/controllers/activities_controller.rb | 12 +- app/controllers/application_controller.rb | 232 +++--- .../aws_presigned_posts_controller.rb | 7 +- .../billing_subscriptions_controller.rb | 28 +- app/controllers/button_debug_controller.rb | 6 +- .../campaign_gift_options_controller.rb | 48 +- app/controllers/campaign_gifts_controller.rb | 9 +- .../campaign_gift_options_controller.rb | 80 +- .../campaigns/donations_controller.rb | 29 +- .../campaigns/supporters_controller.rb | 33 +- app/controllers/campaigns_controller.rb | 25 +- app/controllers/cards_controller.rb | 16 +- .../direct_debit_details_controller.rb | 8 +- app/controllers/email_settings_controller.rb | 4 +- app/controllers/emails_controller.rb | 15 +- app/controllers/event_discounts_controller.rb | 19 +- app/controllers/events_controller.rb | 59 +- app/controllers/front_controller.rb | 22 +- .../image_attachments_controller.rb | 42 +- app/controllers/maps_controller.rb | 52 +- .../nonprofits/activities_controller.rb | 12 +- .../nonprofits/bank_accounts_controller.rb | 109 +-- .../nonprofits/button_controller.rb | 39 +- .../nonprofits/cards_controller.rb | 9 +- .../nonprofits/charges_controller.rb | 19 +- .../custom_field_joins_controller.rb | 64 +- .../custom_field_masters_controller.rb | 42 +- .../nonprofits/donations_controller.rb | 125 ++- .../nonprofits/email_lists_controller.rb | 22 +- .../nonprofits/imports_controller.rb | 10 +- .../miscellaneous_np_infos_controller.rb | 13 +- .../nonprofits/nonprofit_keys_controller.rb | 63 +- .../nonprofits/payments_controller.rb | 44 +- .../nonprofits/payouts_controller.rb | 81 +- .../recurring_donations_controller.rb | 167 ++-- .../nonprofits/refunds_controller.rb | 31 +- .../nonprofits/reports_controller.rb | 14 +- .../nonprofits/supporter_emails_controller.rb | 11 +- .../nonprofits/supporter_notes_controller.rb | 41 +- .../nonprofits/supporters_controller.rb | 192 ++--- .../nonprofits/tag_joins_controller.rb | 40 +- .../nonprofits/tag_masters_controller.rb | 14 +- .../nonprofits/trackings_controller.rb | 8 +- app/controllers/nonprofits_controller.rb | 131 ++-- app/controllers/onboard_controller.rb | 2 + app/controllers/profiles_controller.rb | 75 +- .../recurring_donations_controller.rb | 20 +- app/controllers/roles_controller.rb | 36 +- app/controllers/settings_controller.rb | 44 +- app/controllers/static_controller.rb | 9 +- app/controllers/super_admins_controller.rb | 51 +- app/controllers/ticket_levels_controller.rb | 49 +- app/controllers/tickets_controller.rb | 42 +- .../users/confirmations_controller.rb | 52 +- .../users/registrations_controller.rb | 14 +- app/controllers/users/sessions_controller.rb | 49 +- app/helpers/application_helper.rb | 107 +-- app/helpers/card_helper.rb | 37 +- app/helpers/devise_helper.rb | 4 +- app/helpers/nonprofits_helper.rb | 26 +- app/helpers/onboard_helper.rb | 2 + app/helpers/pricing_helper.rb | 14 +- app/helpers/profiles_helper.rb | 6 +- app/jobs/application_job.rb | 2 + app/mailers/admin_mailer.rb | 3 +- app/mailers/base_mailer.rb | 4 +- app/mailers/billing_subscription_mailer.rb | 8 +- app/mailers/campaign_mailer.rb | 23 +- app/mailers/donation_mailer.rb | 157 ++-- app/mailers/event_mailer.rb | 18 +- app/mailers/export_mailer.rb | 4 +- app/mailers/generic_mailer.rb | 8 +- app/mailers/import_mailer.rb | 14 +- app/mailers/nonprofit_admin_mailer.rb | 46 +- app/mailers/nonprofit_mailer.rb | 140 ++-- app/mailers/payment_mailer.rb | 4 +- app/mailers/recurring_donation_mailer.rb | 21 +- app/mailers/testing.rb | 4 +- app/mailers/ticket_mailer.rb | 15 +- app/mailers/user_mailer.rb | 36 +- app/models/activity.rb | 4 +- app/models/application_record.rb | 6 +- app/models/bank_account.rb | 67 +- app/models/billing_plan.rb | 28 +- app/models/billing_subscription.rb | 49 +- app/models/campaign.rb | 297 ++++---- app/models/campaign_gift.rb | 24 +- app/models/campaign_gift_option.rb | 58 +- app/models/card.rb | 40 +- app/models/charge.rb | 57 +- app/models/comment.rb | 56 +- app/models/coupon.rb | 16 +- app/models/custom_field_join.rb | 35 +- app/models/custom_field_master.rb | 32 +- app/models/direct_debit_detail.rb | 2 + app/models/dispute.rb | 12 +- app/models/donation.rb | 87 +-- app/models/email_draft.rb | 22 +- app/models/email_list.rb | 2 + app/models/email_setting.rb | 6 +- app/models/event.rb | 177 +++-- app/models/event_discount.rb | 5 +- app/models/export.rb | 3 +- app/models/full_contact_info.rb | 40 +- app/models/full_contact_org.rb | 8 +- app/models/full_contact_photo.rb | 22 +- app/models/full_contact_social_profile.rb | 26 +- app/models/full_contact_topic.rb | 8 +- app/models/image_attachment.rb | 12 +- app/models/import.rb | 29 +- app/models/miscellaneous_np_info.rb | 5 +- app/models/nonprofit.rb | 78 +- app/models/nonprofit_account.rb | 18 +- app/models/offsite_payment.rb | 14 +- app/models/payment.rb | 44 +- app/models/payment_import.rb | 2 + app/models/payment_payout.rb | 26 +- app/models/payout.rb | 86 +-- app/models/profile.rb | 189 ++--- app/models/recurring_donation.rb | 39 +- app/models/refund.rb | 39 +- app/models/role.rb | 90 ++- app/models/source_token.rb | 4 +- app/models/supporter.rb | 30 +- app/models/supporter_email.rb | 28 +- app/models/supporter_note.rb | 20 +- app/models/tag_join.rb | 35 +- app/models/tag_master.rb | 36 +- app/models/ticket.rb | 29 +- app/models/ticket_level.rb | 16 +- app/models/tracking.rb | 2 + app/models/user.rb | 154 ++-- app/uploaders/article_background_uploader.rb | 11 +- app/uploaders/article_uploader.rb | 10 +- .../campaign_background_image_uploader.rb | 33 +- .../campaign_banner_image_uploader.rb | 22 +- app/uploaders/campaign_main_image_uploader.rb | 88 +-- .../event_background_image_uploader.rb | 10 +- app/uploaders/event_main_image_uploader.rb | 88 +-- app/uploaders/image_attachment_uploader.rb | 16 +- .../nonprofit_background_uploader.rb | 10 +- app/uploaders/nonprofit_logo_uploader.rb | 78 +- app/uploaders/nonprofit_uploader.rb | 14 +- app/uploaders/profile_uploader.rb | 94 +-- app/views/campaigns/index.rabl | 7 +- app/views/events/index.rabl | 6 +- app/views/maps/all_npo_supporters.rabl | 6 +- app/views/maps/all_npos.rabl | 6 +- app/views/maps/all_supporters.rabl | 7 +- app/views/maps/specific_npo_supporters.rabl | 6 +- .../nonprofits/custom_field_joins/index.rabl | 6 +- .../custom_field_masters/index.rabl | 8 +- app/views/nonprofits/payments/show.rabl | 46 +- .../nonprofits/recurring_donations/show.rabl | 8 +- app/views/nonprofits/refunds/index.rabl | 7 +- bin/bundle | 4 +- bin/rails | 2 + bin/rake | 2 + bin/setup | 4 +- bin/update | 4 +- config.ru | 4 +- config/application.rb | 123 +-- config/boot.rb | 4 +- config/environment.rb | 76 +- config/environments/ci.rb | 6 +- config/environments/development.rb | 7 +- config/environments/production.rb | 7 +- config/environments/staging.rb | 107 +-- config/environments/test.rb | 4 +- .../application_controller_renderer.rb | 2 + config/initializers/assets.rb | 2 + config/initializers/aws.rb | 6 +- config/initializers/aws_ses.rb | 8 +- config/initializers/backtrace_silencers.rb | 2 + config/initializers/block_ips.rb | 5 +- config/initializers/carrierwave.rb | 22 +- config/initializers/chunked_uploader.rb | 4 +- config/initializers/config.rb | 2 + config/initializers/cookies_serializer.rb | 2 + config/initializers/delayed_job_config.rb | 2 + config/initializers/devise.rb | 368 ++++----- config/initializers/devise_async.rb | 4 +- config/initializers/email_jobs.rb | 4 +- .../initializers/filter_parameter_logging.rb | 2 + config/initializers/fullcontact.rb | 8 +- config/initializers/geocode.rb | 6 +- config/initializers/hamster_extensions.rb | 4 +- config/initializers/inflections.rb | 2 + config/initializers/locale.rb | 2 + config/initializers/log_rage.rb | 22 +- config/initializers/mailchimp.rb | 8 +- config/initializers/mime_types.rb | 2 + config/initializers/pg_type_map.rb | 5 +- config/initializers/quiet_assets.rb | 2 + config/initializers/rabl_init.rb | 4 +- config/initializers/reload_api.rb | 2 + config/initializers/secret_token.rb | 4 +- config/initializers/session_store.rb | 2 + config/initializers/slack_notice.rb | 4 +- config/initializers/stripe.rb | 4 +- config/initializers/time.rb | 2 + config/initializers/timeout.rb | 4 +- config/initializers/wrap_parameters.rb | 2 + config/puma.rb | 11 +- config/routes.rb | 440 ++++++----- config/spring.rb | 6 +- ...dexes_for_payment_and_supporter_queries.rb | 42 +- db/migrate/20170307223525_drop_all_cruft.rb | 63 +- ..._end_datetimes_for_events_and_campaigns.rb | 11 +- ...22203228_add_donation_campaign_id_index.rb | 13 +- ...05180556_add_the_tag_joins_backup_table.rb | 2 + ..._index_for_tag_joins_and_add_constraint.rb | 6 +- ...558_add_custom_field_joins_backup_table.rb | 2 + ...ex_for_custom_field_join_and_supporters.rb | 6 +- .../20170808180559_add_inactive_to_card.rb | 6 +- db/migrate/20170818201127_create_exports.rb | 2 + ...002160808_create_miscellaneous_np_infos.rb | 2 + ...0171002164402_add_currency_to_nonprofit.rb | 2 + ...mount_message_to_miscellaneous_np_infos.rb | 2 + ...37_add_first_and_last_name_to_supporter.rb | 2 + db/migrate/20171016181942_add_tracking.rb | 2 + ...06_add_queued_for_import_at_to_donation.rb | 2 + .../20171026102139_add_direct_debit_detail.rb | 10 +- ...1129215957_add_utm_content_to_trackings.rb | 2 + ...20171130182254_add_locale_to_supporters.rb | 2 + ...93955_add_payment_provider_to_donations.rb | 2 + ...3317_add_direct_debit_detail_to_charges.rb | 2 + ...229_add_external_identifier_to_campaign.rb | 2 + ...71207191435_add_index_to_campaign_gifts.rb | 2 + .../20171207191712_add_index_to_activities.rb | 2 + ...1207200746_modify_supporters_name_index.rb | 2 + ...0171207200950_add_supporters_name_index.rb | 2 + ...1207210431_add_charges_payment_id_index.rb | 2 + ...ndexes_for_supporter_deleted_and_import.rb | 2 + .../20180119215653_create_payment_imports.rb | 2 + ...te_donations_payment_imports_join_table.rb | 2 + .../20180202181929_remove_unused_metadata.rb | 74 +- ...1755_remove_recurring_donation_event_id.rb | 3 +- .../20180214124311_create_source_tokens.rb | 11 +- ...20180215124311_add_card_token_to_ticket.rb | 2 + ...16064311_add_indexes_to_supporter_notes.rb | 4 +- ...16124311_change_ddd_supporter_to_holder.rb | 2 + db/migrate/20180217124311_remove_articles.rb | 5 +- ...49_add_index_to_supporter_id_on_tickets.rb | 2 + ...dex_to_event_id_on_donations_and_events.rb | 2 + ...401_add_parent_campaign_id_to_campaigns.rb | 2 + ..._add_reason_for_supporting_to_campaigns.rb | 2 + ...ault_reason_for_supporting_to_campaigns.rb | 2 + ...703165405_add_banner_image_to_campaigns.rb | 2 + .../20180713213748_add_charge_id_indexes.rb | 3 +- ...0180713215825_add_payment_id_to_tickets.rb | 2 + .../20180713220028_add_indexes_to_refunds.rb | 2 + .../20181002160627_correct_dedications.rb | 34 +- ...81003212559_correct_dedication_contacts.rb | 59 +- ...dd_index_parent_campaign_id_to_campaign.rb | 2 + ...1143_add_indexes_to_recurring_donations.rb | 2 + ...add_donation_id_index_to_campaign_gifts.rb | 2 + ...224030_add_index_to_payments_created_at.rb | 2 + db/seeds.rb | 6 +- gems/grape_devise/Gemfile | 4 +- gems/grape_devise/Rakefile | 4 +- gems/grape_devise/grape_devise.gemspec | 44 +- gems/grape_devise/lib/grape_devise.rb | 8 +- gems/grape_devise/lib/grape_devise/api.rb | 7 +- gems/grape_devise/lib/grape_devise/version.rb | 4 +- gems/grape_devise/spec/dummy/Rakefile | 4 +- gems/grape_devise/spec/dummy/app/api/api.rb | 12 +- .../app/controllers/application_controller.rb | 2 + .../dummy/app/helpers/application_helper.rb | 2 + .../spec/dummy/app/models/user.rb | 2 + gems/grape_devise/spec/dummy/bin/bundle | 4 +- gems/grape_devise/spec/dummy/bin/rails | 4 +- gems/grape_devise/spec/dummy/bin/rake | 2 + gems/grape_devise/spec/dummy/config.ru | 4 +- .../spec/dummy/config/application.rb | 7 +- gems/grape_devise/spec/dummy/config/boot.rb | 10 +- .../spec/dummy/config/environment.rb | 4 +- .../dummy/config/environments/development.rb | 2 + .../dummy/config/environments/production.rb | 2 + .../spec/dummy/config/environments/test.rb | 4 +- .../initializers/backtrace_silencers.rb | 2 + .../spec/dummy/config/initializers/devise.rb | 6 +- .../initializers/filter_parameter_logging.rb | 2 + .../dummy/config/initializers/inflections.rb | 2 + .../dummy/config/initializers/mime_types.rb | 2 + .../dummy/config/initializers/secret_token.rb | 2 + .../config/initializers/session_store.rb | 2 + .../config/initializers/wrap_parameters.rb | 2 + gems/grape_devise/spec/dummy/config/routes.rb | 5 +- .../20140913043018_devise_create_users.rb | 7 +- gems/grape_devise/spec/dummy/db/schema.rb | 37 +- gems/grape_devise/spec/factories.rb | 8 +- gems/grape_devise/spec/requests/user_spec.rb | 37 +- gems/grape_devise/spec/spec_helper.rb | 10 +- gems/ruby-param-validation/Rakefile | 6 +- .../lib/param_validation.rb | 191 +++-- .../param_validation.gemspec | 2 + .../test/param_validation_test.rb | 138 ++-- gems/ruby-qx/lib/qx.rb | 31 +- gems/ruby-qx/qx.gemspec | 4 +- gems/ruby-qx/test/UpsertTest.rb | 16 +- gems/ruby-qx/test/qx_test.rb | 238 +++--- lib/audit.rb | 57 +- lib/calculate/calculate_fees.rb | 13 +- lib/calculate/calculate_suggested_amounts.rb | 52 +- lib/cancel_billing_subscription.rb | 28 +- lib/chunked_uploader/s3.rb | 18 +- .../construct_billing_subscription.rb | 31 +- lib/construct/construct_nonprofit.rb | 23 +- lib/controllers/campaign_helper.rb | 32 +- lib/controllers/event_helper.rb | 38 +- lib/controllers/nonprofit_helper.rb | 90 +-- lib/copy_naming_algorithm.rb | 37 +- lib/create/create_campaign.rb | 15 +- lib/create/create_campaign_gift.rb | 135 ++-- lib/create/create_campaign_gift_option.rb | 14 +- lib/create/create_custom_field_join.rb | 63 +- lib/create/create_custom_field_master.rb | 11 +- lib/create/create_peer_to_peer_campaign.rb | 25 +- lib/create/create_tag_master.rb | 12 +- lib/create/stripe/create_stripe_account.rb | 61 +- lib/cypher.rb | 13 +- lib/delayed_job_helper.rb | 19 +- lib/delete/delete_campaign_gift_option.rb | 33 +- lib/delete/delete_custom_field_joins.rb | 38 +- lib/delete/delete_tag_joins.rb | 41 +- lib/email.rb | 8 +- lib/email_job_queue.rb | 4 +- lib/errors/authentication_error.rb | 4 +- lib/errors/cc_org_error.rb | 4 +- lib/errors/charge_error.rb | 4 +- lib/errors/expired_token_error.rb | 4 +- lib/errors/not_enough_quantity_error.rb | 4 +- lib/export/export_payments.rb | 18 +- lib/export/export_recurring_donations.rb | 14 +- lib/export/export_supporter_notes.rb | 143 ++-- lib/export/export_supporters.rb | 21 +- lib/fetch/fetch_background_image.rb | 9 +- lib/fetch/fetch_campaign.rb | 21 +- lib/fetch/fetch_coupon.rb | 10 +- lib/fetch/fetch_event.rb | 21 +- lib/fetch/fetch_miscellaneous_np_info.rb | 9 +- lib/fetch/fetch_nonprofit.rb | 19 +- lib/fetch/fetch_nonprofit_email.rb | 19 +- lib/fetch/fetch_todo_status.rb | 49 +- lib/fetch/stripe/fetch_stripe_account.rb | 20 +- lib/format/format/address.rb | 35 +- lib/format/format/csv.rb | 22 +- lib/format/format/currency.rb | 36 +- lib/format/format/date.rb | 111 +-- lib/format/format/dedication.rb | 7 +- lib/format/format/geography.rb | 600 +++++++-------- lib/format/format/html.rb | 4 +- lib/format/format/indefinitize.rb | 20 +- lib/format/format/interpolate.rb | 5 +- lib/format/format/name.rb | 18 +- lib/format/format/phone.rb | 38 +- lib/format/format/remove_diacritics.rb | 21 +- lib/format/format/timezone.rb | 27 +- lib/format/format/url.rb | 46 +- lib/generators/api/entity/entity_generator.rb | 6 +- .../api/resource/resource_generator.rb | 10 +- .../api/validator/validator_generator.rb | 12 +- .../email_job/email_job_generator.rb | 6 +- .../libmodule/libmodule_generator.rb | 6 +- .../react/component/component_generator.rb | 8 +- lib/generators/react/lib/lib_generator.rb | 8 +- .../react/packroot/packroot_generator.rb | 5 +- .../ts/declaration/declaration_generator.rb | 6 +- lib/geocode_model.rb | 73 +- lib/get_data.rb | 52 +- lib/hash.rb | 10 +- lib/health_report.rb | 37 +- lib/htp.rb | 2 + lib/image.rb | 17 +- lib/import/import_civicrm_payments.rb | 146 ++-- lib/include_asset.rb | 11 +- lib/insert/insert_activities.rb | 209 +++-- lib/insert/insert_bank_account.rb | 90 ++- lib/insert/insert_billing_subscriptions.rb | 26 +- lib/insert/insert_card.rb | 81 +- lib/insert/insert_charge.rb | 268 ++++--- lib/insert/insert_custom_field_joins.rb | 133 ++-- lib/insert/insert_direct_debit_detail.rb | 10 +- lib/insert/insert_disputes.rb | 45 +- lib/insert/insert_donation.rb | 123 +-- lib/insert/insert_duplicate.rb | 134 ++-- lib/insert/insert_email_lists.rb | 35 +- lib/insert/insert_full_contact_infos.rb | 193 +++-- lib/insert/insert_import.rb | 84 +- lib/insert/insert_nonprofit_keys.rb | 44 +- lib/insert/insert_payout.rb | 113 +-- lib/insert/insert_recurring_donation.rb | 117 ++- lib/insert/insert_refunds.rb | 60 +- lib/insert/insert_source_token.rb | 22 +- lib/insert/insert_supporter.rb | 86 +-- lib/insert/insert_supporter_notes.rb | 27 +- lib/insert/insert_tag_joins.rb | 102 ++- lib/insert/insert_tickets.rb | 117 +-- lib/insert/insert_tracking.rb | 22 +- lib/job_types/admin_failed_gift_job.rb | 4 +- lib/job_types/admin_notice_job.rb | 4 +- .../campaign_creation_followup_job.rb | 4 +- .../donor_direct_debit_notification_job.rb | 6 +- .../donor_failed_recurring_donation_job.rb | 4 +- .../donor_payment_notification_job.rb | 24 +- ...or_recurring_donation_change_amount_job.rb | 24 +- .../donor_refund_notification_job.rb | 22 +- lib/job_types/email_job.rb | 41 +- lib/job_types/event_creation_followup_job.rb | 4 +- lib/job_types/export_payment_completed_job.rb | 4 +- lib/job_types/export_payment_failed_job.rb | 4 +- ...xport_recurring_donations_completed_job.rb | 4 +- .../export_recurring_donations_failed_job.rb | 4 +- .../export_supporter_notes_completed_job.rb | 4 +- .../export_supporter_notes_failed_job.rb | 4 +- .../export_supporters_completed_job.rb | 4 +- lib/job_types/export_supporters_failed_job.rb | 4 +- lib/job_types/generic_mail_job.rb | 4 +- .../import_complete_notification_job.rb | 4 +- .../nonprofit_admin_existing_invite_job.rb | 4 +- .../nonprofit_admin_new_invite_job.rb | 4 +- ...onprofit_admin_supporter_fundraiser_job.rb | 4 +- ...nonprofit_failed_recurring_donation_job.rb | 4 +- .../nonprofit_failed_verification_job.rb | 4 +- .../nonprofit_new_bank_account_job.rb | 4 +- .../nonprofit_payment_notification_job.rb | 24 +- lib/job_types/nonprofit_pending_payout_job.rb | 4 +- ...fit_recurring_donation_cancellation_job.rb | 4 +- ...it_recurring_donation_change_amount_job.rb | 6 +- .../nonprofit_refund_notification_job.rb | 22 +- .../nonprofit_successful_verification_job.rb | 4 +- lib/job_types/nonprofit_welcome_job.rb | 4 +- lib/job_types/ticket_mailer_followup_job.rb | 4 +- .../ticket_mailer_receipt_admin_job.rb | 6 +- lib/json_resp.rb | 82 +- lib/list/list_activities.rb | 26 +- lib/mailchimp.rb | 232 +++--- lib/maintain/maintain_dedications.rb | 42 +- lib/maintain/maintain_payment_records.rb | 10 +- lib/maintain/maintain_ticket_records.rb | 13 +- lib/merge_supporters.rb | 81 +- lib/metrics/nonprofit_metrics.rb | 188 ++--- lib/name_copy_naming_algorithm.rb | 20 +- lib/notify/notify_user.rb | 11 +- lib/numeric.rb | 14 +- lib/onboard_accounts.rb | 127 ++- lib/parallel_ar.rb | 6 +- lib/path/nonprofit_path.rb | 16 +- lib/pay_recurring_donation.rb | 129 ++-- lib/psql.rb | 10 +- lib/qexpr.rb | 132 ++-- lib/qexpr_query_chunker.rb | 43 +- lib/query/billing_plans.rb | 23 +- lib/query/query_activities.rb | 5 +- lib/query/query_billing_subscriptions.rb | 18 +- lib/query/query_campaign_gifts.rb | 48 +- lib/query/query_campaign_metrics.rb | 30 +- lib/query/query_campaigns.rb | 78 +- lib/query/query_charges.rb | 2 + lib/query/query_custom_fields.rb | 15 +- lib/query/query_donations.rb | 105 ++- lib/query/query_email_settings.rb | 17 +- lib/query/query_event_discounts.rb | 16 +- lib/query/query_event_metrics.rb | 84 +- lib/query/query_event_organizer.rb | 20 +- lib/query/query_events.rb | 14 +- lib/query/query_full_contact_infos.rb | 13 +- lib/query/query_nonprofit_keys.rb | 15 +- lib/query/query_nonprofits.rb | 114 +-- lib/query/query_payments.rb | 367 +++++---- lib/query/query_profiles.rb | 40 +- lib/query/query_recurring_donations.rb | 280 ++++--- lib/query/query_roles.rb | 45 +- lib/query/query_source_token.rb | 35 +- lib/query/query_supporters.rb | 602 +++++++-------- lib/query/query_ticket_levels.rb | 52 +- lib/query/query_tickets.rb | 144 ++-- lib/query/query_users.rb | 33 +- lib/queue_donations.rb | 52 +- lib/qx_query_chunker.rb | 4 +- lib/required_keys.rb | 7 +- lib/retrieve/retrieve_active_record_items.rb | 48 +- lib/scheduled_jobs.rb | 57 +- lib/search_vector.rb | 32 +- lib/slug_copy_naming_algorithm.rb | 14 +- lib/slug_nonprofit_naming_algorithm.rb | 20 +- lib/slug_p2p_campaign_naming_algorithm.rb | 12 +- lib/stripe_account.rb | 65 +- lib/stripe_utils.rb | 52 +- lib/tasks/civicrm.rake | 8 +- lib/tasks/database.rake | 20 +- lib/tasks/full_contact.rake | 11 +- lib/tasks/health_report.rake | 10 +- lib/tasks/oapi.rake | 6 +- lib/tasks/scheduler.rake | 22 +- lib/tasks/seed.rake | 27 +- lib/tasks/settings.rake | 23 +- lib/timespan.rb | 55 +- lib/update/update_activities.rb | 18 +- lib/update/update_billing_subscriptions.rb | 3 +- lib/update/update_campaign_gift_option.rb | 13 +- lib/update/update_charges.rb | 15 +- lib/update/update_custom_field_joins.rb | 19 +- lib/update/update_disputes.rb | 5 +- lib/update/update_donation.rb | 97 ++- lib/update/update_email_lists.rb | 28 +- lib/update/update_email_settings.rb | 11 +- lib/update/update_miscellaneous_np_info.rb | 21 +- lib/update/update_nonprofit.rb | 60 +- lib/update/update_order.rb | 11 +- lib/update/update_payouts.rb | 26 +- lib/update/update_recurring_donations.rb | 85 +-- lib/update/update_refunds.rb | 23 +- lib/update/update_supporter.rb | 18 +- lib/update/update_supporter_notes.rb | 11 +- lib/update/update_tickets.rb | 29 +- lib/uuid.rb | 6 +- lib/validation_error.rb | 2 + script/delayed_job | 1 + script/rails | 8 +- spec/api/houdini/nonprofit_spec.rb | 175 ++--- .../support/api_shared_user_verification.rb | 115 ++- spec/controllers/aws_presigned_posts_spec.rb | 6 +- .../controllers/billing_subscriptions_spec.rb | 14 +- .../controllers/campaign_gift_options_spec.rb | 14 +- spec/controllers/campaign_gifts_spec.rb | 6 +- .../campaigns/campaign_gift_options_spec.rb | 8 +- spec/controllers/campaigns/donations_spec.rb | 8 +- spec/controllers/campaigns/supporters_spec.rb | 6 +- spec/controllers/campaigns_spec.rb | 27 +- spec/controllers/cards_spec.rb | 8 +- spec/controllers/direct_debit_details_spec.rb | 10 +- spec/controllers/email_settings_spec.rb | 13 +- spec/controllers/emails_spec.rb | 8 +- spec/controllers/event_discounts_spec.rb | 22 +- spec/controllers/events_spec.rb | 32 +- spec/controllers/front_spec.rb | 11 +- spec/controllers/image_attachments_spec.rb | 6 +- spec/controllers/maps_spec.rb | 16 +- .../controllers/nonprofits/activities_spec.rb | 6 +- .../nonprofits/bank_accounts_spec.rb | 6 +- spec/controllers/nonprofits/button_spec.rb | 8 +- spec/controllers/nonprofits/cards_spec.rb | 6 +- spec/controllers/nonprofits/charges_spec.rb | 6 +- .../nonprofits/custom_field_masters_spec.rb | 6 +- .../nonprofits/custom_fields_joins_spec.rb | 10 +- spec/controllers/nonprofits/donations_spec.rb | 21 +- .../nonprofits/email_lists_spec.rb | 6 +- spec/controllers/nonprofits/imports_spec.rb | 6 +- .../nonprofits/miscellaneous_np_infos_spec.rb | 6 +- .../nonprofits/nonprofit_keys_spec.rb | 6 +- spec/controllers/nonprofits/payments_spec.rb | 6 +- spec/controllers/nonprofits/payouts_spec.rb | 8 +- .../nonprofits/recurring_donations_spec.rb | 8 +- spec/controllers/nonprofits/reports_spec.rb | 6 +- .../nonprofits/supporter_emails_spec.rb | 6 +- .../controllers/nonprofits/supporters_spec.rb | 6 +- spec/controllers/nonprofits/tag_joins_spec.rb | 18 +- .../nonprofits/tag_masters_spec.rb | 12 +- spec/controllers/nonprofits/trackings_spec.rb | 8 +- spec/controllers/nonprofits_spec.rb | 38 +- spec/controllers/onboard_controller_spec.rb | 5 +- spec/controllers/profiles_spec.rb | 12 +- spec/controllers/recurring_donations_spec.rb | 6 +- spec/controllers/roles_spec.rb | 14 +- spec/controllers/settings_spec.rb | 6 +- spec/controllers/static_controller_spec.rb | 36 +- spec/controllers/super_admins_spec.rb | 16 +- .../support/new_controller_user_context.rb | 23 +- .../support/shared_user_context.rb | 171 ++--- spec/controllers/ticket_levels_spec.rb | 19 +- spec/controllers/tickets_spec.rb | 16 +- spec/cve/cve_2014_2538_spec.rb | 8 +- spec/cve/cve_2015_3225_spec.rb | 9 +- spec/cve/cve_2015_3226_spec.rb | 15 +- spec/factories/bank_accounts.rb | 3 +- spec/factories/billing_plans.rb | 3 +- spec/factories/billing_subscriptions.rb | 3 +- spec/factories/campaign_gift_options.rb | 4 +- spec/factories/campaign_gifts.rb | 3 +- spec/factories/campaigns.rb | 6 +- spec/factories/cards.rb | 26 +- spec/factories/charges.rb | 3 +- spec/factories/custom_field_joins.rb | 3 +- spec/factories/custom_field_masters.rb | 6 +- spec/factories/direct_debit_details.rb | 3 +- spec/factories/disputes.rb | 3 +- spec/factories/donations.rb | 3 +- spec/factories/email_lists.rb | 3 +- spec/factories/event_discounts.rb | 2 + spec/factories/events.rb | 16 +- spec/factories/exports.rb | 2 + spec/factories/miscellaneous_np_infos.rb | 3 +- spec/factories/nonprofits.rb | 23 +- spec/factories/offsite_payments.rb | 3 +- spec/factories/payment_imports.rb | 6 +- spec/factories/payment_payouts.rb | 3 +- spec/factories/payments.rb | 3 +- spec/factories/payouts.rb | 3 +- spec/factories/profiles.rb | 4 +- spec/factories/recurring_donations.rb | 3 +- spec/factories/refunds.rb | 3 +- spec/factories/roles.rb | 3 +- spec/factories/source_tokens.rb | 2 + spec/factories/supporter_notes.rb | 3 +- spec/factories/supporters.rb | 8 +- spec/factories/tag_joins.rb | 2 + spec/factories/tag_masters.rb | 3 +- spec/factories/ticket_levels.rb | 3 +- spec/factories/tickets.rb | 3 +- spec/factories/users.rb | 6 +- spec/lib/calculate/calculate_fees_spec.rb | 33 +- .../calculate_suggested_amounts_spec.rb | 43 +- spec/lib/cancel_billing_subscriptions_spec.rb | 59 +- spec/lib/chunked_uploader/s3_spec.rb | 2 + .../lib/construct/construct_nonprofit_spec.rb | 31 +- spec/lib/copy_naming_algorithm_spec.rb | 89 +-- spec/lib/create/create_campaign_gift_spec.rb | 199 +++-- spec/lib/create/create_campaign_spec.rb | 6 +- .../create_peer_to_peer_campaign_spec.rb | 12 +- .../delete_campaign_gift_option_spec.rb | 84 +- spec/lib/email_job_queue_spec.rb | 9 +- spec/lib/export/export_payments_spec.rb | 47 +- .../export/export_recurring_donations_spec.rb | 34 +- .../lib/export/export_supporter_notes_spec.rb | 49 +- spec/lib/export/export_supporters_spec.rb | 30 +- spec/lib/fetch/fetch_coupon_spec.rb | 15 +- .../fetch_misc_nonprofit_settings_spec.rb | 21 +- spec/lib/fetch/fetch_nonprofit_email_spec.rb | 34 +- spec/lib/format/currency_spec.rb | 72 +- spec/lib/format/dedication_spec.rb | 12 +- spec/lib/format/geography_spec.rb | 28 +- spec/lib/format/indefinitize_spec.rb | 10 +- spec/lib/format/name_spec.rb | 8 +- spec/lib/format/url_spec.rb | 21 +- .../import/import_civicrm_payments_spec.rb | 6 +- spec/lib/insert/insert_bank_account_spec.rb | 155 ++-- .../insert_billing_subscriptions_spec.rb | 14 +- spec/lib/insert/insert_card_spec.rb | 653 ++++++++-------- spec/lib/insert/insert_charge_spec.rb | 720 +++++++++--------- .../insert/insert_custom_field_joins_spec.rb | 288 ++++--- spec/lib/insert/insert_disputes_spec.rb | 14 +- spec/lib/insert/insert_donation_spec.rb | 110 ++- spec/lib/insert/insert_duplicate_spec.rb | 476 ++++++------ spec/lib/insert/insert_import_spec.rb | 52 +- spec/lib/insert/insert_payout_spec.rb | 352 +++++---- .../insert/insert_recurring_donation_spec.rb | 232 +++--- spec/lib/insert/insert_refunds_spec.rb | 91 ++- spec/lib/insert/insert_source_token_spec.rb | 120 ++- spec/lib/insert/insert_tag_joins_spec.rb | 256 +++---- spec/lib/insert/insert_tickets_spec.rb | 495 ++++++------ .../job_types/admin_failed_gift_job_spec.rb | 8 +- spec/lib/job_types/admin_notice_job_spec.rb | 6 +- .../campaign_creation_followup_job_spec.rb | 6 +- ...onor_direct_debit_notification_job_spec.rb | 6 +- ...onor_failed_recurring_donation_job_spec.rb | 6 +- .../donor_payment_notification_job_spec.rb | 6 +- ...curring_donation_change_amount_job_spec.rb | 6 +- .../donor_refund_notification_job_spec.rb | 5 +- spec/lib/job_types/email_job_spec.rb | 8 +- .../event_creation_followup_job_spec.rb | 6 +- .../export_payment_completed_job_spec.rb | 6 +- .../export_payment_failed_job_spec.rb | 6 +- ..._recurring_donations_completed_job_spec.rb | 6 +- ...ort_recurring_donations_failed_job_spec.rb | 6 +- .../export_supporter_notes_completed_spec.rb | 6 +- .../export_supporter_notes_failed_spec.rb | 8 +- .../export_supporters_completed_job_spec.rb | 6 +- .../export_supporters_failed_job_spec.rb | 6 +- spec/lib/job_types/generic_mail_job_spec.rb | 8 +- .../import_complete_notification_job_spec.rb | 6 +- ...onprofit_admin_existing_invite_job_spec.rb | 6 +- .../nonprofit_admin_new_invite_job_spec.rb | 8 +- ...fit_admin_supporter_fundraiser_job_spec.rb | 6 +- ...ofit_failed_recurring_donation_job_spec.rb | 6 +- .../nonprofit_failed_verification_job_spec.rb | 6 +- .../nonprofit_new_bank_account_job_spec.rb | 6 +- ...nonprofit_payment_notification_job_spec.rb | 6 +- .../nonprofit_pending_payout_job_spec.rb | 6 +- ...ecurring_donation_cancellation_job_spec.rb | 6 +- ...curring_donation_change_amount_job_spec.rb | 6 +- .../nonprofit_refund_notification_job_spec.rb | 5 +- ...profit_successful_verification_job_spec.rb | 6 +- .../job_types/nonprofit_welcome_job_spec.rb | 6 +- .../ticket_mailer_followup_job_spec.rb | 6 +- .../ticket_mailer_receipt_admin_job_spec.rb | 6 +- spec/lib/mailchimp_spec.rb | 69 +- spec/lib/merge_supporters_spec.rb | 83 +- spec/lib/name_copy_naming_algorithm_spec.rb | 68 +- spec/lib/numeric_spec.rb | 121 ++- spec/lib/pay_recurring_donation_spec.rb | 21 +- spec/lib/query/billing_plans_spec.rb | 31 +- .../query/query_billing_subscriptions_spec.rb | 42 +- spec/lib/query/query_campaign_gifts_spec.rb | 58 +- spec/lib/query/query_campaign_metrics_spec.rb | 33 +- spec/lib/query/query_donations_spec.rb | 65 +- spec/lib/query/query_payments_spec.rb | 323 ++++---- .../query/query_recurring_donations_spec.rb | 122 ++- spec/lib/query/query_roles_spec.rb | 13 +- spec/lib/query/query_source_token_spec.rb | 86 ++- spec/lib/query/query_supporters_spec.rb | 65 +- spec/lib/query/query_ticket_levels_spec.rb | 70 +- spec/lib/query/query_users_spec.rb | 27 +- .../retrieve_active_record_items_spec.rb | 57 +- spec/lib/slug_copy_naming_algorithm_spec.rb | 63 +- .../slug_nonprofit_naming_algorithm_spec.rb | 54 +- ...slug_p2p_campaign_naming_algorithm_spec.rb | 42 +- spec/lib/stripe_account_spec.rb | 114 ++- spec/lib/stripe_utils_spec.rb | 28 +- spec/lib/timespan_spec.rb | 106 ++- spec/lib/update/update_charges_spec.rb | 27 +- spec/lib/update/update_disputes_spec.rb | 6 +- spec/lib/update/update_donation_spec.rb | 372 +++++---- .../update_misc_nonprofit_settings_spec.rb | 47 +- spec/lib/update/update_payouts_spec.rb | 73 +- .../update/update_recurring_donations_spec.rb | 118 ++- spec/lib/update/update_refunds_spec.rb | 25 +- spec/lib/update/update_supporter_spec.rb | 6 +- spec/lib/update/update_tickets_spec.rb | 205 +++-- spec/lib/uuid_spec.rb | 2 + spec/mailers/admin_spec.rb | 47 +- spec/mailers/donation_mailer_spec.rb | 66 +- .../delete_custom_field_join_spec.rb | 78 +- spec/migration/delete_tag_join_spec.rb | 77 +- spec/migration/migration_sanity_spec.rb | 22 +- spec/models/campaign_spec.rb | 14 +- spec/models/nonprofit_spec.rb | 16 +- spec/models/payment_import_spec.rb | 4 +- spec/models/ticket_spec.rb | 23 +- spec/rails_helper.rb | 12 +- spec/requests/maintenance_spec.rb | 51 +- .../nonprofits/direct_debit_details_spec.rb | 25 +- spec/spec_helper.rb | 110 ++- spec/support/construct.rb | 20 +- spec/support/contexts.rb | 4 +- .../contexts/general_shared_user_context.rb | 104 ++- .../shared_donation_charge_context.rb | 65 +- .../shared_rd_donation_value_context.rb | 407 +++++----- spec/support/date_time.rb | 4 +- spec/support/expect.rb | 23 +- spec/support/factory_bot.rb | 16 +- spec/support/init_dotenv.rb | 4 +- spec/support/mock_helpers.rb | 24 +- spec/support/payments_for_a_payout.rb | 92 +-- spec/support/test_chunked_uploader.rb | 14 +- 759 files changed, 14563 insertions(+), 14380 deletions(-) diff --git a/Gemfile b/Gemfile index 0a5dda0f..5039b1d3 100755 --- a/Gemfile +++ b/Gemfile @@ -1,14 +1,16 @@ +# frozen_string_literal: true + source 'https://rubygems.org' ruby '2.5.1' -gem 'rake' gem 'rails', '= 5.2.3' +gem 'rake' # https://stripe.com/docs/api gem 'stripe' # Compression of assets on heroku # https://github.com/romanbsd/heroku-deflater -gem 'heroku-deflater', :group => :production +gem 'heroku-deflater', group: :production # json serialization # https://github.com/nesquena/rabl @@ -16,17 +18,17 @@ gem 'rabl' gem 'parallel' -gem 'puma' gem 'bootsnap', require: false -gem 'rack-timeout' -gem 'rack-ssl' +gem 'puma' gem 'puma_worker_killer' +gem 'rack-ssl' +gem 'rack-timeout' -gem 'test-unit', '~> 3.0' gem 'hamster' +gem 'test-unit', '~> 3.0' -gem 'aws-ses' gem 'aws-sdk', '~> 1' +gem 'aws-ses' # for blocking ip addressses gem 'rack-attack' @@ -44,7 +46,6 @@ gem 'qx', path: 'gems/ruby-qx' gem 'dalli' gem 'memcachier' - gem 'param_validation', path: 'gems/ruby-param-validation' # Print colorized text lol @@ -89,33 +90,32 @@ gem 'table_print' gem 'bunny', '>= 2.6.3' -gem 'rails-i18n' -gem 'i18n-js' gem 'countries' - +gem 'i18n-js' +gem 'rails-i18n' group :development, :ci do - gem 'traceroute' gem 'debase' gem 'ruby-debug-ide' + gem 'traceroute' end group :development, :ci, :test do - gem 'timecop' - gem 'pry' - #gem 'pry-byebug' - gem 'binding_of_caller' - gem 'rspec' - gem 'rspec-rails' - gem 'database_cleaner' + gem 'pry' + gem 'timecop' + # gem 'pry-byebug' + gem 'action_mailer_matchers' + gem 'binding_of_caller' + gem 'database_cleaner' gem 'dotenv-rails' - gem 'ruby-prof', '0.15.9' - gem 'stripe-ruby-mock', '~> 2.4.1', :require => 'stripe_mock', git: 'https://github.com/commitchange/stripe-ruby-mock.git', :branch => '2.4.1' gem 'factory_bot' - gem 'factory_bot_rails' - gem 'action_mailer_matchers' + gem 'factory_bot_rails' + gem 'rspec' + gem 'rspec-rails' + gem 'ruby-prof', '0.15.9' gem 'simplecov', '~> 0.16.1', require: false gem 'solargraph' + gem 'stripe-ruby-mock', '~> 2.4.1', require: 'stripe_mock', git: 'https://github.com/commitchange/stripe-ruby-mock.git', branch: '2.4.1' end group :test do @@ -139,6 +139,6 @@ gem 'grape' gem 'grape-entity' gem 'grape-swagger' gem 'grape-swagger-entity' -gem 'grape_url_validator' -gem 'grape_logging' gem 'grape_devise', path: 'gems/grape_devise' +gem 'grape_logging' +gem 'grape_url_validator' diff --git a/Rakefile b/Rakefile index c099dee5..9a148353 100755 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,9 @@ #!/usr/bin/env rake +# frozen_string_literal: true + # 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 File.expand_path('../config/application', __FILE__) +require File.expand_path('config/application', __dir__) Commitchange::Application.load_tasks diff --git a/app/api/houdini/api.rb b/app/api/houdini/api.rb index b2c54ab2..f1e5f35c 100644 --- a/app/api/houdini/api.rb +++ b/app/api/houdini/api.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::API < Grape::API format :json mount Houdini::V1::API => '/v1' -end \ No newline at end of file +end diff --git a/app/api/houdini/v1/api.rb b/app/api/houdini/v1/api.rb index d0e3a921..43b6516b 100644 --- a/app/api/houdini/v1/api.rb +++ b/app/api/houdini/v1/api.rb @@ -1,22 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'houdini/v1/validations' class Houdini::V1::API < Grape::API - logger.formatter = GrapeLogging::Formatters::Rails.new - use GrapeLogging::Middleware::RequestLogger, { logger: logger } - content_type :json, 'application/json' - default_format :json - rescue_from Grape::Exceptions::ValidationErrors do |e| - output = {errors: e} - error! output, 400 - end + logger.formatter = GrapeLogging::Formatters::Rails.new + use GrapeLogging::Middleware::RequestLogger, logger: logger + content_type :json, 'application/json' + default_format :json + rescue_from Grape::Exceptions::ValidationErrors do |e| + output = { errors: e } + error! output, 400 + end - #include Houdini::V1::Helpers::ApplicationHelper - mount Houdini::V1::Nonprofit => '/nonprofit' - # Additional mounts are added via generators above this line + # include Houdini::V1::Helpers::ApplicationHelper + mount Houdini::V1::Nonprofit => '/nonprofit' + # Additional mounts are added via generators above this line # DON'T REMOVE THIS OR THE PREVIOUS LINES!!! - uri_for_host = URI.parse(Settings.api_domain&.url || Settings.cdn.url) - add_swagger_documentation \ - host: "#{uri_for_host.host}#{uri_for_host.port ? ":#{uri_for_host.port}" : ""}", - schemes: [uri_for_host.scheme], - base_path: '/api/v1' -end \ No newline at end of file + uri_for_host = URI.parse(Settings.api_domain&.url || Settings.cdn.url) + add_swagger_documentation \ + host: "#{uri_for_host.host}#{uri_for_host.port ? ":#{uri_for_host.port}" : ''}", + schemes: [uri_for_host.scheme], + base_path: '/api/v1' +end diff --git a/app/api/houdini/v1/base_api.rb b/app/api/houdini/v1/base_api.rb index 17a5dd34..4b25d92e 100644 --- a/app/api/houdini/v1/base_api.rb +++ b/app/api/houdini/v1/base_api.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::BaseAPI < Grape::API - #helpers ApplicationHelper + # helpers ApplicationHelper # helpers do # def session # env['rack.session'] @@ -27,4 +29,4 @@ class Houdini::V1::BaseAPI < Grape::API # allow_forgery_protection.nil? || allow_forgery_protection # end # end -end \ No newline at end of file +end diff --git a/app/api/houdini/v1/entities/nonprofit.rb b/app/api/houdini/v1/entities/nonprofit.rb index 55620d7e..6922e0d0 100644 --- a/app/api/houdini/v1/entities/nonprofit.rb +++ b/app/api/houdini/v1/entities/nonprofit.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::Entities::Nonprofit < Grape::Entity expose :id -end \ No newline at end of file +end diff --git a/app/api/houdini/v1/entities/validation_error.rb b/app/api/houdini/v1/entities/validation_error.rb index af9d7342..d275a2f7 100644 --- a/app/api/houdini/v1/entities/validation_error.rb +++ b/app/api/houdini/v1/entities/validation_error.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::Entities::ValidationError < Grape::Entity - expose :params, documentation: {type: 'String', desc: 'Params where the following had an error.', is_array: true} - expose :messages, documentation: {type:'String', desc: 'The validation messages for the params', is_array: true} -end \ No newline at end of file + expose :params, documentation: { type: 'String', desc: 'Params where the following had an error.', is_array: true } + expose :messages, documentation: { type: 'String', desc: 'The validation messages for the params', is_array: true } +end diff --git a/app/api/houdini/v1/entities/validation_errors.rb b/app/api/houdini/v1/entities/validation_errors.rb index 07f03c73..303893b5 100644 --- a/app/api/houdini/v1/entities/validation_errors.rb +++ b/app/api/houdini/v1/entities/validation_errors.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::Entities::ValidationErrors < Grape::Entity - expose :errors, documentation: {type: ValidationError, desc: 'errors', is_array:true} -end \ No newline at end of file + expose :errors, documentation: { type: ValidationError, desc: 'errors', is_array: true } +end diff --git a/app/api/houdini/v1/helpers/application_helper.rb b/app/api/houdini/v1/helpers/application_helper.rb index 0c1345d6..0af8a17d 100644 --- a/app/api/houdini/v1/helpers/application_helper.rb +++ b/app/api/houdini/v1/helpers/application_helper.rb @@ -1,22 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Houdini::V1::Helpers::ApplicationHelper extend Grape::API::Helpers - def session - env['rack.session'] + env['rack.session'] end def protect_against_forgery - unless verified_request? - error!('Unauthorized', 401) - end + error!('Unauthorized', 401) unless verified_request? end def verified_request? !protect_against_forgery? || request.get? || request.head? || - form_authenticity_token == request.headers['X-CSRF-Token'] || - form_authenticity_token == request.headers['X-Csrf-Token'] + form_authenticity_token == request.headers['X-CSRF-Token'] || + form_authenticity_token == request.headers['X-Csrf-Token'] end def form_authenticity_token @@ -24,11 +23,10 @@ module Houdini::V1::Helpers::ApplicationHelper end def protect_against_forgery? - allow_forgery_protection = Rails.configuration.action_controller.allow_forgery_protection + allow_forgery_protection = Rails.configuration.action_controller.allow_forgery_protection allow_forgery_protection.nil? || allow_forgery_protection end - # def rescue_ar_invalid( *class_to_hash) # rescue_with ActiveRecord::RecordInvalid do |error| # output = [] @@ -40,6 +38,4 @@ module Houdini::V1::Helpers::ApplicationHelper # # end # end - end - diff --git a/app/api/houdini/v1/helpers/rescue_helper.rb b/app/api/houdini/v1/helpers/rescue_helper.rb index 458343e3..66de5e36 100644 --- a/app/api/houdini/v1/helpers/rescue_helper.rb +++ b/app/api/houdini/v1/helpers/rescue_helper.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + module Houdini::V1::Helpers::RescueHelper require 'active_support/concern' extend ActiveSupport::Concern include Grape::DSL::Configuration module ClassMethods - def rescue_ar_invalid( *class_to_hash) - rescue_with ActiveRecord::RecordInvalid do |error| - output = [] - error.record.errors do |attr,message| - output.push({params: "#{class_to_hash[error.record.class]}['#{attr}']", - message: message}) + def rescue_ar_invalid(*class_to_hash) + rescue_with ActiveRecord::RecordInvalid do |error| + output = [] + error.record.errors do |attr, message| + output.push(params: "#{class_to_hash[error.record.class]}['#{attr}']", + message: message) + end + raise Grape::Exceptions::ValidationErrors, output end - raise Grape::Exceptions::ValidationErrors.new(output) - - end end end -end \ No newline at end of file +end diff --git a/app/api/houdini/v1/nonprofit.rb b/app/api/houdini/v1/nonprofit.rb index e01bc7cc..39ba746d 100644 --- a/app/api/houdini/v1/nonprofit.rb +++ b/app/api/houdini/v1/nonprofit.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::Nonprofit < Houdini::V1::BaseAPI - helpers Houdini::V1::Helpers::ApplicationHelper, Houdini::V1::Helpers::RescueHelper + helpers Houdini::V1::Helpers::ApplicationHelper, Houdini::V1::Helpers::RescueHelper - before do - protect_against_forgery - end + before do + protect_against_forgery + end desc 'Return a nonprofit.' do success Houdini::V1::Entities::Nonprofit @@ -18,103 +20,92 @@ class Houdini::V1::Nonprofit < Houdini::V1::BaseAPI present np, as: Houdini::V1::Entities::Nonprofit end end - + desc 'Register a nonprofit' do success Houdini::V1::Entities::Nonprofit - #this needs to be a validation an array - failure [{code:400, message:'Validation Errors', model: Houdini::V1::Entities::ValidationErrors}] + # this needs to be a validation an array + failure [{ code: 400, message: 'Validation Errors', model: Houdini::V1::Entities::ValidationErrors }] end params do - - requires :nonprofit, type: Hash do - requires :name, type:String, desc: 'Organization Name', allow_blank: false, documentation: { param_type: 'body' } - optional :website, type:String, desc: 'Organization website URL', allow_blank:true, regexp: URI::regexp, documentation: { param_type: 'body' }, coerce_with: ->(url) { + requires :nonprofit, type: Hash do + requires :name, type: String, desc: 'Organization Name', allow_blank: false, documentation: { param_type: 'body' } + optional :website, type: String, desc: 'Organization website URL', allow_blank: true, regexp: URI::DEFAULT_PARSER.make_regexp, documentation: { param_type: 'body' }, coerce_with: lambda { |url| coerced_url = url - unless (url =~ /\Ahttp:\/\/.*/i || url =~ /\Ahttps:\/\/.*/i) - coerced_url = 'http://'+ coerced_url + unless url =~ %r{\Ahttp://.*}i || url =~ %r{\Ahttps://.*}i + coerced_url = 'http://' + coerced_url end coerced_url } - requires :zip_code, type:String, allow_blank: false, desc: "Organization Address ZIP Code", documentation: { param_type: 'body' } - requires :state_code, type:String, allow_blank: false, desc: "Organization Address State Code", documentation: { param_type: 'body' } - requires :city, type:String, allow_blank: false, desc: "Organization Address City", documentation: { param_type: 'body' } - optional :email, type:String, desc: 'Organization email (public)', regexp: Email::Regex, documentation: { param_type: 'body' } - optional :phone, type:String, desc: 'Organization phone (public)', documentation: { param_type: 'body' } + requires :zip_code, type: String, allow_blank: false, desc: 'Organization Address ZIP Code', documentation: { param_type: 'body' } + requires :state_code, type: String, allow_blank: false, desc: 'Organization Address State Code', documentation: { param_type: 'body' } + requires :city, type: String, allow_blank: false, desc: 'Organization Address City', documentation: { param_type: 'body' } + optional :email, type: String, desc: 'Organization email (public)', regexp: Email::Regex, documentation: { param_type: 'body' } + optional :phone, type: String, desc: 'Organization phone (public)', documentation: { param_type: 'body' } end requires :user, type: Hash do - requires :name, type:String, desc: 'Full name', allow_blank:false, documentation: { param_type: 'body' } - requires :email, type:String, desc: 'Username', allow_blank: false, documentation: { param_type: 'body' } - requires :password, type:String, desc: 'Password', allow_blank: false, is_equal_to: :password_confirmation, documentation: { param_type: 'body' } - requires :password_confirmation, type:String, desc: 'Password confirmation', allow_blank: false, documentation: { param_type: 'body' } + requires :name, type: String, desc: 'Full name', allow_blank: false, documentation: { param_type: 'body' } + requires :email, type: String, desc: 'Username', allow_blank: false, documentation: { param_type: 'body' } + requires :password, type: String, desc: 'Password', allow_blank: false, is_equal_to: :password_confirmation, documentation: { param_type: 'body' } + requires :password_confirmation, type: String, desc: 'Password confirmation', allow_blank: false, documentation: { param_type: 'body' } end - - end post do declared_params = declared(params) np = nil u = nil Qx.transaction do + np = Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(declared_params[:nonprofit])) + begin - np = Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(declared_params[:nonprofit])) - - begin - np.save! - rescue ActiveRecord::RecordInvalid => e - if (e.record.errors[:slug]) - begin - slug = SlugNonprofitNamingAlgorithm.new(np.state_code_slug, np.city_slug).create_copy_name(np.slug) - np.slug = slug - np.save! - rescue UnableToCreateNameCopyError - raise Grape::Exceptions::ValidationErrors.new(errors:[Grape::Exceptions::Validation.new( - - params: ["nonprofit[name]"], - message: "has an invalid slug. Contact support for help." - )]) - end - else - raise e - end - end - - u = User.new(declared_params[:user]) - u.save! - - role = u.roles.build(host: np, name: 'nonprofit_admin') - role.save! - - billing_plan = BillingPlan.find(Settings.default_bp.id) - b_sub = np.build_billing_subscription(billing_plan: billing_plan, status: 'active') - b_sub.save! + np.save! rescue ActiveRecord::RecordInvalid => e - class_to_name = {Nonprofit => 'nonprofit', User => 'user'} - if class_to_name[e.record.class] - errors = e.record.errors.keys.map {|k| - - errors = e.record.errors[k].uniq - errors.map{|error| Grape::Exceptions::Validation.new( - - params: ["#{class_to_name[e.record.class]}[#{k.to_s}]"], - message: error - - )} - } - - raise Grape::Exceptions::ValidationErrors.new(errors:errors.flatten) + if e.record.errors[:slug] + begin + slug = SlugNonprofitNamingAlgorithm.new(np.state_code_slug, np.city_slug).create_copy_name(np.slug) + np.slug = slug + np.save! + rescue UnableToCreateNameCopyError + raise Grape::Exceptions::ValidationErrors.new(errors: [Grape::Exceptions::Validation.new( + params: ['nonprofit[name]'], + message: 'has an invalid slug. Contact support for help.' + )]) + end else raise e end + end + u = User.new(declared_params[:user]) + u.save! + + role = u.roles.build(host: np, name: 'nonprofit_admin') + role.save! + + billing_plan = BillingPlan.find(Settings.default_bp.id) + b_sub = np.build_billing_subscription(billing_plan: billing_plan, status: 'active') + b_sub.save! + rescue ActiveRecord::RecordInvalid => e + class_to_name = { Nonprofit => 'nonprofit', User => 'user' } + if class_to_name[e.record.class] + errors = e.record.errors.keys.map do |k| + errors = e.record.errors[k].uniq + errors.map do |error| + Grape::Exceptions::Validation.new( + params: ["#{class_to_name[e.record.class]}[#{k}]"], + message: error + ) + end + end + + raise Grape::Exceptions::ValidationErrors.new(errors: errors.flatten) + else + raise e end end - #onboard callback + # onboard callback present np, with: Houdini::V1::Entities::Nonprofit end - - - -end \ No newline at end of file +end diff --git a/app/api/houdini/v1/validations.rb b/app/api/houdini/v1/validations.rb index eb0e60b6..692a5bed 100644 --- a/app/api/houdini/v1/validations.rb +++ b/app/api/houdini/v1/validations.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require 'houdini/v1/validators/is_equal_to' \ No newline at end of file +require 'houdini/v1/validators/is_equal_to' diff --git a/app/api/houdini/v1/validators/is_equal_to.rb b/app/api/houdini/v1/validators/is_equal_to.rb index c84b8075..73faf52b 100644 --- a/app/api/houdini/v1/validators/is_equal_to.rb +++ b/app/api/houdini/v1/validators/is_equal_to.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Houdini::V1::Validators::IsEqualTo < Grape::Validations::Base def validate_param!(attr_name, params) if params[attr_name] != params[@option] - fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name), @scope.full_name(@option)], message: message(:is_equal_to) + raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name), @scope.full_name(@option)], message: message(:is_equal_to) end end -end \ No newline at end of file +end diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index c2028140..09bc4472 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ActivitiesController < ApplicationController + before_action :authenticate_user!, only: [:create] - before_action :authenticate_user!, only: [:create] - - def create - json_saved Activity.create(params[:activity]) - end - + def create + json_saved Activity.create(params[:activity]) + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09be7bba..009393af 100755 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,174 +1,178 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ApplicationController < ActionController::Base - before_action :set_locale, :redirect_to_maintenance + before_action :set_locale, :redirect_to_maintenance - protect_from_forgery + protect_from_forgery - helper_method \ - :current_role?, - :current_nonprofit_user?, - :administered_nonprofit, + helper_method \ + :current_role?, + :current_nonprofit_user?, + :administered_nonprofit, :nonprofit_in_trial?, - :current_plan_tier #int + :current_plan_tier # int - def set_locale - if params[:locale] && Settings.available_locales.include?(params[:locale]) - I18n.locale = params[:locale] - else - I18n.locale = Settings.language - end - end + def set_locale + if params[:locale] && Settings.available_locales.include?(params[:locale]) + I18n.locale = params[:locale] + else + I18n.locale = Settings.language + end + end - def redirect_to_maintenance - if (Settings&.maintenance&.maintenance_mode && !current_user) - unless (self.class == Users::SessionsController && - ((Settings.maintenance.maintenance_token && params[:maintenance_token] == Settings.maintenance.maintenance_token) || params[:format] == 'json')) - redirect_to Settings.maintenance.maintenance_page - end - end - end + def redirect_to_maintenance + if Settings&.maintenance&.maintenance_mode && !current_user + unless self.class == Users::SessionsController && + ((Settings.maintenance.maintenance_token && params[:maintenance_token] == Settings.maintenance.maintenance_token) || params[:format] == 'json') + redirect_to Settings.maintenance.maintenance_page + end + end + end -protected + protected - def json_saved(model, msg=nil) - if model.valid? - flash[:notice] = msg if msg - render json: model, status: 200 - else - render json: model.errors.full_messages, status: :unprocessable_entity - end - end + def json_saved(model, msg = nil) + if model.valid? + flash[:notice] = msg if msg + render json: model, status: 200 + else + render json: model.errors.full_messages, status: :unprocessable_entity + end + end # A response helper for use with the param_validation gem # use like: render_json{ UpdateUsers.update(params[:user]) } # will catch and pretty print exceptions using the rails loggers def render_json(&block) begin - result = {status: 200, json: yield(block)} + result = { status: 200, json: yield(block) } rescue ParamValidation::ValidationError => e logger.info "422: #{e}".red.bold - #logger.info ">>".bold.red + " #{{'Failed key name' => e.data[:key], 'Value' => e.data[:val], 'Failed validator' => e.data[:name]}}".red - result = {status: 422, json: {error: e.message}} - rescue CCOrgError => e - logger.info "422: #{e}".red.bold - result = {status: 422, json: {error: e.message}} + # logger.info ">>".bold.red + " #{{'Failed key name' => e.data[:key], 'Value' => e.data[:val], 'Failed validator' => e.data[:name]}}".red + result = { status: 422, json: { error: e.message } } + rescue CCOrgError => e + logger.info "422: #{e}".red.bold + result = { status: 422, json: { error: e.message } } rescue ActiveRecord::RecordNotFound => e logger.info "404: #{e}".red.bold - result = {status: 404, json: {error: e.message}} - rescue AuthenticationError => e - logger.info "401: #{e}".red.bold - result = {status: 401, json: {error: e.message}} - rescue ExpiredTokenError => e - logger.info "422: #{e}".red.bold - result = {status: 422, json: {error: e.message}} + result = { status: 404, json: { error: e.message } } + rescue AuthenticationError => e + logger.info "401: #{e}".red.bold + result = { status: 401, json: { error: e.message } } + rescue ExpiredTokenError => e + logger.info "422: #{e}".red.bold + result = { status: 422, json: { error: e.message } } rescue Exception => e # a non-validation related exception logger.error "500: #{e}".red.bold - logger.error e.backtrace.take(5).map{|l| ">>".red.bold + " #{l}"}.join("\n").red - result = {status: 500, json: {error: e.message, backtrace: e.backtrace}} + logger.error e.backtrace.take(5).map { |l| '>>'.red.bold + " #{l}" }.join("\n").red + result = { status: 500, json: { error: e.message, backtrace: e.backtrace } } end render result end - # Test that within the last 5 minutes, the user has confirmed their password - def password_was_confirmed(token) - session[:pw_token] == token && Chronic.parse(session[:pw_timestamp]) >= 5.minutes.ago.utc - end + # Test that within the last 5 minutes, the user has confirmed their password + def password_was_confirmed(token) + session[:pw_token] == token && Chronic.parse(session[:pw_timestamp]) >= 5.minutes.ago.utc + end - def store_location - referrer = request.fullpath - no_redirects = ['/users', '/signup', '/signin', '/users/sign_in', '/users/sign_up', '/users/password', '/users/sign_out', /.*\.json.*/, /.*auth\/facebook.*/] - unless request.format.symbol == :json || no_redirects.map{|p| referrer.match(p)}.any? - session[:previous_url] = referrer - end - end + def store_location + referrer = request.fullpath + no_redirects = ['/users', '/signup', '/signin', '/users/sign_in', '/users/sign_up', '/users/password', '/users/sign_out', /.*\.json.*/, %r{.*auth/facebook.*}] + unless request.format.symbol == :json || no_redirects.map { |p| referrer.match(p) }.any? + session[:previous_url] = referrer + end + end - def block_with_sign_in(msg=nil) - store_location + def block_with_sign_in(msg = nil) + store_location if current_user flash[:notice] = "It looks like you're not allowed to access that page. If this seems like a mistake, please contact #{Settings.mailer.email}" redirect_to root_path else msg ||= 'We need to sign you in before you can do that.' - redirect_to new_user_session_path, :flash => {:error => msg} + redirect_to new_user_session_path, flash: { error: msg } end - end + end - def authenticate_user!(options={}) - block_with_sign_in unless current_user - end + def authenticate_user!(_options = {}) + block_with_sign_in unless current_user + end - def authenticate_confirmed_user! - if !current_user - block_with_sign_in - elsif !current_user.confirmed? && !current_role?([:super_associate, :super_admin]) - redirect_to new_user_confirmation_path, flash: {error: 'You need to confirm your account to do that.'} - end - end + def authenticate_confirmed_user! + if !current_user + block_with_sign_in + elsif !current_user.confirmed? && !current_role?(%i[super_associate super_admin]) + redirect_to new_user_confirmation_path, flash: { error: 'You need to confirm your account to do that.' } + end + end - def authenticate_super_associate! - unless current_role?(:super_admin) || current_role?(:super_associate) - block_with_sign_in 'Please login.' - end - end + def authenticate_super_associate! + unless current_role?(:super_admin) || current_role?(:super_associate) + block_with_sign_in 'Please login.' + end + end - def authenticate_super_admin! - unless current_role?(:super_admin) - block_with_sign_in 'Please login.' - end - end + def authenticate_super_admin! + block_with_sign_in 'Please login.' unless current_role?(:super_admin) + end - def current_role?(role_names, host_id = nil) + def current_role?(role_names, host_id = nil) return false unless current_user - role_names = Array(role_names) - key = "current_role_user_#{current_user_id}_names_#{role_names.join("_")}_host_#{host_id}" - QueryRoles.user_has_role?(current_user.id, role_names, host_id) - end - def nonprofit_in_trial?(npo_id=nil) + role_names = Array(role_names) + key = "current_role_user_#{current_user_id}_names_#{role_names.join('_')}_host_#{host_id}" + QueryRoles.user_has_role?(current_user.id, role_names, host_id) + end + + def nonprofit_in_trial?(npo_id = nil) return false if !npo_id && !administered_nonprofit + npo_id ||= administered_nonprofit.id key = "in_trial_user_#{current_user_id}_nonprofit_#{npo_id}" QueryBillingSubscriptions.currently_in_trial?(npo_id) end - def current_plan_tier(npo_id=nil) + def current_plan_tier(npo_id = nil) return 0 if !npo_id && !administered_nonprofit + npo_id ||= administered_nonprofit.id - return 2 if current_role?(:super_admin) - key = "plan_tier_user_#{current_user_id}_nonprofit_#{npo_id}" + return 2 if current_role?(:super_admin) + + key = "plan_tier_user_#{current_user_id}_nonprofit_#{npo_id}" administered_nonprofit ? QueryBillingSubscriptions.plan_tier(npo_id) : 0 - end + end - def administered_nonprofit - return nil unless current_user - key = "administered_nonprofit_user_#{current_user_id}_nonprofit" - Nonprofit.where(id: QueryRoles.host_ids(current_user_id, [:nonprofit_admin, :nonprofit_associate])).last - end + def administered_nonprofit + return nil unless current_user - # devise config + key = "administered_nonprofit_user_#{current_user_id}_nonprofit" + Nonprofit.where(id: QueryRoles.host_ids(current_user_id, %i[nonprofit_admin nonprofit_associate])).last + end - def after_sign_in_path_for(resource) - request.env['omniauth.origin'] || session[:previous_url] || root_path - end + # devise config - def after_sign_up_path_for(resource) - request.env['omniauth.origin'] || session[:previous_url] || root_path - end + def after_sign_in_path_for(_resource) + request.env['omniauth.origin'] || session[:previous_url] || root_path + end - def after_update_path_for(resource) - profile_path(current_user.profile) - end + def after_sign_up_path_for(_resource) + request.env['omniauth.origin'] || session[:previous_url] || root_path + end - def after_inactive_sign_up_path_for(resource) - profile_path(current_user.profile) - end + def after_update_path_for(_resource) + profile_path(current_user.profile) + end - # /devise config + def after_inactive_sign_up_path_for(_resource) + profile_path(current_user.profile) + end -private + # /devise config - def current_user_id - current_user && current_user.id - end + private + def current_user_id + current_user&.id + end end diff --git a/app/controllers/aws_presigned_posts_controller.rb b/app/controllers/aws_presigned_posts_controller.rb index a6855266..b3ed7388 100644 --- a/app/controllers/aws_presigned_posts_controller.rb +++ b/app/controllers/aws_presigned_posts_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AwsPresignedPostsController < ApplicationController before_action :authenticate_user! @@ -7,12 +9,12 @@ class AwsPresignedPostsController < ApplicationController # http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/PresignedPost.html def create uuid = SecureRandom.uuid - p = S3Bucket.presigned_post({ + p = S3Bucket.presigned_post( key: "tmp/#{uuid}/${filename}", success_action_status: 201, acl: 'public-read', expiration: 30.days.from_now - }) + ) render json: { s3_presigned_post: p.fields.to_json, @@ -20,5 +22,4 @@ class AwsPresignedPostsController < ApplicationController s3_uuid: uuid } end - end diff --git a/app/controllers/billing_subscriptions_controller.rb b/app/controllers/billing_subscriptions_controller.rb index cee634ed..258d3756 100644 --- a/app/controllers/billing_subscriptions_controller.rb +++ b/app/controllers/billing_subscriptions_controller.rb @@ -1,30 +1,32 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BillingSubscriptionsController < ApplicationController - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! def create_trial - render JsonResp.new(params){|params| + render JsonResp.new(params) do |_params| requires(:nonprofit_id).as_int requires(:stripe_plan_id).as_string - }.when_valid{|params| + end.when_valid do |params| InsertBillingSubscriptions.trial(params[:nonprofit_id], params[:stripe_plan_id]) - } + end end - def create + def create @nonprofit ||= Nonprofit.find(params[:nonprofit_id]) - @subscription = BillingSubscription.create_with_stripe(@nonprofit, params[:billing_subscription]) - json_saved(@subscription, "Success! You are subscribed to #{Settings.general.name}.") - end + @subscription = BillingSubscription.create_with_stripe(@nonprofit, params[:billing_subscription]) + json_saved(@subscription, "Success! You are subscribed to #{Settings.general.name}.") + end # post /nonprofits/:nonprofit_id/billing_subscription/cancel - def cancel - @result = CancelBillingSubscription.with_stripe(@nonprofit) - flash[:notice] = "Your subscription has been cancelled. We'll email you soon with exports." + def cancel + @result = CancelBillingSubscription.with_stripe(@nonprofit) + flash[:notice] = "Your subscription has been cancelled. We'll email you soon with exports." redirect_to root_url - end + end # get nonprofits/:nonprofit_id/billing_subscription/cancellation def cancellation diff --git a/app/controllers/button_debug_controller.rb b/app/controllers/button_debug_controller.rb index 9194b0a8..53d8a892 100644 --- a/app/controllers/button_debug_controller.rb +++ b/app/controllers/button_debug_controller.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ButtonDebugController < ApplicationController def embedded @np = params[:id] || 1 - respond_to { |format| format.html{render layout: 'layouts/empty'} } + respond_to { |format| format.html { render layout: 'layouts/empty' } } end def button @np = params[:id] || 1 - respond_to { |format| format.html{render layout: 'layouts/empty'} } + respond_to { |format| format.html { render layout: 'layouts/empty' } } end end diff --git a/app/controllers/campaign_gift_options_controller.rb b/app/controllers/campaign_gift_options_controller.rb index 044aab0b..83a19633 100644 --- a/app/controllers/campaign_gift_options_controller.rb +++ b/app/controllers/campaign_gift_options_controller.rb @@ -1,29 +1,31 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGiftOptionsController < ApplicationController - include Controllers::CampaignHelper + include Controllers::CampaignHelper - before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order] + before_action :authenticate_campaign_editor!, only: %i[create destroy update update_order] - def index - @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') - render json: {data: @gift_options} - end + def index + @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') + render json: { data: @gift_options } + end - def show - render json: {data: current_campaign.campaign_gift_options.find(params[:id])} - end + def show + render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } + end - def create - campaign = current_campaign - json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), - 'Gift option successfully created!' - end + def create + campaign = current_campaign + json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), + 'Gift option successfully created!' + end - def update - @campaign = current_campaign - gift_option = @campaign.campaign_gift_options.find params[:id] - json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' - end + def update + @campaign = current_campaign + gift_option = @campaign.campaign_gift_options.find params[:id] + json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' + end # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order # Pass in {data: [{id: 1, order: 1}]} @@ -32,9 +34,9 @@ class CampaignGiftOptionsController < ApplicationController render json: updated_gift_options end - def destroy - @campaign = current_campaign + def destroy + @campaign = current_campaign - render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id])} - end + render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id]) } + end end diff --git a/app/controllers/campaign_gifts_controller.rb b/app/controllers/campaign_gifts_controller.rb index 786173ff..30006e25 100644 --- a/app/controllers/campaign_gifts_controller.rb +++ b/app/controllers/campaign_gifts_controller.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGiftsController < ApplicationController - # post /campaign_gifts - def create - json_saved CreateCampaignGift.create params[:campaign_gift] - end + def create + json_saved CreateCampaignGift.create params[:campaign_gift] + end end diff --git a/app/controllers/campaigns/campaign_gift_options_controller.rb b/app/controllers/campaigns/campaign_gift_options_controller.rb index eba8451d..c9339d83 100644 --- a/app/controllers/campaigns/campaign_gift_options_controller.rb +++ b/app/controllers/campaigns/campaign_gift_options_controller.rb @@ -1,51 +1,51 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Campaigns; class CampaignGiftOptionsController < ApplicationController - include Controllers::CampaignHelper +module Campaigns + class CampaignGiftOptionsController < ApplicationController + include Controllers::CampaignHelper - before_action :authenticate_campaign_editor!, only: [:create, :destroy, :update, :update_order, :report] + before_action :authenticate_campaign_editor!, only: %i[create destroy update update_order report] - def report - respond_to do |format| - format.json do - render json: QueryCampaignGifts.report_metrics(current_campaign.id) - end - end - end + def report + respond_to do |format| + format.json do + render json: QueryCampaignGifts.report_metrics(current_campaign.id) + end + end + end + def index + @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') + render json: { data: @gift_options } + end + def show + render json: { data: current_campaign.campaign_gift_options.find(params[:id]) } + end - def index - @gift_options = current_campaign.campaign_gift_options.order('"order", amount_recurring, amount_one_time') - render json: {data: @gift_options} - end + def create + campaign = current_campaign + json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), + 'Gift option successfully created!' + end - def show - render json: {data: current_campaign.campaign_gift_options.find(params[:id])} - end + def update + @campaign = current_campaign + gift_option = @campaign.campaign_gift_options.find params[:id] + json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' + end - def create - campaign = current_campaign - json_saved CreateCampaignGiftOption.create(campaign, params[:campaign_gift_option]), - 'Gift option successfully created!' - end + # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order + # Pass in {data: [{id: 1, order: 1}]} + def update_order + updated_gift_options = UpdateOrder.with_data('campaign_gift_options', params[:data]) + render json: updated_gift_options + end - def update - @campaign = current_campaign - gift_option = @campaign.campaign_gift_options.find params[:id] - json_saved UpdateCampaignGiftOption.update(gift_option, params[:campaign_gift_option]), 'Successfully updated' - end - - # put /nonprofits/:nonprofit_id/campaigns/:campaign_id/campaign_gift_options/update_order - # Pass in {data: [{id: 1, order: 1}]} - def update_order - updated_gift_options = UpdateOrder.with_data('campaign_gift_options', params[:data]) - render json: updated_gift_options - end - - def destroy - @campaign = current_campaign - - render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id])} - end + def destroy + @campaign = current_campaign + render_json { DeleteCampaignGiftOption.delete(@campaign, params[:id]) } + end end; end diff --git a/app/controllers/campaigns/donations_controller.rb b/app/controllers/campaigns/donations_controller.rb index a53c0f3d..9cb40393 100644 --- a/app/controllers/campaigns/donations_controller.rb +++ b/app/controllers/campaigns/donations_controller.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Campaigns -class DonationsController < ApplicationController - include Controllers::CampaignHelper + class DonationsController < ApplicationController + include Controllers::CampaignHelper - before_action :authenticate_campaign_editor!, only: [:index] - - def index - respond_to do |format| - format.csv do - file_date = Date.today.strftime("%m-%d-%Y") - donations = QueryDonations.campaign_export(current_campaign.id) - send_data(Format::Csv.from_vectors(donations), filename: "campaign-donations-#{file_date}.csv") - end - end - end + before_action :authenticate_campaign_editor!, only: [:index] -end + def index + respond_to do |format| + format.csv do + file_date = Date.today.strftime('%m-%d-%Y') + donations = QueryDonations.campaign_export(current_campaign.id) + send_data(Format::Csv.from_vectors(donations), filename: "campaign-donations-#{file_date}.csv") + end + end + end + end end diff --git a/app/controllers/campaigns/supporters_controller.rb b/app/controllers/campaigns/supporters_controller.rb index 5f77ffd0..a52fb608 100644 --- a/app/controllers/campaigns/supporters_controller.rb +++ b/app/controllers/campaigns/supporters_controller.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Campaigns -class SupportersController < ApplicationController - include Controllers::CampaignHelper + class SupportersController < ApplicationController + include Controllers::CampaignHelper - before_action :authenticate_campaign_editor!, only: [:index] + before_action :authenticate_campaign_editor!, only: [:index] - def index - @panels_layout = true - @nonprofit = current_nonprofit - @campaign = current_campaign - - respond_to do |format| - format.json do - render json: QuerySupporters.campaign_list(@nonprofit.id, @campaign.id, params) - end - format.html - end - end + def index + @panels_layout = true + @nonprofit = current_nonprofit + @campaign = current_campaign -end + respond_to do |format| + format.json do + render json: QuerySupporters.campaign_list(@nonprofit.id, @campaign.id, params) + end + format.html + end + end + end end diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index a6d34d21..9868de95 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -1,15 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignsController < ApplicationController include Controllers::CampaignHelper helper_method :current_campaign_editor? - before_action :authenticate_confirmed_user!, only: [:create, :name_and_id, :duplicate] - before_action :authenticate_campaign_editor!, only: [:update, :soft_delete] - before_action :check_nonprofit_status, only: [:index, :show] + before_action :authenticate_confirmed_user!, only: %i[create name_and_id duplicate] + before_action :authenticate_campaign_editor!, only: %i[update soft_delete] + before_action :check_nonprofit_status, only: %i[index show] def index @nonprofit = current_nonprofit - if (current_nonprofit_user?) + if current_nonprofit_user? @campaigns = @nonprofit.campaigns.includes(:nonprofit).not_deleted.order('created_at desc') @deleted_campaigns = @nonprofit.campaigns.includes(:nonprofit).deleted.order('created_at desc') else @@ -70,14 +72,11 @@ class CampaignsController < ApplicationController # post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate' def duplicate - - render_json { + render_json do InsertDuplicate.campaign(current_campaign.id, current_user.profile.id) - } - + end end - def soft_delete current_campaign.update_attribute(:deleted, params[:delete]) render json: {} @@ -101,17 +100,17 @@ class CampaignsController < ApplicationController end def peer_to_peer - session[:donor_signup_url] = request.env["REQUEST_URI"] + session[:donor_signup_url] = request.env['REQUEST_URI'] @nonprofit = Nonprofit.find_by_id(params[:npo_id]) @parent_campaign = Campaign.find_by_id(params[:campaign_id]) if params[:campaign_id].present? && !@parent_campaign - raise ActionController::RoutingError.new('Not Found') + raise ActionController::RoutingError, 'Not Found' end if current_user @profile = current_user.profile - if (@parent_campaign) + if @parent_campaign @child_campaign = Campaign.where( profile_id: @profile.id, parent_campaign_id: @parent_campaign.id @@ -124,7 +123,7 @@ class CampaignsController < ApplicationController def check_nonprofit_status if !current_role?(:super_admin) && !current_nonprofit.published - raise ActionController::RoutingError.new('Not Found') + raise ActionController::RoutingError, 'Not Found' end end end diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index bcd7c72b..2d13af20 100755 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -1,22 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CardsController < ApplicationController + before_action :authenticate_user!, except: [:create] - before_action :authenticate_user!, :except => [:create] - - # post /cards - def create + # post /cards + def create acct = Supporter.find(params[:card][:holder_id]).nonprofit.stripe_account_id render( - JsonResp.new(params) do |d| + JsonResp.new(params) do |_d| requires(:card).nested do requires(:name, :stripe_card_token).as_string requires(:holder_id).as_int requires(:holder_type).one_of('Supporter') end end.when_valid do |d| - InsertCard.with_stripe(d[:card], acct, params[:event_id], current_user) + InsertCard.with_stripe(d[:card], acct, params[:event_id], current_user) end ) - end - + end end diff --git a/app/controllers/direct_debit_details_controller.rb b/app/controllers/direct_debit_details_controller.rb index ea9e00bb..52c7426d 100644 --- a/app/controllers/direct_debit_details_controller.rb +++ b/app/controllers/direct_debit_details_controller.rb @@ -1,19 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class DirectDebitDetailsController < ApplicationController - - # POST /sepa # This endpoint is used for saving direct debit account details # when SEPA payment is selected in the donation widget. Actual charge is # happening offline, after donations are exported to an external CRM. def create render( - JsonResp.new(params) do |data| + JsonResp.new(params) do |_data| requires(:supporter_id).as_int requires(:sepa_params).nested do requires(:iban, :name, :bic).as_string end - end.when_valid do |data| + end.when_valid do |_data| InsertDirectDebitDetail.execute(params) end ) diff --git a/app/controllers/email_settings_controller.rb b/app/controllers/email_settings_controller.rb index 1c94c8b2..c376e30c 100644 --- a/app/controllers/email_settings_controller.rb +++ b/app/controllers/email_settings_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailSettingsController < ApplicationController include Controllers::NonprofitHelper @@ -15,6 +17,4 @@ class EmailSettingsController < ApplicationController user = current_role?(:super_admin) ? User.find(params[:user_id]) : current_user render json: UpdateEmailSettings.save(params[:nonprofit_id], user.id, params[:email_settings]) end - end - diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb index 60c2b324..95e19c7f 100644 --- a/app/controllers/emails_controller.rb +++ b/app/controllers/emails_controller.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailsController < ApplicationController - before_action :authenticate_user! - - def create - email = params[:email] - GenericMailer.delay.generic_mail(email[:from_email], email[:from_name], email[:message], email[:subject], email[:to_email], email[:to_name]) - render :json => {:notification => 'Email successfully sent'}, :status => :created - end + before_action :authenticate_user! + def create + email = params[:email] + GenericMailer.delay.generic_mail(email[:from_email], email[:from_name], email[:message], email[:subject], email[:to_email], email[:to_name]) + render json: { notification: 'Email successfully sent' }, status: :created + end end diff --git a/app/controllers/event_discounts_controller.rb b/app/controllers/event_discounts_controller.rb index 167637c2..c696d872 100644 --- a/app/controllers/event_discounts_controller.rb +++ b/app/controllers/event_discounts_controller.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventDiscountsController < ApplicationController include Controllers::EventHelper - before_action :authenticate_event_editor!, :except => [:index] + before_action :authenticate_event_editor!, except: [:index] def create params[:event_discount][:event_id] = current_event.id - render JsonResp.new(params[:event_discount]){|data| + render JsonResp.new(params[:event_discount]) do |_data| requires(:code, :name).as_string requires(:event_id, :percent).as_int - }.when_valid{|data| + end.when_valid do |data| { status: 200, json: { event_discount: current_event.event_discounts.create(data) } } - } + end end def index @@ -26,15 +28,14 @@ class EventDiscountsController < ApplicationController .returning('*') ).first ) - render json: {status: 200, data: discount } + render json: { status: 200, data: discount } end def destroy Psql.execute( - Qexpr.new.delete_from("event_discounts") - .where("event_discounts.event_id=$id", id: params["event_id"]) - .where("event_discounts.id=$id", id: params["id"]) + Qexpr.new.delete_from('event_discounts') + .where('event_discounts.event_id=$id', id: params['event_id']) + .where('event_discounts.id=$id', id: params['id']) ) end - end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index b0c82467..2817c9c7 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -1,21 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventsController < ApplicationController - include Controllers::EventHelper + include Controllers::EventHelper - helper_method :current_event_editor? + helper_method :current_event_editor? before_action :authenticate_nonprofit_user!, only: :name_and_id - before_action :authenticate_event_editor!, only: [:update, :soft_delete, :stats, :create, :duplicate] + before_action :authenticate_event_editor!, only: %i[update soft_delete stats create duplicate] - - def index + def index @nonprofit = current_nonprofit - end + end def listings render json: QueryEventMetrics.for_listings('nonprofit', current_nonprofit.id, params) end - def show + def show @event = params[:event_slug] ? Event.find_by_slug!(params[:event_slug]) : Event.find_by_id!(params[:id]) @event_background_image = FetchBackgroundImage.with_model(@event) @nonprofit = @event.nonprofit @@ -24,10 +25,10 @@ class EventsController < ApplicationController flash[:notice] = "Sorry, we couldn't find that event" return end - @organizer = QueryEventOrganizer.with_event(@event.id) - end + @organizer = QueryEventOrganizer.with_event(@event.id) + end - def create + def create render_json do Time.use_zone(current_nonprofit.timezone || 'UTC') do params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present? @@ -35,22 +36,22 @@ class EventsController < ApplicationController end flash[:notice] = 'Your draft event has been created! Well done.' ev = current_nonprofit.events.create(params[:event]) - {url: "/events/#{ev.slug}", event: ev} + { url: "/events/#{ev.slug}", event: ev } end - end + end - def update + def update Time.use_zone(current_nonprofit.timezone || 'UTC') do params[:event][:start_datetime] = Chronic.parse(params[:event][:start_datetime]) if params[:event][:start_datetime].present? params[:event][:end_datetime] = Chronic.parse(params[:event][:end_datetime]) if params[:event][:end_datetime].present? end - current_event.update_attributes(params[:event]) - json_saved current_event, 'Successfully updated' - end + current_event.update_attributes(params[:event]) + json_saved current_event, 'Successfully updated' + end # post 'nonprofits/:np_id/events/:event_id/duplicate' def duplicate - render_json { InsertDuplicate.event(current_event.id, current_user.profile.id)} + render_json { InsertDuplicate.event(current_event.id, current_user.profile.id) } end def activities @@ -58,24 +59,22 @@ class EventsController < ApplicationController end def soft_delete - current_event.update_attribute(:deleted, params[:delete]) - render json: {} - end + current_event.update_attribute(:deleted, params[:delete]) + render json: {} + end - def metrics + def metrics render json: QueryEventMetrics.with_event_ids([current_event.id]).first - end + end - def stats - @event = current_event - @url = Format::Url.concat(root_url, @event.url) - @event_background_image = FetchBackgroundImage.with_model(@event) - render layout: 'layouts/embed' - end + def stats + @event = current_event + @url = Format::Url.concat(root_url, @event.url) + @event_background_image = FetchBackgroundImage.with_model(@event) + render layout: 'layouts/embed' + end def name_and_id render json: QueryEvents.name_and_id(current_nonprofit.id) end - - end diff --git a/app/controllers/front_controller.rb b/app/controllers/front_controller.rb index e43cf7b7..da3b077f 100755 --- a/app/controllers/front_controller.rb +++ b/app/controllers/front_controller.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FrontController < ApplicationController def index - if !Nonprofit.any? - redirect_to onboard_path - elsif current_role?([:nonprofit_admin,:nonprofit_associate]) - redirect_to NonprofitPath.dashboard(administered_nonprofit) - elsif current_user - redirect_to '/profiles/' + current_user.profile.id.to_s - else - redirect_to new_user_session_path - end - end + if Nonprofit.none? + redirect_to onboard_path + elsif current_role?(%i[nonprofit_admin nonprofit_associate]) + redirect_to NonprofitPath.dashboard(administered_nonprofit) + elsif current_user + redirect_to '/profiles/' + current_user.profile.id.to_s + else + redirect_to new_user_session_path + end + end end diff --git a/app/controllers/image_attachments_controller.rb b/app/controllers/image_attachments_controller.rb index 9f47cbbd..fc1d7b13 100644 --- a/app/controllers/image_attachments_controller.rb +++ b/app/controllers/image_attachments_controller.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ImageAttachmentsController < ApplicationController - before_action :authenticate_confirmed_user! - def create - # must return json with a link attr - # http://editor.froala.com/server-integrations/php-image-upload - @image = ImageAttachment.new(:file => params[:file]) - if @image.save - render :json => {:link => @image.file_url} - else - render :json => @image.errors.full_messages, :status => :unprocessable_entity - end - end + before_action :authenticate_confirmed_user! + def create + # must return json with a link attr + # http://editor.froala.com/server-integrations/php-image-upload + @image = ImageAttachment.new(file: params[:file]) + if @image.save + render json: { link: @image.file_url } + else + render json: @image.errors.full_messages, status: :unprocessable_entity + end + end - def remove - @image = ImageAttachment.select{|img| img.file_url == params[:src]}.first - if @image - @image.destroy - render :json => @image - else - render :json => {}, :status => :unprocessable_entity - end - end + def remove + @image = ImageAttachment.select { |img| img.file_url == params[:src] }.first + if @image + @image.destroy + render json: @image + else + render json: {}, status: :unprocessable_entity + end + end end diff --git a/app/controllers/maps_controller.rb b/app/controllers/maps_controller.rb index 1e5df927..2982879a 100644 --- a/app/controllers/maps_controller.rb +++ b/app/controllers/maps_controller.rb @@ -1,34 +1,34 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class MapsController < ApplicationController - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper - before_action :authenticate_super_associate!, only: :all_supporters - before_action :authenticate_nonprofit_user!, only: [:all_npo_supporters, :specific_npo_supporters] + before_action :authenticate_super_associate!, only: :all_supporters + before_action :authenticate_nonprofit_user!, only: %i[all_npo_supporters specific_npo_supporters] - # used on admin/nonprofits_map and front page - def all_npos - respond_to do |format| - format.html { redirect_to :root } - format.json { @map_data = Nonprofit.where("latitude IS NOT NULL").last(1000) } - end - end + # used on admin/nonprofits_map and front page + def all_npos + respond_to do |format| + format.html { redirect_to :root } + format.json { @map_data = Nonprofit.where('latitude IS NOT NULL').last(1000) } + end + end - # used on admin/supporters_map - def all_supporters - @map_data = Supporter.where("latitude IS NOT NULL").last(1000) - end - - # used on npo dashboard - def all_npo_supporters - @map_data = Nonprofit.find(params['npo_id']).supporters.where("latitude IS NOT NULL").last(100) - end - - # used on supporter dashboard - def specific_npo_supporters - supporter_ids = params['supporter_ids'].split(",").map { |s| s.to_i } - supporters = Nonprofit.find(params['npo_id']).supporters.find(supporter_ids).last(500) - @map_data = supporters.map{|s| s if s.latitude != ''} - end + # used on admin/supporters_map + def all_supporters + @map_data = Supporter.where('latitude IS NOT NULL').last(1000) + end + # used on npo dashboard + def all_npo_supporters + @map_data = Nonprofit.find(params['npo_id']).supporters.where('latitude IS NOT NULL').last(100) + end + # used on supporter dashboard + def specific_npo_supporters + supporter_ids = params['supporter_ids'].split(',').map(&:to_i) + supporters = Nonprofit.find(params['npo_id']).supporters.find(supporter_ids).last(500) + @map_data = supporters.map { |s| s if s.latitude != '' } + end end diff --git a/app/controllers/nonprofits/activities_controller.rb b/app/controllers/nonprofits/activities_controller.rb index 87696c3a..d5d6b652 100644 --- a/app/controllers/nonprofits/activities_controller.rb +++ b/app/controllers/nonprofits/activities_controller.rb @@ -1,14 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class ActivitiesController < ApplicationController - include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + class ActivitiesController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_nonprofit_user! # get /nonprofits/:nonprofit_id/supporters/:supporter_id/activities def index render json: QueryActivities.for_timeline(params[:nonprofit_id], params[:supporter_id]) end - - end + end end - diff --git a/app/controllers/nonprofits/bank_accounts_controller.rb b/app/controllers/nonprofits/bank_accounts_controller.rb index 9073c33d..43dfbc31 100644 --- a/app/controllers/nonprofits/bank_accounts_controller.rb +++ b/app/controllers/nonprofits/bank_accounts_controller.rb @@ -1,64 +1,65 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class BankAccountsController < ApplicationController - include Controllers::NonprofitHelper + class BankAccountsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! - # post /nonprofits/:nonprofit_id/bank_account - # must pass in the user's password as params[:password] - def create - if password_was_confirmed(params[:pw_token]) - render_json { InsertBankAccount.with_stripe(current_nonprofit, current_user, params[:bank_account]) } - else - render json: ["Please confirm your password"], status: :unprocessable_entity - end - end + # post /nonprofits/:nonprofit_id/bank_account + # must pass in the user's password as params[:password] + def create + if password_was_confirmed(params[:pw_token]) + render_json { InsertBankAccount.with_stripe(current_nonprofit, current_user, params[:bank_account]) } + else + render json: ['Please confirm your password'], status: :unprocessable_entity + end + end - # get /nonprofits/:nonprofit_id/bank_account/confirmation - def confirmation - @nonprofit = Nonprofit.find(params[:nonprofit_id]) - @bank_account = @nonprofit.bank_account - end + # get /nonprofits/:nonprofit_id/bank_account/confirmation + def confirmation + @nonprofit = Nonprofit.find(params[:nonprofit_id]) + @bank_account = @nonprofit.bank_account + end - # post /nonprofits/:nonprofit_id/bank_account/confirmation - def confirm - npo = current_nonprofit - ba = npo.bank_account - if params[:token] == ba.confirmation_token - ba.update_attribute(:pending_verification, false) - flash[:notice] = "Your bank account is now confirmed!" - redirect_to nonprofits_payouts_path(npo) - else - redirect_to(nonprofits_donations_path(npo), {:flash => {:error => "We could not confirm this bank account. Please follow the exact link provided in the confirmation email."}}) - end - end + # post /nonprofits/:nonprofit_id/bank_account/confirmation + def confirm + npo = current_nonprofit + ba = npo.bank_account + if params[:token] == ba.confirmation_token + ba.update_attribute(:pending_verification, false) + flash[:notice] = 'Your bank account is now confirmed!' + redirect_to nonprofits_payouts_path(npo) + else + redirect_to(nonprofits_donations_path(npo), flash: { error: 'We could not confirm this bank account. Please follow the exact link provided in the confirmation email.' }) + end + end - # get /nonprofits/:nonprofit_id/bank_account/cancellation - def cancellation - @nonprofit = Nonprofit.find(params[:nonprofit_id]) - @bank_account = @nonprofit.bank_account - end + # get /nonprofits/:nonprofit_id/bank_account/cancellation + def cancellation + @nonprofit = Nonprofit.find(params[:nonprofit_id]) + @bank_account = @nonprofit.bank_account + end - # post /nonprofits/:nonprofit_id/bank_account/cancel - def cancel - npo = current_nonprofit - ba = npo.bank_account - if params[:token] == ba.confirmation_token - ba.destroy - flash[:notice] = "Your bank account has been removed." - redirect_to nonprofits_donations_path(npo) - else - redirect_to(nonprofits_donations_path(npo), {:flash => {:error => "We could not remove this bank account. Please follow the exact link provided in the email."}}) - end - end - - def resend_confirmation - npo = current_nonprofit - ba = npo.bank_account - NonprofitMailer.delay.new_bank_account_notification(ba) if ba.valid? - respond_to{|format| format.json{render json: {}}} - end + # post /nonprofits/:nonprofit_id/bank_account/cancel + def cancel + npo = current_nonprofit + ba = npo.bank_account + if params[:token] == ba.confirmation_token + ba.destroy + flash[:notice] = 'Your bank account has been removed.' + redirect_to nonprofits_donations_path(npo) + else + redirect_to(nonprofits_donations_path(npo), flash: { error: 'We could not remove this bank account. Please follow the exact link provided in the email.' }) + end + end -end + def resend_confirmation + npo = current_nonprofit + ba = npo.bank_account + NonprofitMailer.delay.new_bank_account_notification(ba) if ba.valid? + respond_to { |format| format.json { render json: {} } } + end + end end diff --git a/app/controllers/nonprofits/button_controller.rb b/app/controllers/nonprofits/button_controller.rb index a2258b36..35fb85a6 100644 --- a/app/controllers/nonprofits/button_controller.rb +++ b/app/controllers/nonprofits/button_controller.rb @@ -1,28 +1,27 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class ButtonController < ApplicationController - include Controllers::NonprofitHelper + class ButtonController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_user! - before_action :authenticate_user! + def send_code + NonprofitMailer.button_code(current_nonprofit, params[:to_email], params[:to_name], params[:from_email], params[:message], params[:code]).deliver + render json: {}, status: 200 + end + def basic + @nonprofit = current_nonprofit + end - def send_code - NonprofitMailer.button_code(current_nonprofit, params[:to_email], params[:to_name], params[:from_email], params[:message], params[:code]).deliver - render json: {}, status: 200 - end + def guided + @nonprofit = current_nonprofit + end - def basic - @nonprofit = current_nonprofit - end - - def guided - @nonprofit = current_nonprofit - end - - def advanced - @nonprofit = current_nonprofit - end - -end + def advanced + @nonprofit = current_nonprofit + end + end end diff --git a/app/controllers/nonprofits/cards_controller.rb b/app/controllers/nonprofits/cards_controller.rb index 1ee6fdee..8a8f0446 100644 --- a/app/controllers/nonprofits/cards_controller.rb +++ b/app/controllers/nonprofits/cards_controller.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class CardsController < ApplicationController + class CardsController < ApplicationController include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! def edit @nonprofit = current_nonprofit @@ -12,7 +14,7 @@ module Nonprofits # POST /nonprofits/:nonprofit_id/card def create render( - JsonResp.new(params) do |d| + JsonResp.new(params) do |_d| requires(:nonprofit_id).as_int requires(:card).nested do requires(:name, :stripe_card_token, :stripe_card_id).as_string @@ -25,6 +27,5 @@ module Nonprofits end ) end - end end diff --git a/app/controllers/nonprofits/charges_controller.rb b/app/controllers/nonprofits/charges_controller.rb index 25ee872d..4825b881 100644 --- a/app/controllers/nonprofits/charges_controller.rb +++ b/app/controllers/nonprofits/charges_controller.rb @@ -1,14 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class ChargesController < ApplicationController - include Controllers::NonprofitHelper + class ChargesController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user!, only: :index + before_action :authenticate_nonprofit_user!, only: :index - # get /nonprofit/:nonprofit_id/charges - def index - redirect_to controller: :payments, action: :index - end # def index - - end + # get /nonprofit/:nonprofit_id/charges + def index + redirect_to controller: :payments, action: :index + end # def index + end end diff --git a/app/controllers/nonprofits/custom_field_joins_controller.rb b/app/controllers/nonprofits/custom_field_joins_controller.rb index 2c36cfaa..1cf26ea8 100644 --- a/app/controllers/nonprofits/custom_field_joins_controller.rb +++ b/app/controllers/nonprofits/custom_field_joins_controller.rb @@ -1,41 +1,39 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class CustomFieldJoinsController < ApplicationController + class CustomFieldJoinsController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_nonprofit_user! - include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + def index + @custom_field_joins = current_nonprofit + .supporters.find(params[:supporter_id]) + .custom_field_joins + .order('created_at DESC') + end - def index - @custom_field_joins = current_nonprofit - .supporters.find(params[:supporter_id]) - .custom_field_joins - .order('created_at DESC') - end + # used for modify a single supporter's custom fields or a group of + # selected supporters' CFs or all supporters' CFs + def modify + if params[:custom_fields].blank? || params[:custom_fields].empty? + render json: {} + return + end - # used for modify a single supporter's custom fields or a group of - # selected supporters' CFs or all supporters' CFs - def modify - if params[:custom_fields].blank? || params[:custom_fields].empty? - render json: {} - return - end - - if params[:selecting_all] - supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} - else - supporter_ids = params[:supporter_ids]. map(&:to_i) - end + if params[:selecting_all] + supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } + else + supporter_ids = params[:supporter_ids]. map(&:to_i) + end - render InsertCustomFieldJoins.in_bulk(current_nonprofit.id, supporter_ids, params[:custom_fields]) - end + render InsertCustomFieldJoins.in_bulk(current_nonprofit.id, supporter_ids, params[:custom_fields]) + end - - def destroy - supporter = current_nonprofit.supporters.find(params[:supporter_id]) - supporter.custom_field_joins.find(params[:id]).destroy - render json: {}, status: :ok - end - - end + def destroy + supporter = current_nonprofit.supporters.find(params[:supporter_id]) + supporter.custom_field_joins.find(params[:id]).destroy + render json: {}, status: :ok + end + end end - diff --git a/app/controllers/nonprofits/custom_field_masters_controller.rb b/app/controllers/nonprofits/custom_field_masters_controller.rb index 17fad57b..eda2ab8a 100644 --- a/app/controllers/nonprofits/custom_field_masters_controller.rb +++ b/app/controllers/nonprofits/custom_field_masters_controller.rb @@ -1,27 +1,27 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class CustomFieldMastersController < ApplicationController - include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + class CustomFieldMastersController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_nonprofit_user! - def index - @custom_field_masters = current_nonprofit - .custom_field_masters - .order('id DESC') - .not_deleted - end + def index + @custom_field_masters = current_nonprofit + .custom_field_masters + .order('id DESC') + .not_deleted + end - def create - json_saved CreateCustomFieldMaster.create(current_nonprofit, params[:custom_field_master]) - end + def create + json_saved CreateCustomFieldMaster.create(current_nonprofit, params[:custom_field_master]) + end - def destroy - custom_field_master = current_nonprofit.custom_field_masters.find(params[:id]) - custom_field_master.update_attribute(:deleted, true) - custom_field_master.custom_field_joins.destroy_all - render json: {}, status: :ok - end - - end + def destroy + custom_field_master = current_nonprofit.custom_field_masters.find(params[:id]) + custom_field_master.update_attribute(:deleted, true) + custom_field_master.custom_field_joins.destroy_all + render json: {}, status: :ok + end + end end - diff --git a/app/controllers/nonprofits/donations_controller.rb b/app/controllers/nonprofits/donations_controller.rb index 80cd72f0..99b9cf27 100644 --- a/app/controllers/nonprofits/donations_controller.rb +++ b/app/controllers/nonprofits/donations_controller.rb @@ -1,84 +1,83 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class DonationsController < ApplicationController - include Controllers::NonprofitHelper + class DonationsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user!, only: [:index, :update] - before_action :authenticate_campaign_editor!, only: [:create_offsite] + before_action :authenticate_nonprofit_user!, only: %i[index update] + before_action :authenticate_campaign_editor!, only: [:create_offsite] - # get /nonprofit/:nonprofit_id/donations - def index - redirect_to controller: :payments, action: :index - end # def index + # get /nonprofit/:nonprofit_id/donations + def index + redirect_to controller: :payments, action: :index + end # def index - # post /nonprofits/:nonprofit_id/donations - def create + # post /nonprofits/:nonprofit_id/donations + def create + if params[:token] + params[:donation][:token] = params[:token] + render_json { InsertDonation.with_stripe(params[:donation], current_user) } + elsif params[:direct_debit_detail_id] + render JsonResp.new(params[:donation]) do |_data| + requires(:amount).as_int + requires(:supporter_id, :nonprofit_id) + # TODO + # requires_either(:card_id, :direct_debit_detail_id).as_int + optional(:dedication, :designation).as_string + optional(:campaign_id, :event_id).as_int + end.when_valid do |data| - if params[:token] - params[:donation][:token] = params[:token] - return render_json{ InsertDonation.with_stripe(params[:donation], current_user) } - elsif params[:direct_debit_detail_id] - render JsonResp.new(params[:donation]){|data| - requires(:amount).as_int - requires(:supporter_id, :nonprofit_id) - # TODO - # requires_either(:card_id, :direct_debit_detail_id).as_int - optional(:dedication, :designation).as_string - optional(:campaign_id, :event_id).as_int - }.when_valid{|data| + InsertDonation.with_sepa(data) + end + end + end - - InsertDonation.with_sepa(data) - - } - end - end - - # post /nonprofits/:nonprofit_id/donations/create_offsite - def create_offsite - render JsonResp.new(params[:donation]){|data| + # post /nonprofits/:nonprofit_id/donations/create_offsite + def create_offsite + render JsonResp.new(params[:donation]) do |_data| requires(:amount).as_int.min(1) requires(:supporter_id, :nonprofit_id).as_int optional(:dedication, :designation).as_string optional(:campaign_id, :event_id).as_int optional(:date).as_date - optional(:offsite_payment).nested{ + optional(:offsite_payment).nested do optional(:kind).one_of('cash', 'check') optional(:check_number) - } - }.when_valid{|data| InsertDonation.offsite(data)} - end + end + end.when_valid { |data| InsertDonation.offsite(data) } + end - def update - render_json{ UpdateDonation.update_payment(params[:id], params[:donation]) } - end + def update + render_json { UpdateDonation.update_payment(params[:id], params[:donation]) } + end - # put /nonprofits/:nonprofit_id/donations/:id - # update designation, dedication, or comment on a donation in the followup - def followup - nonprofit = Nonprofit.find(params[:nonprofit_id]) - donation = nonprofit.donations.find(params[:id]) - json_saved UpdateDonation.from_followup(donation, params[:donation]) - end + # put /nonprofits/:nonprofit_id/donations/:id + # update designation, dedication, or comment on a donation in the followup + def followup + nonprofit = Nonprofit.find(params[:nonprofit_id]) + donation = nonprofit.donations.find(params[:id]) + json_saved UpdateDonation.from_followup(donation, params[:donation]) + end - # this is a special, weird case - private + # this is a special, weird case + private - def current_campaign - if !@campaign && params[:donation] && params[:donation][:campaign_id] - @campaign = Campaign.where('id = ? ', params[:donation][:campaign_id]).first - end - return @campaign - end + def current_campaign + if !@campaign && params[:donation] && params[:donation][:campaign_id] + @campaign = Campaign.where('id = ? ', params[:donation][:campaign_id]).first + end + @campaign + end - def current_campaign_editor? - !params[:preview] && (current_nonprofit_user? || (current_campaign && current_role?(:campaign_editor, current_campaign.id)) || current_role?(:super_admin)) - end + def current_campaign_editor? + !params[:preview] && (current_nonprofit_user? || (current_campaign && current_role?(:campaign_editor, current_campaign.id)) || current_role?(:super_admin)) + end - def authenticate_campaign_editor! - unless current_campaign_editor? - block_with_sign_in 'You need to be a campaign editor to do that.' - end - end - end + def authenticate_campaign_editor! + unless current_campaign_editor? + block_with_sign_in 'You need to be a campaign editor to do that.' + end + end + end end diff --git a/app/controllers/nonprofits/email_lists_controller.rb b/app/controllers/nonprofits/email_lists_controller.rb index 25a0d8fb..4f4dcc13 100644 --- a/app/controllers/nonprofits/email_lists_controller.rb +++ b/app/controllers/nonprofits/email_lists_controller.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class EmailListsController < ApplicationController - include Controllers::NonprofitHelper + class EmailListsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! - def index - render_json{ Qx.fetch(:email_lists, nonprofit_id: params[:nonprofit_id]) } - end + def index + render_json { Qx.fetch(:email_lists, nonprofit_id: params[:nonprofit_id]) } + end - def create - tag_master_ids = params['tag_masters'].values.map(&:to_i) - render_json{ InsertEmailLists.for_mailchimp(params[:nonprofit_id], tag_master_ids) } + def create + tag_master_ids = params['tag_masters'].values.map(&:to_i) + render_json { InsertEmailLists.for_mailchimp(params[:nonprofit_id], tag_master_ids) } + end end end -end diff --git a/app/controllers/nonprofits/imports_controller.rb b/app/controllers/nonprofits/imports_controller.rb index 9498680a..a50f296c 100644 --- a/app/controllers/nonprofits/imports_controller.rb +++ b/app/controllers/nonprofits/imports_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class ImportsController < ApplicationController @@ -6,15 +8,15 @@ module Nonprofits before_action :authenticate_nonprofit_user! # post /nonprofits/:nonprofit_id/imports def create - render_json{ - InsertImport.delay.from_csv_safe({ + render_json do + InsertImport.delay.from_csv_safe( nonprofit_id: params[:nonprofit_id], user_id: current_user.id, user_email: current_user.email, file_uri: params[:file_uri], header_matches: params[:header_matches] - }) - } + ) + end end end end diff --git a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb index 639c4bc0..ecc4ebee 100644 --- a/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb +++ b/app/controllers/nonprofits/miscellaneous_np_infos_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class MiscellaneousNpInfosController < ApplicationController @@ -12,18 +14,17 @@ module Nonprofits render_json { FetchMiscellaneousNpInfo.fetch(params[:nonprofit_id]) } end end - end def update respond_to do |format| - format.json { - render_json { + format.json do + render_json do update = UpdateMiscellaneousNpInfo.update(params[:nonprofit_id], params[:miscellaneous_np_info]) - #flash[:notice] = "Your Miscellaneous Settings have been saved" + # flash[:notice] = "Your Miscellaneous Settings have been saved" update - } - } + end + end end end end diff --git a/app/controllers/nonprofits/nonprofit_keys_controller.rb b/app/controllers/nonprofits/nonprofit_keys_controller.rb index 7a247fe5..28fdb3f9 100644 --- a/app/controllers/nonprofits/nonprofit_keys_controller.rb +++ b/app/controllers/nonprofits/nonprofit_keys_controller.rb @@ -1,38 +1,39 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class NonprofitKeysController < ApplicationController - include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + class NonprofitKeysController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_nonprofit_user! - # get /nonprofits/:nonprofit_id/nonprofit_keys - # pass in the :select query param, which is the name of the column of the specific token you want - def index - render_json{QueryNonprofitKeys.get_key(current_nonprofit.id, params[:select])} - end - - # Redirects to the mailchimp OAuth2 landing page, first setting the nonprofit id in the session - # GET /nonprofits/:nonprofit_id/nonprofit_keys/mailchimp_login - def mailchimp_login - session[:current_mailchimp_nonprofit_id] = current_nonprofit.id - redirect_to "https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id=#{ENV['MAILCHIMP_OAUTH_CLIENT_ID']}" - end - - # After the user OAuths mailchimp, they are redirected to /mailchimp-landing - # This action then redirects them back to /settings - # GET /mailchimp-landing - def mailchimp_landing - @nonprofit = Nonprofit.find(session[:current_mailchimp_nonprofit_id]) - session.delete(:current_mailchimp_nonprofit_id) - begin - session[:mailchimp_access_token] = InsertNonprofitKeys.insert_mailchimp_access_token(@nonprofit.id, params[:code]) - rescue Exception => e - flash[:notice] = "Unable to connect to your Mailchimp account, please try again. (Error: #{e})" - redirect_to '/settings' - return + # get /nonprofits/:nonprofit_id/nonprofit_keys + # pass in the :select query param, which is the name of the column of the specific token you want + def index + render_json { QueryNonprofitKeys.get_key(current_nonprofit.id, params[:select]) } end - redirect_to nonprofits_supporters_path @nonprofit, 'show-modal' => 'mailchimpSettingsModal' - end -end + # Redirects to the mailchimp OAuth2 landing page, first setting the nonprofit id in the session + # GET /nonprofits/:nonprofit_id/nonprofit_keys/mailchimp_login + def mailchimp_login + session[:current_mailchimp_nonprofit_id] = current_nonprofit.id + redirect_to "https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id=#{ENV['MAILCHIMP_OAUTH_CLIENT_ID']}" + end + + # After the user OAuths mailchimp, they are redirected to /mailchimp-landing + # This action then redirects them back to /settings + # GET /mailchimp-landing + def mailchimp_landing + @nonprofit = Nonprofit.find(session[:current_mailchimp_nonprofit_id]) + session.delete(:current_mailchimp_nonprofit_id) + begin + session[:mailchimp_access_token] = InsertNonprofitKeys.insert_mailchimp_access_token(@nonprofit.id, params[:code]) + rescue Exception => e + flash[:notice] = "Unable to connect to your Mailchimp account, please try again. (Error: #{e})" + redirect_to '/settings' + return + end + redirect_to nonprofits_supporters_path @nonprofit, 'show-modal' => 'mailchimpSettingsModal' + end + end end diff --git a/app/controllers/nonprofits/payments_controller.rb b/app/controllers/nonprofits/payments_controller.rb index f54701cc..e579fad9 100644 --- a/app/controllers/nonprofits/payments_controller.rb +++ b/app/controllers/nonprofits/payments_controller.rb @@ -1,32 +1,33 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class PaymentsController < ApplicationController - include Controllers::NonprofitHelper + class PaymentsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! - - # get /nonprofit/:nonprofit_id/payments - def index - @nonprofit = current_nonprofit - respond_to do |format| - format.html do + # get /nonprofit/:nonprofit_id/payments + def index + @nonprofit = current_nonprofit + respond_to do |format| + format.html do @panels_layout = true end - format.json do - @response = QueryPayments.full_search(params[:nonprofit_id], params) + format.json do + @response = QueryPayments.full_search(params[:nonprofit_id], params) render json: @response, status: :ok - end - end - end # def index + end + end + end # def index def export begin @nonprofit = current_nonprofit @user = current_user_id - ExportPayments::initiate_export(@nonprofit.id, params, @user) - rescue => e + ExportPayments.initiate_export(@nonprofit.id, params, @user) + rescue StandardError => e e end if e.nil? @@ -37,10 +38,10 @@ module Nonprofits end end - def show - @nonprofit = current_nonprofit - @payment = @nonprofit.payments.find(params[:id]) - end # def show + def show + @nonprofit = current_nonprofit + @payment = @nonprofit.payments.find(params[:id]) + end # def show def update @payment = current_nonprofit.payments.find(params[:id]) @@ -68,11 +69,12 @@ module Nonprofits PaymentMailer.resend_donor_receipt(params[:id]) render json: {} end + # post /nonprofits/:nonprofit_id/payments/:id/resend_admin_receipt # pass user_id of the admin to send to def resend_admin_receipt PaymentMailer.resend_admin_receipt(params[:id], current_user.id) render json: {} end - end # class PaymentsController + end # class PaymentsController end # module Nonprofits diff --git a/app/controllers/nonprofits/payouts_controller.rb b/app/controllers/nonprofits/payouts_controller.rb index b9bbff0f..0d47912d 100644 --- a/app/controllers/nonprofits/payouts_controller.rb +++ b/app/controllers/nonprofits/payouts_controller.rb @@ -1,49 +1,50 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class PayoutsController < ApplicationController - include Controllers::NonprofitHelper + class PayoutsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_admin!, only: :create - before_action :authenticate_nonprofit_user!, only: [:index, :show] + before_action :authenticate_nonprofit_admin!, only: :create + before_action :authenticate_nonprofit_user!, only: %i[index show] - def create - payout = InsertPayout.with_stripe(current_nonprofit.id, { - stripe_account_id: current_nonprofit.stripe_account_id, - email: current_user.email, - user_ip: current_user.current_sign_in_ip, - bank_name: current_nonprofit.bank_account.name - }, {before_date: params[:before_date]}) + def create + payout = InsertPayout.with_stripe(current_nonprofit.id, { + stripe_account_id: current_nonprofit.stripe_account_id, + email: current_user.email, + user_ip: current_user.current_sign_in_ip, + bank_name: current_nonprofit.bank_account.name + }, before_date: params[:before_date]) - if payout['failure_message'].present? - flash[:notice] = "The payout failed: #{payout['failure_message']}" - render json: payout, status: :unprocessable_entity - else - flash[:notice] = 'We successfully submitted your payout! View status and receipts below.' - render json: payout, status: :ok - end - end - - def index - @nonprofit = Nonprofit.find(params[:nonprofit_id]) - @payouts = @nonprofit.payouts.order('created_at DESC') - balances = QueryPayments.nonprofit_balances(params[:nonprofit_id]) - @available_total = balances['available_gross'] - @pending_total = balances['pending_gross'] - @can_make_payouts = @nonprofit.can_make_payouts - end - - # get /nonprofits/:nonprofit_id/payouts/:id - def show - payout = current_nonprofit.payouts.find(params[:id]) - respond_to do |format| - format.json{render json: payout} - format.csv do - payments = QueryPayments.for_payout(params[:nonprofit_id], params[:id]) - filename = "payout-#{payout.created_at.strftime("%m-%d-%Y")}" - send_data(Format::Csv.from_vectors(payments), filename: "#{filename}.csv") + if payout['failure_message'].present? + flash[:notice] = "The payout failed: #{payout['failure_message']}" + render json: payout, status: :unprocessable_entity + else + flash[:notice] = 'We successfully submitted your payout! View status and receipts below.' + render json: payout, status: :ok end end - end -end + def index + @nonprofit = Nonprofit.find(params[:nonprofit_id]) + @payouts = @nonprofit.payouts.order('created_at DESC') + balances = QueryPayments.nonprofit_balances(params[:nonprofit_id]) + @available_total = balances['available_gross'] + @pending_total = balances['pending_gross'] + @can_make_payouts = @nonprofit.can_make_payouts + end + + # get /nonprofits/:nonprofit_id/payouts/:id + def show + payout = current_nonprofit.payouts.find(params[:id]) + respond_to do |format| + format.json { render json: payout } + format.csv do + payments = QueryPayments.for_payout(params[:nonprofit_id], params[:id]) + filename = "payout-#{payout.created_at.strftime('%m-%d-%Y')}" + send_data(Format::Csv.from_vectors(payments), filename: "#{filename}.csv") + end + end + end + end end diff --git a/app/controllers/nonprofits/recurring_donations_controller.rb b/app/controllers/nonprofits/recurring_donations_controller.rb index c35ea796..35be402d 100644 --- a/app/controllers/nonprofits/recurring_donations_controller.rb +++ b/app/controllers/nonprofits/recurring_donations_controller.rb @@ -1,94 +1,95 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class RecurringDonationsController < ApplicationController - include Controllers::NonprofitHelper + class RecurringDonationsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user!, except: [:create] + before_action :authenticate_nonprofit_user!, except: [:create] - # get /nonprofits/:nonprofit_id/recurring_donations - def index - @nonprofit = current_nonprofit - @panels_layout = true - respond_to do |format| - format.html - format.json do - # set dashboard params include externally active and failed - #TODO move into javascript - params[:active] = true + # get /nonprofits/:nonprofit_id/recurring_donations + def index + @nonprofit = current_nonprofit + @panels_layout = true + respond_to do |format| + format.html + format.json do + # set dashboard params include externally active and failed + # TODO move into javascript + params[:active] = true - render json: QueryRecurringDonations.full_list(params[:nonprofit_id], params) + render json: QueryRecurringDonations.full_list(params[:nonprofit_id], params) + end end - end - end - - def export - begin - @nonprofit = current_nonprofit - @user = current_user_id - #TODO move into javascript - if params.key?(:active_and_not_failed) - params.delete(:active) if params.key?(:active) - params.delete(:failed) if params.key?(:failed) - end - - [:active_and_not_failed, :active, :failed].each do |k| - if (params.key?(k)) - params[k] = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(params[k]) - end - end - - params[:root_url] = root_url - - ExportRecurringDonations::initiate_export(@nonprofit.id, params, current_user.id) - rescue => e - e - end - if e.nil? - flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." - render json: {}, status: :ok - else - render json: e, status: :ok - end - end - - def show - @recurring_donation = current_recurring_donation - respond_to {|format| format.json} - end - - def destroy - UpdateRecurringDonations.cancel(params[:id], current_user.email) - json_saved current_recurring_donation - end - - def update - json_saved UpdateRecurringDonations - .update(current_recurring_donation, params[:recurring_donation]) - end - - # post /nonprofits/:nonprofit_id/recurring_donations - def create - if params[:recurring_donation][:token] - render_json{ InsertRecurringDonation.with_stripe(params[:recurring_donation]) } - elsif params[:recurring_donation][:direct_debit_detail_id] - render JsonResp.new(params[:recurring_donation]){|data| - requires(:amount).as_int - requires(:supporter_id, :nonprofit_id, :direct_debit_detail_id).as_int - optional(:dedication, :designation).as_string - optional(:campaign_id, :event_id).as_int - }.when_valid{|data| - InsertRecurringDonation.with_sepa(data) - } - else - render json: {}, status: 422 end - end -private + def export + begin + @nonprofit = current_nonprofit + @user = current_user_id + # TODO: move into javascript + if params.key?(:active_and_not_failed) + params.delete(:active) if params.key?(:active) + params.delete(:failed) if params.key?(:failed) + end - def current_recurring_donation - @recurring_donation ||= current_nonprofit.recurring_donations.find params[:id] - end + %i[active_and_not_failed active failed].each do |k| + if params.key?(k) + params[k] = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(params[k]) + end + end -end + params[:root_url] = root_url + + ExportRecurringDonations.initiate_export(@nonprofit.id, params, current_user.id) + rescue StandardError => e + e + end + if e.nil? + flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." + render json: {}, status: :ok + else + render json: e, status: :ok + end + end + + def show + @recurring_donation = current_recurring_donation + respond_to { |format| format.json } + end + + def destroy + UpdateRecurringDonations.cancel(params[:id], current_user.email) + json_saved current_recurring_donation + end + + def update + json_saved UpdateRecurringDonations + .update(current_recurring_donation, params[:recurring_donation]) + end + + # post /nonprofits/:nonprofit_id/recurring_donations + def create + if params[:recurring_donation][:token] + render_json { InsertRecurringDonation.with_stripe(params[:recurring_donation]) } + elsif params[:recurring_donation][:direct_debit_detail_id] + render JsonResp.new(params[:recurring_donation]) do |_data| + requires(:amount).as_int + requires(:supporter_id, :nonprofit_id, :direct_debit_detail_id).as_int + optional(:dedication, :designation).as_string + optional(:campaign_id, :event_id).as_int + end.when_valid do |data| + InsertRecurringDonation.with_sepa(data) + end + else + render json: {}, status: 422 + end + end + + private + + def current_recurring_donation + @recurring_donation ||= current_nonprofit.recurring_donations.find params[:id] + end + end end diff --git a/app/controllers/nonprofits/refunds_controller.rb b/app/controllers/nonprofits/refunds_controller.rb index a06f1290..85c35fac 100644 --- a/app/controllers/nonprofits/refunds_controller.rb +++ b/app/controllers/nonprofits/refunds_controller.rb @@ -1,21 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class RefundsController < ApplicationController - include Controllers::NonprofitHelper + class RefundsController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + before_action :authenticate_nonprofit_user! - # post /charges/:charge_id/refunds - def create - charge = Qx.select("*").from("charges").where(id: params[:charge_id]).execute.first - params[:refund][:user_id] = current_user.id - render_json{ InsertRefunds.with_stripe(charge, params['refund']) } - end + # post /charges/:charge_id/refunds + def create + charge = Qx.select('*').from('charges').where(id: params[:charge_id]).execute.first + params[:refund][:user_id] = current_user.id + render_json { InsertRefunds.with_stripe(charge, params['refund']) } + end - def index - charge = current_nonprofit.charges.find(params[:charge_id]) - @refunds = charge.refunds - end - end + def index + charge = current_nonprofit.charges.find(params[:charge_id]) + @refunds = charge.refunds + end + end end - diff --git a/app/controllers/nonprofits/reports_controller.rb b/app/controllers/nonprofits/reports_controller.rb index 9dd6ca5c..c3c28646 100644 --- a/app/controllers/nonprofits/reports_controller.rb +++ b/app/controllers/nonprofits/reports_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class ReportsController < ApplicationController @@ -8,7 +10,7 @@ module Nonprofits respond_to do |format| format.csv do filename = "end-of-year-report-#{params[:year]}.csv" - data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], {:year => params[:year]}) + data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], year: params[:year]) send_data(Format::Csv.from_array(data), filename: filename) end end @@ -18,17 +20,15 @@ module Nonprofits respond_to do |format| format.csv do name_description = nil - if (params[:year]) + if params[:year] name_description = params[:year] - elsif (params[:start]) + elsif params[:start] name_description = "from-#{params[:start]}" - if (params[:end]) - name_description += "-to-#{params[:end]}" - end + name_description += "-to-#{params[:end]}" if params[:end] end filename = "aggregate-report-#{name_description}.csv" - data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], {:year => params[:year], :start => params[:start], :end => params[:end]}) + data = QuerySupporters.year_aggregate_report(params[:nonprofit_id], year: params[:year], start: params[:start], end: params[:end]) send_data(Format::Csv.from_array(data), filename: filename) end end diff --git a/app/controllers/nonprofits/supporter_emails_controller.rb b/app/controllers/nonprofits/supporter_emails_controller.rb index fcd39683..1256f12d 100644 --- a/app/controllers/nonprofits/supporter_emails_controller.rb +++ b/app/controllers/nonprofits/supporter_emails_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class SupporterEmailsController < ApplicationController @@ -7,19 +9,19 @@ module Nonprofits def create if params[:selecting_all] ids = QuerySupporters.full_filter_expr(params[:nonprofit_id], params[:query]) - .select("supporters.id") - .execute(format: 'csv')[1..-1].flatten + .select('supporters.id') + .execute(format: 'csv')[1..-1].flatten elsif params[:supporter_ids] ids = params[:supporter_ids] end if ids.nil? || ids.empty? - render json: {errors: 'Supporters not found'}, status: :unprocessable_entity + render json: { errors: 'Supporters not found' }, status: :unprocessable_entity return end DelayedJobHelper.enqueue_job(EmailSupporters, :deliver, [ids, params[:supporter_email]]) - render json: {count: ids.count}, status: :ok + render json: { count: ids.count }, status: :ok end def gmail @@ -29,4 +31,3 @@ module Nonprofits end end end - diff --git a/app/controllers/nonprofits/supporter_notes_controller.rb b/app/controllers/nonprofits/supporter_notes_controller.rb index 3073033b..9e086409 100644 --- a/app/controllers/nonprofits/supporter_notes_controller.rb +++ b/app/controllers/nonprofits/supporter_notes_controller.rb @@ -1,27 +1,28 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class SupporterNotesController < ApplicationController - include Controllers::NonprofitHelper + class SupporterNotesController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user!, except: [:create] + before_action :authenticate_nonprofit_user!, except: [:create] - # post /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes - def create - params[:supporter_note][:user_id] ||= current_user && current_user.id - render_json{ InsertSupporterNotes.create([params[:supporter_note]]) } - end + # post /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes + def create + params[:supporter_note][:user_id] ||= current_user&.id + render_json { InsertSupporterNotes.create([params[:supporter_note]]) } + end - # put /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id - def update - params[:supporter_note][:user_id] ||= current_user && current_user.id - params[:supporter_note][:id] = params[:id] - render_json{ UpdateSupporterNotes.update(params[:supporter_note]) } - end - - # delete /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id - def destroy - render_json{ UpdateSupporterNotes.delete(params[:id]) } - end + # put /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id + def update + params[:supporter_note][:user_id] ||= current_user&.id + params[:supporter_note][:id] = params[:id] + render_json { UpdateSupporterNotes.update(params[:supporter_note]) } + end -end + # delete /nonprofits/:nonprofit_id/supporters/:supporter_id/supporter_notes/:id + def destroy + render_json { UpdateSupporterNotes.delete(params[:id]) } + end + end end diff --git a/app/controllers/nonprofits/supporters_controller.rb b/app/controllers/nonprofits/supporters_controller.rb index a81fbe9a..31684107 100644 --- a/app/controllers/nonprofits/supporters_controller.rb +++ b/app/controllers/nonprofits/supporters_controller.rb @@ -1,114 +1,114 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits -class SupportersController < ApplicationController - include Controllers::NonprofitHelper + class SupportersController < ApplicationController + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user!, except: [:new, :create] - #before_action(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} + before_action :authenticate_nonprofit_user!, except: %i[new create] + # before_action(except: [:create, :mailchimp_landing]){authenticate_min_nonprofit_plan(2)} - # get /nonprofit/:nonprofit_id/supporters - def index - @panels_layout = true - @nonprofit = current_nonprofit - respond_to do |format| - format.html - format.json do - render json: QuerySupporters.full_search(params[:nonprofit_id], params) - end - - format.csv do - file_date = Date.today.strftime("%m-%d-%Y") - supporters = QuerySupporters.for_export(params[:nonprofit_id], params) - send_data(Format::Csv.from_vectors(supporters), filename: "supporters-#{file_date}.csv") - end - end - end - - def export - begin + # get /nonprofit/:nonprofit_id/supporters + def index + @panels_layout = true @nonprofit = current_nonprofit - @user = current_user_id - ExportSupporters::initiate_export(@nonprofit.id, params, @user) - rescue => e - e + respond_to do |format| + format.html + format.json do + render json: QuerySupporters.full_search(params[:nonprofit_id], params) + end + + format.csv do + file_date = Date.today.strftime('%m-%d-%Y') + supporters = QuerySupporters.for_export(params[:nonprofit_id], params) + send_data(Format::Csv.from_vectors(supporters), filename: "supporters-#{file_date}.csv") + end + end end - if e.nil? - flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." - render json: {}, status: :ok - else - render json: e, status: :ok + + def export + begin + @nonprofit = current_nonprofit + @user = current_user_id + ExportSupporters.initiate_export(@nonprofit.id, params, @user) + rescue StandardError => e + e + end + if e.nil? + flash[:notice] = "Your export was successfully initiated and you'll be emailed at #{current_user.email} as soon as it's available. Feel free to use the site in the meantime." + render json: {}, status: :ok + else + render json: e, status: :ok + end end - end - def index_metrics - render_json do - QuerySupporters.full_search_metrics(params[:nonprofit_id], params) + def index_metrics + render_json do + QuerySupporters.full_search_metrics(params[:nonprofit_id], params) + end end - end - def show - render json: {data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first} - end - - def email_address - render json: Supporter.find(params[:supporter_id]).email - end - - def full_contact - fc = FullContactInfo.where("supporter_id=#{params[:supporter_id]}").first - if fc - render json: {full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id )} - else - render json: {full_contact: nil} + def show + render json: { data: QuerySupporters.for_crm_profile(params[:nonprofit_id], [params[:id]]).first } end - end - def info_card - render json: QuerySupporters.for_info_card(params[:supporter_id]) - end - - - # post /nonprofits/:nonprofit_id/supporters - def create - render_json{ InsertSupporter.create_or_update(params[:nonprofit_id], params[:supporter]) } - end - - # put /nonprofits/:nonprofit_id/supporters/:id - def update - @supporter = current_nonprofit.supporters.find(params[:id]) - json_saved UpdateSupporter.from_info(@supporter, params[:supporter]) - end - - def bulk_delete - if params[:selecting_all] - supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} - else - supporter_ids = params[:supporter_ids]. map(&:to_i) + def email_address + render json: Supporter.find(params[:supporter_id]).email end - render_json {UpdateSupporter.bulk_delete(current_nonprofit.id, supporter_ids ) } - end - # get /nonprofits/:nonprofit_id/supporters/merge_data - # returns the info required to merge two supporters - def merge_data - render json: QuerySupporters.merge_data(params[:ids]) - end + def full_contact + fc = FullContactInfo.where("supporter_id=#{params[:supporter_id]}").first + if fc + render json: { full_contact: QueryFullContactInfos.fetch_associated_tables(fc.id) } + else + render json: { full_contact: nil } + end + end - # post /nonprofits/:nonprofit_id/supporters/merge - def merge - render JsonResp.new(params){|params| - requires(:supporter) - requires(:nonprofit_id).as_int - requires(:supporter_ids).as_array - }.when_valid{|params| - params[:supporter][:nonprofit_id] = params[:nonprofit_id] - MergeSupporters.selected(params[:supporter], params[:supporter_ids], params[:nonprofit_id], current_user.id) - } - end + def info_card + render json: QuerySupporters.for_info_card(params[:supporter_id]) + end - # def new - # @nonprofit = current_nonprofit - # end + # post /nonprofits/:nonprofit_id/supporters + def create + render_json { InsertSupporter.create_or_update(params[:nonprofit_id], params[:supporter]) } + end -end + # put /nonprofits/:nonprofit_id/supporters/:id + def update + @supporter = current_nonprofit.supporters.find(params[:id]) + json_saved UpdateSupporter.from_info(@supporter, params[:supporter]) + end + + def bulk_delete + if params[:selecting_all] + supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } + else + supporter_ids = params[:supporter_ids]. map(&:to_i) + end + render_json { UpdateSupporter.bulk_delete(current_nonprofit.id, supporter_ids) } + end + + # get /nonprofits/:nonprofit_id/supporters/merge_data + # returns the info required to merge two supporters + def merge_data + render json: QuerySupporters.merge_data(params[:ids]) + end + + # post /nonprofits/:nonprofit_id/supporters/merge + def merge + render JsonResp.new(params) do |_params| + requires(:supporter) + requires(:nonprofit_id).as_int + requires(:supporter_ids).as_array + end.when_valid do |params| + params[:supporter][:nonprofit_id] = params[:nonprofit_id] + MergeSupporters.selected(params[:supporter], params[:supporter_ids], params[:nonprofit_id], current_user.id) + end + end + + # def new + # @nonprofit = current_nonprofit + # end + end end diff --git a/app/controllers/nonprofits/tag_joins_controller.rb b/app/controllers/nonprofits/tag_joins_controller.rb index f499f65c..0a9d2a42 100644 --- a/app/controllers/nonprofits/tag_joins_controller.rb +++ b/app/controllers/nonprofits/tag_joins_controller.rb @@ -1,36 +1,32 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits - class TagJoinsController < ApplicationController - include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_user! + class TagJoinsController < ApplicationController + include Controllers::NonprofitHelper + before_action :authenticate_nonprofit_user! def index render_json do - {data: QuerySupporters.tag_joins(params['nonprofit_id'], params['supporter_id'])} + { data: QuerySupporters.tag_joins(params['nonprofit_id'], params['supporter_id']) } end end - # used for modify a single supporter's tags or a group of - # selected supporters' tags or all supporters' tags - def modify - + # used for modify a single supporter's tags or a group of + # selected supporters' tags or all supporters' tags + def modify if params[:selecting_all] - supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select("supporters.id").execute.map{|h| h['id']} + supporter_ids = QuerySupporters.full_filter_expr(current_nonprofit.id, params[:query]).select('supporters.id').execute.map { |h| h['id'] } else supporter_ids = params[:supporter_ids]. map(&:to_i) end - render InsertTagJoins.in_bulk(current_nonprofit.id, current_user.profile.id, supporter_ids, params[:tags]) + render InsertTagJoins.in_bulk(current_nonprofit.id, current_user.profile.id, supporter_ids, params[:tags]) + end - - - end - - def destroy - supporter = current_nonprofit.supporters.find(params[:supporter_id]) - supporter.tag_joins.find(params[:id]).destroy - render json: {}, status: :ok - end - - end + def destroy + supporter = current_nonprofit.supporters.find(params[:supporter_id]) + supporter.tag_joins.find(params[:id]).destroy + render json: {}, status: :ok + end + end end - diff --git a/app/controllers/nonprofits/tag_masters_controller.rb b/app/controllers/nonprofits/tag_masters_controller.rb index 6abc8a7a..50858208 100644 --- a/app/controllers/nonprofits/tag_masters_controller.rb +++ b/app/controllers/nonprofits/tag_masters_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class TagMastersController < ApplicationController @@ -5,14 +7,14 @@ module Nonprofits before_action :authenticate_nonprofit_user! def index - render json: {data: - Qx.select('id', 'name', 'created_at') + render json: { data: + Qx.select('id', 'name', 'created_at') .from('tag_masters') .where( ['tag_masters.nonprofit_id = $id', id: current_nonprofit.id], - ["coalesce(deleted, FALSE) = FALSE"]) - .execute - } + ['coalesce(deleted, FALSE) = FALSE'] + ) + .execute } end def create @@ -25,7 +27,5 @@ module Nonprofits tag_master.tag_joins.destroy_all render json: {}, status: :ok end - end end - diff --git a/app/controllers/nonprofits/trackings_controller.rb b/app/controllers/nonprofits/trackings_controller.rb index 208e64b7..8a9ca5ce 100644 --- a/app/controllers/nonprofits/trackings_controller.rb +++ b/app/controllers/nonprofits/trackings_controller.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Nonprofits class TrackingsController < ApplicationController # POST /nonprofits/:nonprofit_id/tracking def create - render JsonResp.new(params){|data| + render JsonResp.new(params) do |_data| requires(:donation_id).as_int optional(:utm_campaign, :utm_content, :utm_medium, :utm_source).as_string - }.when_valid{|data| + end.when_valid do |_data| InsertTracking.create(params) - } + end end end end diff --git a/app/controllers/nonprofits_controller.rb b/app/controllers/nonprofits_controller.rb index 55aa04ab..47250a89 100755 --- a/app/controllers/nonprofits_controller.rb +++ b/app/controllers/nonprofits_controller.rb @@ -1,67 +1,69 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later - class NonprofitsController < ApplicationController - include Controllers::NonprofitHelper +class NonprofitsController < ApplicationController + include Controllers::NonprofitHelper - helper_method :current_nonprofit_user? - before_action :authenticate_nonprofit_user!, only: [:dashboard, :dashboard_metrics, :dashboard_todos, :payment_history, :profile_todos, :recurring_donation_stats, :update, :verify_identity] - before_action :authenticate_super_admin!, only: [:destroy] + helper_method :current_nonprofit_user? + before_action :authenticate_nonprofit_user!, only: %i[dashboard dashboard_metrics dashboard_todos payment_history profile_todos recurring_donation_stats update verify_identity] + before_action :authenticate_super_admin!, only: [:destroy] - # get /nonprofits/:id - # get /:state_code/:city/:name - def show + # get /nonprofits/:id + # get /:state_code/:city/:name + def show if !current_nonprofit.published && !current_role?(:super_admin) - block_with_sign_in + block_with_sign_in return end - @nonprofit = current_nonprofit - @url = Format::Url.concat(root_url, @nonprofit.url) - @supporters = @nonprofit.supporters.not_deleted - @profiles = @nonprofit.profiles.order('total_raised DESC').limit(5).includes(:user).uniq + @nonprofit = current_nonprofit + @url = Format::Url.concat(root_url, @nonprofit.url) + @supporters = @nonprofit.supporters.not_deleted + @profiles = @nonprofit.profiles.order('total_raised DESC').limit(5).includes(:user).uniq events = @nonprofit.events.not_deleted.order('start_datetime desc') campaigns = @nonprofit.campaigns.not_deleted.not_a_child.order('created_at desc') - @events = events.upcoming - @any_past_events = events.past.any? - @active_campaigns = campaigns.active - @any_past_campaigns = campaigns.past.any? + @events = events.upcoming + @any_past_events = events.past.any? + @active_campaigns = campaigns.active + @any_past_campaigns = campaigns.past.any? - @nonprofit_background_image = FetchBackgroundImage.with_model(@nonprofit) + @nonprofit_background_image = FetchBackgroundImage.with_model(@nonprofit) - respond_to do |format| - format.html - format.json {@nonprofit} - end - end + respond_to do |format| + format.html + format.json { @nonprofit } + end + end def recurring_donation_stats render json: QueryRecurringDonations.overall_stats(params[:nonprofit_id]) end - def profile_todos - render json: FetchTodoStatus.for_profile(current_nonprofit) - end + def profile_todos + render json: FetchTodoStatus.for_profile(current_nonprofit) + end - def dashboard_todos - render json: FetchTodoStatus.for_dashboard(current_nonprofit) - end + def dashboard_todos + render json: FetchTodoStatus.for_dashboard(current_nonprofit) + end - def create + def create current_user ||= User.find(params[:user_id]) - json_saved Nonprofit.register(current_user, params[:nonprofit]) - end + json_saved Nonprofit.register(current_user, params[:nonprofit]) + end - def update - flash[:notice] = 'Update successful!' + def update + flash[:notice] = 'Update successful!' current_nonprofit.update_attributes params[:nonprofit].except(:verification_status) - json_saved current_nonprofit - end + json_saved current_nonprofit + end - def destroy - current_nonprofit.destroy - flash[:notice] = 'Nonprofit removed' - render json: {} - end + def destroy + current_nonprofit.destroy + flash[:notice] = 'Nonprofit removed' + render json: {} + end # get /nonprofits/:id/donate def donate @@ -69,18 +71,18 @@ @referer = params[:origin] || request.env['HTTP_REFERER'] @campaign = current_nonprofit.campaigns.find_by_id(params[:campaign_id]) if params[:campaign_id] @countries_translations = countries_list(I18n.locale) - respond_to { |format| format.html{render layout: 'layouts/embed'} } + respond_to { |format| format.html { render layout: 'layouts/embed' } } end - def btn - @nonprofit = current_nonprofit - respond_to { |format| format.html{render layout: 'layouts/embed'} } - end + def btn + @nonprofit = current_nonprofit + respond_to { |format| format.html { render layout: 'layouts/embed' } } + end # get /nonprofits/:id/supporter_form def supporter_form - @nonprofit = current_nonprofit - respond_to { |format| format.html{render layout: 'layouts/embed'} } + @nonprofit = current_nonprofit + respond_to { |format| format.html { render layout: 'layouts/embed' } } end # post /nonprofits/:id/supporter_with_tag @@ -89,21 +91,21 @@ render json: InsertSupporter.with_tags_and_fields(@nonprofit.id, params[:supporter]) end - def dashboard - @nonprofit = current_nonprofit - respond_to { |format| format.html } - end + def dashboard + @nonprofit = current_nonprofit + respond_to { |format| format.html } + end - def dashboard_metrics - render json: Hamster::Hash[data: NonprofitMetrics.all_metrics(current_nonprofit.id)] - end + def dashboard_metrics + render json: Hamster::Hash[data: NonprofitMetrics.all_metrics(current_nonprofit.id)] + end - def payment_history + def payment_history render json: NonprofitMetrics.payment_history(params) - end + end - # put /nonprofits/:id/verify_identity - def verify_identity + # put /nonprofits/:id/verify_identity + def verify_identity if params[:legal_entity][:address] tos = { ip: current_user.current_sign_in_ip, @@ -111,8 +113,8 @@ user_agent: request.user_agent } end - render_json{ UpdateNonprofit.verify_identity(params[:nonprofit_id], params[:legal_entity], tos) } - end + render_json { UpdateNonprofit.verify_identity(params[:nonprofit_id], params[:legal_entity], tos) } + end def search render json: QueryNonprofits.by_search_string(params[:npo_name]) @@ -132,13 +134,12 @@ all_countries = ISO3166::Country.translations(locale) if Settings.intntl.all_countries - countries = all_countries.select{ |code, name| Settings.intntl.all_countries.include? code } - countries = countries.map{ |code, name| [code.upcase, name] }.sort{ |a, b| a[1] <=> b[1] } + countries = all_countries.select { |code, _name| Settings.intntl.all_countries.include? code } + countries = countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } countries.push([Settings.intntl.other_country.upcase, I18n.t('nonprofits.donate.info.supporter.other_country')]) if Settings.intntl.other_country countries else - all_countries.map{ |code, name| [code.upcase, name] }.sort{ |a, b| a[1] <=> b[1] } + all_countries.map { |code, name| [code.upcase, name] }.sort_by { |a| a[1] } end end - end diff --git a/app/controllers/onboard_controller.rb b/app/controllers/onboard_controller.rb index 7e11316c..ceb7d782 100644 --- a/app/controllers/onboard_controller.rb +++ b/app/controllers/onboard_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class OnboardController < ApplicationController layout 'layouts/apified' def index diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f171f546..a471a858 100755 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,63 +1,64 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ProfilesController < ApplicationController - helper_method :authenticate_profile_owner! - before_action :authenticate_profile_owner!, only: [:update, :fundraisers, :donations_history] + before_action :authenticate_profile_owner!, only: %i[update fundraisers donations_history] - # get /profiles/:id - # public profile - def show - @profile = Profile.find(params[:id]) - @profile_nonprofits = Psql.execute(Qexpr.new.select("DISTINCT nonprofits.*").from(:nonprofits).join(:supporters, "supporters.nonprofit_id=nonprofits.id AND supporters.profile_id=#{@profile.id}")) + # get /profiles/:id + # public profile + def show + @profile = Profile.find(params[:id]) + @profile_nonprofits = Psql.execute(Qexpr.new.select('DISTINCT nonprofits.*').from(:nonprofits).join(:supporters, "supporters.nonprofit_id=nonprofits.id AND supporters.profile_id=#{@profile.id}")) @campaigns = @profile.campaigns.published.includes(:nonprofit) - if @profile.anonymous? && current_user_id != @profile.user_id && !:super_admin - flash[:notice] = 'That user does not have a public profile.' - redirect_to(request.env["HTTP_REFERER"] || root_url) - return - end - end + if @profile.anonymous? && current_user_id != @profile.user_id && !:super_admin + flash[:notice] = 'That user does not have a public profile.' + redirect_to(request.env['HTTP_REFERER'] || root_url) + return + end + end - # get /profiles/:id/donations_history - def donations_history + # get /profiles/:id/donations_history + def donations_history validate - @profile = Profile.find(params[:id]) - @recurring_donations = @profile.recurring_donations.where(:active => true).includes(:nonprofit) - @donations = @profile.donations.includes(:nonprofit) - end + @profile = Profile.find(params[:id]) + @recurring_donations = @profile.recurring_donations.where(active: true).includes(:nonprofit) + @donations = @profile.donations.includes(:nonprofit) + end # get /profiles/:id/fundraisers def fundraisers validate current_user = Profile.find(params[:id]).user @profile = current_user.profile - @edited_campaigns = Campaign.where("profile_id=#{@profile.id}").order("end_datetime DESC") + @edited_campaigns = Campaign.where("profile_id=#{@profile.id}").order('end_datetime DESC') end # get /profiles/:id/events def events - render json: QueryEventMetrics.for_listings('profile', params[:id], params) + render json: QueryEventMetrics.for_listings('profile', params[:id], params) end - # put /profiles/:id - def update - if current_role?(:super_admin) # can update other profiles - @profile = Profile.find(params[:id]) - else - @profile = current_user.profile - end - @profile.update_attributes(params[:profile]) - json_saved @profile, 'Profile updated' - end + # put /profiles/:id + def update + @profile = if current_role?(:super_admin) # can update other profiles + Profile.find(params[:id]) + else + current_user.profile + end + @profile.update_attributes(params[:profile]) + json_saved @profile, 'Profile updated' + end private - def authenticate_profile_owner!() - if (!current_role?(:super_associate) && - !current_role?(:super_admin) && - (!current_user || - !current_user.profile || - current_user.profile.id != params[:id].to_i)) + def authenticate_profile_owner! + if !current_role?(:super_associate) && + !current_role?(:super_admin) && + (!current_user || + !current_user.profile || + current_user.profile.id != params[:id].to_i) block_with_sign_in end end diff --git a/app/controllers/recurring_donations_controller.rb b/app/controllers/recurring_donations_controller.rb index 3561dd65..bdf0e5ae 100644 --- a/app/controllers/recurring_donations_controller.rb +++ b/app/controllers/recurring_donations_controller.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RecurringDonationsController < ApplicationController - def edit @data = QueryRecurringDonations.fetch_for_edit params[:id] if @data && params[:t] == @data['recurring_donation']['edit_token'] @data['change_amount_suggestions'] = CalculateSuggestedAmounts.calculate(@data['recurring_donation']['amount']) @data['miscellaneous_np_info'] = FetchMiscellaneousNpInfo.fetch(@data['nonprofit']['id']) if @data['miscellaneous_np_info']['donate_again_url'].blank? - @data['miscellaneous_np_info']['donate_again_url'] = url_for(:controller => :nonprofits, :action=> :show, :id => @data['nonprofit']['id'], :only_path => false) + @data['miscellaneous_np_info']['donate_again_url'] = url_for(controller: :nonprofits, action: :show, id: @data['nonprofit']['id'], only_path: false) end respond_to do |format| format.html end else - flash[:notice] = "Unable to find donation. Please follow the exact link provided in your email" + flash[:notice] = 'Unable to find donation. Please follow the exact link provided in your email' redirect_to root_url end end @@ -21,7 +22,7 @@ class RecurringDonationsController < ApplicationController def destroy @data = QueryRecurringDonations.fetch_for_edit params[:id] if params[:edit_token] != @data['recurring_donation']['edit_token'] - render json: {error: 'Invalid token'}, status: :unprocessable_entity + render json: { error: 'Invalid token' }, status: :unprocessable_entity else updated = UpdateRecurringDonations.cancel(params[:id], current_user ? current_user.email : @data['supporter']['email']) render json: updated @@ -37,7 +38,7 @@ class RecurringDonationsController < ApplicationController data['recurring_donation'] = UpdateRecurringDonations.update_paydate(data['recurring_donation'], params[:paydate]) if params[:paydate] render json: data, status: data.is_a?(ValidationError) ? :unprocessable_entity : :ok else - render json: {error: 'Invalid token'}, status: :unprocessable_entity + render json: { error: 'Invalid token' }, status: :unprocessable_entity end end @@ -45,15 +46,14 @@ class RecurringDonationsController < ApplicationController rd = RecurringDonation.where('id = ?', params[:id]).first if rd && params[:edit_token] == rd['edit_token'] begin - amount_response = UpdateRecurringDonations.update_amount(rd, params[:token], params[:amount]) - flash[:notice] = "Your recurring donation amount has been successfully changed to $#{(amount_response.amount/100).to_i}" + amount_response = UpdateRecurringDonations.update_amount(rd, params[:token], params[:amount]) + flash[:notice] = "Your recurring donation amount has been successfully changed to $#{(amount_response.amount / 100).to_i}" render_json { amount_response } - rescue => e + rescue StandardError => e render_json { raise e } end else - render json: {error: 'Invalid token'}, status: :unprocessable_entity + render json: { error: 'Invalid token' }, status: :unprocessable_entity end end - end diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index ff211e3b..fd734d65 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RolesController < ApplicationController - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper - before_action :authenticate_nonprofit_admin! + before_action :authenticate_nonprofit_admin! - def create - role = Role.create_for_nonprofit(params[:role][:name].to_sym, params[:role][:email], FetchNonprofit.with_params(params)) - json_saved role, "User successfully added!" - end + def create + role = Role.create_for_nonprofit(params[:role][:name].to_sym, params[:role][:email], FetchNonprofit.with_params(params)) + json_saved role, 'User successfully added!' + end - def destroy - role = Role.find(params[:id]) - roles = role.user.roles.where(host_id: params[:nonprofit_id], name: role.name) - unless roles.empty? - roles.destroy_all - flash[:notice] = 'User successfully removed' - render json: {} - else - render json: {:error => "We couldn't find that admin"}, :status => :unprocessable_entity - end - end + def destroy + role = Role.find(params[:id]) + roles = role.user.roles.where(host_id: params[:nonprofit_id], name: role.name) + if roles.empty? + render json: { error: "We couldn't find that admin" }, status: :unprocessable_entity + else + roles.destroy_all + flash[:notice] = 'User successfully removed' + render json: {} + end + end end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index a0e60553..b35db2f4 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,31 +1,31 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SettingsController < ApplicationController - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper - helper_method :current_nonprofit_user? - before_action :authenticate_user! + helper_method :current_nonprofit_user? + before_action :authenticate_user! - def index - if current_role?(:super_admin) && params[:nonprofit_id] - @nonprofit = Nonprofit.find(params[:nonprofit_id]) - elsif current_role?([:nonprofit_admin, :nonprofit_associate]) - @nonprofit = administered_nonprofit - end - - if current_role?(:super_admin) && params[:user_id] - @user = User.find_by_id(params[:user_id]) - elsif current_role?(:super_admin) && params[:user_email] - @user = User.find_by_email(params[:user_email]) - else - @user = current_user + def index + if current_role?(:super_admin) && params[:nonprofit_id] + @nonprofit = Nonprofit.find(params[:nonprofit_id]) + elsif current_role?(%i[nonprofit_admin nonprofit_associate]) + @nonprofit = administered_nonprofit end - @profile = @user.profile + @user = if current_role?(:super_admin) && params[:user_id] + User.find_by_id(params[:user_id]) + elsif current_role?(:super_admin) && params[:user_email] + User.find_by_email(params[:user_email]) + else + current_user + end - if @nonprofit - @miscellaneous_np_info = FetchMiscellaneousNpInfo.fetch(@nonprofit.id) - end - - end + @profile = @user.profile + if @nonprofit + @miscellaneous_np_info = FetchMiscellaneousNpInfo.fetch(@nonprofit.id) + end + end end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index 6598e0f2..00e729ba 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class StaticController < ApplicationController layout 'layouts/static' @@ -8,18 +10,17 @@ class StaticController < ApplicationController def ccs ccs_method = !Settings.ccs ? 'local_tar_gz' : Settings.ccs.ccs_method - if (ccs_method == 'local_tar_gz') + if ccs_method == 'local_tar_gz' temp_file = "#{Rails.root}/tmp/#{Time.current.to_i}.tar.gz" result = Kernel.system("git archive --format=tar.gz -o #{temp_file} HEAD") if result - send_file(temp_file, :type => "application/gzip") + send_file(temp_file, type: 'application/gzip') else render body: nil, status: 500 end - elsif (ccs_method == 'github') + elsif ccs_method == 'github' git_hash = File.read("#{Rails.root}/CCS_HASH") redirect_to "https://github.com/#{Settings.ccs.options.account}/#{Settings.ccs.options.repo}/tree/#{git_hash}" end - end end diff --git a/app/controllers/super_admins_controller.rb b/app/controllers/super_admins_controller.rb index 84ed07a5..cd444ceb 100644 --- a/app/controllers/super_admins_controller.rb +++ b/app/controllers/super_admins_controller.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SuperAdminsController < ApplicationController - layout "layouts/page" + layout 'layouts/page' before_action :authenticate_super_associate! - def index - end + def index; end def search_nonprofits render json: QueryNonprofits.for_admin(params) @@ -15,49 +16,47 @@ class SuperAdminsController < ApplicationController render json: QueryProfiles.for_admin(params) end - def search_fullcontact + def search_fullcontact begin result = FullContact.person(email: params[:search]) rescue Exception => e - result = '' + result = '' end render json: [result] end def resend_user_confirmation - ParamValidation.new(params || {}, { - profile_id: {:required => true, is_integer: true} - }) + ParamValidation.new(params || {}, + profile_id: { required: true, is_integer: true }) profile = Profile.includes(:user).where('id = ?', params[:profile_id]).first - unless (profile.user) - raise ArgumentError.new("#{params[:profile_id]} is a profile without a valid user") + unless profile.user + raise ArgumentError, "#{params[:profile_id]} is a profile without a valid user" end profile.user.send_confirmation_instructions - render json: {status: :ok} + render json: { status: :ok } end def recurring_donations_without_cards - odd_donations = QueryRecurringDonations::recurring_donations_without_cards + odd_donations = QueryRecurringDonations.recurring_donations_without_cards respond_to do |format| format.html format.csv do - csv_out = CSV.generate { |csv| + csv_out = CSV.generate do |csv| csv << ['supporter id', 'recurring donation id', 'rd created date', 'rd modified', 'donation id', 'donation card id', 'edit_token', 'nonprofit id', 'last charge succeeded id', 'last charge succeeded created at', 'last charge attempted id', 'last charge attempted created at', 'amount'] - odd_donations.each { |rd| + odd_donations.each do |rd| csv << [rd.supporter.id, rd.id, rd.created_at, rd.updated_at, rd.donation.id, rd.donation.card_id, rd.edit_token, rd.nonprofit.id, rd.most_recent_paid_charge.id, rd.most_recent_paid_charge.created_at, rd.most_recent_charge.id, rd.most_recent_charge.created_at, rd.amount] - } - } + end + end - - send_data(csv_out, filename: "recurring_donations_without_cards-#{Time.now.to_date()}.csv") + send_data(csv_out, filename: "recurring_donations_without_cards-#{Time.now.to_date}.csv") end end end @@ -65,17 +64,13 @@ class SuperAdminsController < ApplicationController def export_supporters_with_rds np = params[:np] ids = params[:ids] - results = QuerySupporters.for_export(np, {ids: ids}) - results[0].push("Management URLS") - results.drop(1).each {|row| - rds = Supporter.includes(:recurring_donations).find(row.last).recurring_donations.select{|rd| rd.active}.map{|rd| "* #{root_url}recurring_donations/#{rd.id}/edit?t=#{rd.edit_token}"}.join("\n") + results = QuerySupporters.for_export(np, ids: ids) + results[0].push('Management URLS') + results.drop(1).each do |row| + rds = Supporter.includes(:recurring_donations).find(row.last).recurring_donations.select(&:active).map { |rd| "* #{root_url}recurring_donations/#{rd.id}/edit?t=#{rd.edit_token}" }.join("\n") row.push(rds) - } + end - - send_data(Format::Csv.from_vectors(results), filename: "supporters_with_multiple_donations.csv") + send_data(Format::Csv.from_vectors(results), filename: 'supporters_with_multiple_donations.csv') end - - end - diff --git a/app/controllers/ticket_levels_controller.rb b/app/controllers/ticket_levels_controller.rb index 3e12ff56..1996fe8c 100644 --- a/app/controllers/ticket_levels_controller.rb +++ b/app/controllers/ticket_levels_controller.rb @@ -1,27 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TicketLevelsController < ApplicationController - include Controllers::EventHelper + include Controllers::EventHelper - before_action :authenticate_event_editor!, :except => [:index, :show] + before_action :authenticate_event_editor!, except: %i[index show] - def index + def index ev_id = current_event.id - render json: {data: QueryTicketLevels.with_event_id(ev_id, current_role?(:event_editor, ev_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id))} - end + render json: { data: QueryTicketLevels.with_event_id(ev_id, current_role?(:event_editor, ev_id) || current_role?(:super_admin) || current_role?(:nonprofit_admin, current_event.nonprofit_id)) } + end - def show - render json: current_ticket_level - end + def show + render json: current_ticket_level + end - def create - ticket_level = current_event.ticket_levels.create params[:ticket_level] - json_saved ticket_level, 'Ticket level created!' - end + def create + ticket_level = current_event.ticket_levels.create params[:ticket_level] + json_saved ticket_level, 'Ticket level created!' + end - def update - current_ticket_level.update_attributes params[:ticket_level] - json_saved current_ticket_level, 'Ticket level updated' - end + def update + current_ticket_level.update_attributes params[:ticket_level] + json_saved current_ticket_level, 'Ticket level updated' + end # put /nonprofits/:nonprofit_id/events/:event_id/ticket_levels/update_order # Pass in {data: [{id: 1, order: 1}]} @@ -31,14 +33,13 @@ class TicketLevelsController < ApplicationController end def destroy - current_ticket_level.destroy - render json: {} - end + current_ticket_level.destroy + render json: {} + end -private - - def current_ticket_level - @ticket_level ||= current_event.ticket_levels.find params[:id] - end + private + def current_ticket_level + @ticket_level ||= current_event.ticket_levels.find params[:id] + end end diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 407961b0..a37b2b95 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TicketsController < ApplicationController - include Controllers::EventHelper + include Controllers::EventHelper - helper_method :current_event_admin?, :current_event_editor? - before_action :authenticate_event_editor!, :except => [:create, :add_note] + helper_method :current_event_admin?, :current_event_editor? + before_action :authenticate_event_editor!, except: %i[create add_note] before_action :authenticate_nonprofit_user!, only: [:delete_card_for_ticket] - # post /nonprofits/:nonprofit_id/events/:event_id/tickets - def create + # post /nonprofits/:nonprofit_id/events/:event_id/tickets + def create authenticate_event_editor! if params[:kind] == 'offsite' render_json do params[:current_user] = current_user @@ -18,29 +20,29 @@ class TicketsController < ApplicationController def update params[:ticket][:ticket_id] = params[:id] params[:ticket][:event_id] = params[:event_id] - render_json{ UpdateTickets.update(params[:ticket], current_user) } + render_json { UpdateTickets.update(params[:ticket], current_user) } end # Attendees dashboard - # get /nonprofits/:nonprofit_id/events/:event_id/tickets - def index - @panels_layout = true - @nonprofit = current_nonprofit - @event = current_event - respond_to do |format| - format.html + # get /nonprofits/:nonprofit_id/events/:event_id/tickets + def index + @panels_layout = true + @nonprofit = current_nonprofit + @event = current_event + respond_to do |format| + format.html format.csv do - file_date = Date.today.strftime("%m-%d-%Y") - filename = "tickets-#{file_date}" + file_date = Date.today.strftime('%m-%d-%Y') + filename = "tickets-#{file_date}" @tickets = QueryTickets.for_export(@event.id, params) - send_data(Format::Csv.from_vectors(@tickets), filename: "#{filename}.csv") + send_data(Format::Csv.from_vectors(@tickets), filename: "#{filename}.csv") end - format.json do + format.json do render json: QueryTickets.attendees_list(@event.id, params) - end - end - end + end + end + end # PUT nonprofits/:nonprofit_id/events/:event_id/tickets/:id/add_note def add_note diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb index 97812ee8..77601e37 100644 --- a/app/controllers/users/confirmations_controller.rb +++ b/app/controllers/users/confirmations_controller.rb @@ -1,41 +1,41 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Users::ConfirmationsController < Devise::ConfirmationsController + # get /confirm + def show + @user = User.confirm_by_token(params[:confirmation_token]) - # get /confirm - def show - @user = User.confirm_by_token(params[:confirmation_token]) - - if !@user.auto_generated || !@user.valid? - flash[:notice] = "We successfully confirmed your account" - redirect_to session[:donor_signup_url] || root_url - else + if !@user.auto_generated || !@user.valid? + flash[:notice] = 'We successfully confirmed your account' + redirect_to session[:donor_signup_url] || root_url + else respond_to do |format| format.html end - end - end + end + end def exists render json: User.find_by_email(params[:email]) end - # post /confirm - # set account password - def confirm - @user = User.find(params[:id]) + # post /confirm + # set account password + def confirm + @user = User.find(params[:id]) - if @user.valid? && @user.update_attributes(params[:user].except(:confirmation_token)) - flash[:notice] = "Your account is all set!" - sign_in @user - redirect_to session[:donor_signup_url] || root_url - else - session[:donor_signup_url] || root_url - #render :action => "show", :layout => 'layouts/embed' - end - end - - def is_confirmed - render json: {is_confirmed: User.find(params[:user_id]).confirmed?} + if @user.valid? && @user.update_attributes(params[:user].except(:confirmation_token)) + flash[:notice] = 'Your account is all set!' + sign_in @user + redirect_to session[:donor_signup_url] || root_url + else + session[:donor_signup_url] || root_url + # render :action => "show", :layout => 'layouts/embed' + end end + def is_confirmed + render json: { is_confirmed: User.find(params[:user_id]).confirmed? } + end end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index 24288ad8..1f516e7a 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Users::RegistrationsController < Devise::RegistrationsController respond_to :html, :json @@ -12,9 +14,9 @@ class Users::RegistrationsController < Devise::RegistrationsController user = User.register_donor!(params[:user]) if user.save sign_in user - render :json => user + render json: user else - render :json => user.errors.full_messages, :status => :unprocessable_entity + render json: user.errors.full_messages, status: :unprocessable_entity clean_up_passwords(user) end end @@ -33,7 +35,7 @@ class Users::RegistrationsController < Devise::RegistrationsController errs = current_user.errors.full_messages else success = false - errs = {:password => :incorrect} + errs = { password: :incorrect } end if success @@ -43,10 +45,10 @@ class Users::RegistrationsController < Devise::RegistrationsController flash[:notice] = 'Account updated!' end - sign_in(current_user, :bypass => true) - render :json => current_user + sign_in(current_user, bypass: true) + render json: current_user else - render :json => {:errors => errs}, :status => :unprocessable_entity + render json: { errors: errs }, status: :unprocessable_entity end end end diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 4ffebf7e..0271dad8 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -1,37 +1,36 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Users::SessionsController < Devise::SessionsController - layout 'layouts/apified', only: :new - respond_to :json, only: :new + layout 'layouts/apified', only: :new + respond_to :json, only: :new def new @theme = 'minimal' super end - def create + def create @theme = 'minimal' - respond_to do |format| - format.json { - warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new") - render :status => 200, :json => { :status => "Success" } - } - end - end - - - # post /users/confirm_auth - # A simple action to confirm an entered password for a user who is already signed in - def confirm_auth - if current_user.valid_password?(params[:password]) - tok = SecureRandom.uuid - session[:pw_token] = tok - session[:pw_timestamp] = Time.current.to_s - render json: {token: tok}, status: :ok - else - render json: ["Incorrect password. Please enter your #{Settings.general.name} %> password."], status: :unprocessable_entity - end + respond_to do |format| + format.json do + warden.authenticate!(scope: resource_name, recall: "#{controller_path}#new") + render status: 200, json: { status: 'Success' } + end + end end - -end + # post /users/confirm_auth + # A simple action to confirm an entered password for a user who is already signed in + def confirm_auth + if current_user.valid_password?(params[:password]) + tok = SecureRandom.uuid + session[:pw_token] = tok + session[:pw_timestamp] = Time.current.to_s + render json: { token: tok }, status: :ok + else + render json: ["Incorrect password. Please enter your #{Settings.general.name} %> password."], status: :unprocessable_entity + end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e2f981df..d6208207 100755 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,70 +1,71 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ApplicationHelper + def resource_name + :user + end - def resource_name - :user - end + def resource + @resource ||= User.new + end - def resource - @resource ||= User.new - end + def devise_mapping + @devise_mapping ||= Devise.mappings[:user] + end - def devise_mapping - @devise_mapping ||= Devise.mappings[:user] - end + def print_currency(cents, unit = 'EUR', sign = true) + dollars = cents.to_f / 100.0 + dollars = number_to_currency(dollars, unit: unit.to_s, precision: dollars.round == dollars ? 0 : 2) + dollars = dollars[1..-1] unless sign + dollars + end - def print_currency(cents, unit="EUR", sign=true) - - dollars = cents.to_f / 100.0 - dollars = number_to_currency(dollars, :unit => "#{unit}", :precision => (dollars.round == dollars) ? 0 : 2) - dollars = dollars[1..-1] if !sign - dollars - end + def print_percent(rate) + (rate.to_f * 100).round(2) + end - def print_percent(rate) - (rate.to_f * 100).round(2) - end + ## Dates - ## Dates + def simple_date(date_object, timezone = nil) + return '' if date_object.nil? - def simple_date date_object, timezone=nil - return '' if date_object.nil? - date_object = date_object.in_time_zone(timezone) if timezone - date_object.strftime("%m/%d/%Y") - end + date_object = date_object.in_time_zone(timezone) if timezone + date_object.strftime('%m/%d/%Y') + end - def simple_time time_object, timezone=nil - return '' if time_object.nil? - time_object = time_object.in_time_zone(timezone) if timezone - time_object.strftime("%l:%M%P") - end + def simple_time(time_object, timezone = nil) + return '' if time_object.nil? - def readable_date date_object - date_object.strftime("%B %d, %Y") - end + time_object = time_object.in_time_zone(timezone) if timezone + time_object.strftime('%l:%M%P') + end - def date_and_time date_object, timezone=nil - date_object = date_object.in_time_zone(timezone) if timezone - date_object.strftime("%m/%d/%Y %I:%M%P (%Z)") - end + def readable_date(date_object) + date_object.strftime('%B %d, %Y') + end - def us_states - [ ['Alabama', 'AL'], ['Alaska', 'AK'], ['Arizona', 'AZ'], ['Arkansas', 'AR'], ['California', 'CA'], ['Colorado', 'CO'], ['Connecticut', 'CT'], ['Delaware', 'DE'], ['District of Columbia', 'DC'], ['Florida', 'FL'], ['Georgia', 'GA'], ['Hawaii', 'HI'], ['Idaho', 'ID'], ['Illinois', 'IL'], ['Indiana', 'IN'], ['Iowa', 'IA'], ['Kansas', 'KS'], ['Kentucky', 'KY'], ['Louisiana', 'LA'], ['Maine', 'ME'], ['Maryland', 'MD'], ['Massachusetts', 'MA'], ['Michigan', 'MI'], ['Minnesota', 'MN'], ['Mississippi', 'MS'], ['Missouri', 'MO'], ['Montana', 'MT'], ['Nebraska', 'NE'], ['Nevada', 'NV'], ['New Hampshire', 'NH'], ['New Jersey', 'NJ'], ['New Mexico', 'NM'], ['New York', 'NY'], ['North Carolina', 'NC'], ['North Dakota', 'ND'], ['Ohio', 'OH'], ['Oklahoma', 'OK'], ['Oregon', 'OR'], ['Pennsylvania', 'PA'], ['Puerto Rico', 'PR'], ['Rhode Island', 'RI'], ['South Carolina', 'SC'], ['South Dakota', 'SD'], ['Tennessee', 'TN'], ['Texas', 'TX'], ['Utah', 'UT'], ['Vermont', 'VT'], ['Virginia', 'VA'], ['Washington', 'WA'], ['West Virginia', 'WV'], ['Wisconsin', 'WI'], ['Wyoming', 'WY'] ] - end + def date_and_time(date_object, timezone = nil) + date_object = date_object.in_time_zone(timezone) if timezone + date_object.strftime('%m/%d/%Y %I:%M%P (%Z)') + end - # Append a parameter to a URL string - def url_with_param(param, val, url) - url + (url.include?('?') ? '&' : '?') + param + '=' + val - end + def us_states + [%w[Alabama AL], %w[Alaska AK], %w[Arizona AZ], %w[Arkansas AR], %w[California CA], %w[Colorado CO], %w[Connecticut CT], %w[Delaware DE], ['District of Columbia', 'DC'], %w[Florida FL], %w[Georgia GA], %w[Hawaii HI], %w[Idaho ID], %w[Illinois IL], %w[Indiana IN], %w[Iowa IA], %w[Kansas KS], %w[Kentucky KY], %w[Louisiana LA], %w[Maine ME], %w[Maryland MD], %w[Massachusetts MA], %w[Michigan MI], %w[Minnesota MN], %w[Mississippi MS], %w[Missouri MO], %w[Montana MT], %w[Nebraska NE], %w[Nevada NV], ['New Hampshire', 'NH'], ['New Jersey', 'NJ'], ['New Mexico', 'NM'], ['New York', 'NY'], ['North Carolina', 'NC'], ['North Dakota', 'ND'], %w[Ohio OH], %w[Oklahoma OK], %w[Oregon OR], %w[Pennsylvania PA], ['Puerto Rico', 'PR'], ['Rhode Island', 'RI'], ['South Carolina', 'SC'], ['South Dakota', 'SD'], %w[Tennessee TN], %w[Texas TX], %w[Utah UT], %w[Vermont VT], %w[Virginia VA], %w[Washington WA], ['West Virginia', 'WV'], %w[Wisconsin WI], %w[Wyoming WY]] + end - # Prepend 'http://' if it is not present in a given url - # Used for linking to nonprofit-provided website - def add_http url - if url[/^http:\/\//] || url[/^https:\/\//] - url - else - 'http://' + url - end - end + # Append a parameter to a URL string + def url_with_param(param, val, url) + url + (url.include?('?') ? '&' : '?') + param + '=' + val + end + # Prepend 'http://' if it is not present in a given url + # Used for linking to nonprofit-provided website + def add_http(url) + if url[%r{^http://}] || url[%r{^https://}] + url + else + 'http://' + url + end + end end diff --git a/app/helpers/card_helper.rb b/app/helpers/card_helper.rb index 7a9309e6..0dd63536 100644 --- a/app/helpers/card_helper.rb +++ b/app/helpers/card_helper.rb @@ -1,23 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CardHelper + def brand_file(brand) + if brand == 'Visa' || brand == 'visa' || brand == 'VISA' + 'visa' + elsif brand == 'American Express' || brand == 'amex' + 'amex' + elsif brand == 'Discover' || brand == 'Discover Card' || brand == 'discover' + 'discover' + elsif brand == 'MasterCard' || brand == 'Mastercard' || brand == 'mastercard' + 'mastercard' + end + end - def brand_file(brand) - if brand == 'Visa' || brand == 'visa' || brand == 'VISA' - 'visa' - elsif brand == 'American Express' || brand == 'amex' - 'amex' - elsif brand == 'Discover' || brand == 'Discover Card' || brand == 'discover' - 'discover' - elsif brand == 'MasterCard' || brand == 'Mastercard' || brand == 'mastercard' - 'mastercard' - end - end + def current_card + current_user&.profile&.card + end - def current_card - current_user && current_user.profile.card - end - - def expiration_years - (0..15).map{|n| (Date.today + n.years).year} - end + def expiration_years + (0..15).map { |n| (Date.today + n.years).year } + end end diff --git a/app/helpers/devise_helper.rb b/app/helpers/devise_helper.rb index c36671b5..03359923 100644 --- a/app/helpers/devise_helper.rb +++ b/app/helpers/devise_helper.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module DeviseHelper def devise_error_messages! if resource && !resource.errors.empty? - resource.errors.first.first.to_s + ' ' + + resource.errors.first.first.to_s + ' ' + resource.errors.first.second end end diff --git a/app/helpers/nonprofits_helper.rb b/app/helpers/nonprofits_helper.rb index 5d9ea441..c721b02f 100644 --- a/app/helpers/nonprofits_helper.rb +++ b/app/helpers/nonprofits_helper.rb @@ -1,16 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module NonprofitsHelper - - def managed_npo_card_json - if current_user - if params[:nonprofit_id] && current_role?(:super_admin) - raw(Nonprofit.find(params[:nonprofit_id]).active_card.to_json) - elsif administered_nonprofit && administered_nonprofit.active_card - raw(administered_nonprofit.active_card.to_json) - end - else - 'undefined' - end - end - + def managed_npo_card_json + if current_user + if params[:nonprofit_id] && current_role?(:super_admin) + raw(Nonprofit.find(params[:nonprofit_id]).active_card.to_json) + elsif administered_nonprofit&.active_card + raw(administered_nonprofit.active_card.to_json) + end + else + 'undefined' + end + end end diff --git a/app/helpers/onboard_helper.rb b/app/helpers/onboard_helper.rb index 1cb832a5..ebc34eda 100644 --- a/app/helpers/onboard_helper.rb +++ b/app/helpers/onboard_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module OnboardHelper end diff --git a/app/helpers/pricing_helper.rb b/app/helpers/pricing_helper.rb index db1d7b48..e6022535 100644 --- a/app/helpers/pricing_helper.rb +++ b/app/helpers/pricing_helper.rb @@ -1,8 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module PricingHelper -private - def nonprofit_email - return nil if @nonprofit.nil? - @nonprofit.email || GetData.chain(@nonprofit.users.first, :email) - end + private + + def nonprofit_email + return nil if @nonprofit.nil? + + @nonprofit.email || GetData.chain(@nonprofit.users.first, :email) + end end diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb index e40303e4..dfca3351 100755 --- a/app/helpers/profiles_helper.rb +++ b/app/helpers/profiles_helper.rb @@ -1,12 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ProfilesHelper - - def get_shortened_name name + def get_shortened_name(name) if name name.length > 18 ? name[0..18] + '...' : name else 'Your Account' end end - end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index cd5fb472..d4046c71 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ApplicationJob < ActiveJob::Base diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb index 11e5250b..1699f1b3 100644 --- a/app/mailers/admin_mailer.rb +++ b/app/mailers/admin_mailer.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AdminMailer < BaseMailer - # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb index 95021647..605976a3 100644 --- a/app/mailers/base_mailer.rb +++ b/app/mailers/base_mailer.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BaseMailer < ActionMailer::Base include Roadie::Rails::Automatic include Devise::Controllers::UrlHelpers add_template_helper(ApplicationHelper) - default :from => Settings.mailer.default_from + default from: Settings.mailer.default_from layout 'email' end diff --git a/app/mailers/billing_subscription_mailer.rb b/app/mailers/billing_subscription_mailer.rb index 93240743..971f4dbd 100644 --- a/app/mailers/billing_subscription_mailer.rb +++ b/app/mailers/billing_subscription_mailer.rb @@ -1,13 +1,13 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BillingSubscriptionMailer < BaseMailer - def failed_notice(np_id) @nonprofit = Nonprofit.find(np_id) @billing_subscription = @nonprofit.billing_subscription @card = @nonprofit.active_card @billing_plan = @billing_subscription.billing_plan - @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) - mail(to: @emails, subject: "Action Needed, Please Update Your #{Settings.general.name} Account") + @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) + mail(to: @emails, subject: "Action Needed, Please Update Your #{Settings.general.name} Account") end - end diff --git a/app/mailers/campaign_mailer.rb b/app/mailers/campaign_mailer.rb index 6919bef2..72fcb0ae 100644 --- a/app/mailers/campaign_mailer.rb +++ b/app/mailers/campaign_mailer.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignMailer < BaseMailer + def creation_followup(campaign) + @creator_profile = campaign.profile + @campaign = campaign + mail(to: @creator_profile.user.email, subject: "Get your new campaign rolling! (via #{Settings.general.name})") + end - def creation_followup(campaign) - @creator_profile = campaign.profile - @campaign = campaign - mail(:to => @creator_profile.user.email, :subject => "Get your new campaign rolling! (via #{Settings.general.name})") - end - - def federated_creation_followup(campaign) - @creator_profile = campaign.profile - @campaign = campaign - mail(:to => @creator_profile.user.email, :subject => "Get your new campaign rolling! (via #{Settings.general.name})") - end + def federated_creation_followup(campaign) + @creator_profile = campaign.profile + @campaign = campaign + mail(to: @creator_profile.user.email, subject: "Get your new campaign rolling! (via #{Settings.general.name})") + end end diff --git a/app/mailers/donation_mailer.rb b/app/mailers/donation_mailer.rb index 35daa7f2..d86a54bf 100644 --- a/app/mailers/donation_mailer.rb +++ b/app/mailers/donation_mailer.rb @@ -1,36 +1,38 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class DonationMailer < BaseMailer - - # Used for both one-time and recurring donations + # Used for both one-time and recurring donations # can pass in array of admin user_ids to send to only some -- if falsey/empty, will send to all - def donor_payment_notification(donation_id, locale=I18n.locale) - @donation = Donation.find(donation_id) - @nonprofit = @donation.nonprofit - if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? + def donor_payment_notification(donation_id, locale = I18n.locale) + @donation = Donation.find(donation_id) + @nonprofit = @donation.nonprofit + if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? @thank_you_note = @donation.campaign.receipt_message else - @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, {'NAME' => @donation.supporter.name}) + @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) end @charge = @donation.charges.last - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email from = Format::Name.email_from_np(@nonprofit.name) I18n.with_locale(locale) do - mail( - to: @donation.supporter.email, - from: from, - reply_to: reply_to, - subject: I18n.t('mailer.donations.donor_direct_debit_notification.subject', nonprofit_name: @nonprofit.name)) + mail( + to: @donation.supporter.email, + from: from, + reply_to: reply_to, + subject: I18n.t('mailer.donations.donor_direct_debit_notification.subject', nonprofit_name: @nonprofit.name) + ) end end - def donor_direct_debit_notification(donation_id, locale=I18n.locale) + def donor_direct_debit_notification(donation_id, locale = I18n.locale) @donation = Donation.find(donation_id) @nonprofit = @donation.nonprofit - if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? + if @donation.campaign && ActionView::Base.full_sanitizer.sanitize(@donation.campaign.receipt_message).present? @thank_you_note = @donation.campaign.receipt_message else - @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, {'NAME' => @donation.supporter.name}) + @thank_you_note = Format::Interpolate.with_hash(@nonprofit.thank_you_note, 'NAME' => @donation.supporter.name) end reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email @@ -45,87 +47,86 @@ class DonationMailer < BaseMailer end end - # Used for both one-time and recurring donations - def nonprofit_payment_notification(donation_id, user_id=nil) - @donation = Donation.find(donation_id) - @charge = @donation.charges.last - @nonprofit = @donation.nonprofit + # Used for both one-time and recurring donations + def nonprofit_payment_notification(donation_id, user_id = nil) + @donation = Donation.find(donation_id) + @charge = @donation.charges.last + @nonprofit = @donation.nonprofit @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') if user_id em = User.find(user_id).email # return unless @emails.include?(em) @emails = [em] end - mail(to: @emails, subject: "Donation receipt for #{@donation.supporter.name}") - end + mail(to: @emails, subject: "Donation receipt for #{@donation.supporter.name}") + end def nonprofit_failed_recurring_donation(donation_id) - @donation = Donation.find(donation_id) - @nonprofit = @donation.nonprofit - @charge = @donation.charges.last + @donation = Donation.find(donation_id) + @nonprofit = @donation.nonprofit + @charge = @donation.charges.last @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') - mail(to: @emails, subject: "Recurring donation payment failure for #{@donation.supporter.name || @donation.supporter.email}") + mail(to: @emails, subject: "Recurring donation payment failure for #{@donation.supporter.name || @donation.supporter.email}") end def donor_failed_recurring_donation(donation_id) - @donation = Donation.find(donation_id) - @nonprofit = @donation.nonprofit - @charge = @donation.charges.last - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + @donation = Donation.find(donation_id) + @nonprofit = @donation.nonprofit + @charge = @donation.charges.last + reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email from = Format::Name.email_from_np(@nonprofit.name) - mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Donation payment failure for #{@nonprofit.name}") + mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Donation payment failure for #{@nonprofit.name}") end def nonprofit_recurring_donation_cancellation(donation_id) - @donation = Donation.find(donation_id) - @nonprofit = @donation.nonprofit - @charge = @donation.charges.last + @donation = Donation.find(donation_id) + @nonprofit = @donation.nonprofit + @charge = @donation.charges.last @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, @donation.campaign ? 'notify_campaigns' : 'notify_payments') - mail(to: @emails, subject: "Recurring donation cancelled for #{@donation.supporter.name || @donation.supporter.email}") - end + mail(to: @emails, subject: "Recurring donation cancelled for #{@donation.supporter.name || @donation.supporter.email}") + end - def nonprofit_recurring_donation_change_amount(donation_id, previous_amount=nil) - @donation = RecurringDonation.find(donation_id).donation - @nonprofit = @donation.nonprofit - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') - @previous_amount = previous_amount - mail(to: @emails, subject:"Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") - end + def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = nil) + @donation = RecurringDonation.find(donation_id).donation + @nonprofit = @donation.nonprofit + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') + @previous_amount = previous_amount + mail(to: @emails, subject: "Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") + end - def donor_recurring_donation_change_amount(donation_id, previous_amount=nil) - @donation = RecurringDonation.find(donation_id).donation - @nonprofit = @donation.nonprofit - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email - if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? - @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message - else - @thank_you_note = nil - end - from = Format::Name.email_from_np(@nonprofit.name) - @previous_amount = previous_amount - mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") - end + def donor_recurring_donation_change_amount(donation_id, previous_amount = nil) + @donation = RecurringDonation.find(donation_id).donation + @nonprofit = @donation.nonprofit + reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? + @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message + else + @thank_you_note = nil + end + from = Format::Name.email_from_np(@nonprofit.name) + @previous_amount = previous_amount + mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") + end - def nonprofit_recurring_donation_change_amount(donation_id, previous_amount=nil) - @donation = RecurringDonation.find(donation_id).donation - @nonprofit = @donation.nonprofit - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') - @previous_amount = previous_amount - mail(to: @emails, subject:"Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") - end - - def donor_recurring_donation_change_amount(donation_id, previous_amount=nil) - @donation = RecurringDonation.find(donation_id).donation - @nonprofit = @donation.nonprofit - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email - if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? - @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message - else - @thank_you_note = nil - end - from = Format::Name.email_from_np(@nonprofit.name) - @previous_amount = previous_amount - mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") - end + def nonprofit_recurring_donation_change_amount(donation_id, previous_amount = nil) + @donation = RecurringDonation.find(donation_id).donation + @nonprofit = @donation.nonprofit + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') + @previous_amount = previous_amount + mail(to: @emails, subject: "Recurring donation amount changed for #{@donation.supporter.name || @donation.supporter.email}") + end + def donor_recurring_donation_change_amount(donation_id, previous_amount = nil) + @donation = RecurringDonation.find(donation_id).donation + @nonprofit = @donation.nonprofit + reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + if @nonprofit.miscellaneous_np_info && ActionView::Base.full_sanitizer.sanitize(@nonprofit.miscellaneous_np_info.change_amount_message).present? + @thank_you_note = @nonprofit.miscellaneous_np_info.change_amount_message + else + @thank_you_note = nil + end + from = Format::Name.email_from_np(@nonprofit.name) + @previous_amount = previous_amount + mail(to: @donation.supporter.email, from: from, reply_to: reply_to, subject: "Recurring donation amount changed for #{@nonprofit.name}") + end end diff --git a/app/mailers/event_mailer.rb b/app/mailers/event_mailer.rb index 49a32b63..47f5ba2f 100644 --- a/app/mailers/event_mailer.rb +++ b/app/mailers/event_mailer.rb @@ -1,14 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventMailer < BaseMailer + helper :application - helper :application - - include Devise::Controllers::UrlHelpers - - def creation_followup(event) - @creator_profile = event.profile - @event = event - mail(:to => @creator_profile.user.email, :subject => "Get your new event rolling on #{Settings.general.name}!") - end + include Devise::Controllers::UrlHelpers + def creation_followup(event) + @creator_profile = event.profile + @event = event + mail(to: @creator_profile.user.email, subject: "Get your new event rolling on #{Settings.general.name}!") + end end diff --git a/app/mailers/export_mailer.rb b/app/mailers/export_mailer.rb index 2df3d36f..477eabf1 100644 --- a/app/mailers/export_mailer.rb +++ b/app/mailers/export_mailer.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ExportMailer < BaseMailer - # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # @@ -18,7 +19,6 @@ class ExportMailer < BaseMailer mail(to: @export.user.email, subject: 'Your payment export has failed') end - def export_recurring_donations_completed_notification(export) @export = export diff --git a/app/mailers/generic_mailer.rb b/app/mailers/generic_mailer.rb index 966c5f9e..c540e55a 100644 --- a/app/mailers/generic_mailer.rb +++ b/app/mailers/generic_mailer.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class GenericMailer < BaseMailer - - def generic_mail(from_email, from_name, message, subject, to_email, to_name) + def generic_mail(from_email, from_name, message, subject, to_email, _to_name) @from_email = from_email @from_name = from_name @message = message - mail(:to => to_email, :from => "#{from_name} <#{Settings.mailer.email}>", :reply_to => from_email, :subject => "#{subject}") + mail(to: to_email, from: "#{from_name} <#{Settings.mailer.email}>", reply_to: from_email, subject: subject.to_s) end # For sending a system notice to super admins @@ -16,5 +17,4 @@ class GenericMailer < BaseMailer emails = QueryUsers.super_admin_emails mail(to: emails, from: "#{@from_name} <#{@from_email}>", reply_to: @from_email, subject: options[:subject], template_name: 'generic_mail') end - end diff --git a/app/mailers/import_mailer.rb b/app/mailers/import_mailer.rb index 92a126f1..3adb30d0 100644 --- a/app/mailers/import_mailer.rb +++ b/app/mailers/import_mailer.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ImportMailer < BaseMailer - - def import_completed_notification(import_id) - @import = Import.find(import_id) - @nonprofit = @import.nonprofit - mail(to: @import.user.email, subject: "Your import is complete!") - end - + def import_completed_notification(import_id) + @import = Import.find(import_id) + @nonprofit = @import.nonprofit + mail(to: @import.user.email, subject: 'Your import is complete!') + end end diff --git a/app/mailers/nonprofit_admin_mailer.rb b/app/mailers/nonprofit_admin_mailer.rb index f7cad1bb..b0198d38 100644 --- a/app/mailers/nonprofit_admin_mailer.rb +++ b/app/mailers/nonprofit_admin_mailer.rb @@ -1,28 +1,28 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NonprofitAdminMailer < BaseMailer + def new_invite(role, raw_token) + @user = role.user + @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) + @nonprofit = role.host + @token = raw_token + mail(to: @user.email, subject: "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}. Let's set your password.") + end - def new_invite(role, raw_token) - @user = role.user - @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) - @nonprofit = role.host - @token = raw_token - mail(:to => @user.email, :subject => "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}. Let's set your password.") - end + def existing_invite(role) + @user = role.user + @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) + @nonprofit = role.host + mail(to: @user.email, subject: "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}.") + end - def existing_invite(role) - @user = role.user - @title_with_article = Format::Indefinitize.with_article(role.name.to_s.titleize) - @nonprofit = role.host - mail(:to => @user.email, :subject => "You're now #{@title_with_article} of #{@nonprofit.name} on #{Settings.general.name}.") - end - - def supporter_fundraiser(event_or_campaign) - @fundraiser = event_or_campaign - @kind = event_or_campaign.class.name.downcase || 'event' - @nonprofit = event_or_campaign.nonprofit - @profile = event_or_campaign.profile - recipients = @nonprofit.nonprofit_personnel_emails - mail(to: recipients, subject: "A Supporter has created #{Format::Indefinitize.with_article(@kind.capitalize)} for your Nonprofit!") - end + def supporter_fundraiser(event_or_campaign) + @fundraiser = event_or_campaign + @kind = event_or_campaign.class.name.downcase || 'event' + @nonprofit = event_or_campaign.nonprofit + @profile = event_or_campaign.profile + recipients = @nonprofit.nonprofit_personnel_emails + mail(to: recipients, subject: "A Supporter has created #{Format::Indefinitize.with_article(@kind.capitalize)} for your Nonprofit!") + end end - diff --git a/app/mailers/nonprofit_mailer.rb b/app/mailers/nonprofit_mailer.rb index e57bd62d..445c7b9e 100644 --- a/app/mailers/nonprofit_mailer.rb +++ b/app/mailers/nonprofit_mailer.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NonprofitMailer < BaseMailer - def failed_verification_notice(np) @nonprofit = np @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') @@ -13,92 +14,93 @@ class NonprofitMailer < BaseMailer mail(to: @emails, subject: "Verification successful on #{Settings.general.name}!") end - def refund_notification(refund_id) - @refund = Refund.find(refund_id) - @charge = @refund.charge - @nonprofit = @refund.payment.nonprofit + def refund_notification(refund_id) + @refund = Refund.find(refund_id) + @charge = @refund.charge + @nonprofit = @refund.payment.nonprofit @supporter = @refund.payment.supporter - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payments') - mail(to: @emails, subject: "A new refund has been made for $#{Format::Currency.cents_to_dollars(@refund.amount)}") - end + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payments') + mail(to: @emails, subject: "A new refund has been made for $#{Format::Currency.cents_to_dollars(@refund.amount)}") + end - def new_bank_account_notification(ba) - @nonprofit = ba.nonprofit - @bank_account = ba - @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) - mail(to: @emails, subject: "We need to confirm the new bank account") - end + def new_bank_account_notification(ba) + @nonprofit = ba.nonprofit + @bank_account = ba + @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) + mail(to: @emails, subject: 'We need to confirm the new bank account') + end - def pending_payout_notification(payout_id) - @payout = Payout.find(payout_id) - @nonprofit = @payout.nonprofit - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') - mail(to: @emails, subject: "Payout of available balance now pending") - end + def pending_payout_notification(payout_id) + @payout = Payout.find(payout_id) + @nonprofit = @payout.nonprofit + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') + mail(to: @emails, subject: 'Payout of available balance now pending') + end - def successful_payout_notification(payout) - @nonprofit = payout.nonprofit - @payout = payout - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') - mail(to: @emails, subject: "Payout of available balance succeeded") - end + def successful_payout_notification(payout) + @nonprofit = payout.nonprofit + @payout = payout + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') + mail(to: @emails, subject: 'Payout of available balance succeeded') + end - def failed_payout_notification(payout) - @nonprofit = payout.nonprofit - @payout = payout - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') - mail(to: @emails, subject: "Payout could not be completed") - end + def failed_payout_notification(payout) + @nonprofit = payout.nonprofit + @payout = payout + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_payouts') + mail(to: @emails, subject: 'Payout could not be completed') + end - def failed_recurring_donation(recurring_donation) - @recurring_donation = recurring_donation - @nonprofit = recurring_donation.nonprofit - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') - mail(to: @emails, subject: "A recurring donation from one of your supporters had a payment failure.") - end + def failed_recurring_donation(recurring_donation) + @recurring_donation = recurring_donation + @nonprofit = recurring_donation.nonprofit + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') + mail(to: @emails, subject: 'A recurring donation from one of your supporters had a payment failure.') + end - def cancelled_recurring_donation(recurring_donation) - @recurring_donation = recurring_donation - @nonprofit = recurring_donation.nonprofit - @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') - mail(to: @emails, subject: "A recurring donation from one of your supporters was cancelled.") - end + def cancelled_recurring_donation(recurring_donation) + @recurring_donation = recurring_donation + @nonprofit = recurring_donation.nonprofit + @emails = QueryUsers.nonprofit_user_emails(@nonprofit.id, 'notify_recurring_donations') + mail(to: @emails, subject: 'A recurring donation from one of your supporters was cancelled.') + end - def verified_notification(nonprofit) - @nonprofit = nonprofit - @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) - mail(to: @emails, subject: "Your nonprofit has been verified!") - end + def verified_notification(nonprofit) + @nonprofit = nonprofit + @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id) + mail(to: @emails, subject: 'Your nonprofit has been verified!') + end - def button_code(nonprofit, to_email, to_name, from_email, message, code) - @nonprofit = nonprofit - @to_email = to_email - @to_name = to_name - @from = from_email - @message = message - @code = code + def button_code(nonprofit, to_email, to_name, from_email, message, code) + @nonprofit = nonprofit + @to_email = to_email + @to_name = to_name + @from = from_email + @message = message + @code = code from = Format::Name.email_from_np(@nonprofit.name) - mail(to: to_email, from: from, reply_to: from_email, subject: "Please include this donate button code on the website") - end + mail(to: to_email, from: from, reply_to: from_email, subject: 'Please include this donate button code on the website') + end def invoice_payment_notification(nonprofit_id, payment) @nonprofit = Nonprofit.find(nonprofit_id) @payment = payment @emails = QueryUsers.all_nonprofit_user_emails(@nonprofit.id, [:nonprofit_admin]) @month_name = Date::MONTHNAMES[payment.date.month] - mail(to: @emails, subject: "#{Settings.general.name} Subscription Receipt for #{@month_name}") + mail(to: @emails, subject: "#{Settings.general.name} Subscription Receipt for #{@month_name}") end - # pass in all of: - # {is_unsubscribed_from_emails, supporter_email, message, email_unsubscribe_uuid, nonprofit_id, from_email, subject} - def supporter_message(args) - return if args[:is_unsubscribed_from_emails] || args[:supporter_email].blank? - @message = args[:message] - @uuid = args[:email_unsubscribe_uuid] - @nonprofit = Nonprofit.find args[:nonprofit_id] + # pass in all of: + # {is_unsubscribed_from_emails, supporter_email, message, email_unsubscribe_uuid, nonprofit_id, from_email, subject} + def supporter_message(args) + return if args[:is_unsubscribed_from_emails] || args[:supporter_email].blank? + + @message = args[:message] + @uuid = args[:email_unsubscribe_uuid] + @nonprofit = Nonprofit.find args[:nonprofit_id] from = Format::Name.email_from_np(@nonprofit.name) - mail(to: args[:supporter_email], reply_to: args[:from_email], from: from, subject: args[:subject]) - end + mail(to: args[:supporter_email], reply_to: args[:from_email], from: from, subject: args[:subject]) + end def setup_verification(np_id) @nonprofit = Nonprofit.find(np_id) @@ -113,6 +115,4 @@ class NonprofitMailer < BaseMailer @emails = QueryUsers.all_nonprofit_user_emails(np_id, [:nonprofit_admin]) mail(to: @emails, reply_to: 'support@commitchange.com', from: "#{Settings.general.name} Support", subject: "A hearty welcome from the #{Settings.general.name} team") end - end - diff --git a/app/mailers/payment_mailer.rb b/app/mailers/payment_mailer.rb index 28b7d52d..21762c5d 100644 --- a/app/mailers/payment_mailer.rb +++ b/app/mailers/payment_mailer.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class PaymentMailer < BaseMailer - # Send a donation receipt to a single admin # or a ticket receipt def resend_admin_receipt(payment_id, user_id) @@ -22,5 +23,4 @@ class PaymentMailer < BaseMailer return TicketMailer.followup(payment.tickets.pluck(:id), payment.charge.id).deliver end end - end diff --git a/app/mailers/recurring_donation_mailer.rb b/app/mailers/recurring_donation_mailer.rb index d1a4a649..ce64e58c 100644 --- a/app/mailers/recurring_donation_mailer.rb +++ b/app/mailers/recurring_donation_mailer.rb @@ -1,14 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RecurringDonationMailer < BaseMailer + def send_cancellation_notices(recurring_donation) + UserMailer.recurring_donation_cancelled(recurring_donation).deliver + NonprofitMailer.cancelled_recurring_donation(recurring_donation).deliver + recurring_donation + end - def send_cancellation_notices(recurring_donation) - UserMailer.recurring_donation_cancelled(recurring_donation).deliver - NonprofitMailer.cancelled_recurring_donation(recurring_donation).deliver - return recurring_donation - end - - def send_failure_notifications(recurring_donation) - UserMailer.recurring_donation_failure(recurring_donation).deliver - NonprofitMailer.failed_recurring_donation(recurring_donation).deliver - end + def send_failure_notifications(recurring_donation) + UserMailer.recurring_donation_failure(recurring_donation).deliver + NonprofitMailer.failed_recurring_donation(recurring_donation).deliver + end end diff --git a/app/mailers/testing.rb b/app/mailers/testing.rb index a82ab782..9d064245 100644 --- a/app/mailers/testing.rb +++ b/app/mailers/testing.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Testing < ActionMailer::Base - default from: "from@example.com" + default from: 'from@example.com' end diff --git a/app/mailers/ticket_mailer.rb b/app/mailers/ticket_mailer.rb index 623646d6..7f39b499 100644 --- a/app/mailers/ticket_mailer.rb +++ b/app/mailers/ticket_mailer.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TicketMailer < BaseMailer - helper :application # Pass in ticket_ids, event_id, and supporter - def followup(ticket_ids, charge_id=nil) + def followup(ticket_ids, charge_id = nil) @charge = charge_id ? Charge.find(charge_id) : nil - @tickets = Ticket.where("id IN(?)", ticket_ids) + @tickets = Ticket.where('id IN(?)', ticket_ids) @event = @tickets.last.event @supporter = @tickets.last.supporter @nonprofit = @supporter.nonprofit from = Format::Name.email_from_np(@nonprofit.name) reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email - mail(from: from, to: @supporter.email, reply_to: reply_to, subject: "Your tickets#{@charge ? ' and receipt ' : ' '}for: #{@event.name}") + mail(from: from, to: @supporter.email, reply_to: reply_to, subject: "Your tickets#{@charge ? ' and receipt ' : ' '}for: #{@event.name}") end - def receipt_admin(ticket_ids, user_id=nil) - @tickets = Ticket.where("id IN (?)", ticket_ids) + def receipt_admin(ticket_ids, user_id = nil) + @tickets = Ticket.where('id IN (?)', ticket_ids) @charge = @tickets.last.charge @supporter = @tickets.last.supporter @event = @tickets.last.event @@ -25,9 +26,9 @@ class TicketMailer < BaseMailer if user_id em = User.find(user_id).email return unless recipients.include?(em) + recipients = [em] end mail(to: recipients, subject: "Ticket redeemed for #{@event.name} - #{@supporter.name}") end - end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index f216cc0e..b9a01478 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,26 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class UserMailer < BaseMailer - - def refund_receipt(refund_id) - @refund = Refund.find(refund_id) + def refund_receipt(refund_id) + @refund = Refund.find(refund_id) @nonprofit = @refund.payment.nonprofit - @charge = @refund.charge + @charge = @refund.charge @supporter = @refund.payment.supporter - reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email + reply_to = @nonprofit.email.blank? ? @nonprofit.users.first.email : @nonprofit.email from = Format::Name.email_from_np(@nonprofit.name) - mail(to: @supporter.email, from: from, reply_to: reply_to, subject: "Your refund receipt for #{@nonprofit.name}") - end + mail(to: @supporter.email, from: from, reply_to: reply_to, subject: "Your refund receipt for #{@nonprofit.name}") + end - def recurring_donation_failure(recurring_donation) - @recurring_donation = recurring_donation - mail(:to => @recurring_donation.email, - :subject => ("We couldn't process your recurring donation towards #{@recurring_donation.nonprofit.name}.")) - end - - def recurring_donation_cancelled(recurring_donation) - @recurring_donation = recurring_donation - mail(:to => @recurring_donation.email, - :subject => ("Your recurring donation towards #{@recurring_donation.nonprofit.name} was successfully cancelled.")) - end + def recurring_donation_failure(recurring_donation) + @recurring_donation = recurring_donation + mail(to: @recurring_donation.email, + subject: "We couldn't process your recurring donation towards #{@recurring_donation.nonprofit.name}.") + end + def recurring_donation_cancelled(recurring_donation) + @recurring_donation = recurring_donation + mail(to: @recurring_donation.email, + subject: "Your recurring donation towards #{@recurring_donation.nonprofit.name} was successfully cancelled.") + end end diff --git a/app/models/activity.rb b/app/models/activity.rb index 20a763bf..8dd456c0 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -1,5 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Activity < ApplicationRecord - end - diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 52fec221..9f8f3f0d 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true -end \ No newline at end of file + self.abstract_class = true +end diff --git a/app/models/bank_account.rb b/app/models/bank_account.rb index b7eedb59..aa3d7f98 100644 --- a/app/models/bank_account.rb +++ b/app/models/bank_account.rb @@ -1,42 +1,41 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BankAccount < ApplicationRecord + # TODO + # attr_accessible \ + # :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") + # :confirmation_token, # str (randomly generated private token for email confirmation) + # :account_number, # str (last digits only) + # :bank_name, # str + # :pending_verification, # bool (whether this bank account is still awaiting email confirmation) + # :status, # str + # :email, # str (contact email associated with the user who created this bank account) + # :deleted, # bool (soft delete flag) + # :stripe_bank_account_token, # str + # :stripe_bank_account_id, # str + # :nonprofit_id, :nonprofit - #TODO - # attr_accessible \ - # :name, # str (readable bank name identifier, eg. "Wells Fargo *1234") - # :confirmation_token, # str (randomly generated private token for email confirmation) - # :account_number, # str (last digits only) - # :bank_name, # str - # :pending_verification, # bool (whether this bank account is still awaiting email confirmation) - # :status, # str - # :email, # str (contact email associated with the user who created this bank account) - # :deleted, # bool (soft delete flag) - # :stripe_bank_account_token, # str - # :stripe_bank_account_id, # str - # :nonprofit_id, :nonprofit + # validates :stripe_bank_account_token, presence: true, uniqueness: true + # validates :stripe_bank_account_id, presence: true, uniqueness: true + # validates :nonprofit, presence: true + # validates :email, presence: true, format: {with: Email::Regex} + # validate :nonprofit_must_be_vetted, on: :create + # validate :nonprofit_has_stripe_account - #validates :stripe_bank_account_token, presence: true, uniqueness: true - # validates :stripe_bank_account_id, presence: true, uniqueness: true - #validates :nonprofit, presence: true - #validates :email, presence: true, format: {with: Email::Regex} - #validate :nonprofit_must_be_vetted, on: :create - #validate :nonprofit_has_stripe_account + has_many :payouts + belongs_to :nonprofit - has_many :payouts - belongs_to :nonprofit + def nonprofit_must_be_vetted + errors.add(:nonprofit, 'must be vetted') unless nonprofit&.vetted + end - def nonprofit_must_be_vetted - errors.add(:nonprofit, "must be vetted") unless self.nonprofit && self.nonprofit.vetted - end - - - def nonprofit_has_stripe_account - errors.add(:nonprofit, 'must have a Stripe account id') if !self.nonprofit || self.nonprofit.stripe_account_id.blank? - end - - # Manually cause an instance to become invalid - def invalidate! - @not_valid = true - end + def nonprofit_has_stripe_account + errors.add(:nonprofit, 'must have a Stripe account id') if !nonprofit || nonprofit.stripe_account_id.blank? + end + # Manually cause an instance to become invalid + def invalidate! + @not_valid = true + end end diff --git a/app/models/billing_plan.rb b/app/models/billing_plan.rb index b5468646..ce5eec79 100644 --- a/app/models/billing_plan.rb +++ b/app/models/billing_plan.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BillingPlan < ApplicationRecord - Names = ['Starter', 'Fundraising', 'Supporter Management'] - DefaultAmounts = [0, 9900, 29900] # in pennies + Names = ['Starter', 'Fundraising', 'Supporter Management'].freeze + DefaultAmounts = [0, 9900, 29_900].freeze # in pennies - #TODO - # attr_accessible \ - # :name, #str: readable name - # :tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) - # :amount, #int (cents) - # :stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription - # :interval, #str ('monthly', 'annual') - # :percentage_fee # 0.038 + # TODO + # attr_accessible \ + # :name, #str: readable name + # :tier, #int: 0-4 (0: Free, 1: Fundraising, 2: Supporter Management) + # :amount, #int (cents) + # :stripe_plan_id, #str (matches plan ID in Stripe) Not needed if it's not a paying subscription + # :interval, #str ('monthly', 'annual') + # :percentage_fee # 0.038 - has_many :billing_subscriptions + has_many :billing_subscriptions - validates :name, :presence => true - validates :amount, :presence => true + validates :name, presence: true + validates :amount, presence: true end diff --git a/app/models/billing_subscription.rb b/app/models/billing_subscription.rb index 85b5679e..66b08ede 100644 --- a/app/models/billing_subscription.rb +++ b/app/models/billing_subscription.rb @@ -1,32 +1,31 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class BillingSubscription < ApplicationRecord + # TODO + # attr_accessible \ + # :nonprofit_id, :nonprofit, + # :billing_plan_id, :billing_plan, + # :stripe_subscription_id, + # :status # trialing, active, past_due, canceled, or unpaid - #TODO - # attr_accessible \ - # :nonprofit_id, :nonprofit, - # :billing_plan_id, :billing_plan, - # :stripe_subscription_id, - # :status # trialing, active, past_due, canceled, or unpaid + attr_accessor :stripe_plan_id, :manual + belongs_to :nonprofit + belongs_to :billing_plan - attr_accessor :stripe_plan_id, :manual - belongs_to :nonprofit - belongs_to :billing_plan + validates :nonprofit, presence: true + validates :billing_plan, presence: true - validates :nonprofit, presence: true - validates :billing_plan, presence: true - - def as_json(options={}) - h = super(options) - h[:plan_name] = self.billing_plan.name - h[:plan_amount] = self.billing_plan.amount / 100 - h - end - - def self.create_with_stripe(np, params) - bp = BillingPlan.find_by_stripe_plan_id params[:stripe_plan_id] - h = ConstructBillingSubscription.with_stripe np, bp - return np.create_billing_subscription h - end + def as_json(options = {}) + h = super(options) + h[:plan_name] = billing_plan.name + h[:plan_amount] = billing_plan.amount / 100 + h + end + def self.create_with_stripe(np, params) + bp = BillingPlan.find_by_stripe_plan_id params[:stripe_plan_id] + h = ConstructBillingSubscription.with_stripe np, bp + np.create_billing_subscription h + end end - diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 137381c1..d9be17c9 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -1,186 +1,185 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Campaign < ApplicationRecord + # TODO + # attr_accessible \ + # :name, + # :tagline, + # :slug, # str: url name + # :total_supporters, + # :goal_amount, + # :nonprofit_id, + # :profile_id, + # :main_image, + # :remove_main_image, # for carrierwave + # :background_image, + # :remove_background_image, #bool carrierwave + # :banner_image, + # :remove_banner_image, + # :published, + # :video_url, #str + # :vimeo_video_id, + # :youtube_video_id, + # :summary, + # :recurring_fund, # bool: whether this is a recurring campaign + # :body, + # :goal_amount_dollars, #accessor: translated into goal_amount (cents) + # :show_total_raised, # bool + # :show_total_count, # bool + # :hide_activity_feed, # bool + # :end_datetime, + # :deleted, #bool (soft delete) + # :hide_goal, # bool + # :hide_thermometer, #bool + # :hide_title, # bool + # :receipt_message, # text + # :hide_custom_amounts, # boolean + # :parent_campaign_id, + # :reason_for_supporting, + # :default_reason_for_supporting - #TODO - # attr_accessible \ - # :name, - # :tagline, - # :slug, # str: url name - # :total_supporters, - # :goal_amount, - # :nonprofit_id, - # :profile_id, - # :main_image, - # :remove_main_image, # for carrierwave - # :background_image, - # :remove_background_image, #bool carrierwave - # :banner_image, - # :remove_banner_image, - # :published, - # :video_url, #str - # :vimeo_video_id, - # :youtube_video_id, - # :summary, - # :recurring_fund, # bool: whether this is a recurring campaign - # :body, - # :goal_amount_dollars, #accessor: translated into goal_amount (cents) - # :show_total_raised, # bool - # :show_total_count, # bool - # :hide_activity_feed, # bool - # :end_datetime, - # :deleted, #bool (soft delete) - # :hide_goal, # bool - # :hide_thermometer, #bool - # :hide_title, # bool - # :receipt_message, # text - # :hide_custom_amounts, # boolean - # :parent_campaign_id, - # :reason_for_supporting, - # :default_reason_for_supporting - - validate :end_datetime_cannot_be_in_past, :on => :create - validates :profile, :presence => true - validates :nonprofit, :presence => true - validates :goal_amount, - :presence => true, - :numericality => {:only_integer => true, :greater_than => 99} - validates :name, - :presence => true, - :length => {:maximum => 60} - validates :slug, uniqueness: {scope: :nonprofit_id, message: 'You already have a campaign with that URL.'}, presence: true + validate :end_datetime_cannot_be_in_past, on: :create + validates :profile, presence: true + validates :nonprofit, presence: true + validates :goal_amount, + presence: true, + numericality: { only_integer: true, greater_than: 99 } + validates :name, + presence: true, + length: { maximum: 60 } + validates :slug, uniqueness: { scope: :nonprofit_id, message: 'You already have a campaign with that URL.' }, presence: true attr_accessor :goal_amount_dollars - mount_uploader :main_image, CampaignMainImageUploader - mount_uploader :background_image, CampaignBackgroundImageUploader - mount_uploader :banner_image, CampaignBannerImageUploader + mount_uploader :main_image, CampaignMainImageUploader + mount_uploader :background_image, CampaignBackgroundImageUploader + mount_uploader :banner_image, CampaignBannerImageUploader - has_many :donations - has_many :charges, through: :donations - has_many :payments, { through: :donations, source: "payment" } - has_many :campaign_gift_options - has_many :campaign_gifts, through: :campaign_gift_options - has_many :supporters, :through => :donations - has_many :recurring_donations - has_many :roles, as: :host, dependent: :destroy - has_many :comments, as: :host, dependent: :destroy - has_many :activities, as: :host, dependent: :destroy - belongs_to :profile - belongs_to :nonprofit + has_many :donations + has_many :charges, through: :donations + has_many :payments, through: :donations, source: 'payment' + has_many :campaign_gift_options + has_many :campaign_gifts, through: :campaign_gift_options + has_many :supporters, through: :donations + has_many :recurring_donations + has_many :roles, as: :host, dependent: :destroy + has_many :comments, as: :host, dependent: :destroy + has_many :activities, as: :host, dependent: :destroy + belongs_to :profile + belongs_to :nonprofit belongs_to :parent_campaign, class_name: 'Campaign' has_many :children_campaigns, class_name: 'Campaign', foreign_key: 'parent_campaign_id' - scope :published, -> {where(:published => true)} - scope :active, -> {where(:published => true).where("end_datetime IS NULL OR end_datetime >= ?", Date.today)} - scope :past, -> {where(:published => true).where("end_datetime < ?", Date.today)} - scope :unpublished, -> {where(:published => [nil, false])} - scope :not_deleted, -> {where(deleted: [nil, false])} - scope :deleted, -> {where(deleted: true)} - scope :not_a_child, -> {where(parent_campaign_id: nil)} + scope :published, -> { where(published: true) } + scope :active, -> { where(published: true).where('end_datetime IS NULL OR end_datetime >= ?', Date.today) } + scope :past, -> { where(published: true).where('end_datetime < ?', Date.today) } + scope :unpublished, -> { where(published: [nil, false]) } + scope :not_deleted, -> { where(deleted: [nil, false]) } + scope :deleted, -> { where(deleted: true) } + scope :not_a_child, -> { where(parent_campaign_id: nil) } - before_validation do - if self.goal_amount_dollars.present? - self.goal_amount = (self.goal_amount_dollars.gsub(',','').to_f * 100).to_i - end - self - end + before_validation do + if goal_amount_dollars.present? + self.goal_amount = (goal_amount_dollars.delete(',').to_f * 100).to_i + end + self + end - before_validation(on: :create) do - unless self.slug - self.slug = Format::Url.convert_to_slug(name) - end - self.set_defaults - self - end + before_validation(on: :create) do + self.slug = Format::Url.convert_to_slug(name) unless slug + set_defaults + self + end - before_save do - self.parse_video_id if self.video_url && self.video_url_changed? - self - end + before_save do + parse_video_id if video_url && video_url_changed? + self + end - after_create do - user = self.profile.user - Role.create(name: :campaign_editor, user_id: user.id, host: self) - if child_campaign? - CampaignMailer.delay.federated_creation_followup(self) - else - CampaignMailer.delay.creation_followup(self) - end + after_create do + user = profile.user + Role.create(name: :campaign_editor, user_id: user.id, host: self) + if child_campaign? + CampaignMailer.delay.federated_creation_followup(self) + else + CampaignMailer.delay.creation_followup(self) + end - NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, self.nonprofit_id) - self - end + NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, nonprofit_id) + self + end - def set_defaults + def set_defaults + self.total_supporters = 1 + self.published = false if published.nil? + end - self.total_supporters = 1 - self.published = false if self.published.nil? - end + def parse_video_id + if video_url.include? 'vimeo' + self.vimeo_video_id = video_url.split('/').last + self.youtube_video_id = nil + elsif video_url.include? 'youtube' + match = video_url.match(/\?v=(.+)/) + return if match.nil? + self.youtube_video_id = match[1].split('&').first + self.vimeo_video_id = nil + elsif video_url.include? 'youtu.be' + self.youtube_video_id = video_url.split('/').last + self.vimeo_video_id = nil + elsif video_url.blank? + self.vimeo_video_id = nil + self.youtube_video_id = nil + end + self + end - def parse_video_id - if self.video_url.include? 'vimeo' - self.vimeo_video_id = self.video_url.split('/').last - self.youtube_video_id = nil - elsif self.video_url.include? 'youtube' - match = self.video_url.match(/\?v=(.+)/) - return if match.nil? - self.youtube_video_id = match[1].split('&').first - self.vimeo_video_id = nil - elsif self.video_url.include? 'youtu.be' - self.youtube_video_id = self.video_url.split('/').last - self.vimeo_video_id = nil - elsif self.video_url.blank? - self.vimeo_video_id = nil - self.youtube_video_id = nil - end - self - end + def total_raised + payments.sum(:gross_amount) + end - def total_raised - self.payments.sum(:gross_amount) - end + def percentage_funded + goal_amount.nil? ? 0 : total_raised * 100 / goal_amount + end - def percentage_funded - self.goal_amount.nil? ? 0 : self.total_raised * 100 / self.goal_amount - end + def average_donation + donations.any? ? total_raised / donations.count : 0 + end - def average_donation - self.donations.any? ? self.total_raised / self.donations.count : 0 - end - - # Validations + # Validations def end_datetime_cannot_be_in_past - if self.end_datetime.present? && self.end_datetime < Time.now + if end_datetime.present? && end_datetime < Time.now errors.add(:end_datetime, "can't be in the past") - end - end + end + end - def ready_to_publish? - [(self.body && self.body.length >= 500), (self.campaign_gift_options.count >= 1)].all? - end + def ready_to_publish? + [(body && body.length >= 500), (campaign_gift_options.count >= 1)].all? + end - def url - "#{self.nonprofit.url}/campaigns/#{self.slug}" - end + def url + "#{nonprofit.url}/campaigns/#{slug}" + end - def days_left - return 0 if self.end_datetime.nil? - (self.end_datetime.to_date - Date.today).to_i - end + def days_left + return 0 if end_datetime.nil? - def finished? - self.end_datetime && self.end_datetime < Time.now - end + (end_datetime.to_date - Date.today).to_i + end + + def finished? + end_datetime && end_datetime < Time.now + end def child_params - excluded_for_peer_to_peer = %w( - id created_at updated_at slug profile_id url + excluded_for_peer_to_peer = %w[ + id created_at updated_at slug profile_id url total_raised show_recurring_amount external_identifier parent_campaign_id reason_for_supporting metadata - ) + ] attributes.except(*excluded_for_peer_to_peer) end diff --git a/app/models/campaign_gift.rb b/app/models/campaign_gift.rb index d08a59da..af40b7f4 100644 --- a/app/models/campaign_gift.rb +++ b/app/models/campaign_gift.rb @@ -1,17 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGift < ApplicationRecord + # TODO + # attr_accessible \ + # :donation_id, + # :donation, + # :campaign_gift_option, + # :campaign_gift_option_id - #TODO - # attr_accessible \ - # :donation_id, - # :donation, - # :campaign_gift_option, - # :campaign_gift_option_id - - belongs_to :donation - belongs_to :campaign_gift_option - - validates :donation, presence: true - validates :campaign_gift_option, presence: true + belongs_to :donation + belongs_to :campaign_gift_option + validates :donation, presence: true + validates :campaign_gift_option, presence: true end diff --git a/app/models/campaign_gift_option.rb b/app/models/campaign_gift_option.rb index 187010d1..a8a1348c 100644 --- a/app/models/campaign_gift_option.rb +++ b/app/models/campaign_gift_option.rb @@ -1,36 +1,36 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignGiftOption < ApplicationRecord + # TODO + # attr_accessible \ + # :amount_one_time, #int (cents) + # :amount_recurring, #int (cents) + # :amount_dollars, #str, gets converted to amount + # :description, # text + # :name, # str + # :campaign, #assocation + # :quantity, #int (optional) + # :to_ship, #boolean + # :order, #int (optional) + # :hide_contributions #boolean (optional) - #TODO - # attr_accessible \ - # :amount_one_time, #int (cents) - # :amount_recurring, #int (cents) - # :amount_dollars, #str, gets converted to amount - # :description, # text - # :name, # str - # :campaign, #assocation - # :quantity, #int (optional) - # :to_ship, #boolean - # :order, #int (optional) - # :hide_contributions #boolean (optional) + belongs_to :campaign + has_many :campaign_gifts + has_many :donations, through: :campaign_gifts - belongs_to :campaign - has_many :campaign_gifts - has_many :donations, through: :campaign_gifts + validates :name, presence: true + validates :campaign, presence: true + validates :amount_one_time, presence: true, numericality: { only_integer: true }, unless: :amount_recurring + validates :amount_recurring, presence: true, numericality: { only_integer: true }, unless: :amount_one_time - validates :name, presence: true - validates :campaign, presence: true - validates :amount_one_time, presence: true, numericality: { only_integer: true }, unless: :amount_recurring - validates :amount_recurring, presence: true, numericality: { only_integer: true }, unless: :amount_one_time - - def total_gifts - return self.campaign_gifts.count - end - - def as_json(options={}) - h = super(options) - h[:total_gifts] = self.total_gifts - h - end + def total_gifts + campaign_gifts.count + end + def as_json(options = {}) + h = super(options) + h[:total_gifts] = total_gifts + h + end end diff --git a/app/models/card.rb b/app/models/card.rb index 0c71e983..b5739b84 100755 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -1,26 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Card < ApplicationRecord + # TODO + # attr_accessible \ + # :cardholders_name, # str (name associated with this card) + # :email, # str (cache the email associated with this card) + # :name, # str (readable card name, eg. Visa *1234) + # :failure_message, # accessor for temporarily storing the stripe decline message + # :status, # str + # :stripe_card_token, # str + # :stripe_card_id, # str + # :stripe_customer_id, # str + # :holder, :holder_id, :holder_type, # polymorphic cardholder association + # :inactive # a card is inactive. This is currently only meaningful for nonprofit cards - #TODO - # attr_accessible \ - # :cardholders_name, # str (name associated with this card) - # :email, # str (cache the email associated with this card) - # :name, # str (readable card name, eg. Visa *1234) - # :failure_message, # accessor for temporarily storing the stripe decline message - # :status, # str - # :stripe_card_token, # str - # :stripe_card_id, # str - # :stripe_customer_id, # str - # :holder, :holder_id, :holder_type, # polymorphic cardholder association - # :inactive # a card is inactive. This is currently only meaningful for nonprofit cards - - - attr_accessor :failure_message - - - belongs_to :holder, polymorphic: true - has_many :charges - has_many :donations - has_many :tickets + attr_accessor :failure_message + belongs_to :holder, polymorphic: true + has_many :charges + has_many :donations + has_many :tickets end diff --git a/app/models/charge.rb b/app/models/charge.rb index 42d7161d..d71c823a 100644 --- a/app/models/charge.rb +++ b/app/models/charge.rb @@ -1,37 +1,36 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # A Charge represents a potential debit to a nonprofit's account on a credit card donation action. class Charge < ApplicationRecord + # TODO + # attr_accessible \ + # :amount, + # :fee, + # :stripe_charge_id, + # :status - #TODO - # attr_accessible \ - # :amount, - # :fee, - # :stripe_charge_id, - # :status + has_one :campaign, through: :donation + has_one :recurring_donation, through: :donation + has_many :tickets + has_many :events, through: :tickets + has_many :refunds + has_many :disputes + belongs_to :supporter + belongs_to :card + belongs_to :direct_debit_detail + belongs_to :nonprofit + belongs_to :donation + belongs_to :payment + scope :paid, -> { where(status: %w[available pending disbursed]) } + scope :not_paid, -> { where(status: [nil, 'failed']) } + scope :available, -> { where(status: 'available') } + scope :pending, -> { where(status: 'pending') } + scope :disbursed, -> { where(status: 'disbursed') } - has_one :campaign, through: :donation - has_one :recurring_donation, through: :donation - has_many :tickets - has_many :events, through: :tickets - has_many :refunds - has_many :disputes - belongs_to :supporter - belongs_to :card - belongs_to :direct_debit_detail - belongs_to :nonprofit - belongs_to :donation - belongs_to :payment - - scope :paid, ->{where(status: ["available", "pending", "disbursed"])} - scope :not_paid, ->{where(status: [nil, "failed"])} - scope :available, ->{where(status: "available")} - scope :pending, ->{where(status: "pending")} - scope :disbursed, ->{where(status: "disbursed")} - - def paid? - self.status.in?(%w[available pending disbursed]) - end - + def paid? + status.in?(%w[available pending disbursed]) + end end diff --git a/app/models/comment.rb b/app/models/comment.rb index 8efbcc7b..1fc75312 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,36 +1,36 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Comment < ApplicationRecord + # TODO + # attr_accessible \ + # :host_id, :host_type, #parent: Event, Campaign, nil + # :profile_id, + # :body - #TODO - # attr_accessible \ - # :host_id, :host_type, #parent: Event, Campaign, nil - # :profile_id, - # :body + validates :profile, presence: true + validates :body, presence: true, length: { maximum: 200 } - validates :profile, :presence => true - validates :body, :presence => true, :length => {:maximum => 200} + has_one :activity, as: :attachment, dependent: :destroy + belongs_to :host, polymorphic: true + belongs_to :donation + belongs_to :profile - has_one :activity, :as => :attachment, :dependent => :destroy - belongs_to :host, :polymorphic => true - belongs_to :donation - belongs_to :profile + before_validation(on: :create) do + remove_newlines + end - before_validation(:on => :create) do - remove_newlines - end - - after_create do - self.create_activity({ - :desc => 'commented', - :profile_id => self.profile_id, - :host_id => self.host_id, - :host_type => self.host_type, - :body => self.body - }) - end - - def remove_newlines - self.body = self.body && self.body.gsub(/\n/,'') - end + after_create do + create_activity( + desc: 'commented', + profile_id: profile_id, + host_id: host_id, + host_type: host_type, + body: body + ) + end + def remove_newlines + self.body = body && body.delete("\n") + end end diff --git a/app/models/coupon.rb b/app/models/coupon.rb index 5b8b5f7c..0453c9e3 100644 --- a/app/models/coupon.rb +++ b/app/models/coupon.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Coupon < ApplicationRecord - # attr_accessible \ - # :name, - # :victim_np_id, - # :paid, # boolean - # :nonprofit, :nonprofit_id + # attr_accessible \ + # :name, + # :victim_np_id, + # :paid, # boolean + # :nonprofit, :nonprofit_id - scope :unpaid, -> {where(paid: [nil,false])} + scope :unpaid, -> { where(paid: [nil, false]) } - validates_presence_of :name, :nonprofit_id, :victim_np_id + validates_presence_of :name, :nonprofit_id, :victim_np_id end diff --git a/app/models/custom_field_join.rb b/app/models/custom_field_join.rb index fb915709..fcd27739 100644 --- a/app/models/custom_field_join.rb +++ b/app/models/custom_field_join.rb @@ -1,26 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CustomFieldJoin < ApplicationRecord + # TODO + # attr_accessible \ + # :supporter, :supporter_id, + # :custom_field_master, :custom_field_master_id, + # :value - #TODO - # attr_accessible \ - # :supporter, :supporter_id, - # :custom_field_master, :custom_field_master_id, - # :value + validates :custom_field_master, presence: true - validates :custom_field_master, presence: true - - belongs_to :custom_field_master + belongs_to :custom_field_master belongs_to :supporter - def self.create_with_name(nonprofit, h) - cfm = nonprofit.custom_field_masters.find_by_name(h['name']) - if cfm.nil? - cfm = nonprofit.custom_field_masters.create(name: h['name']) - end - self.create({value: h['value'], custom_field_master_id: cfm.id, supporter_id: h['supporter_id']}) - end - - def name; custom_field_master.name; end + def self.create_with_name(nonprofit, h) + cfm = nonprofit.custom_field_masters.find_by_name(h['name']) + cfm = nonprofit.custom_field_masters.create(name: h['name']) if cfm.nil? + create(value: h['value'], custom_field_master_id: cfm.id, supporter_id: h['supporter_id']) + end + def name + custom_field_master.name +end end - diff --git a/app/models/custom_field_master.rb b/app/models/custom_field_master.rb index b528b373..d2e386c0 100644 --- a/app/models/custom_field_master.rb +++ b/app/models/custom_field_master.rb @@ -1,24 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CustomFieldMaster < ApplicationRecord + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :created_at - # attr_accessible \ - # :nonprofit, :nonprofit_id, - # :name, - # :deleted, - # :created_at + validates :name, presence: true + validate :no_dupes, on: :create - validates :name, presence: true - validate :no_dupes, on: :create + belongs_to :nonprofit + has_many :custom_field_joins, dependent: :destroy - belongs_to :nonprofit - has_many :custom_field_joins, dependent: :destroy + scope :not_deleted, -> { where(deleted: [nil, false]) } - scope :not_deleted, ->{where(deleted: [nil,false])} - - def no_dupes - return self if nonprofit.nil? - errors.add(:base, "Duplicate custom field") if nonprofit.custom_field_masters.not_deleted.where(name: name).any? - end + def no_dupes + return self if nonprofit.nil? + errors.add(:base, 'Duplicate custom field') if nonprofit.custom_field_masters.not_deleted.where(name: name).any? + end end - diff --git a/app/models/direct_debit_detail.rb b/app/models/direct_debit_detail.rb index a8e96676..59efae5e 100644 --- a/app/models/direct_debit_detail.rb +++ b/app/models/direct_debit_detail.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class DirectDebitDetail < ApplicationRecord # attr_accessible :iban, :account_holder_name, :bic, :supporter_id, :holder diff --git a/app/models/dispute.rb b/app/models/dispute.rb index 78bd2754..aa01fb80 100644 --- a/app/models/dispute.rb +++ b/app/models/dispute.rb @@ -1,11 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Dispute < ApplicationRecord + Reasons = %i[unrecognized duplicate fraudulent subscription_canceled product_unacceptable product_not_received unrecognized credit_not_processed goods_services_returned_or_refused goods_services_cancelled incorrect_account_details insufficient_funds bank_cannot_process debit_not_authorized general].freeze - Reasons = [:unrecognized, :duplicate, :fraudulent, :subscription_canceled, :product_unacceptable, :product_not_received, :unrecognized, :credit_not_processed, :goods_services_returned_or_refused, :goods_services_cancelled, :incorrect_account_details, :insufficient_funds, :bank_cannot_process, :debit_not_authorized, :general] - - - Statuses = [:needs_response, :under_review, :won, :lost, :lost_and_paid] - #TODO + Statuses = %i[needs_response under_review won lost lost_and_paid].freeze + # TODO # attr_accessible \ # :gross_amount, # int # :charge_id, :charge, @@ -15,6 +15,4 @@ class Dispute < ApplicationRecord belongs_to :charge belongs_to :payment - end - diff --git a/app/models/donation.rb b/app/models/donation.rb index b830b8b6..d5b77719 100644 --- a/app/models/donation.rb +++ b/app/models/donation.rb @@ -1,49 +1,50 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Donation < ApplicationRecord + # TODO + # attr_accessible \ + # :date, # datetime (when this donation was made) + # :amount, # int (in cents) + # :recurring, # bool + # :anonymous, # bool + # :email, # str (cached email of the donor) + # :designation, # text + # :dedication, # text + # :comment, # text + # :origin_url, # text + # :nonprofit_id, :nonprofit, + # :card_id, :card, # Card with which any charges were made + # :supporter_id, :supporter, + # :profile_id, :profile, + # :campaign_id, :campaign, + # :payment_id, :payment, + # :event_id, :event, + # :direct_debit_detail_id, :direct_debit_detail, + # :payment_provider - #TODO - # attr_accessible \ - # :date, # datetime (when this donation was made) - # :amount, # int (in cents) - # :recurring, # bool - # :anonymous, # bool - # :email, # str (cached email of the donor) - # :designation, # text - # :dedication, # text - # :comment, # text - # :origin_url, # text - # :nonprofit_id, :nonprofit, - # :card_id, :card, # Card with which any charges were made - # :supporter_id, :supporter, - # :profile_id, :profile, - # :campaign_id, :campaign, - # :payment_id, :payment, - # :event_id, :event, - # :direct_debit_detail_id, :direct_debit_detail, - # :payment_provider + validates :amount, presence: true, numericality: { only_integer: true } + validates :supporter, presence: true + validates :nonprofit, presence: true + validates_associated :charges + validates :payment_provider, inclusion: { in: %w[credit_card sepa] }, allow_blank: true - validates :amount, presence: true, numericality: { only_integer: true } - validates :supporter, presence: true - validates :nonprofit, presence: true - validates_associated :charges - validates :payment_provider, inclusion: { in: ["credit_card", "sepa"]}, allow_blank: true + has_many :charges + has_many :campaign_gifts, dependent: :destroy + has_many :campaign_gift_options, through: :campaign_gifts + has_many :activities, as: :attachment, dependent: :destroy + has_many :payments + has_one :recurring_donation + has_one :payment + has_one :offsite_payment + has_one :tracking + belongs_to :supporter + belongs_to :card + belongs_to :direct_debit_detail + belongs_to :profile + belongs_to :nonprofit + belongs_to :campaign + belongs_to :event - has_many :charges - has_many :campaign_gifts, dependent: :destroy - has_many :campaign_gift_options, through: :campaign_gifts - has_many :activities, as: :attachment, dependent: :destroy - has_many :payments - has_one :recurring_donation - has_one :payment - has_one :offsite_payment - has_one :tracking - belongs_to :supporter - belongs_to :card - belongs_to :direct_debit_detail - belongs_to :profile - belongs_to :nonprofit - belongs_to :campaign - belongs_to :event - - scope :anonymous, -> {where(anonymous: true)} + scope :anonymous, -> { where(anonymous: true) } end diff --git a/app/models/email_draft.rb b/app/models/email_draft.rb index 7de0e030..ed7047dd 100644 --- a/app/models/email_draft.rb +++ b/app/models/email_draft.rb @@ -1,16 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailDraft < ApplicationRecord - #TODO - # attr_accessible \ - # :nonprofit, :nonprofit_id, - # :name, - # :deleted, - # :value, - # :created_at + # TODO + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :value, + # :created_at - belongs_to :nonprofit - - scope :not_deleted, ->{where(deleted: [nil,false])} + belongs_to :nonprofit + scope :not_deleted, -> { where(deleted: [nil, false]) } end - diff --git a/app/models/email_list.rb b/app/models/email_list.rb index f60af7d0..80979b51 100644 --- a/app/models/email_list.rb +++ b/app/models/email_list.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailList < ApplicationRecord # attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master diff --git a/app/models/email_setting.rb b/app/models/email_setting.rb index d81db281..1f6a19e3 100644 --- a/app/models/email_setting.rb +++ b/app/models/email_setting.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailSetting < ApplicationRecord - - #TODO + # TODO # attr_accessible \ # :user_id, :user, # :nonprofit_id, :nonprofit, @@ -13,5 +14,4 @@ class EmailSetting < ApplicationRecord belongs_to :nonprofit belongs_to :user - end diff --git a/app/models/event.rb b/app/models/event.rb index 0e88dc03..bba09a11 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,105 +1,102 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Event < ApplicationRecord + # TODO + # attr_accessible \ + # :deleted, #bool for soft-delete + # :name, # str + # :tagline, # str + # :summary, # text + # :body, # text (html) + # :end_datetime, + # :start_datetime, + # :latitude, # float + # :longitude, # float + # :location, # str + # :city, # str + # :state_code, # str + # :address, # str + # :zip_code, # str + # :main_image, # str + # :remove_main_image, # for carrierwave + # :background_image, # str + # :remove_background_image, # bool carrierwave + # :published, # bool + # :slug, # str + # :directions, # text + # :venue_name, # str + # :profile_id, # creator + # :ticket_levels_attributes, + # :show_total_raised, # bool + # :show_total_count, # bool + # :hide_activity_feed, # bool + # :nonprofit_id, # host + # :hide_title, # bool + # :organizer_email, # string + # :receipt_message # text - #TODO - # attr_accessible \ - # :deleted, #bool for soft-delete - # :name, # str - # :tagline, # str - # :summary, # text - # :body, # text (html) - # :end_datetime, - # :start_datetime, - # :latitude, # float - # :longitude, # float - # :location, # str - # :city, # str - # :state_code, # str - # :address, # str - # :zip_code, # str - # :main_image, # str - # :remove_main_image, # for carrierwave - # :background_image, # str - # :remove_background_image, # bool carrierwave - # :published, # bool - # :slug, # str - # :directions, # text - # :venue_name, # str - # :profile_id, # creator - # :ticket_levels_attributes, - # :show_total_raised, # bool - # :show_total_count, # bool - # :hide_activity_feed, # bool - # :nonprofit_id, # host - # :hide_title, # bool - # :organizer_email, # string - # :receipt_message # text + validates :name, presence: true + validates :end_datetime, presence: true + validates :start_datetime, presence: true + validates :address, presence: true + validates :city, presence: true + validates :state_code, presence: true + validates :slug, presence: true, uniqueness: { scope: :nonprofit_id, message: 'You already have an event with that URL' } + validates :nonprofit_id, presence: true + validates :profile_id, presence: true - validates :name, :presence => true - validates :end_datetime, :presence => true - validates :start_datetime, :presence => true - validates :address, :presence => true - validates :city, :presence => true - validates :state_code, :presence => true - validates :slug, :presence => true, uniqueness: {scope: :nonprofit_id, message: 'You already have an event with that URL'} - validates :nonprofit_id, :presence => true - validates :profile_id, :presence => true - - belongs_to :nonprofit - belongs_to :profile - has_many :donations - has_many :charges, through: :tickets - has_many :supporters, through: :donations - has_many :recurring_donations - has_many :ticket_levels, :dependent => :destroy + belongs_to :nonprofit + belongs_to :profile + has_many :donations + has_many :charges, through: :tickets + has_many :supporters, through: :donations + has_many :recurring_donations + has_many :ticket_levels, dependent: :destroy has_many :event_discounts, dependent: :destroy - has_many :tickets - has_many :payments, through: :tickets - has_many :roles, as: :host, dependent: :destroy - has_many :comments, as: :host, dependent: :destroy - has_many :activities, as: :host, dependent: :destroy + has_many :tickets + has_many :payments, through: :tickets + has_many :roles, as: :host, dependent: :destroy + has_many :comments, as: :host, dependent: :destroy + has_many :activities, as: :host, dependent: :destroy + geocoded_by :full_address - geocoded_by :full_address + accepts_nested_attributes_for :ticket_levels, allow_destroy: true - accepts_nested_attributes_for :ticket_levels, :allow_destroy => true + mount_uploader :main_image, EventMainImageUploader + mount_uploader :background_image, EventBackgroundImageUploader - mount_uploader :main_image, EventMainImageUploader - mount_uploader :background_image, EventBackgroundImageUploader + scope :not_deleted, -> { where(deleted: [nil, false]) } + scope :deleted, -> { where(deleted: true) } + scope :published, -> { where(published: true) } + scope :upcoming, -> { where('start_datetime >= ?', Date.today).published } + scope :past, -> { where('end_datetime < ?', Date.today).published } + scope :unpublished, -> { where('published != ?', true) } - scope :not_deleted, -> {where(deleted: [nil,false])} - scope :deleted, -> {where(deleted: true)} - scope :published, -> {where(:published => true)} - scope :upcoming, -> {where("start_datetime >= ?", Date.today).published} - scope :past, -> {where("end_datetime < ?", Date.today).published} - scope :unpublished, -> {where("published != ?", true)} + validates :slug, uniqueness: { scope: :nonprofit_id, message: 'You already have a campaign with that name.' } - validates :slug, uniqueness: {scope: :nonprofit_id, message: 'You already have a campaign with that name.'} - - before_validation(on: :create) do - unless self.slug - self.slug = Format::Url.convert_to_slug(name) - end - self.published = false if self.published.nil? - self.total_raised ||= 0 + before_validation(on: :create) do + self.slug = Format::Url.convert_to_slug(name) unless slug + self.published = false if published.nil? + self.total_raised ||= 0 self - end - - after_validation :geocode - - after_create do - user = self.profile.user - Role.create(name: :event_editor, user_id: user.id, host: self) - EventMailer.delay.creation_followup(self) - self - end - - def url - "#{self.nonprofit.url}/events/#{self.slug}" - end - - def full_address - Format::Address.full_address(self.address, self.city, self.state_code, self.zip_code) end + after_validation :geocode + + after_create do + user = profile.user + Role.create(name: :event_editor, user_id: user.id, host: self) + EventMailer.delay.creation_followup(self) + self + end + + def url + "#{nonprofit.url}/events/#{slug}" + end + + def full_address + Format::Address.full_address(address, city, state_code, zip_code) + end end diff --git a/app/models/event_discount.rb b/app/models/event_discount.rb index d09d5c9b..7f7d9e15 100644 --- a/app/models/event_discount.rb +++ b/app/models/event_discount.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventDiscount < ApplicationRecord - #TODO + # TODO # attr_accessible \ # :code, # :event_id, @@ -9,5 +11,4 @@ class EventDiscount < ApplicationRecord belongs_to :event has_many :tickets - end diff --git a/app/models/export.rb b/app/models/export.rb index 83f066c2..c7a3a773 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Export < ApplicationRecord - STATUS = %w[queued started completed failed].freeze # attr_accessible :exception, :nonprofit, :status, :user, :export_type, :parameters, :ended, :url, :user_id, :nonprofit_id diff --git a/app/models/full_contact_info.rb b/app/models/full_contact_info.rb index 2035a618..501fbc92 100644 --- a/app/models/full_contact_info.rb +++ b/app/models/full_contact_info.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactInfo < ApplicationRecord - #TODO - # attr_accessible \ - # :email, - # :full_name, - # :gender, - # :city, - # :county, - # :state_code, - # :country, - # :continent, - # :age, - # :age_range, - # :location_general, - # :supporter_id, :supporter, - # :websites + # TODO + # attr_accessible \ + # :email, + # :full_name, + # :gender, + # :city, + # :county, + # :state_code, + # :country, + # :continent, + # :age, + # :age_range, + # :location_general, + # :supporter_id, :supporter, + # :websites - has_many :full_contact_photos - has_many :full_contact_social_profiles - has_many :full_contact_orgs - has_many :full_contact_topics + has_many :full_contact_photos + has_many :full_contact_social_profiles + has_many :full_contact_orgs + has_many :full_contact_topics belongs_to :supporter end diff --git a/app/models/full_contact_org.rb b/app/models/full_contact_org.rb index 2f0b0a43..f457b5bc 100644 --- a/app/models/full_contact_org.rb +++ b/app/models/full_contact_org.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactOrg < ApplicationRecord - - #TODO - # attr_accessible \ + # TODO + # attr_accessible \ # :name, # :is_primary, # :name, @@ -13,5 +14,4 @@ class FullContactOrg < ApplicationRecord # :full_contact_info_id, :full_contact_info belongs_to :full_contact_info - end diff --git a/app/models/full_contact_photo.rb b/app/models/full_contact_photo.rb index 181b92fe..de86b272 100644 --- a/app/models/full_contact_photo.rb +++ b/app/models/full_contact_photo.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactPhoto < ApplicationRecord - #TODO - # attr_accessible \ - # :full_contact_info, - # :full_contact_info_id, - # :type_id, # i.e. twitter, linkedin, facebook - # :is_primary, #bool - # :url #string + # TODO + # attr_accessible \ + # :full_contact_info, + # :full_contact_info_id, + # :type_id, # i.e. twitter, linkedin, facebook + # :is_primary, #bool + # :url #string - belongs_to :full_contact_info + belongs_to :full_contact_info - validates_presence_of :full_contact_info -end \ No newline at end of file + validates_presence_of :full_contact_info +end diff --git a/app/models/full_contact_social_profile.rb b/app/models/full_contact_social_profile.rb index b85511dd..4cdacf24 100644 --- a/app/models/full_contact_social_profile.rb +++ b/app/models/full_contact_social_profile.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactSocialProfile < ApplicationRecord - #TODO - # attr_accessible \ - # :full_contact_info, - # :full_contact_info_id, - # :type_id, # i.e. twitter, linkedin, facebook - # :username, #string - # :uid, # string - # :bio, #string - # :url #string + # TODO + # attr_accessible \ + # :full_contact_info, + # :full_contact_info_id, + # :type_id, # i.e. twitter, linkedin, facebook + # :username, #string + # :uid, # string + # :bio, #string + # :url #string - belongs_to :full_contact_info + belongs_to :full_contact_info - validates_presence_of :full_contact_info -end \ No newline at end of file + validates_presence_of :full_contact_info +end diff --git a/app/models/full_contact_topic.rb b/app/models/full_contact_topic.rb index 5dcdbf97..98f6fe37 100644 --- a/app/models/full_contact_topic.rb +++ b/app/models/full_contact_topic.rb @@ -1,12 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class FullContactTopic < ApplicationRecord - - #TODO - # attr_accessible \ + # TODO + # attr_accessible \ # :provider, # :value, # :full_contact_info_id, :full_contact_info belongs_to :full_contact_info - end diff --git a/app/models/image_attachment.rb b/app/models/image_attachment.rb index 642ba68c..ce97e086 100644 --- a/app/models/image_attachment.rb +++ b/app/models/image_attachment.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ImageAttachment < ApplicationRecord + attr_accessible :parent_id, :file + mount_uploader :file, ImageAttachmentUploader - attr_accessible :parent_id, :file - mount_uploader :file, ImageAttachmentUploader - - # not sure if poly parent is used on this model, as all values are nil in db - belongs_to :parent, :polymorphic => true - + # not sure if poly parent is used on this model, as all values are nil in db + belongs_to :parent, polymorphic: true end diff --git a/app/models/import.rb b/app/models/import.rb index 4c056f1e..8a93f4c6 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -1,20 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Import < ApplicationRecord + # TODO + # attr_accessible \ + # :user_id, :user, + # :email, # email of the user who ma + # :nonprofit_id, :nonprofit, + # :row_count, + # :imported_count, + # :date - #TODO - # attr_accessible \ - # :user_id, :user, - # :email, # email of the user who ma - # :nonprofit_id, :nonprofit, - # :row_count, - # :imported_count, - # :date - - has_many :supporters - belongs_to :nonprofit - belongs_to :user - - validates :user, presence: true + has_many :supporters + belongs_to :nonprofit + belongs_to :user + validates :user, presence: true end - diff --git a/app/models/miscellaneous_np_info.rb b/app/models/miscellaneous_np_info.rb index 240d6478..6a15fee8 100644 --- a/app/models/miscellaneous_np_info.rb +++ b/app/models/miscellaneous_np_info.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class MiscellaneousNpInfo < ApplicationRecord - - #TODO + # TODO # attr_accessible \ # :donate_again_url, # :change_amount_message diff --git a/app/models/nonprofit.rb b/app/models/nonprofit.rb index f03781f1..25c0ad29 100755 --- a/app/models/nonprofit.rb +++ b/app/models/nonprofit.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Nonprofit < ApplicationRecord + Categories = ['Public Benefit', 'Human Services', 'Education', 'Civic Duty', 'Human Rights', 'Animals', 'Environment', 'Health', 'Arts, Culture, Humanities', 'International', 'Children', 'Religion', 'LGBTQ', "Women's Rights", 'Disaster Relief', 'Veterans'].freeze - Categories = ["Public Benefit", "Human Services", "Education", "Civic Duty", "Human Rights", "Animals", "Environment", "Health", "Arts, Culture, Humanities", "International", "Children", "Religion", "LGBTQ", "Women's Rights", "Disaster Relief", "Veterans"] - - #TODO + # TODO # attr_accessible \ # :name, # str # :stripe_account_id, # str @@ -74,7 +75,7 @@ class Nonprofit < ApplicationRecord has_many :email_settings has_many :cards, as: :holder - has_one :bank_account, -> { where("COALESCE(deleted, false) = false") }, + has_one :bank_account, -> { where('COALESCE(deleted, false) = false') }, dependent: :destroy has_one :billing_subscription, dependent: :destroy has_one :billing_plan, through: :billing_subscription @@ -84,12 +85,12 @@ class Nonprofit < ApplicationRecord validates :city, presence: true validates :state_code, presence: true validates :email, format: { with: Email::Regex }, allow_blank: true - validates_uniqueness_of :slug, scope: [:city_slug, :state_code_slug] + validates_uniqueness_of :slug, scope: %i[city_slug state_code_slug] validates_presence_of :slug - scope :vetted, -> {where(vetted: true)} - scope :identity_verified, -> {where(verification_status: 'verified')} - scope :published, -> {where(published: true)} + scope :vetted, -> { where(vetted: true) } + scope :identity_verified, -> { where(verification_status: 'verified') } + scope :published, -> { where(published: true) } mount_uploader :main_image, NonprofitUploader mount_uploader :second_image, NonprofitUploader @@ -103,20 +104,19 @@ class Nonprofit < ApplicationRecord geocoded_by :full_address before_validation(on: :create) do - self.set_slugs + set_slugs self end # Register (create) a nonprofit with an initial admin def self.register(user, params) - np = self.create ConstructNonprofit.construct(user, params) + np = create ConstructNonprofit.construct(user, params) role = Role.create(user: user, name: 'nonprofit_admin', host: np) if np.valid? - return np + np end - def nonprofit_personnel_emails - self.roles.nonprofit_personnel.joins(:user).pluck('users.email') + roles.nonprofit_personnel.joins(:user).pluck('users.email') end def total_recurring @@ -125,62 +125,59 @@ class Nonprofit < ApplicationRecord def donation_history_monthly donation_history_monthly = [] - donations.order("created_at") - .group_by{|d| d.created_at.beginning_of_month} - .each{|_, ds| donation_history_monthly.push(ds.map(&:amount).sum)} + donations.order('created_at') + .group_by { |d| d.created_at.beginning_of_month } + .each { |_, ds| donation_history_monthly.push(ds.map(&:amount).sum) } donation_history_monthly end def as_json(options = {}) h = super(options) - h[:url] = self.url + h[:url] = url h end def url - "/#{self.state_code_slug}/#{self.city_slug}/#{self.slug}" + "/#{state_code_slug}/#{city_slug}/#{slug}" end def set_slugs - unless (self.slug) - self.slug = Format::Url.convert_to_slug self.name - end - unless (self.city_slug) - self.city_slug = Format::Url.convert_to_slug self.city - end + self.slug = Format::Url.convert_to_slug name unless slug + self.city_slug = Format::Url.convert_to_slug city unless city_slug - unless (self.state_code_slug) - self.state_code_slug = Format::Url.convert_to_slug self.state_code + unless state_code_slug + self.state_code_slug = Format::Url.convert_to_slug state_code end self end def full_address - Format::Address.full_address(self.address, self.city, self.state_code) + Format::Address.full_address(address, city, state_code) end def total_raised - QueryPayments.get_payout_totals( QueryPayments.ids_for_payout(self.id))['net_amount'] + QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(id))['net_amount'] end def can_make_payouts - self.vetted && - self.verification_status == 'verified' && - self.bank_account && - !self.bank_account.pending_verification + vetted && + verification_status == 'verified' && + bank_account && + !bank_account.pending_verification end def active_cards - cards.where("COALESCE(cards.inactive, FALSE) = FALSE") + cards.where('COALESCE(cards.inactive, FALSE) = FALSE') end # @param [Card] card the new active_card def active_card=(card) unless card.class == Card - raise ArgumentError.new "Pass a card to active_card or else" + raise ArgumentError, 'Pass a card to active_card or else' end + Card.transaction do - active_cards.update_all :inactive => true + active_cards.update_all inactive: true return cards << card end end @@ -190,14 +187,15 @@ class Nonprofit < ApplicationRecord end def create_active_card(card_data) - if (card_data[:inactive]) - raise ArgumentError.new "This method is for creating active cards only" + if card_data[:inactive] + raise ArgumentError, 'This method is for creating active cards only' end - active_cards.update_all :inactive => true - return cards.create(card_data) + + active_cards.update_all inactive: true + cards.create(card_data) end def currency_symbol - Settings.intntl.all_currencies.find{|i| i.abbv.downcase == currency.downcase}&.symbol + Settings.intntl.all_currencies.find { |i| i.abbv.casecmp(currency).zero? }&.symbol end end diff --git a/app/models/nonprofit_account.rb b/app/models/nonprofit_account.rb index b4f67ffe..5410c269 100644 --- a/app/models/nonprofit_account.rb +++ b/app/models/nonprofit_account.rb @@ -1,14 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NonprofitAccount < ApplicationRecord + # TODO + # attr_accessible \ + # :stripe_account_id, #str + # :nonprofit, :nonprofit_id #int - #TODO - # attr_accessible \ - # :stripe_account_id, #str - # :nonprofit, :nonprofit_id #int - - belongs_to :nonprofit - - validates :nonprofit, presence: true - validates :stripe_account_id, presence: true + belongs_to :nonprofit + validates :nonprofit, presence: true + validates :stripe_account_id, presence: true end diff --git a/app/models/offsite_payment.rb b/app/models/offsite_payment.rb index 798ef1c9..abdbcd37 100644 --- a/app/models/offsite_payment.rb +++ b/app/models/offsite_payment.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class OffsitePayment < ApplicationRecord - - # attr_accessible :gross_amount, :kind, :date, :check_number - belongs_to :payment, dependent: :destroy - belongs_to :donation - belongs_to :nonprofit - belongs_to :supporter - + # attr_accessible :gross_amount, :kind, :date, :check_number + belongs_to :payment, dependent: :destroy + belongs_to :donation + belongs_to :nonprofit + belongs_to :supporter end diff --git a/app/models/payment.rb b/app/models/payment.rb index be3d68e8..f355d8f2 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -1,30 +1,30 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # A payment represents the event where a nonprofit receives money from a supporter # If connected to a charge, this represents money potentially debited to the nonprofit's account # If connected to an offsite_payment, this is money the nonprofit is recording for convenience. class Payment < ApplicationRecord + # TODO + # attr_accessible \ + # :towards, + # :gross_amount, + # :refund_total, + # :fee_total, + # :kind, + # :date -#TODO -# attr_accessible \ -# :towards, -# :gross_amount, -# :refund_total, -# :fee_total, -# :kind, -# :date - - belongs_to :supporter - belongs_to :nonprofit - has_one :charge - has_one :offsite_payment - has_one :refund - has_one :dispute - belongs_to :donation - has_many :tickets - has_one :campaign, through: :donation - has_many :events, through: :tickets - has_many :payment_payouts - has_many :charges - + belongs_to :supporter + belongs_to :nonprofit + has_one :charge + has_one :offsite_payment + has_one :refund + has_one :dispute + belongs_to :donation + has_many :tickets + has_one :campaign, through: :donation + has_many :events, through: :tickets + has_many :payment_payouts + has_many :charges end diff --git a/app/models/payment_import.rb b/app/models/payment_import.rb index 5980928f..4d9fa279 100644 --- a/app/models/payment_import.rb +++ b/app/models/payment_import.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class PaymentImport < ApplicationRecord # attr_accessible :nonprofit, :user diff --git a/app/models/payment_payout.rb b/app/models/payment_payout.rb index b3b01465..f5dc5354 100644 --- a/app/models/payment_payout.rb +++ b/app/models/payment_payout.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # charge_payouts are a join table between charges and payouts # @@ -12,19 +14,17 @@ # since our fees will continue to change as our transaction volume increases class PaymentPayout < ApplicationRecord + # TODO + # attr_accessible \ + # :payment_id, :payment, + # :charge_id, :charge, # deprecated + # :payout_id, :payout, + # :total_fees # int (cents) - #TODO - # attr_accessible \ - # :payment_id, :payment, - # :charge_id, :charge, # deprecated - # :payout_id, :payout, - # :total_fees # int (cents) + belongs_to :charge # deprecated + belongs_to :payment + belongs_to :payout - belongs_to :charge # deprecated - belongs_to :payment - belongs_to :payout - - validates :payment, presence: true - validates :payout, presence: true + validates :payment, presence: true + validates :payout, presence: true end - diff --git a/app/models/payout.rb b/app/models/payout.rb index 6529ea1d..26222453 100644 --- a/app/models/payout.rb +++ b/app/models/payout.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Payouts record a credit of the total pending balance on a nonprofit's account # to their bank account or debit card @@ -5,54 +7,50 @@ # These are tied to Stripe transfers class Payout < ApplicationRecord + # TODO + # attr_accessible \ + # :scheduled, # bool (whether this was made automatically at the beginning of the month) + # :count, # int (number of donations for this payout) + # :ach_fee, # int (in cents, the total fee for the payout itself) + # :gross_amount, # int (in cents, total amount before fees) + # :fee_total, # int (in cents, total amount of fees) + # :net_amount, # int (in cents, total amount after fees for this payout) + # :email, # str (cache of user email who issued this) + # :user_ip, # str (ip address of the user who made this payout) + # :status, # str ('pending', 'paid', 'canceled', or 'failed') + # :failure_message, # str + # :bank_name, # str: cache of the nonprofit's bank name + # :stripe_transfer_id, # str + # :nonprofit_id, :nonprofit - #TODO - # attr_accessible \ - # :scheduled, # bool (whether this was made automatically at the beginning of the month) - # :count, # int (number of donations for this payout) - # :ach_fee, # int (in cents, the total fee for the payout itself) - # :gross_amount, # int (in cents, total amount before fees) - # :fee_total, # int (in cents, total amount of fees) - # :net_amount, # int (in cents, total amount after fees for this payout) - # :email, # str (cache of user email who issued this) - # :user_ip, # str (ip address of the user who made this payout) - # :status, # str ('pending', 'paid', 'canceled', or 'failed') - # :failure_message, # str - # :bank_name, # str: cache of the nonprofit's bank name - # :stripe_transfer_id, # str - # :nonprofit_id, :nonprofit + belongs_to :nonprofit + has_one :bank_account, through: :nonprofit + has_many :payment_payouts + has_many :payments, through: :payment_payouts - belongs_to :nonprofit - has_one :bank_account, through: :nonprofit - has_many :payment_payouts - has_many :payments, through: :payment_payouts + validates :stripe_transfer_id, presence: true, uniqueness: true + validates :nonprofit, presence: true + validates :bank_account, presence: true + validates :email, presence: true + validates :net_amount, presence: true, numericality: { greater_than: 0 } + validate :nonprofit_must_be_vetted, on: :create + validate :nonprofit_must_have_identity_verified, on: :create + validate :bank_account_must_be_confirmed, on: :create - validates :stripe_transfer_id, presence: true, uniqueness: true - validates :nonprofit, presence: true - validates :bank_account, presence: true - validates :email, presence: true - validates :net_amount, presence: true, numericality: {greater_than: 0} - validate :nonprofit_must_be_vetted, on: :create - validate :nonprofit_must_have_identity_verified, on: :create - validate :bank_account_must_be_confirmed, on: :create + scope :pending, -> { where(status: 'pending') } + scope :paid, -> { where(status: %w[paid succeeded]) } - scope :pending, -> {where(status: 'pending')} - scope :paid, -> {where(status: ['paid', 'succeeded'])} + def bank_account_must_be_confirmed + if bank_account&.pending_verification + errors.add(:bank_account, 'must be confirmed via email') + end + end + def nonprofit_must_have_identity_verified + errors.add(:nonprofit, 'must be verified') unless nonprofit && nonprofit.verification_status == 'verified' + end - def bank_account_must_be_confirmed - if self.bank_account && self.bank_account.pending_verification - self.errors.add(:bank_account, 'must be confirmed via email') - end - end - - def nonprofit_must_have_identity_verified - self.errors.add(:nonprofit, "must be verified") unless self.nonprofit && self.nonprofit.verification_status == 'verified' - end - - def nonprofit_must_be_vetted - self.errors.add(:nonprofit, "must be vetted") unless self.nonprofit && self.nonprofit.vetted - end - + def nonprofit_must_be_vetted + errors.add(:nonprofit, 'must be vetted') unless nonprofit&.vetted + end end - diff --git a/app/models/profile.rb b/app/models/profile.rb index be081dd6..3dba93d8 100755 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -1,120 +1,121 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Profile < ApplicationRecord + # TODO + # attr_accessible \ + # :registered, # bool + # :mini_bio, + # :first_name, # str + # :last_name, # str + # :name, + # :phone, # str + # :address, # str + # :email, # str + # :city, # str + # :state_code, # str (eg. CA) + # :zip_code, # str + # :privacy_settings, # text [str]: XXX deprecated + # :picture, # str: either their social network pic or a stored pic on S3 + # :anonymous, # bool: negates all privacy_settings + # :city_state, + # :user_id - #TODO - # attr_accessible \ - # :registered, # bool - # :mini_bio, - # :first_name, # str - # :last_name, # str - # :name, - # :phone, # str - # :address, # str - # :email, # str - # :city, # str - # :state_code, # str (eg. CA) - # :zip_code, # str - # :privacy_settings, # text [str]: XXX deprecated - # :picture, # str: either their social network pic or a stored pic on S3 - # :anonymous, # bool: negates all privacy_settings - # :city_state, - # :user_id + validates :email, format: { with: Email::Regex }, allow_blank: true - validates :email, format: {with: Email::Regex}, allow_blank: true + attr_accessor :email, :city_state - attr_accessor :email, :city_state + serialize :privacy_settings, Array - serialize :privacy_settings, Array + mount_uploader :picture, ProfileUploader - mount_uploader :picture, ProfileUploader + belongs_to :user + has_many :activities # Activities this profile has created + has_many :supporters + has_many :donations + has_many :campaigns + has_many :events + has_many :recurring_donations + has_many :comments, as: :host, dependent: :destroy + has_many :nonprofits, through: :supporters + has_many :activities, dependent: :destroy + # has_one :card, as: :holder - belongs_to :user - has_many :activities # Activities this profile has created - has_many :supporters - has_many :donations - has_many :campaigns - has_many :events - has_many :recurring_donations - has_many :comments, as: :host, dependent: :destroy - has_many :nonprofits, through: :supporters - has_many :activities, dependent: :destroy -# has_one :card, as: :holder + # accepts_nested_attributes_for :card - #accepts_nested_attributes_for :card + scope :non_anon, -> { where(anonymous: [nil, false]) } - scope :non_anon, -> {where(anonymous: [nil, false])} + before_validation(on: :create) do + set_defaults + self + end - before_validation(on: :create) do - self.set_defaults - self - end + def set_defaults + self.name ||= user.name if user + self.email ||= user.email if user + self.picture ||= user.picture if user + if self.name.blank? && first_name.present? && last_name.present? + self.name ||= first_name + ' ' + last_name + end + end - def set_defaults - self.name ||= self.user.name if self.user - self.email ||= self.user.email if self.user - self.picture ||= self.user.picture if self.user - if self.name.blank? && self.first_name.present? && self.last_name.present? - self.name ||= self.first_name + ' ' + self.last_name - end - end + # Queries - # Queries + def recent_donations(npo_id) + donations.valid.order('created_at').where(nonprofit_id: npo_id).take(10) + end - def recent_donations(npo_id) - self.donations.valid.order("created_at").where(nonprofit_id: npo_id).take(10) - end + # Attrs - # Attrs + def total_given_to(nonprofit) + donations.valid.where(nonprofit_id: nonprofit.id).pluck(:amount).sum + end - def total_given_to(nonprofit) - self.donations.valid.where(nonprofit_id: nonprofit.id).pluck(:amount).sum - end + def monthly_giving(nonprofit_id) + donations.where(nonprofit_id: nonprofit_id).map(&:amount).sum + end - def monthly_giving(nonprofit_id) - self.donations.where(nonprofit_id: nonprofit_id).map(&:amount).sum - end + def monthly_total_giving + donations.map(&:amount).sum + end - def monthly_total_giving - self.donations.map(&:amount).sum - end + def full_name + "#{first_name} #{last_name}" + end - def full_name - "#{self.first_name} #{self.last_name}" - end + def supporter_name + self.name.blank? ? 'A Supporter' : self.name + end - def supporter_name - self.name.blank? ? "A Supporter" : self.name - end + def get_profile_picture(size = :normal) + # Can be, in order of precedence: your uploaded photo, facebook picture, or + # default image + if user.picture + return user.get_picture(size) + else + return picture_url(size) + end - def get_profile_picture(size=:normal) - # Can be, in order of precedence: your uploaded photo, facebook picture, or - # default image - if self.user.picture - return self.user.get_picture(size) - else - return self.picture_url(size) - end - # Either does not want photo shown or has none uploaded. - return Image::DefaultProfileUrl - end + # Either does not want photo shown or has none uploaded. + Image::DefaultProfileUrl + end - def url - Rails.application.routes.url_helpers.profile_path(self) - end + def url + Rails.application.routes.url_helpers.profile_path(self) + end - def as_json(options = {}) - h = super(options) - h[:pic_tiny] = self.get_profile_picture :tiny - h[:url] = self.url - h - end + def as_json(options = {}) + h = super(options) + h[:pic_tiny] = get_profile_picture :tiny + h[:url] = url + h + end - # Cache setters - - def set_caches! - self.total_raised = self.donations.pluck(:amount).sum - self.total_recurring = self.recurring_donations.active.pluck(:amount).sum - self.save! - end + # Cache setters + def set_caches! + self.total_raised = donations.pluck(:amount).sum + self.total_recurring = recurring_donations.active.pluck(:amount).sum + save! + end end diff --git a/app/models/recurring_donation.rb b/app/models/recurring_donation.rb index 8833b076..ece20b80 100644 --- a/app/models/recurring_donation.rb +++ b/app/models/recurring_donation.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RecurringDonation < ApplicationRecord - - #TODO: + # TODO: # attr_accessible \ # :amount, # int (cents) # :active, # bool (whether this recurring donation should still be paid) @@ -19,10 +20,10 @@ class RecurringDonation < ApplicationRecord # :nonprofit_id, :nonprofit, # :supporter_id #used because things are messed up in the datamodel - scope :active, -> {where(active: true)} - scope :inactive, -> {where(active: [false,nil])} - scope :monthly, -> {where(time_unit: 'month', interval: 1)} - scope :annual, -> {where(time_unit: 'year', interval: 1)} + scope :active, -> { where(active: true) } + scope :inactive, -> { where(active: [false, nil]) } + scope :monthly, -> { where(time_unit: 'month', interval: 1) } + scope :annual, -> { where(time_unit: 'year', interval: 1) } belongs_to :donation belongs_to :nonprofit @@ -30,37 +31,30 @@ class RecurringDonation < ApplicationRecord has_one :card, through: :donation has_one :supporter, through: :donation - validates :paydate, numericality: {less_than: 29}, allow_blank: true + validates :paydate, numericality: { less_than: 29 }, allow_blank: true validates :donation_id, presence: true validates :nonprofit_id, presence: true validates :start_date, presence: true - validates :interval, presence: true, numericality: {greater_than: 0} - validates :time_unit, presence: true, inclusion: {in: Timespan::Units} + validates :interval, presence: true, numericality: { greater_than: 0 } + validates :time_unit, presence: true, inclusion: { in: Timespan::Units } validates_associated :donation def most_recent_charge - if (self.charges) - return self.charges.sort_by { |c| c.created_at }.last() - end + charges&.max_by(&:created_at) end def most_recent_paid_charge - if (self.charges) - return self.charges.find_all {|c| c.paid?}.sort_by { |c| c.created_at }.last() - end + charges&.find_all(&:paid?)&.max_by(&:created_at) end def total_given - if (self.charges) - return self.charges.find_all(&:paid?).sum(&:amount) - end - + return charges.find_all(&:paid?).sum(&:amount) if charges end # XXX let's make these monthly_totals a query # Or just push it into the front-end def self.monthly_total - self.all.map(&:monthly_total).sum + all.map(&:monthly_total).sum end def monthly_total @@ -68,8 +62,7 @@ class RecurringDonation < ApplicationRecord 'week' => 4, 'day' => 30, 'year' => 0.0833 - }[self.interval] || 1 - return self.donation.amount * multiple + }[interval] || 1 + donation.amount * multiple end - end diff --git a/app/models/refund.rb b/app/models/refund.rb index ef37db60..e315552b 100644 --- a/app/models/refund.rb +++ b/app/models/refund.rb @@ -1,27 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Refund < ApplicationRecord + Reasons = %i[duplicate fraudulent requested_by_customer].freeze - Reasons = [:duplicate, :fraudulent, :requested_by_customer] + # TODO: + # attr_accessible \ + # :amount, # int + # :comment, # text + # :reason, # str ('duplicate', 'fraudulent', or 'requested_by_customer') + # :stripe_refund_id, + # :disbursed, # boolean (whether this refund has been counted in a payout) + # :failure_message, # str (accessor for storing the Stripe error message) + # :user_id, :user, # user who made this refund + # :payment_id, :payment, # negative payment that records this refund + # :charge_id, :charge - # TODO: - # attr_accessible \ - # :amount, # int - # :comment, # text - # :reason, # str ('duplicate', 'fraudulent', or 'requested_by_customer') - # :stripe_refund_id, - # :disbursed, # boolean (whether this refund has been counted in a payout) - # :failure_message, # str (accessor for storing the Stripe error message) - # :user_id, :user, # user who made this refund - # :payment_id, :payment, # negative payment that records this refund - # :charge_id, :charge + attr_accessor :failure_message - attr_accessor :failure_message - - belongs_to :charge - belongs_to :payment - - scope :not_disbursed, ->{where(disbursed: [nil, false])} - scope :disbursed, ->{where(disbursed: [true])} + belongs_to :charge + belongs_to :payment + scope :not_disbursed, -> { where(disbursed: [nil, false]) } + scope :disbursed, -> { where(disbursed: [true]) } end - diff --git a/app/models/role.rb b/app/models/role.rb index 215e24af..3063a4f7 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,50 +1,58 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Role < ApplicationRecord + Names = [ + :super_admin, # global access + :super_associate, # global access to everything except bank acct info + :nonprofit_admin, # npo scoped access to everything + :nonprofit_associate, # npo scoped access to everything except bank acct info + :campaign_editor, # fundraising tools, without dashboard access + :event_editor # // + ].freeze - Names = [ - :super_admin, # global access - :super_associate, # global access to everything except bank acct info - :nonprofit_admin, # npo scoped access to everything - :nonprofit_associate, # npo scoped access to everything except bank acct info - :campaign_editor, # fundraising tools, without dashboard access - :event_editor # // - ] + # TODO: + # attr_accessible \ + # :name, + # :user_id, :user, + # :host, :host_id, :host_type # nil, "Nonprofit", "Campaign", "Event" - # TODO: - # attr_accessible \ - # :name, - # :user_id, :user, - # :host, :host_id, :host_type # nil, "Nonprofit", "Campaign", "Event" + belongs_to :user + belongs_to :host, polymorphic: true - belongs_to :user - belongs_to :host, polymorphic: true + scope :super_admins, -> { where(name: :super_admin) } + scope :super_associate, -> { where(name: :super_associate) } + scope :nonprofit_admins, -> { where(name: :nonprofit_admin) } + scope :nonprofit_personnel, -> { where(name: %i[nonprofit_associate nonprofit_admin]) } + scope :campaign_editors, -> { where(name: :campaign_editor) } + scope :event_editors, -> { where(name: :event_editor) } - scope :super_admins, -> {where(name: :super_admin)} - scope :super_associate, -> {where(name: :super_associate)} - scope :nonprofit_admins, -> {where(name: :nonprofit_admin)} - scope :nonprofit_personnel, -> {where(name: [:nonprofit_associate, :nonprofit_admin])} - scope :campaign_editors, -> {where(name: :campaign_editor)} - scope :event_editors, -> {where(name: :event_editor)} - - validates :user, presence: true - validates :name, inclusion: {in: Names} - validates :host, presence: true, unless: [:super_admin?, :super_associate?] - - def name; super.to_sym; end - def super_admin?; name == :super_admin; end - def super_associate?; name == :super_associate; end - - def self.create_for_nonprofit(role_name, email, nonprofit) - user = User.find_or_create_with_email(email) - role = Role.create(user: user, name: role_name, host: nonprofit) - return role unless role.valid? - if user.confirmed? - NonprofitAdminMailer.delay.existing_invite(role) - else - NonprofitAdminMailer.delay.new_invite(role, user.make_confirmation_token!) - end - return role - end + validates :user, presence: true + validates :name, inclusion: { in: Names } + validates :host, presence: true, unless: %i[super_admin? super_associate?] + def name + super.to_sym end + def super_admin? + name == :super_admin +end + + def super_associate? + name == :super_associate +end + + def self.create_for_nonprofit(role_name, email, nonprofit) + user = User.find_or_create_with_email(email) + role = Role.create(user: user, name: role_name, host: nonprofit) + return role unless role.valid? + + if user.confirmed? + NonprofitAdminMailer.delay.existing_invite(role) + else + NonprofitAdminMailer.delay.new_invite(role, user.make_confirmation_token!) + end + role + end +end diff --git a/app/models/source_token.rb b/app/models/source_token.rb index 159d682f..7e9ba7dc 100644 --- a/app/models/source_token.rb +++ b/app/models/source_token.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SourceToken < ApplicationRecord self.primary_key = :token # attr_accessible :expiration, :token, :max_uses, :total_uses - belongs_to :tokenizable, :polymorphic => true + belongs_to :tokenizable, polymorphic: true belongs_to :event end diff --git a/app/models/supporter.rb b/app/models/supporter.rb index cdb087a2..cfaf71de 100644 --- a/app/models/supporter.rb +++ b/app/models/supporter.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Supporter < ApplicationRecord - - #TODO + # TODO # attr_accessible \ # :search_vectors, # :profile_id, :profile, @@ -49,10 +50,10 @@ class Supporter < ApplicationRecord has_many :tag_masters, through: :tag_joins has_many :custom_field_joins, dependent: :destroy has_many :custom_field_masters, through: :custom_field_joins - belongs_to :merged_into, class_name: 'Supporter', :foreign_key => 'merged_into' + belongs_to :merged_into, class_name: 'Supporter', foreign_key: 'merged_into' - validates :nonprofit, :presence => true - scope :not_deleted, -> {where(deleted: false)} + validates :nonprofit, presence: true + scope :not_deleted, -> { where(deleted: false) } geocoded_by :full_address reverse_geocoded_by :latitude, :longitude do |obj, results| @@ -66,22 +67,21 @@ class Supporter < ApplicationRecord end end - def profile_picture size=:normal - return unless self.profile - self.profile.get_profile_picture(size) - end + def profile_picture(size = :normal) + return unless profile + profile.get_profile_picture(size) + end def as_json(options = {}) h = super(options) - h[:pic_tiny] = self.profile_picture(:tiny) - h[:pic_normal] = self.profile_picture(:normal) - h[:url] = self.profile && Rails.application.routes.url_helpers.profile_path(self.profile) - return h + h[:pic_tiny] = profile_picture(:tiny) + h[:pic_normal] = profile_picture(:normal) + h[:url] = profile && Rails.application.routes.url_helpers.profile_path(profile) + h end def full_address - Format::Address.full_address(self.address, self.city, self.state_code) + Format::Address.full_address(address, city, state_code) end - end diff --git a/app/models/supporter_email.rb b/app/models/supporter_email.rb index 3cd856f9..13864dbd 100644 --- a/app/models/supporter_email.rb +++ b/app/models/supporter_email.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SupporterEmail < ApplicationRecord - # TODO - # attr_accessible \ - # :to, - # :from, - # :subject, - # :body, - # :recipient_count, - # :supporter_id, :supporter, - # :nonprofit_id, - # :gmail_thread_id + # TODO + # attr_accessible \ + # :to, + # :from, + # :subject, + # :body, + # :recipient_count, + # :supporter_id, :supporter, + # :nonprofit_id, + # :gmail_thread_id - belongs_to :supporter - validates_presence_of :nonprofit_id - has_many :activities, as: :attachment, dependent: :destroy + belongs_to :supporter + validates_presence_of :nonprofit_id + has_many :activities, as: :attachment, dependent: :destroy end diff --git a/app/models/supporter_note.rb b/app/models/supporter_note.rb index 8701dd2b..3c827690 100644 --- a/app/models/supporter_note.rb +++ b/app/models/supporter_note.rb @@ -1,15 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SupporterNote < ApplicationRecord + # TODO + # attr_accessible \ + # :content, + # :supporter_id, :supporter - #TODO - # attr_accessible \ - # :content, - # :supporter_id, :supporter + belongs_to :supporter + has_many :activities, as: :attachment, dependent: :destroy - belongs_to :supporter - has_many :activities, as: :attachment, dependent: :destroy - - validates :content, length: {minimum: 1} - validates :supporter_id, presence: true + validates :content, length: { minimum: 1 } + validates :supporter_id, presence: true end - diff --git a/app/models/tag_join.rb b/app/models/tag_join.rb index 45ee10c5..d6ca78ca 100644 --- a/app/models/tag_join.rb +++ b/app/models/tag_join.rb @@ -1,25 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TagJoin < ApplicationRecord + # TODO + # attr_accessible \ + # :supporter, :supporter_id, + # :tag_master, :tag_master_id - #TODO - # attr_accessible \ - # :supporter, :supporter_id, - # :tag_master, :tag_master_id + validates :tag_master, presence: true - validates :tag_master, presence: true - - belongs_to :tag_master - belongs_to :supporter - - def name; self.tag_master.name; end - - def self.create_with_name(nonprofit, h) - tm = nonprofit.tag_masters.find_by_name(h['name']) - if tm.nil? - tm = nonprofit.tag_masters.create(name: h['name']) - end - self.create tag_master: tm, supporter_id: h['supporter_id'] - end + belongs_to :tag_master + belongs_to :supporter + def name + tag_master.name end + def self.create_with_name(nonprofit, h) + tm = nonprofit.tag_masters.find_by_name(h['name']) + tm = nonprofit.tag_masters.create(name: h['name']) if tm.nil? + create tag_master: tm, supporter_id: h['supporter_id'] + end +end diff --git a/app/models/tag_master.rb b/app/models/tag_master.rb index 9bac71ce..b613275d 100644 --- a/app/models/tag_master.rb +++ b/app/models/tag_master.rb @@ -1,26 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TagMaster < ApplicationRecord + # TODO: + # attr_accessible \ + # :nonprofit, :nonprofit_id, + # :name, + # :deleted, + # :created_at - #TODO: - # attr_accessible \ - # :nonprofit, :nonprofit_id, - # :name, - # :deleted, - # :created_at + validates :name, presence: true + validate :no_dupes, on: :create - validates :name, presence: true - validate :no_dupes, on: :create + belongs_to :nonprofit + has_many :tag_joins, dependent: :destroy + has_one :email_list - belongs_to :nonprofit - has_many :tag_joins, dependent: :destroy - has_one :email_list + scope :not_deleted, -> { where(deleted: [nil, false]) } - scope :not_deleted, ->{where(deleted: [nil,false])} - - def no_dupes - return self if nonprofit.nil? - errors.add(:base, "Duplicate tag") if nonprofit.tag_masters.not_deleted.where(name: name).any? - end + def no_dupes + return self if nonprofit.nil? + errors.add(:base, 'Duplicate tag') if nonprofit.tag_masters.not_deleted.where(name: name).any? + end end - diff --git a/app/models/ticket.rb b/app/models/ticket.rb index ee5ad133..e8292b7d 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -1,21 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Ticket < ApplicationRecord - # attr_accessible :note, :event_discount, :event_discount_id belongs_to :event_discount - belongs_to :supporter - belongs_to :profile - belongs_to :ticket_level - belongs_to :event - belongs_to :charge - belongs_to :card - belongs_to :payment - belongs_to :source_token - has_one :nonprofit, through: :event - has_many :activities, as: :attachment, dependent: :destroy + belongs_to :supporter + belongs_to :profile + belongs_to :ticket_level + belongs_to :event + belongs_to :charge + belongs_to :card + belongs_to :payment + belongs_to :source_token + has_one :nonprofit, through: :event + has_many :activities, as: :attachment, dependent: :destroy - def related_tickets - payment.tickets.where('id != ?', self.id) - end + def related_tickets + payment.tickets.where('id != ?', id) + end end diff --git a/app/models/ticket_level.rb b/app/models/ticket_level.rb index d9d7942d..dd0130d5 100644 --- a/app/models/ticket_level.rb +++ b/app/models/ticket_level.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class TicketLevel < ApplicationRecord - - #TODO + # TODO # attr_accessible \ # :amount, #integer # :amount_dollars, #accessor, string @@ -19,14 +20,13 @@ class TicketLevel < ApplicationRecord has_many :tickets belongs_to :event - validates :name, :presence => true - validates :event_id, :presence => true + validates :name, presence: true + validates :event_id, presence: true - scope :not_deleted, ->{where(deleted: [false,nil])} + scope :not_deleted, -> { where(deleted: [false, nil]) } before_validation do - self.amount = Format::Currency.dollars_to_cents(self.amount_dollars) if self.amount_dollars.present? - self.amount = 0 if self.amount.nil? + self.amount = Format::Currency.dollars_to_cents(amount_dollars) if amount_dollars.present? + self.amount = 0 if amount.nil? end - end diff --git a/app/models/tracking.rb b/app/models/tracking.rb index 0903b3e3..afb3cf75 100644 --- a/app/models/tracking.rb +++ b/app/models/tracking.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Tracking < ApplicationRecord # attr_accessible :utm_campaign, :utm_content, :utm_medium, :utm_source diff --git a/app/models/user.rb b/app/models/user.rb index 31b0aba1..7a9af591 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,110 +1,110 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class User < ApplicationRecord + # TODO: + # attr_accessible \ + # :email, # str: balidated with Devise + # :password, # str: hashed with bcrypt + # :phone, # str + # :location, + # :city, + # :state_code, + # :password_confirmation, # accessor: used on registration + # :remember_me, # bool: don't sign user out for a while + # :provider, # str: OAuth provider + # :uid, # str: OAuth user ID + # :pending_password, # bool: User registered with oauth and did not set a password + # :name, # str: created with oauth + # :auto_generated, # bool: flag whether a password was auto-generated for this account + # :referer, # str: ID of the user who referred this account + # :latitude, + # :longitude, + # :reset_password_token, + # :reset_password_sent_at, + # :picture, # str: url for fb or twitter pic + # :current_password, # accessor: for updating pass + # :profile_attributes, + # :phone - #TODO: - # attr_accessible \ - # :email, # str: balidated with Devise - # :password, # str: hashed with bcrypt - # :phone, # str - # :location, - # :city, - # :state_code, - # :password_confirmation, # accessor: used on registration - # :remember_me, # bool: don't sign user out for a while - # :provider, # str: OAuth provider - # :uid, # str: OAuth user ID - # :pending_password, # bool: User registered with oauth and did not set a password - # :name, # str: created with oauth - # :auto_generated, # bool: flag whether a password was auto-generated for this account - # :referer, # str: ID of the user who referred this account - # :latitude, - # :longitude, - # :reset_password_token, - # :reset_password_sent_at, - # :picture, # str: url for fb or twitter pic - # :current_password, # accessor: for updating pass - # :profile_attributes, - # :phone + geocoded_by :location - geocoded_by :location + devise :async, :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable - devise :async, :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable + attr_accessor :offsite_donation_id, :current_password - attr_accessor :offsite_donation_id, :current_password + validates :email, + presence: true, + uniqueness: { case_sensitive: false }, + format: { with: Email::Regex } - validates :email, - presence: true, - uniqueness: {case_sensitive: false}, - format: {with: Email::Regex} - - has_many :donations, through: :profile - has_many :roles, dependent: :destroy - has_one :profile, dependent: :destroy - has_many :imports + has_many :donations, through: :profile + has_many :roles, dependent: :destroy + has_one :profile, dependent: :destroy + has_many :imports has_many :email_settings - accepts_nested_attributes_for :profile + accepts_nested_attributes_for :profile - before_validation(on: :create) do - self.password = Devise.friendly_token.first(8) if self.auto_generated - self.build_profile if self.profile.nil? - self - end + before_validation(on: :create) do + self.password = Devise.friendly_token.first(8) if auto_generated + build_profile if profile.nil? + self + end # This creates the user in the normal way, but also sends the devise email confirmation email, which we don't want to send to np admins or anyone else def self.register_donor!(params) u = User.create!(params) u.send_confirmation_instructions - return u - end + u + end def self.find_or_create_with_email(em) - user = self.where("lower(email) = ?", em.downcase).first + user = where('lower(email) = ?', em.downcase).first return user if user.present? + User.create!(email: em, auto_generated: true) end - def profile_picture(size) - self.profile.picture_url(size) - end + def profile_picture(size) + profile.picture_url(size) + end + # Required by Devise for Omniauth + # https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview + def self.new_with_session(params, session) + super.tap do |user| + if data = session['devise.facebook_data'] && session['devise.facebook_data']['extra']['raw_info'] + user.email = data['email'] if user.email.blank? + end + end + end - # Required by Devise for Omniauth - # https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview - def self.new_with_session(params, session) - super.tap do |user| - if data = session['devise.facebook_data'] && session['devise.facebook_data']['extra']['raw_info'] - user.email = data['email'] if user.email.blank? - end - end - end + # Don't require confirmation for new users -- they can still donate without confirmation + # https://github.com/plataformatec/devise/wiki/How-To:-Override-confirmations-so-users-can-pick-their-own-passwords-as-part-of-confirmation-activation + def confirmation_required? + false + end - # Don't require confirmation for new users -- they can still donate without confirmation - # https://github.com/plataformatec/devise/wiki/How-To:-Override-confirmations-so-users-can-pick-their-own-passwords-as-part-of-confirmation-activation - def confirmation_required? - false - end - - def as_json(options={}) - h = super(options) - h[:unconfirmed_email] = self.unconfirmed_email - h[:confirmed] = self.confirmed? - h[:profile] = self.profile.as_json - h - end + def as_json(options = {}) + h = super(options) + h[:unconfirmed_email] = unconfirmed_email + h[:confirmed] = confirmed? + h[:profile] = profile.as_json + h + end # This is useful for manually generating a Devise user confirmation token so that we can get the confirmation URL with the correct token from anywhere def make_confirmation_token! raw, db = Devise.token_generator.generate(User, :confirmation_token) self.confirmation_token = db self.confirmation_sent_at = Time.now - self.save! - return raw + save! + raw end - def geocode! - #self.geocode - #self.save - end - + def geocode! + # self.geocode + # self.save + end end diff --git a/app/uploaders/article_background_uploader.rb b/app/uploaders/article_background_uploader.rb index 3fbaa342..9ac0229f 100644 --- a/app/uploaders/article_background_uploader.rb +++ b/app/uploaders/article_background_uploader.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class ArticleBackgroundUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -20,7 +21,7 @@ class ArticleBackgroundUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultNonprofitUrl + Image::DefaultNonprofitUrl end # Process files as they are uploaded: @@ -32,14 +33,13 @@ class ArticleBackgroundUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :large do - process :resize_to_fill => [600, 400] + process resize_to_fill: [600, 400] end - # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -51,5 +51,4 @@ class ArticleBackgroundUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/article_uploader.rb b/app/uploaders/article_uploader.rb index ac4b0d86..906c96ad 100644 --- a/app/uploaders/article_uploader.rb +++ b/app/uploaders/article_uploader.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class ArticleUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -20,7 +21,7 @@ class ArticleUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultNonprofitUrl + Image::DefaultNonprofitUrl end # Process files as they are uploaded: @@ -32,13 +33,13 @@ class ArticleUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :thumb do - process :resize_to_fill => [200, 200] + process resize_to_fill: [200, 200] end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -50,5 +51,4 @@ class ArticleUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/campaign_background_image_uploader.rb b/app/uploaders/campaign_background_image_uploader.rb index 57b6c6cb..da31b91c 100644 --- a/app/uploaders/campaign_background_image_uploader.rb +++ b/app/uploaders/campaign_background_image_uploader.rb @@ -1,26 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class CampaignBackgroundImageUploader < CarrierWave::Uploader::Base + include CarrierWave::MiniMagick - include CarrierWave::MiniMagick - + def store_dir + "uploads/campaigns/#{mounted_as}/#{model.id}" + end - def store_dir - "uploads/campaigns/#{mounted_as}/#{model.id}" - end + # Create different versions of your uploaded files: + version :normal do + process resize_to_fill: [1000, 600] + end - # Create different versions of your uploaded files: - version :normal do - process :resize_to_fill => [1000, 600] - end - - def extension_white_list - %w(jpg jpeg png) - end - - def cache_dir - "#{Rails.root}/tmp/uploads" - end + def extension_white_list + %w[jpg jpeg png] + end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/uploaders/campaign_banner_image_uploader.rb b/app/uploaders/campaign_banner_image_uploader.rb index 1c4010d7..09fe0e46 100644 --- a/app/uploaders/campaign_banner_image_uploader.rb +++ b/app/uploaders/campaign_banner_image_uploader.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignBannerImageUploader < CarrierWave::Uploader::Base - include CarrierWave::MiniMagick + include CarrierWave::MiniMagick - def store_dir - "uploads/campaigns/#{mounted_as}/#{model.id}" - end + def store_dir + "uploads/campaigns/#{mounted_as}/#{model.id}" + end - def extension_white_list - %w(jpg jpeg png) - end + def extension_white_list + %w[jpg jpeg png] + end - def cache_dir - "#{Rails.root}/tmp/uploads" - end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/uploaders/campaign_main_image_uploader.rb b/app/uploaders/campaign_main_image_uploader.rb index bcf66cf1..a8def8e4 100644 --- a/app/uploaders/campaign_main_image_uploader.rb +++ b/app/uploaders/campaign_main_image_uploader.rb @@ -1,56 +1,56 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CampaignMainImageUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick - # Include RMagick or MiniMagick support: - # include CarrierWave::RMagick - include CarrierWave::MiniMagick + # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: + # include Sprockets::Helpers::RailsHelper + # include Sprockets::Helpers::IsolatedHelper - # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: - # include Sprockets::Helpers::RailsHelper - # include Sprockets::Helpers::IsolatedHelper + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/campaigns/#{mounted_as}/#{model.id}" + end - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: - def store_dir - "uploads/campaigns/#{mounted_as}/#{model.id}" - end + # Provide a default URL as a default if there hasn't been a file uploaded: + def default_url + # For Rails 3.1+ asset pipeline compatibility: + Image::DefaultProfileUrl + end - # Provide a default URL as a default if there hasn't been a file uploaded: - def default_url - # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl - end + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end - # Process files as they are uploaded: - # process :scale => [200, 300] - # - # def scale(width, height) - # # do something - # end + # Create different versions of your uploaded files: + version :normal do + process resize_to_fill: [524, 360] + end - # Create different versions of your uploaded files: - version :normal do - process :resize_to_fill => [524, 360] - end + version :thumb do + process resize_to_fill: [180, 150] + end - version :thumb do - process :resize_to_fill => [180, 150] - end + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w[jpg jpeg png] + end - # Add a white list of extensions which are allowed to be uploaded. - # For images you might use something like this: - def extension_white_list - %w(jpg jpeg png) - end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end - - def cache_dir - "#{Rails.root}/tmp/uploads" - end + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/uploaders/event_background_image_uploader.rb b/app/uploaders/event_background_image_uploader.rb index 02a304d2..123517b2 100644 --- a/app/uploaders/event_background_image_uploader.rb +++ b/app/uploaders/event_background_image_uploader.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventBackgroundImageUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -18,7 +19,7 @@ class EventBackgroundImageUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultCampaignUrl + Image::DefaultCampaignUrl end # Process files as they are uploaded: @@ -30,13 +31,13 @@ class EventBackgroundImageUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :normal do - process :resize_to_fill => [1000, 600] + process resize_to_fill: [1000, 600] end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -48,5 +49,4 @@ class EventBackgroundImageUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/event_main_image_uploader.rb b/app/uploaders/event_main_image_uploader.rb index 6afc1216..e8b8adb1 100644 --- a/app/uploaders/event_main_image_uploader.rb +++ b/app/uploaders/event_main_image_uploader.rb @@ -1,56 +1,56 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EventMainImageUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick - # Include RMagick or MiniMagick support: - # include CarrierWave::RMagick - include CarrierWave::MiniMagick + # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: + # include Sprockets::Helpers::RailsHelper + # include Sprockets::Helpers::IsolatedHelper - # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: - # include Sprockets::Helpers::RailsHelper - # include Sprockets::Helpers::IsolatedHelper + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/events/#{mounted_as}/#{model.id}" + end - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: - def store_dir - "uploads/events/#{mounted_as}/#{model.id}" - end + # Provide a default URL as a default if there hasn't been a file uploaded: + def default_url + # For Rails 3.1+ asset pipeline compatibility: + Image::DefaultProfileUrl + end - # Provide a default URL as a default if there hasn't been a file uploaded: - def default_url - # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl - end + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end - # Process files as they are uploaded: - # process :scale => [200, 300] - # - # def scale(width, height) - # # do something - # end + # Create different versions of your uploaded files: + version :normal do + process resize_to_fill: [400, 400] + end - # Create different versions of your uploaded files: - version :normal do - process :resize_to_fill => [400, 400] - end + version :thumb do + process resize_to_fill: [100, 100] + end - version :thumb do - process :resize_to_fill => [100,100] - end + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w[jpg jpeg png] + end - # Add a white list of extensions which are allowed to be uploaded. - # For images you might use something like this: - def extension_white_list - %w(jpg jpeg png) - end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end - - def cache_dir - "#{Rails.root}/tmp/uploads" - end + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/uploaders/image_attachment_uploader.rb b/app/uploaders/image_attachment_uploader.rb index 01b644f6..a5e6d304 100644 --- a/app/uploaders/image_attachment_uploader.rb +++ b/app/uploaders/image_attachment_uploader.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class ImageAttachmentUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -20,7 +21,7 @@ class ImageAttachmentUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl + Image::DefaultProfileUrl end # Process files as they are uploaded: @@ -32,23 +33,23 @@ class ImageAttachmentUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :large do - process :resize_to_fill => [600, 400] + process resize_to_fill: [600, 400] end version :medium do - process :resize_to_fill => [400, 266] + process resize_to_fill: [400, 266] end version :small do - process :resize_to_fill => [400, 266] + process resize_to_fill: [400, 266] end # slightly smaller than the normal thumb version :thumb_explore do - process :resize_to_fill => [200, 133] + process resize_to_fill: [200, 133] end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -60,5 +61,4 @@ class ImageAttachmentUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/nonprofit_background_uploader.rb b/app/uploaders/nonprofit_background_uploader.rb index b46f6284..e6134f68 100644 --- a/app/uploaders/nonprofit_background_uploader.rb +++ b/app/uploaders/nonprofit_background_uploader.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class NonprofitBackgroundUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -21,7 +22,7 @@ class NonprofitBackgroundUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultNonprofitUrl + Image::DefaultNonprofitUrl end # Process files as they are uploaded: @@ -33,13 +34,13 @@ class NonprofitBackgroundUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :normal do - process :resize_to_fill => [1000, 600] + process resize_to_fill: [1000, 600] end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -51,5 +52,4 @@ class NonprofitBackgroundUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/nonprofit_logo_uploader.rb b/app/uploaders/nonprofit_logo_uploader.rb index c068b73c..55dd242e 100644 --- a/app/uploaders/nonprofit_logo_uploader.rb +++ b/app/uploaders/nonprofit_logo_uploader.rb @@ -1,51 +1,51 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class NonprofitLogoUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick - # Include RMagick or MiniMagick support: - # include CarrierWave::RMagick - include CarrierWave::MiniMagick + # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: + # include Sprockets::Helpers::RailsHelper + # include Sprockets::Helpers::IsolatedHelper - # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: - # include Sprockets::Helpers::RailsHelper - # include Sprockets::Helpers::IsolatedHelper + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/npo/#{mounted_as}/#{model.id}" + end - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: - def store_dir - "uploads/npo/#{mounted_as}/#{model.id}" - end + # Provide a default URL as a default if there hasn't been a file uploaded: + def default_url + # For Rails 3.1+ asset pipeline compatibility: + Image::DefaultProfileUrl + end - # Provide a default URL as a default if there hasn't been a file uploaded: - def default_url - # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl - end + # Create different versions of your uploaded files: + version :large do + process resize_to_fit: [180, 180] + end + version :normal do + process resize_to_fit: [100, 100] + end + version :small do + process resize_to_fit: [30, 30] + end - # Create different versions of your uploaded files: - version :large do - process :resize_to_fit => [180, 180] - end - version :normal do - process :resize_to_fit => [100, 100] - end - version :small do - process :resize_to_fit => [30, 30] - end + def extension_white_list + %w[jpg jpeg png gif] + end - def extension_white_list - %w(jpg jpeg png gif) - end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end - - def cache_dir - "#{Rails.root}/tmp/uploads" - end + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/uploaders/nonprofit_uploader.rb b/app/uploaders/nonprofit_uploader.rb index fe37a30c..334d3df6 100755 --- a/app/uploaders/nonprofit_uploader.rb +++ b/app/uploaders/nonprofit_uploader.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class NonprofitUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick @@ -20,7 +21,7 @@ class NonprofitUploader < CarrierWave::Uploader::Base # Provide a default URL as a default if there hasn't been a file uploaded: def default_url # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl + Image::DefaultProfileUrl end # Process files as they are uploaded: @@ -32,20 +33,20 @@ class NonprofitUploader < CarrierWave::Uploader::Base # Create different versions of your uploaded files: version :nonprofit_carousel do - process :resize_to_fill => [590, 338] + process resize_to_fill: [590, 338] end version :thumb do - process :resize_to_fill => [188, 120] + process resize_to_fill: [188, 120] end # slightly smaller than the normal thumb version :thumb_explore do - process :resize_to_fill => [100, 100] + process resize_to_fill: [100, 100] end # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list - %w(jpg jpeg png) + %w[jpg jpeg png] end # Override the filename of the uploaded files: @@ -57,5 +58,4 @@ class NonprofitUploader < CarrierWave::Uploader::Base def cache_dir "#{Rails.root}/tmp/uploads" end - end diff --git a/app/uploaders/profile_uploader.rb b/app/uploaders/profile_uploader.rb index ec911fd4..1abd9e4c 100644 --- a/app/uploaders/profile_uploader.rb +++ b/app/uploaders/profile_uploader.rb @@ -1,60 +1,60 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # encoding: utf-8 class ProfileUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick - # Include RMagick or MiniMagick support: - # include CarrierWave::RMagick - include CarrierWave::MiniMagick + # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: + # include Sprockets::Helpers::RailsHelper + # include Sprockets::Helpers::IsolatedHelper - # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility: - # include Sprockets::Helpers::RailsHelper - # include Sprockets::Helpers::IsolatedHelper + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: - def store_dir - "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" - end + # Provide a default URL as a default if there hasn't been a file uploaded: + def default_url + # For Rails 3.1+ asset pipeline compatibility: + Image::DefaultProfileUrl + end - # Provide a default URL as a default if there hasn't been a file uploaded: - def default_url - # For Rails 3.1+ asset pipeline compatibility: - return Image::DefaultProfileUrl - end + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end - # Process files as they are uploaded: - # process :scale => [200, 300] - # - # def scale(width, height) - # # do something - # end + # Create different versions of your uploaded files: + version :normal do + process resize_to_fill: [150, 150] + end + version :medium do + process resize_to_fill: [100, 100] + end + version :tiny do + process resize_to_fill: [50, 50] + end - # Create different versions of your uploaded files: - version :normal do - process :resize_to_fill => [150, 150] - end - version :medium do - process :resize_to_fill => [100, 100] - end - version :tiny do - process :resize_to_fill => [50, 50] - end + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w[jpg jpeg png] + end - # Add a white list of extensions which are allowed to be uploaded. - # For images you might use something like this: - def extension_white_list - %w(jpg jpeg png) - end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end - - def cache_dir - "#{Rails.root}/tmp/uploads" - end + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + def cache_dir + "#{Rails.root}/tmp/uploads" + end end diff --git a/app/views/campaigns/index.rabl b/app/views/campaigns/index.rabl index fe3366a8..d180c586 100644 --- a/app/views/campaigns/index.rabl +++ b/app/views/campaigns/index.rabl @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @campaigns => :data do - collection @campaigns, object_root: false - attributes :name, :total_raised, :goal_amount, :url, :id + collection @campaigns, object_root: false + attributes :name, :total_raised, :goal_amount, :url, :id end - diff --git a/app/views/events/index.rabl b/app/views/events/index.rabl index f449fe4b..ba1da37a 100644 --- a/app/views/events/index.rabl +++ b/app/views/events/index.rabl @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later child @events => :data do - collection @events, object_root: false - attributes :name, :date, :url, :id + collection @events, object_root: false + attributes :name, :date, :url, :id end diff --git a/app/views/maps/all_npo_supporters.rabl b/app/views/maps/all_npo_supporters.rabl index cee568f3..9dd4bbfc 100644 --- a/app/views/maps/all_npo_supporters.rabl +++ b/app/views/maps/all_npo_supporters.rabl @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @map_data => :data do - collection @map_data, object_root: false - attributes :name, :latitude, :longitude, :id + collection @map_data, object_root: false + attributes :name, :latitude, :longitude, :id end diff --git a/app/views/maps/all_npos.rabl b/app/views/maps/all_npos.rabl index d511b8d0..2b04899e 100644 --- a/app/views/maps/all_npos.rabl +++ b/app/views/maps/all_npos.rabl @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @map_data => :data do - collection @map_data, object_root: false - attributes :name, :latitude, :longitude, :id, :email, :phone, :website + collection @map_data, object_root: false + attributes :name, :latitude, :longitude, :id, :email, :phone, :website end diff --git a/app/views/maps/all_supporters.rabl b/app/views/maps/all_supporters.rabl index 970c8663..0d64c6b1 100644 --- a/app/views/maps/all_supporters.rabl +++ b/app/views/maps/all_supporters.rabl @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @map_data => :data do - collection @map_data, object_root: false - attributes :name, :latitude, :longitude, :id, :email, :phone + collection @map_data, object_root: false + attributes :name, :latitude, :longitude, :id, :email, :phone end - diff --git a/app/views/maps/specific_npo_supporters.rabl b/app/views/maps/specific_npo_supporters.rabl index 25a94572..2d0ff097 100644 --- a/app/views/maps/specific_npo_supporters.rabl +++ b/app/views/maps/specific_npo_supporters.rabl @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @map_data => :data do - collection @map_data, object_root: false - attributes :name, :latitude, :longitude, :id, :email, :phone, :address, :city, :state_code, :total_raised + collection @map_data, object_root: false + attributes :name, :latitude, :longitude, :id, :email, :phone, :address, :city, :state_code, :total_raised end diff --git a/app/views/nonprofits/custom_field_joins/index.rabl b/app/views/nonprofits/custom_field_joins/index.rabl index cdae3879..92978134 100644 --- a/app/views/nonprofits/custom_field_joins/index.rabl +++ b/app/views/nonprofits/custom_field_joins/index.rabl @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @custom_field_joins => :data do - collection @custom_field_joins, object_root: false - attributes :name, :created_at, :id, :value + collection @custom_field_joins, object_root: false + attributes :name, :created_at, :id, :value end diff --git a/app/views/nonprofits/custom_field_masters/index.rabl b/app/views/nonprofits/custom_field_masters/index.rabl index d72b90f2..b211fd1e 100644 --- a/app/views/nonprofits/custom_field_masters/index.rabl +++ b/app/views/nonprofits/custom_field_masters/index.rabl @@ -1,9 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @custom_field_masters => :data do - collection @custom_field_masters, object_root: false - attributes :name, :id, :created_at + collection @custom_field_masters, object_root: false + attributes :name, :id, :created_at end - - diff --git a/app/views/nonprofits/payments/show.rabl b/app/views/nonprofits/payments/show.rabl index bd31ac39..c63e7e72 100644 --- a/app/views/nonprofits/payments/show.rabl +++ b/app/views/nonprofits/payments/show.rabl @@ -1,36 +1,36 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object @payment => :data attributes :gross_amount, :towards, :net_amount, :fee_total, :id, :date, :refund_total, :kind node(:consider_donation_anonymous) do |p| - d_anonymous = p.donation.nil? ? false : p.donation.anonymous + d_anonymous = p.donation.nil? ? false : p.donation.anonymous - !!d_anonymous || !!p.supporter.anonymous + !!d_anonymous || !!p.supporter.anonymous end - child :charge do - attributes :created_at, :id, :status + attributes :created_at, :id, :status end child :donation, object_root: false do - attributes :designation, :dedication, :origin_url, :id, :comment - + attributes :designation, :dedication, :origin_url, :id, :comment child :campaign, object_root: false do - attributes :name, :url, :id + attributes :name, :url, :id end - node(:campaign_gift){|d| {name: d.campaign_gifts.any? ? d.campaign_gifts.last.campaign_gift_option.name : nil}} + node(:campaign_gift) { |d| { name: d.campaign_gifts.any? ? d.campaign_gifts.last.campaign_gift_option.name : nil } } child :event, object_root: false do attributes :name, :url, :id end - child :recurring_donation, object_root: false do - attributes :interval, :time_unit, :created_at - end + child :recurring_donation, object_root: false do + attributes :interval, :time_unit, :created_at + end end child :dispute, object_root: false do @@ -38,37 +38,35 @@ child :dispute, object_root: false do end child :refund do - attributes :reason, :comment, :disbursed + attributes :reason, :comment, :disbursed end child :offsite_payment do - attributes :check_number, :kind + attributes :check_number, :kind end - node(:ticket) do |payment| event = payment&.tickets&.last&.event h = { - event: {name: event&.name, url: event&.url, id: event&.id}, - levels: payment.tickets.map{|t| "#{GetData.chain(t.ticket_level, :name)} (#{t.quantity}x)"}.join(", "), - discount: payment.tickets.map{|t| t.event_discount ? "#{t.event_discount.name} (#{t.event_discount.percent}%)" : nil}.compact.join(", ") + event: { name: event&.name, url: event&.url, id: event&.id }, + levels: payment.tickets.map { |t| "#{GetData.chain(t.ticket_level, :name)} (#{t.quantity}x)" }.join(', '), + discount: payment.tickets.map { |t| t.event_discount ? "#{t.event_discount.name} (#{t.event_discount.percent}%)" : nil }.compact.join(', ') } event ? h : nil end child :tickets, object_root: false do - attributes :id + attributes :id - child :ticket_level do - attributes :name - end + child :ticket_level do + attributes :name + end end child :supporter do - attributes :name, :email, :city, :state_code, :address, :zip_code, :phone, :id, :country - + attributes :name, :email, :city, :state_code, :address, :zip_code, :phone, :id, :country end child :nonprofit do - attributes :id + attributes :id end diff --git a/app/views/nonprofits/recurring_donations/show.rabl b/app/views/nonprofits/recurring_donations/show.rabl index 35a7b508..f8040f1a 100644 --- a/app/views/nonprofits/recurring_donations/show.rabl +++ b/app/views/nonprofits/recurring_donations/show.rabl @@ -1,15 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object @recurring_donation => :data attributes :id, :total_given, :supporter_id, :interval, :time_unit, :designation, :anonymous, :start_date, :end_date, :created_at, :paydate, :edit_token child :donation do - attributes :amount, :designation + attributes :amount, :designation end child :supporter do - attributes :name, :email, :id, :anonymous + attributes :name, :email, :id, :anonymous end child :card do - attributes :name + attributes :name end diff --git a/app/views/nonprofits/refunds/index.rabl b/app/views/nonprofits/refunds/index.rabl index afe5ee75..a837a07b 100644 --- a/app/views/nonprofits/refunds/index.rabl +++ b/app/views/nonprofits/refunds/index.rabl @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later object false child @refunds => :data do - collection @refunds, object_root: false - attributes :id, :amount, :created_at, :reason, :comment - + collection @refunds, object_root: false + attributes :id, :amount, :created_at, :reason, :comment end diff --git a/bin/bundle b/bin/bundle index 66e9889e..2dbb7176 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,5 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +# frozen_string_literal: true + +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 07396602..a31728ab 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index 17240489..c1999550 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/bin/setup b/bin/setup index e620b4da..31400462 100755 --- a/bin/setup +++ b/bin/setup @@ -1,10 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/bin/update b/bin/update index a8e4462f..1d6aa6a5 100755 --- a/bin/update +++ b/bin/update @@ -1,10 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/config.ru b/config.ru index 758e51e1..1155c753 100755 --- a/config.ru +++ b/config.ru @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require ::File.expand_path('../config/environment', __FILE__) run Commitchange::Application diff --git a/config/application.rb b/config/application.rb index 91784071..9dd2b4e2 100755 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require_relative 'boot' @@ -7,84 +9,83 @@ require 'rails/all' # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) - -#require File.expand_path('lib/htp') # Hamster Table Print +# require File.expand_path('lib/htp') # Hamster Table Print module Commitchange - class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. - # Custom directories with classes and modules you want to be autoloadable. - # config.autoload_paths += %W(#{config.root}/extras) - config.eager_load_paths += Dir["#{config.root}/lib/**/"] + # Custom directories with classes and modules you want to be autoloadable. + # config.autoload_paths += %W(#{config.root}/extras) + config.eager_load_paths += Dir["#{config.root}/lib/**/"] - config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') - config.eager_load_paths += Dir[Rails.root.join('app', 'api', '*')] + config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') + config.eager_load_paths += Dir[Rails.root.join('app', 'api', '*')] - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named. - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + # Only load the plugins named here, in the order given (default is alphabetical). + # :all can be used as a placeholder for all plugins not explicitly named. + # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - # Activate observers that should always be running. - # config.active_record.observers = :cacher, :garbage_collector, :forum_observer + # Activate observers that should always be running. + # config.active_record.observers = :cacher, :garbage_collector, :forum_observer - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - config.time_zone = 'UTC' + # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. + # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + config.time_zone = 'UTC' - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de + # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de - # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = "utf-8" + # Configure the default encoding used in templates for Ruby 1.9. + config.encoding = 'utf-8' - # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] + # Configure sensitive parameters which will be filtered from the log file. + config.filter_parameters += [:password] - # Enable escaping HTML in JSON. - config.active_support.escape_html_entities_in_json = true + # Enable escaping HTML in JSON. + config.active_support.escape_html_entities_in_json = true - # Use SQL instead of Active Record's schema dumper when creating the database. - # This is necessary if your schema can't be completely dumped by the schema dumper, - # like if you have constraints or database-specific column types - config.active_record.schema_format = :sql + # Use SQL instead of Active Record's schema dumper when creating the database. + # This is necessary if your schema can't be completely dumped by the schema dumper, + # like if you have constraints or database-specific column types + config.active_record.schema_format = :sql - # Enforce whitelist mode for mass assignment. - # This will create an empty whitelist of attributes available for mass-assignment for all models - # in your app. As such, your models will need to explicitly whitelist or blacklist accessible - # parameters by using an attr_accessible or attr_protected declaration. - #config.active_record.whitelist_attributes = true + # Enforce whitelist mode for mass assignment. + # This will create an empty whitelist of attributes available for mass-assignment for all models + # in your app. As such, your models will need to explicitly whitelist or blacklist accessible + # parameters by using an attr_accessible or attr_protected declaration. + # config.active_record.whitelist_attributes = true - # Enable the asset pipeline - config.assets.enabled = true + # Enable the asset pipeline + config.assets.enabled = true - # Precompile all "page" files - config.assets.precompile << Proc.new do |path| - if path =~ /.*page\.(css|js)/ - puts "Compiling asset: " + path - true - else - false - end - end + # Precompile all "page" files + config.assets.precompile << proc do |path| + if /.*page\.(css|js)/.match?(path) + puts 'Compiling asset: ' + path + true + else + false + end + end - # Version of your assets, change this If you want to expire all your assets - # config.assets.version = '1.0' + # Version of your assets, change this If you want to expire all your assets + # config.assets.version = '1.0' - # For Rails 3.1 on Heroku: - # Forces the application to not access the DB - # or load models when precompiling your assets. - # from: devise gem installation instructions/suggestions - # config.assets.initialize_on_precompile = true + # For Rails 3.1 on Heroku: + # Forces the application to not access the DB + # or load models when precompiling your assets. + # from: devise gem installation instructions/suggestions + # config.assets.initialize_on_precompile = true - config.i18n.enforce_available_locales = false + config.i18n.enforce_available_locales = false - # Add trailing slashes to all routes - # config.action_controller.default_url_options = {:trailing_slash => true} - # - # config.browserify_rails.commandline_options = "-t [ babelify --presets es2015 ]" - end + # Add trailing slashes to all routes + # config.action_controller.default_url_options = {:trailing_slash => true} + # + # config.browserify_rails.commandline_options = "-t [ babelify --presets es2015 ]" + end end diff --git a/config/boot.rb b/config/boot.rb index b1a8cf10..62bfc55e 100755 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' -require 'bootsnap/setup' \ No newline at end of file +require 'bootsnap/setup' diff --git a/config/environment.rb b/config/environment.rb index 85fd23e6..9dd7a2ec 100755 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Load the Rails application require_relative 'application' @@ -6,33 +8,28 @@ Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 @ignore_dotenv = ENV['IGNORE_DOTENV'] @env = Rails.env || 'development' -unless (@ignore_dotenv) +unless @ignore_dotenv require 'dotenv' if @env == 'test' - if File.file?(".env.#{@env}") - Dotenv.load ".env.#{@env}" - end + Dotenv.load ".env.#{@env}" if File.file?(".env.#{@env}") else - Dotenv.load ".env" + Dotenv.load '.env' end end @org_name = ENV['ORG_NAME'] || 'default_organization' -puts "config files .env .env.#{@env} ./config/settings.#{@env}.yml#{ @env != 'test' ? " ./config/#{@org_name}.yml": " "} #{ @env != 'test' ? " ./config/#{@org_name}.#{@env}.yml": " "} #{ @env == 'test' ? "./config/settings.test.yml" : ""}" +puts "config files .env .env.#{@env} ./config/settings.#{@env}.yml#{@env != 'test' ? " ./config/#{@org_name}.yml" : ' '} #{@env != 'test' ? " ./config/#{@org_name}.#{@env}.yml" : ' '} #{@env == 'test' ? './config/settings.test.yml' : ''}" if Rails.env == 'test' - Settings.add_source!("./config/settings.test.yml") + Settings.add_source!('./config/settings.test.yml') else Settings.add_source!("./config/#{@org_name}.yml") Settings.add_source!("./config/#{@org_name}.#{Rails.env}.yml") end +# Settings.add_source!("./config/#{@org_name}.#{Rails.env}.yml") - -#Settings.add_source!("./config/#{@org_name}.#{Rails.env}.yml") - -#we load the schema now because we didn't want to do so until we loaded EVERYTHING +# we load the schema now because we didn't want to do so until we loaded EVERYTHING Config.schema do - required(:general).schema do # the name of your website. Default in Settings is "Houdini Project" required(:name).filled(:str?) @@ -45,18 +42,17 @@ Config.schema do # the relative path from asset_host root to your poweredby email logo (PNG, 150px wide) required(:poweredby_logo).filled(:str?) - end required(:default).schema do required(:image).schema do - #the path on your image.host to your default profile image + # the path on your image.host to your default profile image required(:profile).filled(:str?) - #the path on your image.host to your default nonprofit image + # the path on your image.host to your default nonprofit image required(:nonprofit).filled(:str?) - #the path on your image.host to your default campaign background image + # the path on your image.host to your default campaign background image required(:campaign).filled(:str?) end @@ -80,7 +76,7 @@ Config.schema do end required(:mailer).schema do - #an action mailer delivery method + # an action mailer delivery method # Default is sendmail required(:delivery_method).filled(:str?) @@ -132,10 +128,10 @@ Config.schema do optional(:maps).schema do # the map provider to use. Currently that's just Google Maps or nothing # Default is nil - optional(:provider).value(included_in?:['google', nil]) + optional(:provider).value(included_in?: ['google', nil]) optional(:options).schema do - #key for your google maps instance + # key for your google maps instance optional(:key).filled(:str?) end end @@ -144,10 +140,9 @@ Config.schema do # The editor used for editing nonprofit, campaign # and event pages and some email templates # Default is 'quill' - required(:editor).value(included_in?:['quill', 'froala']) + required(:editor).value(included_in?: %w[quill froala]) optional(:editor_options).schema do - # Froala Key if your use froala # Default is nil (you need to get a key) required(:froala_key).filled(:str?) @@ -163,7 +158,7 @@ Config.schema do # Default is 1200 (20 minutes) required(:expiration_time).filled(:int?) - #event donation source tokens are unique. + # event donation source tokens are unique. # The idea is someone may want to donate multiple times at an event without # staff needing to enter their info again. Additionally, they # may want to do it after the event without staff @@ -176,27 +171,25 @@ Config.schema do # The time (in seconds) after an event ends that this token can be used. # Default is 1728000 (20 days) required(:time_after_event).filled(:int?) - end end - #sets the default language for the UI + # sets the default language for the UI required(:language).filled(:str?) - #sets the list of locales available + # sets the list of locales available required(:available_locales).each(:str?) # your default language needs to be in the available locales - rule(make_sure_language_in_locales: [:language, :available_locales]) do |language, available_locales| + rule(make_sure_language_in_locales: %i[language available_locales]) do |language, available_locales| language.included_in?(available_locales) end - # TODO have a way to validate the available_locales are actually available translations + # TODO: have a way to validate the available_locales are actually available translations # Whether to show state fields in the donation wizard optional(:show_state_fields).filled(:bool?) - required(:intntl).schema do # the supporter currencies for the site as abbreviations required(:currencies).each(:str?) @@ -205,17 +198,16 @@ Config.schema do required(:all_currencies).each do # each currency must have the following - # the unit. For 'usd', this would be "dollars" - required(:unit).filled(:str?) - # the abbreviation of the currency. For 'usd', this would be "usd" - required(:abbv).filled(:str?) - # the subunit of the currency. For 'usd', this would be "cents" - required(:subunit).filled(:str?) - # the currency symbol of the currency. For 'usd', this would be "$" - required(:symbol).filled(:str?) - - required(:format).filled(:str?) + # the unit. For 'usd', this would be "dollars" + required(:unit).filled(:str?) + # the abbreviation of the currency. For 'usd', this would be "usd" + required(:abbv).filled(:str?) + # the subunit of the currency. For 'usd', this would be "cents" + required(:subunit).filled(:str?) + # the currency symbol of the currency. For 'usd', this would be "$" + required(:symbol).filled(:str?) + required(:format).filled(:str?) end # an array of country codes to override the default set of countries @@ -228,8 +220,6 @@ Config.schema do # Xavier, I need you document this :) optional(:integration) - - end required(:default_bp).schema do @@ -257,7 +247,7 @@ Config.schema do # complete, corresponding source optional(:ccs).schema do - optional(:ccs_method).value(included_in?: %w(local_tar_gz github)) + optional(:ccs_method).value(included_in?: %w[local_tar_gz github]) # only used for github # NOTE: for github you need to have the hash of the corresponding source in $RAILS_ROOT/CCS_HASH @@ -280,10 +270,9 @@ Config.schema do # the url, absolute or relative, that visitors should be redirected to optional(:maintenance_page).filled(:str?) - end - #the url for your button. As a default, it takes what's in CDN.url + # the url for your button. As a default, it takes what's in CDN.url optional(:button_domain).schema do required(:url).filled?(:str) end @@ -292,7 +281,6 @@ Config.schema do optional(:api_domain).schema do required(:url).filled?(:str) end - end Settings.reload! diff --git a/config/environments/ci.rb b/config/environments/ci.rb index dc55b812..ee0b6c36 100755 --- a/config/environments/ci.rb +++ b/config/environments/ci.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb @@ -20,8 +22,8 @@ Rails.application.configure do # config.action_mailer.default_url_options = { host: 'commitchange.com' } config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } - config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username - config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password + config.action_mailer.smtp_settings['user_name'] = Settings.mailer.username if Settings.mailer.username + config.action_mailer.smtp_settings['password'] = Settings.mailer.password if Settings.mailer.password config.action_mailer.default_url_options = { host: Settings.mailer.host } diff --git a/config/environments/development.rb b/config/environments/development.rb index 8c42eb73..953bd659 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later CarrierWave.configure do |config| config.ignore_integrity_errors = false @@ -38,8 +40,8 @@ Rails.application.configure do # config.action_mailer.default_url_options = { host: 'commitchange.com' } config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym config.action_mailer.smtp_settings = { address: Settings.mailer.address, port: Settings.mailer.port } - config.action_mailer.smtp_settings['user_name']= Settings.mailer.username if Settings.mailer.username - config.action_mailer.smtp_settings['password']= Settings.mailer.password if Settings.mailer.password + config.action_mailer.smtp_settings['user_name'] = Settings.mailer.username if Settings.mailer.username + config.action_mailer.smtp_settings['password'] = Settings.mailer.password if Settings.mailer.password config.action_mailer.default_url_options = { host: Settings.mailer.host } @@ -82,5 +84,4 @@ Rails.application.configure do config.dependency_loading = true if $rails_rake_task config.middleware.use I18n::JS::Middleware - end diff --git a/config/environments/production.rb b/config/environments/production.rb index d730f187..821517b3 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -38,7 +40,6 @@ Rails.application.configure do # 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 @@ -50,7 +51,7 @@ Rails.application.configure do config.log_level = :info # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -79,7 +80,7 @@ Rails.application.configure do # require 'syslog/logger' # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - if ENV["RAILS_LOG_TO_STDOUT"].present? + if ENV['RAILS_LOG_TO_STDOUT'].present? logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) diff --git a/config/environments/staging.rb b/config/environments/staging.rb index d9717aaa..a3904469 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,78 +1,79 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb + # Settings specified here will take precedence over those in config/application.rb - # Code is not reloaded between requests - config.cache_classes = true + # Code is not reloaded between requests + config.cache_classes = true - # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false - config.action_controller.perform_caching = true + # Full error reports are disabled and caching is turned on + config.consider_all_requests_local = false + config.action_controller.perform_caching = true - # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = true + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = true - # Compress JavaScripts and CSS - config.assets.compress = true + # Compress JavaScripts and CSS + config.assets.compress = true - # Generate digests for assets URLs - config.assets.digest = true + # Generate digests for assets URLs + config.assets.digest = true - # Defaults to nil and saved in location specified by config.assets.prefix - # config.assets.manifest = YOUR_PATH + # Defaults to nil and saved in location specified by config.assets.prefix + # config.assets.manifest = YOUR_PATH - # 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 + # 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 - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true # See everything in the log (default is :info) - config.log_level = :info + config.log_level = :info - # Prepend all log lines with the following tags - # config.log_tags = [ :subdomain, :uuid ] + # Prepend all log lines with the following tags + # config.log_tags = [ :subdomain, :uuid ] - # Use a different logger for distributed setups - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # Use a different logger for distributed setups + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) - # Use a different cache store in production - # config.cache_store = :mem_cache_store + # Use a different cache store in production + # config.cache_store = :mem_cache_store - # Enable serving of images, stylesheets, and JavaScripts from an asset server - # cdn_url = "https://d2e5we1j08b82a.cloudfront.net" - # config.action_controller.asset_host = cdn_url - # config.action_mailer.asset_host = cdn_url - config.font_assets.origin = '*' + # Enable serving of images, stylesheets, and JavaScripts from an asset server + # cdn_url = "https://d2e5we1j08b82a.cloudfront.net" + # config.action_controller.asset_host = cdn_url + # config.action_mailer.asset_host = cdn_url + config.font_assets.origin = '*' - # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) - # config.assets.precompile = ['application', 'manifests/*'] + # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) + # config.assets.precompile = ['application', 'manifests/*'] - # Disable delivery errors, bad email addresses will be ignored - # config.action_mailer.raise_delivery_errors = false - config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym - config.action_mailer.default_url_options = { host: Settings.mailer.host } + # Disable delivery errors, bad email addresses will be ignored + # config.action_mailer.raise_delivery_errors = false + config.action_mailer.delivery_method = Settings.mailer.delivery_method.to_sym + config.action_mailer.default_url_options = { host: Settings.mailer.host } - # Enable threaded mode - # config.threadsafe! + # Enable threaded mode + # config.threadsafe! - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation can not be found) - config.i18n.fallbacks = true + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation can not be found) + config.i18n.fallbacks = true - # Send deprecation notices to registered listeners - config.active_support.deprecation = :notify + # Send deprecation notices to registered listeners + config.active_support.deprecation = :notify - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - # config.active_record.auto_explain_threshold_in_seconds = 0.5 + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + # config.active_record.auto_explain_threshold_in_seconds = 0.5 - config.assets.compile = false - - config.threadsafe! - config.dependency_loading = true if $rails_rake_task - # Compress json - # config.middleware.use Rack::Deflater + config.assets.compile = false + config.threadsafe! + config.dependency_loading = true if $rails_rake_task + # Compress json + # config.middleware.use Rack::Deflater end diff --git a/config/environments/test.rb b/config/environments/test.rb index 20bd8332..89d2ed0e 100755 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Commitchange::Application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -39,7 +41,7 @@ Commitchange::Application.configure do # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - config.action_mailer.default_url_options = {host: 'houdiniproject.test'} + config.action_mailer.default_url_options = { host: 'houdiniproject.test' } # Raises error for missing translations # config.action_view.raise_on_missing_translations = true diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 89d2efab..6d56e439 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 01ef3e66..678efe9f 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # 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. diff --git a/config/initializers/aws.rb b/config/initializers/aws.rb index 5335306f..1d534ae9 100644 --- a/config/initializers/aws.rb +++ b/config/initializers/aws.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -AWS.config({ +AWS.config( region: Settings.aws.region, access_key_id: Settings.aws.access_key_id, secret_access_key: Settings.aws.secret_access_key -}) +) s3 = AWS::S3.new S3Bucket = s3.buckets[Settings.aws.bucket] diff --git a/config/initializers/aws_ses.rb b/config/initializers/aws_ses.rb index aa96a921..74e49f1c 100644 --- a/config/initializers/aws_ses.rb +++ b/config/initializers/aws_ses.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later ActionMailer::Base.add_delivery_method :aws_ses, AWS::SES::Base, - access_key_id: ENV['AWS_ACCESS_KEY'], - secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], - server: 'email.us-east-1.amazonaws.com' + access_key_id: ENV['AWS_ACCESS_KEY'], + secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], + server: 'email.us-east-1.amazonaws.com' diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index e095c2f4..c1827ca8 100755 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. diff --git a/config/initializers/block_ips.rb b/config/initializers/block_ips.rb index ed9f52f0..8f91a826 100644 --- a/config/initializers/block_ips.rb +++ b/config/initializers/block_ips.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Rack::Attack.blocklist('block charge abusers') do |req| ['54.159.242.229', '54.161.246.233', - '54.211.94.199' - ].include? req.ip + '54.211.94.199'].include? req.ip end diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index 18e4d95b..301b8c4b 100755 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later CarrierWave.configure do |config| - config.storage = :aws - config.aws_bucket = Settings.aws.bucket - config.aws_acl = :public_read - config.asset_host = Settings.image&.host || "https://#{Settings.aws.bucket}.s3.amazonaws.com" - config.aws_authenticated_url_expiration = 60 * 60 * 24 * 365 - config.aws_credentials = { - access_key_id: Settings.aws.access_key_id, - secret_access_key: Settings.aws.secret_access_key, - config: AWS.config(cache_dir: "#{Rails.root}/tmp/uploads", region: Settings.aws.region) - } + config.storage = :aws + config.aws_bucket = Settings.aws.bucket + config.aws_acl = :public_read + config.asset_host = Settings.image&.host || "https://#{Settings.aws.bucket}.s3.amazonaws.com" + config.aws_authenticated_url_expiration = 60 * 60 * 24 * 365 + config.aws_credentials = { + access_key_id: Settings.aws.access_key_id, + secret_access_key: Settings.aws.secret_access_key, + config: AWS.config(cache_dir: "#{Rails.root}/tmp/uploads", region: Settings.aws.region) + } end diff --git a/config/initializers/chunked_uploader.rb b/config/initializers/chunked_uploader.rb index e0066c98..30d041c3 100644 --- a/config/initializers/chunked_uploader.rb +++ b/config/initializers/chunked_uploader.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -CHUNKED_UPLOADER = ENV['CHUNKED_UPLOAD_CLASS'] ? ENV['CHUNKED_UPLOAD_CLASS'].constantize : ChunkedUploader::S3 \ No newline at end of file +CHUNKED_UPLOADER = ENV['CHUNKED_UPLOAD_CLASS'] ? ENV['CHUNKED_UPLOAD_CLASS'].constantize : ChunkedUploader::S3 diff --git a/config/initializers/config.rb b/config/initializers/config.rb index b253585e..665b270a 100644 --- a/config/initializers/config.rb +++ b/config/initializers/config.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Config.setup do |config| # Name of the constant exposing loaded settings diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 5a6a32d3..ee8dff9c 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/config/initializers/delayed_job_config.rb b/config/initializers/delayed_job_config.rb index 08ff944b..4f673b2d 100644 --- a/config/initializers/delayed_job_config.rb +++ b/config/initializers/delayed_job_config.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Delayed::Worker.max_attempts = 1 diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index c140c3dd..97faf6e5 100755 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,229 +1,229 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| - # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = Settings.devise.mailer_sender + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in Devise::Mailer, + # note that it will be overwritten if you use your own mailer class with default "from" parameter. + config.mailer_sender = Settings.devise.mailer_sender - # Configure the class responsible to send e-mails. - # config.mailer = "Devise::Mailer" + # Configure the class responsible to send e-mails. + # config.mailer = "Devise::Mailer" - # ==> ORM configuration - # Load and configure the ORM. Supports :active_record (default) and - # :mongoid (bson_ext recommended) by default. Other ORMs may be - # available as additional gems. - require 'devise/orm/active_record' + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' - # ==> Configuration for any authentication mechanism - # Configure which keys are used when authenticating a user. The default is - # just :email. You can configure it to use [:username, :subdomain], so for - # authenticating a user, both parameters are required. Remember that those - # parameters are used only when authenticating and not when retrieving from - # session. If you need permissions, you should implement that in a before filter. - # You can also supply a hash where the value is a boolean determining whether - # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [ :email ] + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating a user. The default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating a user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. + # config.authentication_keys = [ :email ] - # Configure parameters from the request object used for authentication. Each entry - # given should be a request method and it will automatically be passed to the - # find_for_authentication method and considered in your model lookup. For instance, - # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. - # The same considerations mentioned for authentication_keys also apply to request_keys. - # config.request_keys = [] + # Configure parameters from the request object used for authentication. Each entry + # given should be a request method and it will automatically be passed to the + # find_for_authentication method and considered in your model lookup. For instance, + # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. + # The same considerations mentioned for authentication_keys also apply to request_keys. + # config.request_keys = [] - # Configure which authentication keys should be case-insensitive. - # These keys will be downcased upon creating or modifying a user and when used - # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [ :email ] + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + config.case_insensitive_keys = [:email] - # Configure which authentication keys should have whitespace stripped. - # These keys will have whitespace before and after removed upon creating or - # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [ :email ] + # Configure which authentication keys should have whitespace stripped. + # These keys will have whitespace before and after removed upon creating or + # modifying a user and when used to authenticate or find a user. Default is :email. + config.strip_whitespace_keys = [:email] - # Tell if authentication through request.params is enabled. True by default. - # It can be set to an array that will enable params authentication only for the - # given strategies, for example, `config.params_authenticatable = [:database]` will - # enable it only for database (email + password) authentication. - # config.params_authenticatable = true + # Tell if authentication through request.params is enabled. True by default. + # It can be set to an array that will enable params authentication only for the + # given strategies, for example, `config.params_authenticatable = [:database]` will + # enable it only for database (email + password) authentication. + # config.params_authenticatable = true - # Tell if authentication through HTTP Basic Auth is enabled. False by default. - # It can be set to an array that will enable http authentication only for the - # given strategies, for example, `config.http_authenticatable = [:token]` will - # enable it only for token authentication. - # config.http_authenticatable = false + # Tell if authentication through HTTP Basic Auth is enabled. False by default. + # It can be set to an array that will enable http authentication only for the + # given strategies, for example, `config.http_authenticatable = [:token]` will + # enable it only for token authentication. + # config.http_authenticatable = false - # If http headers should be returned for AJAX requests. True by default. - # config.http_authenticatable_on_xhr = true + # If http headers should be returned for AJAX requests. True by default. + # config.http_authenticatable_on_xhr = true - # The realm used in Http Basic Authentication. "Application" by default. - # config.http_authentication_realm = "Application" + # The realm used in Http Basic Authentication. "Application" by default. + # config.http_authentication_realm = "Application" - # It will change confirmation, password recovery and other workflows - # to behave the same regardless if the e-mail provided was right or wrong. - # Does not affect registerable. - # config.paranoid = true + # It will change confirmation, password recovery and other workflows + # to behave the same regardless if the e-mail provided was right or wrong. + # Does not affect registerable. + # config.paranoid = true - # By default Devise will store the user in session. You can skip storage for - # :http_auth and :token_auth by adding those symbols to the array below. - # Notice that if you are skipping storage for all authentication paths, you - # may want to disable generating routes to Devise's sessions controller by - # passing :skip => :sessions to `devise_for` in your config/routes.rb - config.skip_session_storage = [:http_auth] + # By default Devise will store the user in session. You can skip storage for + # :http_auth and :token_auth by adding those symbols to the array below. + # Notice that if you are skipping storage for all authentication paths, you + # may want to disable generating routes to Devise's sessions controller by + # passing :skip => :sessions to `devise_for` in your config/routes.rb + config.skip_session_storage = [:http_auth] - # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 10. If - # using other encryptors, it sets how many times you want the password re-encrypted. - # - # Limiting the stretches to just one in testing will increase the performance of - # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use - # a value less than 10 in other environments. - config.stretches = Rails.env.test? ? 1 : 10 + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 10. If + # using other encryptors, it sets how many times you want the password re-encrypted. + # + # Limiting the stretches to just one in testing will increase the performance of + # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use + # a value less than 10 in other environments. + config.stretches = Rails.env.test? ? 1 : 10 + # ==> Configuration for :confirmable + # A period that the user is allowed to access the website even without + # confirming his account. For instance, if set to 2.days, the user will be + # able to access the website for two days without confirming his account, + # access will be blocked just in the third day. Default is 0.days, meaning + # the user cannot access the website without confirming his account. + # config.allow_unconfirmed_access_for = 2.days - # ==> Configuration for :confirmable - # A period that the user is allowed to access the website even without - # confirming his account. For instance, if set to 2.days, the user will be - # able to access the website for two days without confirming his account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming his account. - # config.allow_unconfirmed_access_for = 2.days + # If true, requires any email changes to be confirmed (exactly the same way as + # initial account confirmation) to be applied. Requires additional unconfirmed_email + # db field (see migrations). Until confirmed new email is stored in + # unconfirmed email column, and copied to email column on successful confirmation. + config.reconfirmable = true - # If true, requires any email changes to be confirmed (exactly the same way as - # initial account confirmation) to be applied. Requires additional unconfirmed_email - # db field (see migrations). Until confirmed new email is stored in - # unconfirmed email column, and copied to email column on successful confirmation. - config.reconfirmable = true + # Defines which key will be used when confirming an account + # config.confirmation_keys = [ :email ] - # Defines which key will be used when confirming an account - # config.confirmation_keys = [ :email ] + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks - # ==> Configuration for :rememberable - # The time the user will be remembered without asking for credentials again. - # config.remember_for = 2.weeks + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false - # If true, extends the user's remember period when remembered via cookie. - # config.extend_remember_period = false + # Options to be passed to the created cookie. For instance, you can set + # :secure => true in order to force SSL only cookies. + # config.rememberable_options = {} - # Options to be passed to the created cookie. For instance, you can set - # :secure => true in order to force SSL only cookies. - # config.rememberable_options = {} + # ==> Configuration for :validatable + # Range for password length. Default is 6..128. + # config.password_length = 6..128 - # ==> Configuration for :validatable - # Range for password length. Default is 6..128. - # config.password_length = 6..128 + # Email regex used to validate email formats. It simply asserts that + # an one (and only one) @ exists in the given string. This is mainly + # to give user feedback and not to assert the e-mail validity. + # config.email_regexp = /\A[^@]+@[^@]+\z/ - # Email regex used to validate email formats. It simply asserts that - # an one (and only one) @ exists in the given string. This is mainly - # to give user feedback and not to assert the e-mail validity. - # config.email_regexp = /\A[^@]+@[^@]+\z/ + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. Default is 30 minutes. + # config.timeout_in = 30.minutes - # ==> Configuration for :timeoutable - # The time you want to timeout the user session without activity. After this - # time the user will be asked for credentials again. Default is 30 minutes. - # config.timeout_in = 30.minutes + # If true, expires auth token on session timeout. + # config.expire_auth_token_on_timeout = false - # If true, expires auth token on session timeout. - # config.expire_auth_token_on_timeout = false + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts - # ==> Configuration for :lockable - # Defines which strategy will be used to lock an account. - # :failed_attempts = Locks an account after a number of failed attempts to sign in. - # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts + # Defines which key will be used when locking and unlocking an account + # config.unlock_keys = [ :email ] - # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [ :email ] + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both - # Defines which strategy will be used to unlock an account. - # :email = Sends an unlock link to the user email - # :time = Re-enables login after a certain amount of time (see :unlock_in below) - # :both = Enables both strategies - # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 - # Number of authentication tries before locking an account if lock_strategy - # is failed attempts. - # config.maximum_attempts = 20 + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour - # Time interval to unlock the account if :time is enabled as unlock_strategy. - # config.unlock_in = 1.hour + # ==> Configuration for :recoverable + # + # Defines which key will be used when recovering the password for an account + # config.reset_password_keys = [ :email ] - # ==> Configuration for :recoverable - # - # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [ :email ] + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 6.hours - # Time interval you can reset your password with a reset password key. - # Don't put a too small interval or your users won't have the time to - # change their passwords. - config.reset_password_within = 6.hours + # ==> Configuration for :encryptable + # Allow you to use another encryption algorithm besides bcrypt (default). You can use + # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, + # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) + # and :restful_authentication_sha1 (then you should set stretches to 10, and copy + # REST_AUTH_SITE_KEY to pepper) + # config.encryptor = :sha512 - # ==> Configuration for :encryptable - # Allow you to use another encryption algorithm besides bcrypt (default). You can use - # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, - # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) - # and :restful_authentication_sha1 (then you should set stretches to 10, and copy - # REST_AUTH_SITE_KEY to pepper) - # config.encryptor = :sha512 + # ==> Configuration for :token_authenticatable + # Defines name of the authentication token params key + # config.token_authentication_key = :auth_token - # ==> Configuration for :token_authenticatable - # Defines name of the authentication token params key - # config.token_authentication_key = :auth_token + # ==> Scopes configuration + # Turn scoped views on. Before rendering "sessions/new", it will first check for + # "users/sessions/new". It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = false - # ==> Scopes configuration - # Turn scoped views on. Before rendering "sessions/new", it will first check for - # "users/sessions/new". It's turned off by default because it's slower if you - # are using only default views. - # config.scoped_views = false + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes (usually :user). + # config.default_scope = :user - # Configure the default scope given to Warden. By default it's the first - # devise role declared in your routes (usually :user). - # config.default_scope = :user + # Set this configuration to false if you want /users/sign_out to sign out + # only the current scope. By default, Devise signs out all scopes. + # config.sign_out_all_scopes = true - # Set this configuration to false if you want /users/sign_out to sign out - # only the current scope. By default, Devise signs out all scopes. - # config.sign_out_all_scopes = true + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html, should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. + # + # The "*/*" below is required to match Internet Explorer requests. + # config.navigational_formats = ["*/*", :html] - # ==> Navigation configuration - # Lists the formats that should be treated as navigational. Formats like - # :html, should redirect to the sign in page when the user does not have - # access, but formats like :xml or :json, should return 401. - # - # If you have any extra navigational formats, like :iphone or :mobile, you - # should add them to the navigational formats lists. - # - # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ["*/*", :html] + # The default HTTP method used to sign out a resource. Default is :delete. + config.sign_out_via = :get - # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :get + config.secret_key = ENV.fetch('DEVISE_SECRET_KEY') + # ==> Warden configuration + # If you want to use other strategies, that are not supported by Devise, or + # change the failure app, you can configure them inside the config.warden block. + # + # config.warden do |manager| + # manager.intercept_401 = false + # manager.default_strategies(:scope => :user).unshift :some_external_strategy + # end - config.secret_key = ENV.fetch('DEVISE_SECRET_KEY') - - # ==> Warden configuration - # If you want to use other strategies, that are not supported by Devise, or - # change the failure app, you can configure them inside the config.warden block. - # - # config.warden do |manager| - # manager.intercept_401 = false - # manager.default_strategies(:scope => :user).unshift :some_external_strategy - # end - - # ==> Mountable engine configurations - # When using Devise inside an engine, let's call it `MyEngine`, and this engine - # is mountable, there are some extra configurations to be taken into account. - # The following options are available, assuming the engine is mounted as: - # - # mount MyEngine, at: "/my_engine" - # - # The router that invoked `devise_for`, in the example above, would be: - # config.router_name = :my_engine - # - # When using omniauth, Devise cannot automatically set Omniauth path, - # so you need to do it manually. For the users scope, it would be: - # config.omniauth_path_prefix = "/my_engine/users/auth" + # ==> Mountable engine configurations + # When using Devise inside an engine, let's call it `MyEngine`, and this engine + # is mountable, there are some extra configurations to be taken into account. + # The following options are available, assuming the engine is mounted as: + # + # mount MyEngine, at: "/my_engine" + # + # The router that invoked `devise_for`, in the example above, would be: + # config.router_name = :my_engine + # + # When using omniauth, Devise cannot automatically set Omniauth path, + # so you need to do it manually. For the users scope, it would be: + # config.omniauth_path_prefix = "/my_engine/users/auth" end diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb index 42d81a4e..08a6cce0 100644 --- a/config/initializers/devise_async.rb +++ b/config/initializers/devise_async.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -#Devise::Async.backend = :delayed_job +# Devise::Async.backend = :delayed_job diff --git a/config/initializers/email_jobs.rb b/config/initializers/email_jobs.rb index a327a3a2..6523df69 100644 --- a/config/initializers/email_jobs.rb +++ b/config/initializers/email_jobs.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -MAX_EMAIL_JOB_ATTEMPTS = Rails.env == 'production' ? 50 : 2 \ No newline at end of file +MAX_EMAIL_JOB_ATTEMPTS = Rails.env == 'production' ? 50 : 2 diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1e..7a4f47b4 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/config/initializers/fullcontact.rb b/config/initializers/fullcontact.rb index aba9e144..780bfaaa 100644 --- a/config/initializers/fullcontact.rb +++ b/config/initializers/fullcontact.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require "fullcontact" +require 'fullcontact' FullContact.configure do |config| - config.api_key = ENV['FULL_CONTACT_KEY'] + config.api_key = ENV['FULL_CONTACT_KEY'] end -# see gem docs: https://github.com/fullcontact/fullcontact-api-ruby \ No newline at end of file +# see gem docs: https://github.com/fullcontact/fullcontact-api-ruby diff --git a/config/initializers/geocode.rb b/config/initializers/geocode.rb index aa034b73..0d7a0ed5 100644 --- a/config/initializers/geocode.rb +++ b/config/initializers/geocode.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Geocoder.configure({ +Geocoder.configure( cache: Rails.cache, lookup: :google, use_https: true, api_key: ENV['GOOGLE_API_KEY'], timeout: 10 -}) +) diff --git a/config/initializers/hamster_extensions.rb b/config/initializers/hamster_extensions.rb index 0181ba95..bd096a29 100644 --- a/config/initializers/hamster_extensions.rb +++ b/config/initializers/hamster_extensions.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Hamster extesions/modifications # Default Hamster to_json methods don't work right module ProperJson - def to_json(options={}) + def to_json(options = {}) Hamster.to_ruby(self).to_json(options) end end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9..dc847422 100755 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/config/initializers/locale.rb b/config/initializers/locale.rb index 44eafa22..e86b5d39 100644 --- a/config/initializers/locale.rb +++ b/config/initializers/locale.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later I18n.available_locales = Settings.available_locales Rails.application.config.i18n.fallbacks = [I18n.default_locale] diff --git a/config/initializers/log_rage.rb b/config/initializers/log_rage.rb index f76666a7..99017ba9 100644 --- a/config/initializers/log_rage.rb +++ b/config/initializers/log_rage.rb @@ -1,15 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Rails.application.configure do - if (Rails.env != 'test') + if Rails.env != 'test' - - config.lograge.enabled = true - # add time to lograge - config.lograge.custom_options = lambda do |event| - { time: event.time, - exception: event.payload[:exception], # ["ExceptionClass", "the message"] - exception_object: event.payload[:exception_object] # the exception instance - } + config.lograge.enabled = true + # add time to lograge + config.lograge.custom_options = lambda do |event| + { time: event.time, + exception: event.payload[:exception], # ["ExceptionClass", "the message"] + exception_object: event.payload[:exception_object] } # the exception instance + end end - end -end \ No newline at end of file +end diff --git a/config/initializers/mailchimp.rb b/config/initializers/mailchimp.rb index b727aef8..34ec6aaa 100644 --- a/config/initializers/mailchimp.rb +++ b/config/initializers/mailchimp.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'mailchimp' -Mailchimp.config({ - :api_key => ENV['MAILCHIMP_API_KEY'] -}) +Mailchimp.config( + api_key: ENV['MAILCHIMP_API_KEY'] +) diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc189968..be6fedc5 100755 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/pg_type_map.rb b/config/initializers/pg_type_map.rb index 1072e823..ecb9dd8b 100644 --- a/config/initializers/pg_type_map.rb +++ b/config/initializers/pg_type_map.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'active_record' require 'qx' @@ -8,6 +10,5 @@ rescue ActiveRecord::NoDatabaseError false else Qx.config(type_map: PG::BasicTypeMapForResults.new(ActiveRecord::Base.connection.raw_connection)) - Qx.execute("SET TIME ZONE utc") + Qx.execute('SET TIME ZONE utc') end - diff --git a/config/initializers/quiet_assets.rb b/config/initializers/quiet_assets.rb index 7bb65cb7..b0be9f6f 100644 --- a/config/initializers/quiet_assets.rb +++ b/config/initializers/quiet_assets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later if Rails.env.development? # Rails.application.assets.logger = Logger.new('/dev/null') diff --git a/config/initializers/rabl_init.rb b/config/initializers/rabl_init.rb index acd7ebaa..8d1da391 100644 --- a/config/initializers/rabl_init.rb +++ b/config/initializers/rabl_init.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rabl' Rabl.configure do |config| - config.enable_json_callbacks = true + config.enable_json_callbacks = true end diff --git a/config/initializers/reload_api.rb b/config/initializers/reload_api.rb index 41e476bc..8ec0657e 100644 --- a/config/initializers/reload_api.rb +++ b/config/initializers/reload_api.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + if Rails.env.development? ActiveSupport::Dependencies.explicitly_unloadable_constants << 'Houdini::V1' diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index 10dc8dd1..0d405334 100755 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Be sure to restart your server when you modify this file. @@ -5,4 +7,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -Rails.application.config.secret_token = ENV.fetch('SECRET_TOKEN') +Rails.application.config.secret_key_base = ENV.fetch('SECRET_TOKEN') diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 0fa3b506..c46dbdec 100755 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: '_commitchange_session' diff --git a/config/initializers/slack_notice.rb b/config/initializers/slack_notice.rb index 3f6519e7..2d8f127d 100644 --- a/config/initializers/slack_notice.rb +++ b/config/initializers/slack_notice.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # This will fire a slack event when charges are greater than $3 Million # We can then remove this file and/or update any notice we'd like @@ -10,4 +12,4 @@ # if charges >= 300000000 # notifier = Slack::Notifier.new webhook_url, channel: '#general', username: 'CommitChange' # notifier.ping " We've processed more than $3,000,000 dollars!" -# end \ No newline at end of file +# end diff --git a/config/initializers/stripe.rb b/config/initializers/stripe.rb index 8148222c..e51bc8f7 100644 --- a/config/initializers/stripe.rb +++ b/config/initializers/stripe.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'stripe' -Stripe.api_key = Settings.payment_provider.stripe_private_key; +Stripe.api_key = Settings.payment_provider.stripe_private_key diff --git a/config/initializers/time.rb b/config/initializers/time.rb index ebef3a83..d8dd8755 100644 --- a/config/initializers/time.rb +++ b/config/initializers/time.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later ENV['TZ'] = 'UTC' Time.zone = 'UTC' diff --git a/config/initializers/timeout.rb b/config/initializers/timeout.rb index e1cc5c7c..69b4f74b 100644 --- a/config/initializers/timeout.rb +++ b/config/initializers/timeout.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # timeout = Integer(ENV['WEB_TIMEOUT'] || 15) # if ENV['RAILS_ENV'] == 'development' || ENV['IDE_PROCESS_DISPATCHER'] # timeout = 10000 # end # -# Rack::Timeout.timeout = timeout # seconds \ No newline at end of file +# Rack::Timeout.timeout = timeout # seconds diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index c72a9676..8447298a 100755 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/config/puma.rb b/config/puma.rb index b93dad33..f3eaa09e 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Puma can serve each request in a thread from an internal thread pool. @@ -6,19 +8,17 @@ # 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 }.to_i +threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }.to_i threads threads_count, threads_count preload_app! if ENV['RAILS_ENV'] != 'development' rackup DefaultRackup -port ENV.fetch("PORT") { 5000 } -environment ENV.fetch('RAILS_ENV'){ 'development' } +port ENV.fetch('PORT') { 5000 } +environment ENV.fetch('RAILS_ENV') { 'development' } workers Integer(ENV['WEB_CONCURRENCY'] || 1) - - on_worker_boot do # ActiveSupport.on_load(:active_record) do # config = ActiveRecord::Base.configurations[Rails.env] || @@ -31,4 +31,3 @@ end # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart - diff --git a/config/routes.rb b/config/routes.rb index 32c60eb3..287f964d 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,266 +1,260 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later Rails.application.routes.draw do mount Houdini::API => '/api' if Rails.env == 'development' - get '/button_debug/embedded' => 'button_debug#embedded' - get '/button_debug/button' => 'button_debug#button' - get '/button_debug/embedded/:id' => 'button_debug#embedded' - get '/button_debug/button/:id' => 'button_debug#button' + get '/button_debug/embedded' => 'button_debug#embedded' + get '/button_debug/button' => 'button_debug#button' + get '/button_debug/embedded/:id' => 'button_debug#embedded' + get '/button_debug/button/:id' => 'button_debug#button' end get 'onboard' => 'onboard#index' - resources(:emails, {only: [:create]}) - resources(:settings, {only: [:index]}) - resources(:campaign_gifts, {only: [:create]}) - resource(:cards, {only: [:create, :update, :destroy]}) - resource(:direct_debit_details, {path: 'sepa', controller: :direct_debit_details, only: [:create]}) - # resources(:activities, {only: [:create]}) + resources(:emails, only: [:create]) + resources(:settings, only: [:index]) + resources(:campaign_gifts, only: [:create]) + resource(:cards, only: %i[create update destroy]) + resource(:direct_debit_details, path: 'sepa', controller: :direct_debit_details, only: [:create]) + # resources(:activities, {only: [:create]}) # Creating presigned posts for direct-to-S3 upload - resources(:aws_presigned_posts, {only: [:create]}) + resources(:aws_presigned_posts, only: [:create]) - resources(:image_attachments, {only: [:create]}) do - post(:remove, {on: :collection}) - end - - resources(:profiles, {only: [:show, :update]}) do - get(:fundraisers, {on: :member}) - get(:events, {on: :member}) - get(:donations_history, {on: :member}) - end - - - namespace(:nonprofits, {path: 'nonprofits/:nonprofit_id'}) do - resources(:payouts, {only: [:create, :index, :show]}) - resources(:imports, {only: [:create]}) - resources(:nonprofit_keys, {only: [:index]}) do - get(:mailchimp_login, {on: :collection}) - get(:mailchimp_landing, {on: :collection}) - end - resources(:reports, {only: []}) do - get(:end_of_year, {on: :collection}) - get(:end_of_year_custom, {on: :collection}) - end - resources(:email_lists, {only: [:index, :create]}) - resources(:payments, {only: [:index, :show, :update, :destroy]}) do - post(:export, {on: :collection}) - post(:resend_donor_receipt, {on: :member}) - post(:resend_admin_receipt, {on: :member}) - - end - resources(:donations, {only: [:index, :show, :create, :update]}) do - put(:followup, {on: :member}) - post(:create_offsite, {on: :collection}) - end - resource(:card, {only: [:edit, :update, :show, :create]}) - - resources(:charges, {only: [:index]}) do - resources(:refunds, {only: [:create, :index]}) - end - - resource(:bank_account, {only: [:create]}) do - get(:confirmation) - post(:confirm) - get(:cancellation) - post(:cancel) - post(:resend_confirmation) - end - - resources(:supporter_emails, {only: [:create, :show]}) do - post(:gmail, {on: :collection}) - end - - resources(:custom_field_masters, {only: [:index, :create, :destroy]}) - resources(:custom_field_joins, {only: []}) do - post(:modify, {on: :collection}) - end - - resources(:tag_masters, {only: [:index, :create, :destroy]}) - resources(:tag_joins, {only: []}) do - post(:modify, {on: :collection}) - end - - resources(:supporters, {only: [:index, :show, :create, :update, :new]}) do - resources(:tag_joins, {only: [:index, :destroy]}) - resources(:custom_field_joins, {only: [:index, :destroy]}) - resources(:supporter_notes, {only: [:create, :update, :destroy]}) - resources(:activities, {only: [:index]}) - post(:export, {on: :collection}) - put :bulk_delete, on: :collection - post :merge, on: :collection - get :merge_data, on: :collection - get :info_card, on: :member - get :email_address, on: :member - get :full_contact, on: :member - get :index_metrics, on: :collection - end - - resources(:recurring_donations, {only: [:index, :show, :destroy, :update, :create]}) do - post(:export, on: :collection) - end - - resource(:miscellaneous_np_info, {only: [:show, :update]}) - - namespace(:button) do - root({action: :advanced}) - get(:basic) - get(:guided) - get(:advanced) - post(:send_code) - end - - post 'tracking', controller: 'trackings', action: 'create' - end - - namespace(:campaigns, {path: '/nonprofits/:nonprofit_id/campaigns/:campaign_id/admin', only: []}) do - resources(:supporters, {only: [:index]}) - resources(:donations, {only: [:index]}) - resources(:campaign_gift_options, {only: [:index]}) + resources(:image_attachments, only: [:create]) do + post(:remove, on: :collection) end - resources(:nonprofits, {only: [:show, :create, :update, :destroy]}) do - post(:onboard, {on: :collection}) - get(:profile_todos, {on: :member}) - get(:recurring_donation_stats, {on: :member}) - get(:search, {on: :collection}) - get(:dashboard_todos, {on: :member}) - put(:verify_identity, {on: :member}) + resources(:profiles, only: %i[show update]) do + get(:fundraisers, on: :member) + get(:events, on: :member) + get(:donations_history, on: :member) + end + namespace(:nonprofits, path: 'nonprofits/:nonprofit_id') do + resources(:payouts, only: %i[create index show]) + resources(:imports, only: [:create]) + resources(:nonprofit_keys, only: [:index]) do + get(:mailchimp_login, on: :collection) + get(:mailchimp_landing, on: :collection) + end + resources(:reports, only: []) do + get(:end_of_year, on: :collection) + get(:end_of_year_custom, on: :collection) + end + resources(:email_lists, only: %i[index create]) + resources(:payments, only: %i[index show update destroy]) do + post(:export, on: :collection) + post(:resend_donor_receipt, on: :member) + post(:resend_admin_receipt, on: :member) + end + resources(:donations, only: %i[index show create update]) do + put(:followup, on: :member) + post(:create_offsite, on: :collection) + end + resource(:card, only: %i[edit update show create]) - resources(:roles, {only: [:create, :destroy]}) - resources(:settings, {only: [:index]}) - resources(:pricing, {only: [:index]}) - resources(:email_settings, {only: [:index, :create]}) - resources(:users, {only: [:index, :create]}) do - resources(:email_settings, {only: [:index, :create]}) + resources(:charges, only: [:index]) do + resources(:refunds, only: %i[create index]) end - resources(:campaigns, {only: [:index, :show, :create, :update]}) do - get(:metrics, {on: :member}) - get(:totals, {on: :member}) - get(:timeline, {on: :member}) - post(:duplicate, {on: :member}) - get(:activities, {on: :member}) - put(:soft_delete, {on: :member}) - get(:name_and_id, {on: :collection}) - post :create_from_template, on: :collection - resources(:campaign_gift_options, {only: [:index, :show, :create, :update, :destroy]}) do - put(:update_order, {on: :collection}) - end - end - - resource(:billing_subscription, {only: [:create]}) do - post(:cancel) - post(:create_trial, {on: :member}) + resource(:bank_account, only: [:create]) do + get(:confirmation) + post(:confirm) get(:cancellation) - end + post(:cancel) + post(:resend_confirmation) + end - resources(:events, {only: [:index, :show, :create, :update]}) do - get(:metrics, {on: :member}) - get(:listings, {on: :collection}) - get(:stats, {on: :member}) - get(:name_and_id, {on: :collection}) - get(:activities, {on: :member}) - post(:duplicate, {on: :member}) - put(:soft_delete) - resources(:tickets, {only: [:create, :update, :index, :destroy]}) do - put(:add_note, {on: :member}) - post(:delete_card_for_ticket, {on: :member}) - end - resources(:ticket_levels, {only: [:index, :show, :create, :update, :destroy]}) do - put(:update_order, {on: :collection}) - end - resources(:event_discounts, {only: [:create, :index, :update, :destroy]}) - end + resources(:supporter_emails, only: %i[create show]) do + post(:gmail, on: :collection) + end - get(:donate, {on: :member}) - get(:btn, {on: :member}) - get(:supporter_form, {on: :member}) - post(:custom_supporter, {on: :member}) - get(:dashboard, {on: :member}) - get(:dashboard_metrics, {on: :member}) - get(:payment_history, {on: :member}) + resources(:custom_field_masters, only: %i[index create destroy]) + resources(:custom_field_joins, only: []) do + post(:modify, on: :collection) + end - post(:donate, {on: :member, as: 'create_donation'}) - end + resources(:tag_masters, only: %i[index create destroy]) + resources(:tag_joins, only: []) do + post(:modify, on: :collection) + end - resources(:recurring_donations, {only: [:edit, :destroy, :update]}) do - put(:update_amount, {on: :member}) + resources(:supporters, only: %i[index show create update new]) do + resources(:tag_joins, only: %i[index destroy]) + resources(:custom_field_joins, only: %i[index destroy]) + resources(:supporter_notes, only: %i[create update destroy]) + resources(:activities, only: [:index]) + post(:export, on: :collection) + put :bulk_delete, on: :collection + post :merge, on: :collection + get :merge_data, on: :collection + get :info_card, on: :member + get :email_address, on: :member + get :full_contact, on: :member + get :index_metrics, on: :collection + end + + resources(:recurring_donations, only: %i[index show destroy update create]) do + post(:export, on: :collection) + end + + resource(:miscellaneous_np_info, only: %i[show update]) + + namespace(:button) do + root(action: :advanced) + get(:basic) + get(:guided) + get(:advanced) + post(:send_code) + end + + post 'tracking', controller: 'trackings', action: 'create' end - devise_for :users, - :controllers => { - :sessions => 'users/sessions', - :registrations => 'users/registrations', - :confirmations => 'users/confirmations' - } - devise_scope :user do - match '/sign_in' => 'users/sessions#new', via: [:get, :post] - match '/signup' => 'devise/registrations#new', via: [:get, :post] - post '/confirm' => 'users/confirmations#confirm', via: [:get] - match '/users/is_confirmed' => 'users/confirmations#is_confirmed', via: [:get, :post] - match '/users/exists' => 'users/confirmations#exists', via: [:get] - post '/users/confirm_auth', action: :confirm_auth, controller: 'users/sessions', via: [:get, :post] - end + namespace(:campaigns, path: '/nonprofits/:nonprofit_id/campaigns/:campaign_id/admin', only: []) do + resources(:supporters, only: [:index]) + resources(:donations, only: [:index]) + resources(:campaign_gift_options, only: [:index]) + end - # Super admin - match '/admin' => 'super_admins#index', :as => 'admin', via: [:get, :post] - match '/admin/search-nonprofits' => 'super_admins#search_nonprofits', via: [:get, :post] - match '/admin/search-profiles' => 'super_admins#search_profiles', via: [:get, :post] - match '/admin/search-fullcontact' => 'super_admins#search_fullcontact', via: [:get, :post] - match '/admin/recurring-donations-without-cards' => 'super_admins#recurring_donations_without_cards', via: [:get, :post] - match '/admin/export_supporters_with_rds' => 'super_admins#export_supporters_with_rds', via: [:get, :post] - match '/admin/resend_user_confirmation' => 'super_admins#resend_user_confirmation', via: [:get, :post] + resources(:nonprofits, only: %i[show create update destroy]) do + post(:onboard, on: :collection) + get(:profile_todos, on: :member) + get(:recurring_donation_stats, on: :member) + get(:search, on: :collection) + get(:dashboard_todos, on: :member) + put(:verify_identity, on: :member) + + resources(:roles, only: %i[create destroy]) + resources(:settings, only: [:index]) + resources(:pricing, only: [:index]) + resources(:email_settings, only: %i[index create]) + resources(:users, only: %i[index create]) do + resources(:email_settings, only: %i[index create]) + end + + resources(:campaigns, only: %i[index show create update]) do + get(:metrics, on: :member) + get(:totals, on: :member) + get(:timeline, on: :member) + post(:duplicate, on: :member) + get(:activities, on: :member) + put(:soft_delete, on: :member) + get(:name_and_id, on: :collection) + post :create_from_template, on: :collection + resources(:campaign_gift_options, only: %i[index show create update destroy]) do + put(:update_order, on: :collection) + end + end + + resource(:billing_subscription, only: [:create]) do + post(:cancel) + post(:create_trial, on: :member) + get(:cancellation) + end + + resources(:events, only: %i[index show create update]) do + get(:metrics, on: :member) + get(:listings, on: :collection) + get(:stats, on: :member) + get(:name_and_id, on: :collection) + get(:activities, on: :member) + post(:duplicate, on: :member) + put(:soft_delete) + resources(:tickets, only: %i[create update index destroy]) do + put(:add_note, on: :member) + post(:delete_card_for_ticket, on: :member) + end + resources(:ticket_levels, only: %i[index show create update destroy]) do + put(:update_order, on: :collection) + end + resources(:event_discounts, only: %i[create index update destroy]) + end + + get(:donate, on: :member) + get(:btn, on: :member) + get(:supporter_form, on: :member) + post(:custom_supporter, on: :member) + get(:dashboard, on: :member) + get(:dashboard_metrics, on: :member) + get(:payment_history, on: :member) + + post(:donate, on: :member, as: 'create_donation') + end + + resources(:recurring_donations, only: %i[edit destroy update]) do + put(:update_amount, on: :member) + end + + devise_for :users, + controllers: { + sessions: 'users/sessions', + registrations: 'users/registrations', + confirmations: 'users/confirmations' + } + devise_scope :user do + match '/sign_in' => 'users/sessions#new', via: %i[get post] + match '/signup' => 'devise/registrations#new', via: %i[get post] + post '/confirm' => 'users/confirmations#confirm', via: [:get] + match '/users/is_confirmed' => 'users/confirmations#is_confirmed', via: %i[get post] + match '/users/exists' => 'users/confirmations#exists', via: [:get] + post '/users/confirm_auth', action: :confirm_auth, controller: 'users/sessions', via: %i[get post] + end + + # Super admin + match '/admin' => 'super_admins#index', :as => 'admin', via: %i[get post] + match '/admin/search-nonprofits' => 'super_admins#search_nonprofits', via: %i[get post] + match '/admin/search-profiles' => 'super_admins#search_profiles', via: %i[get post] + match '/admin/search-fullcontact' => 'super_admins#search_fullcontact', via: %i[get post] + match '/admin/recurring-donations-without-cards' => 'super_admins#recurring_donations_without_cards', via: %i[get post] + match '/admin/export_supporters_with_rds' => 'super_admins#export_supporters_with_rds', via: %i[get post] + match '/admin/resend_user_confirmation' => 'super_admins#resend_user_confirmation', via: %i[get post] # Events match '/events' => 'events#index', via: [:get] - match '/events/:event_slug' => 'events#show', via: [:get, :post] + match '/events/:event_slug' => 'events#show', via: %i[get post] - # Nonprofits - match ':state_code/:city/:name' => 'nonprofits#show', :as => :nonprofit_location, via: [:get, :post] - match ':state_code/:city/:name/donate' => 'nonprofits#donate', :as => :nonprofit_donation, via: [:get, :post] - match ':state_code/:city/:name/button' => 'nonprofits/button#guided', via: [:get, :post] + # Nonprofits + match ':state_code/:city/:name' => 'nonprofits#show', :as => :nonprofit_location, via: %i[get post] + match ':state_code/:city/:name/donate' => 'nonprofits#donate', :as => :nonprofit_donation, via: %i[get post] + match ':state_code/:city/:name/button' => 'nonprofits/button#guided', via: %i[get post] - # Campaigns - match ':state_code/:city/:name/campaigns' => 'campaigns#index', via: [:get, :post] - match ':state_code/:city/:name/campaigns/:campaign_slug' => 'campaigns#show', via: [:get, :post] - match ':state_code/:city/:name/campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', via: [:get, :post] - match '/peer-to-peer' => 'campaigns#peer_to_peer', via: [:get, :post] + # Campaigns + match ':state_code/:city/:name/campaigns' => 'campaigns#index', via: %i[get post] + match ':state_code/:city/:name/campaigns/:campaign_slug' => 'campaigns#show', via: %i[get post] + match ':state_code/:city/:name/campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', via: %i[get post] + match '/peer-to-peer' => 'campaigns#peer_to_peer', via: %i[get post] - # Events - match ':state_code/:city/:name/events' => 'events#index', via: [:get, :post] - match ':state_code/:city/:name/events/:event_slug' => 'events#show', via: [:get, :post] - match ':state_code/:city/:name/events/:event_slug/stats' => 'events#stats', via: [:get, :post] - match ':state_code/:city/:name/events/:event_slug/tickets' => 'tickets#index', via: [:get, :post] - # get '/events' => 'events#index' + # Events + match ':state_code/:city/:name/events' => 'events#index', via: %i[get post] + match ':state_code/:city/:name/events/:event_slug' => 'events#show', via: %i[get post] + match ':state_code/:city/:name/events/:event_slug/stats' => 'events#stats', via: %i[get post] + match ':state_code/:city/:name/events/:event_slug/tickets' => 'tickets#index', via: %i[get post] + # get '/events' => 'events#index' - # Dashboard - match ':state_code/:city/:name/dashboard' => 'nonprofits#dashboard', as: :np_dashboard, via: [:get, :post] + # Dashboard + match ':state_code/:city/:name/dashboard' => 'nonprofits#dashboard', as: :np_dashboard, via: %i[get post] - # Misc - get '/pages/wp-plugin', to: redirect('/help/wordpress-plugin') #temporary, until WP plugin updated + # Misc + get '/pages/wp-plugin', to: redirect('/help/wordpress-plugin') # temporary, until WP plugin updated - # Maps - get '/maps/all-npos' => 'maps#all_npos' - get '/maps/all-supporters' => 'maps#all_supporters' - get '/maps/all-npo-supporters' => 'maps#all_npo_supporters' - get '/maps/specific-npo-supporters' => 'maps#specific_npo_supporters' + # Maps + get '/maps/all-npos' => 'maps#all_npos' + get '/maps/all-supporters' => 'maps#all_supporters' + get '/maps/all-npo-supporters' => 'maps#all_npo_supporters' + get '/maps/specific-npo-supporters' => 'maps#specific_npo_supporters' - # Mailchimp Landing - match '/mailchimp-landing' => 'nonprofits/nonprofit_keys#mailchimp_landing', via: [:get, :post] + # Mailchimp Landing + match '/mailchimp-landing' => 'nonprofits/nonprofit_keys#mailchimp_landing', via: %i[get post] # Webhooks post '/webhooks/stripe_subscription_payment' => 'webhooks#subscription_payment' post '/webhooks/stripe' => 'webhooks#stripe' get '/static/terms_and_privacy' => 'static#terms_and_privacy' - get '/static/ccs' => 'static#ccs' - - - - root :to => 'front#index' - - + get '/static/ccs' => 'static#ccs' + root to: 'front#index' end diff --git a/config/spring.rb b/config/spring.rb index c9119b40..c5933e49 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,6 +1,8 @@ -%w( +# frozen_string_literal: true + +%w[ .ruby-version .rbenv-vars tmp/restart.txt tmp/caching-dev.txt -).each { |path| Spring.watch(path) } +].each { |path| Spring.watch(path) } diff --git a/db/migrate/20170307222633_add_indexes_for_payment_and_supporter_queries.rb b/db/migrate/20170307222633_add_indexes_for_payment_and_supporter_queries.rb index 36b5ac5d..c9fc64eb 100644 --- a/db/migrate/20170307222633_add_indexes_for_payment_and_supporter_queries.rb +++ b/db/migrate/20170307222633_add_indexes_for_payment_and_supporter_queries.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexesForPaymentAndSupporterQueries < ActiveRecord::Migration def up Qx.transaction do - Qx.execute(%Q( + Qx.execute(%( CREATE INDEX IF NOT EXISTS payments_date ON payments (date); CREATE INDEX IF NOT EXISTS payments_gross_amount ON payments (gross_amount); CREATE INDEX IF NOT EXISTS payments_kind ON payments (kind); @@ -29,28 +31,28 @@ class AddIndexesForPaymentAndSupporterQueries < ActiveRecord::Migration end def down - Qx.execute(%Q( - DROP INDEX IF EXISTS payments_date; - DROP INDEX IF EXISTS payments_gross_amount; - DROP INDEX IF EXISTS payments_kind; - DROP INDEX IF EXISTS payments_towards; - DROP INDEX IF EXISTS payments_supporter_id; - DROP INDEX IF EXISTS payments_nonprofit_id; + Qx.execute(%( + DROP INDEX IF EXISTS payments_date; + DROP INDEX IF EXISTS payments_gross_amount; + DROP INDEX IF EXISTS payments_kind; + DROP INDEX IF EXISTS payments_towards; + DROP INDEX IF EXISTS payments_supporter_id; + DROP INDEX IF EXISTS payments_nonprofit_id; - DROP INDEX IF EXISTS supporters_created_at; - DROP INDEX IF EXISTS supporters_name; - DROP INDEX IF EXISTS supporters_email; - DROP INDEX IF EXISTS supporters_nonprofit_id; - DROP INDEX IF EXISTS supporters_donation_id; + DROP INDEX IF EXISTS supporters_created_at; + DROP INDEX IF EXISTS supporters_name; + DROP INDEX IF EXISTS supporters_email; + DROP INDEX IF EXISTS supporters_nonprofit_id; + DROP INDEX IF EXISTS supporters_donation_id; - DROP INDEX IF EXISTS donations_amount; - DROP INDEX IF EXISTS donations_designation; - DROP INDEX IF EXISTS donations_supporter_id; + DROP INDEX IF EXISTS donations_amount; + DROP INDEX IF EXISTS donations_designation; + DROP INDEX IF EXISTS donations_supporter_id; - DROP INDEX IF EXISTS tag_joins_supporter_id; - DROP INDEX IF EXISTS tag_joins_tag_master_id; + DROP INDEX IF EXISTS tag_joins_supporter_id; + DROP INDEX IF EXISTS tag_joins_tag_master_id; - DROP INDEX IF EXISTS custom_field_joins_custom_field_master_id; - )) + DROP INDEX IF EXISTS custom_field_joins_custom_field_master_id; + )) end end diff --git a/db/migrate/20170307223525_drop_all_cruft.rb b/db/migrate/20170307223525_drop_all_cruft.rb index 92361fc7..316d8194 100644 --- a/db/migrate/20170307223525_drop_all_cruft.rb +++ b/db/migrate/20170307223525_drop_all_cruft.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class DropAllCruft < ActiveRecord::Migration def change - Qx.execute(%Q( + Qx.execute(%( DROP FUNCTION IF EXISTS update_payment_donations_search_vectors(); DROP FUNCTION IF EXISTS supporters_insert_trigger(); DROP FUNCTION IF EXISTS update_payment_search_vectors(); @@ -22,7 +24,7 @@ class DropAllCruft < ActiveRecord::Migration end def down - Qx.execute(%Q( + Qx.execute(%( CREATE FUNCTION update_payment_donations_search_vectors() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN @@ -42,9 +44,9 @@ SELECT payments.id, concat_ws(' ' , donations.designation , donations.dedication ) AS search_blob -FROM payments +FROM payments LEFT OUTER JOIN supporters - ON payments.supporter_id=supporters.id + ON payments.supporter_id=supporters.id LEFT OUTER JOIN donations ON payments.donation_id=donations.id WHERE (payments.donation_id=NEW.id)) AS data @@ -53,7 +55,7 @@ WHERE (payments.donation_id=NEW.id)) AS data END $$; )) - Qx.execute(%Q( + Qx.execute(%( CREATE FUNCTION supporters_insert_trigger() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -63,7 +65,7 @@ CREATE FUNCTION supporters_insert_trigger() RETURNS trigger END; $$; )) - Qx.execute(%Q( + Qx.execute(%( CREATE FUNCTION update_payment_search_vectors() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN @@ -83,9 +85,9 @@ SELECT payments.id, concat_ws(' ' , donations.designation , donations.dedication ) AS search_blob -FROM payments +FROM payments LEFT OUTER JOIN supporters - ON payments.supporter_id=supporters.id + ON payments.supporter_id=supporters.id LEFT OUTER JOIN donations ON payments.donation_id=donations.id WHERE (payments.id=NEW.id)) AS data @@ -95,7 +97,7 @@ WHERE (payments.id=NEW.id)) AS data )) - Qx.execute(%Q( + Qx.execute(%( CREATE FUNCTION update_payment_supporters_search_vectors() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN @@ -115,9 +117,9 @@ SELECT payments.id, concat_ws(' ' , donations.designation , donations.dedication ) AS search_blob -FROM payments +FROM payments LEFT OUTER JOIN supporters - ON payments.supporter_id=supporters.id + ON payments.supporter_id=supporters.id LEFT OUTER JOIN donations ON payments.donation_id=donations.id WHERE (payments.supporter_id=NEW.id)) AS data @@ -126,8 +128,7 @@ WHERE (payments.supporter_id=NEW.id)) AS data END $$; )) - - Qx.execute(%Q( + Qx.execute(%( CREATE FUNCTION update_supporter_search_vectors() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN @@ -148,14 +149,14 @@ SELECT supporters.id, concat_ws(' ' , payments.kind , payments.towards ) AS search_blob -FROM supporters +FROM supporters LEFT OUTER JOIN payments - ON payments.supporter_id=supporters.id + ON payments.supporter_id=supporters.id LEFT OUTER JOIN donations - ON donations.supporter_id=supporters.id + ON donations.supporter_id=supporters.id LEFT OUTER JOIN ( SELECT string_agg(value::text, ' ') AS value, supporter_id -FROM custom_field_joins +FROM custom_field_joins GROUP BY supporter_id) AS custom_field_joins ON custom_field_joins.supporter_id=supporters.id WHERE (supporters.id=NEW.id)) AS data @@ -164,8 +165,7 @@ WHERE (supporters.id=NEW.id)) AS data END $$; )) - - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE billing_customers ( id integer NOT NULL, card_name character varying(255), @@ -177,7 +177,7 @@ CREATE TABLE billing_customers ( )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE coupons ( id integer NOT NULL, name character varying(255), @@ -189,7 +189,7 @@ CREATE TABLE coupons ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE dedications ( id integer NOT NULL, donation_id integer, @@ -199,7 +199,7 @@ CREATE TABLE dedications ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE email_drafts ( id integer NOT NULL, nonprofit_id integer, @@ -211,7 +211,7 @@ CREATE TABLE email_drafts ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE image_points ( id integer NOT NULL, image_name character varying(255), @@ -226,7 +226,7 @@ CREATE TABLE image_points ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE pg_search_documents ( id integer NOT NULL, content text, @@ -238,7 +238,7 @@ CREATE TABLE pg_search_documents ( )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE prospect_events ( id integer NOT NULL, event character varying(255), @@ -249,7 +249,7 @@ CREATE TABLE prospect_events ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE prospect_visit_params ( id integer NOT NULL, key character varying(255), @@ -258,7 +258,7 @@ CREATE TABLE prospect_visit_params ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE prospect_visits ( id integer NOT NULL, pathname text, @@ -268,7 +268,7 @@ CREATE TABLE prospect_visits ( ); )) - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE prospects ( id integer NOT NULL, ip_address character varying(255), @@ -282,8 +282,7 @@ CREATE TABLE prospect_visits ( ); )) - - Qx.execute(%Q( + Qx.execute(%( CREATE TABLE recommendations ( id integer NOT NULL, nonprofit_id integer, @@ -293,9 +292,5 @@ CREATE TABLE recommendations ( updated_at timestamp without time zone NOT NULL ); )) - - - end - end diff --git a/db/migrate/20170314193744_normalize_start_and_end_datetimes_for_events_and_campaigns.rb b/db/migrate/20170314193744_normalize_start_and_end_datetimes_for_events_and_campaigns.rb index 15227178..9b234ea2 100644 --- a/db/migrate/20170314193744_normalize_start_and_end_datetimes_for_events_and_campaigns.rb +++ b/db/migrate/20170314193744_normalize_start_and_end_datetimes_for_events_and_campaigns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NormalizeStartAndEndDatetimesForEventsAndCampaigns < ActiveRecord::Migration def up @@ -5,11 +7,11 @@ class NormalizeStartAndEndDatetimesForEventsAndCampaigns < ActiveRecord::Migrati add_column :events, :end_datetime, :datetime add_column :campaigns, :end_datetime, :datetime Qx.update(:events) - .set(%Q(start_datetime = ("date" + start_time), end_datetime = ("date" + end_time))) + .set(%(start_datetime = ("date" + start_time), end_datetime = ("date" + end_time))) .where("created_at > '2012-01-01'") .execute Qx.update(:campaigns) - .set("end_datetime = (expiration + end_time)") + .set('end_datetime = (expiration + end_time)') .where("created_at > '2012-01-01'") .execute remove_column :events, :end_time @@ -18,6 +20,7 @@ class NormalizeStartAndEndDatetimesForEventsAndCampaigns < ActiveRecord::Migrati remove_column :campaigns, :expiration remove_column :campaigns, :end_time end + def down add_column :events, :end_time, :time add_column :events, :start_time, :time @@ -25,11 +28,11 @@ class NormalizeStartAndEndDatetimesForEventsAndCampaigns < ActiveRecord::Migrati add_column :campaigns, :expiration, :date add_column :campaigns, :end_time, :time Qx.update(:events) - .set(%Q(end_time = end_datetime::time, start_time = start_datetime::time, "date" = start_datetime::date)) + .set(%(end_time = end_datetime::time, start_time = start_datetime::time, "date" = start_datetime::date)) .where("created_at > '2012-01-01'") .execute Qx.update(:campaigns) - .set("end_time = end_datetime::time, expiration = end_datetime::date") + .set('end_time = end_datetime::time, expiration = end_datetime::date') .where("created_at > '2012-01-01'") .execute remove_column :events, :start_datetime diff --git a/db/migrate/20170322203228_add_donation_campaign_id_index.rb b/db/migrate/20170322203228_add_donation_campaign_id_index.rb index 8fa5a6d8..d797be9a 100644 --- a/db/migrate/20170322203228_add_donation_campaign_id_index.rb +++ b/db/migrate/20170322203228_add_donation_campaign_id_index.rb @@ -1,15 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddDonationCampaignIdIndex < ActiveRecord::Migration def up - Qx.execute(%Q( + Qx.execute(%( CREATE INDEX IF NOT EXISTS donations_campaign_id ON donations (campaign_id); CREATE INDEX IF NOT EXISTS donations_event_id ON donations (event_id); )) end + def down - Qx.execute(%Q( - DROP INDEX IF EXISTS donations_campaign_id; - DROP INDEX IF EXISTS donations_event_id; - )) + Qx.execute(%( + DROP INDEX IF EXISTS donations_campaign_id; + DROP INDEX IF EXISTS donations_event_id; + )) end end diff --git a/db/migrate/20170805180556_add_the_tag_joins_backup_table.rb b/db/migrate/20170805180556_add_the_tag_joins_backup_table.rb index a77dfa34..c694e906 100644 --- a/db/migrate/20170805180556_add_the_tag_joins_backup_table.rb +++ b/db/migrate/20170805180556_add_the_tag_joins_backup_table.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddTheTagJoinsBackupTable < ActiveRecord::Migration def up diff --git a/db/migrate/20170805180557_add_index_for_tag_joins_and_add_constraint.rb b/db/migrate/20170805180557_add_index_for_tag_joins_and_add_constraint.rb index fb22e96c..87b86365 100644 --- a/db/migrate/20170805180557_add_index_for_tag_joins_and_add_constraint.rb +++ b/db/migrate/20170805180557_add_index_for_tag_joins_and_add_constraint.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexForTagJoinsAndAddConstraint < ActiveRecord::Migration def up ids = DeleteTagJoins.find_multiple_tag_joins DeleteTagJoins.copy_and_delete(ids) - add_index :tag_joins, [:tag_master_id, :supporter_id], :unique => true, :name => 'tag_join_supporter_unique_idx' + add_index :tag_joins, %i[tag_master_id supporter_id], unique: true, name: 'tag_join_supporter_unique_idx' end def down - remove_index(:tag_joins, :name => 'tag_join_supporter_unique_idx') + remove_index(:tag_joins, name: 'tag_join_supporter_unique_idx') DeleteTagJoins.revert end end diff --git a/db/migrate/20170805180558_add_custom_field_joins_backup_table.rb b/db/migrate/20170805180558_add_custom_field_joins_backup_table.rb index db8187a9..eb4f70a6 100644 --- a/db/migrate/20170805180558_add_custom_field_joins_backup_table.rb +++ b/db/migrate/20170805180558_add_custom_field_joins_backup_table.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddCustomFieldJoinsBackupTable < ActiveRecord::Migration def change diff --git a/db/migrate/20170805180559_add_index_for_custom_field_join_and_supporters.rb b/db/migrate/20170805180559_add_index_for_custom_field_join_and_supporters.rb index 7da226d6..052fe66f 100644 --- a/db/migrate/20170805180559_add_index_for_custom_field_join_and_supporters.rb +++ b/db/migrate/20170805180559_add_index_for_custom_field_join_and_supporters.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexForCustomFieldJoinAndSupporters < ActiveRecord::Migration def up ids = DeleteCustomFieldJoins.find_multiple_custom_field_joins DeleteCustomFieldJoins.copy_and_delete(ids) - add_index :custom_field_joins, [:custom_field_master_id, :supporter_id], :unique => true, :name => 'custom_field_join_supporter_unique_idx' + add_index :custom_field_joins, %i[custom_field_master_id supporter_id], unique: true, name: 'custom_field_join_supporter_unique_idx' end def down - remove_index(:custom_field_joins, :name => 'custom_field_join_supporter_unique_idx') + remove_index(:custom_field_joins, name: 'custom_field_join_supporter_unique_idx') DeleteCustomFieldJoins.revert end end diff --git a/db/migrate/20170808180559_add_inactive_to_card.rb b/db/migrate/20170808180559_add_inactive_to_card.rb index 6b18d4cf..7721eaae 100644 --- a/db/migrate/20170808180559_add_inactive_to_card.rb +++ b/db/migrate/20170808180559_add_inactive_to_card.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddInactiveToCard < ActiveRecord::Migration class Card < ActiveRecord::Base @@ -6,8 +8,8 @@ class AddInactiveToCard < ActiveRecord::Migration def change add_column :cards, :inactive, :boolean - add_index :cards, [:id, :holder_type, :holder_id, :inactive] # add index for getting active_card + add_index :cards, %i[id holder_type holder_id inactive] # add index for getting active_card Card.reset_column_information - Card.update_all(:inactive => false) + Card.update_all(inactive: false) end end diff --git a/db/migrate/20170818201127_create_exports.rb b/db/migrate/20170818201127_create_exports.rb index c1b0e4d1..1524e10f 100644 --- a/db/migrate/20170818201127_create_exports.rb +++ b/db/migrate/20170818201127_create_exports.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CreateExports < ActiveRecord::Migration def change diff --git a/db/migrate/20171002160808_create_miscellaneous_np_infos.rb b/db/migrate/20171002160808_create_miscellaneous_np_infos.rb index f157816a..2aba8d26 100644 --- a/db/migrate/20171002160808_create_miscellaneous_np_infos.rb +++ b/db/migrate/20171002160808_create_miscellaneous_np_infos.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CreateMiscellaneousNpInfos < ActiveRecord::Migration def change diff --git a/db/migrate/20171002164402_add_currency_to_nonprofit.rb b/db/migrate/20171002164402_add_currency_to_nonprofit.rb index d03545a5..f275aaf6 100644 --- a/db/migrate/20171002164402_add_currency_to_nonprofit.rb +++ b/db/migrate/20171002164402_add_currency_to_nonprofit.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddCurrencyToNonprofit < ActiveRecord::Migration def change diff --git a/db/migrate/20171004203633_add_change_amount_message_to_miscellaneous_np_infos.rb b/db/migrate/20171004203633_add_change_amount_message_to_miscellaneous_np_infos.rb index 67a7ffa4..5f276a2a 100644 --- a/db/migrate/20171004203633_add_change_amount_message_to_miscellaneous_np_infos.rb +++ b/db/migrate/20171004203633_add_change_amount_message_to_miscellaneous_np_infos.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddChangeAmountMessageToMiscellaneousNpInfos < ActiveRecord::Migration def change diff --git a/db/migrate/20171010204437_add_first_and_last_name_to_supporter.rb b/db/migrate/20171010204437_add_first_and_last_name_to_supporter.rb index 7ec499cb..66c239f8 100644 --- a/db/migrate/20171010204437_add_first_and_last_name_to_supporter.rb +++ b/db/migrate/20171010204437_add_first_and_last_name_to_supporter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddFirstAndLastNameToSupporter < ActiveRecord::Migration def change diff --git a/db/migrate/20171016181942_add_tracking.rb b/db/migrate/20171016181942_add_tracking.rb index bab82503..fa1b68c3 100644 --- a/db/migrate/20171016181942_add_tracking.rb +++ b/db/migrate/20171016181942_add_tracking.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddTracking < ActiveRecord::Migration def change diff --git a/db/migrate/20171024133806_add_queued_for_import_at_to_donation.rb b/db/migrate/20171024133806_add_queued_for_import_at_to_donation.rb index e0162a77..fc969eab 100644 --- a/db/migrate/20171024133806_add_queued_for_import_at_to_donation.rb +++ b/db/migrate/20171024133806_add_queued_for_import_at_to_donation.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddQueuedForImportAtToDonation < ActiveRecord::Migration def change diff --git a/db/migrate/20171026102139_add_direct_debit_detail.rb b/db/migrate/20171026102139_add_direct_debit_detail.rb index 634dd7ee..d9bcdde7 100644 --- a/db/migrate/20171026102139_add_direct_debit_detail.rb +++ b/db/migrate/20171026102139_add_direct_debit_detail.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddDirectDebitDetail < ActiveRecord::Migration def change @@ -11,9 +13,9 @@ class AddDirectDebitDetail < ActiveRecord::Migration end add_column :donations, - :direct_debit_detail_id, - :integer, - index: true, - references: :direct_debit_details + :direct_debit_detail_id, + :integer, + index: true, + references: :direct_debit_details end end diff --git a/db/migrate/20171129215957_add_utm_content_to_trackings.rb b/db/migrate/20171129215957_add_utm_content_to_trackings.rb index 3831186c..5047fb6c 100644 --- a/db/migrate/20171129215957_add_utm_content_to_trackings.rb +++ b/db/migrate/20171129215957_add_utm_content_to_trackings.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddUtmContentToTrackings < ActiveRecord::Migration def change diff --git a/db/migrate/20171130182254_add_locale_to_supporters.rb b/db/migrate/20171130182254_add_locale_to_supporters.rb index 1d0c8c6e..8f31d9dc 100644 --- a/db/migrate/20171130182254_add_locale_to_supporters.rb +++ b/db/migrate/20171130182254_add_locale_to_supporters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddLocaleToSupporters < ActiveRecord::Migration def change diff --git a/db/migrate/20171130193955_add_payment_provider_to_donations.rb b/db/migrate/20171130193955_add_payment_provider_to_donations.rb index f6d335f5..a4c399dc 100644 --- a/db/migrate/20171130193955_add_payment_provider_to_donations.rb +++ b/db/migrate/20171130193955_add_payment_provider_to_donations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddPaymentProviderToDonations < ActiveRecord::Migration def change diff --git a/db/migrate/20171206113317_add_direct_debit_detail_to_charges.rb b/db/migrate/20171206113317_add_direct_debit_detail_to_charges.rb index 6734e2dd..2b4dce85 100644 --- a/db/migrate/20171206113317_add_direct_debit_detail_to_charges.rb +++ b/db/migrate/20171206113317_add_direct_debit_detail_to_charges.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddDirectDebitDetailToCharges < ActiveRecord::Migration def change diff --git a/db/migrate/20171207114229_add_external_identifier_to_campaign.rb b/db/migrate/20171207114229_add_external_identifier_to_campaign.rb index 9aedb86a..75f1f95b 100644 --- a/db/migrate/20171207114229_add_external_identifier_to_campaign.rb +++ b/db/migrate/20171207114229_add_external_identifier_to_campaign.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddExternalIdentifierToCampaign < ActiveRecord::Migration def change diff --git a/db/migrate/20171207191435_add_index_to_campaign_gifts.rb b/db/migrate/20171207191435_add_index_to_campaign_gifts.rb index e834f105..21034bdf 100644 --- a/db/migrate/20171207191435_add_index_to_campaign_gifts.rb +++ b/db/migrate/20171207191435_add_index_to_campaign_gifts.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexToCampaignGifts < ActiveRecord::Migration def change diff --git a/db/migrate/20171207191712_add_index_to_activities.rb b/db/migrate/20171207191712_add_index_to_activities.rb index 14ef08a2..d851dbb8 100644 --- a/db/migrate/20171207191712_add_index_to_activities.rb +++ b/db/migrate/20171207191712_add_index_to_activities.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexToActivities < ActiveRecord::Migration def change diff --git a/db/migrate/20171207200746_modify_supporters_name_index.rb b/db/migrate/20171207200746_modify_supporters_name_index.rb index 16c5d2eb..a4c920d7 100644 --- a/db/migrate/20171207200746_modify_supporters_name_index.rb +++ b/db/migrate/20171207200746_modify_supporters_name_index.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ModifySupportersNameIndex < ActiveRecord::Migration def up diff --git a/db/migrate/20171207200950_add_supporters_name_index.rb b/db/migrate/20171207200950_add_supporters_name_index.rb index 150eca64..0ac0d94f 100644 --- a/db/migrate/20171207200950_add_supporters_name_index.rb +++ b/db/migrate/20171207200950_add_supporters_name_index.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddSupportersNameIndex < ActiveRecord::Migration def change diff --git a/db/migrate/20171207210431_add_charges_payment_id_index.rb b/db/migrate/20171207210431_add_charges_payment_id_index.rb index 8d41dfcf..4d612e02 100644 --- a/db/migrate/20171207210431_add_charges_payment_id_index.rb +++ b/db/migrate/20171207210431_add_charges_payment_id_index.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddChargesPaymentIdIndex < ActiveRecord::Migration def change diff --git a/db/migrate/20180106024119_add_indexes_for_supporter_deleted_and_import.rb b/db/migrate/20180106024119_add_indexes_for_supporter_deleted_and_import.rb index 98e4263c..b72d9a6a 100644 --- a/db/migrate/20180106024119_add_indexes_for_supporter_deleted_and_import.rb +++ b/db/migrate/20180106024119_add_indexes_for_supporter_deleted_and_import.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddIndexesForSupporterDeletedAndImport < ActiveRecord::Migration def change diff --git a/db/migrate/20180119215653_create_payment_imports.rb b/db/migrate/20180119215653_create_payment_imports.rb index c80e8bf5..113ca313 100644 --- a/db/migrate/20180119215653_create_payment_imports.rb +++ b/db/migrate/20180119215653_create_payment_imports.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CreatePaymentImports < ActiveRecord::Migration def change diff --git a/db/migrate/20180119215913_create_donations_payment_imports_join_table.rb b/db/migrate/20180119215913_create_donations_payment_imports_join_table.rb index 82b8db95..7cba7c3e 100644 --- a/db/migrate/20180119215913_create_donations_payment_imports_join_table.rb +++ b/db/migrate/20180119215913_create_donations_payment_imports_join_table.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CreateDonationsPaymentImportsJoinTable < ActiveRecord::Migration def change diff --git a/db/migrate/20180202181929_remove_unused_metadata.rb b/db/migrate/20180202181929_remove_unused_metadata.rb index 182f0642..dd8e4e2f 100644 --- a/db/migrate/20180202181929_remove_unused_metadata.rb +++ b/db/migrate/20180202181929_remove_unused_metadata.rb @@ -1,48 +1,48 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RemoveUnusedMetadata < ActiveRecord::Migration - - TABLES = [ - :campaign_gift_options, - :campaign_gifts, - :campaigns, - :cards, - :charges, - :custom_field_masters, - :custom_field_joins, - :disputes, - :donations, - :events, - :imports, - :nonprofits, - :offsite_payments, - :payments, - :payment_payouts, - :payouts, - :profiles, - :recurring_donations, - :refunds, - :roles, - :supporter_emails, - :supporter_notes, - :supporters, - :tag_joins, - :tag_masters, - :ticket_levels, - :tickets, - :users - ] - FIELDS= [:id, :metadata ] + TABLES = %i[ + campaign_gift_options + campaign_gifts + campaigns + cards + charges + custom_field_masters + custom_field_joins + disputes + donations + events + imports + nonprofits + offsite_payments + payments + payment_payouts + payouts + profiles + recurring_donations + refunds + roles + supporter_emails + supporter_notes + supporters + tag_joins + tag_masters + ticket_levels + tickets + users + ].freeze + FIELDS = %i[id metadata].freeze def up - TABLES.each{|table| + TABLES.each do |table| remove_column table, :metadata - } + end end def down - TABLES.each{|table| + TABLES.each do |table| add_column table, :metadata, :text - } - + end end end diff --git a/db/migrate/20180213191755_remove_recurring_donation_event_id.rb b/db/migrate/20180213191755_remove_recurring_donation_event_id.rb index f1c207a3..b4cb776e 100644 --- a/db/migrate/20180213191755_remove_recurring_donation_event_id.rb +++ b/db/migrate/20180213191755_remove_recurring_donation_event_id.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RemoveRecurringDonationEventId < ActiveRecord::Migration def change @@ -5,5 +7,4 @@ class RemoveRecurringDonationEventId < ActiveRecord::Migration t.remove :event_id end end - end diff --git a/db/migrate/20180214124311_create_source_tokens.rb b/db/migrate/20180214124311_create_source_tokens.rb index f4d0fae3..f200799f 100644 --- a/db/migrate/20180214124311_create_source_tokens.rb +++ b/db/migrate/20180214124311_create_source_tokens.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CreateSourceTokens < ActiveRecord::Migration def change create_table :source_tokens, id: false do |t| - t.column :token, 'uuid', primary_key: true, null:false + t.column :token, 'uuid', primary_key: true, null: false t.datetime :expiration - t.references :tokenizable, :polymorphic => true + t.references :tokenizable, polymorphic: true t.references :event t.integer :max_uses, default: 1 t.integer :total_uses, default: 0 t.timestamps end - add_index :source_tokens, :token, :unique => true + add_index :source_tokens, :token, unique: true add_index :source_tokens, :expiration - add_index :source_tokens, [:tokenizable_id, :tokenizable_type] - + add_index :source_tokens, %i[tokenizable_id tokenizable_type] end end diff --git a/db/migrate/20180215124311_add_card_token_to_ticket.rb b/db/migrate/20180215124311_add_card_token_to_ticket.rb index 6a86b920..e74e40b5 100644 --- a/db/migrate/20180215124311_add_card_token_to_ticket.rb +++ b/db/migrate/20180215124311_add_card_token_to_ticket.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AddCardTokenToTicket < ActiveRecord::Migration def up diff --git a/db/migrate/20180216064311_add_indexes_to_supporter_notes.rb b/db/migrate/20180216064311_add_indexes_to_supporter_notes.rb index cc7cb1c1..e453b989 100644 --- a/db/migrate/20180216064311_add_indexes_to_supporter_notes.rb +++ b/db/migrate/20180216064311_add_indexes_to_supporter_notes.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + class AddIndexesToSupporterNotes < ActiveRecord::Migration def change - add_index :supporter_notes, :supporter_id, :order => {:supporter_id => :asc} + add_index :supporter_notes, :supporter_id, order: { supporter_id: :asc } end end diff --git a/db/migrate/20180216124311_change_ddd_supporter_to_holder.rb b/db/migrate/20180216124311_change_ddd_supporter_to_holder.rb index bb26555b..56f4cd75 100644 --- a/db/migrate/20180216124311_change_ddd_supporter_to_holder.rb +++ b/db/migrate/20180216124311_change_ddd_supporter_to_holder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ChangeDddSupporterToHolder < ActiveRecord::Migration def change diff --git a/db/migrate/20180217124311_remove_articles.rb b/db/migrate/20180217124311_remove_articles.rb index cfe1f1da..9aae090c 100644 --- a/db/migrate/20180217124311_remove_articles.rb +++ b/db/migrate/20180217124311_remove_articles.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class RemoveArticles < ActiveRecord::Migration def up drop_table :articles end - def down - end + def down; end end diff --git a/db/migrate/20180608205049_add_index_to_supporter_id_on_tickets.rb b/db/migrate/20180608205049_add_index_to_supporter_id_on_tickets.rb index d2dc5bf2..6dc66844 100644 --- a/db/migrate/20180608205049_add_index_to_supporter_id_on_tickets.rb +++ b/db/migrate/20180608205049_add_index_to_supporter_id_on_tickets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexToSupporterIdOnTickets < ActiveRecord::Migration def change add_index :tickets, :supporter_id diff --git a/db/migrate/20180608212658_add_index_to_event_id_on_donations_and_events.rb b/db/migrate/20180608212658_add_index_to_event_id_on_donations_and_events.rb index c86222f9..6bd038e5 100644 --- a/db/migrate/20180608212658_add_index_to_event_id_on_donations_and_events.rb +++ b/db/migrate/20180608212658_add_index_to_event_id_on_donations_and_events.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexToEventIdOnDonationsAndEvents < ActiveRecord::Migration def change add_index :tickets, :event_id diff --git a/db/migrate/20180703165401_add_parent_campaign_id_to_campaigns.rb b/db/migrate/20180703165401_add_parent_campaign_id_to_campaigns.rb index bcb567ec..725d90a2 100644 --- a/db/migrate/20180703165401_add_parent_campaign_id_to_campaigns.rb +++ b/db/migrate/20180703165401_add_parent_campaign_id_to_campaigns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddParentCampaignIdToCampaigns < ActiveRecord::Migration def change add_column :campaigns, :parent_campaign_id, :integer diff --git a/db/migrate/20180703165402_add_reason_for_supporting_to_campaigns.rb b/db/migrate/20180703165402_add_reason_for_supporting_to_campaigns.rb index 2f6791ca..2d447482 100644 --- a/db/migrate/20180703165402_add_reason_for_supporting_to_campaigns.rb +++ b/db/migrate/20180703165402_add_reason_for_supporting_to_campaigns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddReasonForSupportingToCampaigns < ActiveRecord::Migration def change add_column :campaigns, :reason_for_supporting, :text diff --git a/db/migrate/20180703165404_add_default_reason_for_supporting_to_campaigns.rb b/db/migrate/20180703165404_add_default_reason_for_supporting_to_campaigns.rb index 521ade97..8cc3ddeb 100644 --- a/db/migrate/20180703165404_add_default_reason_for_supporting_to_campaigns.rb +++ b/db/migrate/20180703165404_add_default_reason_for_supporting_to_campaigns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddDefaultReasonForSupportingToCampaigns < ActiveRecord::Migration def change add_column :campaigns, :default_reason_for_supporting, :text diff --git a/db/migrate/20180703165405_add_banner_image_to_campaigns.rb b/db/migrate/20180703165405_add_banner_image_to_campaigns.rb index 8be6b2a9..9bedf1fd 100644 --- a/db/migrate/20180703165405_add_banner_image_to_campaigns.rb +++ b/db/migrate/20180703165405_add_banner_image_to_campaigns.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddBannerImageToCampaigns < ActiveRecord::Migration def change add_column :campaigns, :banner_image, :string diff --git a/db/migrate/20180713213748_add_charge_id_indexes.rb b/db/migrate/20180713213748_add_charge_id_indexes.rb index 52d50a5e..258f1646 100644 --- a/db/migrate/20180713213748_add_charge_id_indexes.rb +++ b/db/migrate/20180713213748_add_charge_id_indexes.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + class AddChargeIdIndexes < ActiveRecord::Migration def change add_index :refunds, :charge_id end - end diff --git a/db/migrate/20180713215825_add_payment_id_to_tickets.rb b/db/migrate/20180713215825_add_payment_id_to_tickets.rb index bbfb275c..dfaf0041 100644 --- a/db/migrate/20180713215825_add_payment_id_to_tickets.rb +++ b/db/migrate/20180713215825_add_payment_id_to_tickets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddPaymentIdToTickets < ActiveRecord::Migration def change add_index :tickets, :payment_id diff --git a/db/migrate/20180713220028_add_indexes_to_refunds.rb b/db/migrate/20180713220028_add_indexes_to_refunds.rb index f618006b..6f215d02 100644 --- a/db/migrate/20180713220028_add_indexes_to_refunds.rb +++ b/db/migrate/20180713220028_add_indexes_to_refunds.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexesToRefunds < ActiveRecord::Migration def change add_index :refunds, :payment_id diff --git a/db/migrate/20181002160627_correct_dedications.rb b/db/migrate/20181002160627_correct_dedications.rb index 40657773..a590b189 100644 --- a/db/migrate/20181002160627_correct_dedications.rb +++ b/db/migrate/20181002160627_correct_dedications.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + class CorrectDedications < ActiveRecord::Migration def up - execute <<-SQL - create or replace function is_valid_json(p_json text) - returns boolean -as -$$ -begin - return (p_json::json is not null); -exception - when others then - return false; -end; -$$ -language plpgsql -immutable; + execute <<~SQL + create or replace function is_valid_json(p_json text) + returns boolean + as + $$ + begin + return (p_json::json is not null); + exception + when others then + return false; + end; + $$ + language plpgsql + immutable; SQL dedications = MaintainDedications.retrieve_non_json_dedications @@ -24,7 +26,5 @@ immutable; MaintainDedications.add_honor_to_any_json_dedications_without_type(dedications) end - def down - end + def down; end end - diff --git a/db/migrate/20181003212559_correct_dedication_contacts.rb b/db/migrate/20181003212559_correct_dedication_contacts.rb index 9631d9ba..a61a68ff 100644 --- a/db/migrate/20181003212559_correct_dedication_contacts.rb +++ b/db/migrate/20181003212559_correct_dedication_contacts.rb @@ -1,33 +1,36 @@ +# frozen_string_literal: true + class CorrectDedicationContacts < ActiveRecord::Migration def up json_dedications = Qx.select('id', 'dedication').from(:donations) - .where("dedication IS NOT NULL AND dedication != ''") - .and_where("is_valid_json(dedication)").ex - parsed_dedications = json_dedications.map{|i| {id: i['id'], dedication: JSON.parse(i['dedication'])}} - with_contact_to_correct = parsed_dedications.select {|i| !i[:dedication]['contact'].blank? && i[:dedication]['contact'].is_a?(String)} - really_icky_dedications, easy_to_split_strings = with_contact_to_correct.partition{|i| i[:dedication]['contact'].split(" - ").count > 3} + .where("dedication IS NOT NULL AND dedication != ''") + .and_where('is_valid_json(dedication)').ex + parsed_dedications = json_dedications.map { |i| { id: i['id'], dedication: JSON.parse(i['dedication']) } } + with_contact_to_correct = parsed_dedications.select { |i| !i[:dedication]['contact'].blank? && i[:dedication]['contact'].is_a?(String) } + really_icky_dedications, easy_to_split_strings = with_contact_to_correct.partition { |i| i[:dedication]['contact'].split(' - ').count > 3 } - easy_to_split_strings.map do |i| - split_contact = i[:dedication]['contact'].split(' - ') - i[:dedication]['contact'] = { - email: split_contact[0], - phone:split_contact[1], - address: split_contact[2], - } - puts i - i - end.each_with_index do |i, index| - unless (i[:id]) - raise Error("Item at index #{index} is invalid. Object:#{i}") - end - Qx.update(:donations).where("id = $id", id:i[:id]).set(dedication: JSON.generate(i[:dedication])).ex - end + easy_to_split_strings.map do |i| + split_contact = i[:dedication]['contact'].split(' - ') + i[:dedication]['contact'] = { + email: split_contact[0], + phone: split_contact[1], + address: split_contact[2] + } + puts i + i + end.each_with_index do |i, index| + unless i[:id] + raise Error("Item at index #{index} is invalid. Object:#{i}") + end + + Qx.update(:donations).where('id = $id', id: i[:id]).set(dedication: JSON.generate(i[:dedication])).ex + end puts "Corrected #{easy_to_split_strings.count} records." - puts "" - puts "" - puts "You must manually fix the following dedications: " + puts '' + puts '' + puts 'You must manually fix the following dedications: ' really_icky_dedications.each do |i| puts i end @@ -35,18 +38,18 @@ class CorrectDedicationContacts < ActiveRecord::Migration def down json_dedications = Qx.select('id', 'dedication').from(:donations) - .where("dedication IS NOT NULL AND dedication != ''") - .and_where("is_valid_json(dedication)").ex + .where("dedication IS NOT NULL AND dedication != ''") + .and_where('is_valid_json(dedication)').ex - parsed_dedications = json_dedications.map{|i| {'id' => i['id'], 'dedication' => JSON.parse(i['dedication'])}} + parsed_dedications = json_dedications.map { |i| { 'id' => i['id'], 'dedication' => JSON.parse(i['dedication']) } } - with_contact_to_correct = parsed_dedications.select {|i| i['dedication']['contact'].is_a?(Hash)} + with_contact_to_correct = parsed_dedications.select { |i| i['dedication']['contact'].is_a?(Hash) } puts "#{with_contact_to_correct.count} to revert" with_contact_to_correct.each do |i| contact_string = "#{i['dedication']['contact']['email']} - #{i['dedication']['contact']['phone']} - #{i['dedication']['contact']['address']}" i['dedication']['contact'] = contact_string - Qx.update(:donations).where("id = $id", id:i['id']).set(dedication: JSON.generate(i['dedication'])).ex + Qx.update(:donations).where('id = $id', id: i['id']).set(dedication: JSON.generate(i['dedication'])).ex end end end diff --git a/db/migrate/20181120182105_add_index_parent_campaign_id_to_campaign.rb b/db/migrate/20181120182105_add_index_parent_campaign_id_to_campaign.rb index 81353b42..7d620860 100644 --- a/db/migrate/20181120182105_add_index_parent_campaign_id_to_campaign.rb +++ b/db/migrate/20181120182105_add_index_parent_campaign_id_to_campaign.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexParentCampaignIdToCampaign < ActiveRecord::Migration def change add_index :campaigns, :parent_campaign_id diff --git a/db/migrate/20181128221143_add_indexes_to_recurring_donations.rb b/db/migrate/20181128221143_add_indexes_to_recurring_donations.rb index 9bdb1c5f..7fec2af3 100644 --- a/db/migrate/20181128221143_add_indexes_to_recurring_donations.rb +++ b/db/migrate/20181128221143_add_indexes_to_recurring_donations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexesToRecurringDonations < ActiveRecord::Migration def change add_index :recurring_donations, :donation_id diff --git a/db/migrate/20181129205652_add_donation_id_index_to_campaign_gifts.rb b/db/migrate/20181129205652_add_donation_id_index_to_campaign_gifts.rb index 8ead22c7..eb79be63 100644 --- a/db/migrate/20181129205652_add_donation_id_index_to_campaign_gifts.rb +++ b/db/migrate/20181129205652_add_donation_id_index_to_campaign_gifts.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddDonationIdIndexToCampaignGifts < ActiveRecord::Migration def change add_index :campaign_gifts, :donation_id diff --git a/db/migrate/20181129224030_add_index_to_payments_created_at.rb b/db/migrate/20181129224030_add_index_to_payments_created_at.rb index b1a6877c..a915cbca 100644 --- a/db/migrate/20181129224030_add_index_to_payments_created_at.rb +++ b/db/migrate/20181129224030_add_index_to_payments_created_at.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddIndexToPaymentsCreatedAt < ActiveRecord::Migration def change add_index :payments, :created_at diff --git a/db/seeds.rb b/db/seeds.rb index 0855c107..8ce782cc 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later bp = BillingPlan.new -bp.name = "Default billing plan" +bp.name = 'Default billing plan' bp.amount = 0 bp.percentage_fee = 0 -bp.save! \ No newline at end of file +bp.save! diff --git a/gems/grape_devise/Gemfile b/gems/grape_devise/Gemfile index bd48deef..1a91d437 100644 --- a/gems/grape_devise/Gemfile +++ b/gems/grape_devise/Gemfile @@ -1,4 +1,6 @@ -source "https://rubygems.org" +# frozen_string_literal: true + +source 'https://rubygems.org' # Declare your gem's dependencies in grape_devise.gemspec. # Bundler will treat runtime dependencies like base dependencies, and diff --git a/gems/grape_devise/Rakefile b/gems/grape_devise/Rakefile index c03dcec3..07595d91 100644 --- a/gems/grape_devise/Rakefile +++ b/gems/grape_devise/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + begin require 'bundler/setup' rescue LoadError @@ -18,8 +20,6 @@ require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) - Bundler::GemHelper.install_tasks - task default: :spec diff --git a/gems/grape_devise/grape_devise.gemspec b/gems/grape_devise/grape_devise.gemspec index 285e4bca..6cf5fa2f 100644 --- a/gems/grape_devise/grape_devise.gemspec +++ b/gems/grape_devise/grape_devise.gemspec @@ -1,32 +1,34 @@ -$:.push File.expand_path("../lib", __FILE__) +# frozen_string_literal: true + +$LOAD_PATH.push File.expand_path('lib', __dir__) # Maintain your gem's version: -require "grape_devise/version" +require 'grape_devise/version' # Describe your gem and declare its dependencies: Gem::Specification.new do |s| - s.name = "grape_devise" + s.name = 'grape_devise' s.version = GrapeDevise::VERSION - s.authors = ["Justin McCormick"] - s.email = ["me@justinmccormick.com"] - s.homepage = "http://github.com/justinm/grape_devise" - s.summary = "Adds support for devise in grape applications" - s.description = "This gem provides access to devise helpers inside of " - "Grape applications." + s.authors = ['Justin McCormick'] + s.email = ['me@justinmccormick.com'] + s.homepage = 'http://github.com/justinm/grape_devise' + s.summary = 'Adds support for devise in grape applications' + s.description = 'This gem provides access to devise helpers inside of ' + 'Grape applications.' - s.licenses = [ 'MIT' ] + s.licenses = ['MIT'] - s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE ", "Rakefile", "README.rdoc"] - s.test_files = Dir["test/**/*"] + s.files = Dir['{app,config,db,lib}/**/*', 'MIT-LICENSE ', 'Rakefile', 'README.rdoc'] + s.test_files = Dir['test/**/*'] - s.add_development_dependency "rspec", "~> 2.99.0" - s.add_development_dependency "rspec-rails", "~> 2.99.0" - s.add_development_dependency "capybara", "~> 2.4.1" - s.add_development_dependency "factory_girl", "~> 4.4.0" - s.add_development_dependency "activerecord-nulldb-adapter", "~> 0.3.1" - s.add_development_dependency "sqlite3" + s.add_development_dependency 'activerecord-nulldb-adapter', '~> 0.3.1' + s.add_development_dependency 'capybara', '~> 2.4.1' + s.add_development_dependency 'factory_girl', '~> 4.4.0' + s.add_development_dependency 'rspec', '~> 2.99.0' + s.add_development_dependency 'rspec-rails', '~> 2.99.0' + s.add_development_dependency 'sqlite3' - s.add_dependency "devise", ">= 2.2.8", "< 5" - s.add_dependency "grape", "> 0.7" - s.add_dependency "rails", "> 3.2", "< 6" + s.add_dependency 'devise', '>= 2.2.8', '< 5' + s.add_dependency 'grape', '> 0.7' + s.add_dependency 'rails', '> 3.2', '< 6' end diff --git a/gems/grape_devise/lib/grape_devise.rb b/gems/grape_devise/lib/grape_devise.rb index e6e9c268..533cc787 100644 --- a/gems/grape_devise/lib/grape_devise.rb +++ b/gems/grape_devise/lib/grape_devise.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + module GrapeDevise end -require "devise" -require "grape" -require "grape_devise/api" +require 'devise' +require 'grape' +require 'grape_devise/api' Devise.helpers << GrapeDevise::API Grape::Endpoint.send :include, GrapeDevise::API diff --git a/gems/grape_devise/lib/grape_devise/api.rb b/gems/grape_devise/lib/grape_devise/api.rb index 9658cda8..771d69f7 100644 --- a/gems/grape_devise/lib/grape_devise/api.rb +++ b/gems/grape_devise/lib/grape_devise/api.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + require 'devise' module GrapeDevise::API extend ActiveSupport::Concern include Devise::Controllers::SignInOut - - def self.define_helpers mapping + + def self.define_helpers(mapping) mapping = mapping.name.to_s class_eval <<-METHODS, __FILE__, __LINE__ + 1 @@ -33,5 +35,4 @@ module GrapeDevise::API end METHODS end - end diff --git a/gems/grape_devise/lib/grape_devise/version.rb b/gems/grape_devise/lib/grape_devise/version.rb index 199dff0a..0932866c 100644 --- a/gems/grape_devise/lib/grape_devise/version.rb +++ b/gems/grape_devise/lib/grape_devise/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module GrapeDevise - VERSION = "0.1.1" + VERSION = '0.1.1' end diff --git a/gems/grape_devise/spec/dummy/Rakefile b/gems/grape_devise/spec/dummy/Rakefile index eb4e20b0..5df4030a 100644 --- a/gems/grape_devise/spec/dummy/Rakefile +++ b/gems/grape_devise/spec/dummy/Rakefile @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # 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 File.expand_path('../config/application', __FILE__) +require File.expand_path('config/application', __dir__) require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) diff --git a/gems/grape_devise/spec/dummy/app/api/api.rb b/gems/grape_devise/spec/dummy/app/api/api.rb index e5e2cc4e..b341fc5d 100644 --- a/gems/grape_devise/spec/dummy/app/api/api.rb +++ b/gems/grape_devise/spec/dummy/app/api/api.rb @@ -1,18 +1,20 @@ -require "grape_devise" +# frozen_string_literal: true + +require 'grape_devise' class API < Grape::API format :json - get "me" do + get 'me' do authenticate_user! current_user end - get "authorized" do + get 'authorized' do user_signed_in? end - post "signin" do + post 'signin' do authenticate_user! end -end \ No newline at end of file +end diff --git a/gems/grape_devise/spec/dummy/app/controllers/application_controller.rb b/gems/grape_devise/spec/dummy/app/controllers/application_controller.rb index d83690e1..1ff0944d 100644 --- a/gems/grape_devise/spec/dummy/app/controllers/application_controller.rb +++ b/gems/grape_devise/spec/dummy/app/controllers/application_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. diff --git a/gems/grape_devise/spec/dummy/app/helpers/application_helper.rb b/gems/grape_devise/spec/dummy/app/helpers/application_helper.rb index de6be794..15b06f0f 100644 --- a/gems/grape_devise/spec/dummy/app/helpers/application_helper.rb +++ b/gems/grape_devise/spec/dummy/app/helpers/application_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ApplicationHelper end diff --git a/gems/grape_devise/spec/dummy/app/models/user.rb b/gems/grape_devise/spec/dummy/app/models/user.rb index a103d300..e6a02e67 100644 --- a/gems/grape_devise/spec/dummy/app/models/user.rb +++ b/gems/grape_devise/spec/dummy/app/models/user.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable diff --git a/gems/grape_devise/spec/dummy/bin/bundle b/gems/grape_devise/spec/dummy/bin/bundle index 66e9889e..2dbb7176 100755 --- a/gems/grape_devise/spec/dummy/bin/bundle +++ b/gems/grape_devise/spec/dummy/bin/bundle @@ -1,3 +1,5 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +# frozen_string_literal: true + +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/gems/grape_devise/spec/dummy/bin/rails b/gems/grape_devise/spec/dummy/bin/rails index 728cd85a..a31728ab 100755 --- a/gems/grape_devise/spec/dummy/bin/rails +++ b/gems/grape_devise/spec/dummy/bin/rails @@ -1,4 +1,6 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +# frozen_string_literal: true + +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/gems/grape_devise/spec/dummy/bin/rake b/gems/grape_devise/spec/dummy/bin/rake index 17240489..c1999550 100755 --- a/gems/grape_devise/spec/dummy/bin/rake +++ b/gems/grape_devise/spec/dummy/bin/rake @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/gems/grape_devise/spec/dummy/config.ru b/gems/grape_devise/spec/dummy/config.ru index 5bc2a619..61c04e13 100644 --- a/gems/grape_devise/spec/dummy/config.ru +++ b/gems/grape_devise/spec/dummy/config.ru @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require ::File.expand_path('../config/environment', __FILE__) run Rails.application diff --git a/gems/grape_devise/spec/dummy/config/application.rb b/gems/grape_devise/spec/dummy/config/application.rb index 2d56f86a..d985cb27 100644 --- a/gems/grape_devise/spec/dummy/config/application.rb +++ b/gems/grape_devise/spec/dummy/config/application.rb @@ -1,7 +1,9 @@ -require File.expand_path('../boot', __FILE__) +# frozen_string_literal: true + +require File.expand_path('boot', __dir__) require 'rails/all' -#require '../..app/models/user' +# require '../..app/models/user' Bundler.require(*Rails.groups) @@ -11,4 +13,3 @@ module Dummy config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')] end end - diff --git a/gems/grape_devise/spec/dummy/config/boot.rb b/gems/grape_devise/spec/dummy/config/boot.rb index ef360470..6d2cba07 100644 --- a/gems/grape_devise/spec/dummy/config/boot.rb +++ b/gems/grape_devise/spec/dummy/config/boot.rb @@ -1,5 +1,7 @@ -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) +# frozen_string_literal: true -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) -$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) +# 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__) diff --git a/gems/grape_devise/spec/dummy/config/environment.rb b/gems/grape_devise/spec/dummy/config/environment.rb index 10e0cadc..bdab7759 100644 --- a/gems/grape_devise/spec/dummy/config/environment.rb +++ b/gems/grape_devise/spec/dummy/config/environment.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Load the Rails application. -require File.expand_path('../application', __FILE__) +require File.expand_path('application', __dir__) # Initialize the Rails application. Dummy::Application.initialize! diff --git a/gems/grape_devise/spec/dummy/config/environments/development.rb b/gems/grape_devise/spec/dummy/config/environments/development.rb index 9d26e125..576e6795 100644 --- a/gems/grape_devise/spec/dummy/config/environments/development.rb +++ b/gems/grape_devise/spec/dummy/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Dummy::Application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/gems/grape_devise/spec/dummy/config/environments/production.rb b/gems/grape_devise/spec/dummy/config/environments/production.rb index b690b1cf..a7d2e602 100644 --- a/gems/grape_devise/spec/dummy/config/environments/production.rb +++ b/gems/grape_devise/spec/dummy/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Dummy::Application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/gems/grape_devise/spec/dummy/config/environments/test.rb b/gems/grape_devise/spec/dummy/config/environments/test.rb index aa7c6159..8ad50deb 100644 --- a/gems/grape_devise/spec/dummy/config/environments/test.rb +++ b/gems/grape_devise/spec/dummy/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Dummy::Application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,7 +16,7 @@ Dummy::Application.configure do # Configure static asset server for tests with Cache-Control for performance. config.serve_static_assets = true - config.static_cache_control = "public, max-age=3600" + config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. config.consider_all_requests_local = true diff --git a/gems/grape_devise/spec/dummy/config/initializers/backtrace_silencers.rb b/gems/grape_devise/spec/dummy/config/initializers/backtrace_silencers.rb index 59385cdf..4b63f289 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/backtrace_silencers.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/backtrace_silencers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # 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. diff --git a/gems/grape_devise/spec/dummy/config/initializers/devise.rb b/gems/grape_devise/spec/dummy/config/initializers/devise.rb index a9cbda54..dbbfbded 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/devise.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/devise.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'devise' # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. @@ -42,12 +44,12 @@ Devise.setup do |config| # Configure which authentication keys should be case-insensitive. # These keys will be downcased upon creating or modifying a user and when used # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [ :email ] + config.case_insensitive_keys = [:email] # Configure which authentication keys should have whitespace stripped. # These keys will have whitespace before and after removed upon creating or # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [ :email ] + config.strip_whitespace_keys = [:email] # Tell if authentication through request.params is enabled. True by default. # It can be set to an array that will enable params authentication only for the diff --git a/gems/grape_devise/spec/dummy/config/initializers/filter_parameter_logging.rb b/gems/grape_devise/spec/dummy/config/initializers/filter_parameter_logging.rb index 4a994e1e..7a4f47b4 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/filter_parameter_logging.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/gems/grape_devise/spec/dummy/config/initializers/inflections.rb b/gems/grape_devise/spec/dummy/config/initializers/inflections.rb index ac033bf9..dc847422 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/inflections.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/inflections.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/gems/grape_devise/spec/dummy/config/initializers/mime_types.rb b/gems/grape_devise/spec/dummy/config/initializers/mime_types.rb index 72aca7e4..df5ec138 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/mime_types.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/mime_types.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/gems/grape_devise/spec/dummy/config/initializers/secret_token.rb b/gems/grape_devise/spec/dummy/config/initializers/secret_token.rb index 823ac2dd..ec8d472b 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/secret_token.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/secret_token.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Your secret key is used for verifying the integrity of signed cookies. diff --git a/gems/grape_devise/spec/dummy/config/initializers/session_store.rb b/gems/grape_devise/spec/dummy/config/initializers/session_store.rb index 155f7b02..ba27628a 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/session_store.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/session_store.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. Dummy::Application.config.session_store :cookie_store, key: '_dummy_session' diff --git a/gems/grape_devise/spec/dummy/config/initializers/wrap_parameters.rb b/gems/grape_devise/spec/dummy/config/initializers/wrap_parameters.rb index 33725e95..246168a4 100644 --- a/gems/grape_devise/spec/dummy/config/initializers/wrap_parameters.rb +++ b/gems/grape_devise/spec/dummy/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/gems/grape_devise/spec/dummy/config/routes.rb b/gems/grape_devise/spec/dummy/config/routes.rb index be2b51d2..ed698740 100644 --- a/gems/grape_devise/spec/dummy/config/routes.rb +++ b/gems/grape_devise/spec/dummy/config/routes.rb @@ -1,7 +1,8 @@ -require "devise" +# frozen_string_literal: true + +require 'devise' Dummy::Application.routes.draw do - devise_for :users mount API => '/' end diff --git a/gems/grape_devise/spec/dummy/db/migrate/20140913043018_devise_create_users.rb b/gems/grape_devise/spec/dummy/db/migrate/20140913043018_devise_create_users.rb index cf497c27..620b04c3 100644 --- a/gems/grape_devise/spec/dummy/db/migrate/20140913043018_devise_create_users.rb +++ b/gems/grape_devise/spec/dummy/db/migrate/20140913043018_devise_create_users.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| ## Database authenticatable - t.string :email, null: false, default: "" - t.string :encrypted_password, null: false, default: "" + t.string :email, null: false, default: '' + t.string :encrypted_password, null: false, default: '' ## Recoverable t.string :reset_password_token @@ -30,7 +32,6 @@ class DeviseCreateUsers < ActiveRecord::Migration # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at - t.timestamps end diff --git a/gems/grape_devise/spec/dummy/db/schema.rb b/gems/grape_devise/spec/dummy/db/schema.rb index 905d99e3..2f5ad323 100644 --- a/gems/grape_devise/spec/dummy/db/schema.rb +++ b/gems/grape_devise/spec/dummy/db/schema.rb @@ -1,4 +1,5 @@ -# encoding: UTF-8 +# frozen_string_literal: true + # 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. @@ -11,24 +12,22 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140913043018) do - - create_table "users", force: true 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.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.datetime "created_at" - t.datetime "updated_at" +ActiveRecord::Schema.define(version: 20_140_913_043_018) do + create_table 'users', force: true 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.integer 'sign_in_count', default: 0, null: false + t.datetime 'current_sign_in_at' + t.datetime 'last_sign_in_at' + t.string 'current_sign_in_ip' + t.string 'last_sign_in_ip' + t.datetime 'created_at' + t.datetime 'updated_at' end - add_index "users", ["email"], name: "index_users_on_email", unique: true - add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - + add_index 'users', ['email'], name: 'index_users_on_email', unique: true + add_index 'users', ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true end diff --git a/gems/grape_devise/spec/factories.rb b/gems/grape_devise/spec/factories.rb index beb87070..a3975f3a 100644 --- a/gems/grape_devise/spec/factories.rb +++ b/gems/grape_devise/spec/factories.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + FactoryGirl.define do factory :user do - email "john.doe@example.com" - password "12345" - password_confirmation "12345" + email 'john.doe@example.com' + password '12345' + password_confirmation '12345' end end diff --git a/gems/grape_devise/spec/requests/user_spec.rb b/gems/grape_devise/spec/requests/user_spec.rb index 86bc519e..25ce81bd 100644 --- a/gems/grape_devise/spec/requests/user_spec.rb +++ b/gems/grape_devise/spec/requests/user_spec.rb @@ -1,52 +1,53 @@ +# frozen_string_literal: true + require 'spec_helper' require 'warden/test/helpers' -RSpec.describe API, :type => :request do +RSpec.describe API, type: :request do include Warden::Test::Helpers let(:user) { build(:user) } - after{ Warden.test_reset! } + after { Warden.test_reset! } - it "should return the current user" do + it 'should return the current user' do login_as user, scope: :user - get "/me" + get '/me' response.body.should eq(user.to_json) end - it "should return an error if not logged in" do + it 'should return an error if not logged in' do login_as nil, scope: :user - get "/me" + get '/me' - response.code.should eq("401") + response.code.should eq('401') end - it "should return true if logged in" do + it 'should return true if logged in' do login_as user, scope: :user - get "/authorized" + get '/authorized' - response.body.should eq("true") + response.body.should eq('true') end - it "should return false if logged out" do + it 'should return false if logged out' do login_as nil, scope: :user - get "/authorized" + get '/authorized' - response.body.should eq("false") + response.body.should eq('false') end - it "should log in the user" do + it 'should log in the user' do User.stub :find_for_database_authentication do user end - post "/signin", { user: { email: user.email, password: user.password } } + post '/signin', user: { email: user.email, password: user.password } - response.code.should eq("201") + response.code.should eq('201') end - -end \ No newline at end of file +end diff --git a/gems/grape_devise/spec/spec_helper.rb b/gems/grape_devise/spec/spec_helper.rb index 89343208..0212f7b1 100644 --- a/gems/grape_devise/spec/spec_helper.rb +++ b/gems/grape_devise/spec/spec_helper.rb @@ -1,7 +1,9 @@ -# Configure Rails Environment -ENV["RAILS_ENV"] = "test" +# frozen_string_literal: true -require File.expand_path("../dummy/config/environment.rb", __FILE__) +# Configure Rails Environment +ENV['RAILS_ENV'] = 'test' + +require File.expand_path('dummy/config/environment.rb', __dir__) require 'rspec' require 'rspec/rails' require 'factory_girl' @@ -16,7 +18,7 @@ Rails.backtrace_cleaner.remove_silencers! # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} +Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } RSpec.configure do |config| # == Mock Framework diff --git a/gems/ruby-param-validation/Rakefile b/gems/ruby-param-validation/Rakefile index 1f33d053..dc5d5818 100644 --- a/gems/ruby-param-validation/Rakefile +++ b/gems/ruby-param-validation/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rake/testtask' Rake::TestTask.new do |t| @@ -5,5 +7,5 @@ Rake::TestTask.new do |t| t.test_files = FileList['test/test*.rb', 'test/*test.rb'] end -desc "Run tests" -task :default => :test \ No newline at end of file +desc 'Run tests' +task default: :test diff --git a/gems/ruby-param-validation/lib/param_validation.rb b/gems/ruby-param-validation/lib/param_validation.rb index 131ffc31..2835763d 100644 --- a/gems/ruby-param-validation/lib/param_validation.rb +++ b/gems/ruby-param-validation/lib/param_validation.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + require 'json' require 'chronic' class ParamValidation - # Given a hash of data and a validation hash, check all the validations, raising an Error on the first invalid key # @raise [ValidationError] if one or more of the validations fail. def initialize(data, validations) @@ -10,34 +11,46 @@ class ParamValidation validations.each do |key, validators| val = key === :root ? data : (data[key] || data[key.to_s] || data[key.to_sym]) next if validators[:required].nil? && val.nil? + validators.each do |name, arg| validator = @@validators[name] msg = validations[key][:message] next unless validator + is_valid = @@validators[name].call(val, arg, data) msg_proc = @@messages[name] - msg ||= @@messages[name].call({key: key, data: data, val: val, arg: arg}) if msg_proc - errors.push({msg: msg, data: {key: key, val: val, name: name, msg: msg}}) unless is_valid + msg ||= @@messages[name].call(key: key, data: data, val: val, arg: arg) if msg_proc + errors.push(msg: msg, data: { key: key, val: val, name: name, msg: msg }) unless is_valid end end if errors.length == 1 raise ValidationError.new(errors[0][:msg], errors[0][:data]) elsif errors.length > 1 - msg = errors.collect {|e| e[:msg]}.join('\n') - raise ValidationError.new(msg, errors.collect{|e| e[:data]}) + msg = errors.collect { |e| e[:msg] }.join('\n') + raise ValidationError.new(msg, errors.collect { |e| e[:data] }) end end - def self.messages; @@messages; end + def self.messages + @@messages + end + def self.set_message(name, &block) @@messages[name] = block end - def self.validators; @@validators; end + def self.validators + @@validators + end + def self.add_validator(name, &block) @@validators[name] = block end - def self.structure_validators; @@structure_validators; end + + def self.structure_validators + @@structure_validators + end + def self.add_structure_validator(name, &block) @@structure_validators[name] = block end @@ -47,64 +60,122 @@ class ParamValidation # - arg is the argument passed into the validator (eg for {required: true}, it is `true`) # - data is the entire set of data @@validators = { - required: lambda {|val, arg, data| !val.nil?}, - absent: lambda {|val, arg, data| val.nil?}, - not_blank: lambda {|val, arg, data| val.is_a?(String) && val.length > 0}, - not_included_in: lambda {|val, arg, data| !arg.include?(val) rescue false}, - included_in: lambda {|val, arg, data| arg.include?(val) rescue false}, - format: lambda {|val, arg, data| val =~ arg rescue false}, - is_integer: lambda {|val, arg, data| val.is_a?(Integer) || val =~ /\A[+-]?\d+\Z/}, - is_float: lambda {|val, arg, data| val.is_a?(Float) || (!!Float(val) rescue false) }, - min_length: lambda {|val, arg, data| val.length >= arg rescue false}, - max_length: lambda {|val, arg, data| val.length <= arg rescue false}, - length_range: lambda {|val, arg, data| arg.cover?(val.length) rescue false}, - length_equals: lambda {|val, arg, data| val.length == arg}, - is_reference: lambda{|val, arg, data| (val.is_a?(Integer)&& val >=0) || val =~ /\A\d+\Z/ || val == ''}, - equals: lambda {|val, arg, data| val == arg}, - min: lambda {|val, arg, data| val >= arg rescue false}, - max: lambda {|val, arg, data| val <= arg rescue false}, - is_array: lambda {|val, arg, data| val.is_a?(Array)}, - is_hash: lambda {|val, arg, data| val.is_a?(Hash)}, - is_json: lambda {|val, arg, data| ParamValidation.is_valid_json?(val)}, - in_range: lambda {|val, arg, data| arg.cover?(val) rescue false}, - is_a: lambda {|val, arg, data| arg.kind_of?(Enumerable) ? arg.any? {|i| val.is_a?(i)} : val.is_a?(arg)}, - can_be_date: lambda {|val, arg, data| val.is_a?(Date) || val.is_a?(DateTime) || Chronic.parse(val)}, - array_of_hashes: lambda {|val, arg, data| data.is_a?(Array) && data.map{|pair| ParamValidation.new(pair.to_h, arg)}.all?} + required: ->(val, _arg, _data) { !val.nil? }, + absent: ->(val, _arg, _data) { val.nil? }, + not_blank: ->(val, _arg, _data) { val.is_a?(String) && !val.empty? }, + not_included_in: lambda { |val, arg, _data| + begin + !arg.include?(val) + rescue StandardError + false + end + }, + included_in: lambda { |val, arg, _data| + begin + arg.include?(val) + rescue StandardError + false + end + }, + format: lambda { |val, arg, _data| + begin + val =~ arg + rescue StandardError + false + end + }, + is_integer: ->(val, _arg, _data) { val.is_a?(Integer) || val =~ /\A[+-]?\d+\Z/ }, + is_float: lambda { |val, _arg, _data| + val.is_a?(Float) || (begin + !!Float(val) + rescue StandardError + false + end) + }, + min_length: lambda { |val, arg, _data| + begin + val.length >= arg + rescue StandardError + false + end + }, + max_length: lambda { |val, arg, _data| + begin + val.length <= arg + rescue StandardError + false + end + }, + length_range: lambda { |val, arg, _data| + begin + arg.cover?(val.length) + rescue StandardError + false + end + }, + length_equals: ->(val, arg, _data) { val.length == arg }, + is_reference: ->(val, _arg, _data) { (val.is_a?(Integer) && val >= 0) || val =~ /\A\d+\Z/ || val == '' }, + equals: ->(val, arg, _data) { val == arg }, + min: lambda { |val, arg, _data| + begin + val >= arg + rescue StandardError + false + end + }, + max: lambda { |val, arg, _data| + begin + val <= arg + rescue StandardError + false + end + }, + is_array: ->(val, _arg, _data) { val.is_a?(Array) }, + is_hash: ->(val, _arg, _data) { val.is_a?(Hash) }, + is_json: ->(val, _arg, _data) { ParamValidation.is_valid_json?(val) }, + in_range: lambda { |val, arg, _data| + begin + arg.cover?(val) + rescue StandardError + false + end + }, + is_a: ->(val, arg, _data) { arg.is_a?(Enumerable) ? arg.any? { |i| val.is_a?(i) } : val.is_a?(arg) }, + can_be_date: ->(val, _arg, _data) { val.is_a?(Date) || val.is_a?(DateTime) || Chronic.parse(val) }, + array_of_hashes: ->(_val, arg, data) { data.is_a?(Array) && data.map { |pair| ParamValidation.new(pair.to_h, arg) }.all? } } @@messages = { - required: lambda {|h| "#{h[:key]} is required"}, - absent: lambda {|h| "#{h[:key]} must not be present"}, - not_blank: lambda {|h| "#{h[:key]} must not be blank"}, - not_included_in: lambda {|h| "#{h[:key]} must not be included in #{h[:arg].join(", ")}"}, - included_in: lambda {|h|"#{h[:key]} must be one of #{h[:arg].join(", ")}"}, - format: lambda {|h|"#{h[:key]} doesn't have the right format"}, - is_integer: lambda {|h|"#{h[:key]} should be an integer"}, - is_float: lambda {|h|"#{h[:key]} should be a float"}, - min_length: lambda {|h|"#{h[:key]} has a minimum length of #{h[:arg]}"}, - max_length: lambda {|h|"#{h[:key]} has a maximum length of #{h[:arg]}"}, - length_range: lambda {|h|"#{h[:key]} should have a length within #{h[:arg]}"}, - length_equals: lambda {|h|"#{h[:key]} should have a length of #{h[:arg]}"}, - is_reference: lambda{|h| "#{h[:key]} should be an integer or blank"}, - equals: lambda {|h|"#{h[:key]} should equal #{h[:arg]}"}, - min: lambda {|h|"#{h[:key]} must be at least #{h[:arg]}"}, - max: lambda {|h|"#{h[:key]} cannot be more than #{h[:arg]}"}, - in_range: lambda {|h|"#{h[:key]} should be within #{h[:arg]}"}, - is_json: lambda {|h| "#{h[:key]} should be valid JSON"}, - is_hash: lambda {|h| "#{h[:key]} should be a hash"}, - is_a: lambda {|h| "#{h[:key]} should be of the type(s): #{h[:arg].kind_of?(Enumerable) ? h[:arg].join(', '): h[:arg]}"}, - can_be_date: lambda {|h| "#{h[:key]} should be a datetime or be parsable as one"}, - array_of_hashes: lambda {|h| "Please pass in an array of hashes"} + required: ->(h) { "#{h[:key]} is required" }, + absent: ->(h) { "#{h[:key]} must not be present" }, + not_blank: ->(h) { "#{h[:key]} must not be blank" }, + not_included_in: ->(h) { "#{h[:key]} must not be included in #{h[:arg].join(', ')}" }, + included_in: ->(h) { "#{h[:key]} must be one of #{h[:arg].join(', ')}" }, + format: ->(h) { "#{h[:key]} doesn't have the right format" }, + is_integer: ->(h) { "#{h[:key]} should be an integer" }, + is_float: ->(h) { "#{h[:key]} should be a float" }, + min_length: ->(h) { "#{h[:key]} has a minimum length of #{h[:arg]}" }, + max_length: ->(h) { "#{h[:key]} has a maximum length of #{h[:arg]}" }, + length_range: ->(h) { "#{h[:key]} should have a length within #{h[:arg]}" }, + length_equals: ->(h) { "#{h[:key]} should have a length of #{h[:arg]}" }, + is_reference: ->(h) { "#{h[:key]} should be an integer or blank" }, + equals: ->(h) { "#{h[:key]} should equal #{h[:arg]}" }, + min: ->(h) { "#{h[:key]} must be at least #{h[:arg]}" }, + max: ->(h) { "#{h[:key]} cannot be more than #{h[:arg]}" }, + in_range: ->(h) { "#{h[:key]} should be within #{h[:arg]}" }, + is_json: ->(h) { "#{h[:key]} should be valid JSON" }, + is_hash: ->(h) { "#{h[:key]} should be a hash" }, + is_a: ->(h) { "#{h[:key]} should be of the type(s): #{h[:arg].is_a?(Enumerable) ? h[:arg].join(', ') : h[:arg]}" }, + can_be_date: ->(h) { "#{h[:key]} should be a datetime or be parsable as one" }, + array_of_hashes: ->(_h) { 'Please pass in an array of hashes' } } # small utility for testing json validity def self.is_valid_json?(str) - begin - JSON.parse(str) - return true - rescue => e - return false - end + JSON.parse(str) + true + rescue StandardError => e + false end # Special error class that holds all the error data for reference @@ -125,6 +196,4 @@ class ParamValidation super(msg) end end - end - diff --git a/gems/ruby-param-validation/param_validation.gemspec b/gems/ruby-param-validation/param_validation.gemspec index 56d8931f..751a4c8f 100644 --- a/gems/ruby-param-validation/param_validation.gemspec +++ b/gems/ruby-param-validation/param_validation.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| s.name = 'param_validation' s.version = '0.0.2' diff --git a/gems/ruby-param-validation/test/param_validation_test.rb b/gems/ruby-param-validation/test/param_validation_test.rb index a58262ef..cafe8435 100644 --- a/gems/ruby-param-validation/test/param_validation_test.rb +++ b/gems/ruby-param-validation/test/param_validation_test.rb @@ -1,173 +1,193 @@ +# frozen_string_literal: true + require './lib/param_validation.rb' require 'minitest/autorun' class ParamValidationTest < Minitest::Test - - def setup - end + def setup; end def test_required - begin; ParamValidation.new({}, {x: {required: true}}) + begin; ParamValidation.new({}, x: { required: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + # If a key is not required, then don't run the tests on it def test_not_required_and_absent_then_tests_do_not_run - ParamValidation.new({}, {x: {max: 100}}) + ParamValidation.new({}, x: { max: 100 }) assert true end + def test_not_blank_fail - begin; ParamValidation.new({x: ''}, {x: {not_blank: true}}) + begin; ParamValidation.new({ x: '' }, x: { not_blank: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_not_blank_fail_nil - begin; ParamValidation.new({x: nil}, {x: {not_blank: true, required: true}}) + begin; ParamValidation.new({ x: nil }, x: { not_blank: true, required: true }) rescue ParamValidation::ValidationError => e; e; end - assert(e.data.one?{|i| i[:name] == :not_blank && i[:key] == :x}) - assert(e.data.one?{|i| i[:name] == :required && i[:key] == :x}) + assert(e.data.one? { |i| i[:name] == :not_blank && i[:key] == :x }) + assert(e.data.one? { |i| i[:name] == :required && i[:key] == :x }) end + def test_not_blank_succeed - ParamValidation.new({x: 'x'}, {x: {not_blank: true}}) + ParamValidation.new({ x: 'x' }, x: { not_blank: true }) assert true end + def test_require_no_err - begin; ParamValidation.new({x: 1}, {x: {required: true}}) + begin; ParamValidation.new({ x: 1 }, x: { required: true }) rescue ParamValidation::ValidationError => e; end assert e.nil? end + def test_absent - begin; ParamValidation.new({x: 1}, {x: {absent: true}}) + begin; ParamValidation.new({ x: 1 }, x: { absent: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_not_included_in - begin; ParamValidation.new({x: 1}, {x: {not_included_in: [1]}}) + begin; ParamValidation.new({ x: 1 }, x: { not_included_in: [1] }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_included_in - begin; ParamValidation.new({x: 1}, {x: {included_in: [2]}}) + begin; ParamValidation.new({ x: 1 }, x: { included_in: [2] }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_format - begin; ParamValidation.new({x: 'x'}, {x: {format: /y/}}) + begin; ParamValidation.new({ x: 'x' }, x: { format: /y/ }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_string - begin; ParamValidation.new({x: '-0'}, {x: {is_reference: true}}) + begin; ParamValidation.new({ x: '-0' }, x: { is_reference: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_negative_integer - begin; ParamValidation.new({x: -1}, {x: {is_reference: true}}) + begin; ParamValidation.new({ x: -1 }, x: { is_reference: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end def test_is_reference_passes - ParamValidation.new({x: '0'}, {x: {is_reference: true}}) - ParamValidation.new({x: 1}, {x: {is_reference: true}}) - ParamValidation.new({x: ''}, {x: {is_reference: true}}) - pass() + ParamValidation.new({ x: '0' }, x: { is_reference: true }) + ParamValidation.new({ x: 1 }, x: { is_reference: true }) + ParamValidation.new({ x: '' }, x: { is_reference: true }) + pass end def test_is_integer - begin; ParamValidation.new({x: 'x'}, {x: {is_integer: true}}) + begin; ParamValidation.new({ x: 'x' }, x: { is_integer: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_is_float - begin; ParamValidation.new({x: 'x'}, {x: {is_float: true}}) + begin; ParamValidation.new({ x: 'x' }, x: { is_float: true }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_min_length - begin; ParamValidation.new({x: []}, {x: {min_length: 2}}) + begin; ParamValidation.new({ x: [] }, x: { min_length: 2 }) rescue ParamValidation::ValidationError => e; e; end assert_equal :x, e.data[:key] end + def test_max_length - begin; ParamValidation.new({x: [1,2,3]}, {x: {max_length: 2}}) + begin; ParamValidation.new({ x: [1, 2, 3] }, x: { max_length: 2 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end + def test_length_range - begin; ParamValidation.new({x: [1,2,3,4]}, {x: {length_range: 1..3}}) + begin; ParamValidation.new({ x: [1, 2, 3, 4] }, x: { length_range: 1..3 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end + def test_length_equals - begin; ParamValidation.new({x: [1,2]}, {x: {length_equals: 1}}) + begin; ParamValidation.new({ x: [1, 2] }, x: { length_equals: 1 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end + def test_min - begin; ParamValidation.new({x: 1}, {x: {min: 2}}) + begin; ParamValidation.new({ x: 1 }, x: { min: 2 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:key], :x end + def test_max - begin; ParamValidation.new({x: 4}, {x: {max: 2}}) + begin; ParamValidation.new({ x: 4 }, x: { max: 2 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:name], :max end + def test_in_range - begin; ParamValidation.new({x: 1}, {x: {in_range: 2..4}}) + begin; ParamValidation.new({ x: 1 }, x: { in_range: 2..4 }) rescue ParamValidation::ValidationError => e; e; end assert_equal e.data[:val], 1 end + def test_equals - begin; ParamValidation.new({x: 1}, {x: {equals: 2}}) + begin; ParamValidation.new({ x: 1 }, x: { equals: 2 }) rescue ParamValidation::ValidationError => e; e; end - assert_equal "x should equal #{2}", e.to_s + assert_equal 'x should equal 2', e.to_s end + def test_root_array_of_hashes - begin; ParamValidation.new({x: 1}, {root: {array_of_hashes: {x: {required: true}}}}) + begin; ParamValidation.new({ x: 1 }, root: { array_of_hashes: { x: { required: true } } }) rescue ParamValidation::ValidationError => e; e; end - assert_equal "Please pass in an array of hashes", e.to_s + assert_equal 'Please pass in an array of hashes', e.to_s end + def test_root_array_of_hashes_with_nesting_ok - v = ParamValidation.new([{'x' => 1}, {x: 1}], {root: {array_of_hashes: {x: {is_integer: true}}}}) + v = ParamValidation.new([{ 'x' => 1 }, { x: 1 }], root: { array_of_hashes: { x: { is_integer: true } } }) assert_equal v, v # test that it does not raise end + def test_root_array_of_hashes_with_nesting - begin; ParamValidation.new([{x: 1}, {x: 'hi'}], {root: {array_of_hashes: {x: {is_integer: true}}}}) + begin; ParamValidation.new([{ x: 1 }, { x: 'hi' }], root: { array_of_hashes: { x: { is_integer: true } } }) rescue ParamValidation::ValidationError => e; e; end - assert_equal "x should be an integer", e.to_s + assert_equal 'x should be an integer', e.to_s end def test_is_json_with_string - begin; ParamValidation.new({x: '[[[[[[['}, {x: {is_json: true}}) + begin; ParamValidation.new({ x: '[[[[[[[' }, x: { is_json: true }) rescue ParamValidation::ValidationError => e; e; end - assert_equal "x should be valid JSON", e.to_s + assert_equal 'x should be valid JSON', e.to_s end def test_is_json_without_string - begin; ParamValidation.new({x: {}}, {x: {is_json: true}}) + begin; ParamValidation.new({ x: {} }, x: { is_json: true }) rescue ParamValidation::ValidationError => e; e; end - assert_equal "x should be valid JSON", e.to_s + assert_equal 'x should be valid JSON', e.to_s end def test_is_a_single - ParamValidation.new({x: 5.6}, {x: {is_a: Float}}) + ParamValidation.new({ x: 5.6 }, x: { is_a: Float }) begin - ParamValidation.new({x: 5.6}, {x: {is_a: Integer}}) + ParamValidation.new({ x: 5.6 }, x: { is_a: Integer }) rescue ParamValidation::ValidationError => e e end assert_equal 'x should be of the type(s): Integer', e.to_s end - def test_is_a_multiple - ParamValidation.new({x: 5.6}, {x: {is_a: [Integer,Float]}}) + ParamValidation.new({ x: 5.6 }, x: { is_a: [Integer, Float] }) begin - ParamValidation.new({x: 5.6}, {x: {is_a: [Integer, Array]}}) + ParamValidation.new({ x: 5.6 }, x: { is_a: [Integer, Array] }) rescue ParamValidation::ValidationError => e e end @@ -176,13 +196,13 @@ class ParamValidationTest < Minitest::Test end def test_can_be_date - ParamValidation.new({x: Date.new()}, {x: {can_be_date: true}}) - ParamValidation.new({x: DateTime.new()}, {x: {can_be_date: true}}) - ParamValidation.new({x: '2017-05-15T12:00:00.000Z'}, {x: {can_be_date: true}}) - ParamValidation.new({x: '2017-05-15'}, {x: {can_be_date: true}}) + ParamValidation.new({ x: Date.new }, x: { can_be_date: true }) + ParamValidation.new({ x: DateTime.new }, x: { can_be_date: true }) + ParamValidation.new({ x: '2017-05-15T12:00:00.000Z' }, x: { can_be_date: true }) + ParamValidation.new({ x: '2017-05-15' }, x: { can_be_date: true }) begin - ParamValidation.new({x: 'not_a _date'}, {x: {can_be_date: true}}) + ParamValidation.new({ x: 'not_a _date' }, x: { can_be_date: true }) rescue ParamValidation::ValidationError => e e end @@ -191,25 +211,25 @@ class ParamValidationTest < Minitest::Test end def test_add_validator - ParamValidation.add_validator(:dollars){|val, arg, data| val =~ /^\d+(\.\d\d)?$/} + ParamValidation.add_validator(:dollars) { |val, _arg, _data| val =~ /^\d+(\.\d\d)?$/ } begin - ParamValidation.new({x: 'hi'}, {x: {dollars: true}}) + ParamValidation.new({ x: 'hi' }, x: { dollars: true }) rescue ParamValidation::ValidationError => e e end assert_equal :dollars, e.data[:name] end + def test_set_message - ParamValidation.add_validator(:dollars){|val, arg, data| val =~ /^\d+(\.\d\d)?$/} - ParamValidation.set_message(:dollars){|h| "#{h[:key]} must be a dollar amount"} + ParamValidation.add_validator(:dollars) { |val, _arg, _data| val =~ /^\d+(\.\d\d)?$/ } + ParamValidation.set_message(:dollars) { |h| "#{h[:key]} must be a dollar amount" } begin - ParamValidation.new({x: 'hi'}, {x: {dollars: true}}) + ParamValidation.new({ x: 'hi' }, x: { dollars: true }) rescue ParamValidation::ValidationError => e e end - assert_equal "x must be a dollar amount", e.to_s + assert_equal 'x must be a dollar amount', e.to_s end - def test_custom_validator - end + def test_custom_validator; end end diff --git a/gems/ruby-qx/lib/qx.rb b/gems/ruby-qx/lib/qx.rb index 5434c1e8..f5ee40e1 100644 --- a/gems/ruby-qx/lib/qx.rb +++ b/gems/ruby-qx/lib/qx.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'active_record' require 'colorize' @@ -39,9 +41,9 @@ class Qx str += expr[:JOIN].map { |from, cond| " JOIN #{from} ON #{cond}" }.join if expr[:JOIN] str += expr[:LEFT_JOIN].map { |from, cond| " LEFT JOIN #{from} ON #{cond}" }.join if expr[:LEFT_JOIN] str += expr[:LEFT_OUTER_JOIN].map { |from, cond| " LEFT OUTER JOIN #{from} ON #{cond}" }.join if expr[:LEFT_OUTER_JOIN] - str += expr[:JOIN_LATERAL].map {|i| " JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}"}.join if expr[:JOIN_LATERAL] + str += expr[:JOIN_LATERAL].map { |i| " JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}" }.join if expr[:JOIN_LATERAL] - str += expr[:LEFT_JOIN_LATERAL].map {|i| " LEFT JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}"}.join if expr[:LEFT_JOIN_LATERAL] + str += expr[:LEFT_JOIN_LATERAL].map { |i| " LEFT JOIN LATERAL (#{i[:select_statement]}) #{i[:join_name]} ON #{i[:success_condition]}" }.join if expr[:LEFT_JOIN_LATERAL] str += ' WHERE ' + expr[:WHERE].map { |w| "(#{w})" }.join(' AND ') if expr[:WHERE] str += ' GROUP BY ' + expr[:GROUP_BY].join(', ') if expr[:GROUP_BY] str += ' HAVING ' + expr[:HAVING].map { |h| "(#{h})" }.join(' AND ') if expr[:HAVING] @@ -77,9 +79,9 @@ class Qx elsif expr[:ON_CONSTRAINT] str += " ON CONSTRAINT #{expr[:ON_CONSTRAINT]}" end - str += ' DO NOTHING' if !expr[:CONFLICT_UPSERT] + str += ' DO NOTHING' unless expr[:CONFLICT_UPSERT] if expr[:CONFLICT_UPSERT] - set_str = expr[:INSERT_COLUMNS].select{|i| i != 'created_at'}.map{|i| "#{i} = EXCLUDED.#{i}" } + set_str = expr[:INSERT_COLUMNS].reject { |i| i == 'created_at' }.map { |i| "#{i} = EXCLUDED.#{i}" } str += " DO UPDATE SET #{set_str.join(', ')}" end end @@ -101,6 +103,7 @@ class Qx str += ' ' + expr[:ON_CONFLICT] if expr[:ON_CONFLICT] str += ' RETURNING ' + expr[:RETURNING].join(', ') if expr[:RETURNING] end + str end @@ -121,6 +124,7 @@ class Qx # Qx.execute(Qx.select("id").from("table_name")) def self.execute(expr, data = {}, options = {}) return expr.execute(data) if expr.is_a?(Qx) + interpolated = Qx.interpolate_expr(expr, data) execute_raw(interpolated, options) end @@ -247,7 +251,7 @@ class Qx def order_by(*cols) orders = /(asc)|(desc)( nulls (first)|(last))?/i # Sanitize out invalid order keywords - @tree[:ORDER_BY] = cols.map { |col, order| [col.to_s, order.to_s.downcase.strip.match(order.to_s.downcase) ? order.to_s.upcase : nil] } + @tree[:ORDER_BY] = cols.map { |col, order| [col.to_s, order.to_s.downcase.strip.match?(order.to_s.downcase) ? order.to_s.upcase : nil] } self end @@ -310,18 +314,15 @@ class Qx self end - def join_lateral(join_name, select_statement, success_condition=true) - + def join_lateral(join_name, select_statement, success_condition = true) @tree[:JOIN_LATERAL] ||= [] - @tree[:JOIN_LATERAL].concat([{join_name: join_name, select_statement: select_statement, success_condition: success_condition}]) + @tree[:JOIN_LATERAL].concat([{ join_name: join_name, select_statement: select_statement, success_condition: success_condition }]) self end - - def left_join_lateral(join_name, select_statement, success_condition=true) - + def left_join_lateral(join_name, select_statement, success_condition = true) @tree[:LEFT_JOIN_LATERAL] ||= [] - @tree[:LEFT_JOIN_LATERAL].concat([{join_name: join_name, select_statement: select_statement, success_condition: success_condition}]) + @tree[:LEFT_JOIN_LATERAL].concat([{ join_name: join_name, select_statement: select_statement, success_condition: success_condition }]) self end @@ -384,7 +385,7 @@ class Qx self end - def on_conflict() + def on_conflict @tree[:ON_CONFLICT] = true self end @@ -399,8 +400,8 @@ class Qx self end - def upsert(on_index, columns=nil) - @tree[:CONFLICT_UPSERT] = {index: on_index, cols: columns} + def upsert(on_index, columns = nil) + @tree[:CONFLICT_UPSERT] = { index: on_index, cols: columns } self end diff --git a/gems/ruby-qx/qx.gemspec b/gems/ruby-qx/qx.gemspec index dcfcd007..195b126b 100644 --- a/gems/ruby-qx/qx.gemspec +++ b/gems/ruby-qx/qx.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Gem::Specification.new do |s| s.name = 'qx' s.version = '0.1.1' @@ -9,7 +11,7 @@ Gem::Specification.new do |s| s.files = 'lib/qx.rb' s.homepage = 'https://github.com/jayrbolton/qx' s.license = 'MIT' - s.add_runtime_dependency 'colorize', '~> 0.8' s.add_runtime_dependency 'activerecord', '>= 3.0' + s.add_runtime_dependency 'colorize', '~> 0.8' s.add_development_dependency 'minitest', '~> 5.9' end diff --git a/gems/ruby-qx/test/UpsertTest.rb b/gems/ruby-qx/test/UpsertTest.rb index 1638669f..909d2fb7 100644 --- a/gems/ruby-qx/test/UpsertTest.rb +++ b/gems/ruby-qx/test/UpsertTest.rb @@ -1,20 +1,20 @@ +# frozen_string_literal: true + require './lib/qx.rb' require 'minitest/autorun' class UpsertTest < Minitest::Test - def setup - - end + def setup; end def test_upsert table = 'x' - column1 = "a" + column1 = 'a' column2 = 'b' - idx = "idx_something_more" + idx = 'idx_something_more' - result = Qx.insert_into(table).values({column1: column1, column2: column2}).on_conflict.upsert(idx).parse + result = Qx.insert_into(table).values(column1: column1, column2: column2).on_conflict.upsert(idx).parse - expected = %Q(INSERT INTO "#{table}" ("column1", "column2") VALUES ($Q$#{column1}$Q$, $Q$#{column2}$Q$) ON CONFLICT ON CONSTRAINT #{idx} DO UPDATE SET "column1" = EXCLUDED."column1", "column2" = EXCLUDED."column2") + expected = %(INSERT INTO "#{table}" ("column1", "column2") VALUES ($Q$#{column1}$Q$, $Q$#{column2}$Q$) ON CONFLICT ON CONSTRAINT #{idx} DO UPDATE SET "column1" = EXCLUDED."column1", "column2" = EXCLUDED."column2") assert_equal(expected, result) end -end \ No newline at end of file +end diff --git a/gems/ruby-qx/test/qx_test.rb b/gems/ruby-qx/test/qx_test.rb index 74fd2ee8..71c497ae 100644 --- a/gems/ruby-qx/test/qx_test.rb +++ b/gems/ruby-qx/test/qx_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require './lib/qx.rb' require 'pg' require 'minitest/autorun' @@ -10,9 +12,7 @@ Qx.config(type_map: tm) Qx.execute_file('./test/test_schema.sql') class QxTest < Minitest::Test - - def setup - end + def setup; end # Let's just test that the schema was executed def test_execute_file @@ -23,241 +23,260 @@ class QxTest < Minitest::Test end def test_select_from - parsed = Qx.select(:id, "name").from(:table_name).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name) + parsed = Qx.select(:id, 'name').from(:table_name).parse + assert_equal parsed, %(SELECT id, name FROM table_name) end + def test_select_distinct_on - parsed = Qx.select(:id, "name").distinct_on(:distinct_col1, :distinct_col2).from(:table_name).parse - assert_equal parsed, %Q(SELECT DISTINCT ON (distinct_col1, distinct_col2) id, name FROM table_name) + parsed = Qx.select(:id, 'name').distinct_on(:distinct_col1, :distinct_col2).from(:table_name).parse + assert_equal parsed, %(SELECT DISTINCT ON (distinct_col1, distinct_col2) id, name FROM table_name) end + def test_select_distinct - parsed = Qx.select(:id, "name").distinct.from(:table_name).parse - assert_equal parsed, %Q(SELECT DISTINCT id, name FROM table_name) + parsed = Qx.select(:id, 'name').distinct.from(:table_name).parse + assert_equal parsed, %(SELECT DISTINCT id, name FROM table_name) end def test_select_as - parsed = Qx.select(:id, "name").from(:table_name).as(:alias).parse - assert_equal parsed, %Q((SELECT id, name FROM table_name) AS "alias") + parsed = Qx.select(:id, 'name').from(:table_name).as(:alias).parse + assert_equal parsed, %((SELECT id, name FROM table_name) AS "alias") end - + def test_select_where - parsed = Qx.select(:id, "name").from(:table_name).where("x = $y OR a = $b", y: 1, b: 2).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name WHERE (x = 1 OR a = 2)) + parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y OR a = $b', y: 1, b: 2).parse + assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1 OR a = 2)) end + def test_select_where_hash_array - parsed = Qx.select(:id, "name").from(:table_name).where([x: 1], ["y = $n", {n: 2}]).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name WHERE ("x" IN (1)) AND (y = 2)) + parsed = Qx.select(:id, 'name').from(:table_name).where([x: 1], ['y = $n', { n: 2 }]).parse + assert_equal parsed, %(SELECT id, name FROM table_name WHERE ("x" IN (1)) AND (y = 2)) end + def test_select_and_where - parsed = Qx.select(:id, "name").from(:table_name).where("x = $y", y: 1).and_where("a = $b", b: 2).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name WHERE (x = 1) AND (a = 2)) + parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y', y: 1).and_where('a = $b', b: 2).parse + assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1) AND (a = 2)) end + def test_select_and_where_hash - parsed = Qx.select(:id, "name").from(:table_name).where("x = $y", y: 1).and_where(a: 2).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name WHERE (x = 1) AND ("a" IN (2))) + parsed = Qx.select(:id, 'name').from(:table_name).where('x = $y', y: 1).and_where(a: 2).parse + assert_equal parsed, %(SELECT id, name FROM table_name WHERE (x = 1) AND ("a" IN (2))) end - + def test_select_and_group_by - parsed = Qx.select(:id, "name").from(:table_name).group_by("col1", "col2").parse - assert_equal parsed, %Q(SELECT id, name FROM table_name GROUP BY col1, col2) + parsed = Qx.select(:id, 'name').from(:table_name).group_by('col1', 'col2').parse + assert_equal parsed, %(SELECT id, name FROM table_name GROUP BY col1, col2) end - + def test_select_and_order_by - parsed = Qx.select(:id, "name").from(:table_name).order_by("col1", ["col2", "DESC NULLS LAST"]).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name ORDER BY col1 , col2 DESC NULLS LAST) + parsed = Qx.select(:id, 'name').from(:table_name).order_by('col1', ['col2', 'DESC NULLS LAST']).parse + assert_equal parsed, %(SELECT id, name FROM table_name ORDER BY col1 , col2 DESC NULLS LAST) end def test_select_having - parsed = Qx.select(:id, "name").from(:table_name).having("COUNT(col1) > $n", n: 1).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1)) + parsed = Qx.select(:id, 'name').from(:table_name).having('COUNT(col1) > $n', n: 1).parse + assert_equal parsed, %(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1)) end + def test_select_and_having - parsed = Qx.select(:id, "name").from(:table_name).having("COUNT(col1) > $n", n: 1).and_having("SUM(col2) > $m", m: 2).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1) AND (SUM(col2) > 2)) + parsed = Qx.select(:id, 'name').from(:table_name).having('COUNT(col1) > $n', n: 1).and_having('SUM(col2) > $m', m: 2).parse + assert_equal parsed, %(SELECT id, name FROM table_name HAVING (COUNT(col1) > 1) AND (SUM(col2) > 2)) end def test_select_limit - parsed = Qx.select(:id, "name").from(:table_name).limit(10).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name LIMIT 10) + parsed = Qx.select(:id, 'name').from(:table_name).limit(10).parse + assert_equal parsed, %(SELECT id, name FROM table_name LIMIT 10) end + def test_select_offset - parsed = Qx.select(:id, "name").from(:table_name).offset(10).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name OFFSET 10) + parsed = Qx.select(:id, 'name').from(:table_name).offset(10).parse + assert_equal parsed, %(SELECT id, name FROM table_name OFFSET 10) end def test_select_join - parsed = Qx.select(:id, "name").from(:table_name).join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id) + parsed = Qx.select(:id, 'name').from(:table_name).join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse + assert_equal parsed, %(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id) end + def test_select_add_join - parsed = Qx.select(:id, "name").from(:table_name).join('assoc1', 'assoc1.table_name_id=table_name.id') - .add_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id JOIN assoc2 ON assoc2.table_name_id=table_name.id) + parsed = Qx.select(:id, 'name').from(:table_name).join('assoc1', 'assoc1.table_name_id=table_name.id') + .add_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse + assert_equal parsed, %(SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id JOIN assoc2 ON assoc2.table_name_id=table_name.id) end + def test_select_left_join - parsed = Qx.select(:id, "name").from(:table_name).left_join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id) + parsed = Qx.select(:id, 'name').from(:table_name).left_join(['assoc1', 'assoc1.table_name_id=table_name.id']).parse + assert_equal parsed, %(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id) end + def test_select_add_left_join - parsed = Qx.select(:id, "name").from(:table_name).left_join('assoc1', 'assoc1.table_name_id=table_name.id') - .add_left_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id LEFT JOIN assoc2 ON assoc2.table_name_id=table_name.id) + parsed = Qx.select(:id, 'name').from(:table_name).left_join('assoc1', 'assoc1.table_name_id=table_name.id') + .add_left_join(['assoc2', 'assoc2.table_name_id=table_name.id']).parse + assert_equal parsed, %(SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id LEFT JOIN assoc2 ON assoc2.table_name_id=table_name.id) end def test_select_where_subquery - parsed = Qx.select(:id, "name").from(:table_name).where("id IN ($ids)", ids: Qx.select("id").from("assoc")).parse - assert_equal parsed, %Q(SELECT id, name FROM table_name WHERE (id IN (SELECT id FROM assoc))) + parsed = Qx.select(:id, 'name').from(:table_name).where('id IN ($ids)', ids: Qx.select('id').from('assoc')).parse + assert_equal parsed, %(SELECT id, name FROM table_name WHERE (id IN (SELECT id FROM assoc))) end def test_select_join_subquery - parsed = Qx.select(:id).from(:table).join([Qx.select(:id).from(:assoc).as(:assoc), "assoc.table_id=table.id"]).parse - assert_equal parsed, %Q(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id) + parsed = Qx.select(:id).from(:table).join([Qx.select(:id).from(:assoc).as(:assoc), 'assoc.table_id=table.id']).parse + assert_equal parsed, %(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id) end def test_select_from_subquery parsed = Qx.select(:id).from(Qx.select(:id).from(:table).as(:table)).parse - assert_equal parsed, %Q(SELECT id FROM (SELECT id FROM table) AS "table") + assert_equal parsed, %(SELECT id FROM (SELECT id FROM table) AS "table") end def test_select_integration parsed = Qx.select(:id) - .from(:table) - .join([Qx.select(:id).from(:assoc).as(:assoc), 'assoc.table_id=table.id']) - .left_join(['lefty', 'lefty.table_id=table.id']) - .where('x = $n', n: 1) - .and_where('y = $n', n: 1) - .group_by(:x) - .order_by(:y) - .having('COUNT(x) > $n', n: 1) - .and_having('COUNT(y) > $n', n: 1) - .limit(10) - .offset(10) - .parse - assert_equal parsed, %Q(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id LEFT JOIN lefty ON lefty.table_id=table.id WHERE (x = 1) AND (y = 1) GROUP BY x HAVING (COUNT(x) > 1) AND (COUNT(y) > 1) ORDER BY y LIMIT 10 OFFSET 10) + .from(:table) + .join([Qx.select(:id).from(:assoc).as(:assoc), 'assoc.table_id=table.id']) + .left_join(['lefty', 'lefty.table_id=table.id']) + .where('x = $n', n: 1) + .and_where('y = $n', n: 1) + .group_by(:x) + .order_by(:y) + .having('COUNT(x) > $n', n: 1) + .and_having('COUNT(y) > $n', n: 1) + .limit(10) + .offset(10) + .parse + assert_equal parsed, %(SELECT id FROM table JOIN (SELECT id FROM assoc) AS "assoc" ON assoc.table_id=table.id LEFT JOIN lefty ON lefty.table_id=table.id WHERE (x = 1) AND (y = 1) GROUP BY x HAVING (COUNT(x) > 1) AND (COUNT(y) > 1) ORDER BY y LIMIT 10 OFFSET 10) end def test_insert_into_values_hash parsed = Qx.insert_into(:table_name).values(x: 1).parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x") VALUES (1)) + assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1)) end + def test_insert_into_values_hash_array - parsed = Qx.insert_into(:table_name).values([{x: 1}, {x: 2}]).parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x") VALUES (1), (2)) + parsed = Qx.insert_into(:table_name).values([{ x: 1 }, { x: 2 }]).parse + assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1), (2)) end + def test_insert_into_values_csv_style parsed = Qx.insert_into(:table_name).values([['x'], [1], [2]]).parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x") VALUES (1), (2)) + assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1), (2)) end + def test_insert_into_values_common_values - parsed = Qx.insert_into(:table_name).values([{x: 'bye'}, {x: 'hi'}]).common_values(z: 1).parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x", "z") VALUES ($Q$bye$Q$, 1), ($Q$hi$Q$, 1)) + parsed = Qx.insert_into(:table_name).values([{ x: 'bye' }, { x: 'hi' }]).common_values(z: 1).parse + assert_equal parsed, %(INSERT INTO "table_name" ("x", "z") VALUES ($Q$bye$Q$, 1), ($Q$hi$Q$, 1)) end + def test_insert_into_values_timestamps parsed = Qx.insert_into(:table_name).values(x: 1).ts.parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x", created_at, updated_at) VALUES (1, '#{Time.now.utc}', '#{Time.now.utc}')) + assert_equal parsed, %(INSERT INTO "table_name" ("x", created_at, updated_at) VALUES (1, '#{Time.now.utc}', '#{Time.now.utc}')) end + def test_insert_into_values_returning parsed = Qx.insert_into(:table_name).values(x: 1).returning('*').parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x") VALUES (1) RETURNING *) + assert_equal parsed, %(INSERT INTO "table_name" ("x") VALUES (1) RETURNING *) end + def test_insert_into_select - parsed = Qx.insert_into(:table_name, ['hi']).select('hi').from(:table2).where("x=y").parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("hi") SELECT hi FROM table2 WHERE (x=y)) + parsed = Qx.insert_into(:table_name, ['hi']).select('hi').from(:table2).where('x=y').parse + assert_equal parsed, %(INSERT INTO "table_name" ("hi") SELECT hi FROM table2 WHERE (x=y)) end def test_update_set - parsed = Qx.update(:table_name).set(x: 1).where("y = 2").parse - assert_equal parsed, %Q(UPDATE "table_name" SET "x" = 1 WHERE (y = 2)) + parsed = Qx.update(:table_name).set(x: 1).where('y = 2').parse + assert_equal parsed, %(UPDATE "table_name" SET "x" = 1 WHERE (y = 2)) end + def test_update_timestamps now = Time.now.utc - parsed = Qx.update(:table_name).set(x: 1).where("y = 2").timestamps.parse - assert_equal parsed, %Q(UPDATE "table_name" SET "x" = 1, updated_at = '#{now}' WHERE (y = 2)) + parsed = Qx.update(:table_name).set(x: 1).where('y = 2').timestamps.parse + assert_equal parsed, %(UPDATE "table_name" SET "x" = 1, updated_at = '#{now}' WHERE (y = 2)) end def test_update_on_conflict - Qx.update(:table_name).set(x: 1).where("y = 2").on_conflict(:nothing).parse - assert_equal parsed, %Q(UPDATE "table_name" SET "x" = 1 WHERE (y = 2) ON CONFLICT DO NOTHING) + Qx.update(:table_name).set(x: 1).where('y = 2').on_conflict(:nothing).parse + assert_equal parsed, %(UPDATE "table_name" SET "x" = 1 WHERE (y = 2) ON CONFLICT DO NOTHING) end def test_insert_timestamps now = Time.now.utc - parsed = Qx.insert_into(:table_name).values({x: 1}).ts.parse - assert_equal parsed, %Q(INSERT INTO "table_name" ("x", created_at, updated_at) VALUES (1, '#{now}', '#{now}')) + parsed = Qx.insert_into(:table_name).values(x: 1).ts.parse + assert_equal parsed, %(INSERT INTO "table_name" ("x", created_at, updated_at) VALUES (1, '#{now}', '#{now}')) end def test_delete_from parsed = Qx.delete_from(:table_name).where(x: 1).parse - assert_equal parsed, %Q(DELETE FROM "table_name" WHERE ("x" IN (1))) + assert_equal parsed, %(DELETE FROM "table_name" WHERE ("x" IN (1))) end def test_pagination parsed = Qx.select(:x).from(:y).paginate(4, 30).parse - assert_equal parsed, %Q(SELECT x FROM y LIMIT 30 OFFSET 90) + assert_equal parsed, %(SELECT x FROM y LIMIT 30 OFFSET 90) end def test_execute_string - result = Qx.execute("SELECT * FROM (VALUES ($x)) AS t", x: 'x') - assert_equal result, [{'column1' => 'x'}] + result = Qx.execute('SELECT * FROM (VALUES ($x)) AS t', x: 'x') + assert_equal result, [{ 'column1' => 'x' }] end + def test_execute_format_csv - result = Qx.execute("SELECT * FROM (VALUES ($x)) AS t", {x: 'x'}, {format: 'csv'}) + result = Qx.execute('SELECT * FROM (VALUES ($x)) AS t', { x: 'x' }, format: 'csv') assert_equal result, [['column1'], ['x']] end + def test_execute_on_instances result = Qx.insert_into(:users).values(id: 1, email: 'uzr@example.com').execute - result = Qx.execute(Qx.select("*").from(:users).limit(1)) - assert_equal result, [{'id' => 1, 'email' => 'uzr@example.com'}] + result = Qx.execute(Qx.select('*').from(:users).limit(1)) + assert_equal result, [{ 'id' => 1, 'email' => 'uzr@example.com' }] Qx.delete_from(:users).where(id: 1).execute end def test_explain - parsed = Qx.select("*").from("table_name").explain.parse - assert_equal parsed, %Q(EXPLAIN SELECT * FROM table_name) + parsed = Qx.select('*').from('table_name').explain.parse + assert_equal parsed, %(EXPLAIN SELECT * FROM table_name) end # Manually test this one for now def test_pp_select - pp = Qx.select("id, name").from("table_name").where(status: 'active').and_where(id: Qx.select("id").from("roles").where(name: "admin")).pp + pp = Qx.select('id, name').from('table_name').where(status: 'active').and_where(id: Qx.select('id').from('roles').where(name: 'admin')).pp pp2 = Qx.insert_into(:table_name).values([x: 1, y: 2]).pp pp3 = Qx.update(:table_name).set(x: 1, y: 2).where(z: 1, a: 22).pp pp_delete = Qx.delete_from(:table_name).where(id: 123).pp - puts "" - puts "--- pretty print" + puts '' + puts '--- pretty print' puts pp puts pp2 puts pp3 puts pp_delete - puts "---" + puts '---' end def test_to_json parsed = Qx.select(:id).from(:users).to_json(:t).parse - assert_equal parsed, %Q(SELECT array_to_json(array_agg(row_to_json(t))) FROM (SELECT id FROM users) AS "t") + assert_equal parsed, %(SELECT array_to_json(array_agg(row_to_json(t))) FROM (SELECT id FROM users) AS "t") end def test_to_json_nested definitions = Qx.select(:part_of_speech, :body) - .from(:definitions) - .where("word_id=words.id") - .order_by("position ASC") - .to_json(:ds) - .as("definitions") + .from(:definitions) + .where('word_id=words.id') + .order_by('position ASC') + .to_json(:ds) + .as('definitions') parsed = Qx.select(:text, :pronunciation, definitions) - .from(:words) - .where("text='autumn'") - .to_json(:ws) - .parse + .from(:words) + .where("text='autumn'") + .to_json(:ws) + .parse assert_equal parsed, "SELECT array_to_json(array_agg(row_to_json(ws))) FROM (SELECT text, pronunciation, (SELECT array_to_json(array_agg(row_to_json(ds))) FROM (SELECT part_of_speech, body FROM definitions WHERE (word_id=words.id) ORDER BY position ASC ) AS \"ds\") AS \"definitions\" FROM words WHERE (text='autumn')) AS \"ws\"" end def test_copy_csv_execution - data = {'id' => '1', 'email' => 'uzr@example.com'} + data = { 'id' => '1', 'email' => 'uzr@example.com' } filename = '/tmp/qx-test.csv' Qx.insert_into(:users).values(data).ex - copy = Qx.select("*").from("users").execute(copy_csv: filename) + copy = Qx.select('*').from('users').execute(copy_csv: filename) contents = File.open(filename, 'r').read - csv_data = contents.split("\n").map{|l| l.split(",")} + csv_data = contents.split("\n").map { |l| l.split(',') } headers = csv_data.first row = csv_data.last assert_equal data.keys, headers @@ -265,11 +284,8 @@ class QxTest < Minitest::Test end def test_remove_clause - expr = Qx.select("*").from("table").limit(1) + expr = Qx.select('*').from('table').limit(1) expr = expr.remove_clause('limit') - assert_equal "SELECT * FROM table", expr.parse + assert_equal 'SELECT * FROM table', expr.parse end - - - end diff --git a/lib/audit.rb b/lib/audit.rb index a7ea242e..c2cd87a8 100644 --- a/lib/audit.rb +++ b/lib/audit.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Audit - # Given a list of pairs of nonprofit ids and stripe_account_ids (eg [[4341, 'acct_arst'], [3624, 'acct_arst']]) # Find all their available balances on both stripe and CC # Give all the ones that dont match up with the difference @@ -23,9 +24,9 @@ module Audit fees = p.payments.sum(:fee_total) net = p.payments.sum(:net_amount) puts [ - [p.gross_amount, p.fee_total, p.net_amount].join(", ") + " -- payout columns", - [gross, fees, net].join(", ") + " -- summed from payments", - [p.gross_amount - gross, p.fee_total - fees, p.net_amount - net].join(", ") + " -- differences" + [p.gross_amount, p.fee_total, p.net_amount].join(', ') + ' -- payout columns', + [gross, fees, net].join(', ') + ' -- summed from payments', + [p.gross_amount - gross, p.fee_total - fees, p.net_amount - net].join(', ') + ' -- differences' ].join("\n") end @@ -36,20 +37,21 @@ module Audit starting_after = nil transfers = [] loop do - new_transfers = Stripe::Transfer.all({limit: 100, starting_after: starting_after, destination: acct}).data + new_transfers = Stripe::Transfer.all(limit: 100, starting_after: starting_after, destination: acct).data break if new_transfers.empty? + transfers += new_transfers starting_after = new_transfers.last.id end ActiveRecord::Base.logger = logger - return transfers + transfers end # Given a list of Stripe transaction objects, see if any are missing on CommitChange def self.find_missing_charges(transfers) transfers - .map{|t| [t.source_transaction, t.amount]} - .select{|id, amount| Charge.where(stripe_charge_id: id, amount: amount).empty?} + .map { |t| [t.source_transaction, t.amount] } + .select { |id, amount| Charge.where(stripe_charge_id: id, amount: amount).empty? } end # Audit some basic balances for a nonprofit with those on Stripe @@ -58,7 +60,7 @@ module Audit puts "Stripe Dashboard: https://dashboard.stripe.com/#{np.stripe_account_id}" puts "CC Payments: https://commitchange.com/nonprofits/#{id}/payments" puts "CC Payouts: https://commitchange.com/nonprofits/#{id}/payouts" - + begin stripe_balances = Stripe::Balance.retrieve(stripe_account: np.stripe_account_id) available = stripe_balances['available'].first['amount'] @@ -74,36 +76,35 @@ module Audit cc_net: bal['net_amount'], diff: bal['net_amount'] - (available + pending) } - return data + data end - # Get the total gross, net + # Get the total gross, net # Pretty much duped from QueryPayments def self.np_balances(np_id) payment_ids_expr = Qx.select('DISTINCT payments.id') - .from(:payments) - .left_join( - [:charges, 'charges.payment_id=payments.id'], - [:refunds, 'refunds.payment_id=payments.id'], - [:disputes, 'disputes.payment_id=payments.id'] - ) - .where('payments.nonprofit_id=$id', id: np_id) - .and_where("refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL") - .and_where(%Q( + .from(:payments) + .left_join( + [:charges, 'charges.payment_id=payments.id'], + [:refunds, 'refunds.payment_id=payments.id'], + [:disputes, 'disputes.payment_id=payments.id'] + ) + .where('payments.nonprofit_id=$id', id: np_id) + .and_where('refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL') + .and_where(%( (refunds.payment_id IS NOT NULL AND (refunds.disbursed IS NULL OR refunds.disbursed='f')) OR (charges.status='available' OR charges.status='pending') OR (disputes.status='lost') )) - return Qx.select( - 'coalesce(SUM(payments.gross_amount), 0) AS gross_amount', - 'coalesce(SUM(payments.fee_total), 0) AS fee_total', - 'coalesce(SUM(payments.net_amount), 0) AS net_amount', - 'COUNT(payments.*) AS count' - ) + Qx.select( + 'coalesce(SUM(payments.gross_amount), 0) AS gross_amount', + 'coalesce(SUM(payments.fee_total), 0) AS fee_total', + 'coalesce(SUM(payments.net_amount), 0) AS net_amount', + 'COUNT(payments.*) AS count' + ) .from(:payments) - .where("payments.id IN ($ids)", ids: payment_ids_expr) + .where('payments.id IN ($ids)', ids: payment_ids_expr) .execute .first end - end diff --git a/lib/calculate/calculate_fees.rb b/lib/calculate/calculate_fees.rb index dc67ce49..846d2baf 100644 --- a/lib/calculate/calculate_fees.rb +++ b/lib/calculate/calculate_fees.rb @@ -1,16 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CalculateFees BaseFeeRate = 0.022 # 2.2% PerTransaction = 30 # 30 cents - def self.for_single_amount(amount, platform_fee=0.0) - ParamValidation.new({fee: platform_fee, amount: amount}, { - amount: {min: 0, is_integer: true}, - fee: {min: 0.0, is_float: true} - }) + def self.for_single_amount(amount, platform_fee = 0.0) + ParamValidation.new({ fee: platform_fee, amount: amount }, + amount: { min: 0, is_integer: true }, + fee: { min: 0.0, is_float: true }) fee = BaseFeeRate + platform_fee (amount * fee).ceil.to_i + PerTransaction end - end - diff --git a/lib/calculate/calculate_suggested_amounts.rb b/lib/calculate/calculate_suggested_amounts.rb index d4af6fab..4c8eaec8 100644 --- a/lib/calculate/calculate_suggested_amounts.rb +++ b/lib/calculate/calculate_suggested_amounts.rb @@ -1,50 +1,48 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'numeric' module CalculateSuggestedAmounts MIN = 25 - MAX = 100000000 - BRACKETS = [{range: MIN...1000, delta:100}, - {range: 1000...5000, delta: 500}, - {range: 5000...MAX, delta: 2500}] + MAX = 100_000_000 + BRACKETS = [{ range: MIN...1000, delta: 100 }, + { range: 1000...5000, delta: 500 }, + { range: 5000...MAX, delta: 2500 }].freeze # Calculates a set of suggested donation amounts based upon our internal special algorithm # This is most useful for suggesting amounts a recurring donor could change to # @return [Array] suggested amounts for your donation # @param [Number] amount the amount in cents to start from def self.calculate(amount) - ParamValidation.new({amount: amount}, amount: {required:true, is_a: Numeric, min: MIN, max:MAX }) + ParamValidation.new({ amount: amount }, amount: { required: true, is_a: Numeric, min: MIN, max: MAX }) result = [] step_down_val = step_down_value(amount) - unless step_down_val.nil? - result.push(step_down_val) - end + result.push(step_down_val) unless step_down_val.nil? higher_amounts = [] - while (higher_amounts.empty? || (higher_amounts.length < 3 && higher_amounts.last() != nil)) + while higher_amounts.empty? || (higher_amounts.length < 3 && !higher_amounts.last.nil?) if higher_amounts.empty? higher_amounts.push(step_up_value(amount)) else higher_amounts.push(step_up_value(higher_amounts.last)) end end - result.concat(higher_amounts.reject {|i| i.nil?}) + result.concat(higher_amounts.reject(&:nil?)) end def self.step_down_value(amount) - initial_bracket = get_bracket_by_amount(amount) - #check_floor_for_delta + # check_floor_for_delta delta_floor = amount.floor_for_delta(initial_bracket[:delta]) - #not on a delta, just send a floor - if (delta_floor != amount) + # not on a delta, just send a floor + if delta_floor != amount return delta_floor < MIN ? nil : delta_floor end - potential_lower_amount = amount - initial_bracket[:delta] # is potential_lower_amount < our MIN? if so, return nil @@ -52,30 +50,25 @@ module CalculateSuggestedAmounts new_bracket = get_bracket_by_amount(potential_lower_amount) - #if in same bracket, potential_lower_amount is our step_down_value + # if in same bracket, potential_lower_amount is our step_down_value - if initial_bracket == new_bracket - return potential_lower_amount - end + return potential_lower_amount if initial_bracket == new_bracket - #we're going to step down by our new bracket value then - return amount - new_bracket[:delta] + # we're going to step down by our new bracket value then + amount - new_bracket[:delta] end - def self.step_up_value(amount) - bracket = get_bracket_by_amount(amount) - #check_ceil_for_delta + # check_ceil_for_delta delta_ceil = amount.ceil_for_delta(bracket[:delta]) - #not on a delta, just send a ceil - if (delta_ceil != amount) + # not on a delta, just send a ceil + if delta_ceil != amount return delta_ceil >= MAX ? nil : delta_ceil end - potential_higher_amount = amount + bracket[:delta] # is potential_lower_amount < our MIN? if so, return nil @@ -84,10 +77,7 @@ module CalculateSuggestedAmounts potential_higher_amount end - - - def self.get_bracket_by_amount(amount) BRACKETS.select { |i| i[:range].cover?(amount) }.first end -end \ No newline at end of file +end diff --git a/lib/cancel_billing_subscription.rb b/lib/cancel_billing_subscription.rb index 75ea72c0..ef33f55c 100644 --- a/lib/cancel_billing_subscription.rb +++ b/lib/cancel_billing_subscription.rb @@ -1,19 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CancelBillingSubscription - # @param [Nonprofit] nonprofit # @return [BillingSubscription] new billing subscription for the nonprofit - def self.with_stripe(nonprofit) + def self.with_stripe(nonprofit) begin - ParamValidation.new({nonprofit: nonprofit}, { - nonprofit: {required: true, is_a: Nonprofit} - }) + ParamValidation.new({ nonprofit: nonprofit }, + nonprofit: { required: true, is_a: Nonprofit }) rescue ParamValidation::ValidationError => e - return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} + return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } end - np_card = nonprofit.active_card - billing_subscription = nonprofit.billing_subscription - return {json:{error: 'We don\'t have a subscription for your non-profit. Please contact support.'}, status: :unprocessable_entity} if np_card.nil? || billing_subscription.nil? # stripe_customer_id on Card object + np_card = nonprofit.active_card + billing_subscription = nonprofit.billing_subscription + return { json: { error: 'We don\'t have a subscription for your non-profit. Please contact support.' }, status: :unprocessable_entity } if np_card.nil? || billing_subscription.nil? # stripe_customer_id on Card object # Cancel and delete the subscription on Stripe begin @@ -21,15 +21,15 @@ module CancelBillingSubscription stripe_subscription = customer.subscriptions.retrieve(billing_subscription.stripe_subscription_id) s = stripe_subscription.delete(at_period_end: false) rescue Stripe::StripeError => e - return {json: {error: "Oops! There was an error processing your subscription cancellation. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error processing your subscription cancellation. Error: #{e}" }, status: :unprocessable_entity } end billing_plan_id = Settings.default_bp.id - billing_subscription.update_attributes({ + billing_subscription.update_attributes( billing_plan_id: billing_plan_id, status: 'active' - }) + ) - return {json:{}, status: :ok} - end + { json: {}, status: :ok } + end end diff --git a/lib/chunked_uploader/s3.rb b/lib/chunked_uploader/s3.rb index 579c6bac..9ef69015 100644 --- a/lib/chunked_uploader/s3.rb +++ b/lib/chunked_uploader/s3.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ChunkedUploader class S3 @@ -9,18 +11,18 @@ module ChunkedUploader # @param [Enumerable] chunk_enum an enumerable of strings. # @param [String] path the path to the object on your S3 bucket # @returns the url to your uploaded file - def self.upload(path,chunk_enum, metadata={}) + def self.upload(path, chunk_enum, metadata = {}) s3 = AWS::S3.new bucket = s3.buckets[S3_BUCKET_NAME] object = bucket.objects[path] io = StringIO.new('', 'w') - content_type = metadata[:content_type] ? metadata[:content_type] : nil - content_disposition = metadata[:content_disposition] ? metadata[:content_disposition] : nil + content_type = metadata[:content_type] || nil + content_disposition = metadata[:content_disposition] || nil begin - object.multipart_upload(:acl => :public_read, :content_type => content_type, content_disposition: content_disposition) do |upload| - chunk_enum.each do |chunk| + object.multipart_upload(acl: :public_read, content_type: content_type, content_disposition: content_disposition) do |upload| + chunk_enum.each do |chunk| export_returned = io.write(chunk) - if (io.size >= MINIMUMBUFFER_SIZE) + if io.size >= MINIMUMBUFFER_SIZE upload.add_part(io.string) io.reopen('') end @@ -28,10 +30,10 @@ module ChunkedUploader upload.add_part(io.string) end object.public_url.to_s - rescue => e + rescue StandardError => e io.close raise e end end end -end \ No newline at end of file +end diff --git a/lib/construct/construct_billing_subscription.rb b/lib/construct/construct_billing_subscription.rb index 51941ed4..06627966 100644 --- a/lib/construct/construct_billing_subscription.rb +++ b/lib/construct/construct_billing_subscription.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'stripe' require 'active_support/core_ext' module ConstructBillingSubscription + def self.with_stripe(np, billing_plan) + raise ArgumentError, 'Billing plan not found' if billing_plan.nil? - def self.with_stripe(np, billing_plan) - raise ArgumentError.new("Billing plan not found") if billing_plan.nil? - trial_end = QueryBillingSubscriptions.currently_in_trial?(np.id) ? (np.created_at + 15.days).to_i : nil - customer = Stripe::Customer.retrieve np.active_card.stripe_customer_id - stripe_subscription = customer.subscriptions.create({ - plan: billing_plan.stripe_plan_id, - trial_end: trial_end - }) - return { - billing_plan_id: billing_plan.id, - stripe_subscription_id: stripe_subscription.id, - status: stripe_subscription.status - } - end - + trial_end = QueryBillingSubscriptions.currently_in_trial?(np.id) ? (np.created_at + 15.days).to_i : nil + customer = Stripe::Customer.retrieve np.active_card.stripe_customer_id + stripe_subscription = customer.subscriptions.create( + plan: billing_plan.stripe_plan_id, + trial_end: trial_end + ) + { + billing_plan_id: billing_plan.id, + stripe_subscription_id: stripe_subscription.id, + status: stripe_subscription.status + } + end end diff --git a/lib/construct/construct_nonprofit.rb b/lib/construct/construct_nonprofit.rb index 7fa5d263..b06bdfae 100644 --- a/lib/construct/construct_nonprofit.rb +++ b/lib/construct/construct_nonprofit.rb @@ -1,17 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'create/stripe/create_stripe_account' module ConstructNonprofit - - def self.construct(user, h) - h[:verification_status] = 'unverified' - h[:published] = true - h[:statement] = h[:name][0..16] - h.except!(:website) if h[:website].blank? - stripe_acct = CreateStripeAccount.for_nonprofit(user, h) - h[:stripe_account_id] = stripe_acct.id - return h - end - + def self.construct(user, h) + h[:verification_status] = 'unverified' + h[:published] = true + h[:statement] = h[:name][0..16] + h.except!(:website) if h[:website].blank? + stripe_acct = CreateStripeAccount.for_nonprofit(user, h) + h[:stripe_account_id] = stripe_acct.id + h + end end - diff --git a/lib/controllers/campaign_helper.rb b/lib/controllers/campaign_helper.rb index d7a568a0..50b64faf 100644 --- a/lib/controllers/campaign_helper.rb +++ b/lib/controllers/campaign_helper.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Controllers::CampaignHelper - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper -private + private - def current_campaign - @campaign ||= FetchCampaign.with_params params, current_nonprofit - raise ActionController::RoutingError.new "Campaign not found" if @campaign.nil? - return @campaign - end + def current_campaign + @campaign ||= FetchCampaign.with_params params, current_nonprofit + raise ActionController::RoutingError, 'Campaign not found' if @campaign.nil? - def current_campaign_editor? - !params[:preview] && (current_nonprofit_user? || current_role?(:campaign_editor, current_campaign.id) || current_role?(:super_admin)) - end + @campaign + end - def authenticate_campaign_editor! - unless current_campaign_editor? - block_with_sign_in 'You need to be a campaign editor to do that.' - end - end + def current_campaign_editor? + !params[:preview] && (current_nonprofit_user? || current_role?(:campaign_editor, current_campaign.id) || current_role?(:super_admin)) + end + def authenticate_campaign_editor! + unless current_campaign_editor? + block_with_sign_in 'You need to be a campaign editor to do that.' + end + end end diff --git a/lib/controllers/event_helper.rb b/lib/controllers/event_helper.rb index a58c778f..7125436a 100644 --- a/lib/controllers/event_helper.rb +++ b/lib/controllers/event_helper.rb @@ -1,27 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Controllers::EventHelper - include Controllers::NonprofitHelper + include Controllers::NonprofitHelper -private + private - def current_event_admin? - current_nonprofit_admin? - end + def current_event_admin? + current_nonprofit_admin? + end - def current_event_editor? - !params[:preview] && (current_nonprofit_user? || current_role?(:event_editor, current_event.id) || current_role?(:super_admin)) - end + def current_event_editor? + !params[:preview] && (current_nonprofit_user? || current_role?(:event_editor, current_event.id) || current_role?(:super_admin)) + end - def authenticate_event_editor! - unless current_event_editor? - block_with_sign_in 'You need to be the event organizer or a nonprofit administrator before doing that.' - end - end + def authenticate_event_editor! + unless current_event_editor? + block_with_sign_in 'You need to be the event organizer or a nonprofit administrator before doing that.' + end + end - def current_event - @event ||= FetchEvent.with_params params, current_nonprofit - raise ActionController::RoutingError.new "Event not found" if @event.nil? - return @event - end + def current_event + @event ||= FetchEvent.with_params params, current_nonprofit + raise ActionController::RoutingError, 'Event not found' if @event.nil? + @event + end end diff --git a/lib/controllers/nonprofit_helper.rb b/lib/controllers/nonprofit_helper.rb index a62cf078..2da72bb5 100644 --- a/lib/controllers/nonprofit_helper.rb +++ b/lib/controllers/nonprofit_helper.rb @@ -1,59 +1,59 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Controllers::NonprofitHelper + private -private + def authenticate_nonprofit_user! + block_with_sign_in 'Please sign in' unless current_nonprofit_user? + end - def authenticate_nonprofit_user! - unless current_nonprofit_user? - block_with_sign_in 'Please sign in' - end - end + def authenticate_nonprofit_admin! + block_with_sign_in 'Please sign in' unless current_nonprofit_admin? + end - def authenticate_nonprofit_admin! - unless current_nonprofit_admin? - block_with_sign_in 'Please sign in' - end - end + def authenticate_min_nonprofit_plan(plan_tier) + unless current_nonprofit_user? && current_plan_tier >= plan_tier + block_with_sign_in 'Please sign in' + end + end - def authenticate_min_nonprofit_plan plan_tier - unless current_nonprofit_user? && current_plan_tier >= plan_tier - block_with_sign_in 'Please sign in' - end - end - - def current_nonprofit_user? + def current_nonprofit_user? return false if params[:preview] - return false unless current_nonprofit_without_exception - @current_user_role ||= current_role?([:nonprofit_admin, :nonprofit_associate], current_nonprofit_without_exception.id) || current_role?(:super_admin) - end + return false unless current_nonprofit_without_exception - def current_nonprofit_admin? - return false if !current_user || current_user.roles.empty? - @current_admin_role ||= current_role?(:nonprofit_admin, current_nonprofit.id) || current_role?(:super_admin) - end + @current_user_role ||= current_role?(%i[nonprofit_admin nonprofit_associate], current_nonprofit_without_exception.id) || current_role?(:super_admin) + end - def current_nonprofit - @nonprofit = current_nonprofit_without_exception - raise ActionController::RoutingError.new "Nonprofit not found" if @nonprofit.nil? - return @nonprofit - end + def current_nonprofit_admin? + return false if !current_user || current_user.roles.empty? - def current_nonprofit_without_exception - key = "current_nonprofit_#{current_user_id}_params_#{[params[:state_code], params[:city], params[:name], params[:nonprofit_id], params[:id]].join("_")}" + @current_admin_role ||= current_role?(:nonprofit_admin, current_nonprofit.id) || current_role?(:super_admin) + end + + def current_nonprofit + @nonprofit = current_nonprofit_without_exception + raise ActionController::RoutingError, 'Nonprofit not found' if @nonprofit.nil? + + @nonprofit + end + + def current_nonprofit_without_exception + key = "current_nonprofit_#{current_user_id}_params_#{[params[:state_code], params[:city], params[:name], params[:nonprofit_id], params[:id]].join('_')}" FetchNonprofit.with_params params, administered_nonprofit - end + end - def donation_stub - return current_nonprofit_without_exception.donations.last unless current_nonprofit_without_exception.donations.empty? - OpenStruct.new( - amount: 2000, - created_at: Time.zone.now, - nonprofit: current_nonprofit_without_exception, - campaign: nil, - designation: "Donor's designation here", - dedication: "Donor's dedication here", - id: 1 - ) - end + def donation_stub + return current_nonprofit_without_exception.donations.last unless current_nonprofit_without_exception.donations.empty? + OpenStruct.new( + amount: 2000, + created_at: Time.zone.now, + nonprofit: current_nonprofit_without_exception, + campaign: nil, + designation: "Donor's designation here", + dedication: "Donor's dedication here", + id: 1 + ) + end end diff --git a/lib/copy_naming_algorithm.rb b/lib/copy_naming_algorithm.rb index 729c7eba..ab8373d1 100644 --- a/lib/copy_naming_algorithm.rb +++ b/lib/copy_naming_algorithm.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CopyNamingAlgorithm DEFAULT_MAX_LENGTH = 255 DEFAULT_MAX_COPIES = 255 - DEFAULT_SEPARATOR_BEFORE_COPY_NUMBER = "_" + DEFAULT_SEPARATOR_BEFORE_COPY_NUMBER = '_' def copy_addition raise NotImplementedError @@ -20,7 +22,7 @@ class CopyNamingAlgorithm DEFAULT_MAX_COPIES end - def get_already_used_name_entities(base_name) + def get_already_used_name_entities(_base_name) raise NotImplementedError end @@ -30,36 +32,35 @@ class CopyNamingAlgorithm def create_copy_name(name_to_copy) # remove copy addition and number - base_name = name_to_copy.gsub(/#{Regexp.quote(self.copy_addition)}(#{Regexp.quote(separator_before_copy_number)}\d+)?\z/,'') - name_entities_to_check_against = get_already_used_name_entities(base_name).collect{|entity| self.get_name_for_entity(entity)}.to_a - (0..max_copies-1).each {|copy_num| + base_name = name_to_copy.gsub(/#{Regexp.quote(copy_addition)}(#{Regexp.quote(separator_before_copy_number)}\d+)?\z/, '') + name_entities_to_check_against = get_already_used_name_entities(base_name).collect { |entity| get_name_for_entity(entity) }.to_a + (0..max_copies - 1).each do |copy_num| name_to_test = generate_name(base_name, copy_num) - if (name_entities_to_check_against.none? {|entity_name| entity_name == name_to_test}) + if name_entities_to_check_against.none? { |entity_name| entity_name == name_to_test } return name_to_test end - } + end - raise UnableToCreateNameCopyError.new("It's not possible to generate a UNIQUE name using name_to_copy: #{name_to_copy} copy_addition: #{self.copy_addition} separator_before_copy_number: #{self.separator_before_copy_number} max_copy_num: #{self.max_copies} max_length: #{self.max_length}") + raise UnableToCreateNameCopyError, "It's not possible to generate a UNIQUE name using name_to_copy: #{name_to_copy} copy_addition: #{copy_addition} separator_before_copy_number: #{separator_before_copy_number} max_copy_num: #{max_copies} max_length: #{max_length}" end def generate_name(name_to_copy, copy_num) - what_to_add = self.copy_addition + self.separator_before_copy_number + generate_copy_number(copy_num) + what_to_add = copy_addition + separator_before_copy_number + generate_copy_number(copy_num) # is what_to_add longer than max length? If so, it's not possible to create a copy - if (what_to_add.length > self.max_length) - raise UnableToCreateNameCopyError.new("It's not possible to generate a name using name_to_copy: #{name_to_copy} copy_addition: #{self.copy_addition} separator_before_copy_number: #{self.separator_before_copy_number} copy_num: #{copy_num} max_length: #{self.max_length}") + if what_to_add.length > max_length + raise UnableToCreateNameCopyError, "It's not possible to generate a name using name_to_copy: #{name_to_copy} copy_addition: #{copy_addition} separator_before_copy_number: #{separator_before_copy_number} copy_num: #{copy_num} max_length: #{max_length}" end - max_length_for_name_to_copy = self.max_length - what_to_add.length - name_to_copy[0..max_length_for_name_to_copy-1] + what_to_add + + max_length_for_name_to_copy = max_length - what_to_add.length + name_to_copy[0..max_length_for_name_to_copy - 1] + what_to_add end def generate_copy_number(unprefixed_copy_number) - number_of_digits = Math.log10(self.max_copies).floor + 1 - "%0#{number_of_digits}d" % unprefixed_copy_number + number_of_digits = Math.log10(max_copies).floor + 1 + format("%0#{number_of_digits}d", unprefixed_copy_number) end - end class UnableToCreateNameCopyError < ArgumentError - -end \ No newline at end of file +end diff --git a/lib/create/create_campaign.rb b/lib/create/create_campaign.rb index 7233d661..4a7f854c 100644 --- a/lib/create/create_campaign.rb +++ b/lib/create/create_campaign.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateCampaign CAMPAIGN_NAME_LENGTH_LIMIT = 60 - # @return [Object] a json object for historical purposes def self.create(params, nonprofit) Time.use_zone(nonprofit.timezone || 'UTC') do @@ -12,22 +13,20 @@ module CreateCampaign if !params[:campaign][:parent_campaign_id] campaign = nonprofit.campaigns.create params[:campaign] - #do notifications + # do notifications user = campaign.profile.user Role.create(name: :campaign_editor, user_id: user.id, host: self) CampaignMailer.delay.creation_followup(self) - NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, self.nonprofit_id) + NonprofitAdminMailer.delay.supporter_fundraiser(self) unless QueryRoles.is_nonprofit_user?(user.id, nonprofit_id) return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty? + return campaign.as_json - #json_saved campaign, 'Campaign created! Well done.' + # json_saved campaign, 'Campaign created! Well done.' else profile_id = params[:campaign][:profile_id] Profile.find(profile_id).update_attributes params[:profile] return CreatePeerToPeerCampaign.create(params[:campaign], profile_id) end end - - - -end \ No newline at end of file +end diff --git a/lib/create/create_campaign_gift.rb b/lib/create/create_campaign_gift.rb index 17c15bbf..c1343333 100644 --- a/lib/create/create_campaign_gift.rb +++ b/lib/create/create_campaign_gift.rb @@ -1,78 +1,77 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateCampaignGift - # @param [Hash] params - # * campaign_gift_option_id - # * donation_id - def self.create(params) - ParamValidation.new(params, { - :campaign_gift_option_id => { - :required => true, - :is_integer => true - }, - :donation_id => { - :required => true, - :is_integer => true - } - }) + # @param [Hash] params + # * campaign_gift_option_id + # * donation_id + def self.create(params) + ParamValidation.new(params, + campaign_gift_option_id: { + required: true, + is_integer: true + }, + donation_id: { + required: true, + is_integer: true + }) - donation = Donation.includes(:nonprofit).includes(:supporter).includes(:recurring_donation).includes(:campaign_gifts).where('id = ?', params[:donation_id]).first - unless donation - raise ParamValidation::ValidationError.new("#{params[:donation_id]} is not a valid donation id.", {:key => :donation_id}) - end + donation = Donation.includes(:nonprofit).includes(:supporter).includes(:recurring_donation).includes(:campaign_gifts).where('id = ?', params[:donation_id]).first + unless donation + raise ParamValidation::ValidationError.new("#{params[:donation_id]} is not a valid donation id.", key: :donation_id) + end - campaign_gift_option = CampaignGiftOption.includes(:campaign).where('id = ?', params[:campaign_gift_option_id]).first - unless campaign_gift_option - raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not a valid campaign gift option", {:key => :campaign_gift_option_id}) - end + campaign_gift_option = CampaignGiftOption.includes(:campaign).where('id = ?', params[:campaign_gift_option_id]).first + unless campaign_gift_option + raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not a valid campaign gift option", key: :campaign_gift_option_id) + end - #does donation already have a campaign_gift - if (donation.campaign_gifts.any?) - raise ParamValidation::ValidationError.new("#{params[:donation_id]} already has at least one associated campaign gift", :key => :donation_id) - end + # does donation already have a campaign_gift + if donation.campaign_gifts.any? + raise ParamValidation::ValidationError.new("#{params[:donation_id]} already has at least one associated campaign gift", key: :donation_id) + end - if (donation.campaign != campaign_gift_option.campaign) - raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not for the same campaign as donation #{params[:donation_id]}", {:key => :campaign_gift_option_id}) - end + if donation.campaign != campaign_gift_option.campaign + raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} is not for the same campaign as donation #{params[:donation_id]}", key: :campaign_gift_option_id) + end - if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0)) - # it's a recurring_donation. Is it enough? for the gift level? - unless donation.recurring_donation.amount == (campaign_gift_option.amount_recurring) - AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) - raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a recurring donation of #{campaign_gift_option.amount_recurring} for donation #{donation.id}", {:key => :campaign_gift_option_id}) - end - else - unless donation.amount == (campaign_gift_option.amount_one_time) - AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) - raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a donation of #{campaign_gift_option.amount_one_time} for donation #{donation.id}", {:key => :campaign_gift_option_id}) - end - end + if !donation.recurring_donation.nil? && (!campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0) + # it's a recurring_donation. Is it enough? for the gift level? + unless donation.recurring_donation.amount == campaign_gift_option.amount_recurring + AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) + raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a recurring donation of #{campaign_gift_option.amount_recurring} for donation #{donation.id}", key: :campaign_gift_option_id) + end + else + unless donation.amount == campaign_gift_option.amount_one_time + AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) + raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a donation of #{campaign_gift_option.amount_one_time} for donation #{donation.id}", key: :campaign_gift_option_id) + end + end - Qx.transaction do - # are any gifts available? - if campaign_gift_option.quantity.nil? || campaign_gift_option.quantity.zero?|| campaign_gift_option.total_gifts < campaign_gift_option.quantity - gift = CampaignGift.new params - gift.save! - return gift - end - end - AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) - raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} has no more inventory", {:key => :campaign_gift_option_id}) - - end - - def self.validate_campaign_gift(cg) - donation = cg.donation - campaign_gift_option = cg.campaign_gift_option - if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0)) - # it's a recurring_donation. Is it enough? for the gift level? - unless donation.recurring_donation.amount == (campaign_gift_option.amount_recurring) - raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring}", {:key => :campaign_gift_option_id}) - end - else - unless donation.amount == (campaign_gift_option.amount_one_time) - raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a donation of at least #{campaign_gift_option.amount_one_time}", {:key => :campaign_gift_option_id}) - end - end - end + Qx.transaction do + # are any gifts available? + if campaign_gift_option.quantity.nil? || campaign_gift_option.quantity.zero? || campaign_gift_option.total_gifts < campaign_gift_option.quantity + gift = CampaignGift.new params + gift.save! + return gift + end + end + AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) + raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} has no more inventory", key: :campaign_gift_option_id) + end + def self.validate_campaign_gift(cg) + donation = cg.donation + campaign_gift_option = cg.campaign_gift_option + if !donation.recurring_donation.nil? && (!campaign_gift_option.amount_recurring.nil? && campaign_gift_option.amount_recurring > 0) + # it's a recurring_donation. Is it enough? for the gift level? + unless donation.recurring_donation.amount == campaign_gift_option.amount_recurring + raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring}", key: :campaign_gift_option_id) + end + else + unless donation.amount == campaign_gift_option.amount_one_time + raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a donation of at least #{campaign_gift_option.amount_one_time}", key: :campaign_gift_option_id) + end + end + end end diff --git a/lib/create/create_campaign_gift_option.rb b/lib/create/create_campaign_gift_option.rb index 98ca146b..ae162e03 100644 --- a/lib/create/create_campaign_gift_option.rb +++ b/lib/create/create_campaign_gift_option.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateCampaignGiftOption - - def self.create campaign, params - gift_option = campaign.campaign_gift_options.build params - gift_option.save - return gift_option - end - + def self.create(campaign, params) + gift_option = campaign.campaign_gift_options.build params + gift_option.save + gift_option + end end diff --git a/lib/create/create_custom_field_join.rb b/lib/create/create_custom_field_join.rb index 55ebc38c..6f4e42ce 100644 --- a/lib/create/create_custom_field_join.rb +++ b/lib/create/create_custom_field_join.rb @@ -1,39 +1,38 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateCustomFieldJoin + def self.create(supporter, _profile_id, params) + custom_field = supporter.custom_field_joins.create(params) + custom_field + end - def self.create(supporter, profile_id, params) - custom_field = supporter.custom_field_joins.create(params) - return custom_field - end + # In the future, this should create an activity feed entry - # In the future, this should create an activity feed entry + # @param [Array] custom_fields Hash with following keys: + # * custom_field_master_id [Integer] for the key corresponding to custom_field_master_id + # * value [Object] the expected value of the field. If this key is an empty string, we remove the custom_field - # @param [Array] custom_fields Hash with following keys: - # * custom_field_master_id [Integer] for the key corresponding to custom_field_master_id - # * value [Object] the expected value of the field. If this key is an empty string, we remove the custom_field - - def self.modify(np, user, supporter_ids, custom_fields) - return if supporter_ids.nil? || supporter_ids.empty? - return if custom_fields.nil? || custom_fields.empty? - supporter_ids.each do |sid| - supporter = np.supporters.find(sid) - custom_fields.each do |custom_field| - existing = supporter.custom_field_joins.find_by_custom_field_master_id(custom_field[:custom_field_master_id]) - if existing - existing.update_attributes({ - custom_field_master_id: custom_field[:custom_field_master_id], - value: custom_field[:value] - }) - else - self.create(supporter, user.profile.id, { - custom_field_master_id: custom_field[:custom_field_master_id], - value: custom_field[:value] - }) - end - end - end - return np - end + def self.modify(np, user, supporter_ids, custom_fields) + return if supporter_ids.nil? || supporter_ids.empty? + return if custom_fields.nil? || custom_fields.empty? + supporter_ids.each do |sid| + supporter = np.supporters.find(sid) + custom_fields.each do |custom_field| + existing = supporter.custom_field_joins.find_by_custom_field_master_id(custom_field[:custom_field_master_id]) + if existing + existing.update_attributes( + custom_field_master_id: custom_field[:custom_field_master_id], + value: custom_field[:value] + ) + else + create(supporter, user.profile.id, + custom_field_master_id: custom_field[:custom_field_master_id], + value: custom_field[:value]) + end + end + end + np + end end - diff --git a/lib/create/create_custom_field_master.rb b/lib/create/create_custom_field_master.rb index decc7ce6..470f5aed 100644 --- a/lib/create/create_custom_field_master.rb +++ b/lib/create/create_custom_field_master.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateCustomFieldMaster - - def self.create(nonprofit, params) - custom_field_master = nonprofit.custom_field_masters.create(params) - return custom_field_master - end + def self.create(nonprofit, params) + custom_field_master = nonprofit.custom_field_masters.create(params) + custom_field_master + end end diff --git a/lib/create/create_peer_to_peer_campaign.rb b/lib/create/create_peer_to_peer_campaign.rb index 032de0ab..91d997ca 100644 --- a/lib/create/create_peer_to_peer_campaign.rb +++ b/lib/create/create_peer_to_peer_campaign.rb @@ -1,14 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreatePeerToPeerCampaign def self.create(campaign_params, profile_id) begin - parent_campaign = Campaign.find(campaign_params[:parent_campaign_id]) - + parent_campaign = Campaign.find(campaign_params[:parent_campaign_id]) rescue ActiveRecord::RecordNotFound return { errors: { parent_campaign_id: 'not found' } }.as_json end - p2p_params = campaign_params.except(:nonprofit_id, :summary,:goal_amount) + p2p_params = campaign_params.except(:nonprofit_id, :summary, :goal_amount) p2p_params.merge!(parent_campaign.child_params) profile = Profile.find(profile_id) @@ -22,9 +23,21 @@ module CreatePeerToPeerCampaign campaign.profile = profile campaign.save - campaign.update_attribute(:main_image, parent_campaign.main_image) unless !parent_campaign.main_image rescue AWS::S3::Errors::NoSuchKey - campaign.update_attribute(:background_image, parent_campaign.background_image) unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey - campaign.update_attribute(:banner_image, parent_campaign.banner_image) unless !parent_campaign.banner_image rescue AWS::S3::Errors::NoSuchKey + begin + campaign.update_attribute(:main_image, parent_campaign.main_image) if parent_campaign.main_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end + begin + campaign.update_attribute(:background_image, parent_campaign.background_image) if parent_campaign.background_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end + begin + campaign.update_attribute(:banner_image, parent_campaign.banner_image) if parent_campaign.banner_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty? diff --git a/lib/create/create_tag_master.rb b/lib/create/create_tag_master.rb index 7c8fc139..9eef5b94 100644 --- a/lib/create/create_tag_master.rb +++ b/lib/create/create_tag_master.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module CreateTagMaster - - def self.create(nonprofit, params) - tag_master = nonprofit.tag_masters.create(params) - return tag_master - end + def self.create(nonprofit, params) + tag_master = nonprofit.tag_masters.create(params) + tag_master + end end - diff --git a/lib/create/stripe/create_stripe_account.rb b/lib/create/stripe/create_stripe_account.rb index 1d1a9412..75681c7c 100644 --- a/lib/create/stripe/create_stripe_account.rb +++ b/lib/create/stripe/create_stripe_account.rb @@ -1,37 +1,38 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'format/name' require 'get_data' require 'stripe' module CreateStripeAccount - - def self.for_nonprofit(user, params) - fst_name, lst_name = Format::Name.split_full(GetData.chain(user, :profile, :name)) - return Stripe::Account.create({ - managed: true, - email: params[:email], - business_name: params[:name], - business_url: params[:website], - legal_entity: { - type: 'company', - address: { - line1: params[:address], - city: params[:city], - state: params[:state_code], - postal_code: params[:zip_code], - country: 'US' - }, - business_name: params[:name], - business_tax_id: params[:ein], - first_name: fst_name, - last_name: lst_name - }, - product_description: 'Nonprofit donations', - tos_acceptance: { - date: Time.current.to_i, - ip: user.current_sign_in_ip - }, - transfer_schedule: { interval: 'manual' } - }) - end + def self.for_nonprofit(user, params) + fst_name, lst_name = Format::Name.split_full(GetData.chain(user, :profile, :name)) + Stripe::Account.create( + managed: true, + email: params[:email], + business_name: params[:name], + business_url: params[:website], + legal_entity: { + type: 'company', + address: { + line1: params[:address], + city: params[:city], + state: params[:state_code], + postal_code: params[:zip_code], + country: 'US' + }, + business_name: params[:name], + business_tax_id: params[:ein], + first_name: fst_name, + last_name: lst_name + }, + product_description: 'Nonprofit donations', + tos_acceptance: { + date: Time.current.to_i, + ip: user.current_sign_in_ip + }, + transfer_schedule: { interval: 'manual' } + ) + end end diff --git a/lib/cypher.rb b/lib/cypher.rb index 3f95b517..0f2e971b 100644 --- a/lib/cypher.rb +++ b/lib/cypher.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'openssl' @@ -8,31 +10,30 @@ require 'openssl' # .iv, .auth_tag both are stored with the encrypted data module Cypher - def self.encrypt(data) cipher = create_cipher cipher.encrypt cipher.key = Base64.decode64(ENV['CYPHER_KEY']) iv = cipher.random_iv encrypted = cipher.update(data) + cipher.final - return {iv: Base64.encode64(iv), key: Base64.encode64(encrypted)} + { iv: Base64.encode64(iv), key: Base64.encode64(encrypted) } end # hash must have properties for :iv and :key def self.decrypt(hash) - iv, encrypted = [Base64.decode64(hash['iv']), Base64.decode64(hash['key'])] + iv = Base64.decode64(hash['iv']) + encrypted = Base64.decode64(hash['key']) decipher = create_cipher decipher.decrypt decipher.key = Base64.decode64(ENV['CYPHER_KEY']) decipher.iv = iv - return decipher.update(encrypted) + decipher.final + decipher.update(encrypted) + decipher.final end -private + private def self.create_cipher OpenSSL::Cipher::AES256.new(:CBC) end - end diff --git a/lib/delayed_job_helper.rb b/lib/delayed_job_helper.rb index 7189a29e..f03b7c8f 100644 --- a/lib/delayed_job_helper.rb +++ b/lib/delayed_job_helper.rb @@ -1,20 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'delayed_job' module DelayedJobHelper - - # Create a serialized delayed job handler for use in inserting new delayed jobs with raw sql - # Be sure to wrap the handler in double quotes when inserting, not single - def self.create_handler(obj, method_name, args) - Delayed::PerformableMethod.new(obj, method_name, args).to_yaml.to_s - end + # Create a serialized delayed job handler for use in inserting new delayed jobs with raw sql + # Be sure to wrap the handler in double quotes when inserting, not single + def self.create_handler(obj, method_name, args) + Delayed::PerformableMethod.new(obj, method_name, args).to_yaml.to_s + end # Manually enqueue a job - def self.enqueue_job(obj, method_name, args, options={}) + def self.enqueue_job(obj, method_name, args, options = {}) handler = Delayed::PerformableMethod.new(obj, method_name, args).to_yaml.to_s Qx.insert_into(:delayed_jobs) - .values({ + .values( created_at: Time.current, updated_at: Time.current, priority: options[:priority] || 0, @@ -22,6 +23,6 @@ module DelayedJobHelper handler: handler, run_at: options[:run_at] || Time.current, queue: options[:queue] - }).returning('*').execute + ).returning('*').execute end end diff --git a/lib/delete/delete_campaign_gift_option.rb b/lib/delete/delete_campaign_gift_option.rb index bcb0afe1..249c0ef4 100644 --- a/lib/delete/delete_campaign_gift_option.rb +++ b/lib/delete/delete_campaign_gift_option.rb @@ -1,27 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module DeleteCampaignGiftOption def self.delete(campaign, campaign_gift_option_id) - ParamValidation.new({:campaign => campaign, - :campaign_gift_option_id => campaign_gift_option_id}, - { - :campaign => { - :required => true, - :is_a => Campaign - }, - :campaign_gift_option_id => { - :required => true, - :is_integer => true - } - } - ) + ParamValidation.new({ campaign: campaign, + campaign_gift_option_id: campaign_gift_option_id }, + campaign: { + required: true, + is_a: Campaign + }, + campaign_gift_option_id: { + required: true, + is_integer: true + }) Qx.transaction do cgo = campaign.campaign_gift_options.where('id = ? ', campaign_gift_option_id).first unless cgo - raise ParamValidation::ValidationError.new("#{campaign_gift_option_id} is not a valid gift option for campaign #{campaign.id}", {:key => :campaign_gift_option_id}) + raise ParamValidation::ValidationError.new("#{campaign_gift_option_id} is not a valid gift option for campaign #{campaign.id}", key: :campaign_gift_option_id) end - if (cgo.campaign_gifts.any?) - raise ParamValidation::ValidationError.new("#{campaign_gift_option_id} already has campaign gifts. It can't be deleted for safety reasons.", {:key => :campaign_gift_option_id}) + if cgo.campaign_gifts.any? + raise ParamValidation::ValidationError.new("#{campaign_gift_option_id} already has campaign gifts. It can't be deleted for safety reasons.", key: :campaign_gift_option_id) end cgo.destroy @@ -29,4 +28,4 @@ module DeleteCampaignGiftOption return cgo end end -end \ No newline at end of file +end diff --git a/lib/delete/delete_custom_field_joins.rb b/lib/delete/delete_custom_field_joins.rb index ac3e8080..9e392733 100644 --- a/lib/delete/delete_custom_field_joins.rb +++ b/lib/delete/delete_custom_field_joins.rb @@ -1,39 +1,37 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module DeleteCustomFieldJoins - @columns = ['id', 'custom_field_master_id', 'supporter_id', 'value', 'created_at', 'updated_at', 'metadata'] + @columns = %w[id custom_field_master_id supporter_id value created_at updated_at metadata] def self.find_multiple_custom_field_joins - bad_results = Qx.select("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_master_id) AS our_concat, COUNT(id) AS our_count"). - from(:custom_field_joins). - group_by("our_concat"). - having('COUNT(id) > 1').parse - - - custom_field_joins_from_qx = CustomFieldJoin. - where("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_master_id) IN (SELECT our_concat FROM (#{bad_results}) AS ignore)"). - select('id, custom_field_master_id, supporter_id, created_at, updated_at') - grouped_custom_field_joins = custom_field_joins_from_qx.group_by{|tj| "#{tj.supporter_id}_#{tj.custom_field_master_id}"} + bad_results = Qx.select("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_master_id) AS our_concat, COUNT(id) AS our_count") + .from(:custom_field_joins) + .group_by('our_concat') + .having('COUNT(id) > 1').parse + custom_field_joins_from_qx = CustomFieldJoin + .where("CONCAT(custom_field_joins.supporter_id, '_', custom_field_joins.custom_field_master_id) IN (SELECT our_concat FROM (#{bad_results}) AS ignore)") + .select('id, custom_field_master_id, supporter_id, created_at, updated_at') + grouped_custom_field_joins = custom_field_joins_from_qx.group_by { |tj| "#{tj.supporter_id}_#{tj.custom_field_master_id}" } ids_to_delete = [] - grouped_custom_field_joins.each { |_, v| - - sorted = v.sort_by {|a| a.updated_at }.to_a - ids_to_delete += sorted.map{|i| i.id}[0, sorted.count - 1] - } + grouped_custom_field_joins.each do |_, v| + sorted = v.sort_by(&:updated_at).to_a + ids_to_delete += sorted.map(&:id)[0, sorted.count - 1] + end ids_to_delete end def self.copy_and_delete(ids_to_delete) if ids_to_delete.any? - Qx.insert_into(:custom_field_joins_backup, @columns).select(@columns).from(:custom_field_joins).where('id IN ($ids)', ids:ids_to_delete).execute + Qx.insert_into(:custom_field_joins_backup, @columns).select(@columns).from(:custom_field_joins).where('id IN ($ids)', ids: ids_to_delete).execute CustomFieldJoin.where('id IN (?)', ids_to_delete).delete_all end - end def self.revert Qx.insert_into(:custom_field_joins, @columns).select(@columns).from(:custom_field_joins_backup).execute - Qx.execute_raw("DELETE FROM custom_field_joins_backup") + Qx.execute_raw('DELETE FROM custom_field_joins_backup') end -end \ No newline at end of file +end diff --git a/lib/delete/delete_tag_joins.rb b/lib/delete/delete_tag_joins.rb index 72e347d5..0e0c875d 100644 --- a/lib/delete/delete_tag_joins.rb +++ b/lib/delete/delete_tag_joins.rb @@ -1,25 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module DeleteTagJoins - @columns = ['id', 'created_at', 'updated_at', 'metadata', 'tag_master_id', 'supporter_id'] + @columns = %w[id created_at updated_at metadata tag_master_id supporter_id] def self.find_multiple_tag_joins - qx_results = Qx.select("CONCAT(tag_joins.supporter_id, '_', tag_joins.tag_master_id) AS our_concat, COUNT(id) AS our_count"). - from(:tag_joins). - group_by("our_concat"). - having('COUNT(id) > 1'). - execute - - tag_joins_from_qx = TagJoin.where("CONCAT(supporter_id, '_', tag_master_id) IN (?)", qx_results.map{|i| i["our_concat"] }).select('id, tag_master_id, supporter_id, created_at') - grouped_tagged_joins = tag_joins_from_qx.group_by{|tj| "#{tj.supporter_id}_#{tj.tag_master_id}"} + qx_results = Qx.select("CONCAT(tag_joins.supporter_id, '_', tag_joins.tag_master_id) AS our_concat, COUNT(id) AS our_count") + .from(:tag_joins) + .group_by('our_concat') + .having('COUNT(id) > 1') + .execute + tag_joins_from_qx = TagJoin.where("CONCAT(supporter_id, '_', tag_master_id) IN (?)", qx_results.map { |i| i['our_concat'] }).select('id, tag_master_id, supporter_id, created_at') + grouped_tagged_joins = tag_joins_from_qx.group_by { |tj| "#{tj.supporter_id}_#{tj.tag_master_id}" } ids_to_delete = [] - grouped_tagged_joins.each { |_, v| - - sorted = v.sort_by {|a| a.created_at }.to_a - ids_to_delete += sorted.map{|i| i.id}[0, sorted.count - 1] - } + grouped_tagged_joins.each do |_, v| + sorted = v.sort_by(&:created_at).to_a + ids_to_delete += sorted.map(&:id)[0, sorted.count - 1] + end ids_to_delete end @@ -27,18 +27,17 @@ module DeleteTagJoins def self.copy_and_delete(ids_to_delete) if ids_to_delete.any? - #select_query = Qx.select(@columns).from(:tag_joins).where('id IN ($ids)', ids:ids_to_delete).parse + # select_query = Qx.select(@columns).from(:tag_joins).where('id IN ($ids)', ids:ids_to_delete).parse - Qx.insert_into(:tag_joins_backup, @columns).select(@columns).from(:tag_joins).where('id IN ($ids)', ids:ids_to_delete).execute - # Qx.execute_raw("INSERT INTO tag_joins_backup ('id', '' #{select_query}") + Qx.insert_into(:tag_joins_backup, @columns).select(@columns).from(:tag_joins).where('id IN ($ids)', ids: ids_to_delete).execute + # Qx.execute_raw("INSERT INTO tag_joins_backup ('id', '' #{select_query}") TagJoin.where('id IN (?)', ids_to_delete).delete_all end - end def self.revert Qx.insert_into(:tag_joins, @columns).select(@columns).from(:tag_joins_backup).execute - #Qx.execute_raw("INSERT INTO tag_joins SELECT * FROM tag_joins_backup") - Qx.execute_raw("DELETE FROM tag_joins_backup") + # Qx.execute_raw("INSERT INTO tag_joins SELECT * FROM tag_joins_backup") + Qx.execute_raw('DELETE FROM tag_joins_backup') end -end \ No newline at end of file +end diff --git a/lib/email.rb b/lib/email.rb index d255f6e6..255c722f 100644 --- a/lib/email.rb +++ b/lib/email.rb @@ -1,7 +1,7 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Email - - Regex ||= /\A[^ ]+@[^ ]+\.[^ ]+/i - #PsqlRegex ||= '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$' - + Regex ||= /\A[^ ]+@[^ ]+\.[^ ]+/i.freeze + # PsqlRegex ||= '^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+[.][A-Za-z]+$' end diff --git a/lib/email_job_queue.rb b/lib/email_job_queue.rb index 25482a03..84e247bd 100644 --- a/lib/email_job_queue.rb +++ b/lib/email_job_queue.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module EmailJobQueue def self.queue(klass, *args) Delayed::Job.enqueue klass.new(*args) end -end \ No newline at end of file +end diff --git a/lib/errors/authentication_error.rb b/lib/errors/authentication_error.rb index 603bff36..01f51b35 100644 --- a/lib/errors/authentication_error.rb +++ b/lib/errors/authentication_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class AuthenticationError < RuntimeError -end \ No newline at end of file +end diff --git a/lib/errors/cc_org_error.rb b/lib/errors/cc_org_error.rb index 0d1dff0e..9dcadea5 100644 --- a/lib/errors/cc_org_error.rb +++ b/lib/errors/cc_org_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class CCOrgError < RuntimeError -end \ No newline at end of file +end diff --git a/lib/errors/charge_error.rb b/lib/errors/charge_error.rb index 33ddb2c1..7f9160e0 100644 --- a/lib/errors/charge_error.rb +++ b/lib/errors/charge_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ChargeError < RuntimeError -end \ No newline at end of file +end diff --git a/lib/errors/expired_token_error.rb b/lib/errors/expired_token_error.rb index 066c32d4..2fa14242 100644 --- a/lib/errors/expired_token_error.rb +++ b/lib/errors/expired_token_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class ExpiredTokenError < RuntimeError -end \ No newline at end of file +end diff --git a/lib/errors/not_enough_quantity_error.rb b/lib/errors/not_enough_quantity_error.rb index d9f74792..018d5ffe 100644 --- a/lib/errors/not_enough_quantity_error.rb +++ b/lib/errors/not_enough_quantity_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NotEnoughQuantityError < CCOrgError attr_accessor :klass, :id, :requested @@ -7,4 +9,4 @@ class NotEnoughQuantityError < CCOrgError @requested = requested super(msg) end -end \ No newline at end of file +end diff --git a/lib/export/export_payments.rb b/lib/export/export_payments.rb index a54d5dc1..1324aab4 100644 --- a/lib/export/export_payments.rb +++ b/lib/export/export_payments.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ExportPayments - def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, npo_id: { required: true, is_integer: true }, params: { required: true, is_hash: true }, @@ -12,6 +12,7 @@ module ExportPayments unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) @@ -30,7 +31,7 @@ module ExportPayments user_id: { required: true, is_integer: true }, export_id: { required: true, is_integer: true }) - params = JSON.parse(params, :object_class=> HashWithIndifferentAccess) + params = JSON.parse(params, object_class: HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once ParamValidation.new({ params: params }, params: { is_hash: true }) @@ -45,30 +46,29 @@ module ExportPayments unless Nonprofit.exists?(npo_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc().strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') filename = "tmp/csv-exports/payments-#{file_date}.csv" - url = CHUNKED_UPLOADER.upload(filename, QueryPayments.for_export_enumerable(npo_id, params, 30000).map{|i| i.to_csv}, :content_type => 'text/csv', content_disposition: 'attachment') + url = CHUNKED_UPLOADER.upload(filename, QueryPayments.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv), content_type: 'text/csv', content_disposition: 'attachment') export.url = url export.status = :completed export.ended = Time.now export.save! ExportMailer.delay.export_payments_completed_notification(export) - rescue => e + rescue StandardError => e if export export.status = :failed export.exception = e.to_s export.ended = Time.now export.save! - if user - ExportMailer.delay.export_payments_failed_notification(export) - end + ExportMailer.delay.export_payments_failed_notification(export) if user raise e end raise e diff --git a/lib/export/export_recurring_donations.rb b/lib/export/export_recurring_donations.rb index a8b146e5..9d9e1d23 100644 --- a/lib/export/export_recurring_donations.rb +++ b/lib/export/export_recurring_donations.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ExportRecurringDonations - def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, npo_id: { required: true, is_integer: true }, params: { required: true, is_hash: true }, @@ -12,6 +12,7 @@ module ExportRecurringDonations unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) @@ -30,7 +31,7 @@ module ExportRecurringDonations user_id: { required: true, is_integer: true }, export_id: { required: true, is_integer: true }) - params = JSON.parse(params, :object_class=> HashWithIndifferentAccess) + params = JSON.parse(params, object_class: HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once ParamValidation.new({ params: params }, params: { is_hash: true }) @@ -45,22 +46,23 @@ module ExportRecurringDonations unless Nonprofit.exists?(npo_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc().strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') filename = "tmp/csv-exports/recurring_donations-#{file_date}.csv" - url = CHUNKED_UPLOADER.upload(filename, QueryRecurringDonations.for_export_enumerable(npo_id, params, 30000).map{|i| i.to_csv}, :content_type => 'text/csv', content_disposition: 'attachment') + url = CHUNKED_UPLOADER.upload(filename, QueryRecurringDonations.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv), content_type: 'text/csv', content_disposition: 'attachment') export.url = url export.status = :completed export.ended = Time.now export.save! ExportMailer.delay.export_recurring_donations_completed_notification(export) - rescue => e + rescue StandardError => e if export export.status = :failed export.exception = e.to_s diff --git a/lib/export/export_supporter_notes.rb b/lib/export/export_supporter_notes.rb index 83b9316e..52b3af11 100644 --- a/lib/export/export_supporter_notes.rb +++ b/lib/export/export_supporter_notes.rb @@ -1,74 +1,77 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ExportSupporterNotes - def self.initiate_export(npo_id, params, user_id) + def self.initiate_export(npo_id, params, user_id) + ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, + npo_id: { required: true, is_integer: true }, + params: { required: true, is_hash: true }, + user_id: { required: true, is_integer: true }) + npo = Nonprofit.where('id = ?', npo_id).first + unless npo + raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) + end - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_hash: true }, - user_id: { required: true, is_integer: true }) - npo = Nonprofit.where('id = ?', npo_id).first - unless npo - raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) - end - user = User.where('id = ?', user_id).first - unless user - raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) - end - - e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportSupporterNotes', parameters: params.to_json) - - DelayedJobHelper.enqueue_job(ExportSupporterNotes, :run_export, [npo_id, params.to_json, user_id, e.id]) + user = User.where('id = ?', user_id).first + unless user + raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) + end + + e = Export.create(nonprofit: npo, user: user, status: :queued, export_type: 'ExportSupporterNotes', parameters: params.to_json) + + DelayedJobHelper.enqueue_job(ExportSupporterNotes, :run_export, [npo_id, params.to_json, user_id, e.id]) + end + + def self.run_export(npo_id, params, user_id, export_id) + # need to check that + ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, + npo_id: { required: true, is_integer: true }, + params: { required: true, is_json: true }, + user_id: { required: true, is_integer: true }, + export_id: { required: true, is_integer: true }) + + params = JSON.parse(params, object_class: HashWithIndifferentAccess) + # verify that it's also a hash since we can't do that at once + ParamValidation.new({ params: params }, + params: { is_hash: true }) + begin + export = Export.find(export_id) + rescue ActiveRecord::RecordNotFound + raise ParamValidation::ValidationError.new("Export #{export_id} doesn't exist!", key: :export_id) + end + export.status = :started + export.save! + + unless Nonprofit.exists?(npo_id) + raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) + end + + user = User.where('id = ?', user_id).first + unless user + raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) + end + + file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') + filename = "tmp/csv-exports/supporters-notes-#{file_date}.csv" + + url = CHUNKED_UPLOADER.upload(filename, QuerySupporters.supporter_note_export_enumerable(npo_id, params, 30_000).map(&:to_csv), content_type: 'text/csv', content_disposition: 'attachment') + export.url = url + export.status = :completed + export.ended = Time.now + export.save! + + EmailJobQueue.queue(JobTypes::ExportSupporterNotesCompletedJob, export) + rescue StandardError => e + if export + export.status = :failed + export.exception = e.to_s + export.ended = Time.now + export.save! + if user + EmailJobQueue.queue(JobTypes::ExportSupporterNotesFailedJob, export) end - - def self.run_export(npo_id, params, user_id, export_id) - # need to check that - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id, export_id: export_id }, - npo_id: { required: true, is_integer: true }, - params: { required: true, is_json: true }, - user_id: { required: true, is_integer: true }, - export_id: { required: true, is_integer: true }) - - params = JSON.parse(params, :object_class=> HashWithIndifferentAccess) - # verify that it's also a hash since we can't do that at once - ParamValidation.new({ params: params }, - params: { is_hash: true }) - begin - export = Export.find(export_id) - rescue ActiveRecord::RecordNotFound - raise ParamValidation::ValidationError.new("Export #{export_id} doesn't exist!", key: :export_id) - end - export.status = :started - export.save! - - unless Nonprofit.exists?(npo_id) - raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) - end - user = User.where('id = ?', user_id).first - unless user - raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) - end - - file_date = Time.now.getutc().strftime('%m-%d-%Y--%H-%M-%S') - filename = "tmp/csv-exports/supporters-notes-#{file_date}.csv" - - url = CHUNKED_UPLOADER.upload(filename, QuerySupporters.supporter_note_export_enumerable(npo_id, params, 30000).map{|i| i.to_csv}, content_type: 'text/csv', content_disposition: 'attachment') - export.url = url - export.status = :completed - export.ended = Time.now - export.save! - - EmailJobQueue.queue(JobTypes::ExportSupporterNotesCompletedJob, export) - rescue => e - if export - export.status = :failed - export.exception = e.to_s - export.ended = Time.now - export.save! - if user - EmailJobQueue.queue(JobTypes::ExportSupporterNotesFailedJob, export) - end - raise e - end - raise e - end -end \ No newline at end of file + raise e + end + raise e + end +end diff --git a/lib/export/export_supporters.rb b/lib/export/export_supporters.rb index c657ffb0..8c7c4991 100644 --- a/lib/export/export_supporters.rb +++ b/lib/export/export_supporters.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + module ExportSupporters def self.initiate_export(npo_id, params, user_id) - ParamValidation.new({ npo_id: npo_id, params: params, user_id: user_id }, npo_id: { required: true, is_integer: true }, params: { required: true, is_hash: true }, @@ -9,6 +10,7 @@ module ExportSupporters unless npo raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) @@ -27,7 +29,7 @@ module ExportSupporters user_id: { required: true, is_integer: true }, export_id: { required: true, is_integer: true }) - params = JSON.parse(params, :object_class=> HashWithIndifferentAccess) + params = JSON.parse(params, object_class: HashWithIndifferentAccess) # verify that it's also a hash since we can't do that at once ParamValidation.new({ params: params }, params: { is_hash: true }) @@ -42,32 +44,31 @@ module ExportSupporters unless Nonprofit.exists?(npo_id) raise ParamValidation::ValidationError.new("Nonprofit #{npo_id} doesn't exist!", key: :npo_id) end + user = User.where('id = ?', user_id).first unless user raise ParamValidation::ValidationError.new("User #{user_id} doesn't exist!", key: :user_id) end - file_date = Time.now.getutc().strftime('%m-%d-%Y--%H-%M-%S') + file_date = Time.now.getutc.strftime('%m-%d-%Y--%H-%M-%S') filename = "tmp/csv-exports/supporters-#{file_date}.csv" - url = CHUNKED_UPLOADER.upload(filename, QuerySupporters.for_export_enumerable(npo_id, params, 30000).map{|i| i.to_csv}, content_type: 'text/csv', content_disposition: 'attachment') + url = CHUNKED_UPLOADER.upload(filename, QuerySupporters.for_export_enumerable(npo_id, params, 30_000).map(&:to_csv), content_type: 'text/csv', content_disposition: 'attachment') export.url = url export.status = :completed export.ended = Time.now export.save! - EmailJobQueue.queue(JobTypes::ExportSupportersCompletedJob, export) - rescue => e + EmailJobQueue.queue(JobTypes::ExportSupportersCompletedJob, export) + rescue StandardError => e if export export.status = :failed export.exception = e.to_s export.ended = Time.now export.save! - if user - EmailJobQueue.queue(JobTypes::ExportSupportersFailedJob, export) - end + EmailJobQueue.queue(JobTypes::ExportSupportersFailedJob, export) if user raise e end raise e end -end \ No newline at end of file +end diff --git a/lib/fetch/fetch_background_image.rb b/lib/fetch/fetch_background_image.rb index 79492cbd..5c3a7e72 100644 --- a/lib/fetch/fetch_background_image.rb +++ b/lib/fetch/fetch_background_image.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchBackgroundImage - - def self.with_model(model) - return model.background_image_url(:normal) unless model.background_image.file.nil? - end + def self.with_model(model) + return model.background_image_url(:normal) unless model.background_image.file.nil? + end end diff --git a/lib/fetch/fetch_campaign.rb b/lib/fetch/fetch_campaign.rb index 52bd775e..508a9afc 100644 --- a/lib/fetch/fetch_campaign.rb +++ b/lib/fetch/fetch_campaign.rb @@ -1,14 +1,13 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchCampaign - - def self.with_params(params, nonprofit=nil) - nonprofit ||= FetchNonprofit.with_params(params) - if params[:campaign_slug] - return nonprofit.campaigns.where(slug: params[:campaign_slug]).last - elsif params[:campaign_id] || params[:id] - return nonprofit.campaigns.find(params[:campaign_id] || params[:id]) - end - end - + def self.with_params(params, nonprofit = nil) + nonprofit ||= FetchNonprofit.with_params(params) + if params[:campaign_slug] + return nonprofit.campaigns.where(slug: params[:campaign_slug]).last + elsif params[:campaign_id] || params[:id] + return nonprofit.campaigns.find(params[:campaign_id] || params[:id]) + end + end end - diff --git a/lib/fetch/fetch_coupon.rb b/lib/fetch/fetch_coupon.rb index 402a4e16..c9cb9af9 100644 --- a/lib/fetch/fetch_coupon.rb +++ b/lib/fetch/fetch_coupon.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchCoupon - def self.page params - return params[:name].gsub('-','_') if params[:name] - end -end \ No newline at end of file + def self.page(params) + return params[:name].tr('-', '_') if params[:name] + end +end diff --git a/lib/fetch/fetch_event.rb b/lib/fetch/fetch_event.rb index cf8a1a9c..0b501881 100644 --- a/lib/fetch/fetch_event.rb +++ b/lib/fetch/fetch_event.rb @@ -1,14 +1,13 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchEvent - - def self.with_params(params, nonprofit=nil) - nonprofit ||= FetchNonprofit.with_params(params) - if params[:event_slug] - return nonprofit.events.find_by_slug(params[:event_slug]) - elsif params[:event_id] || params[:id] - return nonprofit.events.find(params[:event_id] || params[:id]) - end - end - + def self.with_params(params, nonprofit = nil) + nonprofit ||= FetchNonprofit.with_params(params) + if params[:event_slug] + return nonprofit.events.find_by_slug(params[:event_slug]) + elsif params[:event_id] || params[:id] + return nonprofit.events.find(params[:event_id] || params[:id]) + end + end end - diff --git a/lib/fetch/fetch_miscellaneous_np_info.rb b/lib/fetch/fetch_miscellaneous_np_info.rb index 85510589..8bac4187 100644 --- a/lib/fetch/fetch_miscellaneous_np_info.rb +++ b/lib/fetch/fetch_miscellaneous_np_info.rb @@ -1,8 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchMiscellaneousNpInfo def self.fetch(np_id) - ParamValidation.new({np_id: np_id}, np_id: {:required => true, :is_integer => true}) - raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", {key: :np_id}) unless Nonprofit.exists?(np_id) + ParamValidation.new({ np_id: np_id }, np_id: { required: true, is_integer: true }) + raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", key: :np_id) unless Nonprofit.exists?(np_id) + MiscellaneousNpInfo.where('nonprofit_id = ?', np_id).first_or_initialize end -end \ No newline at end of file +end diff --git a/lib/fetch/fetch_nonprofit.rb b/lib/fetch/fetch_nonprofit.rb index a7043742..32db3546 100644 --- a/lib/fetch/fetch_nonprofit.rb +++ b/lib/fetch/fetch_nonprofit.rb @@ -1,15 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchNonprofit - - def self.with_params(params, administered_nonprofit=nil) - if params[:state_code] && params[:city] && params[:name] - return Nonprofit.where(:state_code_slug => params[:state_code], :city_slug => params[:city], :slug => params[:name]).last - elsif params[:nonprofit_id] || params[:id] - return Nonprofit.find_by_id(params[:nonprofit_id] || params[:id]) + def self.with_params(params, administered_nonprofit = nil) + if params[:state_code] && params[:city] && params[:name] + Nonprofit.where(state_code_slug: params[:state_code], city_slug: params[:city], slug: params[:name]).last + elsif params[:nonprofit_id] || params[:id] + Nonprofit.find_by_id(params[:nonprofit_id] || params[:id]) elsif administered_nonprofit administered_nonprofit - end - end - + end + end end - diff --git a/lib/fetch/fetch_nonprofit_email.rb b/lib/fetch/fetch_nonprofit_email.rb index dc11e78d..0dbd4e72 100644 --- a/lib/fetch/fetch_nonprofit_email.rb +++ b/lib/fetch/fetch_nonprofit_email.rb @@ -1,13 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchNonprofitEmail + def self.with_charge(charge) + nonprofit = charge.nonprofit + nonprofit.email.blank? ? Settings.mailer.email : nonprofit.email + end - def self.with_charge charge - nonprofit = charge.nonprofit - nonprofit.email.blank? ? Settings.mailer.email : nonprofit.email - end - - def self.with_donation donation - nonprofit = donation.nonprofit - nonprofit.email.blank? ? Settings.mailer.email : nonprofit.email - end + def self.with_donation(donation) + nonprofit = donation.nonprofit + nonprofit.email.blank? ? Settings.mailer.email : nonprofit.email + end end diff --git a/lib/fetch/fetch_todo_status.rb b/lib/fetch/fetch_todo_status.rb index ac601198..245bcf12 100644 --- a/lib/fetch/fetch_todo_status.rb +++ b/lib/fetch/fetch_todo_status.rb @@ -1,28 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module FetchTodoStatus + def self.for_profile(np) + { + has_logo: np.logo?, + has_background: np.background_image?, + has_summary: np.summary?, + has_image: np.main_image?, + has_highlight: !np.achievements.join.blank?, + has_services: np.full_description? + } + end - def self.for_profile(np) - { - has_logo: np.logo?, - has_background: np.background_image?, - has_summary: np.summary?, - has_image: np.main_image?, - has_highlight: !np.achievements.join.blank?, - has_services: np.full_description? - } - end - - def self.for_dashboard(np) - { - has_campaign: np.campaigns.any?, - has_event: np.events.any?, - has_donation: np.donations.any?, - has_branding: np.brand_color?, - has_bank: np.bank_account.present?, - is_paying: np.billing_plan.present?, - has_imported: np.supporters.pluck(:imported_at).any?, - is_verified: np.verification_status == 'verified' && np.bank_account.present?, - has_thank_you: np.thank_you_note.present? - } - end + def self.for_dashboard(np) + { + has_campaign: np.campaigns.any?, + has_event: np.events.any?, + has_donation: np.donations.any?, + has_branding: np.brand_color?, + has_bank: np.bank_account.present?, + is_paying: np.billing_plan.present?, + has_imported: np.supporters.pluck(:imported_at).any?, + is_verified: np.verification_status == 'verified' && np.bank_account.present?, + has_thank_you: np.thank_you_note.present? + } + end end diff --git a/lib/fetch/stripe/fetch_stripe_account.rb b/lib/fetch/stripe/fetch_stripe_account.rb index 0e7f8aa3..f7cffa4e 100644 --- a/lib/fetch/stripe/fetch_stripe_account.rb +++ b/lib/fetch/stripe/fetch_stripe_account.rb @@ -1,15 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Retrive a stripe account object, catching any errors module FetchStripeAccount - - def self.with_account_id(stripe_account_id) - begin - stripe_acct = Stripe::Account.retrieve(stripe_account_id) - rescue - stripe_acct = nil - end - return stripe_acct - end - + def self.with_account_id(stripe_account_id) + begin + stripe_acct = Stripe::Account.retrieve(stripe_account_id) + rescue StandardError + stripe_acct = nil + end + stripe_acct + end end diff --git a/lib/format/format/address.rb b/lib/format/format/address.rb index 62781dec..1cf070d6 100644 --- a/lib/format/format/address.rb +++ b/lib/format/format/address.rb @@ -1,23 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Format; module Address - - def self.full_address(street, city, state, zip=nil) - # Albuquerque | NM | Albuquerque NM | 1234 Street Ln, Albuquerque NM - [[street, city].compact.join(", "), state, zip].compact.join(' ') - end +module Format + module Address + def self.full_address(street, city, state, zip = nil) + # Albuquerque | NM | Albuquerque NM | 1234 Street Ln, Albuquerque NM + [[street, city].compact.join(', '), state, zip].compact.join(' ') + end - def self.city_and_state(city,state) - [city, state].join(', ') if !city.blank? && !state.blank? - end + def self.city_and_state(city, state) + [city, state].join(', ') if !city.blank? && !state.blank? + end - def self.city_or_state(city,state) - city_and_state(city,state) || city || state - end + def self.city_or_state(city, state) + city_and_state(city, state) || city || state + end - def self.with_supporter(s) - return '' if s.nil? - [[s.address, s.city, s.state_code].reject(&:blank?).join(", "), s.zip_code].reject(&:blank?).join(" ") - end + def self.with_supporter(s) + return '' if s.nil? + [[s.address, s.city, s.state_code].reject(&:blank?).join(', '), s.zip_code].reject(&:blank?).join(' ') + end end; end - diff --git a/lib/format/format/csv.rb b/lib/format/format/csv.rb index 1eda6751..c107cbd4 100644 --- a/lib/format/format/csv.rb +++ b/lib/format/format/csv.rb @@ -1,33 +1,33 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'csv' require 'format/currency' module Format module Csv - # Convert an array of hashes of data into a csv # @param [Array] an array of hashes. The hash keys of the first item in the array become the CSV titles # @return [String] def self.from_data(arr) - return CSV.generate do |csv| - csv << arr.first.keys.map{|k| k.to_s.titleize} - arr.each{|h| csv << h.values} + CSV.generate do |csv| + csv << arr.first.keys.map { |k| k.to_s.titleize } + arr.each { |h| csv << h.values } end end def self.from_vectors(vecs) - return CSV.generate do |csv| - csv << vecs.first.to_a.map{|k| k.to_s.titleize} - vecs.drop(1).each{|v| csv << v.to_a} + CSV.generate do |csv| + csv << vecs.first.to_a.map { |k| k.to_s.titleize } + vecs.drop(1).each { |v| csv << v.to_a } end end def self.from_array(arr) - return CSV.generate do |csv| - csv << arr.first.map{|h| h.to_s.titleize} - arr.drop(1).each{|row| csv << (row||[])} + CSV.generate do |csv| + csv << arr.first.map { |h| h.to_s.titleize } + arr.drop(1).each { |row| csv << (row || []) } end end - end end diff --git a/lib/format/format/currency.rb b/lib/format/format/currency.rb index e81e1c01..e8161e3b 100644 --- a/lib/format/format/currency.rb +++ b/lib/format/format/currency.rb @@ -1,21 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Format; module Currency - - - # Converts currency units into subunits. - # @param [String] units - # @return [Integer] - def self.dollars_to_cents(units) - return (units.gsub(',','').gsub(Settings.intntl.currencies[0],'').to_f * 100).to_i - end - - # Converts currency subunits into units. - # @param [Integer] subunits - # @return [String] - def self.cents_to_dollars(subunits) - return (subunits.to_f / 100.0).to_s - .gsub(/^(\d+)\.0$/, '\1') # remove trailing zero if no decimals (eg. "1.0" -> "1") - .gsub(/^(\d+)\.(\d)$/, '\1.\20') # add a second zero if single decimal (eg. "9.9" -> "9.90") - end +module Format + module Currency + # Converts currency units into subunits. + # @param [String] units + # @return [Integer] + def self.dollars_to_cents(units) + (units.delete(',').gsub(Settings.intntl.currencies[0], '').to_f * 100).to_i + end + # Converts currency subunits into units. + # @param [Integer] subunits + # @return [String] + def self.cents_to_dollars(subunits) + (subunits.to_f / 100.0).to_s + .gsub(/^(\d+)\.0$/, '\1') # remove trailing zero if no decimals (eg. "1.0" -> "1") + .gsub(/^(\d+)\.(\d)$/, '\1.\20') # add a second zero if single decimal (eg. "9.9" -> "9.90") + end end; end diff --git a/lib/format/format/date.rb b/lib/format/format/date.rb index 7d803e3c..77c57ee2 100644 --- a/lib/format/format/date.rb +++ b/lib/format/format/date.rb @@ -1,64 +1,69 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'chronic' -module Format; module Date +module Format + module Date + ISORegex = /\d\d\d\d-\d\d-\d\d/.freeze - ISORegex = /\d\d\d\d-\d\d-\d\d/ - - def self.parse(str) - Chronic.parse(str) - end - - def self.from(str) - return DateTime.strptime(str, "%m/%d/%Y") - end - - def self.to_readable(date) - date.strftime("%A, %B #{date.day.ordinalize}") - end - - def self.full(date, timezone=nil) - return '' if date.nil? - date = Chronic.parse(date) if date.is_a?(String) - date = date.in_time_zone(timezone) if timezone - date.strftime("%m/%-d/%Y %l:%M%P") - end - - def self.full_range(date1, date2, timezone=nil) - return full(date1, timezone) if date2.nil? - return full(date2, timezone) if date1.nil? - if simple(date1) == simple(date2) - return full(date1, timezone) + ' - ' + time(date2, timezone) - else - return full(date1, timezone) + ' - ' + full(date2, timezone) + def self.parse(str) + Chronic.parse(str) end - end - def self.simple(date, timezone=nil) - return '' if date.nil? - date = Chronic.parse(date) if date.is_a?(String) - date = date.in_time_zone(timezone) if timezone - date.strftime("%m/%d/%Y") - end + def self.from(str) + DateTime.strptime(str, '%m/%d/%Y') + end - def self.time(datetime, timezone=nil) - return '' if datetime.nil? - datetime = Chronic.parse(datetime) if datetime.is_a?(String) - datetime = datetime.in_time_zone(timezone) if timezone - datetime.strftime("%l:%M%P") - end + def self.to_readable(date) + date.strftime("%A, %B #{date.day.ordinalize}") + end - def self.us_timezones - #zones=ActiveSupport::TimeZone.us_zones - zones=ActiveSupport::TimeZone.all - names = zones.map(&:name) - vals = zones.map{|t| t.tzinfo.name} - return names.zip(vals).sort_by{|name, val| name} - end + def self.full(date, timezone = nil) + return '' if date.nil? - def self.parse_partial_str(str) - return nil if str.nil? - Time.new(*str.match(/(\d\d\d\d)-?(\d\d)?-?(\d\d)?/).to_a[1..-1].compact.map(&:to_i)) - end + date = Chronic.parse(date) if date.is_a?(String) + date = date.in_time_zone(timezone) if timezone + date.strftime('%m/%-d/%Y %l:%M%P') + end + def self.full_range(date1, date2, timezone = nil) + return full(date1, timezone) if date2.nil? + return full(date2, timezone) if date1.nil? + if simple(date1) == simple(date2) + return full(date1, timezone) + ' - ' + time(date2, timezone) + else + return full(date1, timezone) + ' - ' + full(date2, timezone) + end + end + + def self.simple(date, timezone = nil) + return '' if date.nil? + + date = Chronic.parse(date) if date.is_a?(String) + date = date.in_time_zone(timezone) if timezone + date.strftime('%m/%d/%Y') + end + + def self.time(datetime, timezone = nil) + return '' if datetime.nil? + + datetime = Chronic.parse(datetime) if datetime.is_a?(String) + datetime = datetime.in_time_zone(timezone) if timezone + datetime.strftime('%l:%M%P') + end + + def self.us_timezones + # zones=ActiveSupport::TimeZone.us_zones + zones = ActiveSupport::TimeZone.all + names = zones.map(&:name) + vals = zones.map { |t| t.tzinfo.name } + names.zip(vals).sort_by { |name, _val| name } + end + + def self.parse_partial_str(str) + return nil if str.nil? + + Time.new(*str.match(/(\d\d\d\d)-?(\d\d)?-?(\d\d)?/).to_a[1..-1].compact.map(&:to_i)) + end end; end diff --git a/lib/format/format/dedication.rb b/lib/format/format/dedication.rb index 29650c18..86d6c388 100644 --- a/lib/format/format/dedication.rb +++ b/lib/format/format/dedication.rb @@ -1,16 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'json' module Format module Dedication - def self.from_json(json_text) begin hash = JSON.parse(json_text) - rescue + rescue StandardError return json_text end - return "Donation made in #{hash['type'] || 'honor'} of #{hash['name']}. Note: #{hash['note']}" + "Donation made in #{hash['type'] || 'honor'} of #{hash['name']}. Note: #{hash['note']}" end end end diff --git a/lib/format/format/geography.rb b/lib/format/format/geography.rb index 6ac3394c..f53f1532 100644 --- a/lib/format/format/geography.rb +++ b/lib/format/format/geography.rb @@ -1,305 +1,307 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Format; module Geography +module Format + module Geography + StateCodes = %w[AL AK AZ AR CA CO CT DE DC FL GA HI ID IL IN IA KS KY LA ME MD MA MI MN MS MO MT NE NV NH NJ NM NY NC ND OH OK OR PA PR RI SC SD TN TX UT VT VA WA WV WI WY].freeze - StateCodes = [ 'AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'DC', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'PR', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY' ] + StateMappings = { + 'alabama' => 'AL', + 'alaska' => 'AK', + 'arizona' => 'AZ', + 'arkansas' => 'AR', + 'california' => 'CA', + 'colorado' => 'CO', + 'connecticut' => 'CT', + 'delaware' => 'DE', + 'district of columbia' => 'DC', + 'florida' => 'FL', + 'georgia' => 'GA', + 'hawaii' => 'HI', + 'idaho' => 'ID', + 'illinois' => 'IL', + 'indiana' => 'IN', + 'iowa' => 'IA', + 'kansas' => 'KS', + 'kentucky' => 'KY', + 'louisiana' => 'LA', + 'maine' => 'ME', + 'maryland' => 'MD', + 'massachusetts' => 'MA', + 'michigan' => 'MI', + 'minnesota' => 'MN', + 'mississippi' => 'MS', + 'missouri' => 'MO', + 'montana' => 'MT', + 'nebraska' => 'NE', + 'nevada' => 'NV', + 'new hampshire' => 'NH', + 'new jersey' => 'NJ', + 'new mexico' => 'NM', + 'new york' => 'NY', + 'north carolina' => 'NC', + 'north dakota' => 'ND', + 'ohio' => 'OH', + 'oklahoma' => 'OK', + 'oregon' => 'OR', + 'pennsylvania' => 'PA', + 'puerto rico' => 'PR', + 'rhode island' => 'RI', + 'south carolina' => 'SC', + 'south dakota' => 'SD', + 'tennessee' => 'TN', + 'texas' => 'TX', + 'utah' => 'UT', + 'vermont' => 'VT', + 'virginia' => 'VA', + 'washington' => 'WA', + 'west virginia' => 'WV', + 'wisconsin' => 'WI', + 'wyoming' => 'WY' + }.freeze - StateMappings = { - 'alabama' => 'AL', - 'alaska' => 'AK', - 'arizona' => 'AZ', - 'arkansas' => 'AR', - 'california' => 'CA', - 'colorado' => 'CO', - 'connecticut' => 'CT', - 'delaware' => 'DE', - 'district of columbia' => 'DC', - 'florida' => 'FL', - 'georgia' => 'GA', - 'hawaii' => 'HI', - 'idaho' => 'ID', - 'illinois' => 'IL', - 'indiana' => 'IN', - 'iowa' => 'IA', - 'kansas' => 'KS', - 'kentucky' => 'KY', - 'louisiana' => 'LA', - 'maine' => 'ME', - 'maryland' => 'MD', - 'massachusetts' => 'MA', - 'michigan' => 'MI', - 'minnesota' => 'MN', - 'mississippi' => 'MS', - 'missouri' => 'MO', - 'montana' => 'MT', - 'nebraska' => 'NE', - 'nevada' => 'NV', - 'new hampshire' => 'NH', - 'new jersey' => 'NJ', - 'new mexico' => 'NM', - 'new york' => 'NY', - 'north carolina' => 'NC', - 'north dakota' => 'ND', - 'ohio' => 'OH', - 'oklahoma' => 'OK', - 'oregon' => 'OR', - 'pennsylvania' => 'PA', - 'puerto rico' => 'PR', - 'rhode island' => 'RI', - 'south carolina' => 'SC', - 'south dakota' => 'SD', - 'tennessee' => 'TN', - 'texas' => 'TX', - 'utah' => 'UT', - 'vermont' => 'VT', - 'virginia' => 'VA', - 'washington' => 'WA', - 'west virginia' => 'WV', - 'wisconsin' => 'WI', - 'wyoming' => 'WY' - } + Countries = [ + 'Afghanistan', + 'Albania', + 'Algeria', + 'American Samoa', + 'Andorra', + 'Angola', + 'Anguilla', + 'Antarctica', + 'Antigua and Barbuda', + 'Argentina', + 'Armenia', + 'Aruba', + 'Australia', + 'Austria', + 'Azerbaijan', + 'Bahamas', + 'Bahrain', + 'Bangladesh', + 'Barbados', + 'Belarus', + 'Belgium', + 'Belize', + 'Benin', + 'Bermuda', + 'Bhutan', + 'Bolivia', + 'Bosnia and Herzegovina', + 'Botswana', + 'Bouvet Island', + 'Brazil', + 'British Indian Ocean Territory', + 'Brunei Darussalam', + 'Bulgaria', + 'Burkina Faso', + 'Burundi', + 'Cambodia', + 'Cameroon', + 'Canada', + 'Cape Verde', + 'Cayman Islands', + 'Central African Republic', + 'Chad', + 'Chile', + 'China', + 'Christmas Island', + 'Cocos (Keeling) Islands', + 'Colombia', + 'Comoros', + 'Congo', + 'Cook Islands', + 'Costa Rica', + "Cote D'ivoire", + 'Croatia', + 'Cuba', + 'Cyprus', + 'Czech Republic', + 'Denmark', + 'Djibouti', + 'Dominica', + 'Dominican Republic', + 'Ecuador', + 'Egypt', + 'El Salvador', + 'Equatorial Guinea', + 'Eritrea', + 'Estonia', + 'Ethiopia', + 'Falkland Islands (Malvinas)', + 'Faroe Islands', + 'Fiji', + 'Finland', + 'France', + 'French Guiana', + 'French Polynesia', + 'French Southern Territories', + 'Gabon', + 'Gambia', + 'Georgia', + 'Germany', + 'Ghana', + 'Gibraltar', + 'Greece', + 'Greenland', + 'Grenada', + 'Guadeloupe', + 'Guam', + 'Guatemala', + 'Guinea', + 'Guinea-bissau', + 'Guyana', + 'Haiti', + 'Heard Island and Mcdonald Islands', + 'Honduras', + 'Hong Kong', + 'Hungary', + 'Iceland', + 'India', + 'Indonesia', + 'Iran', + 'Iraq', + 'Ireland', + 'Israel', + 'Italy', + 'Jamaica', + 'Japan', + 'Jordan', + 'Kazakhstan', + 'Kenya', + 'Kiribati', + 'Korea (South)', + 'Kuwait', + 'Kyrgyzstan', + "Lao People's Democratic Republic", + 'Latvia', + 'Lebanon', + 'Lesotho', + 'Liberia', + 'Libyan Arab Jamahiriya', + 'Liechtenstein', + 'Lithuania', + 'Luxembourg', + 'Macao', + 'Macedonia', + 'Madagascar', + 'Malawi', + 'Malaysia', + 'Maldives', + 'Mali', + 'Malta', + 'Marshall Islands', + 'Martinique', + 'Mauritania', + 'Mauritius', + 'Mayotte', + 'Mexico', + 'Micronesia', + 'Moldova', + 'Monaco', + 'Mongolia', + 'Montserrat', + 'Morocco', + 'Mozambique', + 'Myanmar', + 'Namibia', + 'Nauru', + 'Nepal', + 'Netherlands', + 'Netherlands Antilles', + 'New Caledonia', + 'New Zealand', + 'Nicaragua', + 'Niger', + 'Nigeria', + 'Niue', + 'Norfolk Island', + 'Northern Mariana Islands', + 'Norway', + 'Oman', + 'Pakistan', + 'Palau', + 'Palestinian Territory', + 'Panama', + 'Papua New Guinea', + 'Paraguay', + 'Peru', + 'Philippines', + 'Pitcairn', + 'Poland', + 'Portugal', + 'Puerto Rico', + 'Qatar', + 'Reunion', + 'Romania', + 'Russia', + 'Rwanda', + 'Saint Helena', + 'Saint Kitts and Nevis', + 'Saint Lucia', + 'Saint Pierre and Miquelon', + 'Saint Vincent and The Grenadines', + 'Samoa', + 'San Marino', + 'Sao Tome and Principe', + 'Saudi Arabia', + 'Senegal', + 'Serbia and Montenegro', + 'Seychelles', + 'Sierra Leone', + 'Singapore', + 'Slovakia', + 'Slovenia', + 'Solomon Islands', + 'Somalia', + 'South Africa', + 'South Georgia and The South Sandwich Islands', + 'Spain', + 'Sri Lanka', + 'Sudan', + 'Suriname', + 'Svalbard and Jan Mayen', + 'Swaziland', + 'Sweden', + 'Switzerland', + 'Syria ', + 'Taiwan', + 'Tajikistan', + 'Tanzania', + 'Thailand', + 'Timor-leste', + 'Togo', + 'Tokelau', + 'Tonga', + 'Trinidad and Tobago', + 'Tunisia', + 'Turkey', + 'Turkmenistan', + 'Tuvalu', + 'Uganda', + 'Ukraine', + 'United Arab Emirates', + 'United Kingdom', + 'United States', + 'Uruguay', + 'Uzbekistan', + 'Vanuatu', + 'Venezuela', + 'Viet Nam', + 'Virgin Islands', + 'Wallis and Futuna', + 'Western Sahara', + 'Yemen', + 'Zambia', + 'Zimbabwe' + ].freeze -Countries = [ - "Afghanistan", - "Albania", - "Algeria", - "American Samoa", - "Andorra", - "Angola", - "Anguilla", - "Antarctica", - "Antigua and Barbuda", - "Argentina", - "Armenia", - "Aruba", - "Australia", - "Austria", - "Azerbaijan", - "Bahamas", - "Bahrain", - "Bangladesh", - "Barbados", - "Belarus", - "Belgium", - "Belize", - "Benin", - "Bermuda", - "Bhutan", - "Bolivia", - "Bosnia and Herzegovina", - "Botswana", - "Bouvet Island", - "Brazil", - "British Indian Ocean Territory", - "Brunei Darussalam", - "Bulgaria", - "Burkina Faso", - "Burundi", - "Cambodia", - "Cameroon", - "Canada", - "Cape Verde", - "Cayman Islands", - "Central African Republic", - "Chad", - "Chile", - "China", - "Christmas Island", - "Cocos (Keeling) Islands", - "Colombia", - "Comoros", - "Congo", - "Cook Islands", - "Costa Rica", - "Cote D'ivoire", - "Croatia", - "Cuba", - "Cyprus", - "Czech Republic", - "Denmark", - "Djibouti", - "Dominica", - "Dominican Republic", - "Ecuador", - "Egypt", - "El Salvador", - "Equatorial Guinea", - "Eritrea", - "Estonia", - "Ethiopia", - "Falkland Islands (Malvinas)", - "Faroe Islands", - "Fiji", - "Finland", - "France", - "French Guiana", - "French Polynesia", - "French Southern Territories", - "Gabon", - "Gambia", - "Georgia", - "Germany", - "Ghana", - "Gibraltar", - "Greece", - "Greenland", - "Grenada", - "Guadeloupe", - "Guam", - "Guatemala", - "Guinea", - "Guinea-bissau", - "Guyana", - "Haiti", - "Heard Island and Mcdonald Islands", - "Honduras", - "Hong Kong", - "Hungary", - "Iceland", - "India", - "Indonesia", - "Iran", - "Iraq", - "Ireland", - "Israel", - "Italy", - "Jamaica", - "Japan", - "Jordan", - "Kazakhstan", - "Kenya", - "Kiribati", - "Korea (South)", - "Kuwait", - "Kyrgyzstan", - "Lao People's Democratic Republic", - "Latvia", - "Lebanon", - "Lesotho", - "Liberia", - "Libyan Arab Jamahiriya", - "Liechtenstein", - "Lithuania", - "Luxembourg", - "Macao", - "Macedonia", - "Madagascar", - "Malawi", - "Malaysia", - "Maldives", - "Mali", - "Malta", - "Marshall Islands", - "Martinique", - "Mauritania", - "Mauritius", - "Mayotte", - "Mexico", - "Micronesia", - "Moldova", - "Monaco", - "Mongolia", - "Montserrat", - "Morocco", - "Mozambique", - "Myanmar", - "Namibia", - "Nauru", - "Nepal", - "Netherlands", - "Netherlands Antilles", - "New Caledonia", - "New Zealand", - "Nicaragua", - "Niger", - "Nigeria", - "Niue", - "Norfolk Island", - "Northern Mariana Islands", - "Norway", - "Oman", - "Pakistan", - "Palau", - "Palestinian Territory", - "Panama", - "Papua New Guinea", - "Paraguay", - "Peru", - "Philippines", - "Pitcairn", - "Poland", - "Portugal", - "Puerto Rico", - "Qatar", - "Reunion", - "Romania", - "Russia", - "Rwanda", - "Saint Helena", - "Saint Kitts and Nevis", - "Saint Lucia", - "Saint Pierre and Miquelon", - "Saint Vincent and The Grenadines", - "Samoa", - "San Marino", - "Sao Tome and Principe", - "Saudi Arabia", - "Senegal", - "Serbia and Montenegro", - "Seychelles", - "Sierra Leone", - "Singapore", - "Slovakia", - "Slovenia", - "Solomon Islands", - "Somalia", - "South Africa", - "South Georgia and The South Sandwich Islands", - "Spain", - "Sri Lanka", - "Sudan", - "Suriname", - "Svalbard and Jan Mayen", - "Swaziland", - "Sweden", - "Switzerland", - "Syria ", - "Taiwan", - "Tajikistan", - "Tanzania", - "Thailand", - "Timor-leste", - "Togo", - "Tokelau", - "Tonga", - "Trinidad and Tobago", - "Tunisia", - "Turkey", - "Turkmenistan", - "Tuvalu", - "Uganda", - "Ukraine", - "United Arab Emirates", - "United Kingdom", - "United States", - "Uruguay", - "Uzbekistan", - "Vanuatu", - "Venezuela", - "Viet Nam", - "Virgin Islands", - "Wallis and Futuna", - "Western Sahara", - "Yemen", - "Zambia", - "Zimbabwe" -] - - # Convert a full state name like "New Mexico" into a code like "NM" - # Will leave strings that are already state codes alone - def self.full_state_to_code(str) - str = str.strip - return str if StateCodes.include?(str.upcase) - return StateMappings[str.downcase] - end + # Convert a full state name like "New Mexico" into a code like "NM" + # Will leave strings that are already state codes alone + def self.full_state_to_code(str) + str = str.strip + return str if StateCodes.include?(str.upcase) + StateMappings[str.downcase] + end end; end diff --git a/lib/format/format/html.rb b/lib/format/format/html.rb index 23f2a543..8d2e5906 100644 --- a/lib/format/format/html.rb +++ b/lib/format/format/html.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Format module HTML def self.has_only_empty_tags(html_str) - return true if html_str && html_str.gsub(/<[^>]*>/ui,'').gsub(" ", "").strip == "" + return true if html_str && html_str.gsub(/<[^>]*>/ui, '').gsub(' ', '').strip == '' end end end diff --git a/lib/format/format/indefinitize.rb b/lib/format/format/indefinitize.rb index 68683734..e84fd2d9 100644 --- a/lib/format/format/indefinitize.rb +++ b/lib/format/format/indefinitize.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Format - module Indefinitize - VOWELS = %w(a e i o u) + module Indefinitize + VOWELS = %w[a e i o u].freeze - def self.article word - VOWELS.include?(word[0].downcase) ? 'an' : 'a' - end + def self.article(word) + VOWELS.include?(word[0].downcase) ? 'an' : 'a' + end - def self.with_article word - article(word) + ' ' + word - end - end + def self.with_article(word) + article(word) + ' ' + word + end + end end diff --git a/lib/format/format/interpolate.rb b/lib/format/format/interpolate.rb index dc53a5a7..16e1d3b9 100644 --- a/lib/format/format/interpolate.rb +++ b/lib/format/format/interpolate.rb @@ -1,9 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Format module Interpolate def self.with_hash(str, hash) return '' if str.nil? - str.gsub(/{{.+}}/){|key| hash[key.gsub(/[{}]/,'')]} + + str.gsub(/{{.+}}/) { |key| hash[key.gsub(/[{}]/, '')] } end end end diff --git a/lib/format/format/name.rb b/lib/format/format/name.rb index 53d4dccb..fea72fb2 100644 --- a/lib/format/format/name.rb +++ b/lib/format/format/name.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'active_support/core_ext' module Format - module Name - - def self.split_full(name) - return '' if name.nil? - name.split(/\ (\w+\s*)$/) - end + module Name + def self.split_full(name) + return '' if name.nil? + + name.split(/\ (\w+\s*)$/) + end # Format a nonprofit name into an email header def self.email_from_np(np_name) - "\"#{np_name.gsub(',', '').gsub("\"", '')}\" <#{Settings.mailer.email}>" + "\"#{np_name.delete(',').delete('"')}\" <#{Settings.mailer.email}>" end - end + end end diff --git a/lib/format/format/phone.rb b/lib/format/format/phone.rb index 81e88201..f20e21b4 100644 --- a/lib/format/format/phone.rb +++ b/lib/format/format/phone.rb @@ -1,22 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Format; module Phone - - def self.readable(number) - # Convert to: - # (505) 263-6320 - # or: - # 263-6320 - return '' if number.blank? - - stripped = number.gsub(/[-\(\)\.\s]/, '') # remove extra chars and space - if stripped.length == 10 - return "(#{stripped[0..2]}) #{stripped[3..5]}-#{stripped[6..9]}" - elsif stripped.length == 7 - return "#{stripped[0..2]}-#{stripped[3..6]}" - else - return number - end - end +module Format + module Phone + def self.readable(number) + # Convert to: + # (505) 263-6320 + # or: + # 263-6320 + return '' if number.blank? + stripped = number.gsub(/[-\(\)\.\s]/, '') # remove extra chars and space + if stripped.length == 10 + return "(#{stripped[0..2]}) #{stripped[3..5]}-#{stripped[6..9]}" + elsif stripped.length == 7 + return "#{stripped[0..2]}-#{stripped[3..6]}" + else + return number + end + end end; end - diff --git a/lib/format/format/remove_diacritics.rb b/lib/format/format/remove_diacritics.rb index 52680e0c..67ba2c74 100644 --- a/lib/format/format/remove_diacritics.rb +++ b/lib/format/format/remove_diacritics.rb @@ -1,16 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -require "i18n" +require 'i18n' module Format - module RemoveDiacritics - - def self.from_hash(hash, keys) - # returns a new hash with any diacritics replaced with a plain character + module RemoveDiacritics + def self.from_hash(hash, keys) + # returns a new hash with any diacritics replaced with a plain character # only from values corresponding to specified keys: - # {"city" => "São Paulo"} ["city"] will return {"city" => "Sao Paulo"} - Hash[hash.map{|k, v| [k, (keys.include? k) ? I18n.transliterate(v) : v]}] - end - - end + # {"city" => "São Paulo"} ["city"] will return {"city" => "Sao Paulo"} + Hash[hash.map { |k, v| [k, (keys.include? k) ? I18n.transliterate(v) : v] }] + end + end end - diff --git a/lib/format/format/timezone.rb b/lib/format/format/timezone.rb index 08cec6dc..2fac11f6 100644 --- a/lib/format/format/timezone.rb +++ b/lib/format/format/timezone.rb @@ -1,25 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Format module Timezone def self.to_proxy(str) - dict = { - "Hawaii" => 'Pacific/Honolulu', - "Alaska" => 'America/Juneau', - "Pacific Time (US & Canada)" => 'America/Los_Angeles', - "Arizona" => 'America/Phoenix', - "Mountain Time (US & Canada)" => 'America/Denver', - "Central Time (US & Canada)" => 'America/Chicago', - "Eastern Time (US & Canada)" => 'America/New_York', - "Indiana (East)" => 'America/Indiana/Indianapolis' + dict = { + 'Hawaii' => 'Pacific/Honolulu', + 'Alaska' => 'America/Juneau', + 'Pacific Time (US & Canada)' => 'America/Los_Angeles', + 'Arizona' => 'America/Phoenix', + 'Mountain Time (US & Canada)' => 'America/Denver', + 'Central Time (US & Canada)' => 'America/Chicago', + 'Eastern Time (US & Canada)' => 'America/New_York', + 'Indiana (East)' => 'America/Indiana/Indianapolis' } - if dict.has_key?(str) + if dict.key?(str) return dict[str] - elsif dict.has_value?(str) + elsif dict.value?(str) return str else - return false + return false end end end end - diff --git a/lib/format/format/url.rb b/lib/format/format/url.rb index 59a1fe42..1ff81c6f 100644 --- a/lib/format/format/url.rb +++ b/lib/format/format/url.rb @@ -1,27 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -module Format; module Url +module Format + module Url + def self.without_prefix(url) + url.gsub(%r{(http(s)?://)|(www\.)|(\?.*$)|(#.*$)}, '') + end - def self.without_prefix(url) - url.gsub(/(http(s)?:\/\/)|(www\.)|(\?.*$)|(#.*$)/, '') - end + # Given ["What hello", "hi! lol?"] + # Return ["what-hello", "hi-lol"] + def self.convert_to_slug(*words) + return '' if words.empty? || !words.all? # true if any are nil or empty - # Given ["What hello", "hi! lol?"] - # Return ["what-hello", "hi-lol"] - def self.convert_to_slug(*words) - return '' if words.empty? || !words.all? # true if any are nil or empty - words.map do |d| - d.strip.downcase - .gsub(/['`]/,'') # no apostrophes - .gsub(/\./,'') # no dots - .gsub(/\s*@\s*/, ' at ') # @ -> at - .gsub(/\s*&\s*/, ' and ') # & -> and - .gsub(/\s*[^A-Za-z0-9\.\-]\s*/, '-') # replace oddballs with hyphen - .gsub(/\A[-\.]+|[-\.]+\z/,'') # strip leading/trailing hyphens - end.join("/") - end - - def self.concat(*urls) - return urls.join('/').gsub(/([^:])\/\/+/,'\1/') - end + words.map do |d| + d.strip.downcase + .gsub(/['`]/, '') # no apostrophes + .delete('.') # no dots + .gsub(/\s*@\s*/, ' at ') # @ -> at + .gsub(/\s*&\s*/, ' and ') # & -> and + .gsub(/\s*[^A-Za-z0-9\.\-]\s*/, '-') # replace oddballs with hyphen + .gsub(/\A[-\.]+|[-\.]+\z/, '') # strip leading/trailing hyphens + end.join('/') + end + def self.concat(*urls) + urls.join('/').gsub(%r{([^:])//+}, '\1/') + end end; end diff --git a/lib/generators/api/entity/entity_generator.rb b/lib/generators/api/entity/entity_generator.rb index 8e781872..1382f313 100644 --- a/lib/generators/api/entity/entity_generator.rb +++ b/lib/generators/api/entity/entity_generator.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails/generators' class Api::EntityGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_to_entity - template 'entity.rb.erb', File.join("app/api/houdini/v1/entities", "#{name.underscore}.rb") + template 'entity.rb.erb', File.join('app/api/houdini/v1/entities', "#{name.underscore}.rb") end end diff --git a/lib/generators/api/resource/resource_generator.rb b/lib/generators/api/resource/resource_generator.rb index 99aef6b1..a233320f 100644 --- a/lib/generators/api/resource/resource_generator.rb +++ b/lib/generators/api/resource/resource_generator.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails/generators' class Api::ResourceGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_to_resource - template 'resource.rb.erb', File.join("app/api/houdini/v1", "#{name.underscore}.rb") + template 'resource.rb.erb', File.join('app/api/houdini/v1', "#{name.underscore}.rb") end def copy_to_spec - template 'spec.rb.erb', File.join("spec/api/houdini/", "#{name.underscore}_spec.rb") + template 'spec.rb.erb', File.join('spec/api/houdini/', "#{name.underscore}_spec.rb") end def add_to_root_api - inject_into_file "app/api/houdini/v1/api.rb", "mount Houdini::V1::#{ name.camelcase} => \"/#{name.underscore}\"\n ", before:"# Additional mounts are added via generators above this line" + inject_into_file 'app/api/houdini/v1/api.rb', "mount Houdini::V1::#{name.camelcase} => \"/#{name.underscore}\"\n ", before: '# Additional mounts are added via generators above this line' end end diff --git a/lib/generators/api/validator/validator_generator.rb b/lib/generators/api/validator/validator_generator.rb index 7c57d094..23492492 100644 --- a/lib/generators/api/validator/validator_generator.rb +++ b/lib/generators/api/validator/validator_generator.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails/generators' class Api::ValidatorGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_to_validators - post_api_part = File.join("houdini/v1/validators", "#{name.underscore}.rb") - output_file = File.join("app/api", post_api_part ) + post_api_part = File.join('houdini/v1/validators', "#{name.underscore}.rb") + output_file = File.join('app/api', post_api_part) template 'validator.rb.erb', output_file end def add_to_root_validations - post_api_part = File.join("houdini/v1/validators", "#{name.underscore}") - append_to_file "app/api/houdini/v1/validations.rb", "\nrequire '#{post_api_part}'" + post_api_part = File.join('houdini/v1/validators', name.underscore.to_s) + append_to_file 'app/api/houdini/v1/validations.rb', "\nrequire '#{post_api_part}'" end end diff --git a/lib/generators/email_job/email_job_generator.rb b/lib/generators/email_job/email_job_generator.rb index 64de7f90..67138a48 100644 --- a/lib/generators/email_job/email_job_generator.rb +++ b/lib/generators/email_job/email_job_generator.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class EmailJobGenerator < Rails::Generators::NamedBase - argument :attribs, :type => :array - source_root File.expand_path('../templates', __FILE__) + argument :attribs, type: :array + source_root File.expand_path('templates', __dir__) def copy_file_to_lib template 'email_job_template.erb', "lib/job_types/#{name.underscore}.rb" template 'email_job_spec_template.erb', "spec/lib/job_types/#{name.underscore}_spec.rb" diff --git a/lib/generators/libmodule/libmodule_generator.rb b/lib/generators/libmodule/libmodule_generator.rb index 0232b220..d82497e9 100644 --- a/lib/generators/libmodule/libmodule_generator.rb +++ b/lib/generators/libmodule/libmodule_generator.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class LibmoduleGenerator < Rails::Generators::NamedBase - argument :mod_type, :type => :string - source_root File.expand_path('../templates', __FILE__) + argument :mod_type, type: :string + source_root File.expand_path('templates', __dir__) def copy_file_to_lib template 'libmodule_template.erb', "lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}.rb" template 'libmodule_spec_template.erb', "spec/lib/#{mod_type.underscore}/#{mod_type.underscore}_#{name.underscore}_spec.rb" diff --git a/lib/generators/react/component/component_generator.rb b/lib/generators/react/component/component_generator.rb index 96b6b92e..fa2ae5a4 100644 --- a/lib/generators/react/component/component_generator.rb +++ b/lib/generators/react/component/component_generator.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class React::ComponentGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_file_to_component - template 'component.tsx.erb', File.join("javascripts/src/components", *(class_path + ["#{file_name.camelize}.tsx"])) - template 'component.spec.tsx.erb', File.join("javascripts/src/components", *(class_path + ["#{file_name.camelize}.spec.tsx"])) + template 'component.tsx.erb', File.join('javascripts/src/components', *(class_path + ["#{file_name.camelize}.tsx"])) + template 'component.spec.tsx.erb', File.join('javascripts/src/components', *(class_path + ["#{file_name.camelize}.spec.tsx"])) end end diff --git a/lib/generators/react/lib/lib_generator.rb b/lib/generators/react/lib/lib_generator.rb index 1f07f34e..f40bcb67 100644 --- a/lib/generators/react/lib/lib_generator.rb +++ b/lib/generators/react/lib/lib_generator.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + class React::LibGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_file_to_lib - template 'module.ts.erb', File.join("javascripts/src/lib/", *(class_path + ["#{file_name.underscore}.ts"])) - template 'module.spec.ts.erb', File.join("javascripts/src/lib/", *(class_path + ["#{file_name.underscore}.spec.ts"])) + template 'module.ts.erb', File.join('javascripts/src/lib/', *(class_path + ["#{file_name.underscore}.ts"])) + template 'module.spec.ts.erb', File.join('javascripts/src/lib/', *(class_path + ["#{file_name.underscore}.spec.ts"])) end end diff --git a/lib/generators/react/packroot/packroot_generator.rb b/lib/generators/react/packroot/packroot_generator.rb index a684165a..06354227 100644 --- a/lib/generators/react/packroot/packroot_generator.rb +++ b/lib/generators/react/packroot/packroot_generator.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module React class PackrootGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_file_to_app template 'page.tsx.erb', "javascripts/app/#{file_name.underscore}.tsx" generate 'react:component', "#{file_name.underscore}/#{file_name.camelize}" end end end - diff --git a/lib/generators/ts/declaration/declaration_generator.rb b/lib/generators/ts/declaration/declaration_generator.rb index 3c1a9e09..d7bbc609 100644 --- a/lib/generators/ts/declaration/declaration_generator.rb +++ b/lib/generators/ts/declaration/declaration_generator.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Ts::DeclarationGenerator < Rails::Generators::NamedBase - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def copy_template - template 'template.d.ts.erb', File.join("types", name, 'index.d.ts') + template 'template.d.ts.erb', File.join('types', name, 'index.d.ts') end end diff --git a/lib/geocode_model.rb b/lib/geocode_model.rb index cf802e54..2d4903c6 100644 --- a/lib/geocode_model.rb +++ b/lib/geocode_model.rb @@ -1,47 +1,46 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module GeocodeModel - def self.supporter(id) supp = Supporter.find_by_id(id) - if supp.address && supp.state_code && supp.city - with_reverse(supp) - end + with_reverse(supp) if supp.address && supp.state_code && supp.city end - # Just a wrapper around a model's geocode method for delaying with: - # GeocodeModel.delay.geocode(user) - def self.geocode(model) - begin - model.geocode - rescue Exception => e - puts e - end - model.save - model - end + # Just a wrapper around a model's geocode method for delaying with: + # GeocodeModel.delay.geocode(user) + def self.geocode(model) + begin + model.geocode + rescue Exception => e + puts e + end + model.save + model + end - def self.with_reverse(model) - begin - model.geocode - model.reverse_geocode - rescue Exception => e - puts e - end - model.save - model - end + def self.with_reverse(model) + begin + model.geocode + model.reverse_geocode + rescue Exception => e + puts e + end + model.save + model + end - # Geocode and get the timezone for a model - def self.with_timezone(model) - begin - geocode(model) - rescue Exception => e - puts e - end - return model unless model.latitude && model.longitude + # Geocode and get the timezone for a model + def self.with_timezone(model) + begin + geocode(model) + rescue Exception => e + puts e + end + return model unless model.latitude && model.longitude - model.timezone = NearestTimeZone.to(model.latitude, model.longitude) - model.save - model - end + model.timezone = NearestTimeZone.to(model.latitude, model.longitude) + model.save + model + end end diff --git a/lib/get_data.rb b/lib/get_data.rb index 295fc19f..71ab6957 100644 --- a/lib/get_data.rb +++ b/lib/get_data.rb @@ -1,33 +1,33 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module GetData + def self.chain(obj, *methods) + methods.each do |m| + if m.is_a?(Array) + params = m[1..-1] + m = m[0] + end - def self.chain(obj, *methods) - methods.each do |m| - if m.is_a?(Array) - params = m[1..-1] - m = m[0] - end - - if obj != nil && obj.respond_to?(m) - obj = obj.send(m, *params) - elsif obj.respond_to?(:has_key?) && obj.has_key?(m) - obj = obj[m] - else - return nil - end - end - return obj - end + if !obj.nil? && obj.respond_to?(m) + obj = obj.send(m, *params) + elsif obj.respond_to?(:has_key?) && obj.key?(m) + obj = obj[m] + else + return nil + end + end + obj + end def self.hash(h, *keys) - keys.each do |k| - if h.has_key?(k) - h = h[k] - else - return nil - end - end - return h + keys.each do |k| + if h.key?(k) + h = h[k] + else + return nil + end + end + h end end - diff --git a/lib/hash.rb b/lib/hash.rb index d12f3b70..8c00bc76 100644 --- a/lib/hash.rb +++ b/lib/hash.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Hash def keep_keys(*keys) - keys = keys.map{|k| k.to_s} - clone.delete_if{|k,v| !keys.include?(k.to_s)} + keys = keys.map(&:to_s) + clone.delete_if { |k, _v| !keys.include?(k.to_s) } end def keep_keys!(*keys) - keys = keys.map{|k| k.to_s} - delete_if{|k,v| !keys.include?(k.to_s)} + keys = keys.map(&:to_s) + delete_if { |k, _v| !keys.include?(k.to_s) } end end diff --git a/lib/health_report.rb b/lib/health_report.rb index 53e4130c..e93ca417 100644 --- a/lib/health_report.rb +++ b/lib/health_report.rb @@ -1,34 +1,35 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'format/csv' require 'format/currency' - module HealthReport # Send an email report about what has happend on the servers and database in the last 24hrs, and how things are running # Returns a hash of metrics data def self.query_data # Transaction metrics - charges = Qx.select("COUNT(charges.id), SUM(charges.amount), SUM(charges.fee) as fees") - .from("charges") - .where("created_at > $d", d: 24.hours.ago) - .and_where("charges.status != 'failed'") - .ex.last + charges = Qx.select('COUNT(charges.id), SUM(charges.amount), SUM(charges.fee) as fees') + .from('charges') + .where('created_at > $d', d: 24.hours.ago) + .and_where("charges.status != 'failed'") + .ex.last # Recurring donation metrics - rec_dons = Qx.select("COUNT(id), SUM(amount)") - .from("recurring_donations") - .where("active=TRUE") - .ex.last + rec_dons = Qx.select('COUNT(id), SUM(amount)') + .from('recurring_donations') + .where('active=TRUE') + .ex.last # Info about disabled nonprofit accounts due to ident verification - disabled_nps = Qx.select("nonprofits.id", "nonprofits.name", "nonprofits.stripe_account_id") - .from("nonprofits") - .where("verification_status != 'verified'") - .and_where("created_at > $d", d: 3.months.ago) - .ex(format: 'csv') + disabled_nps = Qx.select('nonprofits.id', 'nonprofits.name', 'nonprofits.stripe_account_id') + .from('nonprofits') + .where("verification_status != 'verified'") + .and_where('created_at > $d', d: 3.months.ago) + .ex(format: 'csv') - return { + { charges_count: charges['count'], charges_sum: charges['sum'], charges_fees: charges['fees'], @@ -39,10 +40,10 @@ module HealthReport end # Given a hash of data, formats it into a multi-line string - def self.format_data data + def self.format_data(data) disabled_nps = Format::Csv.from_array(data[:recently_disabled_nps]) - return %Q( + %( Transaction Metrics for the last 24hrs: Total count: #{data[:charges_count]} Total amount: $#{Format::Currency.cents_to_dollars(data[:charges_sum])} diff --git a/lib/htp.rb b/lib/htp.rb index 7385bbb0..ee28d9ee 100644 --- a/lib/htp.rb +++ b/lib/htp.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Hamster Table Print diff --git a/lib/image.rb b/lib/image.rb index 9e7a8e65..c25bcc72 100644 --- a/lib/image.rb +++ b/lib/image.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module Image + AssetPath = 'https://dmnsmycmdpaix.cloudfront.net/uploads' - AssetPath = "https://dmnsmycmdpaix.cloudfront.net/uploads" + DefaultProfileUrl = Settings.default.image.profile + DefaultNonprofitUrl = Settings.default.image.nonprofit + DefaultCampaignUrl = Settings.default.image.campaign - DefaultProfileUrl = Settings.default.image.profile; - DefaultNonprofitUrl = Settings.default.image.nonprofit; - DefaultCampaignUrl = Settings.default.image.campaign; - - def self._url(resource_name, image_name, version='normal') - %Q( + def self._url(resource_name, image_name, version = 'normal') + %( concat(#{Qexpr.quote AssetPath} , '/', #{Qexpr.quote resource_name} , '/', #{Qexpr.quote image_name} , '/', #{resource_name + '.id'} , '/', #{Qexpr.quote version}, '_', #{resource_name + '.' + image_name}) - ) + ) end end diff --git a/lib/import/import_civicrm_payments.rb b/lib/import/import_civicrm_payments.rb index 71bac5ff..257c74e9 100644 --- a/lib/import/import_civicrm_payments.rb +++ b/lib/import/import_civicrm_payments.rb @@ -1,93 +1,81 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ImportCivicrmPayments - ## MINIMALLY TESTED!!! def self.import_from_csv(csv_body, nonprofit, field_of_supporter_id) - Qx.transaction do - CSV::Converters[:blank_to_nil] = lambda do |field| - field && field.empty? ? nil : field + Qx.transaction do + CSV::Converters[:blank_to_nil] = lambda do |field| + field && field.empty? ? nil : field + end + + csv = CSV.new(csv_body, headers: true, converters: [:blank_to_nil]) + contrib_records = csv.to_a.map(&:to_hash) + pay_imp = PaymentImport.create(nonprofit: nonprofit) + + supporter_id_custom_field = CustomFieldMaster.where('nonprofit_id = ? AND name = ?', nonprofit.id, field_of_supporter_id).first + + unless supporter_id_custom_field + raise ParamValidation::ValidationError.new("There is no custom field for nonprofit #{nonprofit.id} and field named #{field_of_supporter_id}", key: :field_of_supporter_id) + end + + supporters_with_fields = Supporter.includes(:custom_field_joins).where('supporters.nonprofit_id = ? AND custom_field_joins.custom_field_master_id = ?', nonprofit.id, supporter_id_custom_field.id) + questionable_records = [] + contrib_records.each do |r| + our_supporter = supporters_with_fields.where('custom_field_joins.value = ?', r[field_of_supporter_id].to_s).first + unless our_supporter + questionable_records.push(r) + next + end + + known_fields = ['Date Received', 'Total Amount'] + + notes = '' + r.except(known_fields).keys.each do |k| + notes += "#{k}: #{r[k]}\n" + end + + offsite = nil + if r['payment_instrument'] == 'Check' + offsite = { kind: 'check', check_number: r['Check Number'] } + end + + puts r['Date Received'] + date_received = nil + + Time.use_zone('Pacific Time (US & Canada)') do + date_received = Time.zone.parse(r['Date Received']) + puts date_received + end + + d = InsertDonation.offsite( + { + amount: Format::Currency.dollars_to_cents(r['Total Amount']), + nonprofit_id: nonprofit.id, + supporter_id: our_supporter.id, + comment: notes, + date: date_received.to_s, + offsite_payment: offsite + }.with_indifferent_access + ) + puts d + pay_imp.donations.push(Donation.find(d[:json]['donation']['id'])) + end + questionable_records end - - csv = CSV.new(csv_body, :headers => true, :converters => [ :blank_to_nil]) - contrib_records = csv.to_a.map {|row| row.to_hash } - pay_imp = PaymentImport.create(nonprofit: nonprofit) - - supporter_id_custom_field = CustomFieldMaster.where("nonprofit_id = ? AND name = ?", nonprofit.id, field_of_supporter_id).first - - unless supporter_id_custom_field - raise ParamValidation::ValidationError.new("There is no custom field for nonprofit #{nonprofit.id} and field named #{field_of_supporter_id}", {key: :field_of_supporter_id}) - end - - supporters_with_fields = Supporter.includes(:custom_field_joins).where("supporters.nonprofit_id = ? AND custom_field_joins.custom_field_master_id = ?", nonprofit.id, supporter_id_custom_field.id) - questionable_records = [] - contrib_records.each {|r| - - our_supporter = supporters_with_fields.where('custom_field_joins.value = ?', r[field_of_supporter_id].to_s).first - unless our_supporter - questionable_records.push(r) - next - end - - known_fields = ['Date Received', 'Total Amount', ] - - notes = "" - r.except(known_fields).keys.each{|k| - notes += "#{k}: #{r[k]}\n" - } - - - offsite = nil - if r['payment_instrument'] == 'Check' - offsite = {kind: 'check', check_number: r['Check Number']} - end - - puts r['Date Received'] - date_received = nil - - - Time.use_zone('Pacific Time (US & Canada)') do - date_received = Time.zone.parse(r['Date Received']) - puts date_received - end - - - - - d = InsertDonation.offsite( - { - amount: Format::Currency.dollars_to_cents(r['Total Amount']), - nonprofit_id: nonprofit.id, - supporter_id: our_supporter.id, - comment: notes, - date: date_received.to_s, - offsite_payment: offsite - }.with_indifferent_access - ) - puts d - pay_imp.donations.push(Donation.find(d[:json]['donation']['id'])) - } - questionable_records - end end def self.undo(import_id) Qx.transaction do - import = PaymentImport.find(import_id) - import.donations.each{|d| + import = PaymentImport.find(import_id) + import.donations.each do |d| + d.payments.each(&:destroy) + d.offsite_payment&.destroy - d.payments.each{|p| - p.destroy - } - if d.offsite_payment - d.offsite_payment.destroy + d.destroy end - - d.destroy - - } - - import.destroy + import.destroy end end -end \ No newline at end of file +end diff --git a/lib/include_asset.rb b/lib/include_asset.rb index cd10bdb3..924946c1 100644 --- a/lib/include_asset.rb +++ b/lib/include_asset.rb @@ -1,18 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module IncludeAsset - # These are custom asset include functions for use in views that cache-bust using the current git version def self.js(path) - %Q().html_safe + %().html_safe end def self.css(path) - %Q().html_safe + %().html_safe end -private - + private + def self.asset_version ENV['ASSET_VERSION'] end diff --git a/lib/insert/insert_activities.rb b/lib/insert/insert_activities.rb index 7fe6aa18..5bfc572d 100644 --- a/lib/insert/insert_activities.rb +++ b/lib/insert/insert_activities.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'active_support/core_ext' @@ -5,9 +7,8 @@ require 'format/currency' require 'format/date' module InsertActivities - def self.insert_cols - ["action_type", "public", "created_at", "updated_at", "supporter_id", "attachment_type", "attachment_id", "nonprofit_id", "date", "json_data", "kind"] + %w[action_type public created_at updated_at supporter_id attachment_type attachment_id nonprofit_id date json_data kind] end # These line up with the above columns @@ -26,188 +27,186 @@ module InsertActivities def self.for_recurring_donations(payment_ids) insert_recurring_donations_expr - .and_where("payments.id IN ($ids)", ids: payment_ids) + .and_where('payments.id IN ($ids)', ids: payment_ids) .execute end def self.insert_recurring_donations_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - "payments.supporter_id", - "'Payment' AS attachment_type", - "payments.id AS attachment_id", - "payments.nonprofit_id", - "payments.date", - "json_build_object('gross_amount', payments.gross_amount, 'start_date', donations.created_at, 'designation', donations.designation, 'dedication', donations.dedication, 'interval', recurring_donations.interval, 'time_unit', recurring_donations.time_unit)", - "'RecurringDonation' AS kind" - ])) + 'payments.supporter_id', + "'Payment' AS attachment_type", + 'payments.id AS attachment_id', + 'payments.nonprofit_id', + 'payments.date', + "json_build_object('gross_amount', payments.gross_amount, 'start_date', donations.created_at, 'designation', donations.designation, 'dedication', donations.dedication, 'interval', recurring_donations.interval, 'time_unit', recurring_donations.time_unit)", + "'RecurringDonation' AS kind" + ])) .from(:payments) - .join(:donations, "donations.id=payments.donation_id") - .add_join(:recurring_donations, "recurring_donations.donation_id=donations.id") + .join(:donations, 'donations.id=payments.donation_id') + .add_join(:recurring_donations, 'recurring_donations.donation_id=donations.id') .where("payments.kind='RecurringDonation'") end def self.for_one_time_donations(payment_ids) insert_one_time_donations_expr - .and_where("payments.id IN ($ids)", ids: payment_ids) + .and_where('payments.id IN ($ids)', ids: payment_ids) .execute end def self.insert_one_time_donations_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - "payments.supporter_id", - "'Payment' AS attachment_type", - "payments.id AS attachment_id", - "payments.nonprofit_id", - "payments.date", - "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'dedication', donations.dedication)", - "'Donation' AS kind" - ])) + 'payments.supporter_id', + "'Payment' AS attachment_type", + 'payments.id AS attachment_id', + 'payments.nonprofit_id', + 'payments.date', + "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'dedication', donations.dedication)", + "'Donation' AS kind" + ])) .from(:payments) - .join(:donations, "donations.id=payments.donation_id") + .join(:donations, 'donations.id=payments.donation_id') .where("payments.kind='Donation'") end - + def self.for_tickets(ticket_ids) insert_tickets_expr - .and_where("tickets.id IN ($ids)", ids: ticket_ids) + .and_where('tickets.id IN ($ids)', ids: ticket_ids) .execute end def self.insert_tickets_expr Qx.insert_into(:activities, insert_cols) - .select(defaults.concat([ - "tickets.supporter_id", - "'Ticket' AS attachment_type", - "tickets.id AS attachment_id", - "event.nonprofit_id", - "tickets.created_at AS date", - "json_build_object('gross_amount', coalesce(payment.gross_amount, 0), 'event_name', event.name, 'event_id', event.id, 'quantity', tickets.quantity)", - "'Ticket' AS kind" - ])) + .select(defaults.concat([ + 'tickets.supporter_id', + "'Ticket' AS attachment_type", + 'tickets.id AS attachment_id', + 'event.nonprofit_id', + 'tickets.created_at AS date', + "json_build_object('gross_amount', coalesce(payment.gross_amount, 0), 'event_name', event.name, 'event_id', event.id, 'quantity', tickets.quantity)", + "'Ticket' AS kind" + ])) .from(:tickets) - .join("payments AS payment", "payment.id=tickets.payment_id") - .add_join("events AS event", "event.id=tickets.event_id") + .join('payments AS payment', 'payment.id=tickets.payment_id') + .add_join('events AS event', 'event.id=tickets.event_id') end def self.for_refunds(payment_ids) insert_refunds_expr - .and_where("payments.id IN ($ids)", ids: payment_ids) + .and_where('payments.id IN ($ids)', ids: payment_ids) .execute end def self.insert_refunds_expr - Qx.insert_into(:activities, insert_cols.concat(["user_id"])) + Qx.insert_into(:activities, insert_cols.concat(['user_id'])) .select(defaults.concat([ - "payments.supporter_id", - "'Payment' AS attachment_type", - "payments.id AS attachment_id", - "payments.nonprofit_id", - "payments.date", - "json_build_object('gross_amount', payments.gross_amount, 'reason', refunds.reason, 'user_email', users.email)", - "'Refund' AS kind", - "users.id AS user_id" - ])) + 'payments.supporter_id', + "'Payment' AS attachment_type", + 'payments.id AS attachment_id', + 'payments.nonprofit_id', + 'payments.date', + "json_build_object('gross_amount', payments.gross_amount, 'reason', refunds.reason, 'user_email', users.email)", + "'Refund' AS kind", + 'users.id AS user_id' + ])) .from(:payments) - .join(:refunds, "refunds.payment_id=payments.id") - .left_join(:users, "refunds.user_id=users.id") + .join(:refunds, 'refunds.payment_id=payments.id') + .left_join(:users, 'refunds.user_id=users.id') .where("payments.kind='Refund'") end def self.for_disputes(payment_ids) insert_disputes_expr - .and_where("payments.id IN ($ids)", ids: payment_ids) + .and_where('payments.id IN ($ids)', ids: payment_ids) .execute end def self.insert_disputes_expr Qx.insert_into(:activities, insert_cols) .select(defaults.concat([ - "payments.supporter_id", - "'Payment' AS attachment_type", - "payments.id AS attachment_id", - "payments.nonprofit_id", - "payments.date", - "json_build_object('gross_amount', payments.gross_amount, 'reason', disputes.reason, 'original_kind', other_payment.kind, 'original_date', other_payment.date)", - "'Dispute' AS kind" - ])) + 'payments.supporter_id', + "'Payment' AS attachment_type", + 'payments.id AS attachment_id', + 'payments.nonprofit_id', + 'payments.date', + "json_build_object('gross_amount', payments.gross_amount, 'reason', disputes.reason, 'original_kind', other_payment.kind, 'original_date', other_payment.date)", + "'Dispute' AS kind" + ])) .from(:payments) - .join(:disputes, "disputes.payment_id=payments.id") - .add_join(:charges, "disputes.charge_id=charges.id") - .add_join("payments AS other_payment", "other_payment.id=charges.payment_id") + .join(:disputes, 'disputes.payment_id=payments.id') + .add_join(:charges, 'disputes.charge_id=charges.id') + .add_join('payments AS other_payment', 'other_payment.id=charges.payment_id') .where("payments.kind='Dispute'") end def self.for_supporter_emails(ids) insert_supporter_emails_expr - .and_where("supporter_emails.id IN ($ids)", ids: ids) + .and_where('supporter_emails.id IN ($ids)', ids: ids) .execute end def self.insert_supporter_emails_expr - Qx.insert_into(:activities, insert_cols.concat(["user_id"])) - .select(defaults.concat([ - "supporter_emails.supporter_id", - "'SupporterEmail' AS attachment_type", - "supporter_emails.id AS attachment_id", - "supporter_emails.nonprofit_id", - "supporter_emails.created_at AS date", - "json_build_object('gmail_thread_id', supporter_emails.gmail_thread_id, 'subject', supporter_emails.subject, 'from', supporter_emails.from)", - "'SupporterEmail' AS kind", - "users.id AS user_id" - ])) + Qx.insert_into(:activities, insert_cols.concat(['user_id'])) + .select(defaults.concat([ + 'supporter_emails.supporter_id', + "'SupporterEmail' AS attachment_type", + 'supporter_emails.id AS attachment_id', + 'supporter_emails.nonprofit_id', + 'supporter_emails.created_at AS date', + "json_build_object('gmail_thread_id', supporter_emails.gmail_thread_id, 'subject', supporter_emails.subject, 'from', supporter_emails.from)", + "'SupporterEmail' AS kind", + 'users.id AS user_id' + ])) .from(:supporter_emails) - .left_join(:users, "users.id=supporter_emails.user_id") + .left_join(:users, 'users.id=supporter_emails.user_id') end def self.for_supporter_notes(ids) insert_supporter_notes_expr - .and_where("supporter_notes.id IN ($ids)", ids: ids) + .and_where('supporter_notes.id IN ($ids)', ids: ids) .execute end def self.insert_supporter_notes_expr - Qx.insert_into(:activities, insert_cols.concat(["user_id"])) - .select(defaults.concat([ - "supporter_notes.supporter_id", - "'SupporterEmail' AS attachment_type", - "supporter_notes.id AS attachment_id", - "supporters.nonprofit_id", - "supporter_notes.created_at AS date", - "json_build_object('content', supporter_notes.content, 'user_email', users.email)", - "'SupporterNote' AS kind", - "users.id AS user_id" - ])) + Qx.insert_into(:activities, insert_cols.concat(['user_id'])) + .select(defaults.concat([ + 'supporter_notes.supporter_id', + "'SupporterEmail' AS attachment_type", + 'supporter_notes.id AS attachment_id', + 'supporters.nonprofit_id', + 'supporter_notes.created_at AS date', + "json_build_object('content', supporter_notes.content, 'user_email', users.email)", + "'SupporterNote' AS kind", + 'users.id AS user_id' + ])) .from(:supporter_notes) - .join("supporters", "supporters.id=supporter_notes.supporter_id") - .add_left_join(:users, "users.id=supporter_notes.user_id") + .join('supporters', 'supporters.id=supporter_notes.supporter_id') + .add_left_join(:users, 'users.id=supporter_notes.user_id') end def self.for_offsite_donations(payment_ids) insert_offsite_donations_expr - .and_where("payments.id IN ($ids)", ids: payment_ids) + .and_where('payments.id IN ($ids)', ids: payment_ids) .execute end def self.insert_offsite_donations_expr - Qx.insert_into(:activities, insert_cols.concat(["user_id"])) - .select(defaults.concat([ - "payments.supporter_id", - "'Payment' AS attachment_type", - "payments.id AS attachment_id", - "payments.nonprofit_id", - "payments.date", - "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'user_email', users.email)", - "'OffsitePayment' AS kind", - "users.id AS user_id" - ])) + Qx.insert_into(:activities, insert_cols.concat(['user_id'])) + .select(defaults.concat([ + 'payments.supporter_id', + "'Payment' AS attachment_type", + 'payments.id AS attachment_id', + 'payments.nonprofit_id', + 'payments.date', + "json_build_object('gross_amount', payments.gross_amount, 'designation', donations.designation, 'user_email', users.email)", + "'OffsitePayment' AS kind", + 'users.id AS user_id' + ])) .from(:payments) .where("payments.kind = 'OffsitePayment'") - .join(:offsite_payments, "offsite_payments.payment_id=payments.id") - .add_join(:donations, "payments.donation_id=donations.id") - .add_left_join(:users, "users.id=offsite_payments.user_id") + .join(:offsite_payments, 'offsite_payments.payment_id=payments.id') + .add_join(:donations, 'payments.donation_id=donations.id') + .add_left_join(:users, 'users.id=offsite_payments.user_id') end - - end diff --git a/lib/insert/insert_bank_account.rb b/lib/insert/insert_bank_account.rb index c96f1b70..d6e7e32d 100644 --- a/lib/insert/insert_bank_account.rb +++ b/lib/insert/insert_bank_account.rb @@ -1,67 +1,63 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertBankAccount - # @param [Nonprofit] nonprofit # # stripe_bank_account_token: data.stripe_resp.id, - #stripe_bank_account_id: data.stripe_resp.bank_account.id, - # name: data.stripe_resp.bank_account.bank_name + ' *' + data.stripe_resp.bank_account.last4, - # email: app.user.email + # stripe_bank_account_id: data.stripe_resp.bank_account.id, + # name: data.stripe_resp.bank_account.bank_name + ' *' + data.stripe_resp.bank_account.last4, + # email: app.user.email def self.with_stripe(nonprofit, user, params) - ParamValidation.new({nonprofit: nonprofit, user: user}, { - :nonprofit => { - :required => true, - :is_a => Nonprofit - }, - :user => { - :required => true, - :is_a => User - } - }) - ParamValidation.new(params|| {}, { - :stripe_bank_account_token => { - :required => true, - :not_blank => true - } - }) + ParamValidation.new({ nonprofit: nonprofit, user: user }, + nonprofit: { + required: true, + is_a: Nonprofit + }, + user: { + required: true, + is_a: User + }) + ParamValidation.new(params || {}, + stripe_bank_account_token: { + required: true, + not_blank: true + }) - unless (nonprofit.vetted) - raise ArgumentError.new "#{nonprofit.id} is not vetted." + unless nonprofit.vetted + raise ArgumentError, "#{nonprofit.id} is not vetted." end stripe_acct = Stripe::Account.retrieve(StripeAccount.find_or_create(nonprofit.id)) nonprofit.reload - #this shouldn't be possible but we'll check any who - if (nonprofit.stripe_account_id.blank?) - raise ArgumentError.new "#{nonprofit.id} does not have a valid stripe_account_id associated with it" + # this shouldn't be possible but we'll check any who + if nonprofit.stripe_account_id.blank? + raise ArgumentError, "#{nonprofit.id} does not have a valid stripe_account_id associated with it" end Qx.transaction do - begin - ba = stripe_acct.external_accounts.create(external_account: params[:stripe_bank_account_token]) - ba.default_for_currency = true - ba.save + ba = stripe_acct.external_accounts.create(external_account: params[:stripe_bank_account_token]) + ba.default_for_currency = true + ba.save - BankAccount.where('nonprofit_id = ?', nonprofit.id).update_all(deleted: true) + BankAccount.where('nonprofit_id = ?', nonprofit.id).update_all(deleted: true) - bank_account = BankAccount.create( - stripe_bank_account_id: ba.id, - stripe_bank_account_token: params[:stripe_bank_account_token], - confirmation_token: SecureRandom.uuid, - nonprofit: nonprofit, - name: params[:name] || "Bank #{SecureRandom.uuid}", - email: user.email, - pending_verification: true - ) + bank_account = BankAccount.create( + stripe_bank_account_id: ba.id, + stripe_bank_account_token: params[:stripe_bank_account_token], + confirmation_token: SecureRandom.uuid, + nonprofit: nonprofit, + name: params[:name] || "Bank #{SecureRandom.uuid}", + email: user.email, + pending_verification: true + ) - NonprofitMailer.delay.new_bank_account_notification(bank_account) - return bank_account - rescue Stripe::StripeError => error - params[:failure_message] = "Failed to connect the bank account: #{error.inspect}" - raise ArgumentError.new("Failed to connect the bank account: #{error.inspect}") - end + NonprofitMailer.delay.new_bank_account_notification(bank_account) + return bank_account + rescue Stripe::StripeError => error + params[:failure_message] = "Failed to connect the bank account: #{error.inspect}" + raise ArgumentError, "Failed to connect the bank account: #{error.inspect}" end - end -end \ No newline at end of file +end diff --git a/lib/insert/insert_billing_subscriptions.rb b/lib/insert/insert_billing_subscriptions.rb index 48bfecc0..be663533 100644 --- a/lib/insert/insert_billing_subscriptions.rb +++ b/lib/insert/insert_billing_subscriptions.rb @@ -1,23 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'delayed_job_helper' require 'active_support/core_ext' - module InsertBillingSubscriptions - def self.trial(np_id, stripe_plan_id) - begin - nonprofit = Nonprofit.includes(:billing_subscription).find(np_id) - billing_plan = BillingPlan.where('stripe_plan_id = ?', stripe_plan_id).last - sub = nonprofit.create_billing_subscription(billing_plan: billing_plan, status: 'trialing') - n = 10 - DelayedJobHelper.enqueue_job(self, :check_trial, [sub['id']], {run_at: n.days.from_now}) - return {json: sub} - rescue ActiveRecord::RecordNotFound => e - return {json: { error: e }, status: :unprocessable_entity} - end - + nonprofit = Nonprofit.includes(:billing_subscription).find(np_id) + billing_plan = BillingPlan.where('stripe_plan_id = ?', stripe_plan_id).last + sub = nonprofit.create_billing_subscription(billing_plan: billing_plan, status: 'trialing') + n = 10 + DelayedJobHelper.enqueue_job(self, :check_trial, [sub['id']], run_at: n.days.from_now) + { json: sub } + rescue ActiveRecord::RecordNotFound => e + { json: { error: e }, status: :unprocessable_entity } end def self.check_trial(bs_id) @@ -26,9 +23,8 @@ module InsertBillingSubscriptions Qx.update(:billing_subscriptions) .set(status: 'inactive') .timestamps - .where("id = $id", id: bs_id) + .where('id = $id', id: bs_id) .execute end end - end diff --git a/lib/insert/insert_card.rb b/lib/insert/insert_card.rb index dfb7709e..ffd6504b 100644 --- a/lib/insert/insert_card.rb +++ b/lib/insert/insert_card.rb @@ -1,8 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'hash' module InsertCard - - # Create a new card # If a stripe_customer_id is present, then update that customer's primary source; otherwise create a new customer # @param [ActiveSupport::HashWithIndifferentAccess] card_data card data @@ -17,60 +17,55 @@ module InsertCard # @param [String] stripe_account_id not clear what this should do. # @param [Integer] event_id id for events with when you want it associated with an event - # @param [User] current_user the user making the request. Used for validating that the current_user can make a long term token request - def self.with_stripe(card_data, stripe_account_id=nil, event_id=nil, current_user = nil) - + # @param [User] current_user the user making the request. Used for validating that the current_user can make a long term token request + def self.with_stripe(card_data, _stripe_account_id = nil, event_id = nil, current_user = nil) begin - ParamValidation.new(card_data.merge({event_id: event_id}), { - holder_type: {required: true, included_in: ['Nonprofit', 'Supporter']}, - holder_id: {required: true}, - stripe_card_id: {not_blank: true, required: true}, - stripe_card_token: {not_blank: true, required: true}, - name: {not_blank: true, required: true}, - event_id: {is_reference: true} - }) + ParamValidation.new(card_data.merge(event_id: event_id), + holder_type: { required: true, included_in: %w[Nonprofit Supporter] }, + holder_id: { required: true }, + stripe_card_id: { not_blank: true, required: true }, + stripe_card_token: { not_blank: true, required: true }, + name: { not_blank: true, required: true }, + event_id: { is_reference: true }) rescue ParamValidation::ValidationError => e - return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} + return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } end - - # validate that the user is with the correct nonprofit - card_data = card_data.keep_keys(:holder_type, :holder_id, :stripe_card_id, :stripe_card_token, :name ) - holder_types = {'Nonprofit' => :nonprofit, 'Supporter' => :supporter} + card_data = card_data.keep_keys(:holder_type, :holder_id, :stripe_card_id, :stripe_card_token, :name) + holder_types = { 'Nonprofit' => :nonprofit, 'Supporter' => :supporter } holder_type = holder_types[card_data[:holder_type]] holder = nil begin if holder_type == :nonprofit - holder = Nonprofit.select("id, email").includes(:cards).find(card_data[:holder_id]) + holder = Nonprofit.select('id, email').includes(:cards).find(card_data[:holder_id]) elsif holder_type == :supporter - holder = Supporter.select("id, email, nonprofit_id").includes(:cards, :nonprofit).find(card_data[:holder_id]) + holder = Supporter.select('id, email, nonprofit_id').includes(:cards, :nonprofit).find(card_data[:holder_id]) end rescue ActiveRecord::RecordNotFound - return {json: {error: "Sorry, you need to provide a nonprofit or supporter"}, status: :unprocessable_entity} + return { json: { error: 'Sorry, you need to provide a nonprofit or supporter' }, status: :unprocessable_entity } end begin if holder_type == :supporter && event_id event = Event.where('id = ?', event_id).first unless event - raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", {key: :event_id}) + raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", key: :event_id) end - if (holder.nonprofit != event.nonprofit ) - raise ParamValidation::ValidationError.new("Event #{event_id} is not for the same nonprofit as supporter #{holder.id}", {key: :event_id}) + if holder.nonprofit != event.nonprofit + raise ParamValidation::ValidationError.new("Event #{event_id} is not for the same nonprofit as supporter #{holder.id}", key: :event_id) end unless QueryRoles.is_authorized_for_nonprofit?(current_user.id, holder.nonprofit.id) - raise AuthenticationError.new + raise AuthenticationError end end rescue AuthenticationError - return {json: {error: "You're not authorized to perform that action"}, status: :unauthorized} - rescue => e - return {json: {error: "Oops! There was an error: #{e.message}"}, status: :unprocessable_entity} - + return { json: { error: "You're not authorized to perform that action" }, status: :unauthorized } + rescue StandardError => e + return { json: { error: "Oops! There was an error: #{e.message}" }, status: :unprocessable_entity } end stripe_account_hash = {} # stripe_account_id ? {stripe_account: stripe_account_id} : {} begin @@ -84,43 +79,39 @@ module InsertCard card_data[:stripe_customer_id] = stripe_customer.id rescue Stripe::CardError => e - return {json: {error: "Oops! #{e.json_body[:error][:message]}"}, status: :unprocessable_entity} + return { json: { error: "Oops! #{e.json_body[:error][:message]}" }, status: :unprocessable_entity } rescue Stripe::StripeError => e - return {json: {error: "Oops! There was an error processing your payment, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error processing your payment, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } end card = nil source_token = nil begin - Card.transaction { - - if (holder_type == :nonprofit) + Card.transaction do + if holder_type == :nonprofit # @type [Nonprofit] holder card = holder.create_active_card(card_data) - elsif (holder_type == :supporter) + elsif holder_type == :supporter # @type [Supporter] holder card = holder.cards.create(card_data) params = {} - if event - params[:event] = event - end + params[:event] = event if event source_token = InsertSourceToken.create_record(card, params).token end card.save! - } + end rescue ActiveRecord::ActiveRecordError => e - return {json: {error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } rescue e - return {json: {error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } rescue e - return {json: {error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error saving your card, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } end - return { status: :ok, json: card.attributes.with_indifferent_access.merge(token: source_token) } - end + { status: :ok, json: card.attributes.with_indifferent_access.merge(token: source_token) } +end def self.customer_data(holder, card_data) { email: holder['email'], metadata: { cardholders_name: card_data[:cardholders_name], holder_id: card_data[:holder_id], holder_type: card_data[:holder_type] } } end - end diff --git a/lib/insert/insert_charge.rb b/lib/insert/insert_charge.rb index 15433c83..c8390ee4 100644 --- a/lib/insert/insert_charge.rb +++ b/lib/insert/insert_charge.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' @@ -6,161 +8,155 @@ require 'stripe' require 'get_data' require 'active_support/core_ext' require 'query/billing_plans' -require 'stripe_account' unless !Settings.payment_provider.stripe_connect +require 'stripe_account' if Settings.payment_provider.stripe_connect module InsertCharge - # In data, pass in: amount, nonprofit_id, supporter_id, card_id, statement # Optionally pass in :metadata for stripe and donation_id to connect to donation? # @raise [ParamValidation::ValidationError] parameter validation occurred # @raise [Stripe::StripeError] the stripe account couldn't be accessed or created def self.with_stripe(data) + ParamValidation.new(data || {}, + amount: { + required: true, + is_integer: true, + min: 0 + }, + nonprofit_id: { + required: true, + is_integer: true + }, + supporter_id: { + required: true, + is_integer: true + }, + card_id: { + required: true, + is_integer: true + }, + statement: { + required: true, + not_blank: true + }) + + np = Nonprofit.where('id = ?', data[:nonprofit_id]).first + + unless np + raise ParamValidation::ValidationError.new("#{data[:nonprofit_id]} is not a valid Nonprofit", key: :nonprofit_id) + end + + supporter = Supporter.where('id = ?', data[:supporter_id]).first + + unless supporter + raise ParamValidation::ValidationError.new("#{data[:supporter_id]} is not a valid Supporter", key: :supporter_id) + end + + card = Card.where('id = ?', data[:card_id]).first + + unless card + raise ParamValidation::ValidationError.new("#{data[:card_id]} is not a valid card", key: :card_id) + end + + unless np == supporter.nonprofit + raise ParamValidation::ValidationError.new("#{data[:supporter_id]} does not belong to this nonprofit #{np.id}", key: :supporter_id) + end + + unless card.holder == supporter + if data[:old_donation] + # these are not new donations so we let them fly (for now) + else + raise ParamValidation::ValidationError.new("#{data[:card_id]} does not belong to this supporter #{supporter.id}", key: :card_id) + end + end + + result = {} + # Catch errors thrown by the stripe gem so we can respond with a 422 with an error message rather than 500 begin - ParamValidation.new(data || {}, { - :amount => { - :required => true, - :is_integer => true, - :min => 0 - }, - :nonprofit_id => { - :required => true, - :is_integer => true - }, - :supporter_id => { - :required => true, - :is_integer => true - }, - :card_id => { - :required => true, - :is_integer => true - }, - :statement => { - :required => true, - :not_blank => true - } - }) + stripe_customer_id = card.stripe_customer_id + stripe_account_id = StripeAccount.find_or_create(data[:nonprofit_id]) + rescue StandardError => e + raise e + end + nonprofit_currency = Qx.select(:currency).from(:nonprofits).where('id=$id', id: data[:nonprofit_id]).execute.first['currency'] - np = Nonprofit.where('id = ?', data[:nonprofit_id]).first + stripe_charge_data = { + customer: stripe_customer_id, + amount: data[:amount], + currency: nonprofit_currency, + description: data[:statement], + statement_descriptor: data[:statement][0..21].gsub(/[<>"']/, ''), + metadata: data[:metadata] + } - unless np - raise ParamValidation::ValidationError.new("#{data[:nonprofit_id]} is not a valid Nonprofit", {:key => :nonprofit_id}) - end - - supporter = Supporter.where('id = ?', data[:supporter_id]).first - - unless supporter - raise ParamValidation::ValidationError.new("#{data[:supporter_id]} is not a valid Supporter", {:key => :supporter_id}) - end - - card = Card.where('id = ?', data[:card_id]).first - - unless card - raise ParamValidation::ValidationError.new("#{data[:card_id]} is not a valid card", {:key => :card_id}) - end - - unless np == supporter.nonprofit - raise ParamValidation::ValidationError.new("#{data[:supporter_id]} does not belong to this nonprofit #{np.id}", {:key => :supporter_id}) - end - - unless card.holder == supporter - if (data[:old_donation]) - #these are not new donations so we let them fly (for now) - else - raise ParamValidation::ValidationError.new("#{data[:card_id]} does not belong to this supporter #{supporter.id}", {:key => :card_id}) - end - end - - result = {} - # Catch errors thrown by the stripe gem so we can respond with a 422 with an error message rather than 500 - begin - stripe_customer_id = card.stripe_customer_id - stripe_account_id = StripeAccount.find_or_create(data[:nonprofit_id]) - rescue => e - raise e - end - nonprofit_currency = Qx.select(:currency).from(:nonprofits).where("id=$id", id: data[:nonprofit_id]).execute.first['currency'] - - stripe_charge_data = { - customer: stripe_customer_id, - amount: data[:amount], - currency: nonprofit_currency, - description: data[:statement], - statement_descriptor: data[:statement][0..21].gsub(/[<>"']/,''), - metadata: data[:metadata] - } - - if Settings.payment_provider.stripe_connect - stripe_account_id = StripeAccount.find_or_create(data[:nonprofit_id]) - # Get the percentage fee on the nonprofit's billing plan - platform_fee = BillingPlans.get_percentage_fee(data[:nonprofit_id]) - fee = CalculateFees.for_single_amount(data[:amount], platform_fee) - stripe_charge_data[:application_fee]= fee + if Settings.payment_provider.stripe_connect + stripe_account_id = StripeAccount.find_or_create(data[:nonprofit_id]) + # Get the percentage fee on the nonprofit's billing plan + platform_fee = BillingPlans.get_percentage_fee(data[:nonprofit_id]) + fee = CalculateFees.for_single_amount(data[:amount], platform_fee) + stripe_charge_data[:application_fee] = fee # For backwards compatibility, see if the customer exists in the primary or the connected account # If it's a legacy customer, charge to the primary account and transfer with .destination # Otherwise, charge directly to the connected account - begin - stripe_cust = Stripe::Customer.retrieve(stripe_customer_id) - params = [stripe_charge_data.merge(destination: stripe_account_id), {}] - rescue - params = [stripe_charge_data, {stripe_account: stripe_account_id}] - end - else - fee=0 - stripe_charge_data[:source]=card['stripe_card_id'] - params = [stripe_charge_data, {}] - end - begin - stripe_charge = Stripe::Charge.create(*params) - rescue Stripe::CardError => e - failure_message = "There was an error with your card: #{e.json_body[:error][:message]}" - rescue Stripe::StripeError => e - failure_message = "We're sorry, but something went wrong. We've been notified about this issue." + stripe_cust = Stripe::Customer.retrieve(stripe_customer_id) + params = [stripe_charge_data.merge(destination: stripe_account_id), {}] + rescue StandardError + params = [stripe_charge_data, { stripe_account: stripe_account_id }] end + else + fee = 0 + stripe_charge_data[:source] = card['stripe_card_id'] + params = [stripe_charge_data, {}] + end + begin + stripe_charge = Stripe::Charge.create(*params) + rescue Stripe::CardError => e + failure_message = "There was an error with your card: #{e.json_body[:error][:message]}" + rescue Stripe::StripeError => e + failure_message = "We're sorry, but something went wrong. We've been notified about this issue." + end - charge = Charge.new + charge = Charge.new - charge.amount = data[:amount] - charge.fee = fee + charge.amount = data[:amount] + charge.fee = fee - charge.stripe_charge_id = GetData.chain(stripe_charge, :id) - charge.failure_message = failure_message - charge.status = GetData.chain(stripe_charge, :paid) ? 'pending' : 'failed' - charge.card = card - charge.donation = Donation.where('id = ?', data[:donation_id]).first - charge.supporter = supporter - charge.nonprofit = np + charge.stripe_charge_id = GetData.chain(stripe_charge, :id) + charge.failure_message = failure_message + charge.status = GetData.chain(stripe_charge, :paid) ? 'pending' : 'failed' + charge.card = card + charge.donation = Donation.where('id = ?', data[:donation_id]).first + charge.supporter = supporter + charge.nonprofit = np + charge.save! + result['charge'] = charge + + if stripe_charge && stripe_charge.status != 'failed' + payment = Payment.new + payment.gross_amount = data[:amount] + payment.fee_total = -fee + payment.net_amount = data[:amount] - fee + payment.towards = data[:towards] + payment.kind = data[:kind] + payment.donation = Donation.where('id = ?', data[:donation_id]).first + payment.nonprofit = np + payment.supporter = supporter + payment.refund_total = 0 + payment.date = data[:date] || result['charge'].created_at + payment.save! + + result['payment'] = payment + + charge.payment = payment charge.save! result['charge'] = charge - - if stripe_charge && stripe_charge.status != 'failed' - payment = Payment.new - payment.gross_amount = data[:amount] - payment.fee_total = -fee - payment.net_amount = data[:amount] - fee - payment.towards = data[:towards] - payment.kind = data[:kind] - payment.donation = Donation.where('id = ?', data[:donation_id]).first - payment.nonprofit = np - payment.supporter = supporter - payment.refund_total = 0 - payment.date = data[:date] || result['charge'].created_at - payment.save! - - - result['payment'] = payment - - charge.payment = payment - charge.save! - result['charge'] = charge - end - - return result - rescue => e - raise e end + + result + rescue StandardError => e + raise e end def self.with_sepa(data) @@ -171,7 +167,7 @@ module InsertCharge # TODO fee = 0 - #todo charge should be changed to SEPA charge + # TODO: charge should be changed to SEPA charge c = Charge.new c.direct_debit_detail = entities[:direct_debit_detail_id] @@ -186,9 +182,9 @@ module InsertCharge p = Payment.new - p.gross_amount= data[:amount] - p.fee_total= -fee - p.net_amount= data[:amount] - fee + p.gross_amount = data[:amount] + p.fee_total = -fee + p.net_amount = data[:amount] - fee p.towards = data[:towards] p.kind = data[:kind] p.nonprofit = entities[:nonprofit_id] diff --git a/lib/insert/insert_custom_field_joins.rb b/lib/insert/insert_custom_field_joins.rb index f25a38cd..d49d2b4c 100644 --- a/lib/insert/insert_custom_field_joins.rb +++ b/lib/insert/insert_custom_field_joins.rb @@ -1,131 +1,124 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'delayed_job_helper' require 'qx' require 'update/update_custom_field_joins' module InsertCustomFieldJoins - # Bulk insert many field joins into many supporters # for every field name, find or create it for the nonprofit # field_data should be an array of arrays liks [['Company', 'Pixar'], # ['Shirt-size', 'Small']] def self.find_or_create(np_id, supporter_ids, field_data) - ParamValidation.new({np_id: np_id, supporter_ids: supporter_ids, field_data: field_data}, - { - :np_id => { - :required => true, - :is_integer=> true - }, - :supporter_ids => { - :required => true, - :is_array => true, - :min_length => 1 - }, - :field_data => { - :required => true, - :is_array => true, - :min_length => 1 - } - }) + ParamValidation.new({ np_id: np_id, supporter_ids: supporter_ids, field_data: field_data }, + np_id: { + required: true, + is_integer: true + }, + supporter_ids: { + required: true, + is_array: true, + min_length: 1 + }, + field_data: { + required: true, + is_array: true, + min_length: 1 + }) - #make sure the np exists - np = Nonprofit.where("id = ? ", np_id).first + # make sure the np exists + np = Nonprofit.where('id = ? ', np_id).first unless np - raise ParamValidation::ValidationError.new("#{np_id} is not a valid non-profit", {:key => :np_id}) + raise ParamValidation::ValidationError.new("#{np_id} is not a valid non-profit", key: :np_id) end - #make sure the supporters_ids exist - supporter_ids.each {|id| + # make sure the supporters_ids exist + supporter_ids.each do |id| unless np.supporters.where('id = ?', id).exists? - raise ParamValidation::ValidationError.new("#{id} is not a valid supporter for nonprofit #{np_id}", {:key => :supporter_ids}) + raise ParamValidation::ValidationError.new("#{id} is not a valid supporter for nonprofit #{np_id}", key: :supporter_ids) end - } + end Qx.transaction do # get the custom_field_master_id for each field_data name - cfm_id_to_value = field_data.map { |name, value| - cfm = CustomFieldMaster.where("nonprofit_id = ? and name = ?", np_id, name).first - unless cfm - cfm = CustomFieldMaster.create!(:nonprofit => np, :name => name) - end - {:custom_field_master_id => cfm.id, :value => value} - } + cfm_id_to_value = field_data.map do |name, value| + cfm = CustomFieldMaster.where('nonprofit_id = ? and name = ?', np_id, name).first + cfm ||= CustomFieldMaster.create!(nonprofit: np, name: name) + { custom_field_master_id: cfm.id, value: value } + end return in_bulk(np_id, supporter_ids, cfm_id_to_value) end end - # Validation: *np_id is valid, corresponds to real nonprofit # # # @param [Integer] np_id nonprofit_id whose custom_fields this applies to # @param [Array] supporter_ids the supporter ids in which the custom fields should be modified # @param [Array>] field_data the fields you'd like to modify. Each item is a hash with following keys: - # * custom_field_master_id [Integer] for the key corresponding to custom_field_master_id - # * value [Object] the expected value of the field. If this key is an empty string, we remove the custom_field + # * custom_field_master_id [Integer] for the key corresponding to custom_field_master_id + # * value [Object] the expected value of the field. If this key is an empty string, we remove the custom_field def self.in_bulk(np_id, supporter_ids, field_data) begin ParamValidation.new({ - np_id: np_id, - supporter_ids: supporter_ids, - field_data: field_data - }, { - np_id: {required: true, is_integer: true}, - supporter_ids: {required:true, is_array: true}, - field_data: { required: true, is_array: true} - # array_of_hashes: { - # selected: {required: true}, tag_master_id: {required: true, is_integer: true} - # } - - }) + np_id: np_id, + supporter_ids: supporter_ids, + field_data: field_data + }, + np_id: { required: true, is_integer: true }, + supporter_ids: { required: true, is_array: true }, + field_data: { required: true, is_array: true }) + # array_of_hashes: { + # selected: {required: true}, tag_master_id: {required: true, is_integer: true} + # } rescue ParamValidation::ValidationError => e - return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} + return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } end begin - return {json: {error: "Nonprofit #{np_id} is not valid"}, status: :unprocessable_entity} unless Nonprofit.exists?(np_id) + return { json: { error: "Nonprofit #{np_id} is not valid" }, status: :unprocessable_entity } unless Nonprofit.exists?(np_id) # verify that the supporters belong to the nonprofit supporter_ids = Supporter.where('nonprofit_id = ? and id IN (?)', np_id, supporter_ids).pluck(:id) unless supporter_ids.any? - return {json: {inserted_count: 0, removed_count: 0}, status: :ok} + return { json: { inserted_count: 0, removed_count: 0 }, status: :ok } end # filtering the tag_data to this nonprofit - valid_ids = CustomFieldMaster.where('nonprofit_id = ? and id IN (?)', np_id, field_data.map {|fd| fd[:custom_field_master_id] }).pluck(:id).to_a - filtered_field_data = field_data.select {|i| valid_ids.include? i[:custom_field_master_id ].to_i} + valid_ids = CustomFieldMaster.where('nonprofit_id = ? and id IN (?)', np_id, field_data.map { |fd| fd[:custom_field_master_id] }).pluck(:id).to_a + filtered_field_data = field_data.select { |i| valid_ids.include? i[:custom_field_master_id].to_i } # first, delete the items which should be removed - to_insert, to_remove = filtered_field_data.partition{|t| + to_insert, to_remove = filtered_field_data.partition do |t| !t[:value].blank? - } + end deleted = [] if to_remove.any? deleted = Qx.delete_from(:custom_field_joins) - .where("supporter_id IN ($ids)", ids: supporter_ids) - .and_where("custom_field_master_id in ($fields)", fields: to_remove.map{|t| t[:custom_field_master_id]}) - .returning('*') - .execute + .where('supporter_id IN ($ids)', ids: supporter_ids) + .and_where('custom_field_master_id in ($fields)', fields: to_remove.map { |t| t[:custom_field_master_id] }) + .returning('*') + .execute end - # next add only the selected tag_joins if to_insert.any? - insert_data = supporter_ids.map{|id| to_insert.map{|cfm| {supporter_id: id, custom_field_master_id: cfm[:custom_field_master_id], value: cfm[:value]}}}.flatten + insert_data = supporter_ids.map { |id| to_insert.map { |cfm| { supporter_id: id, custom_field_master_id: cfm[:custom_field_master_id], value: cfm[:value] } } }.flatten cfj = Qx.insert_into(:custom_field_joins) - .values(insert_data) - .timestamps - .on_conflict() - .conflict_columns(:supporter_id, :custom_field_master_id).upsert(:custom_field_join_supporter_unique_idx) - .returning('*') - .execute + .values(insert_data) + .timestamps + .on_conflict + .conflict_columns(:supporter_id, :custom_field_master_id).upsert(:custom_field_join_supporter_unique_idx) + .returning('*') + .execute else cfj = [] end rescue ActiveRecord::ActiveRecordError => e - return {json: {error: "A DB error occurred. Please contact support. \n #{e.message}"}, status: :unprocessable_entity} + return { json: { error: "A DB error occurred. Please contact support. \n #{e.message}" }, status: :unprocessable_entity } end # Create an activity for the modified tags for every supporter @@ -134,10 +127,8 @@ module InsertCustomFieldJoins # activities = Psql.execute( Qexpr.new.insert(:activities, activity_data) ) # Sync mailchimp lists, if present - #Mailchimp.delay.sync_supporters_to_list_from_tag_joins(np_id, supporter_ids, tag_data) - - return {json: {inserted_count: cfj.count, removed_count: deleted.count }, status: :ok} + # Mailchimp.delay.sync_supporters_to_list_from_tag_joins(np_id, supporter_ids, tag_data) + { json: { inserted_count: cfj.count, removed_count: deleted.count }, status: :ok } end - end diff --git a/lib/insert/insert_direct_debit_detail.rb b/lib/insert/insert_direct_debit_detail.rb index cf3219a4..d4cc73d6 100644 --- a/lib/insert/insert_direct_debit_detail.rb +++ b/lib/insert/insert_direct_debit_detail.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertDirectDebitDetail def self.execute(params) @@ -5,18 +7,18 @@ module InsertDirectDebitDetail direct_debit_detail = {} begin - DirectDebitDetail.transaction { + DirectDebitDetail.transaction do direct_debit_detail = DirectDebitDetail.create( bic: params[:sepa_params][:bic], iban: params[:sepa_params][:iban], account_holder_name: params[:sepa_params][:name], holder: supporter ) - } + end rescue ActiveRecord::ActiveRecordError => e - return {json: {error: "Oops! There was an error saving your direct debit details, and it did not complete. Please try again in a moment. Error: #{e}"}, status: :unprocessable_entity} + return { json: { error: "Oops! There was an error saving your direct debit details, and it did not complete. Please try again in a moment. Error: #{e}" }, status: :unprocessable_entity } end - return { status: :ok, json: direct_debit_detail } + { status: :ok, json: direct_debit_detail } end end diff --git a/lib/insert/insert_disputes.rb b/lib/insert/insert_disputes.rb index 41222f80..c6cd7e53 100644 --- a/lib/insert/insert_disputes.rb +++ b/lib/insert/insert_disputes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' @@ -5,42 +7,41 @@ require 'calculate/calculate_fees' require 'active_support/core_ext' module InsertDisputes - # A new dispute takes a charge id and dispute id and creates: # A dispute row with the charge gross amount and the dispute id # A payment row negative gross and net, just like a refund, but with kind "Dispute" def self.create_record(stripe_charge_id, stripe_dispute_id) # Find the existing charge - ch = Qx.select("*").from("charges").where("stripe_charge_id=$id", id: stripe_charge_id).ex.first - raise ArgumentError.new("Charge not found") if ch.nil? + ch = Qx.select('*').from('charges').where('stripe_charge_id=$id', id: stripe_charge_id).ex.first + raise ArgumentError, 'Charge not found' if ch.nil? result = {} now = Time.current result[:payment] = Psql.execute( Qexpr.new.insert(:payments, [{ - gross_amount: -ch['amount'], - fee_total: 0, - net_amount: -ch['amount'], - kind: 'Dispute', - refund_total: 0, - nonprofit_id: ch['nonprofit_id'], - supporter_id: ch['supporter_id'], - donation_id: ch['donation_id'], - date: now - }]).returning('*') + gross_amount: -ch['amount'], + fee_total: 0, + net_amount: -ch['amount'], + kind: 'Dispute', + refund_total: 0, + nonprofit_id: ch['nonprofit_id'], + supporter_id: ch['supporter_id'], + donation_id: ch['donation_id'], + date: now + }]).returning('*') ).first # Create a dispute record result[:dispute] = Psql.execute( Qexpr.new.insert(:disputes, [{ - gross_amount: ch['amount'], - status: :needs_response, - charge_id: ch['id'], - reason: :unrecognized, - payment_id: result[:payment]['id'], - stripe_dispute_id: stripe_dispute_id - }]).returning('*') + gross_amount: ch['amount'], + status: :needs_response, + charge_id: ch['id'], + reason: :unrecognized, + payment_id: result[:payment]['id'], + stripe_dispute_id: stripe_dispute_id + }]).returning('*') ).first # Prevent refunds from being able to happen on the payment @@ -49,8 +50,6 @@ module InsertDisputes # Insert an activity record InsertActivities.for_disputes([result[:payment]['id']]) - return result + result end - end - diff --git a/lib/insert/insert_donation.rb b/lib/insert/insert_donation.rb index 86875837..74a4d8c0 100644 --- a/lib/insert/insert_donation.rb +++ b/lib/insert/insert_donation.rb @@ -1,25 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertDonation - - # Make a one-time donation (call InsertRecurringDonation.with_stripe to create a recurring donation) # In data, pass in: # amount, card_id, nonprofit_id, supporter_id # designation, dedication # recurring_donation if is recurring - def self.with_stripe(data, current_user=nil) + def self.with_stripe(data, current_user = nil) data = data.with_indifferent_access ParamValidation.new(data, common_param_validations - .merge(token: {required: true, format: UUID::Regex})) + .merge(token: { required: true, format: UUID::Regex })) source_token = QuerySourceToken.get_and_increment_source_token(data[:token], current_user) tokenizable = source_token.tokenizable QuerySourceToken.validate_source_token_type(source_token) - entities = RetrieveActiveRecordItems.retrieve_from_keys(data, {Supporter => :supporter_id, Nonprofit => :nonprofit_id}) + entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) validate_entities(entities) @@ -36,10 +36,11 @@ module InsertDonation data = data.except(:old_donation).except('old_donation') result = result.merge(insert_charge(data)) if result['charge']['status'] == 'failed' - raise ChargeError.new(result['charge']['failure_message']) + raise ChargeError, result['charge']['failure_message'] end + # Create the donation record - result['donation'] = self.insert_donation(data, entities) + result['donation'] = insert_donation(data, entities) update_donation_keys(result) result['activity'] = InsertActivities.for_one_time_donations([result['payment'].id]) EmailJobQueue.queue(JobTypes::NonprofitPaymentNotificationJob, result['donation'].id) @@ -63,46 +64,46 @@ module InsertDonation # pass in amount, nonprofit_id, supporter_id, check_number # also pass in offsite_payment sub-hash (can be empty) def self.offsite(data) - ParamValidation.new(data, common_param_validations.merge(offsite_payment: {is_hash: true})) + ParamValidation.new(data, common_param_validations.merge(offsite_payment: { is_hash: true })) - entities = RetrieveActiveRecordItems.retrieve_from_keys(data, {Supporter => :supporter_id, Nonprofit => :nonprofit_id}) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) + entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) validate_entities(entities) data = date_from_data(data) - result = {'donation' => self.insert_donation(data.except('offsite_payment'), entities)} - result['payment'] = self.insert_payment('OffsitePayment', 0, result['donation']['id'], data) + result = { 'donation' => insert_donation(data.except('offsite_payment'), entities) } + result['payment'] = insert_payment('OffsitePayment', 0, result['donation']['id'], data) result['offsite_payment'] = Psql.execute( Qexpr.new.insert(:offsite_payments, [ - (data['offsite_payment'] || {}).merge({ - gross_amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - donation_id: result['donation']['id'], - payment_id: result['payment']['id'], - date: data['date'] - }) - ]).returning('*') + (data['offsite_payment'] || {}).merge( + gross_amount: data['amount'], + nonprofit_id: data['nonprofit_id'], + supporter_id: data['supporter_id'], + donation_id: result['donation']['id'], + payment_id: result['payment']['id'], + date: data['date'] + ) + ]).returning('*') ).first result['activity'] = InsertActivities.for_offsite_donations([result['payment']['id']]) QueueDonations.delay.execute_for_donation(result['donation'].id) - return {status: 200, json: result} + { status: 200, json: result } end def self.with_sepa(data) data = data.with_indifferent_access ParamValidation.new(data, common_param_validations - .merge(direct_debit_detail_id: {required: true, is_reference: true})) + .merge(direct_debit_detail_id: { required: true, is_reference: true })) - entities = RetrieveActiveRecordItems.retrieve_from_keys(data, {Supporter => :supporter_id, Nonprofit => :nonprofit_id}) + entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) result = {} data[:date] = Time.now result = result.merge(insert_charge(data)) - result['donation'] = self.insert_donation(data, entities) + result['donation'] = insert_donation(data, entities) update_donation_keys(result) EmailJobQueue.queue(JobTypes::NonprofitPaymentNotificationJob, result['donation'].id) @@ -114,44 +115,44 @@ module InsertDonation result end -private + private def self.get_nonprofit_data(nonprofit_id) Psql.execute( Qexpr.new.select(:statement, :name).from(:nonprofits) - .where("id=$id", id: nonprofit_id) + .where('id=$id', id: nonprofit_id) ).first end def self.insert_charge(data) payment_provider = payment_provider(data) nonprofit_data = get_nonprofit_data(data['nonprofit_id']) - kind = data['recurring_donation'] ? "RecurringDonation" : "Donation" + kind = data['recurring_donation'] ? 'RecurringDonation' : 'Donation' if payment_provider == :credit_card - return InsertCharge.with_stripe({ + return InsertCharge.with_stripe( donation_id: data['donation_id'], kind: kind, towards: data['designation'], - metadata: {kind: kind, nonprofit_id: data['nonprofit_id']}, + metadata: { kind: kind, nonprofit_id: data['nonprofit_id'] }, statement: "Donation #{nonprofit_data['statement'] || nonprofit_data['name']}", amount: data['amount'], nonprofit_id: data['nonprofit_id'], supporter_id: data['supporter_id'], card_id: data['card_id'], old_donation: data['old_donation'] ? true : false - }) + ) elsif payment_provider == :sepa - return InsertCharge.with_sepa({ + return InsertCharge.with_sepa( donation_id: data['donation_id'], kind: kind, towards: data['designation'], - metadata: {kind: kind, nonprofit_id: data['nonprofit_id']}, + metadata: { kind: kind, nonprofit_id: data['nonprofit_id'] }, statement: "Donation #{nonprofit_data['statement'] || nonprofit_data['name']}", amount: data['amount'], nonprofit_id: data['nonprofit_id'], supporter_id: data['supporter_id'], direct_debit_detail_id: data['direct_debit_detail_id'] - }) + ) end end @@ -159,17 +160,17 @@ private def self.insert_payment(kind, fee_total, donation_id, data) Psql.execute( Qexpr.new.insert(:payments, [{ - donation_id: donation_id, - gross_amount: data['amount'], - nonprofit_id: data['nonprofit_id'], - supporter_id: data['supporter_id'], - refund_total: 0, - date: data['date'], - towards: data['designation'], - kind: kind, - fee_total: fee_total, - net_amount: data['amount'] - fee_total - }]).returning('*') + donation_id: donation_id, + gross_amount: data['amount'], + nonprofit_id: data['nonprofit_id'], + supporter_id: data['supporter_id'], + refund_total: 0, + date: data['date'], + towards: data['designation'], + kind: kind, + fee_total: fee_total, + net_amount: data['amount'] - fee_total + }]).returning('*') ).first end @@ -202,31 +203,31 @@ private def self.locale_for_supporter(supporter_id) Psql.execute( Qexpr.new.select(:locale).from(:supporters) - .where("id=$id", id: supporter_id) + .where('id=$id', id: supporter_id) ).first['locale'] end def self.payment_provider(data) - if data[:card_id] || data["card_id"] + if data[:card_id] || data['card_id'] :credit_card - elsif data[:direct_debit_detail_id] || data["direct_debit_detail_id"] + elsif data[:direct_debit_detail_id] || data['direct_debit_detail_id'] :sepa end end -def self.parse_date(date) + def self.parse_date(date) date.blank? ? Time.current : Chronic.parse(date) - end + end def self.common_param_validations { - amount: {required: true, is_integer: true}, - nonprofit_id: {required: true, is_reference: true}, - supporter_id: {required: true, is_reference: true}, - designation: {is_a: String}, - dedication: {is_a: String}, - campaign_id: {is_reference: true}, - event_id: {is_reference: true}, + amount: { required: true, is_integer: true }, + nonprofit_id: { required: true, is_reference: true }, + supporter_id: { required: true, is_reference: true }, + designation: { is_a: String }, + dedication: { is_a: String }, + campaign_id: { is_reference: true }, + event_id: { is_reference: true } } end @@ -236,11 +237,11 @@ def self.parse_date(date) raise ParamValidation::ValidationError.new("Supporter #{entities[:supporter_id].id} is deleted", key: :supporter_id) end - if entities[:event_id] && entities[:event_id].deleted + if entities[:event_id]&.deleted raise ParamValidation::ValidationError.new("Event #{entities[:event_id].id} is deleted", key: :event_id) end - if entities[:campaign_id] && entities[:campaign_id].deleted + if entities[:campaign_id]&.deleted raise ParamValidation::ValidationError.new("Campaign #{entities[:campaign_id].id} is deleted", key: :campaign_id) end diff --git a/lib/insert/insert_duplicate.rb b/lib/insert/insert_duplicate.rb index 60e6e6d3..d0c68f07 100644 --- a/lib/insert/insert_duplicate.rb +++ b/lib/insert/insert_duplicate.rb @@ -1,19 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertDuplicate def self.campaign(campaign_id, profile_id) - ParamValidation.new({:campaign_id => campaign_id, :profile_id => profile_id}, - { - :campaign_id => {:required => true, :is_integer => true}, - :profile_id => {:required => true, :is_integer => true} - }) - campaign = Campaign.where("id = ?", campaign_id).first + ParamValidation.new({ campaign_id: campaign_id, profile_id: profile_id }, + campaign_id: { required: true, is_integer: true }, + profile_id: { required: true, is_integer: true }) + campaign = Campaign.where('id = ?', campaign_id).first unless campaign - raise ParamValidation::ValidationError.new("#{campaign_id} is not a valid campaign", {:key => :campaign_id}) + raise ParamValidation::ValidationError.new("#{campaign_id} is not a valid campaign", key: :campaign_id) end - profile = Profile.where("id = ?", profile_id).first + profile = Profile.where('id = ?', profile_id).first unless profile - raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", {:key =>:profile_id}) + raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", key: :profile_id) end Qx.transaction do @@ -21,7 +21,7 @@ module InsertDuplicate dupe.slug = SlugCopyNamingAlgorithm.new(Campaign, dupe.nonprofit.id).create_copy_name(dupe.slug) dupe.name = NameCopyNamingAlgorithm.new(Campaign, dupe.nonprofit.id).create_copy_name(dupe.name) - if (dupe.end_datetime && dupe.end_datetime.ago(7.days) < DateTime.now) + if dupe.end_datetime && dupe.end_datetime.ago(7.days) < DateTime.now dupe.end_datetime = DateTime.now.since(7.days) end @@ -29,9 +29,17 @@ module InsertDuplicate dupe.save! - dupe.update_attribute(:main_image, campaign.main_image) unless !campaign.main_image rescue AWS::S3::Errors::NoSuchKey + begin + dupe.update_attribute(:main_image, campaign.main_image) if campaign.main_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end - dupe.update_attribute(:background_image, campaign.background_image) unless !campaign.background_image rescue AWS::S3::Errors::NoSuchKey + begin + dupe.update_attribute(:background_image, campaign.background_image) if campaign.background_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end InsertDuplicate.campaign_gift_options(campaign_id, dupe.id) @@ -40,19 +48,17 @@ module InsertDuplicate end def self.event(event_id, profile_id) - ParamValidation.new({:event_id => event_id, :profile_id => profile_id}, - { - :event_id => {:required => true, :is_integer => true}, - :profile_id => {:required => true, :is_integer => true} - }) - event = Event.where("id = ?", event_id).first + ParamValidation.new({ event_id: event_id, profile_id: profile_id }, + event_id: { required: true, is_integer: true }, + profile_id: { required: true, is_integer: true }) + event = Event.where('id = ?', event_id).first unless event - raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", {:key => :event_id}) + raise ParamValidation::ValidationError.new("#{event_id} is not a valid event", key: :event_id) end - profile = Profile.where("id = ?", profile_id).first + profile = Profile.where('id = ?', profile_id).first unless profile - raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", {:key =>:profile_id}) + raise ParamValidation::ValidationError.new("#{profile_id} is not a valid profile", key: :profile_id) end Qx.transaction do @@ -63,24 +69,31 @@ module InsertDuplicate we_changed_start_time = false - length_of_event = dupe.end_datetime - dupe.start_datetime - if (dupe.start_datetime.ago(7.days) < DateTime.now) + length_of_event = dupe.end_datetime - dupe.start_datetime + if dupe.start_datetime.ago(7.days) < DateTime.now dupe.start_datetime = DateTime.now.since(7.days) we_changed_start_time = true end - if (we_changed_start_time && dupe.end_datetime) + if we_changed_start_time && dupe.end_datetime dupe.end_datetime = dupe.start_datetime.since(length_of_event) end - dupe.published = false dupe.save! - dupe.update_attribute(:main_image, event.main_image) unless !event.main_image rescue AWS::S3::Errors::NoSuchKey + begin + dupe.update_attribute(:main_image, event.main_image) if event.main_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end - dupe.update_attribute(:background_image, event.background_image) unless !event.background_image rescue AWS::S3::Errors::NoSuchKey + begin + dupe.update_attribute(:background_image, event.background_image) if event.background_image + rescue StandardError + AWS::S3::Errors::NoSuchKey + end InsertDuplicate.ticket_levels(event_id, dupe.id) InsertDuplicate.event_discounts(event_id, dupe.id) @@ -92,58 +105,57 @@ module InsertDuplicate # selects all gift options associated with old campaign # and inserts them and creates associations with a new campaign def self.campaign_gift_options(old_campaign_id, new_campaign_id) - cgos = Qx.select("*") - .from("campaign_gift_options") - .where(campaign_id: old_campaign_id) - .execute - .map {|c| c.except("id", "created_at", "updated_at", "campaign_id") } + cgos = Qx.select('*') + .from('campaign_gift_options') + .where(campaign_id: old_campaign_id) + .execute + .map { |c| c.except('id', 'created_at', 'updated_at', 'campaign_id') } if cgos.any? - return Qx.insert_into("campaign_gift_options") - .values(cgos) - .common_values({campaign_id: new_campaign_id}) - .ts - .returning("*") - .execute + return Qx.insert_into('campaign_gift_options') + .values(cgos) + .common_values(campaign_id: new_campaign_id) + .ts + .returning('*') + .execute end end # selects all ticket levels associated with old event # and inserts them and creates associations with a new event def self.ticket_levels(old_event_id, new_event_id) - tls = Qx.select("*") - .from("ticket_levels") - .where(event_id: old_event_id) - .execute - .map {|t| t.except("id", "created_at", "updated_at", "event_id") } + tls = Qx.select('*') + .from('ticket_levels') + .where(event_id: old_event_id) + .execute + .map { |t| t.except('id', 'created_at', 'updated_at', 'event_id') } if tls.any? - return Qx.insert_into("ticket_levels") - .values(tls) - .common_values({event_id: new_event_id}) - .ts - .returning("*") - .execute + return Qx.insert_into('ticket_levels') + .values(tls) + .common_values(event_id: new_event_id) + .ts + .returning('*') + .execute end end # selects all discounts associated with old event # and inserts them and creates associations with a new event def self.event_discounts(old_event_id, new_event_id) - eds = Qx.select("*") - .from("event_discounts") - .where(event_id: old_event_id) - .execute - .map {|t| t.except("id", "created_at", "updated_at", "event_id") } + eds = Qx.select('*') + .from('event_discounts') + .where(event_id: old_event_id) + .execute + .map { |t| t.except('id', 'created_at', 'updated_at', 'event_id') } if eds.any? - return Qx.insert_into("event_discounts") - .values(eds) - .common_values({event_id: new_event_id}) - .ts - .returning("*") - .execute + return Qx.insert_into('event_discounts') + .values(eds) + .common_values(event_id: new_event_id) + .ts + .returning('*') + .execute end end end - diff --git a/lib/insert/insert_email_lists.rb b/lib/insert/insert_email_lists.rb index 30d04c35..194ed56e 100644 --- a/lib/insert/insert_email_lists.rb +++ b/lib/insert/insert_email_lists.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module InsertEmailLists - def self.for_mailchimp(npo_id, tag_master_ids) # Partial SQL expression for deleting deselected tags delete_expr = Qx.delete_from(:email_lists).where(nonprofit_id: npo_id).returning('mailchimp_list_id') @@ -10,35 +11,33 @@ module InsertEmailLists if tag_master_ids.empty? # no tags were selected; remove all email lists deleted = delete_expr.execute else # Remove all email lists that exist in the db that are not included in tag_master_ids - deleted = delete_expr.where("tag_master_id NOT IN($ids)", ids: tag_master_ids).execute + deleted = delete_expr.where('tag_master_id NOT IN($ids)', ids: tag_master_ids).execute end - mailchimp_lists_to_delete = deleted.map{|h| h['mailchimp_list_id']} + mailchimp_lists_to_delete = deleted.map { |h| h['mailchimp_list_id'] } result = Mailchimp.delete_mailchimp_lists(npo_id, mailchimp_lists_to_delete) - return {deleted: deleted, deleted_result: result} if tag_master_ids.empty? + return { deleted: deleted, deleted_result: result } if tag_master_ids.empty? - existing = Qx.select("tag_master_id").from(:email_lists) - .where(nonprofit_id: npo_id) - .and_where("tag_master_id IN ($ids)", ids: tag_master_ids) - .execute + existing = Qx.select('tag_master_id').from(:email_lists) + .where(nonprofit_id: npo_id) + .and_where('tag_master_id IN ($ids)', ids: tag_master_ids) + .execute tag_master_ids -= existing lists = Mailchimp.create_mailchimp_lists(npo_id, tag_master_ids) - if !lists || !lists.any? || !lists.first[:name] - raise Exception.new("Unable to create mailchimp lists. Response was: #{lists}") + if !lists || lists.none? || !lists.first[:name] + raise Exception, "Unable to create mailchimp lists. Response was: #{lists}" end inserted_lists = Qx.insert_into(:email_lists) - .values( lists.map{|ls| {list_name: ls[:name], mailchimp_list_id: ls[:id], tag_master_id: ls[:tag_master_id]}}) - .common_values({ nonprofit_id: npo_id, }) - .ts - .returning('*') - .execute + .values(lists.map { |ls| { list_name: ls[:name], mailchimp_list_id: ls[:id], tag_master_id: ls[:tag_master_id] } }) + .common_values(nonprofit_id: npo_id) + .ts + .returning('*') + .execute UpdateEmailLists.delay.populate_lists_on_mailchimp(npo_id) - return {deleted: deleted, deleted_result: result, inserted_lists: inserted_lists, inserted_result: lists} + { deleted: deleted, deleted_result: result, inserted_lists: inserted_lists, inserted_result: lists } end - end - diff --git a/lib/insert/insert_full_contact_infos.rb b/lib/insert/insert_full_contact_infos.rb index 7b479390..f32ff447 100644 --- a/lib/insert/insert_full_contact_infos.rb +++ b/lib/insert/insert_full_contact_infos.rb @@ -1,25 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module InsertFullContactInfos - - # Work off of the full_contact_jobs queue def self.work_queue - ids = Qx.select('supporter_id').from('full_contact_jobs').ex.map{|h| h['supporter_id']} + ids = Qx.select('supporter_id').from('full_contact_jobs').ex.map { |h| h['supporter_id'] } Qx.delete_from('full_contact_jobs').where('TRUE').execute - self.bulk(ids) if ids.any? + bulk(ids) if ids.any? end - # Enqueue full contact jobs for a set of supporter ids def self.enqueue(supporter_ids) Qx.insert_into(:full_contact_jobs) - .values(supporter_ids.map{|id| {supporter_id: id}}) + .values(supporter_ids.map { |id| { supporter_id: id } }) .ex end - # We need to throttle our requests by 10ms since that is our rate limit on FullContact def self.bulk(supporter_ids) created_ids = [] @@ -30,9 +28,8 @@ module InsertFullContactInfos interval = 0.1 - (Time.current - now) # account for time taken in .single sleep interval if interval > 0 end - return created_ids + created_ids end - # Fetch and persist a single full contact record for a single supporter # return an exception if 404 or something else went poop @@ -63,54 +60,55 @@ module InsertFullContactInfos age: GetData.hash(result, 'demographics', 'age'), age_range: GetData.hash(result, 'demographics', 'age_range'), location_general: GetData.hash(result, 'demographics', 'location_general'), - websites: (GetData.hash(result, 'contact_info', 'websites') || []).map{|h| h.url}.join(','), + websites: (GetData.hash(result, 'contact_info', 'websites') || []).map(&:url).join(','), supporter_id: supporter_id } - if existing - full_contact_info = Qx.update(:full_contact_infos) - .set(info_data) - .timestamps - .where(id: existing['id']) - .returning('*') - .execute.first - else - full_contact_info = Qx.insert_into(:full_contact_infos) - .values(info_data) - .returning('*') - .timestamps - .execute.first - end + full_contact_info = if existing + Qx.update(:full_contact_infos) + .set(info_data) + .timestamps + .where(id: existing['id']) + .returning('*') + .execute.first + else + Qx.insert_into(:full_contact_infos) + .values(info_data) + .returning('*') + .timestamps + .execute.first + end if result['photos'].present? - photo_data = result['photos'].map{|h| {type_id: h.type_id, url: h.url, is_primary: h.is_primary}} - Qx.delete_from("full_contact_photos") + photo_data = result['photos'].map { |h| { type_id: h.type_id, url: h.url, is_primary: h.is_primary } } + Qx.delete_from('full_contact_photos') .where(full_contact_info_id: full_contact_info['id']) .execute full_contact_photos = Qx.insert_into(:full_contact_photos) - .values(photo_data) - .common_values(full_contact_info_id: full_contact_info['id']) - .timestamps - .returning("*") - .execute + .values(photo_data) + .common_values(full_contact_info_id: full_contact_info['id']) + .timestamps + .returning('*') + .execute end if result['social_profiles'].present? - profile_data = result['social_profiles'].map{|h| {type_id: h.type_id, username: h.username, uid: h.id, bio: h.bio, url: h.url, followers: h.followers, following: h.following} } - Qx.delete_from("full_contact_social_profiles") + profile_data = result['social_profiles'].map { |h| { type_id: h.type_id, username: h.username, uid: h.id, bio: h.bio, url: h.url, followers: h.followers, following: h.following } } + Qx.delete_from('full_contact_social_profiles') .where(full_contact_info_id: full_contact_info['id']) .execute full_contact_social_profiles = Qx.insert_into(:full_contact_social_profiles) - .values(profile_data) - .common_values(full_contact_info_id: full_contact_info['id']) - .timestamps - .returning("*") - .execute + .values(profile_data) + .common_values(full_contact_info_id: full_contact_info['id']) + .timestamps + .returning('*') + .execute end if result['digital_footprint'] && result['digital_footprint']['topics'].present? profile_data = result['social_profiles'] - .map{|h| { + .map do |h| + { type_id: h.type_id, username: h.username, uid: h.id, @@ -118,53 +116,55 @@ module InsertFullContactInfos url: h.url, followers: h.followers, following: h.following - } } - - vals = result['digital_footprint']['topics'].map{|h| h.value} + } + end + + vals = result['digital_footprint']['topics'].map(&:value) existing_vals = Qx.select('value').from('full_contact_topics') - .where("value IN ($vals)", vals: vals) - .and_where("full_contact_info_id=$id", id: full_contact_info['id']) - .execute.map{|h| h['value']} + .where('value IN ($vals)', vals: vals) + .and_where('full_contact_info_id=$id', id: full_contact_info['id']) + .execute.map { |h| h['value'] } topic_data = result['digital_footprint']['topics'] - .reject{|h| existing_vals.include?(h.value)} - .map{|h| {value: h.value, provider: h.provider}} + .reject { |h| existing_vals.include?(h.value) } + .map { |h| { value: h.value, provider: h.provider } } if topic_data.any? full_contact_topics = Qx.insert_into(:full_contact_topics) - .values(topic_data) - .common_values(full_contact_info_id: full_contact_info['id']) - .timestamps - .returning('*') - .execute + .values(topic_data) + .common_values(full_contact_info_id: full_contact_info['id']) + .timestamps + .returning('*') + .execute end end - if result['organizations'].present? Qx.delete_from('full_contact_orgs') .where(full_contact_info_id: full_contact_info['id']) .execute - org_data = result['organizations'].map{|h| { - is_primary: h.is_primary, - name: h.name, - start_date: h.start_date, - end_date: h.end_date, - title: h.title, - current: h.current - } } - .map{|h| h[:end_date] = Format::Date.parse_partial_str(h[:end_date]); h} - .map{|h| h[:start_date] = Format::Date.parse_partial_str(h[:start_date]); h} + org_data = result['organizations'].map do |h| + { + is_primary: h.is_primary, + name: h.name, + start_date: h.start_date, + end_date: h.end_date, + title: h.title, + current: h.current + } + end + .map { |h| h[:end_date] = Format::Date.parse_partial_str(h[:end_date]); h } + .map { |h| h[:start_date] = Format::Date.parse_partial_str(h[:start_date]); h } full_contact_orgs = Qx.insert_into(:full_contact_orgs) - .values(org_data) - .common_values(full_contact_info_id: full_contact_info['id']) - .timestamps - .returning('*') - .execute + .values(org_data) + .common_values(full_contact_info_id: full_contact_info['id']) + .timestamps + .returning('*') + .execute end - return { + { 'full_contact_info' => full_contact_info, 'full_contact_photos' => full_contact_photos, 'full_contact_social_profiles' => full_contact_social_profiles, @@ -176,35 +176,30 @@ module InsertFullContactInfos # Delete all orphaned full contact infos that do not have supporters # or full_contact photos, social_profiles, topics, orgs, etc that do not have a parent info def self.cleanup_orphans - Qx.delete_from("full_contact_infos") - .where("id IN ($ids)", ids: Qx.select("full_contact_infos.id") - .from("full_contact_infos") - .left_join("supporters", "full_contact_infos.supporter_id=supporters.id") - .where("supporters.id IS NULL") - ).ex - Qx.delete_from("full_contact_photos") - .where("id IN ($ids)", ids: Qx.select("full_contact_photos.id") - .from("full_contact_photos") - .left_join("full_contact_infos", "full_contact_infos.id=full_contact_photos.full_contact_info_id") - .where("full_contact_infos.id IS NULL") - ).ex - Qx.delete_from("full_contact_social_profiles") - .where("id IN ($ids)", ids: Qx.select("full_contact_social_profiles.id") - .from("full_contact_social_profiles") - .left_join("full_contact_infos", "full_contact_infos.id=full_contact_social_profiles.full_contact_info_id") - .where("full_contact_infos.id IS NULL") - ).ex - Qx.delete_from("full_contact_topics") - .where("id IN ($ids)", ids: Qx.select("full_contact_topics.id") - .from("full_contact_topics") - .left_join("full_contact_infos", "full_contact_infos.id=full_contact_topics.full_contact_info_id") - .where("full_contact_infos.id IS NULL") - ).ex - Qx.delete_from("full_contact_orgs") - .where("id IN ($ids)", ids: Qx.select("full_contact_orgs.id") - .from("full_contact_orgs") - .left_join("full_contact_infos", "full_contact_infos.id=full_contact_orgs.full_contact_info_id") - .where("full_contact_infos.id IS NULL") - ).ex + Qx.delete_from('full_contact_infos') + .where('id IN ($ids)', ids: Qx.select('full_contact_infos.id') + .from('full_contact_infos') + .left_join('supporters', 'full_contact_infos.supporter_id=supporters.id') + .where('supporters.id IS NULL')).ex + Qx.delete_from('full_contact_photos') + .where('id IN ($ids)', ids: Qx.select('full_contact_photos.id') + .from('full_contact_photos') + .left_join('full_contact_infos', 'full_contact_infos.id=full_contact_photos.full_contact_info_id') + .where('full_contact_infos.id IS NULL')).ex + Qx.delete_from('full_contact_social_profiles') + .where('id IN ($ids)', ids: Qx.select('full_contact_social_profiles.id') + .from('full_contact_social_profiles') + .left_join('full_contact_infos', 'full_contact_infos.id=full_contact_social_profiles.full_contact_info_id') + .where('full_contact_infos.id IS NULL')).ex + Qx.delete_from('full_contact_topics') + .where('id IN ($ids)', ids: Qx.select('full_contact_topics.id') + .from('full_contact_topics') + .left_join('full_contact_infos', 'full_contact_infos.id=full_contact_topics.full_contact_info_id') + .where('full_contact_infos.id IS NULL')).ex + Qx.delete_from('full_contact_orgs') + .where('id IN ($ids)', ids: Qx.select('full_contact_orgs.id') + .from('full_contact_orgs') + .left_join('full_contact_infos', 'full_contact_infos.id=full_contact_orgs.full_contact_info_id') + .where('full_contact_infos.id IS NULL')).ex end end diff --git a/lib/insert/insert_import.rb b/lib/insert/insert_import.rb index 5de38679..e7bad74e 100644 --- a/lib/insert/insert_import.rb +++ b/lib/insert/insert_import.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'required_keys' @@ -9,22 +11,19 @@ require 'insert/insert_custom_field_joins' require 'insert/insert_tag_joins' module InsertImport - # Wrap the import in a transaction and email any errors def self.from_csv_safe(data) - begin - Qx.transaction do - InsertImport.from_csv(data) - end - rescue Exception => e - body = "Import failed. Error: #{e}" - GenericMailer.generic_mail( - 'support@commitchange.com', 'Jay Bot', # FROM - body, - 'Import error', # SUBJECT - 'support@commitchange.com', 'Jay' # TO - ).deliver + Qx.transaction do + InsertImport.from_csv(data) end + rescue Exception => e + body = "Import failed. Error: #{e}" + GenericMailer.generic_mail( + 'support@commitchange.com', 'Jay Bot', # FROM + body, + 'Import error', # SUBJECT + 'support@commitchange.com', 'Jay' # TO + ).deliver end # Insert a bunch of Supporter and related data using a CSV and a bunch of header_matches @@ -33,22 +32,21 @@ module InsertImport # data: nonprofit_id, user_email, user_id, file, header_matches # Will send a notification email to user_email when the import is completed def self.from_csv(data) - ParamValidation.new(data, { - file_uri: {required: true}, - header_matches: {required: true}, - nonprofit_id: {required: true, is_integer: true}, - user_email: {required: true} - }) + ParamValidation.new(data, + file_uri: { required: true }, + header_matches: { required: true }, + nonprofit_id: { required: true, is_integer: true }, + user_email: { required: true }) import = Qx.insert_into(:imports) - .values({ - date: Time.current, - nonprofit_id: data[:nonprofit_id], - user_id: data[:user_id] - }) - .timestamps - .returning('*') - .execute.first + .values( + date: Time.current, + nonprofit_id: data[:nonprofit_id], + user_id: data[:user_id] + ) + .timestamps + .returning('*') + .execute.first row_count = 0 imported_count = 0 supporter_ids = [] @@ -59,9 +57,10 @@ module InsertImport CSV.new(open(data[:file_uri]), headers: :first_row).each do |row| row_count += 1 # triplet of [header_name, value, import_key] - matches = row.map{|key, val| [key, val, data[:header_matches][key]]} + matches = row.map { |key, val| [key, val, data[:header_matches][key]] } next if matches.empty? - table_data = matches.reduce({}) do |acc, triplet| + + table_data = matches.each_with_object({}) do |triplet, acc| key, val, match = triplet if match == 'custom_field' acc['custom_fields'] ||= [] @@ -76,7 +75,6 @@ module InsertImport acc[table][col] = val end end - acc end # Create supporter record @@ -96,11 +94,11 @@ module InsertImport if table_data['supporter']['id'] && table_data['custom_fields'] && table_data['custom_fields'].any? InsertCustomFieldJoins.find_or_create(data[:nonprofit_id], [table_data['supporter']['id']], table_data['custom_fields']) end - + # Create new tags if table_data['supporter']['id'] && table_data['tags'] && table_data['tags'].any? # Split tags by semicolons - tags = table_data['tags'].select{|t| t.present?}.map{|t| t.split(/[;,]/).map(&:strip)}.flatten + tags = table_data['tags'].select(&:present?).map { |t| t.split(/[;,]/).map(&:strip) }.flatten InsertTagJoins.find_or_create(data[:nonprofit_id], [table_data['supporter']['id']], tags) end @@ -119,7 +117,7 @@ module InsertImport # Create payment record if table_data['donation'] && table_data['donation']['id'] - table_data['payment'] = Qx.insert_into(:payments).values({ + table_data['payment'] = Qx.insert_into(:payments).values( gross_amount: table_data['donation']['amount'], fee_total: 0, net_amount: table_data['donation']['amount'], @@ -129,8 +127,8 @@ module InsertImport donation_id: table_data['donation']['id'], towards: table_data['donation']['designation'], date: table_data['donation']['date'] - }).ts.returning('*') - .execute.first + ).ts.returning('*') + .execute.first imported_count += 1 else table_data['payment'] = {} @@ -138,7 +136,7 @@ module InsertImport # Create offsite payment record if table_data['donation'] && table_data['donation']['id'] - table_data['offsite_payment'] = Qx.insert_into(:offsite_payments).values({ + table_data['offsite_payment'] = Qx.insert_into(:offsite_payments).values( gross_amount: table_data['donation']['amount'], check_number: GetData.chain(table_data['offsite_payment'], 'check_number'), kind: table_data['offsite_payment'] && table_data['offsite_payment']['check_number'] ? 'check' : '', @@ -147,8 +145,8 @@ module InsertImport donation_id: table_data['donation']['id'], payment_id: table_data['payment']['id'], date: table_data['donation']['date'] - }).ts.returning('*') - .execute.first + ).ts.returning('*') + .execute.first imported_count += 1 else table_data['offsite_payment'] = {} @@ -161,12 +159,12 @@ module InsertImport InsertActivities.for_offsite_donations(created_payment_ids) if created_payment_ids.count > 0 import = Qx.update(:imports) - .set(row_count: row_count, imported_count: imported_count) - .where(id: import['id']) - .returning('*') - .execute.first + .set(row_count: row_count, imported_count: imported_count) + .where(id: import['id']) + .returning('*') + .execute.first InsertFullContactInfos.enqueue(supporter_ids) if supporter_ids.any? ImportMailer.delay.import_completed_notification(import['id']) - return import + import end end diff --git a/lib/insert/insert_nonprofit_keys.rb b/lib/insert/insert_nonprofit_keys.rb index 10dc47db..c1b70160 100644 --- a/lib/insert/insert_nonprofit_keys.rb +++ b/lib/insert/insert_nonprofit_keys.rb @@ -1,35 +1,35 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'httparty' require 'cypher' - module InsertNonprofitKeys include HTTParty - def self.insert_mailchimp_access_token(npo_id, code) - form_data = "grant_type=authorization_code&client_id=#{URI.escape ENV['MAILCHIMP_OAUTH_CLIENT_ID']}&client_secret=#{ENV['MAILCHIMP_OAUTH_CLIENT_SECRET']}&redirect_uri=#{ENV['MAILCHIMP_REDIRECT_URL']}%2Fmailchimp-landing&code=#{URI.escape code}" + def self.insert_mailchimp_access_token(npo_id, code) + form_data = "grant_type=authorization_code&client_id=#{URI.escape ENV['MAILCHIMP_OAUTH_CLIENT_ID']}&client_secret=#{ENV['MAILCHIMP_OAUTH_CLIENT_SECRET']}&redirect_uri=#{ENV['MAILCHIMP_REDIRECT_URL']}%2Fmailchimp-landing&code=#{URI.escape code}" - response = post('https://login.mailchimp.com/oauth2/token', { body: form_data }) - if response['error'] - raise Exception.new(response['error']) - end - response['access_token'] = Cypher.encrypt(response['access_token']) + response = post('https://login.mailchimp.com/oauth2/token', body: form_data) + raise Exception, response['error'] if response['error'] - key_row_id = Qx.select("*") - .from(:nonprofit_keys).where(nonprofit_id: npo_id) - .execute.map{|h| h['id']}.first + response['access_token'] = Cypher.encrypt(response['access_token']) - if key_row_id.nil? - Qx.insert_into(:nonprofit_keys) - .values({nonprofit_id: npo_id, mailchimp_token: response['access_token'].to_json}) - .ts.execute - else - Qx.update(:nonprofit_keys) - .set(mailchimp_token: response['access_token']) - .ts.where({'id' => key_row_id}) - .execute - end + key_row_id = Qx.select('*') + .from(:nonprofit_keys).where(nonprofit_id: npo_id) + .execute.map { |h| h['id'] }.first - return response['access_token'] + if key_row_id.nil? + Qx.insert_into(:nonprofit_keys) + .values(nonprofit_id: npo_id, mailchimp_token: response['access_token'].to_json) + .ts.execute + else + Qx.update(:nonprofit_keys) + .set(mailchimp_token: response['access_token']) + .ts.where('id' => key_row_id) + .execute end + + response['access_token'] + end end diff --git a/lib/insert/insert_payout.rb b/lib/insert/insert_payout.rb index bfc6eabe..b8a52fd2 100644 --- a/lib/insert/insert_payout.rb +++ b/lib/insert/insert_payout.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Create a new payout @@ -10,82 +12,83 @@ require 'update/update_disputes' require 'param_validation' module InsertPayout - # Pass in the following inside the data hash: # - stripe_account_id # - email # - user_ip # - bank_name # options hash can have a :date (before date) for only paying out funds before a certain date (useful for only disbursing the prev month) - def self.with_stripe(np_id, data, options={}) - bigger_data = (data ? data : {}).merge(np_id: np_id) - ParamValidation.new(bigger_data, { - np_id: {required: true, is_integer: true}, - stripe_account_id: {not_blank: true, required: true}, - email: {not_blank: true, required: true}, - user_ip: {not_blank: true, required: true}, - bank_name: {not_blank: true, required: true} - }) + def self.with_stripe(np_id, data, options = {}) + bigger_data = (data || {}).merge(np_id: np_id) + ParamValidation.new(bigger_data, + np_id: { required: true, is_integer: true }, + stripe_account_id: { not_blank: true, required: true }, + email: { not_blank: true, required: true }, + user_ip: { not_blank: true, required: true }, + bank_name: { not_blank: true, required: true }) options ||= {} entities = RetrieveActiveRecordItems.retrieve_from_keys(bigger_data, Nonprofit => :np_id) payment_ids = QueryPayments.ids_for_payout(np_id, options) if payment_ids.count < 1 - raise ArgumentError.new("No payments are available for disbursal on this account.") + raise ArgumentError, 'No payments are available for disbursal on this account.' end + totals = QueryPayments.get_payout_totals(payment_ids) nonprofit_currency = entities[:np_id].currency now = Time.current begin stripe_transfer = StripeUtils.create_transfer(totals['net_amount'], data[:stripe_account_id], nonprofit_currency) - Psql.transaction do - # Create the Transfer on Stripe + Psql.transaction do + # Create the Transfer on Stripe - # Retrieve all payments with available charges and undisbursed refunds - # Mark all the above payments as disbursed - UpdateCharges.disburse_all_with_payments(payment_ids) - # Mark all the above refunds as disbursed - UpdateRefunds.disburse_all_with_payments(payment_ids) - # Mark all disputes as lost_and_paid - UpdateDisputes.disburse_all_with_payments(payment_ids) - # Get gross total, total fees, net total, and total count - # Create the payout record (whether it succeeded on Stripe or not) - payout = Psql.execute( - Qexpr.new.insert(:payouts, [{ - net_amount: totals['net_amount'], - nonprofit_id: np_id, - failure_message: stripe_transfer['failure_message'], - status: stripe_transfer.status, - fee_total: totals['fee_total'], - gross_amount: totals['gross_amount'], - email: data[:email], - count: totals['count'], - stripe_transfer_id: stripe_transfer.id, - user_ip: data[:user_ip], - ach_fee: 0, - bank_name: data[:bank_name]}]) - .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') - ).first - # Create PaymentPayout records linking all the payments to the payout - pps = Psql.execute(Qexpr.new.insert('payment_payouts', payment_ids.map{|id| {payment_id: id.to_i}}, {common_data: {payout_id: payout['id'].to_i}})) - NonprofitMailer.delay.pending_payout_notification(payout['id'].to_i) + # Retrieve all payments with available charges and undisbursed refunds + # Mark all the above payments as disbursed + UpdateCharges.disburse_all_with_payments(payment_ids) + # Mark all the above refunds as disbursed + UpdateRefunds.disburse_all_with_payments(payment_ids) + # Mark all disputes as lost_and_paid + UpdateDisputes.disburse_all_with_payments(payment_ids) + # Get gross total, total fees, net total, and total count + # Create the payout record (whether it succeeded on Stripe or not) + payout = Psql.execute( + Qexpr.new.insert(:payouts, [{ + net_amount: totals['net_amount'], + nonprofit_id: np_id, + failure_message: stripe_transfer['failure_message'], + status: stripe_transfer.status, + fee_total: totals['fee_total'], + gross_amount: totals['gross_amount'], + email: data[:email], + count: totals['count'], + stripe_transfer_id: stripe_transfer.id, + user_ip: data[:user_ip], + ach_fee: 0, + bank_name: data[:bank_name] + }]) + .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') + ).first + # Create PaymentPayout records linking all the payments to the payout + pps = Psql.execute(Qexpr.new.insert('payment_payouts', payment_ids.map { |id| { payment_id: id.to_i } }, common_data: { payout_id: payout['id'].to_i })) + NonprofitMailer.delay.pending_payout_notification(payout['id'].to_i) return payout end rescue Stripe::StripeError => e payout = Psql.execute( - Qexpr.new.insert(:payouts, [{ - net_amount: totals['net_amount'], - nonprofit_id: np_id, - failure_message: e.message, - status: 'failed', - fee_total: totals['fee_total'], - gross_amount: totals['gross_amount'], - email: data[:email], - count: totals['count'], - stripe_transfer_id: nil, - user_ip: data[:user_ip], - ach_fee: 0, - bank_name: data[:bank_name]}]) - .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') + Qexpr.new.insert(:payouts, [{ + net_amount: totals['net_amount'], + nonprofit_id: np_id, + failure_message: e.message, + status: 'failed', + fee_total: totals['fee_total'], + gross_amount: totals['gross_amount'], + email: data[:email], + count: totals['count'], + stripe_transfer_id: nil, + user_ip: data[:user_ip], + ach_fee: 0, + bank_name: data[:bank_name] + }]) + .returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name') ).first return payout end diff --git a/lib/insert/insert_recurring_donation.rb b/lib/insert/insert_recurring_donation.rb index fc2acba6..021fdfc6 100644 --- a/lib/insert/insert_recurring_donation.rb +++ b/lib/insert/insert_recurring_donation.rb @@ -1,41 +1,40 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertRecurringDonation - # Create a recurring_donation, donation, payment, charge, and activity # See controllers/nonprofits/recurring_donations_controller#create for the data params to pass in def self.with_stripe(data) data = data.with_indifferent_access ParamValidation.new(data, InsertDonation.common_param_validations - .merge(token: {required: true, format: UUID::Regex})) + .merge(token: { required: true, format: UUID::Regex })) - unless data[:recurring_donation].nil? + if data[:recurring_donation].nil? + data[:recurring_donation] = {} + else - ParamValidation.new(data[:recurring_donation], { - interval: {is_integer: true}, - start_date: {can_be_date: true}, - time_unit: {included_in: %w(month day week year)}, - paydate: {is_integer:true} - }) - if (data[:recurring_donation][:paydate]) + ParamValidation.new(data[:recurring_donation], + interval: { is_integer: true }, + start_date: { can_be_date: true }, + time_unit: { included_in: %w[month day week year] }, + paydate: { is_integer: true }) + if data[:recurring_donation][:paydate] data[:recurring_donation][:paydate] = data[:recurring_donation][:paydate].to_i end - ParamValidation.new(data[:recurring_donation], { - paydate: {min:1, max:28} - }) + ParamValidation.new(data[:recurring_donation], + paydate: { min: 1, max: 28 }) - else - data[:recurring_donation] = {} end source_token = QuerySourceToken.get_and_increment_source_token(data[:token], nil) tokenizable = source_token.tokenizable QuerySourceToken.validate_source_token_type(source_token) - entities = RetrieveActiveRecordItems.retrieve_from_keys(data, {Supporter => :supporter_id, Nonprofit => :nonprofit_id}) + entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id) - entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, {Campaign => :campaign_id, Event => :event_id, Profile => :profile_id}, true)) + entities = entities.merge(RetrieveActiveRecordItems.retrieve_from_keys(data, { Campaign => :campaign_id, Event => :event_id, Profile => :profile_id }, true)) InsertDonation.validate_entities(entities) @@ -52,10 +51,10 @@ module InsertRecurringDonation data = data.except(:old_donation).except('old_donation') # if start date is today, make initial charge first test_start_date = get_test_start_date(data) - if test_start_date == nil || Time.current >= test_start_date + if test_start_date.nil? || Time.current >= test_start_date result = result.merge(InsertDonation.insert_charge(data)) if result['charge']['status'] == 'failed' - raise ChargeError.new(result['charge']['failure_message']) + raise ChargeError, result['charge']['failure_message'] end end @@ -63,7 +62,7 @@ module InsertRecurringDonation result['donation'] = InsertDonation.insert_donation(data, entities) entities[:donation_id] = result['donation'] # Create the recurring_donation record - result['recurring_donation'] = insert_recurring_donation(data,entities) + result['recurring_donation'] = insert_recurring_donation(data, entities) # Update charge foreign keys if result['payment'] InsertDonation.update_donation_keys(result) @@ -74,10 +73,10 @@ module InsertRecurringDonation EmailJobQueue.queue(JobTypes::NonprofitPaymentNotificationJob, result['donation'].id) EmailJobQueue.queue(JobTypes::DonorPaymentNotificationJob, result['donation'].id, entities[:supporter_id].locale) QueueDonations.delay.execute_for_donation(result['donation']['id']) - return result + result end -def self.with_sepa(data) + def self.with_sepa(data) data = set_defaults(data) data = data.merge(payment_provider: payment_provider(data)) result = {} @@ -87,16 +86,14 @@ def self.with_sepa(data) end result['donation'] = Psql.execute(Qexpr.new.insert(:donations, [ - data.except(:recurring_donation) - ]).returning('*')).first + data.except(:recurring_donation) + ]).returning('*')).first result['recurring_donation'] = Psql.execute(Qexpr.new.insert(:recurring_donations, [ - data[:recurring_donation].merge(donation_id: result['donation']['id']) - ]).returning('*')).first + data[:recurring_donation].merge(donation_id: result['donation']['id']) + ]).returning('*')).first - if result['payment'] - InsertDonation.update_donation_keys(result) - end + InsertDonation.update_donation_keys(result) if result['payment'] DonationMailer.delay.nonprofit_payment_notification(result['donation']['id']) DonationMailer.delay.donor_direct_debit_notification(result['donation']['id'], locale_for_supporter(result['donation']['supporter_id'])) @@ -104,21 +101,21 @@ def self.with_sepa(data) QueueDonations.delay.execute_for_donation(result['donation']['id']) { status: 200, json: result } - end - - - # the data model here is brutal. This needs to get cleaned up. - def self.convert_donation_to_recurring_donation(donation_id) - ParamValidation.new({donation_id: donation_id}, {donation_id: {:required => true, :is_integer => true}}) - don = Donation.where('id = ? ', donation_id).first - if !don - raise ParamValidation::ValidationError.new("#{donation_id} is not a valid donation", {:key => :donation_id, :val => donation_id}) end - rd = insert_recurring_donation({amount:don.amount, email: don.supporter.email, anonymous: don.anonymous, origin_url: don.origin_url, recurring_donation: { start_date: don.created_at, :paydate => convert_date_to_valid_paydate(don.created_at)}, date: don.created_at}, {supporter_id: don.supporter, nonprofit_id: don.nonprofit, donation_id: don}) + + # the data model here is brutal. This needs to get cleaned up. + def self.convert_donation_to_recurring_donation(donation_id) + ParamValidation.new({ donation_id: donation_id }, donation_id: { required: true, is_integer: true }) + don = Donation.where('id = ? ', donation_id).first + unless don + raise ParamValidation::ValidationError.new("#{donation_id} is not a valid donation", key: :donation_id, val: donation_id) + end + + rd = insert_recurring_donation({ amount: don.amount, email: don.supporter.email, anonymous: don.anonymous, origin_url: don.origin_url, recurring_donation: { start_date: don.created_at, paydate: convert_date_to_valid_paydate(don.created_at) }, date: don.created_at }, supporter_id: don.supporter, nonprofit_id: don.nonprofit, donation_id: don) don.recurring_donation = rd don.recurring = true - don.payment.kind = "RecurringDonation" + don.payment.kind = 'RecurringDonation' don.payment.save! rd.save! don.save! @@ -126,7 +123,7 @@ def self.with_sepa(data) rd end - def self.insert_recurring_donation(data, entities) + def self.insert_recurring_donation(data, entities) rd = RecurringDonation.new rd.amount = data[:amount] rd.nonprofit = entities[:nonprofit_id] @@ -134,17 +131,17 @@ def self.with_sepa(data) rd.supporter_id = entities[:supporter_id].id rd.active = true rd.edit_token = SecureRandom.uuid - rd.n_failures= 0 - rd.email= entities[:supporter_id].email - rd.interval = data[:recurring_donation][:interval].blank? ? 1 : data[:recurring_donation][:interval] - rd.time_unit= data[:recurring_donation][:time_unit].blank? ? 'month' : data[:recurring_donation][:time_unit] - if data[:recurring_donation][:start_date].blank? - rd.start_date= Time.current.beginning_of_day - elsif data[:recurring_donation][:start_date].is_a? Time - rd.start_date = data[:recurring_donation][:start_date] - else - rd.start_date = Chronic.parse(data[:recurring_donation][:start_date]) - end + rd.n_failures = 0 + rd.email = entities[:supporter_id].email + rd.interval = data[:recurring_donation][:interval].blank? ? 1 : data[:recurring_donation][:interval] + rd.time_unit = data[:recurring_donation][:time_unit].blank? ? 'month' : data[:recurring_donation][:time_unit] + rd.start_date = if data[:recurring_donation][:start_date].blank? + Time.current.beginning_of_day + elsif data[:recurring_donation][:start_date].is_a? Time + data[:recurring_donation][:start_date] + else + Chronic.parse(data[:recurring_donation][:start_date]) + end if rd.time_unit == 'month' && rd.interval == 1 && data[:recurring_donation][:paydate].nil? rd.paydate = convert_date_to_valid_paydate(rd.start_date) @@ -154,22 +151,20 @@ def self.with_sepa(data) rd.save! rd - end -def self.get_test_start_date(data) + end + + def self.get_test_start_date(data) unless data[:recurring_donation] && data[:recurring_donation][:start_date] return nil end - return Chronic.parse(data[:recurring_donation][:start_date]) - - - end - + Chronic.parse(data[:recurring_donation][:start_date]) + end def self.locale_for_supporter(supporter_id) Psql.execute( Qexpr.new.select(:locale).from(:supporters) - .where("id=$id", id: supporter_id) + .where('id=$id', id: supporter_id) ).first['locale'] end @@ -183,6 +178,6 @@ def self.get_test_start_date(data) def self.convert_date_to_valid_paydate(date) day = date.day - return day > 28 ? 28 : day + day > 28 ? 28 : day end end diff --git a/lib/insert/insert_refunds.rb b/lib/insert/insert_refunds.rb index c50a7b47..aa589994 100644 --- a/lib/insert/insert_refunds.rb +++ b/lib/insert/insert_refunds.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'format/currency' require 'validation_error' @@ -10,30 +12,28 @@ require 'param_validation' require 'insert/insert_activities' module InsertRefunds - # Refund a given charge, up to its net amount # params: amount, donation obj def self.with_stripe(charge, h) - ParamValidation.new(charge, { - payment_id: {required: true, is_integer: true}, - stripe_charge_id: {required: true, format: /^(test_)?ch_.*$/}, - amount: {required: true, is_integer: true, min: 1}, - id: {required: true, is_integer: true}, - nonprofit_id: {required: true, is_integer: true}, - supporter_id: {required: true, is_integer: true} - }) - ParamValidation.new(h, { amount: {required: true, is_integer: true, min: 1} }) - - original_payment = Qx.select("*").from("payments").where(id: charge['payment_id']).execute.first - raise ActiveRecord::RecordNotFound.new("Cannot find original payment for refund on charge #{charge['id']}") if original_payment.nil? + ParamValidation.new(charge, + payment_id: { required: true, is_integer: true }, + stripe_charge_id: { required: true, format: /^(test_)?ch_.*$/ }, + amount: { required: true, is_integer: true, min: 1 }, + id: { required: true, is_integer: true }, + nonprofit_id: { required: true, is_integer: true }, + supporter_id: { required: true, is_integer: true }) + ParamValidation.new(h, amount: { required: true, is_integer: true, min: 1 }) + + original_payment = Qx.select('*').from('payments').where(id: charge['payment_id']).execute.first + raise ActiveRecord::RecordNotFound, "Cannot find original payment for refund on charge #{charge['id']}" if original_payment.nil? if original_payment['refund_total'].to_i + h['amount'].to_i > original_payment['gross_amount'].to_i - raise RuntimeError.new("Refund amount must be less than the net amount of the payment (for charge #{charge['id']})") + raise "Refund amount must be less than the net amount of the payment (for charge #{charge['id']})" end stripe_charge = Stripe::Charge.retrieve(charge['stripe_charge_id']) - refund_post_data = {'amount' => h['amount'], 'refund_application_fee' => true, 'reverse_transfer' => true} + refund_post_data = { 'amount' => h['amount'], 'refund_application_fee' => true, 'reverse_transfer' => true } refund_post_data['reason'] = h['reason'] unless h['reason'].blank? # Stripe will error on blank reason field stripe_refund = stripe_charge.refunds.create(refund_post_data) h['stripe_refund_id'] = stripe_refund.id @@ -45,19 +45,19 @@ module InsertRefunds fees = (h['amount'] * -original_payment['fee_total'] / original_payment['gross_amount']).ceil net = gross + fees # Create a corresponding negative payment record - payment_row = Qx.insert_into(:payments).values({ - gross_amount: gross, - fee_total: fees, - net_amount: net, - kind: 'Refund', - towards: original_payment['towards'], - date: refund_row['created_at'], - nonprofit_id: charge['nonprofit_id'], - supporter_id: charge['supporter_id'] - }) - .timestamps - .returning('*') - .execute.first + payment_row = Qx.insert_into(:payments).values( + gross_amount: gross, + fee_total: fees, + net_amount: net, + kind: 'Refund', + towards: original_payment['towards'], + date: refund_row['created_at'], + nonprofit_id: charge['nonprofit_id'], + supporter_id: charge['supporter_id'] + ) + .timestamps + .returning('*') + .execute.first InsertActivities.for_refunds([payment_row['id']]) @@ -68,8 +68,6 @@ module InsertRefunds # Send the refund receipts in a delayed job Delayed::Job.enqueue JobTypes::DonorRefundNotificationJob.new(refund_row['id']) Delayed::Job.enqueue JobTypes::NonprofitRefundNotificationJob.new(refund_row['id']) - return {'payment' => payment_row, 'refund' => refund_row} + { 'payment' => payment_row, 'refund' => refund_row } end - end - diff --git a/lib/insert/insert_source_token.rb b/lib/insert/insert_source_token.rb index ece45da2..a9e92a67 100644 --- a/lib/insert/insert_source_token.rb +++ b/lib/insert/insert_source_token.rb @@ -1,14 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertSourceToken - - def self.create_record(tokenizable, params={}) - ParamValidation.new({tokenizable:tokenizable}.merge(params), { - tokenizable: {required:true}, - event: {is_a: Event}, - expiration_time: {is_integer: true, min: 1}, - max_uses: {is_integer: true, min: 1} - }) - if (params[:event] != nil) + def self.create_record(tokenizable, params = {}) + ParamValidation.new({ tokenizable: tokenizable }.merge(params), + tokenizable: { required: true }, + event: { is_a: Event }, + expiration_time: { is_integer: true, min: 1 }, + max_uses: { is_integer: true, min: 1 }) + if !params[:event].nil? max_uses = params[:max_uses] || Settings.source_tokens.event_donation_source.max_uses expiration_diff = params[:expiration_time] || Settings.source_tokens.event_donation_source.time_after_event expiration = params[:event].end_datetime + expiration_diff.to_i @@ -26,6 +26,4 @@ module InsertSourceToken c.save! c end - - -end \ No newline at end of file +end diff --git a/lib/insert/insert_supporter.rb b/lib/insert/insert_supporter.rb index 594b93a3..a41eebdf 100644 --- a/lib/insert/insert_supporter.rb +++ b/lib/insert/insert_supporter.rb @@ -1,58 +1,57 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' require 'i18n' module InsertSupporter - - def self.create_or_update(np_id, data, update=false) - ParamValidation.new(data.merge(np_id: np_id), { - np_id: {required: true, is_integer: true} - }) - address_keys = ['name', 'address', 'city', 'country', 'state_code'] + def self.create_or_update(np_id, data, update = false) + ParamValidation.new(data.merge(np_id: np_id), + np_id: { required: true, is_integer: true }) + address_keys = %w[name address city country state_code] custom_fields = data['customFields'] data = HashWithIndifferentAccess.new(Format::RemoveDiacritics.from_hash(data, address_keys)) - .except(:customFields) + .except(:customFields) - supporter = Qx.select("*").from(:supporters) - .where("name = $n AND email = $e", n: data[:name], e: data[:email]) - .and_where("nonprofit_id=$id", id: np_id) - .and_where("coalesce(deleted, FALSE)=FALSE") - .execute.last - if supporter and update + supporter = Qx.select('*').from(:supporters) + .where('name = $n AND email = $e', n: data[:name], e: data[:email]) + .and_where('nonprofit_id=$id', id: np_id) + .and_where('coalesce(deleted, FALSE)=FALSE') + .execute.last + if supporter && update supporter = Qx.update(:supporters) - .set(defaults(data)) - .where("id=$id", id: supporter['id']) - .returning('*') - .timestamps - .execute.last - else + .set(defaults(data)) + .where('id=$id', id: supporter['id']) + .returning('*') + .timestamps + .execute.last + else supporter = Qx.insert_into(:supporters) - .values(defaults(data).merge(nonprofit_id: np_id)) - .returning('*') - .timestamps - .execute.last - end - - if custom_fields - InsertCustomFieldJoins.find_or_create(np_id, [supporter['id']], custom_fields) + .values(defaults(data).merge(nonprofit_id: np_id)) + .returning('*') + .timestamps + .execute.last end - #GeocodeModel.delay.supporter(supporter['id']) + if custom_fields + InsertCustomFieldJoins.find_or_create(np_id, [supporter['id']], custom_fields) + end + + # GeocodeModel.delay.supporter(supporter['id']) InsertFullContactInfos.enqueue([supporter['id']]) - return supporter + supporter end - - def self.defaults(h) + def self.defaults(h) h = h.except('profile_id') unless h['profile_id'].present? - if h['first_name'].present? || h['last_name'].present? - h['name'] = h['first_name'] || h['last_name'] - if h['first_name'] && h['last_name'] - h['name'] = "#{h['first_name'].strip} #{h['last_name'].strip}" - end - end + if h['first_name'].present? || h['last_name'].present? + h['name'] = h['first_name'] || h['last_name'] + if h['first_name'] && h['last_name'] + h['name'] = "#{h['first_name'].strip} #{h['last_name'].strip}" + end + end h['email_unsubscribe_uuid'] = SecureRandom.uuid @@ -62,8 +61,8 @@ module InsertSupporter h = h.except('address_line2') - return h - end + h + end # pass in a hash of supporter info, as well as # any property with tag_x will create a tag with name 'name' @@ -78,15 +77,14 @@ module InsertSupporter # The above will create a supporter with name/email, one tag with name 'xy', # and one field with name 'xy' and value 420 def self.with_tags_and_fields(np_id, data) - tags = data.select{|key, val| key.match(/^tag_/)}.map{|key, val| key.gsub('tag_', '')} - fields = data.select{|key, val| key.match(/^field_/)}.map{|key, val| [key.gsub('field_', ''), val]} - supp_cols = data.select{|key, val| !key.match(/^field_/) && !key.match(/^tag_/)} + tags = data.select { |key, _val| key.match(/^tag_/) }.map { |key, _val| key.gsub('tag_', '') } + fields = data.select { |key, _val| key.match(/^field_/) }.map { |key, val| [key.gsub('field_', ''), val] } + supp_cols = data.select { |key, _val| !key.match(/^field_/) && !key.match(/^tag_/) } supporter = create_or_update(np_id, supp_cols) InsertTagJoins.delay.find_or_create(np_id, [supporter['id']], tags) if tags.any? InsertCustomFieldJoins.delay.find_or_create(np_id, [supporter['id']], fields) if fields.any? - return supporter + supporter end - end diff --git a/lib/insert/insert_supporter_notes.rb b/lib/insert/insert_supporter_notes.rb index 003f2d06..f868c624 100644 --- a/lib/insert/insert_supporter_notes.rb +++ b/lib/insert/insert_supporter_notes.rb @@ -1,22 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'param_validation' require 'qx' module InsertSupporterNotes def self.create(notes) - ParamValidation.new(notes, { - root: { array_of_hashes: { - supporter_id: {required: true, is_integer: true}, - user_id: {required: true, is_integer: true}, - content: {required: true} - } } - }) + ParamValidation.new(notes, + root: { array_of_hashes: { + supporter_id: { required: true, is_integer: true }, + user_id: { required: true, is_integer: true }, + content: { required: true } + } }) inserted = Qx.insert_into(:supporter_notes) - .values(notes) - .timestamps - .returning('*') - .execute - InsertActivities.for_supporter_notes(inserted.map{|h| h['id']}) - return inserted + .values(notes) + .timestamps + .returning('*') + .execute + InsertActivities.for_supporter_notes(inserted.map { |h| h['id'] }) + inserted end end diff --git a/lib/insert/insert_tag_joins.rb b/lib/insert/insert_tag_joins.rb index 11fa284e..a7286ee4 100644 --- a/lib/insert/insert_tag_joins.rb +++ b/lib/insert/insert_tag_joins.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qx' module InsertTagJoins - - # @param [Integer] np_id id for a [Nonprofit] # @param [Integer] profile_id id for the [Profile] corresponding to the current user. Not used currently but needed # @param [Array] supporter_ids the ids of the all the supporters whose tags should be changed. @@ -15,69 +15,64 @@ module InsertTagJoins def self.in_bulk(np_id, profile_id, supporter_ids, tag_data) begin ParamValidation.new({ - np_id: np_id, - profile_id: profile_id, - supporter_ids: supporter_ids, - tag_data: tag_data - }, { - np_id: {required: true, is_integer: true}, - profile_id: {required: true, is_integer: true}, - supporter_ids: {is_array: true}, - tag_data: { required: true - # array_of_hashes: { - # selected: {required: true}, tag_master_id: {required: true, is_integer: true} - # } - } - }) + np_id: np_id, + profile_id: profile_id, + supporter_ids: supporter_ids, + tag_data: tag_data + }, + np_id: { required: true, is_integer: true }, + profile_id: { required: true, is_integer: true }, + supporter_ids: { is_array: true }, + tag_data: { required: true }) + # array_of_hashes: { + # selected: {required: true}, tag_master_id: {required: true, is_integer: true} + # } rescue ParamValidation::ValidationError => e - return {json: {error: "Validation error\n #{e.message}", errors: e.data}, status: :unprocessable_entity} + return { json: { error: "Validation error\n #{e.message}", errors: e.data }, status: :unprocessable_entity } end begin - return {json: {error: "Nonprofit #{np_id} is not valid"}, status: :unprocessable_entity} unless Nonprofit.exists?(np_id) - return {json: {error: "Profile #{profile_id} is not valid"}, status: :unprocessable_entity} unless Profile.exists?(profile_id) - + return { json: { error: "Nonprofit #{np_id} is not valid" }, status: :unprocessable_entity } unless Nonprofit.exists?(np_id) + return { json: { error: "Profile #{profile_id} is not valid" }, status: :unprocessable_entity } unless Profile.exists?(profile_id) # verify that the supporters belong to the nonprofit original_supporter_request = supporter_ids.count supporter_ids = Supporter.where('nonprofit_id = ? and id IN (?)', np_id, supporter_ids).pluck(:id) unless supporter_ids.any? - return {json: {inserted_count: 0, removed_count: 0}, status: :ok} + return { json: { inserted_count: 0, removed_count: 0 }, status: :ok } end # filtering the tag_data to this nonprofit - valid_ids = TagMaster.where('nonprofit_id = ? and id IN (?)', np_id, tag_data.map {|tg| tg[:tag_master_id] }).pluck(:id).to_a - filtered_tag_data = tag_data.select {|i| valid_ids.include? i[:tag_master_id].to_i} - - + valid_ids = TagMaster.where('nonprofit_id = ? and id IN (?)', np_id, tag_data.map { |tg| tg[:tag_master_id] }).pluck(:id).to_a + filtered_tag_data = tag_data.select { |i| valid_ids.include? i[:tag_master_id].to_i } # first, delete the items which should be removed - to_remove = filtered_tag_data.select{|t| !t[:selected]}.map{|t| t[:tag_master_id]} + to_remove = filtered_tag_data.reject { |t| t[:selected] }.map { |t| t[:tag_master_id] } deleted = [] if to_remove.any? deleted = Qx.delete_from(:tag_joins) - .where("supporter_id IN ($ids)", ids: supporter_ids) - .and_where("tag_master_id in ($tags)", tags: to_remove) - .returning('*') - .execute + .where('supporter_id IN ($ids)', ids: supporter_ids) + .and_where('tag_master_id in ($tags)', tags: to_remove) + .returning('*') + .execute end # next add only the selected tag_joins - to_insert = filtered_tag_data.select{|t| t[:selected]}.map{|t| t[:tag_master_id]} - insert_data = supporter_ids.map{|id| to_insert.map{|tag_master_id| {supporter_id: id, tag_master_id: tag_master_id}}}.flatten + to_insert = filtered_tag_data.select { |t| t[:selected] }.map { |t| t[:tag_master_id] } + insert_data = supporter_ids.map { |id| to_insert.map { |tag_master_id| { supporter_id: id, tag_master_id: tag_master_id } } }.flatten if insert_data.any? tags = Qx.insert_into(:tag_joins) - .values(insert_data) - .timestamps - .on_conflict() - .conflict_columns(:supporter_id, :tag_master_id).upsert(:tag_join_supporter_unique_idx) - .returning('*') - .execute + .values(insert_data) + .timestamps + .on_conflict + .conflict_columns(:supporter_id, :tag_master_id).upsert(:tag_join_supporter_unique_idx) + .returning('*') + .execute else tags = [] end rescue ActiveRecord::ActiveRecordError => e - return {json: {error: "A DB error occurred. Please contact support. \n #{e.message}"}, status: :unprocessable_entity} + return { json: { error: "A DB error occurred. Please contact support. \n #{e.message}" }, status: :unprocessable_entity } end # Create an activity for the modified tags for every supporter @@ -88,40 +83,35 @@ module InsertTagJoins # Sync mailchimp lists, if present Mailchimp.delay.sync_supporters_to_list_from_tag_joins(np_id, supporter_ids, tag_data) - return {json: {inserted_count: tags.count, removed_count: deleted.count }, status: :ok} + { json: { inserted_count: tags.count, removed_count: deleted.count }, status: :ok } end - # Find or create many tag names for every supporter # Creates tag masters for tag names that are not present def self.find_or_create(np_id, supporter_ids, tag_names) # Pair each tag name with a tag master id tags = tag_names.map do |name| tm = Qx.select(:id).from(:tag_masters) - .where(name: name) - .and_where(nonprofit_id: np_id) - .execute.last - if !tm - tm = Qx.insert_into(:tag_masters).values({ - name: name, - nonprofit_id: np_id - }).ts.returning('id').execute.last - end + .where(name: name) + .and_where(nonprofit_id: np_id) + .execute.last + tm ||= Qx.insert_into(:tag_masters).values( + name: name, + nonprofit_id: np_id + ).ts.returning('id').execute.last [name, tm['id']] end tag_join_data = supporter_ids.map do |id| - tags.map{|name, tm_id| {supporter_id: id, tag_master_id: tm_id}} + tags.map { |_name, tm_id| { supporter_id: id, tag_master_id: tm_id } } end.flatten tag_joins = Qx.insert_into(:tag_joins) - .values(tag_join_data) - .ts.returning('id').execute + .values(tag_join_data) + .ts.returning('id').execute - return tag_joins + tag_joins end private - - end diff --git a/lib/insert/insert_tickets.rb b/lib/insert/insert_tickets.rb index e1ca13d6..bb9529cb 100644 --- a/lib/insert/insert_tickets.rb +++ b/lib/insert/insert_tickets.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertTickets - # Will generate rows for payment, offsite_payment or charge, tickets, activities # pass in: # data: { @@ -16,32 +17,31 @@ module InsertTickets # } def self.create(data) data = data.with_indifferent_access - ParamValidation.new(data, { - tickets: {required: true, is_array: true}, - nonprofit_id: {required: true, is_reference: true}, - supporter_id: {required: true, is_reference: true}, - event_id: {required: true, is_reference: true}, - event_discount_id: {is_reference: true}, - kind: {included_in: ['free', 'charge', 'offsite']}, - token: {format: UUID::Regex}, - offsite_payment: {is_hash: true} - }) + ParamValidation.new(data, + tickets: { required: true, is_array: true }, + nonprofit_id: { required: true, is_reference: true }, + supporter_id: { required: true, is_reference: true }, + event_id: { required: true, is_reference: true }, + event_discount_id: { is_reference: true }, + kind: { included_in: %w[free charge offsite] }, + token: { format: UUID::Regex }, + offsite_payment: { is_hash: true }) - data[:tickets].each {|t| - ParamValidation.new(t, {quantity: {is_integer: true, required: true, min: 1}, ticket_level_id: {is_reference: true, required: true}}) - } + data[:tickets].each do |t| + ParamValidation.new(t, quantity: { is_integer: true, required: true, min: 1 }, ticket_level_id: { is_reference: true, required: true }) + end - ParamValidation.new(data[:offsite_payment], {kind: {included_in: %w(cash check)}}) if data[:offsite_payment] && !data[:offsite_payment][:kind].blank? + ParamValidation.new(data[:offsite_payment], kind: { included_in: %w[cash check] }) if data[:offsite_payment] && !data[:offsite_payment][:kind].blank? - entities = RetrieveActiveRecordItems.retrieve_from_keys(data, {Supporter => :supporter_id, Nonprofit => :nonprofit_id, Event => :event_id}) + entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Supporter => :supporter_id, Nonprofit => :nonprofit_id, Event => :event_id) - entities.merge!(RetrieveActiveRecordItems.retrieve_from_keys(data, {EventDiscount => :event_discount_id}, true)) + entities.merge!(RetrieveActiveRecordItems.retrieve_from_keys(data, { EventDiscount => :event_discount_id }, true)) tl_entities = get_ticket_level_entities(data) validate_entities(entities, tl_entities) - #verify that enough tickets_available + # verify that enough tickets_available QueryTicketLevels.verify_tickets_available(data[:tickets]) gross_amount = QueryTicketLevels.gross_amount_from_tickets(data[:tickets], data[:event_discount_id]) @@ -63,28 +63,29 @@ module InsertTickets # Create charge for tickets elsif data['kind'] == 'charge' || !data['kind'] - source_token = QuerySourceToken.get_and_increment_source_token(data[:token],nil) + source_token = QuerySourceToken.get_and_increment_source_token(data[:token], nil) QuerySourceToken.validate_source_token_type(source_token) tokenizable = source_token.tokenizable ## does the card belong to the supporter? if tokenizable.holder != entities[:supporter_id] raise ParamValidation::ValidationError.new("Supporter #{entities[:supporter_id].id} does not own card #{tokenizable.id}", key: :token) end - result = result.merge(InsertCharge.with_stripe({ - kind: "Ticket", - towards: entities[:event_id].name, - metadata: {kind: "Ticket", event_id: entities[:event_id].id, nonprofit_id: entities[:nonprofit_id].id}, - statement: "Tickets #{entities[:event_id].name}", - amount: gross_amount, - nonprofit_id: entities[:nonprofit_id].id, - supporter_id: entities[:supporter_id].id, - card_id: tokenizable.id - })) + + result = result.merge(InsertCharge.with_stripe( + kind: 'Ticket', + towards: entities[:event_id].name, + metadata: { kind: 'Ticket', event_id: entities[:event_id].id, nonprofit_id: entities[:nonprofit_id].id }, + statement: "Tickets #{entities[:event_id].name}", + amount: gross_amount, + nonprofit_id: entities[:nonprofit_id].id, + supporter_id: entities[:supporter_id].id, + card_id: tokenizable.id + )) if result['charge']['status'] == 'failed' - raise ChargeError.new(result['charge']['failure_message']) + raise ChargeError, result['charge']['failure_message'] end else - raise ParamValidation::ValidationError.new("Ticket costs money but you didn't pay.", {key: :kind}) + raise ParamValidation::ValidationError.new("Ticket costs money but you didn't pay.", key: :kind) end end @@ -94,29 +95,29 @@ module InsertTickets result['tickets'] = generated_ticket_entities(data['tickets'], result, entities) # Create the activity rows for the tickets - InsertActivities.for_tickets(result['tickets'].map{|t| t.id}) + InsertActivities.for_tickets(result['tickets'].map(&:id)) - ticket_ids = result['tickets'].map{|t| t.id} + ticket_ids = result['tickets'].map(&:id) charge_id = result['charge'] ? result['charge'].id : nil EmailJobQueue.queue(JobTypes::TicketMailerReceiptAdminJob, ticket_ids) EmailJobQueue.queue(JobTypes::TicketMailerFollowupJob, ticket_ids, charge_id) - return result - end - + result + end # Generate a set of 'bid ids' (ids for each ticket scoped within the event) def self.generate_bid_ids(event_id, tickets) # Generate the bid ids last_bid_id = Psql.execute( - Qexpr.new.select("COUNT(*)").from(:tickets) - .where("event_id=$id", id: event_id)).first['count'].to_i - tickets.zip(last_bid_id + 1 .. last_bid_id + tickets.count).map{|h, id| h.merge('bid_id' => id)} + Qexpr.new.select('COUNT(*)').from(:tickets) + .where('event_id=$id', id: event_id) + ).first['count'].to_i + tickets.zip(last_bid_id + 1..last_bid_id + tickets.count).map { |h, id| h.merge('bid_id' => id) } end - #not really needed but used for breaking into the unit test and getting the IDs + # not really needed but used for breaking into the unit test and getting the IDs def self.generated_ticket_entities(ticket_data, result, entities) - ticket_data.map{|ticket_request| + ticket_data.map do |ticket_request| t = Ticket.new t.quantity = ticket_request['quantity'] t.ticket_level = ticket_request['ticket_level_id'] @@ -128,7 +129,7 @@ module InsertTickets t.event_discount = entities[:event_discount_id] t.save! t - }.to_a + end.to_a end def self.validate_entities(entities, tl_entities) @@ -141,8 +142,8 @@ module InsertTickets raise ParamValidation::ValidationError.new("Event #{entities[:event_id].id} is deleted", key: :event_id) end - #verify that enough tickets_available - tl_entities.each {|i| + # verify that enough tickets_available + tl_entities.each do |i| if i[:ticket_level_id].deleted raise ParamValidation::ValidationError.new("Ticket level #{i[:ticket_level_id].id} is deleted", key: :tickets) end @@ -150,7 +151,7 @@ module InsertTickets if i[:ticket_level_id].event != entities[:event_id] raise ParamValidation::ValidationError.new("Ticket level #{i[:ticket_level_id].id} does not belong to event #{entities[:event_id]}", key: :tickets) end - } + end # Does the supporter belong to the nonprofit? if entities[:supporter_id].nonprofit != entities[:nonprofit_id] @@ -168,35 +169,35 @@ module InsertTickets end def self.get_ticket_level_entities(data) - data[:tickets].map{|i| + data[:tickets].map do |i| { - quantity: i[:quantity], - ticket_level_id: RetrieveActiveRecordItems.retrieve_from_keys(i, TicketLevel => :ticket_level_id)[:ticket_level_id] + quantity: i[:quantity], + ticket_level_id: RetrieveActiveRecordItems.retrieve_from_keys(i, TicketLevel => :ticket_level_id)[:ticket_level_id] } - }.to_a + end.to_a end def self.create_payment(entities, gross_amount) p = Payment.new - p.gross_amount= gross_amount - p.nonprofit= entities[:nonprofit_id] - p.supporter= entities[:supporter_id] - p.refund_total= 0 + p.gross_amount = gross_amount + p.nonprofit = entities[:nonprofit_id] + p.supporter = entities[:supporter_id] + p.refund_total = 0 p.date = Time.current p.towards = entities[:event_id].name p.fee_total = 0 p.net_amount = gross_amount - p.kind= "OffsitePayment" + p.kind = 'OffsitePayment' p.save! p end def self.create_offsite_payment(entities, gross_amount, data, payment) p = OffsitePayment.new - p.gross_amount= gross_amount - p.nonprofit= entities[:nonprofit_id] - p.supporter= entities[:supporter_id] - p.date= Time.current + p.gross_amount = gross_amount + p.nonprofit = entities[:nonprofit_id] + p.supporter = entities[:supporter_id] + p.date = Time.current p.payment = payment p.kind = data['offsite_payment']['kind'] p.check_number = data['offsite_payment']['check_number'] diff --git a/lib/insert/insert_tracking.rb b/lib/insert/insert_tracking.rb index dc5dc3ff..45b8a69b 100644 --- a/lib/insert/insert_tracking.rb +++ b/lib/insert/insert_tracking.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module InsertTracking def self.create(params) result = {} result['tracking'] = Qx.insert_into(:trackings) - .values({ - utm_campaign: params[:utm_campaign], - utm_content: params[:utm_content], - utm_medium: params[:utm_medium], - utm_source: params[:utm_source], - donation_id: params[:donation_id] - }) - .timestamps - .returning('*') - .execute.first + .values( + utm_campaign: params[:utm_campaign], + utm_content: params[:utm_content], + utm_medium: params[:utm_medium], + utm_source: params[:utm_source], + donation_id: params[:donation_id] + ) + .timestamps + .returning('*') + .execute.first { status: 200, json: result } end diff --git a/lib/job_types/admin_failed_gift_job.rb b/lib/job_types/admin_failed_gift_job.rb index aa90f2ed..d7da2959 100644 --- a/lib/job_types/admin_failed_gift_job.rb +++ b/lib/job_types/admin_failed_gift_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class AdminFailedGiftJob < EmailJob @@ -12,4 +14,4 @@ module JobTypes AdminMailer.notify_failed_gift(@donation, @campaign_gift_option).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/admin_notice_job.rb b/lib/job_types/admin_notice_job.rb index a16720f1..54b09bf8 100644 --- a/lib/job_types/admin_notice_job.rb +++ b/lib/job_types/admin_notice_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class AdminNoticeJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes GenericMailer.admin_notice(@options).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/campaign_creation_followup_job.rb b/lib/job_types/campaign_creation_followup_job.rb index cb627e0a..6c92b870 100644 --- a/lib/job_types/campaign_creation_followup_job.rb +++ b/lib/job_types/campaign_creation_followup_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class CampaignCreationFollowupJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes CampaignMailer.creation_followup(@campaign).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/donor_direct_debit_notification_job.rb b/lib/job_types/donor_direct_debit_notification_job.rb index dccf0fe0..84b94706 100644 --- a/lib/job_types/donor_direct_debit_notification_job.rb +++ b/lib/job_types/donor_direct_debit_notification_job.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class DonorDirectDebitNotificationJob < EmailJob attr_reader :donation_id - def initialize(donation_id, locale=I18n.locale) + def initialize(donation_id, locale = I18n.locale) @donation_id = donation_id @locale = locale end @@ -12,4 +14,4 @@ module JobTypes DonationMailer.donor_direct_debit_notification(@donation_id, @locale).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/donor_failed_recurring_donation_job.rb b/lib/job_types/donor_failed_recurring_donation_job.rb index 9b29bdd4..272ab40e 100644 --- a/lib/job_types/donor_failed_recurring_donation_job.rb +++ b/lib/job_types/donor_failed_recurring_donation_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class DonorFailedRecurringDonationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes DonationMailer.donor_failed_recurring_donation(@donation_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/donor_payment_notification_job.rb b/lib/job_types/donor_payment_notification_job.rb index 490bbaab..ca85280f 100644 --- a/lib/job_types/donor_payment_notification_job.rb +++ b/lib/job_types/donor_payment_notification_job.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class DonorPaymentNotificationJob < EmailJob - attr_reader :donation_id - def initialize(donation_id, locale=I18n.locale) - @donation_id = donation_id - @locale = locale - end + class DonorPaymentNotificationJob < EmailJob + attr_reader :donation_id + def initialize(donation_id, locale = I18n.locale) + @donation_id = donation_id + @locale = locale + end - def perform - DonationMailer.donor_payment_notification(@donation_id, @locale).deliver - end - end -end \ No newline at end of file + def perform + DonationMailer.donor_payment_notification(@donation_id, @locale).deliver + end + end +end diff --git a/lib/job_types/donor_recurring_donation_change_amount_job.rb b/lib/job_types/donor_recurring_donation_change_amount_job.rb index 4cb920fb..6fa6de5b 100644 --- a/lib/job_types/donor_recurring_donation_change_amount_job.rb +++ b/lib/job_types/donor_recurring_donation_change_amount_job.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class DonorRecurringDonationChangeAmountJob < EmailJob - attr_reader :donation_id, :previous_amount - def initialize(donation_id, previous_amount=nil) - @donation_id = donation_id - @previous_amount = previous_amount - end + class DonorRecurringDonationChangeAmountJob < EmailJob + attr_reader :donation_id, :previous_amount + def initialize(donation_id, previous_amount = nil) + @donation_id = donation_id + @previous_amount = previous_amount + end - def perform - DonationMailer.donor_recurring_donation_change_amount(@donation_id, @previous_amount).deliver - end - end -end \ No newline at end of file + def perform + DonationMailer.donor_recurring_donation_change_amount(@donation_id, @previous_amount).deliver + end + end +end diff --git a/lib/job_types/donor_refund_notification_job.rb b/lib/job_types/donor_refund_notification_job.rb index 8cc4357e..1343427b 100644 --- a/lib/job_types/donor_refund_notification_job.rb +++ b/lib/job_types/donor_refund_notification_job.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class DonorRefundNotificationJob < EmailJob - attr_reader :refund_id - def initialize(refund_id) - @refund_id = refund_id - end + class DonorRefundNotificationJob < EmailJob + attr_reader :refund_id + def initialize(refund_id) + @refund_id = refund_id + end - def perform - UserMailer.refund_receipt(@refund_id).deliver - end - end -end \ No newline at end of file + def perform + UserMailer.refund_receipt(@refund_id).deliver + end + end +end diff --git a/lib/job_types/email_job.rb b/lib/job_types/email_job.rb index e5811637..d238ca29 100644 --- a/lib/job_types/email_job.rb +++ b/lib/job_types/email_job.rb @@ -1,27 +1,28 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class EmailJob - def perform - raise 'You need to override this' - end + class EmailJob + def perform + raise 'You need to override this' + end - def max_attempts - MAX_EMAIL_JOB_ATTEMPTS || 1 - end + def max_attempts + MAX_EMAIL_JOB_ATTEMPTS || 1 + end - def destroy_failed_jobs? - false - end + def destroy_failed_jobs? + false + end - def error(job, exception) - end + def error(job, exception); end - def reschedule_at(current_time, attempts) - current_time + attempts**(2.195); - end + def reschedule_at(current_time, attempts) + current_time + attempts**2.195 + end - def queue_name - 'email_queue' - end - end -end \ No newline at end of file + def queue_name + 'email_queue' + end + end +end diff --git a/lib/job_types/event_creation_followup_job.rb b/lib/job_types/event_creation_followup_job.rb index 9141f3c2..cea71321 100644 --- a/lib/job_types/event_creation_followup_job.rb +++ b/lib/job_types/event_creation_followup_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class EventCreationFollowupJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes EventMailer.creation_followup(@event).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_payment_completed_job.rb b/lib/job_types/export_payment_completed_job.rb index ad60f392..c8d92482 100644 --- a/lib/job_types/export_payment_completed_job.rb +++ b/lib/job_types/export_payment_completed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportPaymentCompletedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_payments_completed_notification(export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_payment_failed_job.rb b/lib/job_types/export_payment_failed_job.rb index bb1ffeaf..991cace8 100644 --- a/lib/job_types/export_payment_failed_job.rb +++ b/lib/job_types/export_payment_failed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportPaymentFailedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_payments_failed_notification(export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_recurring_donations_completed_job.rb b/lib/job_types/export_recurring_donations_completed_job.rb index 56f4ca1f..8871a91d 100644 --- a/lib/job_types/export_recurring_donations_completed_job.rb +++ b/lib/job_types/export_recurring_donations_completed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportRecurringDonationsCompletedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_recurring_donations_completed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_recurring_donations_failed_job.rb b/lib/job_types/export_recurring_donations_failed_job.rb index dcfa69fb..705fbfa1 100644 --- a/lib/job_types/export_recurring_donations_failed_job.rb +++ b/lib/job_types/export_recurring_donations_failed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportRecurringDonationsFailedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_recurring_donations_failed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_supporter_notes_completed_job.rb b/lib/job_types/export_supporter_notes_completed_job.rb index 31ccd056..10542128 100644 --- a/lib/job_types/export_supporter_notes_completed_job.rb +++ b/lib/job_types/export_supporter_notes_completed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportSupporterNotesCompletedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_supporter_notes_completed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_supporter_notes_failed_job.rb b/lib/job_types/export_supporter_notes_failed_job.rb index 40652dc1..1579836b 100644 --- a/lib/job_types/export_supporter_notes_failed_job.rb +++ b/lib/job_types/export_supporter_notes_failed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ExportSupporterNotesFailedJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ExportMailer.export_supporter_notes_failed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_supporters_completed_job.rb b/lib/job_types/export_supporters_completed_job.rb index 7c9b09da..84e1a452 100644 --- a/lib/job_types/export_supporters_completed_job.rb +++ b/lib/job_types/export_supporters_completed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JobTypes class ExportSupportersCompletedJob < EmailJob attr_reader :export @@ -10,4 +12,4 @@ module JobTypes ExportMailer.export_supporters_completed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/export_supporters_failed_job.rb b/lib/job_types/export_supporters_failed_job.rb index e7555f9e..f8c7cfc9 100644 --- a/lib/job_types/export_supporters_failed_job.rb +++ b/lib/job_types/export_supporters_failed_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module JobTypes class ExportSupportersFailedJob < EmailJob attr_reader :export @@ -10,4 +12,4 @@ module JobTypes ExportMailer.export_supporters_failed_notification(@export).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/generic_mail_job.rb b/lib/job_types/generic_mail_job.rb index 1a7738a5..121baba0 100644 --- a/lib/job_types/generic_mail_job.rb +++ b/lib/job_types/generic_mail_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class GenericMailJob < EmailJob @@ -16,4 +18,4 @@ module JobTypes GenericMailer.generic_mail(@from_email, @from_name, @message, @subject, @to_email, @to_name).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/import_complete_notification_job.rb b/lib/job_types/import_complete_notification_job.rb index fca866b7..1ae54972 100644 --- a/lib/job_types/import_complete_notification_job.rb +++ b/lib/job_types/import_complete_notification_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class ImportCompleteNotificationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes ImportMailer.import_completed_notification(@import_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_admin_existing_invite_job.rb b/lib/job_types/nonprofit_admin_existing_invite_job.rb index 2f2a3322..0eae9123 100644 --- a/lib/job_types/nonprofit_admin_existing_invite_job.rb +++ b/lib/job_types/nonprofit_admin_existing_invite_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitAdminExistingInviteJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitAdminMailer.existing_invite(@role).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_admin_new_invite_job.rb b/lib/job_types/nonprofit_admin_new_invite_job.rb index c0d03dea..dcccbfe6 100644 --- a/lib/job_types/nonprofit_admin_new_invite_job.rb +++ b/lib/job_types/nonprofit_admin_new_invite_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitAdminNewInviteJob < EmailJob @@ -12,4 +14,4 @@ module JobTypes NonprofitAdminMailer.new_invite(@role, @raw_token).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_admin_supporter_fundraiser_job.rb b/lib/job_types/nonprofit_admin_supporter_fundraiser_job.rb index 031fd930..a4a2937d 100644 --- a/lib/job_types/nonprofit_admin_supporter_fundraiser_job.rb +++ b/lib/job_types/nonprofit_admin_supporter_fundraiser_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitAdminSupporterFundraiserJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitAdminMailer.supporter_fundraiser(@event_or_campaign).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_failed_recurring_donation_job.rb b/lib/job_types/nonprofit_failed_recurring_donation_job.rb index bb3f2f53..76bf5ce9 100644 --- a/lib/job_types/nonprofit_failed_recurring_donation_job.rb +++ b/lib/job_types/nonprofit_failed_recurring_donation_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitFailedRecurringDonationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes DonationMailer.nonprofit_failed_recurring_donation(@donation_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_failed_verification_job.rb b/lib/job_types/nonprofit_failed_verification_job.rb index ba4e71b4..68fb717e 100644 --- a/lib/job_types/nonprofit_failed_verification_job.rb +++ b/lib/job_types/nonprofit_failed_verification_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitFailedVerificationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitMailer.failed_verification_notice(@np).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_new_bank_account_job.rb b/lib/job_types/nonprofit_new_bank_account_job.rb index b7688f7c..55a2adca 100644 --- a/lib/job_types/nonprofit_new_bank_account_job.rb +++ b/lib/job_types/nonprofit_new_bank_account_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitNewBankAccountJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitMailer.new_bank_account_notification(@ba).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_payment_notification_job.rb b/lib/job_types/nonprofit_payment_notification_job.rb index 3936115e..5d328e03 100644 --- a/lib/job_types/nonprofit_payment_notification_job.rb +++ b/lib/job_types/nonprofit_payment_notification_job.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class NonprofitPaymentNotificationJob < EmailJob - attr_reader :donation_id, :user_id - def initialize(donation_id, user_id=nil) - @donation_id = donation_id - @user_id = user_id - end + class NonprofitPaymentNotificationJob < EmailJob + attr_reader :donation_id, :user_id + def initialize(donation_id, user_id = nil) + @donation_id = donation_id + @user_id = user_id + end - def perform - DonationMailer.nonprofit_payment_notification(@donation_id, @user_id).deliver - end - end -end \ No newline at end of file + def perform + DonationMailer.nonprofit_payment_notification(@donation_id, @user_id).deliver + end + end +end diff --git a/lib/job_types/nonprofit_pending_payout_job.rb b/lib/job_types/nonprofit_pending_payout_job.rb index 662e3f35..827db759 100644 --- a/lib/job_types/nonprofit_pending_payout_job.rb +++ b/lib/job_types/nonprofit_pending_payout_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitPendingPayoutJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitMailer.pending_payout_notification(@payout_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_recurring_donation_cancellation_job.rb b/lib/job_types/nonprofit_recurring_donation_cancellation_job.rb index 0f0513d6..2a33b52a 100644 --- a/lib/job_types/nonprofit_recurring_donation_cancellation_job.rb +++ b/lib/job_types/nonprofit_recurring_donation_cancellation_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitRecurringDonationCancellationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes DonationMailer.nonprofit_recurring_donation_cancellation(@donation_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_recurring_donation_change_amount_job.rb b/lib/job_types/nonprofit_recurring_donation_change_amount_job.rb index c1209e40..35528a93 100644 --- a/lib/job_types/nonprofit_recurring_donation_change_amount_job.rb +++ b/lib/job_types/nonprofit_recurring_donation_change_amount_job.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitRecurringDonationChangeAmountJob < EmailJob attr_reader :donation_id, :previous_amount - def initialize(donation_id, previous_amount=nil) + def initialize(donation_id, previous_amount = nil) @donation_id = donation_id @previous_amount = previous_amount end @@ -12,4 +14,4 @@ module JobTypes DonationMailer.nonprofit_recurring_donation_change_amount(@donation_id, @previous_amount).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_refund_notification_job.rb b/lib/job_types/nonprofit_refund_notification_job.rb index 9531c858..ea08ae3a 100644 --- a/lib/job_types/nonprofit_refund_notification_job.rb +++ b/lib/job_types/nonprofit_refund_notification_job.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes - class NonprofitRefundNotificationJob < EmailJob - attr_reader :refund_id - def initialize(refund_id) - @refund_id = refund_id - end + class NonprofitRefundNotificationJob < EmailJob + attr_reader :refund_id + def initialize(refund_id) + @refund_id = refund_id + end - def perform - NonprofitMailer.refund_notification(@refund_id).deliver - end - end -end \ No newline at end of file + def perform + NonprofitMailer.refund_notification(@refund_id).deliver + end + end +end diff --git a/lib/job_types/nonprofit_successful_verification_job.rb b/lib/job_types/nonprofit_successful_verification_job.rb index d11ae13c..a19109ef 100644 --- a/lib/job_types/nonprofit_successful_verification_job.rb +++ b/lib/job_types/nonprofit_successful_verification_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitSuccessfulVerificationJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitMailer.successful_verification_notice(@np).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/nonprofit_welcome_job.rb b/lib/job_types/nonprofit_welcome_job.rb index dd0fb773..8c13bdb1 100644 --- a/lib/job_types/nonprofit_welcome_job.rb +++ b/lib/job_types/nonprofit_welcome_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class NonprofitWelcomeJob < EmailJob @@ -11,4 +13,4 @@ module JobTypes NonprofitMailer.welcome(@nonprofit_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/ticket_mailer_followup_job.rb b/lib/job_types/ticket_mailer_followup_job.rb index e7749058..09ea2f78 100644 --- a/lib/job_types/ticket_mailer_followup_job.rb +++ b/lib/job_types/ticket_mailer_followup_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class TicketMailerFollowupJob < EmailJob @@ -12,4 +14,4 @@ module JobTypes TicketMailer.followup(@ticket_ids, @charge_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/job_types/ticket_mailer_receipt_admin_job.rb b/lib/job_types/ticket_mailer_receipt_admin_job.rb index b65c2fe2..ba0f2911 100644 --- a/lib/job_types/ticket_mailer_receipt_admin_job.rb +++ b/lib/job_types/ticket_mailer_receipt_admin_job.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module JobTypes class TicketMailerReceiptAdminJob < EmailJob attr_reader :ticket_ids - def initialize(ticket_ids, user_id=nil) + def initialize(ticket_ids, user_id = nil) @ticket_ids = ticket_ids @user_id = user_id end @@ -12,4 +14,4 @@ module JobTypes TicketMailer.receipt_admin(@ticket_ids, @user_id).deliver end end -end \ No newline at end of file +end diff --git a/lib/json_resp.rb b/lib/json_resp.rb index d5dd39b0..b2f528f4 100644 --- a/lib/json_resp.rb +++ b/lib/json_resp.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Provide a declarative json validation and error responses for the rails 'render' method in controllers # @@ -9,7 +11,6 @@ # * Respond with proper codes and error messages for everything class JsonResp - attr_accessor :errors def initialize(params, &block) @@ -17,36 +18,35 @@ class JsonResp validation = JsonResp::Validation.new(params) validation.instance_exec(params, &block) @errors = validation.errors - return self + self end - def when_valid(&block) - return {status: 422, json: {errors: @errors}} if @errors.any? + def when_valid + return { status: 422, json: { errors: @errors } } if @errors.any? + begin - @response = block.call(@params) + @response = yield(@params) rescue Exception => e - @response = {status: 500, json: {error: "We're sorry, but something went wrong. We've been notified about this issue."}} + @response = { status: 500, json: { error: "We're sorry, but something went wrong. We've been notified about this issue." } } puts e puts e.backtrace.first(10) end - return @response + @response end - # Validation of a set of request parameters class Validation - attr_accessor :errors, :params def initialize(params) @params = params @errors = [] - return self + self end def requires(*keys) - @errors.concat keys.select{|k| @params[k].blank? }.map{|k| "#{k} required"} - return Param.new(keys, @errors, @params) + @errors.concat keys.select { |k| @params[k].blank? }.map { |k| "#{k} required" } + Param.new(keys, @errors, @params) end def requires_either(key1, key2) @@ -54,16 +54,15 @@ class JsonResp if @params[key1].blank? && @params[key2].blank? @errors << error_message else - @errors.concat [key1, key2].select{|k| @params[k].blank? }.map{|k| "#{k} required"} + @errors.concat [key1, key2].select { |k| @params[k].blank? }.map { |k| "#{k} required" } end - return Param.new([key1, key2], @errors, @params) + Param.new([key1, key2], @errors, @params) end def optional(*keys) - keys_to_check = keys.select{|k| @params[k].present?} - return Param.new(keys_to_check, @errors, @params) + keys_to_check = keys.select { |k| @params[k].present? } + Param.new(keys_to_check, @errors, @params) end - end class Param @@ -74,67 +73,66 @@ class JsonResp attr_accessor :keys, :errors, :params def initialize(keys, errors, params) - @keys = keys.reject{|k| params[k].nil? } + @keys = keys.reject { |k| params[k].nil? } @errors = errors @params = params end def as_string - @errors.concat @keys.reject{|k| @params[k].is_a?(String)}.map{|k| "#{k} must be a string"} - return self + @errors.concat @keys.reject { |k| @params[k].is_a?(String) }.map { |k| "#{k} must be a string" } + self end def as_int @errors.concat @keys - .reject{|k| @params[k].is_a?(Integer) || @params[k].to_i.to_s == @params[k]} - .map{|k| "#{k} must be an integer"} - return self + .reject { |k| @params[k].is_a?(Integer) || @params[k].to_i.to_s == @params[k] } + .map { |k| "#{k} must be an integer" } + self end def with_format(regex) - @errors.concat @keys.reject{|k| @params[k] =~ regex}.map{|k| "#{k} must match: #{regex}"} - return self + @errors.concat @keys.reject { |k| @params[k] =~ regex }.map { |k| "#{k} must match: #{regex}" } + self end def one_of(*vals) - @errors.concat @keys.reject{|k| vals.include?(@params[k])}.map{|k| "#{k} must be one of: #{vals.join(", ")}"} - return self + @errors.concat @keys.reject { |k| vals.include?(@params[k]) }.map { |k| "#{k} must be one of: #{vals.join(', ')}" } + self end def nested(&block) - @errors.concat @keys.map{|k| Validation.new(@params[k]).instance_exec(@params, &block).errors}.flatten - return self + @errors.concat @keys.map { |k| Validation.new(@params[k]).instance_exec(@params, &block).errors }.flatten + self end def as_array - @errors.concat @keys.reject{|k| @params[k].is_a?(Array)}.map{|k| "#{k} must be an array"} + @errors.concat @keys.reject { |k| @params[k].is_a?(Array) }.map { |k| "#{k} must be an array" } end def array_of(&block) - @errors.concat @keys.reject{|k| @params[k].is_a?(Array)}.map{|k| "#{k} must be an array"} - @errors.concat @keys.map{|k| @params[k].map{|h| Validation.new(h).instance_exec(@params, &block).errors}}.flatten - return self + @errors.concat @keys.reject { |k| @params[k].is_a?(Array) }.map { |k| "#{k} must be an array" } + @errors.concat @keys.map { |k| @params[k].map { |h| Validation.new(h).instance_exec(@params, &block).errors } }.flatten + self end def as_date with_format /\d\d\d\d-\d\d-\d\d/ - @errors.concat @keys.map{|k| [k].concat @params[k].split('-').map(&:to_i)} - .reject{|key, year, month, day| year.present? && year > 1000 && year < 3000 && month.present? && month > 0 && month < 13 && day.present? && day > 0 && day < 32} - .map{|k, _,_,_| "#{k} must be a valid date"} + @errors.concat @keys.map { |k| [k].concat @params[k].split('-').map(&:to_i) } + .reject { |_key, year, month, day| year.present? && year > 1000 && year < 3000 && month.present? && month > 0 && month < 13 && day.present? && day > 0 && day < 32 } + .map { |k, _, _, _| "#{k} must be a valid date" } end def min(n) - @errors.concat @keys.reject{|k| @params[k] >= n}.map{|k| "#{k} must be at least #{n}"} - return self + @errors.concat @keys.reject { |k| @params[k] >= n }.map { |k| "#{k} must be at least #{n}" } + self end def max(n) - @errors.concat @keys.reject{|k| @params[k] <= n}.map{|k| "#{k} must be less than #{n + 1}"} - return self + @errors.concat @keys.reject { |k| @params[k] <= n }.map { |k| "#{k} must be less than #{n + 1}" } + self end - # TODO min_len, max_len, as_float, as_currency, as_time, as_datetime + # TODO: min_len, max_len, as_float, as_currency, as_time, as_datetime # TODO return err resp on unrecognized params - end end diff --git a/lib/list/list_activities.rb b/lib/list/list_activities.rb index da740931..d2ea977b 100644 --- a/lib/list/list_activities.rb +++ b/lib/list/list_activities.rb @@ -1,17 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module ListActivities - - def self.with_params(params, default_activities=nil) - acts = default_activities || Activity - acts = acts.includes(:supporter, :attachment, :host).order('created_at DESC') - acts = acts.where(host_id: params[:host_id]) unless params[:host_id].blank? - acts = acts.where(attachment_id: params[:attachment_id]) unless params[:attachment_id].blank? - acts = acts.where(nonprofit_id: params[:nonprofit_id]) unless params[:nonprofit_id].blank? - if params[:public] - acts = acts.is_public - end - acts = acts.limit(params[:limit]) unless params[:limit].blank? - return acts - end - + def self.with_params(params, default_activities = nil) + acts = default_activities || Activity + acts = acts.includes(:supporter, :attachment, :host).order('created_at DESC') + acts = acts.where(host_id: params[:host_id]) unless params[:host_id].blank? + acts = acts.where(attachment_id: params[:attachment_id]) unless params[:attachment_id].blank? + acts = acts.where(nonprofit_id: params[:nonprofit_id]) unless params[:nonprofit_id].blank? + acts = acts.is_public if params[:public] + acts = acts.limit(params[:limit]) unless params[:limit].blank? + acts + end end diff --git a/lib/mailchimp.rb b/lib/mailchimp.rb index 31f06bc4..8738d35e 100644 --- a/lib/mailchimp.rb +++ b/lib/mailchimp.rb @@ -1,168 +1,164 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'httparty' require 'digest/md5' module Mailchimp - include HTTParty - format :json + include HTTParty + format :json def self.base_uri(key) dc = get_datacenter(key) - return "https://#{dc}.api.mailchimp.com/3.0" + "https://#{dc}.api.mailchimp.com/3.0" end - # Run the configuration from an initializer - # data: {:api_key => String} - def self.config(hash) - @options = { - :headers => { - 'Content-Type' => 'application/json', - 'Accept' => 'application/json' - } - } - @body = { - :apikey => hash[:api_key] - } - end + # Run the configuration from an initializer + # data: {:api_key => String} + def self.config(hash) + @options = { + headers: { + 'Content-Type' => 'application/json', + 'Accept' => 'application/json' + } + } + @body = { + apikey: hash[:api_key] + } + end # Given a nonprofit mailchimp oauth2 key, return its current datacenter def self.get_datacenter(key) - metadata = HTTParty.get('https://login.mailchimp.com/oauth2/metadata', { - headers: { - 'User-Agent' => 'oauth2-draft-v10', - 'Host' => 'login.mailchimp.com', - 'Accept' => 'application/json', - 'Authorization' => "OAuth #{key}" - } - }) - return metadata['dc'] + metadata = HTTParty.get('https://login.mailchimp.com/oauth2/metadata', + headers: { + 'User-Agent' => 'oauth2-draft-v10', + 'Host' => 'login.mailchimp.com', + 'Accept' => 'application/json', + 'Authorization' => "OAuth #{key}" + }) + metadata['dc'] end - def self.signup email, mailchimp_list_id - body_hash = @body.merge({ - :id => mailchimp_list_id, - :email => {:email => email} - }) - post("/lists/subscribe", @options.merge(:body => body_hash.to_json)).parsed_response + def self.signup(email, mailchimp_list_id) + body_hash = @body.merge( + id: mailchimp_list_id, + email: { email: email } + ) + post('/lists/subscribe', @options.merge(body: body_hash.to_json)).parsed_response end def self.get_mailchimp_token(npo_id) mailchimp_token = QueryNonprofitKeys.get_key(npo_id, 'mailchimp_token') throw RuntimeError.new("No Mailchimp connection for this nonprofit: #{npo_id}") if mailchimp_token.nil? - return mailchimp_token + mailchimp_token end # Given a nonprofit id and a list of tag master ids that they make into email lists, # create those email lists on mailchimp and return an array of hashes of mailchimp list ids, names, and tag_master_id - def self.create_mailchimp_lists(npo_id, tag_master_ids) + def self.create_mailchimp_lists(npo_id, tag_master_ids) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) puts "URI #{uri}" puts "KEY #{mailchimp_token}" npo = Qx.fetch(:nonprofits, npo_id).first - tags = Qx.select("DISTINCT(tag_masters.name) AS tag_name, tag_masters.id") - .from(:tag_masters) - .where({"tag_masters.nonprofit_id" => npo_id}) - .and_where("tag_masters.id IN ($ids)", ids: tag_master_ids) - .join(:nonprofits, "tag_masters.nonprofit_id = nonprofits.id") - .execute + tags = Qx.select('DISTINCT(tag_masters.name) AS tag_name, tag_masters.id') + .from(:tag_masters) + .where('tag_masters.nonprofit_id' => npo_id) + .and_where('tag_masters.id IN ($ids)', ids: tag_master_ids) + .join(:nonprofits, 'tag_masters.nonprofit_id = nonprofits.id') + .execute tags.map do |h| - list = post(uri+'/lists', { - basic_auth: {username: '', password: mailchimp_token}, - headers: {'Content-Type' => 'application/json'}, - body: { - name: 'CommitChange-'+h['tag_name'], - contact: { - company: npo['name'], - address1: npo['address'] || '', - city: npo['city'] || '', - state: npo['state_code'] || '', - zip: npo['zip_code'] || '', - country: npo['state_code'] || '', - phone: npo['phone'] || '' - }, - permission_reminder: 'You are a registered supporter of our nonprofit.', - campaign_defaults: { - from_name: npo['name'] || '', - from_email: npo['email'].blank? ? "support@commichange.com" : npo['email'], - subject: "Enter your subject here...", - language: 'en' - }, - email_type_option: false, - visibility: 'prv' - }.to_json - }) - if list.code != 200 - raise Exception.new("Failed to create list: #{list}") - end - {id: list['id'], name: list['name'], tag_master_id: h['id']} + list = post(uri + '/lists', + basic_auth: { username: '', password: mailchimp_token }, + headers: { 'Content-Type' => 'application/json' }, + body: { + name: 'CommitChange-' + h['tag_name'], + contact: { + company: npo['name'], + address1: npo['address'] || '', + city: npo['city'] || '', + state: npo['state_code'] || '', + zip: npo['zip_code'] || '', + country: npo['state_code'] || '', + phone: npo['phone'] || '' + }, + permission_reminder: 'You are a registered supporter of our nonprofit.', + campaign_defaults: { + from_name: npo['name'] || '', + from_email: npo['email'].blank? ? 'support@commichange.com' : npo['email'], + subject: 'Enter your subject here...', + language: 'en' + }, + email_type_option: false, + visibility: 'prv' + }.to_json) + raise Exception, "Failed to create list: #{list}" if list.code != 200 + + { id: list['id'], name: list['name'], tag_master_id: h['id'] } end end # Given a nonprofit id and post_data, which is an array of batch operation hashes # See here: http://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-batch-operations/ - # Perform all the batch operations and return a status report + # Perform all the batch operations and return a status report def self.perform_batch_operations(npo_id, post_data) return if post_data.empty? + mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) - batch_job_id = post(uri + '/batches', { - basic_auth: {username: "CommitChange", password: mailchimp_token}, - headers: {'Content-Type' => 'application/json'}, - body: {operations: post_data}.to_json - })['id'] + batch_job_id = post(uri + '/batches', + basic_auth: { username: 'CommitChange', password: mailchimp_token }, + headers: { 'Content-Type' => 'application/json' }, + body: { operations: post_data }.to_json)['id'] check_batch_status(npo_id, batch_job_id) end def self.check_batch_status(npo_id, batch_job_id) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) - batch_status = get(uri+'/batches/'+batch_job_id, { - basic_auth: {username: "CommitChange", password: mailchimp_token}, - headers: {'Content-Type' => 'application/json'} - }) + batch_status = get(uri + '/batches/' + batch_job_id, + basic_auth: { username: 'CommitChange', password: mailchimp_token }, + headers: { 'Content-Type' => 'application/json' }) end def self.delete_mailchimp_lists(npo_id, mailchimp_list_ids) mailchimp_token = get_mailchimp_token(npo_id) uri = base_uri(mailchimp_token) mailchimp_list_ids.map do |id| - delete(uri + "/lists/#{id}", {basic_auth: {username: "CommitChange", password: mailchimp_token}}) + delete(uri + "/lists/#{id}", basic_auth: { username: 'CommitChange', password: mailchimp_token }) end end # `removed` and `added` are arrays of tag join ids that have been added or removed to a supporter def self.sync_supporters_to_list_from_tag_joins(npo_id, supporter_ids, tag_data) - emails = Qx.select(:email).from(:supporters).where("id IN ($ids)", ids: supporter_ids).execute.map{|h| h['email']} - to_add = get_mailchimp_list_ids(tag_data.select{|h| h['selected']}.map{|h| h['tag_master_id']}) - to_remove = get_mailchimp_list_ids(tag_data.reject{|h| h['selected']}.map{|h| h['tag_master_id']}) + emails = Qx.select(:email).from(:supporters).where('id IN ($ids)', ids: supporter_ids).execute.map { |h| h['email'] } + to_add = get_mailchimp_list_ids(tag_data.select { |h| h['selected'] }.map { |h| h['tag_master_id'] }) + to_remove = get_mailchimp_list_ids(tag_data.reject { |h| h['selected'] }.map { |h| h['tag_master_id'] }) return if to_add.empty? && to_remove.empty? - bulk_post = emails.map{|em| to_add.map{|ml_id| {method: 'POST', path: "lists/#{ml_id}/members", body: {email_address: em, status: 'subscribed'}.to_json}}}.flatten - bulk_delete = emails.map{|em| to_remove.map{|ml_id| {method: 'DELETE', path: "lists/#{ml_id}/members/#{Digest::MD5.hexdigest(em.downcase).to_s}"}}}.flatten + bulk_post = emails.map { |em| to_add.map { |ml_id| { method: 'POST', path: "lists/#{ml_id}/members", body: { email_address: em, status: 'subscribed' }.to_json } } }.flatten + bulk_delete = emails.map { |em| to_remove.map { |ml_id| { method: 'DELETE', path: "lists/#{ml_id}/members/#{Digest::MD5.hexdigest(em.downcase)}" } } }.flatten perform_batch_operations(npo_id, bulk_post.concat(bulk_delete)) end def self.get_mailchimp_list_ids(tag_master_ids) return [] if tag_master_ids.empty? - to_insert_data = Qx.select("email_lists.mailchimp_list_id") - .from(:tag_masters) - .where("tag_masters.id IN ($ids)", ids: tag_master_ids) - .join("email_lists", "email_lists.tag_master_id=tag_masters.id") - .execute.map{|h| h['mailchimp_list_id']} - end + to_insert_data = Qx.select('email_lists.mailchimp_list_id') + .from(:tag_masters) + .where('tag_masters.id IN ($ids)', ids: tag_master_ids) + .join('email_lists', 'email_lists.tag_master_id=tag_masters.id') + .execute.map { |h| h['mailchimp_list_id'] } + end # @param [Nonprofit] nonprofit def self.hard_sync_lists(nonprofit) - return if !nonprofit + return unless nonprofit nonprofit.tag_masters.not_deleted.each do |i| - if (i.email_list) - hard_sync_list(i.email_list) - end + hard_sync_list(i.email_list) if i.email_list end end @@ -170,54 +166,52 @@ module Mailchimp def self.hard_sync_list(email_list) ops = generate_batch_ops_for_hard_sync(email_list) perform_batch_operations(email_list.nonprofit.id, ops) - - end + end def self.generate_batch_ops_for_hard_sync(email_list) - #get the subscribers from mailchimp + # get the subscribers from mailchimp mailchimp_subscribers = get_list_mailchimp_subscribers(email_list) - #get our subscribers - our_supporters = email_list.tag_master.tag_joins.map{|i| i.supporter} + # get our subscribers + our_supporters = email_list.tag_master.tag_joins.map(&:supporter) - #split them as follows: + # split them as follows: # on both lists, on our list, on the mailchimp list in_both, in_mailchimp_only = mailchimp_subscribers.partition do |mc_sub| - our_supporters.any?{|s| s.email.downcase == mc_sub[:email_address].downcase} + our_supporters.any? { |s| s.email.casecmp(mc_sub[:email_address]).zero? } end - + _, in_our_side_only = our_supporters.partition do |s| - mailchimp_subscribers.any?{|mc_sub| s.email.downcase == mc_sub[:email_address].downcase} + mailchimp_subscribers.any? { |mc_sub| s.email.casecmp(mc_sub[:email_address]).zero? } end # if on our list, add to mailchimp - output = in_our_side_only.map{|i| - {method: 'POST', path: "lists/#{email_list.mailchimp_list_id}/members", body: {email_address: i.email, status: 'subscribed'}.to_json} - } + output = in_our_side_only.map do |i| + { method: 'POST', path: "lists/#{email_list.mailchimp_list_id}/members", body: { email_address: i.email, status: 'subscribed' }.to_json } + end # if on mailchimp list, delete from mailchimp - output = output.concat(in_mailchimp_only.map{|i| {method: 'DELETE', path: "lists/#{email_list.mailchimp_list_id}/members/#{i[:id]}"}}) + output = output.concat(in_mailchimp_only.map { |i| { method: 'DELETE', path: "lists/#{email_list.mailchimp_list_id}/members/#{i[:id]}" } }) - return output + output end def self.get_list_mailchimp_subscribers(email_list) mailchimp_token = get_mailchimp_token(email_list.tag_master.nonprofit.id) uri = base_uri(mailchimp_token) - result = get(uri + "/lists/#{email_list.mailchimp_list_id}/members?count=1000000000", { - basic_auth: {username: "CommitChange", password: mailchimp_token}, - headers: {'Content-Type' => 'application/json'}}) - members = result['members'].map do |i| - {id: i['id'], email_address: i['email_address']} - end.to_a + result = get(uri + "/lists/#{email_list.mailchimp_list_id}/members?count=1000000000", + basic_auth: { username: 'CommitChange', password: mailchimp_token }, + headers: { 'Content-Type' => 'application/json' }) + members = result['members'].map do |i| + { id: i['id'], email_address: i['email_address'] } + end.to_a end def self.get_email_lists(nonprofit) mailchimp_token = get_mailchimp_token(nonprofit.id) uri = base_uri(mailchimp_token) - result = get(uri + "/lists", { - basic_auth: {username: "CommitChange", password: mailchimp_token}, - headers: {'Content-Type' => 'application/json'}}) + result = get(uri + '/lists', + basic_auth: { username: 'CommitChange', password: mailchimp_token }, + headers: { 'Content-Type' => 'application/json' }) result['lists'] - - end + end end diff --git a/lib/maintain/maintain_dedications.rb b/lib/maintain/maintain_dedications.rb index d58ae687..d67f5099 100644 --- a/lib/maintain/maintain_dedications.rb +++ b/lib/maintain/maintain_dedications.rb @@ -1,44 +1,42 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module MaintainDedications def self.retrieve_json_dedications - return Qx.select('id', 'dedication').from(:donations) - .where("is_valid_json(dedication)").ex - + Qx.select('id', 'dedication').from(:donations) + .where('is_valid_json(dedication)').ex end - def self.retrieve_non_json_dedications(include_blank=false) + def self.retrieve_non_json_dedications(include_blank = false) temp = Qx.select('id', 'dedication').from(:donations) temp = temp.where("dedication IS NOT NULL AND dedication != ''") unless include_blank - temp = temp.and_where("NOT is_valid_json(dedication)") - return temp.ex + temp = temp.and_where('NOT is_valid_json(dedication)') + temp.ex end def self.create_json_dedications_from_plain_text(dedications) dedications.map do |i| - output = {id: i['id']} + output = { id: i['id'] } if i['dedication'] =~ /(((in (loving )?)?memory of|in memorium)\:? )(.+)/i - output[:dedication] = JSON.generate({type: 'memory', note: $+ }) + output[:dedication] = JSON.generate(type: 'memory', note: $+) elsif i['dedication'] =~ /((in honor of|honor of)\:? )(.+)/i - output[:dedication] = JSON.generate({type: 'honor', note: $+ }) + output[:dedication] = JSON.generate(type: 'honor', note: $+) else - output[:dedication] = JSON.generate({type: 'honor', note: i['dedication'] }) + output[:dedication] = JSON.generate(type: 'honor', note: i['dedication']) end output end.each do |i| - Qx.update(:donations).where('id = $id', {id: i[:id]}).set({dedication: i[:dedication]}).ex + Qx.update(:donations).where('id = $id', id: i[:id]).set(dedication: i[:dedication]).ex end end def self.add_honor_to_any_json_dedications_without_type(json_dedications) - json_dedications.map{|i| {'id' => i['id'], 'dedication' => JSON::parse(i['dedication']) }} - .select{|i| !%w(honor memory).include?(i['dedication']['type'])} - .map{|i| i['dedication']['type'] = 'honor'; i } - .each do |i| - Qx.update(:donations).where('id = $id', id: i['id']) - .set(dedication: JSON.generate(i['dedication'])).ex - end + json_dedications.map { |i| { 'id' => i['id'], 'dedication' => JSON.parse(i['dedication']) } } + .reject { |i| %w[honor memory].include?(i['dedication']['type']) } + .map { |i| i['dedication']['type'] = 'honor'; i } + .each do |i| + Qx.update(:donations).where('id = $id', id: i['id']) + .set(dedication: JSON.generate(i['dedication'])).ex + end end - - - -end \ No newline at end of file +end diff --git a/lib/maintain/maintain_payment_records.rb b/lib/maintain/maintain_payment_records.rb index b95edf92..a4705cc4 100644 --- a/lib/maintain/maintain_payment_records.rb +++ b/lib/maintain/maintain_payment_records.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module MaintainPaymentRecords # For records which have no associated charge, refund, nonprofit, supporter, donation or a gross_amount # The record is basically useless @@ -6,7 +8,7 @@ module MaintainPaymentRecords end def self.set_payment_supporter_and_nonprofit_though_charge_refund(i) - p = Payment.includes(:refund => :charge).find(i) + p = Payment.includes(refund: :charge).find(i) p.supporter_id = p.refund.charge.supporter_id p.nonprofit_id = p.refund.charge.nonprofit_id p.refund.disbursed = true @@ -16,9 +18,7 @@ module MaintainPaymentRecords def self.delete_payment_and_offsite_payment_record(id) p = Payment.includes(:offsite_payment).find(id) - if (p.offsite_payment) - p.offsite_payment.destroy - end + p.offsite_payment&.destroy p.destroy end -end \ No newline at end of file +end diff --git a/lib/maintain/maintain_ticket_records.rb b/lib/maintain/maintain_ticket_records.rb index d4035197..abfdb27d 100644 --- a/lib/maintain/maintain_ticket_records.rb +++ b/lib/maintain/maintain_ticket_records.rb @@ -1,18 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module MaintainTicketRecords - # a function for taking every ticket record with a card and creating a token # if the event was in the last two weeks def self.tokenize_cards_already_on_tickets Qx.transaction do - event_ids = Event.where('end_datetime >= ?', Time.current-2.weeks).pluck(:id) + event_ids = Event.where('end_datetime >= ?', Time.current - 2.weeks).pluck(:id) t = Ticket.includes(:card).includes(:event).where('card_id IS NOT NULL and event_id IN (?)', event_ids) - t.each{|i| - token = InsertSourceToken.create_record(i.card, {event: i.event}) + t.each do |i| + token = InsertSourceToken.create_record(i.card, event: i.event) i.source_token = token i.save! - } + end end end -end \ No newline at end of file +end diff --git a/lib/merge_supporters.rb b/lib/merge_supporters.rb index a679b30b..04a79035 100644 --- a/lib/merge_supporters.rb +++ b/lib/merge_supporters.rb @@ -1,81 +1,80 @@ -# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later - module MergeSupporters +# frozen_string_literal: true +# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later +module MergeSupporters # For supporters that have been merged, we want to update all their child tables to the new supporter_id def self.update_associations(old_supporter_ids, new_supporter_id, np_id, profile_id) # The new supporter needs to have the following tables from the merged supporters: - associations = [:activities, :donations, :recurring_donations, :offsite_payments, :payments, :tickets, :supporter_notes, :supporter_emails, :full_contact_infos] - + associations = %i[activities donations recurring_donations offsite_payments payments tickets supporter_notes supporter_emails full_contact_infos] + associations.each do |table_name| - Qx.update(table_name).set(supporter_id: new_supporter_id).where("supporter_id IN ($ids)", ids: old_supporter_ids).timestamps.execute + Qx.update(table_name).set(supporter_id: new_supporter_id).where('supporter_id IN ($ids)', ids: old_supporter_ids).timestamps.execute end old_supporters = Supporter.includes(:tag_joins).includes(:custom_field_joins).where('id in (?)', old_supporter_ids) - old_tags = old_supporters.map{|i| i.tag_joins.map{|j| j.tag_master}}.flatten.uniq + old_tags = old_supporters.map { |i| i.tag_joins.map(&:tag_master) }.flatten.uniq - #delete old tags + # delete old tags InsertTagJoins.in_bulk(np_id, profile_id, old_supporter_ids, - old_tags.map{|i| {tag_master_id: i.id, selected: false}}) + old_tags.map { |i| { tag_master_id: i.id, selected: false } }) + InsertTagJoins.in_bulk(np_id, profile_id, [new_supporter_id], old_tags.map { |i| { tag_master_id: i.id, selected: true } }) - InsertTagJoins.in_bulk(np_id, profile_id, [new_supporter_id], old_tags.map{|i| {tag_master_id: i.id, selected: true}}) + all_custom_field_joins = old_supporters.map(&:custom_field_joins).flatten + group_joins_by_custom_field_master = all_custom_field_joins.group_by { |i| i.custom_field_master.id } + one_custom_field_join_per_user = group_joins_by_custom_field_master.map do |_k, v| + v.sort_by(&:created_at).reverse.first + end - all_custom_field_joins = old_supporters.map{| i| i.custom_field_joins}.flatten - group_joins_by_custom_field_master = all_custom_field_joins.group_by{|i| i.custom_field_master.id} - one_custom_field_join_per_user = group_joins_by_custom_field_master.map{|k,v| - v.sort_by{|i| - i.created_at - }.reverse.first} + # delete old supporter custom_field + InsertCustomFieldJoins.in_bulk(np_id, old_supporter_ids, one_custom_field_join_per_user.map do |i| + { + custom_field_master_id: i.custom_field_master_id, + value: '' + } + end) - #delete old supporter custom_field - InsertCustomFieldJoins.in_bulk(np_id, old_supporter_ids, one_custom_field_join_per_user.map{|i| { - custom_field_master_id: i.custom_field_master_id, - value: "" - }}) - - #insert new supporter custom field - InsertCustomFieldJoins.in_bulk(np_id, [new_supporter_id], one_custom_field_join_per_user.map{|i| { - custom_field_master_id: i.custom_field_master_id, - value: i.value - }}) + # insert new supporter custom field + InsertCustomFieldJoins.in_bulk(np_id, [new_supporter_id], one_custom_field_join_per_user.map do |i| + { + custom_field_master_id: i.custom_field_master_id, + value: i.value + } + end) # Update all deleted/merged supporters to record when and where they got merged - Psql.execute(Qexpr.new.update(:supporters, {merged_at: Time.current, merged_into: new_supporter_id}).where("id IN ($ids)", ids: old_supporter_ids)) + Psql.execute(Qexpr.new.update(:supporters, merged_at: Time.current, merged_into: new_supporter_id).where('id IN ($ids)', ids: old_supporter_ids)) # Removing any duplicate custom fields UpdateCustomFieldJoins.delete_dupes([new_supporter_id]) end - def self.selected(merged_data, supporter_ids,np_id, profile_id) + def self.selected(merged_data, supporter_ids, np_id, profile_id) new_supporter = Supporter.new(merged_data) new_supporter.save! # Update merged supporters as deleted - Psql.execute(Qexpr.new.update(:supporters, {deleted: true}).where("id IN ($ids)", ids: supporter_ids)) + Psql.execute(Qexpr.new.update(:supporters, deleted: true).where('id IN ($ids)', ids: supporter_ids)) # Update all associated tables - self.update_associations(supporter_ids, new_supporter['id'],np_id, profile_id) - return {json: new_supporter, status: :ok} + update_associations(supporter_ids, new_supporter['id'], np_id, profile_id) + { json: new_supporter, status: :ok } end - # Merge supporters for a nonprofit based on an array of groups of ids, generated from QuerySupporters.dupes_on_email or dupes_on_names def self.merge_by_id_groups(np_id, arr_of_ids, profile_id) Qx.transaction do - arr_of_ids.select{|arr| arr.count > 1}.each do |ids| + arr_of_ids.select { |arr| arr.count > 1 }.each do |ids| # Get all column data from every supporter all_data = Psql.execute( Qexpr.new.from(:supporters) .select(:email, :name, :phone, :address, :city, :state_code, :zip_code, :organization, :country, :created_at) - .where("id IN ($ids)", ids: ids) - .order_by("created_at ASC") + .where('id IN ($ids)', ids: ids) + .order_by('created_at ASC') ) # Use the most recent non null/blank column data for the new supporter - data = all_data.reduce({}) do |acc, supp| - supp.except('created_at').each{|key, val| acc[key] = val unless val.blank?} - acc - end.merge({'nonprofit_id' => np_id}) + data = all_data.each_with_object({}) do |supp, acc| + supp.except('created_at').each { |key, val| acc[key] = val unless val.blank? } + end.merge('nonprofit_id' => np_id) MergeSupporters.selected(data, ids, np_id, profile_id) end end end - - end diff --git a/lib/metrics/nonprofit_metrics.rb b/lib/metrics/nonprofit_metrics.rb index 73aed549..ee651236 100644 --- a/lib/metrics/nonprofit_metrics.rb +++ b/lib/metrics/nonprofit_metrics.rb @@ -1,110 +1,110 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module NonprofitMetrics - def self.payments(np_id) Qx.select( - "(SUM(payments.gross_amount) / 100.0)::money::text AS total", - "(AVG(payments.gross_amount) / 100.0)::money::text AS average", - "(SUM(week.gross_amount) / 100.0)::money::text AS week", - "(SUM(month.gross_amount) / 100.0)::money::text AS month", - "(SUM(year.gross_amount) / 100.0)::money::text AS year", + '(SUM(payments.gross_amount) / 100.0)::money::text AS total', + '(AVG(payments.gross_amount) / 100.0)::money::text AS average', + '(SUM(week.gross_amount) / 100.0)::money::text AS week', + '(SUM(month.gross_amount) / 100.0)::money::text AS month', + '(SUM(year.gross_amount) / 100.0)::money::text AS year' ) - .from(:payments) - .left_join( - ['payments week', "week.id=payments.id AND week.date > date_trunc('week', NOW())"], - ['payments month', "month.id=payments.id AND month.date > date_trunc('month', NOW())"], - ['payments year', "year.id=payments.id AND year.date > date_trunc('year', NOW())"] - ) - .where("payments.nonprofit_id=$id", id: np_id) - .execute.last + .from(:payments) + .left_join( + ['payments week', "week.id=payments.id AND week.date > date_trunc('week', NOW())"], + ['payments month', "month.id=payments.id AND month.date > date_trunc('month', NOW())"], + ['payments year', "year.id=payments.id AND year.date > date_trunc('year', NOW())"] + ) + .where('payments.nonprofit_id=$id', id: np_id) + .execute.last end def self.recurring(np_id) # total, average, this month Qx.select( - "(SUM(recurring_donations.amount) / 100.0)::money::text AS total", - "(AVG(recurring_donations.amount) / 100.0)::money::text AS average", - "(SUM(month.amount) / 100.0)::money::text AS month", + '(SUM(recurring_donations.amount) / 100.0)::money::text AS total', + '(AVG(recurring_donations.amount) / 100.0)::money::text AS average', + '(SUM(month.amount) / 100.0)::money::text AS month' ) - .from(:recurring_donations) - .left_join("recurring_donations month", "month.id=recurring_donations.id AND month.created_at > date_trunc('month', NOW())") - .where("recurring_donations.active=TRUE") - .and_where("recurring_donations.n_failures < 3") - .and_where("recurring_donations.nonprofit_id=$id", id: np_id) - .execute.last + .from(:recurring_donations) + .left_join('recurring_donations month', "month.id=recurring_donations.id AND month.created_at > date_trunc('month', NOW())") + .where('recurring_donations.active=TRUE') + .and_where('recurring_donations.n_failures < 3') + .and_where('recurring_donations.nonprofit_id=$id', id: np_id) + .execute.last end def self.supporters(np_id) Qx.select( - "COUNT(supporters) AS total", - "COUNT(week) AS week", - "COUNT(month) AS month" + 'COUNT(supporters) AS total', + 'COUNT(week) AS week', + 'COUNT(month) AS month' ) - .from(:supporters) - .left_join("supporters week", "week.id=supporters.id AND week.created_at > date_trunc('week', NOW()) AND week.imported_at IS NULL") - .add_left_join("supporters month", "month.id=supporters.id AND month.created_at > date_trunc('month', NOW()) AND month.imported_at IS NULL") - .where("coalesce(supporters.deleted, FALSE) = FALSE") - .and_where("supporters.nonprofit_id=$id", id: np_id) - .execute.last + .from(:supporters) + .left_join('supporters week', "week.id=supporters.id AND week.created_at > date_trunc('week', NOW()) AND week.imported_at IS NULL") + .add_left_join('supporters month', "month.id=supporters.id AND month.created_at > date_trunc('month', NOW()) AND month.imported_at IS NULL") + .where('coalesce(supporters.deleted, FALSE) = FALSE') + .and_where('supporters.nonprofit_id=$id', id: np_id) + .execute.last end def self.recent_donations(np_id) Qx.select( - "(payments.gross_amount / 100)::money::text AS amount", - "payments.date", - "payments.id AS payment_id", - "supporters.name AS supporter_name", - "supporters.email AS supporter_email" + '(payments.gross_amount / 100)::money::text AS amount', + 'payments.date', + 'payments.id AS payment_id', + 'supporters.name AS supporter_name', + 'supporters.email AS supporter_email' ) - .from(:payments) - .join("supporters", "payments.supporter_id=supporters.id") - .where("payments.nonprofit_id=$id", id: np_id) - .and_where("payments.kind IN ('Donation', 'RecurringDonation', 'Ticket')") - .limit(10) - .order_by("payments.date DESC") - .execute + .from(:payments) + .join('supporters', 'payments.supporter_id=supporters.id') + .where('payments.nonprofit_id=$id', id: np_id) + .and_where("payments.kind IN ('Donation', 'RecurringDonation', 'Ticket')") + .limit(10) + .order_by('payments.date DESC') + .execute end def self.recent_supporters(np_id) - Qx.select("name", "email", "id", "created_at") - .from(:supporters) - .where("supporters.nonprofit_id=$id", id: np_id) - .and_where("coalesce(supporters.deleted, FALSE) = FALSE") - .and_where("supporters.import_id IS NULL") - .limit(10) - .order_by("supporters.created_at DESC") - .execute + Qx.select('name', 'email', 'id', 'created_at') + .from(:supporters) + .where('supporters.nonprofit_id=$id', id: np_id) + .and_where('coalesce(supporters.deleted, FALSE) = FALSE') + .and_where('supporters.import_id IS NULL') + .limit(10) + .order_by('supporters.created_at DESC') + .execute end def self.all_metrics(np_id) - keys = [:payments, :recurring, :supporters, :recent_donations, :recent_supporters, :published_campaigns] - keys.reduce({}) do |accum, elem| + keys = %i[payments recurring supporters recent_donations recent_supporters published_campaigns] + keys.each_with_object({}) do |elem, accum| accum[elem] = NonprofitMetrics.send(elem, np_id) - accum end end def self.published_campaigns(np_id) Qx.select( - "campaigns.name", - "campaigns.id", - "campaigns.created_at", - "campaigns.end_datetime", - "COUNT(supporters.id) AS supporter_count", - "(SUM(one_time.amount)/ 100)::money::text AS total_one_time", - "(SUM(recurring_donations.amount)/ 100)::money::text AS total_recurring" + 'campaigns.name', + 'campaigns.id', + 'campaigns.created_at', + 'campaigns.end_datetime', + 'COUNT(supporters.id) AS supporter_count', + '(SUM(one_time.amount)/ 100)::money::text AS total_one_time', + '(SUM(recurring_donations.amount)/ 100)::money::text AS total_recurring' ) - .from(:campaigns) - .left_join("donations", "donations.campaign_id=campaigns.id") - .add_left_join("donations AS one_time", "donations.id=one_time.id AND one_time.recurring_donation_id IS NULL") - .add_left_join("recurring_donations", "recurring_donations.donation_id=donations.id AND recurring_donations.active=TRUE") - .add_left_join("supporters", "supporters.id=donations.supporter_id") - .group_by("campaigns.id") - .where("campaigns.nonprofit_id=$id", id: np_id) - .and_where("campaigns.published = TRUE") - .order_by("campaigns.end_datetime DESC") - .execute + .from(:campaigns) + .left_join('donations', 'donations.campaign_id=campaigns.id') + .add_left_join('donations AS one_time', 'donations.id=one_time.id AND one_time.recurring_donation_id IS NULL') + .add_left_join('recurring_donations', 'recurring_donations.donation_id=donations.id AND recurring_donations.active=TRUE') + .add_left_join('supporters', 'supporters.id=donations.supporter_id') + .group_by('campaigns.id') + .where('campaigns.nonprofit_id=$id', id: np_id) + .and_where('campaigns.published = TRUE') + .order_by('campaigns.end_datetime DESC') + .execute end # Given a starting date, ending date, and time interval, @@ -113,44 +113,44 @@ module NonprofitMetrics # each hash is nested in an outer hash, set to a key that is also the date, lol # this is used in the payment_history query to fill in missing dates in the data. def self.payment_history_timespans(params) - raise ArgumentError.new("Invalid timespan") unless ['year', 'month', 'week', 'day'].include? params[:timeSpan] + raise ArgumentError, 'Invalid timespan' unless %w[year month week day].include? params[:timeSpan] + date_hash = {} beginning_of = 'beginning_of_' + params[:timeSpan] current_date = Chronic.parse(params[:startDate]).send(beginning_of) end_date = Chronic.parse(params[:endDate]).send(beginning_of) while current_date <= end_date - date = current_date.strftime("%F") - date_hash[date] = {'time_span' => date} + date = current_date.strftime('%F') + date_hash[date] = { 'time_span' => date } current_date += 1.send(params[:timeSpan]) end - return date_hash + date_hash end def self.payment_history(params) results = Qx.select( "to_char(date_trunc('#{params[:timeSpan]}', MAX(payments.date)), 'YYYY-MM-DD') AS time_span", - "coalesce(SUM(payments.gross_amount), 0) AS total_cents", - "coalesce(SUM(onetime.gross_amount ), 0) AS onetime_cents", - "coalesce(SUM(recurring.gross_amount ), 0) AS recurring_cents", - "coalesce(SUM(tickets.gross_amount ), 0) AS tickets_cents" + 'coalesce(SUM(payments.gross_amount), 0) AS total_cents', + 'coalesce(SUM(onetime.gross_amount ), 0) AS onetime_cents', + 'coalesce(SUM(recurring.gross_amount ), 0) AS recurring_cents', + 'coalesce(SUM(tickets.gross_amount ), 0) AS tickets_cents' ) - .from(:payments) - .left_join( - ["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"], - ["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"], - ["payments AS tickets", "tickets.id=payments.id AND tickets.kind='Ticket'"] - ) - .where("payments.nonprofit_id" => params[:id]) - .and_where("payments.date >= $d", d: params[:startDate]) - .and_where("payments.date <= $d", d: params[:endDate]) - .group_by("date_trunc('#{params[:timeSpan]}', payments.date)") - .order_by("MAX(payments.date)") - .execute + .from(:payments) + .left_join( + ['payments AS onetime', "onetime.id=payments.id AND onetime.kind='Donation'"], + ['payments AS recurring', "recurring.id=payments.id AND recurring.kind='RecurringDonation'"], + ['payments AS tickets', "tickets.id=payments.id AND tickets.kind='Ticket'"] + ) + .where('payments.nonprofit_id' => params[:id]) + .and_where('payments.date >= $d', d: params[:startDate]) + .and_where('payments.date <= $d', d: params[:endDate]) + .group_by("date_trunc('#{params[:timeSpan]}', payments.date)") + .order_by('MAX(payments.date)') + .execute date_hash = payment_history_timespans(params) - return results.reduce(date_hash){|acc, r| acc[r['time_span']] = r; acc}.values + results.each_with_object(date_hash) { |r, acc| acc[r['time_span']] = r; }.values end - end diff --git a/lib/name_copy_naming_algorithm.rb b/lib/name_copy_naming_algorithm.rb index 1fba6644..f70aae5f 100644 --- a/lib/name_copy_naming_algorithm.rb +++ b/lib/name_copy_naming_algorithm.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class NameCopyNamingAlgorithm < CopyNamingAlgorithm - attr_accessor :klass, :nonprofit_id # @param [Class] klass def initialize(klass, nonprofit_id) - @klass = klass - @nonprofit_id = nonprofit_id + @klass = klass + @nonprofit_id = nonprofit_id end def copy_addition @@ -13,7 +14,7 @@ class NameCopyNamingAlgorithm < CopyNamingAlgorithm end def separator_before_copy_number - " " + ' ' end def max_copies @@ -29,13 +30,10 @@ class NameCopyNamingAlgorithm < CopyNamingAlgorithm end def get_already_used_name_entities(base_name) - end_name = "#{copy_addition.gsub("(","\\(").gsub(")", "\\)")} \\d{2}" + end_name = "#{copy_addition.gsub('(', '\\(').gsub(')', '\\)')} \\d{2}" end_name_length = copy_addition.length + 3 amount_to_strip = end_name_length + base_name.length - max_length - if (amount_to_strip < 0) - amount_to_strip = 0 - end - @klass.method(:where).call('name SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)', "#{base_name[0..base_name.length-amount_to_strip-1]}_*" + end_name, nonprofit_id).select('name') + amount_to_strip = 0 if amount_to_strip < 0 + @klass.method(:where).call('name SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)', "#{base_name[0..base_name.length - amount_to_strip - 1]}_*" + end_name, nonprofit_id).select('name') end - -end \ No newline at end of file +end diff --git a/lib/notify/notify_user.rb b/lib/notify/notify_user.rb index 1a1073f1..ca0f85f7 100644 --- a/lib/notify/notify_user.rb +++ b/lib/notify/notify_user.rb @@ -1,13 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module NotifyUser - def self.send_confirmation_email(user_id) - ParamValidation.new({user_id: user_id}, user_id: {required:true, is_integer: true}) + ParamValidation.new({ user_id: user_id }, user_id: { required: true, is_integer: true }) user = User.where('id = ?', user_id).first - if !user - raise ParamValidation::ValidationError.new("#{user_id} is not a valid user id", {key: :user_id, val: user_id}) + unless user + raise ParamValidation::ValidationError.new("#{user_id} is not a valid user id", key: :user_id, val: user_id) end user.send_confirmation_instructions end -end \ No newline at end of file +end diff --git a/lib/numeric.rb b/lib/numeric.rb index af0b53b8..bf657fc0 100644 --- a/lib/numeric.rb +++ b/lib/numeric.rb @@ -1,18 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class Numeric # Works like Numeric#floor but uses an offset other than 1. Ex: 6.floor_for_delta(5) -> 5 # @param [Integer] delta the integer offsets from zero to round down to # @return [Integer] def floor_for_delta(delta) - raise ArgumentError.new('delta must be a positive integer') unless delta.is_a?(Integer) && delta > 0 - (self % delta).zero? ? self : ((self.to_i / delta)) * delta; + raise ArgumentError, 'delta must be a positive integer' unless delta.is_a?(Integer) && delta > 0 + + (self % delta).zero? ? self : ((to_i / delta)) * delta end # Works like Numeric#ceil but uses an offset other than 1. Ex: 6.floor_for_delta(5) -> 10 # @param [Integer] delta the integer offsets from zero to round up to # @return [Integer] def ceil_for_delta(delta) - raise ArgumentError.new('delta must be a positive integer') unless delta.is_a?(Integer) && delta > 0 - (self % delta).zero? ? self : ((self.floor.to_i / delta)+1) * delta; + raise ArgumentError, 'delta must be a positive integer' unless delta.is_a?(Integer) && delta > 0 + + (self % delta).zero? ? self : ((floor.to_i / delta) + 1) * delta end -end \ No newline at end of file +end diff --git a/lib/onboard_accounts.rb b/lib/onboard_accounts.rb index a04a605f..38e944c4 100644 --- a/lib/onboard_accounts.rb +++ b/lib/onboard_accounts.rb @@ -1,51 +1,50 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'param_validation' require 'qx' module OnboardAccounts - def self.create_org(params) nonprofit_data = set_nonprofit_defaults(params['nonprofit']) - ParamValidation.new(nonprofit_data, { - name: {required: true}, - # email: {required: true}, - # phone: {required: true}, - city: {required: true}, - state_code: {required: true} - }) + ParamValidation.new(nonprofit_data, + name: { required: true }, + # email: {required: true}, + # phone: {required: true}, + city: { required: true }, + state_code: { required: true }) user_data = set_user_defaults(params['user']) - ParamValidation.new(user_data, { - name: {required: true}, - email: {required: true}, - password: {required: true}, - phone: {required: true} - }) + ParamValidation.new(user_data, + name: { required: true }, + email: { required: true }, + password: { required: true }, + phone: { required: true }) extra_info = params['extraInfo'] nonprofit = Qx.insert_into(:nonprofits) - .values(nonprofit_data).timestamps - .returning('*') - .execute.last + .values(nonprofit_data).timestamps + .returning('*') + .execute.last billing_plan_id = Settings.default_bp.id billing_subscription = Qx.insert_into(:billing_subscriptions) - .values({ - nonprofit_id: nonprofit['id'], - billing_plan_id: billing_plan_id, - status: 'active' - }) - .timestamps.execute.last + .values( + nonprofit_id: nonprofit['id'], + billing_plan_id: billing_plan_id, + status: 'active' + ) + .timestamps.execute.last # Create the user using the User and Role models (since we have to use Devise) user = User.create!(user_data) role = Qx.insert_into(:roles) - .values(user_id: user.id, name: 'nonprofit_admin', host_id: nonprofit['id'], host_type: 'Nonprofit') - .timestamps - .execute.last + .values(user_id: user.id, name: 'nonprofit_admin', host_id: nonprofit['id'], host_type: 'Nonprofit') + .timestamps + .execute.last - self.delay.send_onboard_email(nonprofit, nonprofit_data, user_data, extra_info) + delay.send_onboard_email(nonprofit, nonprofit_data, user_data, extra_info) - return { + { nonprofit: nonprofit, user: user, role: role, @@ -54,59 +53,57 @@ module OnboardAccounts end ### ethis is a one time method in order to add a user without testing for the method. Do not use this long term - def self.create_org_with_user(params, user=nil) + def self.create_org_with_user(params, user = nil) nonprofit_data = set_nonprofit_defaults(params['nonprofit']) - ParamValidation.new(nonprofit_data, { - name: {required: true}, - # email: {required: true}, - # phone: {required: true}, - city: {required: true}, - state_code: {required: true} - }) - if (!user) + ParamValidation.new(nonprofit_data, + name: { required: true }, + # email: {required: true}, + # phone: {required: true}, + city: { required: true }, + state_code: { required: true }) + unless user user_data = set_user_defaults(params['user']) - ParamValidation.new(user_data, { - name: {required: true}, - email: {required: true}, - password: {required: true}, - phone: {required: true} - }) + ParamValidation.new(user_data, + name: { required: true }, + email: { required: true }, + password: { required: true }, + phone: { required: true }) end extra_info = params['extraInfo'] nonprofit = Qx.insert_into(:nonprofits) - .values(nonprofit_data).timestamps - .returning('*') - .execute.last + .values(nonprofit_data).timestamps + .returning('*') + .execute.last # Create a billing subscription for the 6% fee tier billing_plan_id = Settings.default_bp.id billing_subscription = Qx.insert_into(:billing_subscriptions) - .values({ - nonprofit_id: nonprofit['id'], - billing_plan_id: billing_plan_id, - status: 'active' - }) - .timestamps.execute.last + .values( + nonprofit_id: nonprofit['id'], + billing_plan_id: billing_plan_id, + status: 'active' + ) + .timestamps.execute.last # Create the user using the User and Role models (since we have to use Devise) user = !user ? User.create!(user_data) : user role = Qx.insert_into(:roles) - .values(user_id: user.id, name: 'nonprofit_admin', host_id: nonprofit['id'], host_type: 'Nonprofit') - .timestamps - .execute.last + .values(user_id: user.id, name: 'nonprofit_admin', host_id: nonprofit['id'], host_type: 'Nonprofit') + .timestamps + .execute.last - self.delay.send_onboard_email(nonprofit, nonprofit_data, user_data, extra_info) + delay.send_onboard_email(nonprofit, nonprofit_data, user_data, extra_info) - return { - nonprofit: nonprofit, - user: user, - role: role, - billing_subscription: billing_subscription + { + nonprofit: nonprofit, + user: user, + role: role, + billing_subscription: billing_subscription } end def self.set_nonprofit_defaults(data) - data = data.merge({ + data = data.merge( verification_status: 'unverified', published: true, vetted: Settings.nonprofits_must_be_vetted ? false : true, @@ -114,7 +111,7 @@ module OnboardAccounts city_slug: Format::Url.convert_to_slug(data[:city]), state_code_slug: Format::Url.convert_to_slug(data[:state_code]), slug: Format::Url.convert_to_slug(data[:name]) - }) + ) data end @@ -130,7 +127,7 @@ module OnboardAccounts NonprofitMailer.welcome(np['id']).deliver # Send an email notifying people internal folks of the new nonporfit, with the above info and extra_info to_emails = ['support@commitchange.com'] - message = %Q( + message = %( New signup on CommitChange for an organization with the name "#{np['name']}" Location: #{np['city']} #{np['state_code']}, #{np['zip_code']} Org Email: #{nonprofit_data['email']} @@ -140,7 +137,7 @@ module OnboardAccounts User Phone: #{user_data['phone']} Entity Type: #{extra_info['entity_type']} How they heard about us: #{extra_info['how_they_heard']} - What they want to use: #{['use_donations', 'use_crm', 'use_campaigns', 'use_events'].select{|x| extra_info[x] == 'on'}.join(", ")} + What they want to use: #{%w[use_donations use_crm use_campaigns use_events].select { |x| extra_info[x] == 'on' }.join(', ')} ) subject = "New Account Signup: #{np['name']}" GenericMailer.generic_mail('support@commitchange.com', 'CC Bot', message, subject, to_emails, '').deliver diff --git a/lib/parallel_ar.rb b/lib/parallel_ar.rb index 40d5629e..9537381f 100644 --- a/lib/parallel_ar.rb +++ b/lib/parallel_ar.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'parallel' module ParallelAr - def self.reduce(arr, accum, &block) Parallel.each(arr, in_threads: 8) do |elem| ActiveRecord::Base.connection_pool.with_connection do @@ -11,7 +12,6 @@ module ParallelAr end end end - return accum + accum end - end diff --git a/lib/path/nonprofit_path.rb b/lib/path/nonprofit_path.rb index 3b4cb912..f7a1de48 100644 --- a/lib/path/nonprofit_path.rb +++ b/lib/path/nonprofit_path.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module NonprofitPath + def self.show(np) + return '/' unless np - def self.show(np) - return "/" unless np - "/#{np.state_code_slug}/#{np.city_slug}/#{np.slug}" - end + "/#{np.state_code_slug}/#{np.city_slug}/#{np.slug}" + end - def self.dashboard(np) - "#{show(np)}/dashboard" - end + def self.dashboard(np) + "#{show(np)}/dashboard" + end end diff --git a/lib/pay_recurring_donation.rb b/lib/pay_recurring_donation.rb index 200158c9..f8f798cb 100644 --- a/lib/pay_recurring_donation.rb +++ b/lib/pay_recurring_donation.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'insert/insert_donation' require 'insert/insert_supporter_notes' @@ -5,8 +7,6 @@ require 'timespan' require 'delayed_job_helper' module PayRecurringDonation - - # Pay ALL recurring donations that are currently due; each payment gets a queued delayed_job # Returns the number of queued jobs def self.pay_all_due_with_stripe @@ -14,24 +14,23 @@ module PayRecurringDonation ids = Psql.execute_vectors( QueryRecurringDonations._all_that_are_due )[1..-1].flatten - + jobs = ids.map do |id| - {handler: DelayedJobHelper.create_handler(PayRecurringDonation, :with_stripe, [id])} + { handler: DelayedJobHelper.create_handler(PayRecurringDonation, :with_stripe, [id]) } end - Psql.execute(Qexpr.new.insert(:delayed_jobs, jobs, { - common_data: { - run_at: Time.current, - attempts: 0, - failed_at: nil, - last_error: nil, - locked_at: nil, - locked_by: nil, - priority: 0, - queue: "rec-don-payments" - } - })) - return ids + Psql.execute(Qexpr.new.insert(:delayed_jobs, jobs, + common_data: { + run_at: Time.current, + attempts: 0, + failed_at: nil, + last_error: nil, + locked_at: nil, + locked_by: nil, + priority: 0, + queue: 'rec-don-payments' + })) + ids end # run the payrecurring_donation in development so I can make sure we have the expected failures @@ -60,20 +59,19 @@ module PayRecurringDonation # Charge an existing donation via stripe, only if it is due # Pass in an instance of an existing RecurringDonation def self.with_stripe(rd_id) - ParamValidation.new({:rd_id => rd_id}, { - :rd_id => { - :required => true, - :is_integer=> true - } - }) + ParamValidation.new({ rd_id: rd_id }, + rd_id: { + required: true, + is_integer: true + }) rd = RecurringDonation.where('id = ?', rd_id).first unless rd - raise ParamValidation::ValidationError.new("#{rd_id} is not a valid recurring donation", {:key => :rd_id}) + raise ParamValidation::ValidationError.new("#{rd_id} is not a valid recurring donation", key: :rd_id) end - return false if !QueryRecurringDonations.is_due?(rd_id) + return false unless QueryRecurringDonations.is_due?(rd_id) donation = Donation.where('id = ?', rd['donation_id']).first unless donation @@ -81,94 +79,93 @@ module PayRecurringDonation end result = {} - result = result.merge(InsertDonation.insert_charge({ - 'card_id' => donation['card_id'], - 'recurring_donation' => true, - 'designation' => donation['designation'], - 'amount' => donation['amount'], - 'nonprofit_id' => donation['nonprofit_id'], - 'donation_id' => donation['id'], - 'supporter_id' => donation['supporter_id'], - 'old_donation' => true - })) + result = result.merge(InsertDonation.insert_charge( + 'card_id' => donation['card_id'], + 'recurring_donation' => true, + 'designation' => donation['designation'], + 'amount' => donation['amount'], + 'nonprofit_id' => donation['nonprofit_id'], + 'donation_id' => donation['id'], + 'supporter_id' => donation['supporter_id'], + 'old_donation' => true + )) if result['charge']['status'] != 'failed' result['recurring_donation'] = Psql.execute( - Qexpr.new.update(:recurring_donations, {n_failures: 0}) - .where("id=$id", id: rd_id).returning('*') + Qexpr.new.update(:recurring_donations, n_failures: 0) + .where('id=$id', id: rd_id).returning('*') ).first Delayed::Job.enqueue JobTypes::DonorPaymentNotificationJob.new(rd['donation_id']) Delayed::Job.enqueue JobTypes::NonprofitPaymentNotificationJob.new(rd['donation_id']) InsertActivities.for_recurring_donations([result['payment']['id']]) else result['recurring_donation'] = Psql.execute( - Qexpr.new.update(:recurring_donations, {n_failures: rd['n_failures'] + 1}) - .where("id=$id", id: rd_id).returning('*') + Qexpr.new.update(:recurring_donations, n_failures: rd['n_failures'] + 1) + .where('id=$id', id: rd_id).returning('*') ).first DonationMailer.delay.donor_failed_recurring_donation(rd['donation_id']) if rd['n_failures'] >= 3 DonationMailer.delay.nonprofit_failed_recurring_donation(rd['donation_id']) end - InsertSupporterNotes.create([{content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540}]) + InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540 }]) end - return result + result end - def self.fail_a_recurring_donation(rd, donation, notify_nonprofit=false) + def self.fail_a_recurring_donation(rd, donation, notify_nonprofit = false) recurring_donation = Psql.execute( - Qexpr.new.update(:recurring_donations, {n_failures: 3}) - .where("id=$id", id: rd['id']).returning('*') + Qexpr.new.update(:recurring_donations, n_failures: 3) + .where('id=$id', id: rd['id']).returning('*') ).first DonationMailer.delay.donor_failed_recurring_donation(rd['donation_id']) if notify_nonprofit DonationMailer.delay.nonprofit_failed_recurring_donation(rd['donation_id']) end - InsertSupporterNotes.create([{content: "This supporter had a payment failure for their recurring donation with ID #{rd['id']}", supporter_id: donation['supporter_id'], user_id: 540}]) - return recurring_donation + InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd['id']}", supporter_id: donation['supporter_id'], user_id: 540 }]) + recurring_donation end # Charge an existing donation via stripe, NO MATTER WHAT # Pass in an instance of an existing RecurringDonation - def self.with_stripe_BUT_NO_MATTER_WHAT(rd_id, enter_todays_date, run_this=false, set_this_true=false, this_one_needs_to_be_false=true, is_this_run_dangerously="no") - - if (PayRecurringDonation::ULTIMATE_VERIFICATION(enter_todays_date, run_this, set_this_true, this_one_needs_to_be_false, is_this_run_dangerously)) + def self.with_stripe_BUT_NO_MATTER_WHAT(rd_id, enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = 'no') + if PayRecurringDonation::ULTIMATE_VERIFICATION(enter_todays_date, run_this, set_this_true, this_one_needs_to_be_false, is_this_run_dangerously) rd = Psql.execute("SELECT * FROM recurring_donations WHERE id=#{rd_id}").first donation = Psql.execute("SELECT * FROM donations WHERE id=#{rd['donation_id']}").first result = {} - result = result.merge(InsertDonation.insert_charge({ - 'card_id' => donation['card_id'], - 'recurring_donation' => true, - 'designation' => donation['designation'], - 'amount' => donation['amount'], - 'nonprofit_id' => donation['nonprofit_id'], - 'donation_id' => donation['id'], - 'supporter_id' => donation['supporter_id'] - })) + result = result.merge(InsertDonation.insert_charge( + 'card_id' => donation['card_id'], + 'recurring_donation' => true, + 'designation' => donation['designation'], + 'amount' => donation['amount'], + 'nonprofit_id' => donation['nonprofit_id'], + 'donation_id' => donation['id'], + 'supporter_id' => donation['supporter_id'] + )) if result['charge']['status'] != 'failed' result['recurring_donation'] = Psql.execute( - Qexpr.new.update(:recurring_donations, {n_failures: 0}) - .where("id=$id", id: rd_id).returning('*') + Qexpr.new.update(:recurring_donations, n_failures: 0) + .where('id=$id', id: rd_id).returning('*') ).first Delayed::Job.enqueue JobTypes::DonorPaymentNotificationJob.new(rd['donation_id']) Delayed::Job.enqueue JobTypes::NonprofitPaymentNotificationJob.new(rd['donation_id']) InsertActivities.for_recurring_donations([result['payment']['id']]) else result['recurring_donation'] = Psql.execute( - Qexpr.new.update(:recurring_donations, {n_failures: rd['n_failures'] + 1}) - .where("id=$id", id: rd_id).returning('*') + Qexpr.new.update(:recurring_donations, n_failures: rd['n_failures'] + 1) + .where('id=$id', id: rd_id).returning('*') ).first DonationMailer.delay.donor_failed_recurring_donation(rd['donation_id']) if rd['n_failures'] >= 3 DonationMailer.delay.nonprofit_failed_recurring_donation(rd['donation_id']) end - InsertSupporterNotes.create([{content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540}]) + InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540 }]) end return result end - return false + false end - def self.ULTIMATE_VERIFICATION(enter_todays_date, run_this=false, set_this_true=false, this_one_needs_to_be_false=true, is_this_run_dangerously="no") - return (Date.parse(enter_todays_date) == Date.today() && run_this && set_this_true && !this_one_needs_to_be_false && is_this_run_dangerously == "run dangerously") + def self.ULTIMATE_VERIFICATION(enter_todays_date, run_this = false, set_this_true = false, this_one_needs_to_be_false = true, is_this_run_dangerously = 'no') + (Date.parse(enter_todays_date) == Date.today && run_this && set_this_true && !this_one_needs_to_be_false && is_this_run_dangerously == 'run dangerously') end end diff --git a/lib/psql.rb b/lib/psql.rb index a9a18a1a..4226ce88 100644 --- a/lib/psql.rb +++ b/lib/psql.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Some convenience wrappers around the postgresql gem, allowing us to avoid activerecord dependency # combine usage of this library with Qexpr @@ -9,11 +11,10 @@ require 'qx' # Initialize the database connection module Psql - # Execute a sql statement (string) def self.execute(statement) puts statement if ENV['RAILS_ENV'] != 'production' && ENV['RAILS_LOG_LEVEL'] == 'debug' # log to STDOUT on dev/staging - return Qx.execute_raw(raw_expr_str(statement)) + Qx.execute_raw(raw_expr_str(statement)) end # A variation of execute that returns a vector of vectors rather than a vector of hashes @@ -21,7 +22,7 @@ module Psql def self.execute_vectors(statement) puts statement if ENV['RAILS_ENV'] != 'production' && ENV['RAILS_LOG_LEVEL'] == 'debug' # log to STDOUT on dev/staging raw_str = statement.to_s.uncolorize.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') - return Qx.execute_raw(raw_expr_str(statement), format: 'csv') + Qx.execute_raw(raw_expr_str(statement), format: 'csv') end def self.transaction(&block) @@ -30,11 +31,10 @@ module Psql end end -private + private # Raw expression string def self.raw_expr_str(statement) statement.to_s.uncolorize.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') end - end diff --git a/lib/qexpr.rb b/lib/qexpr.rb index e0948527..fa3bee63 100644 --- a/lib/qexpr.rb +++ b/lib/qexpr.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # A module that allows you to construct complex SQL expressions by piecing # together methods in ruby. @@ -12,22 +14,19 @@ require 'hamster' require 'colorize' class Qexpr - attr_accessor :tree - - def initialize(h=nil) + def initialize(h = nil) @tree = Hamster::Hash[h] end - def to_s - self.parse + parse end # Parse an qexpr object into a sql string expression def parse - expr = "" + expr = '' if @tree[:insert] expr = "#{@tree[:insert]} #{@tree[:values].blue}" expr += "\nRETURNING ".bold.light_blue + (@tree[:returning] || ['id']).join(', ').blue @@ -37,8 +36,9 @@ class Qexpr # Query-based expessions expr = @tree[:update] || @tree[:delete_from] || @tree[:select] if expr.nil? || expr.empty? - raise ArgumentError.new("Must have a select, update, or delete clause") + raise ArgumentError, 'Must have a select, update, or delete clause' end + if @tree[:from] expr += "\nFROM".bold.light_blue + @tree[:from].map do |f| f.is_a?(String) ? f : " (#{f[:sub_expr].parse}\n) AS #{f[:as]}" @@ -52,44 +52,39 @@ class Qexpr expr += @tree[:limit] if @tree[:limit] expr += @tree[:offset] if @tree[:offset] - if @tree[:select] && @tree[:as] - expr = "(#{expr}) AS #{@tree[:as]}" - end + expr = "(#{expr}) AS #{@tree[:as]}" if @tree[:select] && @tree[:as] if @tree[:update] && @tree[:returning] expr += "\nRETURNING ".bold.light_blue + @tree[:returning].join(', ').blue end - return expr + expr end - # insert into table_name the values from every hash inside of arr # optionally pass in: # no_timestamps: don't set created_at and updated_at # common_data: a hash of data to set for all rows # returning: what columns to return - def insert(table_name, arr, options={}) + def insert(table_name, arr, options = {}) arr = [arr] if arr.is_a? Hash - arr = arr.map{|h| h.sort.to_h} # Make sure all key/vals are ordered the same way + arr = arr.map { |h| h.sort.to_h } # Make sure all key/vals are ordered the same way keys = arr.first.keys keys = keys.concat(options[:common_data].keys) if options[:common_data] - keys = keys.map{|k| "\"#{k}\""}.join(', ') - ts_columns = options[:no_timestamps] ? "" : "created_at, updated_at, " - ts_values = options[:no_timestamps] ? "" : "#{Qexpr.now}, #{Qexpr.now}, " - common_vals = options[:common_data] ? options[:common_data].values.map{|v| Qexpr.quote(v)} : [] - vals = arr.map{|h| '(' + ts_values + h.values.map{|v| Qexpr.quote(v)}.concat(common_vals).join(',') + ')'}.join(',') + keys = keys.map { |k| "\"#{k}\"" }.join(', ') + ts_columns = options[:no_timestamps] ? '' : 'created_at, updated_at, ' + ts_values = options[:no_timestamps] ? '' : "#{Qexpr.now}, #{Qexpr.now}, " + common_vals = options[:common_data] ? options[:common_data].values.map { |v| Qexpr.quote(v) } : [] + vals = arr.map { |h| '(' + ts_values + h.values.map { |v| Qexpr.quote(v) }.concat(common_vals).join(',') + ')' }.join(',') Qexpr.new @tree - .put(:insert, "INSERT INTO".bold.light_blue + " #{table_name} (#{ts_columns} #{keys})".blue) + .put(:insert, 'INSERT INTO'.bold.light_blue + " #{table_name} (#{ts_columns} #{keys})".blue) .put(:values, "\nVALUES".bold.light_blue + " #{vals}".blue) end - - def update(table_name, settings, os={}) - Qexpr.new @tree.put(:update, "UPDATE".bold.light_blue + " #{table_name}".blue + "\nSET".bold.light_blue + " #{settings.map{|key,val| "#{key.to_s}=#{Qexpr.quote(val)}"}.join(', ')}".blue) + def update(table_name, settings, _os = {}) + Qexpr.new @tree.put(:update, 'UPDATE'.bold.light_blue + " #{table_name}".blue + "\nSET".bold.light_blue + " #{settings.map { |key, val| "#{key}=#{Qexpr.quote(val)}" }.join(', ')}".blue) end - def delete_from(table_name) - Qexpr.new @tree.put(:delete_from, "DELETE FROM".bold.light_blue + " #{table_name}".blue) + Qexpr.new @tree.put(:delete_from, 'DELETE FROM'.bold.light_blue + " #{table_name}".blue) end # Create or append select columns @@ -97,12 +92,12 @@ class Qexpr if @tree[:select] Qexpr.new @tree.put(:select, @tree[:select] + ", #{cols.join(', ')}".blue) else - if cols.count < 4 - cols = " #{cols.join(", ")}" - else - cols = "\n #{cols.join("\n, ")}" - end - Qexpr.new @tree.put(:select, "\nSELECT".bold.light_blue + "#{cols}".blue) + cols = if cols.count < 4 + " #{cols.join(', ')}" + else + "\n #{cols.join("\n, ")}" + end + Qexpr.new @tree.put(:select, "\nSELECT".bold.light_blue + cols.to_s.blue) end end @@ -110,67 +105,59 @@ class Qexpr Qexpr.new @tree.put(:select, "\nSELECT DISTINCT".bold.light_blue + "\n #{cols.join("\n, ")}".blue) end - def select_distinct_on(cols_distinct, cols_select) - Qexpr.new @tree.put(:select, "SELECT DISTINCT ON".bold.light_blue + " (#{Array(cols_distinct).join(', ')})\n #{Array(cols_select).join("\n, ")}".blue) + Qexpr.new @tree.put(:select, 'SELECT DISTINCT ON'.bold.light_blue + " (#{Array(cols_distinct).join(', ')})\n #{Array(cols_select).join("\n, ")}".blue) end - - def from(expr, as=nil) + def from(expr, as = nil) Qexpr.new @tree.put(:from, (@tree[:from] || Hamster::Vector[]).add(Qexpr.from_expr(expr, as))) end - def group_by(*cols) Qexpr.new @tree.put(:group_by, "\nGROUP BY".bold.light_blue + " #{cols.join(', ')}".blue) end - def order_by(expr) - Qexpr.new @tree.put(:order_by, "\nORDER BY".bold.light_blue + " #{expr.to_s}".blue) + Qexpr.new @tree.put(:order_by, "\nORDER BY".bold.light_blue + " #{expr}".blue) end - def limit(i) Qexpr.new @tree.put(:limit, "\nLIMIT".bold.light_blue + " #{i.to_i}".blue) end - def offset(i) Qexpr.new @tree.put(:offset, "\nOFFSET".bold.light_blue + " #{i.to_i}".blue) end - - def join(table_name, on_expr, data={}) + def join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) - return Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nJOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) + Qexpr.new @tree + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nJOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) end - def inner_join(table_name, on_expr, data={}) + def inner_join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) - return Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nINNER JOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) + Qexpr.new @tree + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nINNER JOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) end - def left_outer_join(table_name, on_expr, data={}) + def left_outer_join(table_name, on_expr, data = {}) on_expr = Qexpr.interpolate_expr(on_expr, data) - return Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nLEFT OUTER JOIN".bold.light_blue + " #{table_name}\n ".blue + "ON".bold.light_blue + " #{on_expr}".blue)) + Qexpr.new @tree + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\nLEFT OUTER JOIN".bold.light_blue + " #{table_name}\n ".blue + 'ON'.bold.light_blue + " #{on_expr}".blue)) end - def join_lateral(join_name, select_statement, success_condition=true, data={}) + def join_lateral(join_name, select_statement, success_condition = true, data = {}) select_statement = Qexpr.interpolate_expr(select_statement, data) - return Qexpr.new @tree - .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\n JOIN LATERAL".bold.light_blue + " (#{select_statement})\n #{join_name} ".blue + "ON".bold.light_blue + " #{success_condition}".blue)) + Qexpr.new @tree + .put(:joins, (@tree[:joins] || Hamster::Vector[]).add("\n JOIN LATERAL".bold.light_blue + " (#{select_statement})\n #{join_name} ".blue + 'ON'.bold.light_blue + " #{success_condition}".blue)) end - def as(name) - return Qexpr.new @tree.put(:as, name) + Qexpr.new @tree.put(:as, name) end - def where(expr, data={}) + def where(expr, data = {}) expr = Qexpr.interpolate_expr(expr, data) if @tree[:where] Qexpr.new @tree.put(:where, @tree[:where] + "\nAND".bold.light_blue + " (#{expr})".blue) @@ -179,13 +166,11 @@ class Qexpr end end - def returning(*cols) Qexpr.new @tree.put(:returning, (@tree[:returning] || Hamster::Vector[]).concat(cols)) end - - def having(expr, data={}) + def having(expr, data = {}) if @tree[:having] Qexpr.new @tree.put(:having, @tree[:having] + "\nAND".bold.light_blue + " (#{Qexpr.interpolate_expr(expr, data)})".blue) else @@ -201,7 +186,7 @@ class Qexpr # Remove clauses from the expression # eg expr.remove(:from, :where) def remove(*keys) - return Qexpr.new keys.reduce(@tree){|tree, key| tree.delete(key)} + Qexpr.new keys.reduce(@tree) { |tree, key| tree.delete(key) } end # Quote a string for use in sql to prevent injection or weird errors @@ -211,19 +196,19 @@ class Qexpr def self.quote(val) if val.is_a?(Integer) || (val.is_a?(String) && val =~ /^\$Q\$.+\$Q\$$/) # is a valid num or already quoted val - elsif val == nil - "NULL" + elsif val.nil? + 'NULL' elsif !!val == val # is a boolean val ? "'t'" : "'f'" else - return "$Q$" + val.to_s + "$Q$" + '$Q$' + val.to_s + '$Q$' end end # An alias of PG.quote_ident, for convenience sake # Double-quotes sql identifiers def self.quote_ident(str) - str.split('.').map{|s| "\"#{s}\""}.join('.') + str.split('.').map { |s| "\"#{s}\"" }.join('.') end # sql-quoted datetime value useful for created_at and updated_at columns @@ -234,7 +219,7 @@ class Qexpr # Given a max page length and the current page, # return the offset value # (eg: page_length=30 and page=3, then return 60) - def self.page_offset(page_length, page=1) + def self.page_offset(page_length, page = 1) page = page.to_i page = 1 if page <= 0 Qexpr.quote((page.to_i - 1) * page_length.to_i) @@ -242,11 +227,12 @@ class Qexpr # Given the total row count, the max page length, and the current page, # return the total results left - def self.remaining_count(total_count, page_length, current_page=1) - return 0 unless current_page - rem = total_count.to_i - (current_page.to_i) * page_length.to_i - rem = 0 if rem < 0 - return rem + def self.remaining_count(total_count, page_length, current_page = 1) + return 0 unless current_page + + rem = total_count.to_i - current_page.to_i * page_length.to_i + rem = 0 if rem < 0 + rem end # Given a string sql expression with interpolations like "WHERE id > ${id}" @@ -256,14 +242,14 @@ class Qexpr expr.gsub(/\$\w+/) do |match| val = data[match.gsub(/[ \$]*/, '').to_sym] if val.is_a?(Array) || val.is_a?(Hamster::Vector) - val.to_a.map{|x| Qexpr.quote(x)}.join(', ') + val.to_a.map { |x| Qexpr.quote(x) }.join(', ') else Qexpr.quote val end end end -private + private # Given some kind of expr object (might be just a string or another whole Qexpr expr), and an 'as' value # then give back either a hash for the sub-Qexpr expression, or just a string. @@ -272,7 +258,7 @@ private if expr.is_a?(Qexpr) Hamster::Hash[sub_expr: expr, as: as] else - " #{expr} #{as ? "AS #{as.to_s}" : ""}" + " #{expr} #{as ? "AS #{as}" : ''}" end end end diff --git a/lib/qexpr_query_chunker.rb b/lib/qexpr_query_chunker.rb index c61cf28b..8853b25f 100644 --- a/lib/qexpr_query_chunker.rb +++ b/lib/qexpr_query_chunker.rb @@ -1,34 +1,27 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -#TODO combine these two items +# TODO combine these two items module QexprQueryChunker - # Used to get a chunk of a Qexpr query # @param [Integer] offset the offset for the beginning of the chunk # @param [Integer] limit the maximum number of rows to get in the chunk # @param [Boolean] skip_header whether you should skip the header row in the returned output. Defaults to false # @yieldreturn [Qexpr] a block which, when called, returns the main Qexpr query # @return [Enumerator] an Enumerator, with each item an array for a row - def self.get_chunk_of_query(offset=nil, limit=nil, skip_header=false, &block) - Enumerator.new {|y| + def self.get_chunk_of_query(offset = nil, limit = nil, skip_header = false, &block) + Enumerator.new do |y| + expr = block.call + expr = expr.offset(offset) if offset - expr = block.call() - if offset - expr = expr.offset(offset) - end - - if limit - expr = expr.limit(limit) - end + expr = expr.limit(limit) if limit vecs = Psql.execute_vectors(expr.parse) - if (!skip_header) - y << vecs.first.to_a.map{|k| k.to_s.titleize} + y << vecs.first.to_a.map { |k| k.to_s.titleize } unless skip_header - end - - vecs.drop(1).each{|v| y << v.to_a} - } + vecs.drop(1).each { |v| y << v.to_a } + end end # Get a lazy enumerable getting a query in chunks. block is a block used for creating a query for a new chunk @@ -39,23 +32,23 @@ module QexprQueryChunker # @yieldparam [Boolean] skip_header whether you should skip the header row in the returned output. # @yieldreturn [Enumerator] an Enumerator, with each item an array for a row # @return [Enumerator::Lazy] a lazy enumerator for getting every item in the query - def self.for_export_enumerable(chunk_limit=35000, &block) + def self.for_export_enumerable(chunk_limit = 35_000, &block) Enumerator.new do |y| last_export_length = 0 limit = chunk_limit page = 0 - while page == 0 || last_export_length == limit do + while page == 0 || last_export_length == limit # either we haven't started yet or the last export == limit (since if it didn't we're to the end) page += 1 offset = Qexpr.page_offset(limit, page) export_returned = block.call(offset, limit, page > 1).to_a - #we got the titles too if on_first, let's skip one row - last_export_length = page == 1 ? export_returned.length-1 : export_returned.length + # we got the titles too if on_first, let's skip one row + last_export_length = page == 1 ? export_returned.length - 1 : export_returned.length # efficient? no. Do we care? eh. - export_returned.each {|i| + export_returned.each do |i| y << i - } + end end end.lazy end -end \ No newline at end of file +end diff --git a/lib/query/billing_plans.rb b/lib/query/billing_plans.rb index c9973059..72ffa2ca 100644 --- a/lib/query/billing_plans.rb +++ b/lib/query/billing_plans.rb @@ -1,22 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module BillingPlans - def self.get_percentage_fee(nonprofit_id) - ParamValidation.new({nonprofit_id:nonprofit_id}, {nonprofit_id: {:required => true, :is_integer => true}}) + ParamValidation.new({ nonprofit_id: nonprofit_id }, nonprofit_id: { required: true, is_integer: true }) - unless (Nonprofit.exists?(nonprofit_id)) - raise ParamValidation::ValidationError.new("#{nonprofit_id} does not exist", {:key => :nonprofit_id} ) + unless Nonprofit.exists?(nonprofit_id) + raise ParamValidation::ValidationError.new("#{nonprofit_id} does not exist", key: :nonprofit_id) end - - result = Qx.select("billing_plans.percentage_fee") - .from("billing_plans") - .join("billing_subscriptions bs", "bs.billing_plan_id = billing_plans.id") - .where("bs.nonprofit_id=$id", id: nonprofit_id) - .execute - return result.empty? ? 0 : result.last['percentage_fee'] + result = Qx.select('billing_plans.percentage_fee') + .from('billing_plans') + .join('billing_subscriptions bs', 'bs.billing_plan_id = billing_plans.id') + .where('bs.nonprofit_id=$id', id: nonprofit_id) + .execute + result.empty? ? 0 : result.last['percentage_fee'] end - end diff --git a/lib/query/query_activities.rb b/lib/query/query_activities.rb index d1915b60..994edf3d 100644 --- a/lib/query/query_activities.rb +++ b/lib/query/query_activities.rb @@ -1,13 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module QueryActivities def self.for_timeline(nonprofit_id, supporter_id) - Qx.select( "activities.*") + Qx.select('activities.*') .from(:activities) .where("activities.supporter_id = #{supporter_id.to_i} AND activities.nonprofit_id = #{nonprofit_id.to_i}") .order_by('activities.date DESC') .execute end end - diff --git a/lib/query/query_billing_subscriptions.rb b/lib/query/query_billing_subscriptions.rb index 9962fc12..434b7b57 100644 --- a/lib/query/query_billing_subscriptions.rb +++ b/lib/query/query_billing_subscriptions.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' require 'active_support/core_ext' module QueryBillingSubscriptions - def self.days_left_in_trial(np_id) - sub = Qx.fetch(:billing_subscriptions, {nonprofit_id: np_id}).last + sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last return 0 if sub.nil? - return sub['status'] == 'trialing' ? (((sub['created_at'] + 10.days) - Time.current) / 86400).floor : 0 + + sub['status'] == 'trialing' ? (((sub['created_at'] + 10.days) - Time.current) / 86_400).floor : 0 end def self.plan_tier(np_id) - sub = Qx.fetch(:billing_subscriptions, {nonprofit_id: np_id}).last + sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last return 2 if sub && sub['status'] != 'inactive' - return 0 + + 0 end def self.currently_in_trial?(np_id) - sub = Qx.fetch(:billing_subscriptions, {nonprofit_id: np_id}).last - return sub && sub['status'] == 'trialing' + sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last + sub && sub['status'] == 'trialing' end end - diff --git a/lib/query/query_campaign_gifts.rb b/lib/query/query_campaign_gifts.rb index 6ebf2325..f4be0075 100644 --- a/lib/query/query_campaign_gifts.rb +++ b/lib/query/query_campaign_gifts.rb @@ -1,31 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Query code for both campaign_gift_options and campaign_gifts require 'psql' module QueryCampaignGifts - - - # Create a mapping of: { - # 'total_donations' => Integer, # total donations for gift options - # 'total_one_time' => Integer, # total one-time donations for gift option - # 'total_recurring' => Integer, - # 'name' => String, # name of the gift level - # - # Includes the overall sum as well as the donations without gift options - def self.report_metrics(campaign_id) - - - data = Psql.execute(%Q( + # Create a mapping of: { + # 'total_donations' => Integer, # total donations for gift options + # 'total_one_time' => Integer, # total one-time donations for gift option + # 'total_recurring' => Integer, + # 'name' => String, # name of the gift level + # + # Includes the overall sum as well as the donations without gift options + def self.report_metrics(campaign_id) + data = Psql.execute(%( SELECT campaign_gift_options.name , COUNT(*) AS total_donations , SUM(ds_one_time.amount) AS total_one_time , SUM(ds_recurring.amount) AS total_recurring FROM (#{donations_for_campaign(campaign_id).parse}) AS ds - LEFT OUTER JOIN (#{get_corresponding_payments(campaign_id, %Q(LEFT OUTER JOIN recurring_donations ON recurring_donations.donation_id = donations.id - ), %Q(WHERE recurring_donations.id IS NULL))}) ds_one_time + LEFT OUTER JOIN (#{get_corresponding_payments(campaign_id, %(LEFT OUTER JOIN recurring_donations ON recurring_donations.donation_id = donations.id + ), %(WHERE recurring_donations.id IS NULL))}) ds_one_time ON ds_one_time.id = ds.id - LEFT OUTER JOIN (#{get_corresponding_payments(campaign_id, %Q(INNER JOIN recurring_donations ON recurring_donations.donation_id = donations.id))}) ds_recurring + LEFT OUTER JOIN (#{get_corresponding_payments(campaign_id, %(INNER JOIN recurring_donations ON recurring_donations.donation_id = donations.id))}) ds_recurring ON ds_recurring.id = ds.id LEFT OUTER JOIN campaign_gifts ON campaign_gifts.donation_id=ds.id @@ -35,16 +33,15 @@ module QueryCampaignGifts ORDER BY total_donations DESC )) - return Hamster::Hash[data: data] - end + Hamster::Hash[data: data] + end - def self.donations_for_campaign(campaign_id) - Qx.select('donations.id, donations.amount').from(:donations).where("campaign_id IN ($ids)", {ids:QueryCampaigns.get_campaign_and_children(campaign_id) - }) - end + def self.donations_for_campaign(campaign_id) + Qx.select('donations.id, donations.amount').from(:donations).where('campaign_id IN ($ids)', ids: QueryCampaigns.get_campaign_and_children(campaign_id)) + end - def self.get_corresponding_payments(campaign_id, recurring_clauses, where_clauses="") - %Q(SELECT donations.id, payments.gross_amount AS amount + def self.get_corresponding_payments(campaign_id, recurring_clauses, where_clauses = '') + %(SELECT donations.id, payments.gross_amount AS amount FROM (#{donations_for_campaign(campaign_id).parse}) donations #{recurring_clauses} JOIN LATERAL ( @@ -55,6 +52,5 @@ module QueryCampaignGifts ) payments ON true #{where_clauses} ) - end + end end - diff --git a/lib/query/query_campaign_metrics.rb b/lib/query/query_campaign_metrics.rb index b2cc1529..30b03588 100644 --- a/lib/query/query_campaign_metrics.rb +++ b/lib/query/query_campaign_metrics.rb @@ -1,31 +1,29 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryCampaignMetrics - def self.on_donations(campaign_id) campaign = Campaign.find(campaign_id) result = Psql.execute( - Qexpr.new.select("COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count", - "COALESCE(SUM(payments.gross_amount), 0) AS total_raised") - .from("campaigns") + Qexpr.new.select('COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count', + 'COALESCE(SUM(payments.gross_amount), 0) AS total_raised') + .from('campaigns') .join( - "donations", "donations.campaign_id=campaigns.id" + 'donations', 'donations.campaign_id=campaigns.id' ) - .join_lateral("payments", QueryDonations.get_first_payment_for_donation.parse, true) + .join_lateral('payments', QueryDonations.get_first_payment_for_donation.parse, true) .where("campaigns.id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) - .parse - })") + .parse})") ).last - return { - 'supporters_count' => result['supporters_count'], - 'total_raised'=> result['total_raised'], - 'goal_amount'=> campaign.goal_amount, - 'show_total_count'=> campaign.show_total_count, - 'show_total_raised'=> campaign.show_total_raised + { + 'supporters_count' => result['supporters_count'], + 'total_raised' => result['total_raised'], + 'goal_amount' => campaign.goal_amount, + 'show_total_count' => campaign.show_total_count, + 'show_total_raised' => campaign.show_total_raised } end end - - diff --git a/lib/query/query_campaigns.rb b/lib/query/query_campaigns.rb index ec4eec89..b61775b6 100644 --- a/lib/query/query_campaigns.rb +++ b/lib/query/query_campaigns.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' module QueryCampaigns - def self.featured(limit, gross_more_than) expr = Qexpr.new.select( 'campaigns.name', @@ -11,77 +12,72 @@ module QueryCampaigns Image._url('campaigns', 'main_image', 'normal') + 'AS main_image_url', "concat('/nonprofits/', campaigns.nonprofit_id, '/campaigns/', campaigns.id) AS url" ).from( - Qexpr.new.select("campaigns.*", "SUM(donations.amount) AS gross") - .from("campaigns") - .join("donations", "donations.campaign_id=campaigns.id") - .group_by("campaigns.id"), - "campaigns" + Qexpr.new.select('campaigns.*', 'SUM(donations.amount) AS gross') + .from('campaigns') + .join('donations', 'donations.campaign_id=campaigns.id') + .group_by('campaigns.id'), + 'campaigns' ).where("campaigns.gross > $amount AND campaigns.published='t' AND campaigns.nonprofit_id!=$id", amount: gross_more_than, id: 4182) - .order_by("campaigns.updated_at ASC") - .limit(limit) + .order_by('campaigns.updated_at ASC') + .limit(limit) Psql.execute(expr.parse) end - def self.timeline(campaign_id) - ex = QueryCampaigns.payments_expression(campaign_id, true) - ex.group_by("DATE(payments.date)") - .order_by("DATE(payments.date)") + ex = QueryCampaigns.payments_expression(campaign_id, true) + ex.group_by('DATE(payments.date)') + .order_by('DATE(payments.date)') .execute end - def self.payments_expression(campaign_id, for_timeline) selects = [ - "coalesce(SUM(payments.gross_amount), 0) AS total_cents", - "coalesce(SUM(recurring.gross_amount), 0) AS recurring_cents", - "coalesce(SUM(offsite.gross_amount), 0) AS offsite_cents", - "coalesce(SUM(onetime.gross_amount), 0) AS onetime_cents"] + 'coalesce(SUM(payments.gross_amount), 0) AS total_cents', + 'coalesce(SUM(recurring.gross_amount), 0) AS recurring_cents', + 'coalesce(SUM(offsite.gross_amount), 0) AS offsite_cents', + 'coalesce(SUM(onetime.gross_amount), 0) AS onetime_cents' + ] - for_timeline ? - selects.push("MAX(DATE(payments.date)) AS date") : - selects.push("coalesce(count(supporters.id), 0) AS supporters_count") + for_timeline ? + selects.push('MAX(DATE(payments.date)) AS date') : + selects.push('coalesce(count(supporters.id), 0) AS supporters_count') - return Qx.select(*selects) - .from("payments") + Qx.select(*selects) + .from('payments') .left_join( - ["donations", "payments.donation_id=donations.id"], - ["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"], - ["payments AS offsite", "offsite.id=payments.id AND offsite.kind='OffsitePayment'"], - ["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"]) + ['donations', 'payments.donation_id=donations.id'], + ['payments AS onetime', "onetime.id=payments.id AND onetime.kind='Donation'"], + ['payments AS offsite', "offsite.id=payments.id AND offsite.kind='OffsitePayment'"], + ['payments AS recurring', "recurring.id=payments.id AND recurring.kind='RecurringDonation'"] + ) .where("donations.campaign_id IN (#{QueryCampaigns.get_campaign_and_children(campaign_id).parse})") end - def self.totals(campaign_id) - ex = QueryCampaigns.payments_expression(campaign_id, false) - ex.add_left_join(["supporters", "donations.supporter_id=supporters.id"]) + ex = QueryCampaigns.payments_expression(campaign_id, false) + ex.add_left_join(['supporters', 'donations.supporter_id=supporters.id']) .execute.first end - def self.name_and_id(npo_id) - np = Nonprofit.find(npo_id) campaigns = np.campaigns.not_deleted.includes(:profile).order('campaigns.name ASC') output = campaigns.map do |i| { - 'name' => i.name, - 'id' => i.id, - 'isChildCampaign' => i.child_campaign?, - 'creator' => i.profile&.name || "user ##{i.profile.id}" + 'name' => i.name, + 'id' => i.id, + 'isChildCampaign' => i.child_campaign?, + 'creator' => i.profile&.name || "user ##{i.profile.id}" } end output end def self.get_campaign_and_children(campaign_id) - Qx.select("id") - .from('campaigns') - .where("campaigns.id = $id OR campaigns.parent_campaign_id=$id", - id: campaign_id) + Qx.select('id') + .from('campaigns') + .where('campaigns.id = $id OR campaigns.parent_campaign_id=$id', + id: campaign_id) end - - end diff --git a/lib/query/query_charges.rb b/lib/query/query_charges.rb index 0f6c6019..832188db 100644 --- a/lib/query/query_charges.rb +++ b/lib/query/query_charges.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' module QueryCharges diff --git a/lib/query/query_custom_fields.rb b/lib/query/query_custom_fields.rb index 304c9a35..fec50508 100644 --- a/lib/query/query_custom_fields.rb +++ b/lib/query/query_custom_fields.rb @@ -1,20 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' module QueryCustomFields - - # Find all duplicate custom field joins on supporters # Returns an array of groups of duplicate custom_field_join_ids def self.find_dupes(np_id) - Qx.select("ARRAY_AGG(custom_field_joins.id)") + Qx.select('ARRAY_AGG(custom_field_joins.id)') .from(:custom_field_joins) - .join(:custom_field_masters, "custom_field_masters.id=custom_field_joins.custom_field_master_id") - .where("custom_field_masters.nonprofit_id=$id", id: np_id) - .group_by("custom_field_joins.custom_field_master_id", "custom_field_joins.value", "custom_field_joins.supporter_id") - .having("COUNT(custom_field_joins.id) > 1") + .join(:custom_field_masters, 'custom_field_masters.id=custom_field_joins.custom_field_master_id') + .where('custom_field_masters.nonprofit_id=$id', id: np_id) + .group_by('custom_field_joins.custom_field_master_id', 'custom_field_joins.value', 'custom_field_joins.supporter_id') + .having('COUNT(custom_field_joins.id) > 1') .execute(format: 'csv')[1..-1] end - end diff --git a/lib/query/query_donations.rb b/lib/query/query_donations.rb index 5c4a4317..9c7d106c 100644 --- a/lib/query/query_donations.rb +++ b/lib/query/query_donations.rb @@ -1,77 +1,77 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'query/query_supporters' module QueryDonations - # Export all donation data for a given campaign - def self.campaign_export(campaign_id) + def self.campaign_export(campaign_id) Psql.execute_vectors( Qexpr.new.select([ 'donations.created_at', - '(payments.gross_amount/100.00)::money::text AS amount', - "COUNT(recurring_donations.id) > 0 AS recurring", - "STRING_AGG(campaign_gift_options.name, ',') AS campaign_gift_names" + '(payments.gross_amount/100.00)::money::text AS amount', + 'COUNT(recurring_donations.id) > 0 AS recurring', + "STRING_AGG(campaign_gift_options.name, ',') AS campaign_gift_names" ].concat(QuerySupporters.supporter_export_selections) .concat([ - "supporters.id AS \"Supporter ID\"", - ]).concat([ - "coalesce(donations.designation, 'None') AS designation", - "#{QueryPayments.get_dedication_or_empty('type')}::text AS \"Dedication Type\"", - "#{QueryPayments.get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", - "#{QueryPayments.get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", - "#{QueryPayments.get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", - "#{QueryPayments.get_dedication_or_empty('contact', "phone")}::text AS \"Dedicated To: Phone\"", - "#{QueryPayments.get_dedication_or_empty( "contact", "address")}::text AS \"Dedicated To: Address\"", - "#{QueryPayments.get_dedication_or_empty( "note")}::text AS \"Dedicated To: Note\"", - "donations.campaign_id AS \"Campaign Id\"", - "users.email AS \"Campaign Creator Email\"" - ]) - ).from(:donations) - .join(:supporters, "supporters.id=donations.supporter_id") - .left_outer_join(:campaign_gifts, "campaign_gifts.donation_id=donations.id") - .left_outer_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id") - .left_outer_join(:recurring_donations, "recurring_donations.donation_id = donations.id") + 'supporters.id AS "Supporter ID"' + ]).concat([ + "coalesce(donations.designation, 'None') AS designation", + "#{QueryPayments.get_dedication_or_empty('type')}::text AS \"Dedication Type\"", + "#{QueryPayments.get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", + "#{QueryPayments.get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", + "#{QueryPayments.get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", + "#{QueryPayments.get_dedication_or_empty('contact', 'phone')}::text AS \"Dedicated To: Phone\"", + "#{QueryPayments.get_dedication_or_empty('contact', 'address')}::text AS \"Dedicated To: Address\"", + "#{QueryPayments.get_dedication_or_empty('note')}::text AS \"Dedicated To: Note\"", + 'donations.campaign_id AS "Campaign Id"', + 'users.email AS "Campaign Creator Email"' + ])).from(:donations) + .join(:supporters, 'supporters.id=donations.supporter_id') + .left_outer_join(:campaign_gifts, 'campaign_gifts.donation_id=donations.id') + .left_outer_join(:campaign_gift_options, 'campaign_gift_options.id=campaign_gifts.campaign_gift_option_id') + .left_outer_join(:recurring_donations, 'recurring_donations.donation_id = donations.id') .join_lateral(:payments, get_first_payment_for_donation.parse, true) .join(Qx.select('id, profile_id').from('campaigns') .where("id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) .parse})").as('campaigns').parse, - 'donations.campaign_id=campaigns.id') + 'donations.campaign_id=campaigns.id') .join(Qx.select('users.id, profiles.id AS profiles_id, users.email') .from('users') .add_join('profiles', 'profiles.user_id = users.id') - .as("users").parse, "users.profiles_id=campaigns.profile_id") - .group_by("donations.id", "supporters.id", "payments.id", "payments.gross_amount", "users.email") - .order_by("donations.date") + .as('users').parse, 'users.profiles_id=campaigns.profile_id') + .group_by('donations.id', 'supporters.id', 'payments.id', 'payments.gross_amount', 'users.email') + .order_by('donations.date') ) - end + end def self.for_campaign_activities(id) QueryDonations.activities_expression(['donations.recurring']) - .where("donations.campaign_id IN (#{QueryCampaigns + .where("donations.campaign_id IN (#{QueryCampaigns .get_campaign_and_children(id) .parse})") - .execute + .execute end def self.activities_expression(additional_selects) selects = [" - CASE + CASE WHEN donations.anonymous='t' - OR supporters.anonymous='t' - OR supporters.name='' - OR supporters.name IS NULL - THEN 'A supporter' - ELSE supporters.name - END AS supporter_name", - "(donations.amount / 100.0)::money::text as amount", - "donations.date"] + (additional_selects ? additional_selects : []) + OR supporters.anonymous='t' + OR supporters.name='' + OR supporters.name IS NULL + THEN 'A supporter' + ELSE supporters.name + END AS supporter_name", + '(donations.amount / 100.0)::money::text as amount', + 'donations.date'] + (additional_selects || []) - return Qx.select(selects.join(',')) + Qx.select(selects.join(',')) .from(:donations) .left_join(:supporters, 'donations.supporter_id=supporters.id') - .order_by("donations.date desc") + .order_by('donations.date desc') .limit(15) end @@ -79,21 +79,20 @@ module QueryDonations # !!! Note this returns the PAYMENT_IDS for each offsite donation def self.dupe_offsite_donations(np_id) payment_ids = Psql.execute_vectors( - Qexpr.new.select("ARRAY_AGG(payments.id) AS ids") - .from("donations") - .join(:offsite_payments, "offsite_payments.donation_id=donations.id") - .join(:payments, "payments.donation_id=donations.id") - .where("donations.nonprofit_id=$id", id: np_id) - .group_by("donations.supporter_id", "donations.amount", "donations.date") - .having("COUNT(donations.id) > 1") + Qexpr.new.select('ARRAY_AGG(payments.id) AS ids') + .from('donations') + .join(:offsite_payments, 'offsite_payments.donation_id=donations.id') + .join(:payments, 'payments.donation_id=donations.id') + .where('donations.nonprofit_id=$id', id: np_id) + .group_by('donations.supporter_id', 'donations.amount', 'donations.date') + .having('COUNT(donations.id) > 1') )[1..-1].map(&:flatten) end - def self.get_first_payment_for_donation(table_selector='donations') + def self.get_first_payment_for_donation(table_selector = 'donations') Qx.select('payments.id, payments.gross_amount').from(:payments) - .where("payments.donation_id = #{table_selector}.id") - .order_by('payments.created_at ASC') - .limit(1) + .where("payments.donation_id = #{table_selector}.id") + .order_by('payments.created_at ASC') + .limit(1) end - end diff --git a/lib/query/query_email_settings.rb b/lib/query/query_email_settings.rb index 2d1c4171..b2f6e639 100644 --- a/lib/query/query_email_settings.rb +++ b/lib/query/query_email_settings.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryEmailSettings - - Settings = ['notify_payments', 'notify_campaigns', 'notify_events', 'notify_payouts', 'notify_recurring_donations'] + Settings = %w[notify_payments notify_campaigns notify_events notify_payouts notify_recurring_donations].freeze def self.fetch(np_id, user_id) - es = Psql.execute(%Q( + es = Psql.execute(%( SELECT * FROM email_settings WHERE nonprofit_id=#{Qexpr.quote(np_id.to_i)} @@ -13,14 +14,14 @@ module QueryEmailSettings # If the user's event_settings table does not exist, return a hash with all settings true if es.nil? - es = Psql.execute(%Q( + es = Psql.execute(%( SELECT column_name FROM information_schema.columns WHERE table_name='email_settings' - )).map{|h| h['column_name']} - .reject{|name| ['id', 'nonprofit_id', 'user_id'].include?(name)} - .reduce({}){|h, name| h[name] = true; h} + )).map { |h| h['column_name'] } + .reject { |name| %w[id nonprofit_id user_id].include?(name) } + .each_with_object({}) { |name, h| h[name] = true; } end - return es + es end end diff --git a/lib/query/query_event_discounts.rb b/lib/query/query_event_discounts.rb index 1ab648a7..b0bb4d87 100644 --- a/lib/query/query_event_discounts.rb +++ b/lib/query/query_event_discounts.rb @@ -1,15 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryEventDiscounts - def self.with_event_ids(event_ids) return [] if event_ids.empty? - x = Psql.execute( - Qexpr.new.select("name", "id", "percent", "code", "created_at") - .from("event_discounts") - .where("event_discounts.event_id IN ($ids)", ids: event_ids) - .order_by("created_at DESC"), - ).map{|h| HashWithIndifferentAccess.new(h)} + x = Psql.execute( + Qexpr.new.select('name', 'id', 'percent', 'code', 'created_at') + .from('event_discounts') + .where('event_discounts.event_id IN ($ids)', ids: event_ids) + .order_by('created_at DESC') + ).map { |h| HashWithIndifferentAccess.new(h) } end - end diff --git a/lib/query/query_event_metrics.rb b/lib/query/query_event_metrics.rb index 5d555685..21fdb0be 100644 --- a/lib/query/query_event_metrics.rb +++ b/lib/query/query_event_metrics.rb @@ -1,47 +1,49 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryEventMetrics - - def self.expression(additional_selects=[]) + def self.expression(additional_selects = []) selects = [ - "coalesce(tickets.total, 0) AS total_attendees", - "coalesce(tickets.checked_in_count, 0) AS checked_in_count", - "coalesce(ticket_payments.total_paid, 0) AS tickets_total_paid", - "coalesce(donations.payment_total, 0) AS donations_total_paid", - "coalesce(ticket_payments.total_paid, 0) + coalesce(donations.payment_total, 0) AS total_paid" + 'coalesce(tickets.total, 0) AS total_attendees', + 'coalesce(tickets.checked_in_count, 0) AS checked_in_count', + 'coalesce(ticket_payments.total_paid, 0) AS tickets_total_paid', + 'coalesce(donations.payment_total, 0) AS donations_total_paid', + 'coalesce(ticket_payments.total_paid, 0) + coalesce(donations.payment_total, 0) AS total_paid' ] - tickets_sub = Qx.select("event_id", "SUM(quantity) AS total", "SUM(tickets.checked_in::int) AS checked_in_count") - .from("tickets") - .group_by("event_id") - .as("tickets") - - ticket_payments_subquery = Qx.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + tickets_sub = Qx.select('event_id', 'SUM(quantity) AS total', 'SUM(tickets.checked_in::int) AS checked_in_count') + .from('tickets') + .group_by('event_id') + .as('tickets') - ticket_payments_sub = Qx.select("SUM(payments.gross_amount) AS total_paid", "tickets.event_id") - .from(:payments) - .join(ticket_payments_subquery, "payments.id=tickets.payment_id") - .group_by("tickets.event_id") - .as("ticket_payments") + ticket_payments_subquery = Qx.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') - donations_sub = Qx.select("event_id", "SUM(payments.gross_amount) as payment_total") - .from("donations") - .group_by("event_id") - .left_join("payments", "donations.id=payments.donation_id") - .as("donations") + ticket_payments_sub = Qx.select('SUM(payments.gross_amount) AS total_paid', 'tickets.event_id') + .from(:payments) + .join(ticket_payments_subquery, 'payments.id=tickets.payment_id') + .group_by('tickets.event_id') + .as('ticket_payments') + + donations_sub = Qx.select('event_id', 'SUM(payments.gross_amount) as payment_total') + .from('donations') + .group_by('event_id') + .left_join('payments', 'donations.id=payments.donation_id') + .as('donations') selects = selects.concat(additional_selects) - return Qx.select(*selects) - .from("events") - .left_join( - [tickets_sub, "tickets.event_id = events.id"], - [donations_sub, "donations.event_id = events.id"], - [ticket_payments_sub, "ticket_payments.event_id=events.id"] + Qx.select(*selects) + .from('events') + .left_join( + [tickets_sub, 'tickets.event_id = events.id'], + [donations_sub, 'donations.event_id = events.id'], + [ticket_payments_sub, 'ticket_payments.event_id=events.id'] ) end def self.with_event_ids(event_ids) return [] if event_ids.empty? - QueryEventMetrics.expression().where("events.id in ($ids)", ids: event_ids).execute + + QueryEventMetrics.expression.where('events.id in ($ids)', ids: event_ids).execute end def self.for_listings(id_type, id, params) @@ -61,29 +63,25 @@ module QueryEventMetrics exp = QueryEventMetrics.expression(selects) if id_type == 'profile' - exp = exp.and_where(["events.profile_id = $id", id: id]) + exp = exp.and_where(['events.profile_id = $id', id: id]) end if id_type == 'nonprofit' - exp = exp.and_where(["events.nonprofit_id = $id", id: id]) + exp = exp.and_where(['events.nonprofit_id = $id', id: id]) end if params['active'].present? exp = exp - .and_where(['events.end_datetime >= $date', date: Time.now]) - .and_where(["events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE"]) + .and_where(['events.end_datetime >= $date', date: Time.now]) + .and_where(['events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE']) end if params['past'].present? exp = exp - .and_where(['events.end_datetime < $date', date: Time.now]) - .and_where(["events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE"]) + .and_where(['events.end_datetime < $date', date: Time.now]) + .and_where(['events.published = TRUE AND coalesce(events.deleted, FALSE) = FALSE']) end if params['unpublished'].present? - exp = exp.and_where(["coalesce(events.published, FALSE) = FALSE AND coalesce(events.deleted, FALSE) = FALSE"]) + exp = exp.and_where(['coalesce(events.published, FALSE) = FALSE AND coalesce(events.deleted, FALSE) = FALSE']) end - if params['deleted'].present? - exp = exp.and_where(["events.deleted = TRUE"]) - end - return exp.execute + exp = exp.and_where(['events.deleted = TRUE']) if params['deleted'].present? + exp.execute end - end - diff --git a/lib/query/query_event_organizer.rb b/lib/query/query_event_organizer.rb index c70507b1..2bac4d1b 100644 --- a/lib/query/query_event_organizer.rb +++ b/lib/query/query_event_organizer.rb @@ -1,15 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryEventOrganizer - def self.with_event(event_id) + def self.with_event(event_id) Qx.select( - "coalesce(profiles.name, nonprofits.name) AS name", - "coalesce(users.email, nonprofits.email) AS email" - ) + 'coalesce(profiles.name, nonprofits.name) AS name', + 'coalesce(users.email, nonprofits.email) AS email' + ) .from(:events) - .left_join(:profiles, "profiles.id=events.profile_id") - .add_left_join(:users, "profiles.user_id=users.id") - .add_join(:nonprofits, "events.nonprofit_id=nonprofits.id") - .where("events.id=$id", id: event_id) + .left_join(:profiles, 'profiles.id=events.profile_id') + .add_left_join(:users, 'profiles.user_id=users.id') + .add_join(:nonprofits, 'events.nonprofit_id=nonprofits.id') + .where('events.id=$id', id: event_id) .execute.first - end + end end diff --git a/lib/query/query_events.rb b/lib/query/query_events.rb index 252236c7..37a3af5a 100644 --- a/lib/query/query_events.rb +++ b/lib/query/query_events.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' @@ -5,13 +7,13 @@ module QueryEvents def self.name_and_id(npo_id) Psql.execute( Qexpr.new.select( - "events.name", - "events.id") - .from("events") - .where("events.nonprofit_id=$id", id: npo_id) + 'events.name', + 'events.id' + ) + .from('events') + .where('events.nonprofit_id=$id', id: npo_id) .where("events.deleted='f' OR events.deleted IS NULL") - .order_by("events.name ASC") + .order_by('events.name ASC') ) end - end diff --git a/lib/query/query_full_contact_infos.rb b/lib/query/query_full_contact_infos.rb index dc288246..e8c3f134 100644 --- a/lib/query/query_full_contact_infos.rb +++ b/lib/query/query_full_contact_infos.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' module QueryFullContactInfos - def self.fetch_associated_tables(fc_info_id) - photo = Psql.execute( Qexpr.new.from(:full_contact_photos).select('url').where("full_contact_info_id = $id", id: fc_info_id).where("is_primary")) - orgs = Psql.execute( Qexpr.new.from(:full_contact_orgs).select('current', 'name', 'title', 'start_date', 'end_date').where("full_contact_info_id = $id", id: fc_info_id).order_by('start_date DESC NULLS LAST')) - topics = Psql.execute( Qexpr.new.from(:full_contact_topics).select('value').where("full_contact_info_id = $id", id: fc_info_id).order_by('value ASC')) - profiles = Psql.execute( Qexpr.new.from(:full_contact_social_profiles).select('type_id', 'followers', 'url').where("full_contact_info_id = $id", id: fc_info_id).order_by('type_id ASC')) - return { + photo = Psql.execute(Qexpr.new.from(:full_contact_photos).select('url').where('full_contact_info_id = $id', id: fc_info_id).where('is_primary')) + orgs = Psql.execute(Qexpr.new.from(:full_contact_orgs).select('current', 'name', 'title', 'start_date', 'end_date').where('full_contact_info_id = $id', id: fc_info_id).order_by('start_date DESC NULLS LAST')) + topics = Psql.execute(Qexpr.new.from(:full_contact_topics).select('value').where('full_contact_info_id = $id', id: fc_info_id).order_by('value ASC')) + profiles = Psql.execute(Qexpr.new.from(:full_contact_social_profiles).select('type_id', 'followers', 'url').where('full_contact_info_id = $id', id: fc_info_id).order_by('type_id ASC')) + { photo: photo, topics: topics, orgs: orgs, diff --git a/lib/query/query_nonprofit_keys.rb b/lib/query/query_nonprofit_keys.rb index a3abd041..3e0c9bef 100644 --- a/lib/query/query_nonprofit_keys.rb +++ b/lib/query/query_nonprofit_keys.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module QueryNonprofitKeys - def self.get_key(npo_id, key_name) query = Qx.select(key_name) - .from(:nonprofit_keys) - .where({'nonprofit_id' => npo_id}) - .execute - raise ActiveRecord::RecordNotFound.new("Nonprofit key does not exist: #{key_name}") if query.empty? - Cypher.decrypt(JSON.parse query.first[key_name]) - end + .from(:nonprofit_keys) + .where('nonprofit_id' => npo_id) + .execute + raise ActiveRecord::RecordNotFound, "Nonprofit key does not exist: #{key_name}" if query.empty? + Cypher.decrypt(JSON.parse(query.first[key_name])) + end end diff --git a/lib/query/query_nonprofits.rb b/lib/query/query_nonprofits.rb index bd8b069c..7e1e4a39 100644 --- a/lib/query/query_nonprofits.rb +++ b/lib/query/query_nonprofits.rb @@ -1,26 +1,27 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' require 'psql' module QueryNonprofits - def self.all_that_need_payouts Psql.execute_vectors( Qexpr.new.select( - "nonprofits.id", - "nonprofits.stripe_account_id", + 'nonprofits.id', + 'nonprofits.stripe_account_id', "'support@commitchange.com' AS email", "'192.168.0.1' AS user_ip", - "bank_accounts.name" + 'bank_accounts.name' ).from(:nonprofits) .where("nonprofits.verification_status='verified'") - .join(:bank_accounts, "bank_accounts.nonprofit_id=nonprofits.id") + .join(:bank_accounts, 'bank_accounts.nonprofit_id=nonprofits.id') .where("bank_accounts.pending_verification='f'") .join( - Qexpr.new.select("nonprofit_id") - .from(:charges).group_by("nonprofit_id") - .where("status='available'").as("charges"), - "charges.nonprofit_id=nonprofits.id" + Qexpr.new.select('nonprofit_id') + .from(:charges).group_by('nonprofit_id') + .where("status='available'").as('charges'), + 'charges.nonprofit_id=nonprofits.id' ) )[1..-1] end @@ -28,18 +29,16 @@ module QueryNonprofits def self.by_search_string(string) results = Psql.execute_vectors( Qexpr.new.select( - "nonprofits.id", - "nonprofits.name" + 'nonprofits.id', + 'nonprofits.name' ).from(:nonprofits) - .where("lower(nonprofits.name) LIKE lower($search)", search: "%#{string}%") + .where('lower(nonprofits.name) LIKE lower($search)', search: "%#{string}%") .where("nonprofits.published='t'") - .order_by("nonprofits.name ASC") + .order_by('nonprofits.name ASC') .limit(10) )[1..-1] - if results - results = results.map {|id, name| {id: id, name: name}} - end - return results + results = results.map { |id, name| { id: id, name: name } } if results + results end def self.for_admin(params) @@ -52,66 +51,67 @@ module QueryNonprofits 'nonprofits.verification_status', 'nonprofits.vetted', 'nonprofits.stripe_account_id', - 'coalesce(events.count, 0) AS events_count', - 'coalesce(campaigns.count, 0) AS campaigns_count', + 'coalesce(events.count, 0) AS events_count', + 'coalesce(campaigns.count, 0) AS campaigns_count', 'billing_plans.percentage_fee', 'cards.stripe_customer_id', 'charges.total_processed', 'charges.total_fees' ).from(:nonprofits) - .add_left_join(:cards, "cards.holder_id=nonprofits.id AND cards.holder_type='Nonprofit'") - .add_left_join(:billing_subscriptions, "billing_subscriptions.nonprofit_id=nonprofits.id") - .add_left_join(:billing_plans, "billing_subscriptions.billing_plan_id=billing_plans.id") - .add_left_join( - Qx.select( - "((SUM(coalesce(fee, 0)) * .978) / 100)::money::text AS total_fees", - "(SUM(coalesce(amount, 0)) / 100)::money::text AS total_processed", - "nonprofit_id") - .from(:charges) - .where("status != 'failed'") - .and_where("created_at::date >= '2017-03-15'") - .group_by("nonprofit_id") - .as("charges"), - "charges.nonprofit_id=nonprofits.id" - ) - .add_left_join( - Qx.select("COUNT(id)", "nonprofit_id") - .from(:events) - .group_by("nonprofit_id") - .as("events"), - "events.nonprofit_id=nonprofits.id" - ) - .add_left_join( - Qx.select("COUNT(id)", "nonprofit_id") - .from(:campaigns) - .group_by("nonprofit_id") - .as("campaigns"), - "campaigns.nonprofit_id=nonprofits.id" - ) - .paginate(params[:page].to_i, params[:page_length].to_i) - .order_by('nonprofits.created_at DESC') + .add_left_join(:cards, "cards.holder_id=nonprofits.id AND cards.holder_type='Nonprofit'") + .add_left_join(:billing_subscriptions, 'billing_subscriptions.nonprofit_id=nonprofits.id') + .add_left_join(:billing_plans, 'billing_subscriptions.billing_plan_id=billing_plans.id') + .add_left_join( + Qx.select( + '((SUM(coalesce(fee, 0)) * .978) / 100)::money::text AS total_fees', + '(SUM(coalesce(amount, 0)) / 100)::money::text AS total_processed', + 'nonprofit_id' + ) + .from(:charges) + .where("status != 'failed'") + .and_where("created_at::date >= '2017-03-15'") + .group_by('nonprofit_id') + .as('charges'), + 'charges.nonprofit_id=nonprofits.id' + ) + .add_left_join( + Qx.select('COUNT(id)', 'nonprofit_id') + .from(:events) + .group_by('nonprofit_id') + .as('events'), + 'events.nonprofit_id=nonprofits.id' + ) + .add_left_join( + Qx.select('COUNT(id)', 'nonprofit_id') + .from(:campaigns) + .group_by('nonprofit_id') + .as('campaigns'), + 'campaigns.nonprofit_id=nonprofits.id' + ) + .paginate(params[:page].to_i, params[:page_length].to_i) + .order_by('nonprofits.created_at DESC') - if params[:search].present? - expr = expr.where(%Q( + if params[:search].present? + expr = expr.where(%( nonprofits.name ILIKE $search OR nonprofits.email ILIKE $search OR nonprofits.city ILIKE $search ), search: '%' + params[:search] + '%') - end + end - return expr.execute + expr.execute end - def self.find_nonprofits_with_no_payments() + def self.find_nonprofits_with_no_payments Nonprofit.includes(:payments).where('payments.nonprofit_id IS NULL') end def self.find_nonprofits_with_payments_in_last_n_days(days) - Payment.where("date >= ?", Time.now - days.days).pluck('nonprofit_id').to_a.uniq + Payment.where('date >= ?', Time.now - days.days).pluck('nonprofit_id').to_a.uniq end def self.find_nonprofits_with_payments_but_not_in_last_n_days(days) recent_nonprofits = find_nonprofits_with_payments_in_last_n_days(days) - Payment.where("date < ?", Time.now - days.days).pluck('nonprofit_id').to_a.uniq.select{|i| !recent_nonprofits.include?(i)} + Payment.where('date < ?', Time.now - days.days).pluck('nonprofit_id').to_a.uniq.reject { |i| recent_nonprofits.include?(i) } end end diff --git a/lib/query/query_payments.rb b/lib/query/query_payments.rb index f535e791..203251d3 100644 --- a/lib/query/query_payments.rb +++ b/lib/query/query_payments.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' require 'psql' @@ -6,8 +8,6 @@ require 'query/query_supporters' require 'active_support/core_ext' module QueryPayments - - # Fetch all payments connected to available charges, undisbursed refunds or lost disputes # Ids For Payouts collects all payments where: # *they have a connected charge, refund or dispute (CRD), i.e. the CRD's payment_id is not NULL and represents a record in payments @@ -20,38 +20,39 @@ module QueryPayments # * For refunds and disputes, the gross_amount should be negative since we're decreasing the nonprofit's balance # # In effect, we're getting the list of payments which haven't been paid out in a some fashion. This is not a great design but it works mostly. - def self.ids_for_payout(npo_id, options={}) + def self.ids_for_payout(npo_id, options = {}) end_of_day = (Time.current + 1.day).beginning_of_day Qx.select('DISTINCT payments.id') - .from(:payments) - .left_join(:charges, 'charges.payment_id=payments.id') - .add_left_join(:refunds, 'refunds.payment_id=payments.id') - .add_left_join(:disputes, 'disputes.payment_id=payments.id') - .where('payments.nonprofit_id=$id', id: npo_id) - .and_where("refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL") - .and_where(%Q( + .from(:payments) + .left_join(:charges, 'charges.payment_id=payments.id') + .add_left_join(:refunds, 'refunds.payment_id=payments.id') + .add_left_join(:disputes, 'disputes.payment_id=payments.id') + .where('payments.nonprofit_id=$id', id: npo_id) + .and_where('refunds.payment_id IS NOT NULL OR charges.payment_id IS NOT NULL OR disputes.payment_id IS NOT NULL') + .and_where(%( ((refunds.payment_id IS NOT NULL AND refunds.disbursed IS NULL) OR refunds.disbursed='f') OR (charges.status='available') OR (disputes.status='lost') )) - .and_where("payments.date <= $date", date: options[:date] || end_of_day) - .execute.map{|h| h['id']} + .and_where('payments.date <= $date', date: options[:date] || end_of_day) + .execute.map { |h| h['id'] } end # the amount to payout calculates the total payout based upon the payments it's provided, likely provided from ids_to_payout def self.get_payout_totals(payment_ids) - return {'gross_amount' => 0, 'fee_total' => 0, 'net_amount' => 0} if payment_ids.empty? + return { 'gross_amount' => 0, 'fee_total' => 0, 'net_amount' => 0 } if payment_ids.empty? + Qx.select( 'SUM(payments.gross_amount) AS gross_amount', 'SUM(payments.fee_total) AS fee_total', 'SUM(payments.net_amount) AS net_amount', - 'COUNT(payments.*) AS count') + 'COUNT(payments.*) AS count' + ) .from(:payments) - .where("payments.id IN ($ids)", ids: payment_ids) + .where('payments.id IN ($ids)', ids: payment_ids) .execute.first end - def self.nonprofit_balances(npo_id) Psql.execute( Qexpr.new.select( @@ -60,17 +61,17 @@ module QueryPayments 'COUNT(available) AS count_available', 'COUNT(pending) AS count_pending', 'COUNT(refunds) AS count_refunds', - 'COUNT(disputes) AS count_disputes') + 'COUNT(disputes) AS count_disputes' + ) .from(:payments) .left_outer_join('refunds', "refunds.payment_id=payments.id AND (refunds.disbursed='f' OR refunds.disbursed IS NULL)") - .left_outer_join("charges available", "available.status='available' AND available.payment_id=payments.id") - .left_outer_join("charges pending", "pending.status='pending' AND pending.payment_id=payments.id") - .left_outer_join("disputes", "disputes.status='lost' AND disputes.payment_id=payments.id") - .where("payments.nonprofit_id=$id", id: npo_id) + .left_outer_join('charges available', "available.status='available' AND available.payment_id=payments.id") + .left_outer_join('charges pending', "pending.status='pending' AND pending.payment_id=payments.id") + .left_outer_join('disputes', "disputes.status='lost' AND disputes.payment_id=payments.id") + .where('payments.nonprofit_id=$id', id: npo_id) ).first end - def self.full_search(npo_id, query) limit = 30 offset = Qexpr.page_offset(limit, query[:page]) @@ -87,84 +88,79 @@ module QueryPayments payments = Psql.execute(expr.limit(limit).offset(offset).parse) totals_query = expr - .remove(:select) - .remove(:order_by) - .select( - 'COALESCE(COUNT(payments.id), 0) AS count', - 'COALESCE((SUM(payments.gross_amount) / 100.0), 0)::money::text AS amount') + .remove(:select) + .remove(:order_by) + .select( + 'COALESCE(COUNT(payments.id), 0) AS count', + 'COALESCE((SUM(payments.gross_amount) / 100.0), 0)::money::text AS amount' + ) totals = Psql.execute(totals_query).first - return { + { data: payments, total_count: totals['count'], total_amount: totals['amount'], remaining: Qexpr.remaining_count(totals['count'], limit, query[:page]) } - end - # we must provide payments.*, supporters.*, donations.*, associated event_id, associated campaign_id def self.full_search_expr(npo_id, query) expr = Qexpr.new.from('payments') - .left_outer_join('supporters', "supporters.id=payments.supporter_id") - .left_outer_join('donations', 'donations.id=payments.donation_id' ) - .join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", 'payments.id = filtered_payments.id') - .order_by('payments.date DESC') + .left_outer_join('supporters', 'supporters.id=payments.supporter_id') + .left_outer_join('donations', 'donations.id=payments.donation_id') + .join("(#{select_to_filter_search(npo_id, query)}) AS \"filtered_payments\"", 'payments.id = filtered_payments.id') + .order_by('payments.date DESC') - if ['asc', 'desc'].include? query[:sort_amount] + if %w[asc desc].include? query[:sort_amount] expr = expr.order_by("payments.gross_amount #{query[:sort_amount]}") end - if ['asc', 'desc'].include? query[:sort_date] + if %w[asc desc].include? query[:sort_date] expr = expr.order_by("payments.date #{query[:sort_date]}") end - if ['asc', 'desc'].include? query[:sort_name] + if %w[asc desc].include? query[:sort_name] expr = expr.order_by("coalesce(NULLIF(supporters.name, ''), NULLIF(supporters.email, '')) #{query[:sort_name]}") end - if ['asc', 'desc'].include? query[:sort_type] + if %w[asc desc].include? query[:sort_type] expr = expr.order_by("payments.kind #{query[:sort_type]}") end - if ['asc', 'desc'].include? query[:sort_towards] + if %w[asc desc].include? query[:sort_towards] expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") end - return expr + expr end # perform the search but only get the relevant payment_ids def self.select_to_filter_search(npo_id, query) - inner_donation_search = Qexpr.new.select('donations.*').from('donations') - if (query[:event_id].present?) + if query[:event_id].present? inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) end - if (query[:campaign_id].present?) + if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id]) end expr = Qexpr.new.select('payments.id').from('payments') - .left_outer_join('supporters', "supporters.id=payments.supporter_id") - .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments.donation_id' ) - .where('payments.nonprofit_id=$id', id: npo_id.to_i) + .left_outer_join('supporters', 'supporters.id=payments.supporter_id') + .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments.donation_id') + .where('payments.nonprofit_id=$id', id: npo_id.to_i) - - if query[:search].present? - expr = SearchVector.query(query[:search], expr) - end - if ['asc', 'desc'].include? query[:sort_amount] + expr = SearchVector.query(query[:search], expr) if query[:search].present? + if %w[asc desc].include? query[:sort_amount] expr = expr.order_by("payments.gross_amount #{query[:sort_amount]}") end - if ['asc', 'desc'].include? query[:sort_date] + if %w[asc desc].include? query[:sort_date] expr = expr.order_by("payments.date #{query[:sort_date]}") end - if ['asc', 'desc'].include? query[:sort_name] + if %w[asc desc].include? query[:sort_name] expr = expr.order_by("coalesce(NULLIF(supporters.name, ''), NULLIF(supporters.email, '')) #{query[:sort_name]}") end - if ['asc', 'desc'].include? query[:sort_type] + if %w[asc desc].include? query[:sort_type] expr = expr.order_by("payments.kind #{query[:sort_type]}") end - if ['asc', 'desc'].include? query[:sort_towards] + if %w[asc desc].include? query[:sort_towards] expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") end if query[:after_date].present? @@ -183,10 +179,10 @@ module QueryPayments expr = expr.where("to_char(payments.date, 'YYYY')=$year", year: query[:year]) end if query[:designation].present? - expr = expr.where("donations.designation @@ $s", s: "#{query[:designation]}") + expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s) end if query[:dedication].present? - expr = expr.where("donations.dedication @@ $s", s: "#{query[:dedication]}") + expr = expr.where('donations.dedication @@ $s', s: (query[:dedication]).to_s) end if query[:donation_type].present? expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) @@ -194,66 +190,61 @@ module QueryPayments if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string expr = expr - .left_outer_join("campaigns", "campaigns.id=donations.campaign_id" ) - .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) + .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') + .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) end if query[:event_id].present? - tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix") + tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by('payment_id').as('tix') expr = expr - .left_outer_join(tickets_subquery, "tix.payment_id=payments.id") - .where("tix.event_id=$id OR donations.event_id=$id", id: query[:event_id]) + .left_outer_join(tickets_subquery, 'tix.payment_id=payments.id') + .where('tix.event_id=$id OR donations.event_id=$id', id: query[:event_id]) end expr = expr - #we have the first part of the search. We need to create the second in certain situations + # we have the first part of the search. We need to create the second in certain situations filtered_payment_id_search = expr.parse if query[:event_id].present? || query[:campaign_id].present? - filtered_payment_id_search = filtered_payment_id_search + " UNION DISTINCT " + create_reverse_select(npo_id, query).parse + filtered_payment_id_search = filtered_payment_id_search + ' UNION DISTINCT ' + create_reverse_select(npo_id, query).parse end - - filtered_payment_id_search end # we use this when we need to get the refund info - def self.create_reverse_select(npo_id, query) + def self.create_reverse_select(npo_id, query) inner_donation_search = Qexpr.new.select('donations.*').from('donations') - if (query[:event_id].present?) + if query[:event_id].present? inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) end - if (query[:campaign_id].present?) + if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id]) end expr = Qexpr.new.select('payments.id').from('payments') - .left_outer_join('supporters', "supporters.id=payments.supporter_id") + .left_outer_join('supporters', 'supporters.id=payments.supporter_id') .left_outer_join('refunds', 'payments.id=refunds.payment_id') - .left_outer_join('charges', 'refunds.charge_id=charges.id') - .left_outer_join('payments AS payments_orig', 'payments_orig.id=charges.payment_id') - .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments_orig.donation_id' ) - .where('payments.nonprofit_id=$id', id: npo_id.to_i) + .left_outer_join('charges', 'refunds.charge_id=charges.id') + .left_outer_join('payments AS payments_orig', 'payments_orig.id=charges.payment_id') + .left_outer_join(inner_donation_search.as('donations'), 'donations.id=payments_orig.donation_id') + .where('payments.nonprofit_id=$id', id: npo_id.to_i) - - if query[:search].present? - expr = SearchVector.query(query[:search], expr) - end - if ['asc', 'desc'].include? query[:sort_amount] + expr = SearchVector.query(query[:search], expr) if query[:search].present? + if %w[asc desc].include? query[:sort_amount] expr = expr.order_by("payments.gross_amount #{query[:sort_amount]}") end - if ['asc', 'desc'].include? query[:sort_date] + if %w[asc desc].include? query[:sort_date] expr = expr.order_by("payments.date #{query[:sort_date]}") end - if ['asc', 'desc'].include? query[:sort_name] + if %w[asc desc].include? query[:sort_name] expr = expr.order_by("coalesce(NULLIF(supporters.name, ''), NULLIF(supporters.email, '')) #{query[:sort_name]}") end - if ['asc', 'desc'].include? query[:sort_type] + if %w[asc desc].include? query[:sort_type] expr = expr.order_by("payments.kind #{query[:sort_type]}") end - if ['asc', 'desc'].include? query[:sort_towards] + if %w[asc desc].include? query[:sort_towards] expr = expr.order_by("NULLIF(payments.towards, '') #{query[:sort_towards]}") end if query[:after_date].present? @@ -272,10 +263,10 @@ module QueryPayments expr = expr.where("to_char(payments.date, 'YYYY')=$year", year: query[:year]) end if query[:designation].present? - expr = expr.where("donations.designation @@ $s", s: "#{query[:designation]}") + expr = expr.where('donations.designation @@ $s', s: (query[:designation]).to_s) end if query[:dedication].present? - expr = expr.where("donations.dedication @@ $s", s: "#{query[:dedication]}") + expr = expr.where('donations.dedication @@ $s', s: (query[:dedication]).to_s) end if query[:donation_type].present? expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) @@ -283,65 +274,60 @@ module QueryPayments if query[:campaign_id].present? campaign_search = campaign_and_child_query_as_raw_string expr = expr - .left_outer_join("campaigns", "campaigns.id=donations.campaign_id" ) - .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) + .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') + .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id]) end if query[:event_id].present? - tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix") + tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by('payment_id').as('tix') expr = expr - .left_outer_join(tickets_subquery, "tix.payment_id=payments_orig.id") - .where("tix.event_id=$id OR donations.event_id=$id", id: query[:event_id]) + .left_outer_join(tickets_subquery, 'tix.payment_id=payments_orig.id') + .where('tix.event_id=$id OR donations.event_id=$id', id: query[:event_id]) end expr end - def self.for_export_enumerable(npo_id, query, chunk_limit=35000) - ParamValidation.new({npo_id: npo_id, query:query}, {npo_id: {required: true, is_int: true}, - query: {required:true, is_hash: true}}) + def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) + ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, + query: { required: true, is_hash: true }) - return QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| + QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) end - end def self.for_export(npo_id, query) - tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') expr = full_search_expr(npo_id, query) - .select(*export_selects) - .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') - .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') - .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') - .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') - .parse + .select(*export_selects) + .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') + .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') + .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') + .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') + .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') + .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') + .parse Psql.execute_vectors(expr) end - def self.get_chunk_of_export(npo_id, query, offset=nil, limit=nil, skip_header=false ) - - return QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) { - - - tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + def self.get_chunk_of_export(npo_id, query, offset = nil, limit = nil, skip_header = false) + QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) do + tickets_subquery = Qexpr.new.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') expr = full_search_expr(npo_id, query) - .select(*export_selects) - .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') - .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') - .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') - .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') - } + .select(*export_selects) + .left_outer_join('campaign_gifts', 'campaign_gifts.donation_id=donations.id') + .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') + .left_outer_join("(#{campaigns_with_creator_email}) AS campaigns_for_export", 'donations.campaign_id=campaigns_for_export.id') + .left_outer_join(tickets_subquery, 'tickets.payment_id=payments.id') + .left_outer_join('events events_for_export', 'events_for_export.id=tickets.event_id OR donations.event_id=events_for_export.id') + .left_outer_join('offsite_payments', 'offsite_payments.payment_id=payments.id') + end end - def self.get_dedication_or_empty(*path) - "json_extract_path_text(coalesce(nullif(trim(both from donations.dedication), ''), '{}')::json, #{path.map{|i| "'#{i}'"}.join(',')})" + "json_extract_path_text(coalesce(nullif(trim(both from donations.dedication), ''), '{}')::json, #{path.map { |i| "'#{i}'" }.join(',')})" end def self.export_selects @@ -350,114 +336,109 @@ module QueryPayments '(payments.fee_total / 100.0)::money::text AS fee_total', '(payments.net_amount / 100.0)::money::text AS net_amount', 'payments.kind AS type'] - .concat(QuerySupporters.supporter_export_selections) - .concat([ - "coalesce(donations.designation, 'None') AS designation", - "#{get_dedication_or_empty('type')}::text AS \"Dedication Type\"", - "#{get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", - "#{get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", - "#{get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", - "#{get_dedication_or_empty('contact', "phone")}::text AS \"Dedicated To: Phone\"", - "#{get_dedication_or_empty( "contact", "address")}::text AS \"Dedicated To: Address\"", - "#{get_dedication_or_empty( "note")}::text AS \"Dedicated To: Note\"", - 'donations.anonymous', - 'donations.comment', - "coalesce(nullif(campaigns_for_export.name, ''), 'None') AS campaign", - "campaigns_for_export.id AS \"Campaign Id\"", - "coalesce(nullif(campaigns_for_export.creator_email, ''), '') AS campaign_creator_email", - "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS campaign_gift_level", - 'events_for_export.name AS event_name', - 'payments.id AS payment_id', - 'offsite_payments.check_number AS check_number', - 'donations.comment AS donation_note' - ]) + .concat(QuerySupporters.supporter_export_selections) + .concat([ + "coalesce(donations.designation, 'None') AS designation", + "#{get_dedication_or_empty('type')}::text AS \"Dedication Type\"", + "#{get_dedication_or_empty('name')}::text AS \"Dedicated To: Name\"", + "#{get_dedication_or_empty('supporter_id')}::text AS \"Dedicated To: Supporter ID\"", + "#{get_dedication_or_empty('contact', 'email')}::text AS \"Dedicated To: Email\"", + "#{get_dedication_or_empty('contact', 'phone')}::text AS \"Dedicated To: Phone\"", + "#{get_dedication_or_empty('contact', 'address')}::text AS \"Dedicated To: Address\"", + "#{get_dedication_or_empty('note')}::text AS \"Dedicated To: Note\"", + 'donations.anonymous', + 'donations.comment', + "coalesce(nullif(campaigns_for_export.name, ''), 'None') AS campaign", + 'campaigns_for_export.id AS "Campaign Id"', + "coalesce(nullif(campaigns_for_export.creator_email, ''), '') AS campaign_creator_email", + "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS campaign_gift_level", + 'events_for_export.name AS event_name', + 'payments.id AS payment_id', + 'offsite_payments.check_number AS check_number', + 'donations.comment AS donation_note' + ]) end - # Create the data structure for the payout export CSVs # Has two sections: two rows for info about the payout, then all the rows after that are for the payments # TODO reuse the standard payment export query for the payment rows for this query def self.for_payout(npo_id, payout_id) - tickets_subquery = Qx.select("payment_id", "MAX(event_id) AS event_id").from("tickets").group_by("payment_id").as("tickets") + tickets_subquery = Qx.select('payment_id', 'MAX(event_id) AS event_id').from('tickets').group_by('payment_id').as('tickets') supporters_subq = Qx.select(QuerySupporters.supporter_export_selections) Qx.select( - "to_char(payouts.created_at, 'MM/DD/YYYY HH24:MIam') AS date", - "(payouts.gross_amount / 100.0)::money::text AS gross_total", - "(payouts.fee_total / 100.0)::money::text AS fee_total", - "(payouts.net_amount / 100.0)::money::text AS net_total", - "bank_accounts.name AS bank_name", - "payouts.status" - ) + "to_char(payouts.created_at, 'MM/DD/YYYY HH24:MIam') AS date", + '(payouts.gross_amount / 100.0)::money::text AS gross_total', + '(payouts.fee_total / 100.0)::money::text AS fee_total', + '(payouts.net_amount / 100.0)::money::text AS net_total', + 'bank_accounts.name AS bank_name', + 'payouts.status' + ) .from(:payouts) - .join(:bank_accounts, "bank_accounts.nonprofit_id=payouts.nonprofit_id") - .where("payouts.nonprofit_id=$id", id: npo_id) - .and_where("payouts.id=$id", id: payout_id) + .join(:bank_accounts, 'bank_accounts.nonprofit_id=payouts.nonprofit_id') + .where('payouts.nonprofit_id=$id', id: npo_id) + .and_where('payouts.id=$id', id: payout_id) .execute(format: 'csv') .concat([[]]) .concat( Qx.select([ "to_char(payments.date, 'MM/DD/YYYY HH24:MIam') AS \"Date\"", - "(payments.gross_amount/100.0)::money::text AS \"Gross Amount\"", - "(payments.fee_total / 100.0)::money::text AS \"Fee Total\"", - "(payments.net_amount / 100.0)::money::text AS \"Net Amount\"", - "payments.kind AS \"Type\"", - "payments.id AS \"Payment ID\"" - ].concat(QuerySupporters.supporter_export_selections) + '(payments.gross_amount/100.0)::money::text AS "Gross Amount"', + '(payments.fee_total / 100.0)::money::text AS "Fee Total"', + '(payments.net_amount / 100.0)::money::text AS "Net Amount"', + 'payments.kind AS "Type"', + 'payments.id AS "Payment ID"' + ].concat(QuerySupporters.supporter_export_selections) .concat([ - "coalesce(donations.designation, 'None') AS \"Designation\"", - "donations.dedication AS \"Honorarium/Memorium\"", - "donations.anonymous AS \"Anonymous?\"", - "donations.comment AS \"Comment\"", - "coalesce(nullif(campaigns.name, ''), 'None') AS \"Campaign\"", - "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS \"Campaign Gift Level\"", - "coalesce(events.name, 'None') AS \"Event\"" - ]) - ) + "coalesce(donations.designation, 'None') AS \"Designation\"", + 'donations.dedication AS "Honorarium/Memorium"', + 'donations.anonymous AS "Anonymous?"', + 'donations.comment AS "Comment"', + "coalesce(nullif(campaigns.name, ''), 'None') AS \"Campaign\"", + "coalesce(nullif(campaign_gift_options.name, ''), 'None') AS \"Campaign Gift Level\"", + "coalesce(events.name, 'None') AS \"Event\"" + ])) .distinct_on('payments.date, payments.id') .from(:payments) - .join(:payment_payouts, "payment_payouts.payment_id=payments.id") - .add_join(:payouts, "payouts.id=payment_payouts.payout_id") - .left_join(:supporters, "payments.supporter_id=supporters.id") - .add_left_join(:donations, "donations.id=payments.donation_id") - .add_left_join(:campaigns, "donations.campaign_id=campaigns.id") - .add_left_join(:campaign_gifts, "donations.id=campaign_gifts.donation_id") - .add_left_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id") - .add_left_join(tickets_subquery, "tickets.payment_id=payments.id") - .add_left_join(:events, "events.id=tickets.event_id OR (events.id = donations.event_id)") - .where("payouts.id=$id", id: payout_id) - .and_where("payments.nonprofit_id=$id", id: npo_id) - .order_by("payments.date DESC, payments.id") + .join(:payment_payouts, 'payment_payouts.payment_id=payments.id') + .add_join(:payouts, 'payouts.id=payment_payouts.payout_id') + .left_join(:supporters, 'payments.supporter_id=supporters.id') + .add_left_join(:donations, 'donations.id=payments.donation_id') + .add_left_join(:campaigns, 'donations.campaign_id=campaigns.id') + .add_left_join(:campaign_gifts, 'donations.id=campaign_gifts.donation_id') + .add_left_join(:campaign_gift_options, 'campaign_gift_options.id=campaign_gifts.campaign_gift_option_id') + .add_left_join(tickets_subquery, 'tickets.payment_id=payments.id') + .add_left_join(:events, 'events.id=tickets.event_id OR (events.id = donations.event_id)') + .where('payouts.id=$id', id: payout_id) + .and_where('payments.nonprofit_id=$id', id: npo_id) + .order_by('payments.date DESC, payments.id') .execute(format: 'csv') ) end - def self.find_payments_where_too_far_from_charge_date(id=nil) + def self.find_payments_where_too_far_from_charge_date(id = nil) pay = Payment.includes(:donation).includes(:offsite_payment) - if (id) - pay = pay.where('id = ?', id) - end + pay = pay.where('id = ?', id) if id pay = pay.where('date IS NOT NULL').order('id ASC') - pay.all.each{|p| - next if p.offsite_payment != nil + pay.all.each do |p| + next unless p.offsite_payment.nil? + lowest_charge_for_payment = Charge.where('payment_id = ?', p.id).order('created_at ASC').limit(1).first - - if (lowest_charge_for_payment) + if lowest_charge_for_payment diff = p.date - lowest_charge_for_payment.created_at diff_too_big = diff > 10.minutes || diff < -10.minutes end - if (lowest_charge_for_payment && diff_too_big) + if lowest_charge_for_payment && diff_too_big yield(p.donation.id, p.donation.date, p.id, p.date, lowest_charge_for_payment.id, lowest_charge_for_payment.created_at, diff) end - - } + end end def self.campaign_and_child_query_as_raw_string - "SELECT c_temp.id from campaigns c_temp where c_temp.id=$id OR c_temp.parent_campaign_id=$id" + 'SELECT c_temp.id from campaigns c_temp where c_temp.id=$id OR c_temp.parent_campaign_id=$id' end def self.campaigns_with_creator_email - Qexpr.new.select('campaigns.*, users.email AS creator_email').from(:campaigns).left_outer_join(:profiles, "profiles.id = campaigns.profile_id").left_outer_join(:users, 'users.id = profiles.user_id') + Qexpr.new.select('campaigns.*, users.email AS creator_email').from(:campaigns).left_outer_join(:profiles, 'profiles.id = campaigns.profile_id').left_outer_join(:users, 'users.id = profiles.user_id') end end diff --git a/lib/query/query_profiles.rb b/lib/query/query_profiles.rb index cf3b7e56..d1938a9b 100644 --- a/lib/query/query_profiles.rb +++ b/lib/query/query_profiles.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' module QueryProfiles - def self.for_admin(params) - expr = Qx.select( - 'profiles.name', - 'profiles.id', - 'profiles.created_at::date::text AS created_at', - 'users.confirmed_at AS is_confirmed', - 'users.email') - .from(:profiles) - .add_left_join("users", "profiles.user_id=users.id") - .order_by("profiles.created_at DESC") - .paginate(params[:page].to_i, params[:page_length].to_i) + expr = Qx.select( + 'profiles.name', + 'profiles.id', + 'profiles.created_at::date::text AS created_at', + 'users.confirmed_at AS is_confirmed', + 'users.email' + ) + .from(:profiles) + .add_left_join('users', 'profiles.user_id=users.id') + .order_by('profiles.created_at DESC') + .paginate(params[:page].to_i, params[:page_length].to_i) - if params[:search].present? - expr = expr.where(%Q( - profiles.name LIKE $search - OR users.email LIKE $search - OR users.name LIKE $search - ), search: '%' + params[:search].downcase + '%') - end + if params[:search].present? + expr = expr.where(%( + profiles.name LIKE $search + OR users.email LIKE $search + OR users.name LIKE $search + ), search: '%' + params[:search].downcase + '%') + end - return expr.execute + expr.execute end end diff --git a/lib/query/query_recurring_donations.rb b/lib/query/query_recurring_donations.rb index 8edd9108..8172a0a6 100644 --- a/lib/query/query_recurring_donations.rb +++ b/lib/query/query_recurring_donations.rb @@ -1,33 +1,33 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' require 'psql' module QueryRecurringDonations - # Calculate a nonprofit's total recurring donations def self.monthly_total(np_id) - Qx.select("coalesce(sum(amount), 0) AS sum") - .from("recurring_donations") + Qx.select('coalesce(sum(amount), 0) AS sum') + .from('recurring_donations') .where(nonprofit_id: np_id) .and_where(is_external_active_clause('recurring_donations')) .execute.first['sum'] end - # Fetch a single recurring donation for its edit page def self.fetch_for_edit(id) recurring_donation = Psql.execute( - Qexpr.new.select( - "recurring_donations.*", - "nonprofits.id AS nonprofit_id", - "nonprofits.name AS nonprofit_name", - "cards.name AS card_name" - ).from('recurring_donations') - .left_outer_join('donations', 'donations.id=recurring_donations.donation_id') - .left_outer_join('cards', 'donations.card_id=cards.id') - .left_outer_join('nonprofits', 'nonprofits.id=recurring_donations.nonprofit_id') - .where('recurring_donations.id=$id', id: id) - ).first + Qexpr.new.select( + 'recurring_donations.*', + 'nonprofits.id AS nonprofit_id', + 'nonprofits.name AS nonprofit_name', + 'cards.name AS card_name' + ).from('recurring_donations') + .left_outer_join('donations', 'donations.id=recurring_donations.donation_id') + .left_outer_join('cards', 'donations.card_id=cards.id') + .left_outer_join('nonprofits', 'nonprofits.id=recurring_donations.nonprofit_id') + .where('recurring_donations.id=$id', id: id) + ).first return recurring_donation if !recurring_donation || !recurring_donation['id'] @@ -39,22 +39,21 @@ module QueryRecurringDonations nonprofit = Nonprofit.find(recurring_donation['nonprofit_id']) - return { + { 'recurring_donation' => recurring_donation, 'supporter' => supporter, 'nonprofit' => nonprofit } end - # Construct a full query for the dashboard/export listings def self.full_search_expr(np_id, query) expr = Qexpr.new - .from('recurring_donations') - .left_outer_join('supporters', 'supporters.id=recurring_donations.supporter_id') - .join('donations', 'donations.id=recurring_donations.donation_id') - .left_outer_join('charges paid_charges', 'paid_charges.donation_id=donations.id') - .where('recurring_donations.nonprofit_id=$id', id: np_id.to_i) + .from('recurring_donations') + .left_outer_join('supporters', 'supporters.id=recurring_donations.supporter_id') + .join('donations', 'donations.id=recurring_donations.donation_id') + .left_outer_join('charges paid_charges', 'paid_charges.donation_id=donations.id') + .where('recurring_donations.nonprofit_id=$id', id: np_id.to_i) failed_or_active_clauses = [] @@ -73,29 +72,27 @@ module QueryRecurringDonations failed_or_active_clauses.push("(#{clause})") end - if (failed_or_active_clauses.any?) - expr = expr.where("#{failed_or_active_clauses.join(' OR ')}") + if failed_or_active_clauses.any? + expr = expr.where(failed_or_active_clauses.join(' OR ').to_s) end - - expr = expr.where("paid_charges.id IS NULL OR paid_charges.status != 'failed'") - .group_by('recurring_donations.id') - .order_by('recurring_donations.created_at') + expr = expr.where("paid_charges.id IS NULL OR paid_charges.status != 'failed'") + .group_by('recurring_donations.id') + .order_by('recurring_donations.created_at') if query[:search].present? matcher = "%#{query[:search].downcase.split(' ').join('%')}%" - expr = expr.where(%Q(( + expr = expr.where(%(( lower(supporters.name) LIKE $name OR lower(supporters.email) LIKE $email OR recurring_donations.amount=$amount OR recurring_donations.id=$id - )), {name: matcher, email: matcher, amount: query[:search].to_i, id: query[:search].to_i}) + )), name: matcher, email: matcher, amount: query[:search].to_i, id: query[:search].to_i) end - return expr + expr end - # Fetch the full table of results for the dashboard - def self.full_list(np_id, query={}) + def self.full_list(np_id, query = {}) limit = 30 offset = Qexpr.page_offset(limit, query[:page]) expr = full_search_expr(np_id, query).select( @@ -108,8 +105,9 @@ module QueryRecurringDonations 'MAX(supporters.email) AS email', 'MAX(supporters.name) AS name', 'MAX(supporters.id) AS supporter_id', - 'SUM(paid_charges.amount) AS total_given') - .limit(limit).offset(offset) + 'SUM(paid_charges.amount) AS total_given' + ) + .limit(limit).offset(offset) data = Psql.execute(expr) total_count = Psql.execute( @@ -118,75 +116,74 @@ module QueryRecurringDonations ).first['count'] total_amount = monthly_total(np_id) - return { + { data: data, total_amount: total_amount, total_count: total_count, - remaining: Qexpr.remaining_count(total_count, limit, query[:page]), + remaining: Qexpr.remaining_count(total_count, limit, query[:page]) } end - def self.for_export_enumerable(npo_id, query, chunk_limit=35000) - ParamValidation.new({npo_id: npo_id, query:query}, {npo_id: {required: true, is_int: true}, - query: {required:true, is_hash: true}}) + def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) + ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, + query: { required: true, is_hash: true }) - return QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| + QexprQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) end - end - def self.get_chunk_of_export(npo_id, query, offset=nil, limit=nil, skip_header=false ) + def self.get_chunk_of_export(npo_id, query, offset = nil, limit = nil, skip_header = false) root_url = query[:root_url] - return QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) { - full_search_expr(npo_id, query).select( - 'recurring_donations.created_at', - '(recurring_donations.amount / 100.0)::money::text AS amount', - "concat('Every ', recurring_donations.interval, ' ', recurring_donations.time_unit, '(s)') AS interval", - '(SUM(paid_charges.amount) / 100.0)::money::text AS total_contributed', - 'MAX(campaigns.name) AS campaign_name', - 'MAX(supporters.name) AS supporter_name', - 'MAX(supporters.email) AS supporter_email', - 'MAX(supporters.phone) AS phone', - 'MAX(supporters.address) AS address', - 'MAX(supporters.city) AS city', - 'MAX(supporters.state_code) AS state', - 'MAX(supporters.zip_code) AS zip_code', - 'MAX(cards.name) AS card_name', - 'recurring_donations.id AS "Recurring Donation ID"', - 'MAX(donations.id) AS "Donation ID"', - "CASE WHEN #{is_cancelled_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Cancelled", - "CASE WHEN #{is_failed_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Failed", - 'recurring_donations.cancelled_at AS "Cancelled At"', - "CASE WHEN #{is_active_clause('recurring_donations')} THEN concat('#{root_url}recurring_donations/', recurring_donations.id, '/edit?t=', recurring_donations.edit_token) ELSE '' END AS \"Donation Management Url\"") - .left_outer_join('campaigns' , 'campaigns.id=donations.campaign_id') - .left_outer_join('cards', 'cards.id=donations.card_id') - } + QexprQueryChunker.get_chunk_of_query(offset, limit, skip_header) do + full_search_expr(npo_id, query).select( + 'recurring_donations.created_at', + '(recurring_donations.amount / 100.0)::money::text AS amount', + "concat('Every ', recurring_donations.interval, ' ', recurring_donations.time_unit, '(s)') AS interval", + '(SUM(paid_charges.amount) / 100.0)::money::text AS total_contributed', + 'MAX(campaigns.name) AS campaign_name', + 'MAX(supporters.name) AS supporter_name', + 'MAX(supporters.email) AS supporter_email', + 'MAX(supporters.phone) AS phone', + 'MAX(supporters.address) AS address', + 'MAX(supporters.city) AS city', + 'MAX(supporters.state_code) AS state', + 'MAX(supporters.zip_code) AS zip_code', + 'MAX(cards.name) AS card_name', + 'recurring_donations.id AS "Recurring Donation ID"', + 'MAX(donations.id) AS "Donation ID"', + "CASE WHEN #{is_cancelled_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Cancelled", + "CASE WHEN #{is_failed_clause('recurring_donations')} THEN 'true' ELSE 'false' END AS Failed", + 'recurring_donations.cancelled_at AS "Cancelled At"', + "CASE WHEN #{is_active_clause('recurring_donations')} THEN concat('#{root_url}recurring_donations/', recurring_donations.id, '/edit?t=', recurring_donations.edit_token) ELSE '' END AS \"Donation Management Url\"" + ) + .left_outer_join('campaigns', 'campaigns.id=donations.campaign_id') + .left_outer_join('cards', 'cards.id=donations.card_id') + end end - def self.recurring_donations_without_cards - RecurringDonation.active.includes(:card).includes(:charges).includes(:donation).includes(:nonprofit).includes(:supporter).where("cards.id IS NULL").order("recurring_donations.created_at DESC") + RecurringDonation.active.includes(:card).includes(:charges).includes(:donation).includes(:nonprofit).includes(:supporter).where('cards.id IS NULL').order('recurring_donations.created_at DESC') end - - def self._splitting_rd_supporters_without_cards() + + def self._splitting_rd_supporters_without_cards supporters_with_valid_rds = [] supporters_without_valid_rds = [] send_to_wendy = [] - supporters_with_cardless_rds = recurring_donations_without_cards.map {|rd| rd.supporter}.uniq{|s| s.id} + supporters_with_cardless_rds = recurring_donations_without_cards.map(&:supporter).uniq(&:id) - #does the supporter have even one rd with a valid card - supporters_with_cardless_rds.each {|s| + # does the supporter have even one rd with a valid card + supporters_with_cardless_rds.each do |s| valid_rd = find_recurring_donation_with_a_card(s) # they have a recurring donation with a card for the same org - if (valid_rd) - if (s.recurring_donations.length > 2) - #they have too many recurring_donations. Send to wendy + if valid_rd + if s.recurring_donations.length > 2 + # they have too many recurring_donations. Send to wendy send_to_wendy.push(s) else # are the recurring_donations the same amount? - if (s.recurring_donations[0].amount == s.recurring_donations[1].amount) + if s.recurring_donations[0].amount == s.recurring_donations[1].amount supporters_with_valid_rds.push(s) else # they're not the same amount. We got no clue. Send to Wendy @@ -197,60 +194,60 @@ module QueryRecurringDonations # they have no other recurring donations supporters_without_valid_rds.push(s) end - } + end - return supporters_with_valid_rds, send_to_wendy, supporters_without_valid_rds + [supporters_with_valid_rds, send_to_wendy, supporters_without_valid_rds] end # @param [Array] wendy_list_of_supporters # @param [String] path - # def self.create_wendy_csv(path, wendy_list_of_supporters) - # CSV.open(path, 'wb') {|csv| - # csv << ['supporter id', 'nonprofit id', 'supporter name', 'supporter address', 'supporter city', 'supporter state', 'supporter ZIP', 'supporter country', 'supporter phone', 'supporter email', 'supporter rd amounts'] - # wendy_list_of_supporters.each { |s| - # amounts = '$'+ s.recurring_donations.active.collect {|rd| Format::Currency.cents_to_dollars(rd.amount)}.join(", $") - # csv << [s.id, s.nonprofit.id, s.name, s.address, s.city, s.state_code, s.zip_code, s.country, s.phone, s.email, amounts] - # } - # } - # end + # def self.create_wendy_csv(path, wendy_list_of_supporters) + # CSV.open(path, 'wb') {|csv| + # csv << ['supporter id', 'nonprofit id', 'supporter name', 'supporter address', 'supporter city', 'supporter state', 'supporter ZIP', 'supporter country', 'supporter phone', 'supporter email', 'supporter rd amounts'] + # wendy_list_of_supporters.each { |s| + # amounts = '$'+ s.recurring_donations.active.collect {|rd| Format::Currency.cents_to_dollars(rd.amount)}.join(", $") + # csv << [s.id, s.nonprofit.id, s.name, s.address, s.city, s.state_code, s.zip_code, s.country, s.phone, s.email, amounts] + # } + # } + # end # @param [Supporter] supporter def self.find_recurring_donation_with_a_card(supporter) - supporter.recurring_donations.select{|rd| - rd.donation != nil && rd.donation.card != nil}.first() + supporter.recurring_donations.select do |rd| + !rd.donation.nil? && !rd.donation.card.nil? + end .first end # Check if a single recdon is due -- used in PayRecurringDonation.with_stripe def self.is_due?(rd_id) Psql.execute( _all_that_are_due - .where("recurring_donations.id=$id", id: rd_id) + .where('recurring_donations.id=$id', id: rd_id) ).any? end - # Sql partial expression # Select all due recurring donations # Can use this for all donations in the db, or extend the query for only those with a nonprofit_id, supporter_id, etc (see is_due?) # XXX horrendous conditional --what is wrong with me? def self._all_that_are_due now = Time.current - Qexpr.new.select("recurring_donations.id") - .from(:recurring_donations) - .where("recurring_donations.active='t'") - .where("coalesce(recurring_donations.n_failures, 0) < 3") - .where("recurring_donations.start_date IS NULL OR recurring_donations.start_date <= $now", now: now) - .where("recurring_donations.end_date IS NULL OR recurring_donations.end_date > $now", now: now) - .join('donations','recurring_donations.donation_id=donations.id and (donations.payment_provider IS NULL OR donations.payment_provider!=\'sepa\')') - .left_outer_join( # Join the most recent paid charge - Qexpr.new.select(:donation_id, "MAX(created_at) AS created_at") - .from(:charges) - .where("status != 'failed'") - .group_by("donation_id") - .as("last_charge"), - "last_charge.donation_id=recurring_donations.donation_id" - ) - .where(%Q( + Qexpr.new.select('recurring_donations.id') + .from(:recurring_donations) + .where("recurring_donations.active='t'") + .where('coalesce(recurring_donations.n_failures, 0) < 3') + .where('recurring_donations.start_date IS NULL OR recurring_donations.start_date <= $now', now: now) + .where('recurring_donations.end_date IS NULL OR recurring_donations.end_date > $now', now: now) + .join('donations', 'recurring_donations.donation_id=donations.id and (donations.payment_provider IS NULL OR donations.payment_provider!=\'sepa\')') + .left_outer_join( # Join the most recent paid charge + Qexpr.new.select(:donation_id, 'MAX(created_at) AS created_at') + .from(:charges) + .where("status != 'failed'") + .group_by('donation_id') + .as('last_charge'), + 'last_charge.donation_id=recurring_donations.donation_id' + ) + .where(%( last_charge.donation_id IS NULL OR ( (recurring_donations.time_unit != 'month' OR recurring_donations.interval != 1) @@ -271,34 +268,34 @@ module QueryRecurringDonations ) ) ) - ), { - now: now, - beginning_of_month: now.beginning_of_month, - beginning_of_last_month: (now - 1.month).beginning_of_month, - today: now.day - }) - .order_by('recurring_donations.created_at') + ), + now: now, + beginning_of_month: now.beginning_of_month, + beginning_of_last_month: (now - 1.month).beginning_of_month, + today: now.day) + .order_by('recurring_donations.created_at') end + # Some general statistics for a nonprofit def self.overall_stats(np_id) - return Psql.execute( + Psql.execute( Qexpr.new.from(:recurring_donations) .select( - "money(avg(recurring_donations.amount) / 100.0) AS average", - "money(coalesce(sum(rds_active.amount), 0) / 100.0) AS active_sum", - "coalesce(count(rds_active), 0) AS active_count", - "money(coalesce(sum(rds_inactive.amount), 0) / 100.0) AS inactive_sum", - "coalesce(count(rds_inactive), 0) AS inactive_count", - "money(coalesce(sum(rds_failed.amount), 0) / 100.0) AS failed_sum", - "coalesce(count(rds_failed), 0) AS failed_count", - "money(coalesce(sum(rds_cancelled.amount), 0) / 100.0) AS cancelled_sum", - "coalesce(count(rds_cancelled), 0) AS cancelled_count" + 'money(avg(recurring_donations.amount) / 100.0) AS average', + 'money(coalesce(sum(rds_active.amount), 0) / 100.0) AS active_sum', + 'coalesce(count(rds_active), 0) AS active_count', + 'money(coalesce(sum(rds_inactive.amount), 0) / 100.0) AS inactive_sum', + 'coalesce(count(rds_inactive), 0) AS inactive_count', + 'money(coalesce(sum(rds_failed.amount), 0) / 100.0) AS failed_sum', + 'coalesce(count(rds_failed), 0) AS failed_count', + 'money(coalesce(sum(rds_cancelled.amount), 0) / 100.0) AS cancelled_sum', + 'coalesce(count(rds_cancelled), 0) AS cancelled_count' ) .left_outer_join('recurring_donations rds_active', "rds_active.id=recurring_donations.id AND #{is_external_active_clause('rds_active')}") .left_outer_join('recurring_donations rds_inactive', "rds_inactive.id=recurring_donations.id AND #{is_external_cancelled_clause('rds_inactive')}") .left_outer_join('recurring_donations rds_failed', "rds_failed.id=recurring_donations.id AND #{is_failed_clause('rds_failed')}") .left_outer_join('recurring_donations rds_cancelled', "rds_cancelled.id=recurring_donations.id AND #{is_cancelled_clause('rds_cancelled')}") - .where("recurring_donations.nonprofit_id=$id", id: np_id) + .where('recurring_donations.nonprofit_id=$id', id: np_id) ).first end @@ -316,7 +313,6 @@ module QueryRecurringDonations "#{field_for_rd}.active='t'" end - def self.is_cancelled_clause(field_for_rd) "NOT (#{is_active_clause(field_for_rd)})" end @@ -330,21 +326,23 @@ module QueryRecurringDonations end def self.last_charge - Qexpr.new.select(:donation_id, "MAX(created_at) AS created_at") - .from(:charges) - .where("status != 'failed'") - .group_by("donation_id") - .as("last_charge") + Qexpr.new.select(:donation_id, 'MAX(created_at) AS created_at') + .from(:charges) + .where("status != 'failed'") + .group_by('donation_id') + .as('last_charge') end def self.export_for_transfer(nonprofit_id) - items = RecurringDonation.where("nonprofit_id = ?", nonprofit_id).active.includes('supporter').includes('card').to_a - output = items.map{|i| {supporter: i.supporter.id, - supporter_name: i.supporter.name, - supporter_email: i.supporter.email, - amount: i.amount, - paydate: i.paydate, - card: i.card.stripe_card_id}} - return output.to_a + items = RecurringDonation.where('nonprofit_id = ?', nonprofit_id).active.includes('supporter').includes('card').to_a + output = items.map do |i| + { supporter: i.supporter.id, + supporter_name: i.supporter.name, + supporter_email: i.supporter.email, + amount: i.amount, + paydate: i.paydate, + card: i.card.stripe_card_id } + end + output.to_a end end diff --git a/lib/query/query_roles.rb b/lib/query/query_roles.rb index 01db6251..b7807784 100644 --- a/lib/query/query_roles.rb +++ b/lib/query/query_roles.rb @@ -1,27 +1,28 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryRoles + def self.user_has_role?(user_id, role_names, host_id = nil) + expr = Qx.select('COUNT(roles)').from(:roles) + .where('name IN ($names)', names: Array(role_names)) + .and_where(user_id: user_id) + expr = expr.and_where(host_id: host_id) if host_id + expr.execute.first['count'] > 0 + end - def self.user_has_role?(user_id, role_names, host_id=nil) - expr = Qx.select("COUNT(roles)").from(:roles) - .where("name IN ($names)", names: Array(role_names)) - .and_where(user_id: user_id) - expr = expr.and_where(host_id: host_id) if host_id - return expr.execute.first['count'] > 0 - end + # Get host tables -- host can be nonprofit, campaign, event + def self.host_ids(user_id, role_names) + Qx.select('host_id').from(:roles) + .where(user_id: user_id) + .and_where('roles.name IN ($names)', names: role_names) + .execute.map { |h| h['host_id'] } + end - # Get host tables -- host can be nonprofit, campaign, event - def self.host_ids(user_id, role_names) - Qx.select("host_id").from(:roles) - .where(user_id: user_id) - .and_where("roles.name IN ($names)", names: role_names) - .execute.map{|h| h['host_id']} - end + def self.is_nonprofit_user?(user_id, np_id) + user_has_role?(user_id, %i[nonprofit_admin nonprofit_associate], np_id) + end - def self.is_nonprofit_user?(user_id, np_id) - user_has_role?(user_id, [:nonprofit_admin, :nonprofit_associate], np_id) - end - - def self.is_authorized_for_nonprofit?(user_id, np_id) - user_has_role?(user_id, [:super_admin]) || is_nonprofit_user?(user_id, np_id) - end -end \ No newline at end of file + def self.is_authorized_for_nonprofit?(user_id, np_id) + user_has_role?(user_id, [:super_admin]) || is_nonprofit_user?(user_id, np_id) + end +end diff --git a/lib/query/query_source_token.rb b/lib/query/query_source_token.rb index 25a7abb6..0c9233ec 100644 --- a/lib/query/query_source_token.rb +++ b/lib/query/query_source_token.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QuerySourceToken - EXPIRED_TOKEN_MESSAGE = "There was an error processing your card and it was not charged. Please try again." + EXPIRED_TOKEN_MESSAGE = 'There was an error processing your card and it was not charged. Please try again.' AUTH_ERROR_MESSAGE = "You're not authorized to make this charge" # @param [String] source_token @@ -11,43 +13,36 @@ module QuerySourceToken # @raise [ExpiredTokenError] when the source token has already been used too many times # or we're past the expiration date def self.get_and_increment_source_token(token, user = nil) - ParamValidation.new({token: token}, { - token: {required: true, format: UUID::Regex} - }) + ParamValidation.new({ token: token }, + token: { required: true, format: UUID::Regex }) source_token = SourceToken.where('token = ?', token).first if source_token - source_token.with_lock { + source_token.with_lock do unless source_token_unexpired?(source_token) - raise ExpiredTokenError.new(EXPIRED_TOKEN_MESSAGE) + raise ExpiredTokenError, EXPIRED_TOKEN_MESSAGE end if source_token.event - unless user - raise AuthenticationError.new AUTH_ERROR_MESSAGE - end + raise AuthenticationError, AUTH_ERROR_MESSAGE unless user unless QueryRoles.is_authorized_for_nonprofit?(user.id, source_token.event.nonprofit.id) - raise AuthenticationError.new AUTH_ERROR_MESSAGE + raise AuthenticationError, AUTH_ERROR_MESSAGE end end source_token.total_uses = source_token.total_uses + 1 source_token.save! - } + end else - raise ParamValidation::ValidationError.new "#{token} doesn't represent a valid source", {:key => :token} + raise ParamValidation::ValidationError.new "#{token} doesn't represent a valid source", key: :token end source_token end - def self.source_token_unexpired?(source_token) - if source_token.max_uses <= source_token.total_uses - return false - end - if source_token.expiration < Time.now - return false - end + return false if source_token.max_uses <= source_token.total_uses + return false if source_token.expiration < Time.now + true end @@ -57,4 +52,4 @@ module QuerySourceToken raise ParamValidation::ValidationError.new("The item for token #{data[:token]} is not a Card", key: :token) end end -end \ No newline at end of file +end diff --git a/lib/query/query_supporters.rb b/lib/query/query_supporters.rb index 017a9948..eab913da 100644 --- a/lib/query/query_supporters.rb +++ b/lib/query/query_supporters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qexpr' require 'psql' @@ -6,44 +8,42 @@ require 'format/currency' require 'format/csv' module QuerySupporters - # Query supporters and their donations and gift levels for a campaign def self.campaign_list_expr(np_id, campaign_id, query) expr = Qexpr.new.from('supporters') - .left_outer_join('donations', 'donations.supporter_id=supporters.id') - .left_outer_join('campaign_gifts', 'donations.id=campaign_gifts.donation_id') - .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') - .join_lateral(:payments, Qx + .left_outer_join('donations', 'donations.supporter_id=supporters.id') + .left_outer_join('campaign_gifts', 'donations.id=campaign_gifts.donation_id') + .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') + .join_lateral(:payments, Qx .select('payments.id, payments.gross_amount').from(:payments) .where('payments.donation_id = donations.id') .order_by('payments.created_at ASC') .limit(1).parse, true) - .join(Qx.select('id, profile_id').from('campaigns') + .join(Qx.select('id, profile_id').from('campaigns') .where("id IN (#{QueryCampaigns .get_campaign_and_children(campaign_id) .parse})").as('campaigns').parse, - 'donations.campaign_id=campaigns.id') - .join(Qx.select('users.id, profiles.id AS profiles_id, users.email') + 'donations.campaign_id=campaigns.id') + .join(Qx.select('users.id, profiles.id AS profiles_id, users.email') .from('users') .add_join('profiles', 'profiles.user_id = users.id') - .as("users").parse, "users.profiles_id=campaigns.profile_id") - .where("supporters.nonprofit_id=$id", id: np_id) - .group_by('supporters.id') - .order_by('MAX(donations.date) DESC') + .as('users').parse, 'users.profiles_id=campaigns.profile_id') + .where('supporters.nonprofit_id=$id', id: np_id) + .group_by('supporters.id') + .order_by('MAX(donations.date) DESC') - if query[:search].present? - expr = expr.where(%Q( + if query[:search].present? + expr = expr.where(%( supporters.name ILIKE $search OR supporters.email ILIKE $search OR campaign_gift_options.name ILIKE $search ), search: '%' + query[:search] + '%') end - return expr + expr end - - # Used in the campaign donor listing - def self.campaign_list(np_id, campaign_id, query) + # Used in the campaign donor listing + def self.campaign_list(np_id, campaign_id, query) limit = 50 offset = Qexpr.page_offset(limit, query[:page]) @@ -60,24 +60,24 @@ module QuerySupporters ) total_count = Psql.execute( - Qexpr.new.select("COUNT(s)") + Qexpr.new.select('COUNT(s)') .from(campaign_list_expr(np_id, campaign_id, query).remove(:order_by).select('supporters.id').as('s').parse) ).first['count'] - return { - data: data, - total_count: total_count, - remaining: Qexpr.remaining_count(total_count, limit, query[:page]) + { + data: data, + total_count: total_count, + remaining: Qexpr.remaining_count(total_count, limit, query[:page]) } - end + end def self.full_search_metrics(np_id, query) total_count = full_filter_expr(np_id, query) - .select("COUNT(supporters)") - .remove_clause(:order_by) - .execute.first['count'] + .select('COUNT(supporters)') + .remove_clause(:order_by) + .execute.first['count'] - return { + { total_count: total_count, remaining_count: Qexpr.remaining_count(total_count, 30, query[:page]) } @@ -94,40 +94,34 @@ module QuerySupporters "to_char(payments.max_date, 'MM/DD/YY') AS last_contribution", 'payments.sum AS total_raised' ] - if query[:select] - select += query[:select].split(',') - end + select += query[:select].split(',') if query[:select] supps = full_filter_expr(np_id, query) - .select(*select) - .paginate(query[:page].to_i, 30) - .execute + .select(*select) + .paginate(query[:page].to_i, 30) + .execute - return { data: supps } + { data: supps } end - - def self._full_search(np_id, query) select = [ - 'supporters.name', - 'supporters.email', - 'supporters.is_unsubscribed_from_emails', - 'supporters.id AS id', - 'tags.names AS tags', - "to_char(payments.max_date, 'MM/DD/YY') AS last_contribution", - 'payments.sum AS total_raised' + 'supporters.name', + 'supporters.email', + 'supporters.is_unsubscribed_from_emails', + 'supporters.id AS id', + 'tags.names AS tags', + "to_char(payments.max_date, 'MM/DD/YY') AS last_contribution", + 'payments.sum AS total_raised' ] - if query[:select] - select += query[:select].split(',') - end + select += query[:select].split(',') if query[:select] supps = full_filter_expr(np_id, query) - .select(*select) - .paginate(query[:page].to_i, query[:page_length].to_i) - .execute + .select(*select) + .paginate(query[:page].to_i, query[:page_length].to_i) + .execute - return { data: supps } + { data: supps } end # # Given a list of supporters, you may want to remove duplicates from those supporters. @@ -154,74 +148,73 @@ module QuerySupporters # return new_supporters # end - # Perform all filters and search for /nonprofits/id/supporters dashboard and export def self.full_filter_expr(np_id, query) payments_subquery = - Qx.select("supporter_id", "SUM(gross_amount)", "MAX(date) AS max_date", "MIN(date) AS min_date", "COUNT(*) AS count") - .from( - Qx.select("supporter_id", "date", "gross_amount") - .from(:payments) - .join(Qx.select('id') - .from(:supporters) - .where("supporters.nonprofit_id = $id and deleted != 'true'", id: np_id ) - .as("payments_to_supporters"), "payments_to_supporters.id = payments.supporter_id" - ) - .as("outer_from_payment_to_supporter") - .parse) - .group_by(:supporter_id) - .as(:payments) + Qx.select('supporter_id', 'SUM(gross_amount)', 'MAX(date) AS max_date', 'MIN(date) AS min_date', 'COUNT(*) AS count') + .from( + Qx.select('supporter_id', 'date', 'gross_amount') + .from(:payments) + .join(Qx.select('id') + .from(:supporters) + .where("supporters.nonprofit_id = $id and deleted != 'true'", id: np_id) + .as('payments_to_supporters'), 'payments_to_supporters.id = payments.supporter_id') + .as('outer_from_payment_to_supporter') + .parse + ) + .group_by(:supporter_id) + .as(:payments) - tags_subquery = Qx.select("tag_joins.supporter_id", "ARRAY_AGG(tag_masters.id) AS ids", "ARRAY_AGG(tag_masters.name::text) AS names") - .from(:tag_joins) - .join(:tag_masters, "tag_masters.id=tag_joins.tag_master_id") - .where("tag_masters.deleted IS NULL") - .group_by("tag_joins.supporter_id") - .as(:tags) + tags_subquery = Qx.select('tag_joins.supporter_id', 'ARRAY_AGG(tag_masters.id) AS ids', 'ARRAY_AGG(tag_masters.name::text) AS names') + .from(:tag_joins) + .join(:tag_masters, 'tag_masters.id=tag_joins.tag_master_id') + .where('tag_masters.deleted IS NULL') + .group_by('tag_joins.supporter_id') + .as(:tags) expr = Qx.select('supporters.id').from(:supporters) - .where( - ["supporters.nonprofit_id=$id", id: np_id.to_i], - ["supporters.deleted != true"] - ) - .left_join( - [tags_subquery, "tags.supporter_id=supporters.id"], - [payments_subquery, "payments.supporter_id=supporters.id"] - ) - .order_by('payments.max_date DESC NULLS LAST') + .where( + ['supporters.nonprofit_id=$id', id: np_id.to_i], + ['supporters.deleted != true'] + ) + .left_join( + [tags_subquery, 'tags.supporter_id=supporters.id'], + [payments_subquery, 'payments.supporter_id=supporters.id'] + ) + .order_by('payments.max_date DESC NULLS LAST') if query[:last_payment_after].present? - expr = expr.and_where("payments.max_date > $d", d: Chronic.parse(query[:last_payment_after])) + expr = expr.and_where('payments.max_date > $d', d: Chronic.parse(query[:last_payment_after])) end if query[:last_payment_before].present? - expr = expr.and_where("payments.max_date < $d", d: Chronic.parse(query[:last_payment_before])) + expr = expr.and_where('payments.max_date < $d', d: Chronic.parse(query[:last_payment_before])) end if query[:first_payment_after].present? - expr = expr.and_where("payments.min_date > $d", d: Chronic.parse(query[:first_payment_after])) + expr = expr.and_where('payments.min_date > $d', d: Chronic.parse(query[:first_payment_after])) end if query[:first_payment_before].present? - expr = expr.and_where("payments.min_date < $d", d: Chronic.parse(query[:first_payment_before])) + expr = expr.and_where('payments.min_date < $d', d: Chronic.parse(query[:first_payment_before])) end if query[:total_raised_greater_than].present? - expr = expr.and_where("payments.sum > $amount", amount: query[:total_raised_greater_than].to_i * 100) + expr = expr.and_where('payments.sum > $amount', amount: query[:total_raised_greater_than].to_i * 100) end if query[:total_raised_less_than].present? - expr = expr.and_where("payments.sum < $amount OR payments.supporter_id IS NULL", amount: query[:total_raised_less_than].to_i * 100) + expr = expr.and_where('payments.sum < $amount OR payments.supporter_id IS NULL', amount: query[:total_raised_less_than].to_i * 100) end - if ['week', 'month', 'quarter', 'year'].include? query[:has_contributed_during] + if %w[week month quarter year].include? query[:has_contributed_during] d = Time.current.send('beginning_of_' + query[:has_contributed_during]) - expr = expr.and_where("payments.max_date >= $d", d: d) + expr = expr.and_where('payments.max_date >= $d', d: d) end - if ['week', 'month', 'quarter', 'year'].include? query[:has_not_contributed_during] + if %w[week month quarter year].include? query[:has_not_contributed_during] d = Time.current.send('beginning_of_' + query[:has_not_contributed_during]) - expr = expr.and_where("payments.count = 0 OR payments.max_date <= $d", d: d) + expr = expr.and_where('payments.count = 0 OR payments.max_date <= $d', d: d) end if query[:MAX_payment_before].present? date_ago = Timespan::TimeUnits[query[:MAX_payment_before]].utc - expr = expr.and_where("payments.max_date < $date OR payments.count = 0", date: date_ago) + expr = expr.and_where('payments.max_date < $date OR payments.count = 0', date: date_ago) end if query[:search].present? - expr = expr.and_where(%Q( + expr = expr.and_where(%( supporters.name ILIKE $search OR supporters.email ILIKE $search OR supporters.organization ILIKE $search @@ -229,65 +222,66 @@ module QuerySupporters end if query[:notes].present? notes_subquery = Qx.select("STRING_AGG(content, ' ') as content, supporter_id") - .from(:supporter_notes) - .group_by(:supporter_id) - .as(:notes) - expr = expr.add_left_join(notes_subquery, "notes.supporter_id=supporters.id") - .and_where("to_tsvector('english', notes.content) @@ plainto_tsquery('english', $notes)", notes: query[:notes]) + .from(:supporter_notes) + .group_by(:supporter_id) + .as(:notes) + expr = expr.add_left_join(notes_subquery, 'notes.supporter_id=supporters.id') + .and_where("to_tsvector('english', notes.content) @@ plainto_tsquery('english', $notes)", notes: query[:notes]) end if query[:custom_fields].present? - c_f_subquery = Qx.select("STRING_AGG(value, ' ') as value", "supporter_id") - .from(:custom_field_joins) - .group_by("custom_field_joins.supporter_id") - .as(:custom_fields) - expr = expr.add_left_join(c_f_subquery, "custom_fields.supporter_id=supporters.id") - .and_where("to_tsvector('english', custom_fields.value) @@ plainto_tsquery('english', $custom_fields)", custom_fields: query[:custom_fields]) + c_f_subquery = Qx.select("STRING_AGG(value, ' ') as value", 'supporter_id') + .from(:custom_field_joins) + .group_by('custom_field_joins.supporter_id') + .as(:custom_fields) + expr = expr.add_left_join(c_f_subquery, 'custom_fields.supporter_id=supporters.id') + .and_where("to_tsvector('english', custom_fields.value) @@ plainto_tsquery('english', $custom_fields)", custom_fields: query[:custom_fields]) end if query[:location].present? - expr = expr.and_where("lower(supporters.city) LIKE $city OR lower(supporters.zip_code) LIKE $zip", city: query[:location].downcase, zip: query[:location].downcase) + expr = expr.and_where('lower(supporters.city) LIKE $city OR lower(supporters.zip_code) LIKE $zip', city: query[:location].downcase, zip: query[:location].downcase) end if query[:recurring].present? - rec_ps_subquery = Qx.select("payments.count", "payments.supporter_id") - .from(:payments) - .where("kind='RecurringDonation'") - .group_by("payments.supporter_id") - .as(:rec_ps) - expr = expr.add_left_join(rec_ps_subquery, "rec_ps.supporter_id=supporters.id") - .and_where('rec_ps.count > 0') + rec_ps_subquery = Qx.select('payments.count', 'payments.supporter_id') + .from(:payments) + .where("kind='RecurringDonation'") + .group_by('payments.supporter_id') + .as(:rec_ps) + expr = expr.add_left_join(rec_ps_subquery, 'rec_ps.supporter_id=supporters.id') + .and_where('rec_ps.count > 0') end if query[:ids].present? - expr = expr.and_where("supporters.id IN ($ids)", ids: query[:ids].split(",").map(&:to_i)) + expr = expr.and_where('supporters.id IN ($ids)', ids: query[:ids].split(',').map(&:to_i)) end if query[:select].present? - expr = expr.select(*query[:select].split(",").map{|x| Qx.quote_ident(x)}) + expr = expr.select(*query[:select].split(',').map { |x| Qx.quote_ident(x) }) end # Sort by supporters who have all of the list of tag names if query[:tags].present? tag_ids = (query[:tags].is_a?(String) ? query[:tags].split(',') : query[:tags]).map(&:to_i) - expr = expr.and_where("tags.ids @> ARRAY[$tag_ids]", tag_ids: tag_ids) + expr = expr.and_where('tags.ids @> ARRAY[$tag_ids]', tag_ids: tag_ids) end if query[:campaign_id].present? - expr = expr.add_join("donations", "donations.supporter_id=supporters.id AND donations.campaign_id IN (#{QueryCampaigns + expr = expr.add_join('donations', "donations.supporter_id=supporters.id AND donations.campaign_id IN (#{QueryCampaigns .get_campaign_and_children(query[:campaign_id].to_i) .parse})") end if query[:event_id].present? - select_tickets_supporters = Qx.select("event_ticket_supporters.supporter_id") - .from( - "#{Qx.select("MAX(tickets.event_id) AS event_id", "tickets.supporter_id") - .from(:tickets) - .where("event_id = $event_id", event_id: query[:event_id]) - .group_by(:supporter_id).as('event_ticket_supporters').parse}" - ) + select_tickets_supporters = Qx.select('event_ticket_supporters.supporter_id') + .from( + Qx.select('MAX(tickets.event_id) AS event_id', 'tickets.supporter_id') + .from(:tickets) + .where('event_id = $event_id', event_id: query[:event_id]) + .group_by(:supporter_id).as('event_ticket_supporters').parse.to_s + ) select_donation_supporters = - Qx.select("event_donation_supporters.supporter_id") - .from( - "#{Qx.select("MAX(donations.event_id) AS event_id", "donations.supporter_id") - .from(:donations) - .where("event_id = $event_id", event_id: query[:event_id] ) - .group_by(:supporter_id).as('event_donation_supporters').parse}") + Qx.select('event_donation_supporters.supporter_id') + .from( + Qx.select('MAX(donations.event_id) AS event_id', 'donations.supporter_id') + .from(:donations) + .where('event_id = $event_id', event_id: query[:event_id]) + .group_by(:supporter_id).as('event_donation_supporters').parse.to_s + ) union_expr = "( #{select_tickets_supporters.parse} @@ -296,39 +290,38 @@ UNION DISTINCT ) AS event_supporters" expr = expr - .add_join( - union_expr, - "event_supporters.supporter_id=supporters.id" - ) + .add_join( + union_expr, + 'event_supporters.supporter_id=supporters.id' + ) end - if ['asc', 'desc'].include? query[:sort_name] - expr = expr.order_by(["supporters.name", query[:sort_name]]) + if %w[asc desc].include? query[:sort_name] + expr = expr.order_by(['supporters.name', query[:sort_name]]) end - if ['asc', 'desc'].include? query[:sort_contributed] - expr = expr.and_where("payments.sum > 0").order_by(["payments.sum", query[:sort_contributed]]) + if %w[asc desc].include? query[:sort_contributed] + expr = expr.and_where('payments.sum > 0').order_by(['payments.sum', query[:sort_contributed]]) end - if ['asc', 'desc'].include? query[:sort_last_payment] - expr = expr.order_by(["payments.max_date", "#{query[:sort_last_payment].upcase} NULLS LAST"]) + if %w[asc desc].include? query[:sort_last_payment] + expr = expr.order_by(['payments.max_date', "#{query[:sort_last_payment].upcase} NULLS LAST"]) end - return expr + expr end - def self.for_export_enumerable(npo_id, query, chunk_limit=35000) - ParamValidation.new({npo_id: npo_id, query:query}, {npo_id: {required: true, is_int: true}, - query: {required:true, is_hash: true}}) + def self.for_export_enumerable(npo_id, query, chunk_limit = 35_000) + ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, + query: { required: true, is_hash: true }) - return QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| + QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_export(npo_id, query, offset, limit, skip_header) end - end - def self.get_chunk_of_export(np_id, query, offset=nil, limit=nil, skip_header=false) - return QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do + def self.get_chunk_of_export(np_id, query, offset = nil, limit = nil, skip_header = false) + QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do expr = full_filter_expr(np_id, query) selects = supporter_export_selections.concat([ - '(payments.sum / 100)::money::text AS total_contributed', - 'supporters.id AS id' + '(payments.sum / 100)::money::text AS total_contributed', + 'supporters.id AS id' ]) if query[:export_custom_fields] # Add a select/csv-column for every custom field master for this nonprofit @@ -340,57 +333,53 @@ UNION DISTINCT # ... ids = query[:export_custom_fields].split(',').map(&:to_i) if ids.any? - cfms = Qx.select("name", "id").from(:custom_field_masters).where(nonprofit_id: np_id).and_where("id IN ($ids)", ids: ids).ex + cfms = Qx.select('name', 'id').from(:custom_field_masters).where(nonprofit_id: np_id).and_where('id IN ($ids)', ids: ids).ex cfms.compact.map do |cfm| - table_alias = "cfjs_#{cfm['name'].gsub(/\$/, "")}" + table_alias = "cfjs_#{cfm['name'].delete('$')}" table_alias_quot = "\"#{table_alias}\"" - field_join_subq = Qx.select("STRING_AGG(value, ',') as value", "supporter_id") - .from("custom_field_joins") - .join("custom_field_masters" , "custom_field_masters.id=custom_field_joins.custom_field_master_id") - .where("custom_field_masters.id=$id", id: cfm['id']) - .group_by(:supporter_id) - .as(table_alias) + field_join_subq = Qx.select("STRING_AGG(value, ',') as value", 'supporter_id') + .from('custom_field_joins') + .join('custom_field_masters', 'custom_field_masters.id=custom_field_joins.custom_field_master_id') + .where('custom_field_masters.id=$id', id: cfm['id']) + .group_by(:supporter_id) + .as(table_alias) expr.add_left_join(field_join_subq, "#{table_alias_quot}.supporter_id=supporters.id") selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm['name']}\""]) end end end - - get_last_payment_query = Qx.select('supporter_id', "MAX(date) AS date") - .from(:payments) - .group_by("supporter_id") - .as("last_payment") + get_last_payment_query = Qx.select('supporter_id', 'MAX(date) AS date') + .from(:payments) + .group_by('supporter_id') + .as('last_payment') expr.add_left_join(get_last_payment_query, 'last_payment.supporter_id = supporters.id') selects = selects.concat(['last_payment.date as "Last Payment Received"']) - - supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", "supporter_notes.supporter_id") - .from(:supporter_notes) - .group_by('supporter_notes.supporter_id') - .as("supporter_note_query") + supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", 'supporter_notes.supporter_id') + .from(:supporter_notes) + .group_by('supporter_notes.supporter_id') + .as('supporter_note_query') expr.add_left_join(supporter_note_query, 'supporter_note_query.supporter_id=supporters.id') - selects = selects.concat(["supporter_note_query.notes AS notes"]).concat(["ARRAY_TO_STRING(tags.names, ',') as tags"]) - + selects = selects.concat(['supporter_note_query.notes AS notes']).concat(["ARRAY_TO_STRING(tags.names, ',') as tags"]) expr.select(selects) end end - def self.supporter_note_export_enumerable(npo_id, query, chunk_limit=35000) - ParamValidation.new({npo_id: npo_id, query:query}, {npo_id: {required: true, is_int: true}, - query: {required:true, is_hash: true}}) + def self.supporter_note_export_enumerable(npo_id, query, chunk_limit = 35_000) + ParamValidation.new({ npo_id: npo_id, query: query }, npo_id: { required: true, is_int: true }, + query: { required: true, is_hash: true }) - return QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| + QxQueryChunker.for_export_enumerable(chunk_limit) do |offset, limit, skip_header| get_chunk_of_supporter_note_export(npo_id, query, offset, limit, skip_header) end - end - def self.get_chunk_of_supporter_note_export(np_id, query, offset=nil, limit=nil, skip_header=false) - return QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do + def self.get_chunk_of_supporter_note_export(np_id, query, offset = nil, limit = nil, skip_header = false) + QxQueryChunker.get_chunk_of_query(offset, limit, skip_header) do expr = full_filter_expr(np_id, query) supporter_note_select = [ 'supporters.id', @@ -408,41 +397,41 @@ UNION DISTINCT def self.for_export(np_id, query) expr = full_filter_expr(np_id, query) selects = supporter_export_selections.concat([ - '(payments.sum / 100)::money::text AS total_contributed', - 'supporters.id AS id' - ]) + '(payments.sum / 100)::money::text AS total_contributed', + 'supporters.id AS id' + ]) if query[:export_custom_fields] # Add a select/csv-column for every custom field master for this nonprofit # and add a left join for every custom field master - # eg if the npo has a custom field like Employer with id 99, then the query will be - # SELECT export_cfj_Employer.value AS Employer, ... - # FROM supporters + # eg if the npo has a custom field like Employer with id 99, then the query will be + # SELECT export_cfj_Employer.value AS Employer, ... + # FROM supporters # LEFT JOIN custom_field_joins AS export_cfj_Employer ON export_cfj_Employer.supporter_id=supporters.id AND export_cfj_Employer.custom_field_master_id=99 # ... ids = query[:export_custom_fields].split(',').map(&:to_i) if ids.any? - cfms = Qx.select("name", "id").from(:custom_field_masters).where(nonprofit_id: np_id).and_where("id IN ($ids)", ids: ids).ex + cfms = Qx.select('name', 'id').from(:custom_field_masters).where(nonprofit_id: np_id).and_where('id IN ($ids)', ids: ids).ex cfms.compact.map do |cfm| - table_alias = "cfjs_#{cfm['name'].gsub(/\$/, "")}" + table_alias = "cfjs_#{cfm['name'].delete('$')}" table_alias_quot = "\"#{table_alias}\"" - field_join_subq = Qx.select("STRING_AGG(value, ',') as value", "supporter_id") - .from("custom_field_joins") - .join("custom_field_masters" , "custom_field_masters.id=custom_field_joins.custom_field_master_id") - .where("custom_field_masters.id=$id", id: cfm['id']) - .group_by(:supporter_id) - .as(table_alias) + field_join_subq = Qx.select("STRING_AGG(value, ',') as value", 'supporter_id') + .from('custom_field_joins') + .join('custom_field_masters', 'custom_field_masters.id=custom_field_joins.custom_field_master_id') + .where('custom_field_masters.id=$id', id: cfm['id']) + .group_by(:supporter_id) + .as(table_alias) expr.add_left_join(field_join_subq, "#{table_alias_quot}.supporter_id=supporters.id") selects = selects.concat(["#{table_alias_quot}.value AS \"#{cfm['name']}\""]) end end end - supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", "supporter_notes.supporter_id") - .from(:supporter_notes) - .group_by('supporter_notes.supporter_id') - .as("supporter_note_query") + supporter_note_query = Qx.select("STRING_AGG(supporter_notes.created_at || ': ' || supporter_notes.content, '\r\n' ORDER BY supporter_notes.created_at DESC) as notes", 'supporter_notes.supporter_id') + .from(:supporter_notes) + .group_by('supporter_notes.supporter_id') + .as('supporter_note_query') expr.add_left_join(supporter_note_query, 'supporter_note_query.supporter_id=supporters.id') - selects = selects.concat(["supporter_note_query.notes AS notes"]) + selects = selects.concat(['supporter_note_query.notes AS notes']) expr.select(selects).execute(format: 'csv') end @@ -451,17 +440,17 @@ UNION DISTINCT [ "substring(trim(both from supporters.name) from '^.+ ([^\s]+)$') AS \"Last Name\"", "substring(trim(both from supporters.name) from '^(.+) [^\s]+$') AS \"First Name\"", - "trim(both from supporters.name) AS \"Full Name\"", - "supporters.organization AS \"Organization\"", - "supporters.email \"Email\"", - "supporters.phone \"Phone\"", - "supporters.address \"Address\"", - "supporters.city \"City\"", - "supporters.state_code \"State\"", - "supporters.zip_code \"Postal Code\"", - "supporters.country \"Country\"", - "supporters.anonymous \"Anonymous?\"", - "supporters.id \"Supporter ID\"" + 'trim(both from supporters.name) AS "Full Name"', + 'supporters.organization AS "Organization"', + 'supporters.email "Email"', + 'supporters.phone "Phone"', + 'supporters.address "Address"', + 'supporters.city "City"', + 'supporters.state_code "State"', + 'supporters.zip_code "Postal Code"', + 'supporters.country "Country"', + 'supporters.anonymous "Anonymous?"', + 'supporters.id "Supporter ID"' ] end @@ -469,9 +458,9 @@ UNION DISTINCT # Partial sql expression def self.dupes_expr(np_id) - Qx.select("ARRAY_AGG(id) AS ids") + Qx.select('ARRAY_AGG(id) AS ids') .from(:supporters) - .where("nonprofit_id=$id", id: np_id) + .where('nonprofit_id=$id', id: np_id) .and_where("deleted='f' OR deleted IS NULL") .having('COUNT(id) > 1') end @@ -483,7 +472,7 @@ UNION DISTINCT # (each sub-array is a group of duplicates) def self.dupes_on_email(np_id) dupes_expr(np_id) - .and_where("email IS NOT NULL") + .and_where('email IS NOT NULL') .and_where("email != ''") .group_by(:email) .execute(format: 'csv')[1..-1] @@ -493,7 +482,7 @@ UNION DISTINCT # Find all duplicate supporters by the name column def self.dupes_on_name(np_id) dupes_expr(np_id) - .and_where("name IS NOT NULL") + .and_where('name IS NOT NULL') .group_by(:name) .execute(format: 'csv')[1..-1] .map(&:flatten) @@ -504,7 +493,7 @@ UNION DISTINCT def self.dupes_on_name_and_email(np_id) dupes_expr(np_id) .and_where("name IS NOT NULL AND email IS NOT NULL AND email != ''") - .group_by("name, email") + .group_by('name, email') .execute(format: 'csv')[1..-1] .map(&:flatten) end @@ -514,22 +503,22 @@ UNION DISTINCT # Only including payments for the given year def self.end_of_year_donor_report(np_id, year) supporter_expr = Qexpr.new - .select( supporter_export_selections.concat(["(payments.sum / 100.0)::money::text AS \"Total Contributions #{year}\"", "supporters.id"]) ) - .from(:supporters) - .join(Qexpr.new - .select("SUM(gross_amount)", "supporter_id") + .select(supporter_export_selections.concat(["(payments.sum / 100.0)::money::text AS \"Total Contributions #{year}\"", 'supporters.id'])) + .from(:supporters) + .join(Qexpr.new + .select('SUM(gross_amount)', 'supporter_id') .from(:payments) .group_by(:supporter_id) - .where("date >= $date", date: "#{year}-01-01 00:00:00 UTC") - .where("date < $date", date: "#{year+1}-01-01 00:00:00 UTC") - .as(:payments), "payments.supporter_id=supporters.id") - .where('payments.sum > 25000') - .as('supporters') + .where('date >= $date', date: "#{year}-01-01 00:00:00 UTC") + .where('date < $date', date: "#{year + 1}-01-01 00:00:00 UTC") + .as(:payments), 'payments.supporter_id=supporters.id') + .where('payments.sum > 25000') + .as('supporters') Psql.execute_vectors( Qexpr.new .select( - "supporters.*", + 'supporters.*', '(payments.gross_amount / 100.0)::money::text AS "Donation Amount"', 'payments.date AS "Donation Date"', 'payments.towards AS "Designation"' @@ -538,86 +527,84 @@ UNION DISTINCT .join(supporter_expr, 'supporters.id = payments.supporter_id') .where('payments.nonprofit_id = $id', id: np_id) .where('payments.date >= $date', date: "#{year}-01-01 00:00:00 UTC") - .where('payments.date < $date', date: "#{year+1}-01-01 00:00:00 UTC") - .order_by("supporters.\"MAX Name\", payments.date DESC") + .where('payments.date < $date', date: "#{year + 1}-01-01 00:00:00 UTC") + .order_by('supporters."MAX Name", payments.date DESC') ) end - # returns an array of common selects for supporters # which gets concated with an optional array of additional selects # used for merging supporters, crm profile and info card def self.profile_selects(arr = []) - ["supporters.id", - "supporters.name", - "supporters.email", - "supporters.address", - "supporters.state_code", - "supporters.city", - "supporters.zip_code", - "supporters.country", - "supporters.organization", - "supporters.phone"] + arr + ['supporters.id', + 'supporters.name', + 'supporters.email', + 'supporters.address', + 'supporters.state_code', + 'supporters.city', + 'supporters.zip_code', + 'supporters.country', + 'supporters.organization', + 'supporters.phone'] + arr end - # used on crm profile and info card - def self.profile_payments_subquery - Qx.select("supporter_id", "SUM(gross_amount)", "COUNT(id) AS count") - .from("payments") - .group_by("supporter_id") - .as("payments") + def self.profile_payments_subquery + Qx.select('supporter_id', 'SUM(gross_amount)', 'COUNT(id) AS count') + .from('payments') + .group_by('supporter_id') + .as('payments') end - # Get a large set of detailed info for a single supporter, to be displayed in # the side panel details of the supporter listing after clicking a row. def self.for_crm_profile(npo_id, ids) selects = [ - "supporters.created_at", - "supporters.imported_at", - "supporters.anonymous AS anon", - "supporters.is_unsubscribed_from_emails", - "COALESCE(MAX(payments.sum), 0) AS raised", - "COALESCE(MAX(payments.count), 0) AS payments_count", - "COALESCE(COUNT(recurring_donations.active), 0) AS recurring_donations_count", - "MAX(full_contact_infos.full_name) AS fc_full_name", - "MAX(full_contact_infos.age) AS fc_age", - "MAX(full_contact_infos.location_general) AS fc_location_general", - "MAX(full_contact_infos.websites) AS fc_websites"] + 'supporters.created_at', + 'supporters.imported_at', + 'supporters.anonymous AS anon', + 'supporters.is_unsubscribed_from_emails', + 'COALESCE(MAX(payments.sum), 0) AS raised', + 'COALESCE(MAX(payments.count), 0) AS payments_count', + 'COALESCE(COUNT(recurring_donations.active), 0) AS recurring_donations_count', + 'MAX(full_contact_infos.full_name) AS fc_full_name', + 'MAX(full_contact_infos.age) AS fc_age', + 'MAX(full_contact_infos.location_general) AS fc_location_general', + 'MAX(full_contact_infos.websites) AS fc_websites' + ] Qx.select(*QuerySupporters.profile_selects(selects)) - .from("supporters") + .from('supporters') .left_join( - ["donations", "donations.supporter_id=supporters.id"], - ["full_contact_infos", "full_contact_infos.supporter_id=supporters.id"], - ["recurring_donations", "recurring_donations.donation_id=donations.id"], - [QuerySupporters.profile_payments_subquery, "payments.supporter_id=supporters.id"]) - .group_by("supporters.id") - .where("supporters.id IN ($ids)", ids: ids) - .and_where("supporters.nonprofit_id = $id", id: npo_id) + ['donations', 'donations.supporter_id=supporters.id'], + ['full_contact_infos', 'full_contact_infos.supporter_id=supporters.id'], + ['recurring_donations', 'recurring_donations.donation_id=donations.id'], + [QuerySupporters.profile_payments_subquery, 'payments.supporter_id=supporters.id'] + ) + .group_by('supporters.id') + .where('supporters.id IN ($ids)', ids: ids) + .and_where('supporters.nonprofit_id = $id', id: npo_id) .execute end def self.for_info_card(id) - selects = ["COALESCE(MAX(payments.sum), 0) AS raised"] + selects = ['COALESCE(MAX(payments.sum), 0) AS raised'] Qx.select(*QuerySupporters.profile_selects(selects)) - .from("supporters") - .left_join([QuerySupporters.profile_payments_subquery, "payments.supporter_id=supporters.id"]) - .group_by("supporters.id") - .where("supporters.id=$id", id: id) + .from('supporters') + .left_join([QuerySupporters.profile_payments_subquery, 'payments.supporter_id=supporters.id']) + .group_by('supporters.id') + .where('supporters.id=$id', id: id) .execute.first end def self.merge_data(ids) Qx.select(*QuerySupporters.profile_selects) - .from("supporters") - .group_by("supporters.id") - .where("supporters.id IN ($ids)", ids: ids.split(',')) + .from('supporters') + .group_by('supporters.id') + .where('supporters.id IN ($ids)', ids: ids.split(',')) .execute end - def self.year_aggregate_report(npo_id, time_range_params) npo_id = npo_id.to_i @@ -626,10 +613,9 @@ UNION DISTINCT rescue ArgumentError => e raise ParamValidation::ValidationError.new(e.message, {}) end - ParamValidation.new({npo_id: npo_id}, { - npo_id: {required: true, is_integer: true} - }) - aggregate_dons = %Q( + ParamValidation.new({ npo_id: npo_id }, + npo_id: { required: true, is_integer: true }) + aggregate_dons = %( array_to_string( array_agg( payments.date::date || ' ' || @@ -642,51 +628,46 @@ UNION DISTINCT ) AS "Payment History" ) selects = supporter_export_selections.concat([ - "SUM(payments.gross_amount / 100)::text::money AS \"Total Payments\"", - "MAX(payments.date)::date AS \"Last Payment Date\"", - "AVG(payments.gross_amount / 100)::text::money AS \"Average Payment\"", - aggregate_dons - ]) - return Qx.select(selects) + 'SUM(payments.gross_amount / 100)::text::money AS "Total Payments"', + 'MAX(payments.date)::date AS "Last Payment Date"', + 'AVG(payments.gross_amount / 100)::text::money AS "Average Payment"', + aggregate_dons + ]) + Qx.select(selects) .from(:supporters) - .join("payments", "payments.supporter_id=supporters.id AND payments.date::date >= $min_date AND payments.date::date < $max_date",:min_date => min_date.to_date, :max_date => max_date.to_date ) + .join('payments', 'payments.supporter_id=supporters.id AND payments.date::date >= $min_date AND payments.date::date < $max_date', min_date: min_date.to_date, max_date: max_date.to_date) .where('supporters.nonprofit_id=$id', id: npo_id) - .group_by("supporters.id") + .group_by('supporters.id') .order_by("substring(trim(supporters.name) from '^.+ ([^\s]+)$')") .execute(format: 'csv') end - def self.get_min_or_max_dates_for_range(time_range_params) - begin - if (time_range_params[:year]) - if (time_range_params[:year].is_a?(Integer)) - return DateTime.new(time_range_params[:year], 1, 1), DateTime.new(time_range_params[:year]+1, 1, 1) - end - if (time_range_params[:year].is_a?(String)) - wip = time_range_params[:year].to_i - return DateTime.new(wip, 1, 1), DateTime.new(wip+1, 1, 1) - end + if time_range_params[:year] + if time_range_params[:year].is_a?(Integer) + return DateTime.new(time_range_params[:year], 1, 1), DateTime.new(time_range_params[:year] + 1, 1, 1) end - if (time_range_params[:start]) - start = parse_convert_datetime(time_range_params[:start]) - if (time_range_params[:end]) - end_datetime = parse_convert_datetime(time_range_params[:end]) - end - unless start.nil? - return start, end_datetime ? end_datetime : start + 1.year - end + if time_range_params[:year].is_a?(String) + wip = time_range_params[:year].to_i + return DateTime.new(wip, 1, 1), DateTime.new(wip + 1, 1, 1) end - raise ArgumentError.new("no valid time range provided") - rescue - raise ArgumentError.new("no valid time range provided") end + if time_range_params[:start] + start = parse_convert_datetime(time_range_params[:start]) + if time_range_params[:end] + end_datetime = parse_convert_datetime(time_range_params[:end]) + end + return start, end_datetime || start + 1.year unless start.nil? + end + raise ArgumentError, 'no valid time range provided' + rescue StandardError + raise ArgumentError, 'no valid time range provided' end def self.tag_joins(nonprofit_id, supporter_id) - Qx.select('tag_masters.id', 'tag_masters.name') + Qx.select('tag_masters.id', 'tag_masters.name') .from('tag_joins') .left_join('tag_masters', 'tag_masters.id = tag_joins.tag_master_id') .where( @@ -700,25 +681,18 @@ UNION DISTINCT # this is inefficient, don't use in live code def self.find_supporters_with_multiple_recurring_donations_evil_way(npo_id) supporters = Supporter.where('supporters.nonprofit_id = ?', npo_id).includes(:recurring_donations) - supporters.select{|s| s.recurring_donations.length > 1} + supporters.select { |s| s.recurring_donations.length > 1 } end # this is inefficient, don't use in live code def self.find_supporters_with_multiple_active_recurring_donations_evil_way(npo_id) supporters = Supporter.where('supporters.nonprofit_id = ?', npo_id).includes(:recurring_donations) - supporters.select{|s| s.recurring_donations.select{|rd| rd.active }.length > 1} + supporters.select { |s| s.recurring_donations.select(&:active).length > 1 } end def self.parse_convert_datetime(date) - if (date.is_a?(DateTime)) - return date - end - if (date.is_a?(Date)) - return date.to_datetime - end - if(date.is_a?(String)) - return DateTime.parse(date) - end + return date if date.is_a?(DateTime) + return date.to_datetime if date.is_a?(Date) + return DateTime.parse(date) if date.is_a?(String) end end - diff --git a/lib/query/query_ticket_levels.rb b/lib/query/query_ticket_levels.rb index 6e2fea0e..6e60d0a0 100644 --- a/lib/query/query_ticket_levels.rb +++ b/lib/query/query_ticket_levels.rb @@ -1,52 +1,52 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'hashie' module QueryTicketLevels - # Given an array of ticket hashes, where each hash has a ticket_level_id and a quantity, # calculate the gross amount for all the tickets # # This could probably be more efficient. I didn't think of a way to calculate it within the query itself. # Although I think it's O(n), and n will always be quite small (the number of tickets someone buys) def self.gross_amount_from_tickets(tickets, discount_id) - amounts = TicketLevel.where('id IN (?)', tickets.map{|h| h['ticket_level_id']}).map{|i| [i.id, i.amount]}.to_h - total = tickets.map{|t| amounts[t['ticket_level_id'].to_i].to_i * t['quantity'].to_i}.sum + amounts = TicketLevel.where('id IN (?)', tickets.map { |h| h['ticket_level_id'] }).map { |i| [i.id, i.amount] }.to_h + total = tickets.map { |t| amounts[t['ticket_level_id'].to_i].to_i * t['quantity'].to_i }.sum if discount_id perc = EventDiscount.find(discount_id).percent - total = total - (total * (perc / 100.0)).round + total -= (total * (perc / 100.0)).round end - return total + total end def self.with_event_id(event_id, is_admin) - expr = Qx.select("ticket_levels.*", "SUM(tickets.quantity) AS quantity") - .from(:ticket_levels) - .left_join([:tickets, "ticket_levels.id=tickets.ticket_level_id"]) - .group_by("ticket_levels.id") - .where("ticket_levels.event_id = $id", id: event_id) - .order_by("ticket_levels.order ASC, coalesce(ticket_levels.amount, 'Infinity'::float) ASC, LOWER(ticket_levels.name) ASC") # This puts free ticket levels at the bottom + expr = Qx.select('ticket_levels.*', 'SUM(tickets.quantity) AS quantity') + .from(:ticket_levels) + .left_join([:tickets, 'ticket_levels.id=tickets.ticket_level_id']) + .group_by('ticket_levels.id') + .where('ticket_levels.event_id = $id', id: event_id) + .order_by("ticket_levels.order ASC, coalesce(ticket_levels.amount, 'Infinity'::float) ASC, LOWER(ticket_levels.name) ASC") # This puts free ticket levels at the bottom - if !is_admin - expr = expr.and_where("coalesce(ticket_levels.admin_only, FALSE) = FALSE") + unless is_admin + expr = expr.and_where('coalesce(ticket_levels.admin_only, FALSE) = FALSE') end - return expr.execute + expr.execute end def self.verify_tickets_available(tickets) - tickets.each{|data| - if (data[:quantity] != 0) - tl = TicketLevel.find(data[:ticket_level_id]) - if tl.limit && tl.limit > 0 - already_sold = Ticket.where('ticket_level_id = ?', data[:ticket_level_id]).sum('tickets.quantity') - unless (already_sold + data[:quantity]) <= tl.limit - raise NotEnoughQuantityError.new(TicketLevel, data[:ticket_level_id], data[:quantity], "Oops! We sold out some of the tickets you wanted before ordering. Please refresh to see what tickets are still available.") - end - end - end - } - end + tickets.each do |data| + next unless data[:quantity] != 0 + tl = TicketLevel.find(data[:ticket_level_id]) + next unless tl.limit && tl.limit > 0 + + already_sold = Ticket.where('ticket_level_id = ?', data[:ticket_level_id]).sum('tickets.quantity') + unless (already_sold + data[:quantity]) <= tl.limit + raise NotEnoughQuantityError.new(TicketLevel, data[:ticket_level_id], data[:quantity], 'Oops! We sold out some of the tickets you wanted before ordering. Please refresh to see what tickets are still available.') + end + end + end end diff --git a/lib/query/query_tickets.rb b/lib/query/query_tickets.rb index f8582893..fc7fb696 100644 --- a/lib/query/query_tickets.rb +++ b/lib/query/query_tickets.rb @@ -1,72 +1,72 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueryTickets - def self.attendees_expr(event_id, query) expr = Qexpr.new - .from('tickets') - .where("coalesce(tickets.deleted, FALSE) = FALSE") - .left_outer_join("event_discounts", "event_discounts.id=tickets.event_discount_id") - .left_outer_join( - Qexpr.new.select("*") - .from(:supporters).group_by("id").as("supporters"), - 'tickets.supporter_id=supporters.id' - ) - .left_outer_join("charges", "charges.id=tickets.charge_id") - .left_outer_join( - Qexpr.new.select("charge_id", "SUM(coalesce(amount, 0)) AS amount") - .from(:refunds) - .group_by(:charge_id) - .as(:refunds), - "refunds.charge_id=charges.id" - ) - .left_outer_join( - Qexpr.new.select("id", "name", "amount") - .from(:ticket_levels).group_by("id").as("ticket_levels"), - 'tickets.ticket_level_id=ticket_levels.id' - ) - .left_outer_join( - Qexpr.new.select('token', 'tokenizable_id').from(:source_tokens).group_by( 'token', 'tokenizable_id').as('source_tokens'), - 'tickets.source_token_id=source_tokens.token' - ) - .left_outer_join( - # TODO this does not support anything other than cards! - Qexpr.new.select('id', 'name').from(:cards).group_by('id', 'name').as('cards'), - 'source_tokens.tokenizable_id = cards.id' - ) - .left_outer_join( - Qexpr.new.select('supporter_id', 'MAX(event_id) AS event_id', 'SUM(amount) AS total_amount') - .from(:donations).where("event_id=$id", id: event_id).group_by("supporter_id").as(:donations), - "donations.supporter_id=supporters.id AND donations.event_id=$id", id: event_id - ) - .where('tickets.event_id=$id', id: event_id) - .order_by('tickets.bid_id DESC') + .from('tickets') + .where('coalesce(tickets.deleted, FALSE) = FALSE') + .left_outer_join('event_discounts', 'event_discounts.id=tickets.event_discount_id') + .left_outer_join( + Qexpr.new.select('*') + .from(:supporters).group_by('id').as('supporters'), + 'tickets.supporter_id=supporters.id' + ) + .left_outer_join('charges', 'charges.id=tickets.charge_id') + .left_outer_join( + Qexpr.new.select('charge_id', 'SUM(coalesce(amount, 0)) AS amount') + .from(:refunds) + .group_by(:charge_id) + .as(:refunds), + 'refunds.charge_id=charges.id' + ) + .left_outer_join( + Qexpr.new.select('id', 'name', 'amount') + .from(:ticket_levels).group_by('id').as('ticket_levels'), + 'tickets.ticket_level_id=ticket_levels.id' + ) + .left_outer_join( + Qexpr.new.select('token', 'tokenizable_id').from(:source_tokens).group_by('token', 'tokenizable_id').as('source_tokens'), + 'tickets.source_token_id=source_tokens.token' + ) + .left_outer_join( + # TODO: this does not support anything other than cards! + Qexpr.new.select('id', 'name').from(:cards).group_by('id', 'name').as('cards'), + 'source_tokens.tokenizable_id = cards.id' + ) + .left_outer_join( + Qexpr.new.select('supporter_id', 'MAX(event_id) AS event_id', 'SUM(amount) AS total_amount') + .from(:donations).where('event_id=$id', id: event_id).group_by('supporter_id').as(:donations), + 'donations.supporter_id=supporters.id AND donations.event_id=$id', id: event_id + ) + .where('tickets.event_id=$id', id: event_id) + .order_by('tickets.bid_id DESC') if query[:search].present? query[:search] = "%#{query[:search].downcase.split(' ').join('%')}%" - expr = expr.where(%Q( + expr = expr.where(%( lower(supporters.name) LIKE $search OR lower(supporters.email) LIKE $search OR lower(ticket_levels.name) LIKE $search ), search: '%' + query[:search] + '%') end - if ['asc', 'desc'].include? query[:sort_attendee] + if %w[asc desc].include? query[:sort_attendee] expr = expr.order_by("lower(supporters.name) #{query[:sort_attendee]} NULLS LAST") end - if ['asc', 'desc'].include? query[:sort_id] + if %w[asc desc].include? query[:sort_id] expr = expr.order_by("tickets.bid_id #{query[:sort_id]}") end - if ['asc', 'desc'].include? query[:sort_note] + if %w[asc desc].include? query[:sort_note] expr = expr.order_by("lower(tickets.note) #{query[:sort_note]} NULLS LAST") end - if ['asc', 'desc'].include? query[:sort_ticket_level] + if %w[asc desc].include? query[:sort_ticket_level] expr = expr.order_by("lower(ticket_levels.name) #{query[:sort_ticket_level]} NULLS LAST") end - if ['asc', 'desc'].include? query[:sort_donation] + if %w[asc desc].include? query[:sort_donation] expr = expr.order_by("total_donations #{query[:sort_donation]} NULLS LAST") end - return expr + expr end - def self.attendees_list(event_id, query) limit = 30 offset = Qexpr.page_offset(limit, query[:page]) @@ -78,44 +78,42 @@ module QueryTickets ) total_count = Psql.execute( - Qexpr.new.select("COUNT(ts)") + Qexpr.new.select('COUNT(ts)') .from(attendees_expr(event_id, query) .remove(:order_by).select('tickets.id'), 'ts') ).first['count'] - #TODO this worries me. Seems like a recipe for slow returns... perhaps some caching of the tokens every so often? - data.each{|i| - unless (i['source_token_id'] && QuerySourceToken.source_token_unexpired?(SourceToken.find(i['source_token_id']))) + # TODO: this worries me. Seems like a recipe for slow returns... perhaps some caching of the tokens every so often? + data.each do |i| + unless i['source_token_id'] && QuerySourceToken.source_token_unexpired?(SourceToken.find(i['source_token_id'])) i['source_token_id'] = nil end - } + end - return { + { data: data, total_count: total_count, remaining: Qexpr.remaining_count(total_count, limit, query[:page]) } end - def self.for_export(event_id, query) Psql.execute_vectors( attendees_expr(event_id, query) .select([ - "tickets.bid_id AS id", - "ticket_levels.name AS ticket_level", - "MONEY((coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) / 100.0) AS ticket_cost", - "MONEY(coalesce(donations.total_amount, 0) / 100.0) AS total_donations", - "tickets.quantity", - "tickets.checked_in AS \"Checked In?\"", - "tickets.note", + 'tickets.bid_id AS id', + 'ticket_levels.name AS ticket_level', + 'MONEY((coalesce(charges.amount, 0) - coalesce(refunds.amount, 0)) / 100.0) AS ticket_cost', + 'MONEY(coalesce(donations.total_amount, 0) / 100.0) AS total_donations', + 'tickets.quantity', + 'tickets.checked_in AS "Checked In?"', + 'tickets.note', "CASE WHEN event_discounts.id IS NULL THEN 'None' ELSE concat(event_discounts.name, ' (', event_discounts.percent, '%)') END AS \"Discount\"", "CASE WHEN tickets.card_id IS NULL OR tickets.card_id = 0 THEN '' ELSE 'YES' END AS \"Card Saved?\"" ].concat(QuerySupporters.supporter_export_selections)) ) end - def self.attendees_list_selection ['tickets.id', 'tickets.bid_id', @@ -133,27 +131,25 @@ module QueryTickets 'supporters.email AS email', 'coalesce(donations.total_amount, 0) AS total_donations', 'source_tokens.token AS token', - 'cards.name AS card_name' - ] + 'cards.name AS card_name'] end def self.for_event_activities(event_id) selects = [" - CASE - WHEN supporters.anonymous='t' - OR supporters.name='' - OR supporters.name IS NULL - THEN 'A supporter' - ELSE supporters.name - END AS supporter_name", - 'tickets.quantity', 'tickets.created_at'] - return Qx.select(selects.join(',')) + CASE + WHEN supporters.anonymous='t' + OR supporters.name='' + OR supporters.name IS NULL + THEN 'A supporter' + ELSE supporters.name + END AS supporter_name", + 'tickets.quantity', 'tickets.created_at'] + Qx.select(selects.join(',')) .from(:tickets) .left_join(:supporters, 'tickets.supporter_id=supporters.id') .where('tickets.event_id=$id', id: event_id) - .order_by("tickets.created_at desc") + .order_by('tickets.created_at desc') .limit(15) .execute end - end diff --git a/lib/query/query_users.rb b/lib/query/query_users.rb index 94bcb3c2..579a9e72 100644 --- a/lib/query/query_users.rb +++ b/lib/query/query_users.rb @@ -1,40 +1,41 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'psql' require 'qexpr' require 'query/query_email_settings' module QueryUsers - # Return all the nonprofit user emails for a given email notification setting # for notification_type in ['payments', 'campaigns', 'events', 'payouts', 'recurring_donations'] def self.nonprofit_user_emails(np_id, notification_type) - raise ArgumentError.new('Invalid notification type') unless QueryEmailSettings::Settings.include?(notification_type) - Qx.select("users.email") - .from("users") - .join("roles", "roles.user_id=users.id") - .add_join("nonprofits", "roles.host_id=nonprofits.id AND roles.host_type='Nonprofit'") - .add_left_join("email_settings", "email_settings.user_id=users.id") + raise ArgumentError, 'Invalid notification type' unless QueryEmailSettings::Settings.include?(notification_type) + + Qx.select('users.email') + .from('users') + .join('roles', 'roles.user_id=users.id') + .add_join('nonprofits', "roles.host_id=nonprofits.id AND roles.host_type='Nonprofit'") + .add_left_join('email_settings', 'email_settings.user_id=users.id') .where("email_settings.user_id IS NULL OR email_settings.#{notification_type}=TRUE") - .and_where("nonprofits.id=$id", id: np_id) - .group_by("users.email") - .execute.map{|h| h['email']} + .and_where('nonprofits.id=$id', id: np_id) + .group_by('users.email') + .execute.map { |h| h['email'] } end # Return all nonprofit emails regardless of email settings - def self.all_nonprofit_user_emails(np_id, roles=[:nonprofit_admin, :nonprofit_user]) + def self.all_nonprofit_user_emails(np_id, roles = %i[nonprofit_admin nonprofit_user]) Qx.select('users.email').from('users') .join('roles', 'roles.user_id = users.id') .add_join('nonprofits', 'nonprofits.id = roles.host_id AND roles.host_type=\'Nonprofit\'') .where('nonprofits.id=$id', id: np_id) .and_where('roles.name IN ($names)', names: roles) - .execute.map{|h| h['email']} + .execute.map { |h| h['email'] } end # Return an array of email address strings for all users with role of 'super_admin' def self.super_admin_emails - Qx.select("users.email").from("users") - .join("roles", "roles.user_id=users.id AND roles.name='super_admin'") - .ex.map{|h| h['email']} + Qx.select('users.email').from('users') + .join('roles', "roles.user_id=users.id AND roles.name='super_admin'") + .ex.map { |h| h['email'] } end - end diff --git a/lib/queue_donations.rb b/lib/queue_donations.rb index d9eeea03..ccbbd8bf 100644 --- a/lib/queue_donations.rb +++ b/lib/queue_donations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module QueueDonations def self.execute_for_donation(id) @@ -10,15 +12,17 @@ module QueueDonations def self.execute_all donations = fetch_donations return if donations.empty? + donations_ids = donations.collect(&:id) execute(donations) end def self.dry_execute_all -puts "dry push donations to civi" + puts 'dry push donations to civi' donations = fetch_donations return if donations.empty? + donations_ids = donations.collect(&:id) dry_execute(donations) @@ -31,18 +35,16 @@ puts "dry push donations to civi" donations_ids = donations.collect(&:id) set_queued_for_import_at(donations_ids) - rescue Bunny::Exception, Bunny::ClientTimeout, Bunny::ConnectionTimeout Rails.logger.warn "Bunny error: QueueDonations.execute failed for ids #{donations_ids}" - return + nil end def self.dry_execute(donations) push(donations) - rescue Bunny::Exception, Bunny::ClientTimeout, Bunny::ConnectionTimeout Rails.logger.warn "Bunny error: QueueDonations.dry_execute failed for ids #{donations_ids}" - return + nil end def self.push(donations) @@ -68,16 +70,16 @@ puts "dry push donations to civi" def self.set_queued_for_import_at(ids) timestamp = Time.current - Qx.update(:donations). - where('id IN ($ids)', ids: ids). - set(queued_for_import_at: timestamp). - execute + Qx.update(:donations) + .where('id IN ($ids)', ids: ids) + .set(queued_for_import_at: timestamp) + .execute end def self.fetch_donations - Donation. - where('queued_for_import_at IS null'). - includes(:supporter, :nonprofit, :tracking, :payment,:recurring_donation) + Donation + .where('queued_for_import_at IS null') + .includes(:supporter, :nonprofit, :tracking, :payment, :recurring_donation) end def self.prepare_donation_params(donation) @@ -87,7 +89,7 @@ puts "dry push donations to civi" recurring = donation.recurring_donation action_type = :donate - action_technical_type = "cc.wemove.eu:donate" + action_technical_type = 'cc.wemove.eu:donate' action_name = "undefined_#{donation.supporter.locale}" external_id = campaign ? campaign.external_identifier : "cc_default_#{nonprofit.id}" @@ -118,7 +120,8 @@ puts "dry push donations to civi" { email: supporter.email } ], addresses: [ - { zip: supporter.zip_code, country: supporter.country }], + { zip: supporter.zip_code, country: supporter.country } + ] } end @@ -128,26 +131,26 @@ puts "dry push donations to civi" currency: donation.nonprofit.currency, recurring_id: donation.recurring_donation ? "cc_#{donation.recurring_donation.id}" : nil, external_identifier: "cc_#{donation.id}", - type: donation.recurring ? "recurring" : "single" + type: donation.recurring ? 'recurring' : 'single' } if donation.card_id - data = common_data.merge({ - payment_processor: "stripe", + data = common_data.merge( + payment_processor: 'stripe', amount_charged: donation.payment.charge.amount / 100.0, transaction_id: donation.payment.charge.stripe_charge_id, - status: donation.payment.charge.paid? ? "success" : "not_paid" - }) + status: donation.payment.charge.paid? ? 'success' : 'not_paid' + ) elsif donation.direct_debit_detail_id - data = common_data.merge({ - payment_processor: "sepa", + data = common_data.merge( + payment_processor: 'sepa', amount_charged: 0, transaction_id: "cc_#{donation.id}", iban: donation.direct_debit_detail.iban, bic: donation.direct_debit_detail.bic, account_holder: donation.direct_debit_detail.account_holder_name, - status: "success" - }) + status: 'success' + ) end data @@ -158,9 +161,10 @@ puts "dry push donations to civi" id: recurring.id, start: recurring.start_date, time_unit: recurring.time_unit, - active: recurring.active, + active: recurring.active } end + def self.tracking_data(tracking) { source: tracking.utm_source, diff --git a/lib/qx_query_chunker.rb b/lib/qx_query_chunker.rb index cee3ca0b..f2303a06 100644 --- a/lib/qx_query_chunker.rb +++ b/lib/qx_query_chunker.rb @@ -1 +1,3 @@ -QxQueryChunker = QexprQueryChunker \ No newline at end of file +# frozen_string_literal: true + +QxQueryChunker = QexprQueryChunker diff --git a/lib/required_keys.rb b/lib/required_keys.rb index c4d75e53..64b9e0f4 100644 --- a/lib/required_keys.rb +++ b/lib/required_keys.rb @@ -1,12 +1,13 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # Given a hash and an array of keys # Raise an argument error if any keys are missing from the hash class RequiredKeys - def initialize(hash, keys) - missing = keys.select{|k| hash[k].nil?} - raise ArgumentError.new("Missing keys: #{missing}") if missing.any? + missing = keys.select { |k| hash[k].nil? } + raise ArgumentError, "Missing keys: #{missing}" if missing.any? end end diff --git a/lib/retrieve/retrieve_active_record_items.rb b/lib/retrieve/retrieve_active_record_items.rb index a0b172a9..3a79461f 100644 --- a/lib/retrieve/retrieve_active_record_items.rb +++ b/lib/retrieve/retrieve_active_record_items.rb @@ -1,45 +1,49 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module RetrieveActiveRecordItems - def self.retrieve(data, optional= false) - data.map{|k,v| - our_integer = Integer(v) rescue nil + def self.retrieve(data, optional = false) + data.map do |k, v| + our_integer = begin + Integer(v) + rescue StandardError + nil + end unless (optional && v.nil?) || (our_integer && our_integer > 0) - raise ArgumentError.new("Value '#{v}' for Key '#{k}' is not valid") + raise ArgumentError, "Value '#{v}' for Key '#{k}' is not valid" end - unless k.is_a? Class - raise ArgumentError.new("Key '#{k.to_s}' is not a class") - end + raise ArgumentError, "Key '#{k}' is not a class" unless k.is_a? Class + ret = [] if optional && v.nil? ret = [k, nil] else ret = [k, k.where('id = ?', our_integer).first] - if (ret[1] == nil) - raise ParamValidation::ValidationError.new("ID #{v} is not a valid #{k.to_s}", {key: k}) + if ret[1].nil? + raise ParamValidation::ValidationError.new("ID #{v} is not a valid #{k}", key: k) end end ret - }.to_h + end.to_h end - def self.retrieve_from_keys(input, class_to_key_hash, optional=false) - class_to_key_hash.map{|k,v| - unless k.is_a? Class - raise ArgumentError.new("Key '#{k.to_s}' is not a class") - end + def self.retrieve_from_keys(input, class_to_key_hash, optional = false) + class_to_key_hash.map do |k, v| + raise ArgumentError, "Key '#{k}' is not a class" unless k.is_a? Class + ret = nil begin - item = retrieve({k => input[v]}, optional) + item = retrieve({ k => input[v] }, optional) ret = [v, item[k]] rescue ParamValidation::ValidationError - raise ParamValidation::ValidationError.new("ID #{input[v]} is not a valid #{k.to_s}", {key: v}) + raise ParamValidation::ValidationError.new("ID #{input[v]} is not a valid #{k}", key: v) rescue ArgumentError - raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", {key: v}) - rescue - raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", {key: v}) + raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", key: v) + rescue StandardError + raise ParamValidation::ValidationError.new("#{input[v]} is not a valid ID for Key '#{v}'", key: v) end ret - }.to_h + end.to_h end -end \ No newline at end of file +end diff --git a/lib/scheduled_jobs.rb b/lib/scheduled_jobs.rb index 3d4f992d..13ec5dbc 100644 --- a/lib/scheduled_jobs.rb +++ b/lib/scheduled_jobs.rb @@ -1,9 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' -require 'enumerator' - module ScheduledJobs - # Each of these functions should return an Enumerator # Each value in the enumerator should be a lambda # That way the heroku_scheduled_job task can iterate over each lambda @@ -15,41 +14,38 @@ module ScheduledJobs def self.delete_junk_data # Delete all custom fields with emptly/nil vals del_cfjs_noval = Qx.delete_from(:custom_field_joins) - .where("value IS NULL OR value=''") + .where("value IS NULL OR value=''") # Delete orphaned custom field joins (those should also all have supporters) - del_cfjs_orphaned = Qx.delete_from(:custom_field_joins).where("id IN ($ids)", { - ids: Qx.select("custom_field_joins.id") - .from(:custom_field_joins) - .left_join("supporters", "custom_field_joins.supporter_id=supporters.id") - .where("supporters.id IS NULL") - }) + del_cfjs_orphaned = Qx.delete_from(:custom_field_joins).where('id IN ($ids)', + ids: Qx.select('custom_field_joins.id') + .from(:custom_field_joins) + .left_join('supporters', 'custom_field_joins.supporter_id=supporters.id') + .where('supporters.id IS NULL')) # Delete orphaned tag joins - del_tags_orphaned = Qx.delete_from(:tag_joins).where("id IN ($ids)", { - ids: Qx.select("tag_joins.id") - .from(:tag_joins) - .left_join(:supporters, "tag_joins.supporter_id=supporters.id") - .where("supporters.id IS NULL") - }) + del_tags_orphaned = Qx.delete_from(:tag_joins).where('id IN ($ids)', + ids: Qx.select('tag_joins.id') + .from(:tag_joins) + .left_join(:supporters, 'tag_joins.supporter_id=supporters.id') + .where('supporters.id IS NULL')) - return Enumerator.new do |yielder| + Enumerator.new do |yielder| yielder << lambda do del_cfjs_noval.execute - "Successfully cleaned up custom field joins with no values" + 'Successfully cleaned up custom field joins with no values' end yielder << lambda do del_cfjs_orphaned.execute - "Successfully cleaned up custom field joins that have been orphaned from supporters" + 'Successfully cleaned up custom field joins that have been orphaned from supporters' end yielder << lambda do del_tags_orphaned.execute - "Successfully cleaned up tags that have been orphaned from supporters" + 'Successfully cleaned up tags that have been orphaned from supporters' end end end - def self.pay_recurring_donations - return Enumerator.new do |yielder| + Enumerator.new do |yielder| yielder << lambda do ids = PayRecurringDonation.pay_all_due_with_stripe "Queued jobs to pay #{ids.count} total recurring donations\n Recurring Donation Ids to run are: \n#{ids.join('\n')}" @@ -58,7 +54,7 @@ module ScheduledJobs end def self.update_verification_statuses - return Enumerator.new do |yielder| + Enumerator.new do |yielder| Nonprofit.where(verification_status: 'pending').each do |np| yielder << lambda do acct = Stripe::Account.retrieve(np.stripe_account_id) @@ -74,8 +70,8 @@ module ScheduledJobs end def self.update_np_balances - return Enumerator.new do |yielder| - nps = Nonprofit.where("id IN (?)", Charge.pending.uniq.pluck(:nonprofit_id)) + Enumerator.new do |yielder| + nps = Nonprofit.where('id IN (?)', Charge.pending.uniq.pluck(:nonprofit_id)) nps.each do |np| yielder << lambda do UpdateNonprofit.mark_available_charges(np.id) @@ -86,13 +82,12 @@ module ScheduledJobs end def self.update_pending_payouts - return Enumerator.new do |yielder| + Enumerator.new do |yielder| Payout.pending.includes(:nonprofit).each do |p| yielder << lambda do err = false - p.status = Stripe::Transfer.retrieve(p.stripe_transfer_id, { - stripe_account: p.nonprofit.stripe_account_id - }).status + p.status = Stripe::Transfer.retrieve(p.stripe_transfer_id, + stripe_account: p.nonprofit.stripe_account_id).status p.save "Updated status for NP #{p.nonprofit.id}, payout # #{p.id}" end @@ -101,9 +96,9 @@ module ScheduledJobs end def self.delete_expired_source_tokens - return Enumerator.new do |yielder| + Enumerator.new do |yielder| yielder << lambda do - tokens_deleted = SourceToken.where("expiration > ?", DateTime.now - 1.day).delete_all + tokens_deleted = SourceToken.where('expiration > ?', DateTime.now - 1.day).delete_all "Deleted #{tokens_deleted} source tokens" end end diff --git a/lib/search_vector.rb b/lib/search_vector.rb index 9b190382..dde98873 100644 --- a/lib/search_vector.rb +++ b/lib/search_vector.rb @@ -1,13 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module SearchVector + AcceptedTables = %w[supporters payments].freeze - AcceptedTables = ['supporters', 'payments'] - - def self.query(query_string, expr=nil) + def self.query(query_string, expr = nil) (expr || Qexpr.new).where( "to_tsvector('english', coalesce(supporters.name, '') || ' ' || coalesce(supporters.email, '')) @@ plainto_tsquery('english', $search)", - { search: query_string} + search: query_string ) end @@ -27,18 +28,18 @@ module SearchVector , donations.dedication ) AS search_blob" ) - .from(:payments) - .left_outer_join('supporters', 'payments.supporter_id=supporters.id') - .left_outer_join('donations', 'payments.donation_id=donations.id') + .from(:payments) + .left_outer_join('supporters', 'payments.supporter_id=supporters.id') + .left_outer_join('donations', 'payments.donation_id=donations.id') end # Construct of query of ids and search blobs for all supporters # for use in a sub-query def self._supporters_blob_query - fields_subquery = Qexpr.new.select("string_agg(value::text, ' ') AS value", "supporter_id") - .from(:custom_field_joins) - .group_by(:supporter_id) - .as(:custom_field_joins) + fields_subquery = Qexpr.new.select("string_agg(value::text, ' ') AS value", 'supporter_id') + .from(:custom_field_joins) + .group_by(:supporter_id) + .as(:custom_field_joins) Qexpr.new.select( 'supporters.id', "concat_ws(' ' @@ -55,10 +56,9 @@ module SearchVector , payments.towards ) AS search_blob" ) - .from(:supporters) - .left_outer_join(:payments, "payments.supporter_id=supporters.id") - .left_outer_join(:donations, "donations.supporter_id=supporters.id") - .left_outer_join(fields_subquery, "custom_field_joins.supporter_id=supporters.id") + .from(:supporters) + .left_outer_join(:payments, 'payments.supporter_id=supporters.id') + .left_outer_join(:donations, 'donations.supporter_id=supporters.id') + .left_outer_join(fields_subquery, 'custom_field_joins.supporter_id=supporters.id') end - end diff --git a/lib/slug_copy_naming_algorithm.rb b/lib/slug_copy_naming_algorithm.rb index c12bde98..0927265f 100644 --- a/lib/slug_copy_naming_algorithm.rb +++ b/lib/slug_copy_naming_algorithm.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SlugCopyNamingAlgorithm < CopyNamingAlgorithm - attr_accessor :klass, :nonprofit_id # @param [Class] klass def initialize(klass, nonprofit_id) - @klass = klass - @nonprofit_id = nonprofit_id + @klass = klass + @nonprofit_id = nonprofit_id end def copy_addition - "_copy" + '_copy' end def max_copies @@ -21,8 +22,7 @@ class SlugCopyNamingAlgorithm < CopyNamingAlgorithm end def get_already_used_name_entities(base_name) - end_name = "\\_copy\\_\\d{2}" + end_name = '\\_copy\\_\\d{2}' @klass.method(:where).call('slug SIMILAR TO ? AND nonprofit_id = ? AND (deleted IS NULL OR deleted = false)', base_name + end_name, nonprofit_id).select('slug') end - -end \ No newline at end of file +end diff --git a/lib/slug_nonprofit_naming_algorithm.rb b/lib/slug_nonprofit_naming_algorithm.rb index 010acc3c..7fe78721 100644 --- a/lib/slug_nonprofit_naming_algorithm.rb +++ b/lib/slug_nonprofit_naming_algorithm.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SlugNonprofitNamingAlgorithm < CopyNamingAlgorithm + attr_accessor :state_slug, :city_slug - attr_accessor :state_slug, :city_slug - - def initialize( state_slug, city_slug) - @state_slug = state_slug - @city_slug = city_slug + def initialize(state_slug, city_slug) + @state_slug = state_slug + @city_slug = city_slug end def copy_addition - "" + '' end def max_copies @@ -25,8 +26,7 @@ class SlugNonprofitNamingAlgorithm < CopyNamingAlgorithm end def get_already_used_name_entities(base_name) - end_name = "\\-\\d{2}" - Nonprofit.method(:where).call('slug SIMILAR TO ? AND state_code_slug = ? AND city_slug = ?', base_name + end_name, @state_slug, @city_slug).select('slug') + end_name = '\\-\\d{2}' + Nonprofit.method(:where).call('slug SIMILAR TO ? AND state_code_slug = ? AND city_slug = ?', base_name + end_name, @state_slug, @city_slug).select('slug') end - -end \ No newline at end of file +end diff --git a/lib/slug_p2p_campaign_naming_algorithm.rb b/lib/slug_p2p_campaign_naming_algorithm.rb index cbbe6aeb..c6bcdba2 100644 --- a/lib/slug_p2p_campaign_naming_algorithm.rb +++ b/lib/slug_p2p_campaign_naming_algorithm.rb @@ -1,14 +1,15 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later class SlugP2pCampaignNamingAlgorithm < CopyNamingAlgorithm - attr_accessor :nonprofit_id # @param [Integer] nonprofit_id def initialize(nonprofit_id) - @nonprofit_id = nonprofit_id + @nonprofit_id = nonprofit_id end def copy_addition - "" + '' end def max_copies @@ -20,8 +21,7 @@ class SlugP2pCampaignNamingAlgorithm < CopyNamingAlgorithm end def get_already_used_name_entities(base_name) - end_name = "\\_\\d{3}" + end_name = '\\_\\d{3}' Campaign.where('slug SIMILAR TO ? AND nonprofit_id = ?', base_name + end_name, nonprofit_id).select('slug') end - -end \ No newline at end of file +end diff --git a/lib/stripe_account.rb b/lib/stripe_account.rb index eaa236da..a4c111dd 100644 --- a/lib/stripe_account.rb +++ b/lib/stripe_account.rb @@ -1,17 +1,18 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module StripeAccount - # Returns the stripe account ID string def self.find_or_create(nonprofit_id) - ParamValidation.new({:nonprofit_id => nonprofit_id}, {:nonprofit_id => {:required=> true, :is_integer => true}}) - begin - np = Nonprofit.find(nonprofit_id) - rescue => e - raise ParamValidation::ValidationError.new("#{nonprofit_id} is not a valid nonprofit", {:key => :nonprofit_id}) - end + ParamValidation.new({ nonprofit_id: nonprofit_id }, nonprofit_id: { required: true, is_integer: true }) + begin + np = Nonprofit.find(nonprofit_id) + rescue StandardError => e + raise ParamValidation::ValidationError.new("#{nonprofit_id} is not a valid nonprofit", key: :nonprofit_id) + end - if !np['stripe_account_id'] + if !np['stripe_account_id'] return create(np) else return np['stripe_account_id'] @@ -20,32 +21,32 @@ module StripeAccount # np should be a hash with string keys def self.create(np) - ParamValidation.new({:np => np}, {:np => {:required=> true, :is_a => Nonprofit}}) - params = { - managed: true, - email: np['email'].present? ? np['email'] : np.roles.nonprofit_admins.order('created_at ASC').first.user.email, - business_name: np['name'], - legal_entity: { - type: 'company', - address: { - city: np['city'], - state: np['state_code'], - postal_code: np['zip_code'], - country: 'US' - }, - business_name: np['name'], - }, - product_description: 'Nonprofit donations', - transfer_schedule: { interval: 'manual' } - } + ParamValidation.new({ np: np }, np: { required: true, is_a: Nonprofit }) + params = { + managed: true, + email: np['email'].present? ? np['email'] : np.roles.nonprofit_admins.order('created_at ASC').first.user.email, + business_name: np['name'], + legal_entity: { + type: 'company', + address: { + city: np['city'], + state: np['state_code'], + postal_code: np['zip_code'], + country: 'US' + }, + business_name: np['name'] + }, + product_description: 'Nonprofit donations', + transfer_schedule: { interval: 'manual' } + } - if np['website'] && np['website'] =~ URI::regexp - params[:business_url] = np['website'] - end + if np['website'] && np['website'] =~ URI::DEFAULT_PARSER.make_regexp + params[:business_url] = np['website'] + end - acct = Stripe::Account.create(params) + acct = Stripe::Account.create(params) Qx.update(:nonprofits).set(stripe_account_id: acct.id).where(id: np['id']).execute NonprofitMailer.delay.setup_verification(np['id']) - return acct.id - end + acct.id + end end diff --git a/lib/stripe_utils.rb b/lib/stripe_utils.rb index 820a15ea..7a32c443 100644 --- a/lib/stripe_utils.rb +++ b/lib/stripe_utils.rb @@ -1,35 +1,35 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'stripe' require 'calculate/calculate_fees' module StripeUtils + # Get the verification status from a stripe object + # Some of our accounts seem to be marked 'Unverified,' but have no + # fields_needed set and have transfers_enabled set to true. So for our system, + # that practically means they are verified. + def self.get_verification_status(stripe_acct) + return 'verified' if stripe_acct.transfers_enabled - # Get the verification status from a stripe object - # Some of our accounts seem to be marked 'Unverified,' but have no - # fields_needed set and have transfers_enabled set to true. So for our system, - # that practically means they are verified. - def self.get_verification_status(stripe_acct) - return 'verified' if stripe_acct.transfers_enabled - return stripe_acct.legal_entity.verification.status - end + stripe_acct.legal_entity.verification.status + end - def self.create_transfer(net_amount, stripe_account_id, currency) - Stripe::Transfer.create({ - amount: net_amount, - currency: currency || Settings.intntl.currencies[0], - recipient: 'self' - }, { - stripe_account: stripe_account_id - }) - end + def self.create_transfer(net_amount, stripe_account_id, currency) + Stripe::Transfer.create({ + amount: net_amount, + currency: currency || Settings.intntl.currencies[0], + recipient: 'self' + }, + stripe_account: stripe_account_id) + end - - def self.create_refund(stripe_charge, amount, reason) - stripe_charge.refunds.create({ - amount: amount, - refund_application_fee: true, - reverse_transfer: true, - reason: reason - }) - end + def self.create_refund(stripe_charge, amount, reason) + stripe_charge.refunds.create( + amount: amount, + refund_application_fee: true, + reverse_transfer: true, + reason: reason + ) + end end diff --git a/lib/tasks/civicrm.rake b/lib/tasks/civicrm.rake index 4b040383..dae3cb1e 100644 --- a/lib/tasks/civicrm.rake +++ b/lib/tasks/civicrm.rake @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'queue_donations' namespace :civicrm do - desc "pushes donation records to CiviCRM" - task :push => :environment do + desc 'pushes donation records to CiviCRM' + task push: :environment do QueueDonations.execute_all end desc "pushes donation records to CiviCRM, but doesn't mark them as pushed (useful for debugging)" - task :dry_run => :environment do + task dry_run: :environment do QueueDonations.dry_execute_all end end diff --git a/lib/tasks/database.rake b/lib/tasks/database.rake index ca0636b2..3f6a4a3b 100644 --- a/lib/tasks/database.rake +++ b/lib/tasks/database.rake @@ -1,24 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -Rake::Task["db:structure:dump"].clear +Rake::Task['db:structure:dump'].clear namespace :db do namespace :structure do - desc "Overriding the task db:structure:dump task to remove -i option from pg_dump to make postgres 9.5 compatible" - task dump: [:environment, :load_config] do + desc 'Overriding the task db:structure:dump task to remove -i option from pg_dump to make postgres 9.5 compatible' + task dump: %i[environment load_config] do config = ActiveRecord::Base.configurations[Rails.env] set_psql_env(config) - filename = File.join(Rails.root, "db", "structure.sql") - database = config["database"] + filename = File.join(Rails.root, 'db', 'structure.sql') + database = config['database'] command = "pg_dump -s -x -O -f #{Shellwords.escape(filename)} #{Shellwords.escape(database)}" raise 'Error dumping database' unless Kernel.system(command) - File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } + File.open(filename, 'a') { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } if ActiveRecord::Base.connection.supports_migrations? - File.open(filename, "a") do |f| + File.open(filename, 'a') do |f| f.puts ActiveRecord::Base.connection.dump_schema_information f.print "\n" end end - Rake::Task["db:structure:dump"].reenable + Rake::Task['db:structure:dump'].reenable end end @@ -28,4 +30,4 @@ namespace :db do ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password'] ENV['PGUSER'] = configuration['username'].to_s if configuration['username'] end -end \ No newline at end of file +end diff --git a/lib/tasks/full_contact.rake b/lib/tasks/full_contact.rake index 7ef13ced..8a6b983a 100644 --- a/lib/tasks/full_contact.rake +++ b/lib/tasks/full_contact.rake @@ -1,12 +1,13 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -desc "For generating Full Contact data" +desc 'For generating Full Contact data' # Clear old activerecord sessions tables daily -task :work_full_contact_queue => :environment do - +task work_full_contact_queue: :environment do loop do - sleep(10) until Qx.select("COUNT(*)").from("full_contact_jobs").execute.first['count'] > 0 - puts "working..." + sleep(10) until Qx.select('COUNT(*)').from('full_contact_jobs').execute.first['count'] > 0 + puts 'working...' begin InsertFullContactInfos.work_queue diff --git a/lib/tasks/health_report.rake b/lib/tasks/health_report.rake index daa1a910..e9f965af 100644 --- a/lib/tasks/health_report.rake +++ b/lib/tasks/health_report.rake @@ -1,10 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -desc "For sending an activity report email of what has been happening on the system" +desc 'For sending an activity report email of what has been happening on the system' # Clear old activerecord sessions tables daily -task :send_health_report => :environment do - GenericMailer.admin_notice({ +task send_health_report: :environment do + GenericMailer.admin_notice( body: HealthReport.format_data(HealthReport.query_data), subject: "CommitChange activity report #{Format::Date.to_readable(Time.now)}" - }).deliver + ).deliver end diff --git a/lib/tasks/oapi.rake b/lib/tasks/oapi.rake index 4bb6cf8d..46fb359a 100644 --- a/lib/tasks/oapi.rake +++ b/lib/tasks/oapi.rake @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require 'grape-swagger/rake/oapi_tasks' namespace :oapi do task gen: [:environment] do ENV['store'] = 'tmp/openapi.json' GrapeSwagger::Rake::OapiTasks.new(Houdini::API) - Rake::Task['oapi:fetch'].invoke() + Rake::Task['oapi:fetch'].invoke end -end \ No newline at end of file +end diff --git a/lib/tasks/scheduler.rake b/lib/tasks/scheduler.rake index 37bade48..6ba7837d 100644 --- a/lib/tasks/scheduler.rake +++ b/lib/tasks/scheduler.rake @@ -1,25 +1,25 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'scheduled_jobs' desc "For use with Heroku's Scheduler add-on" # We use a single rake call so we can catch and send any errors that happen in the job -task :heroku_scheduled_job, [:name] => :environment do |t, args| +task :heroku_scheduled_job, [:name] => :environment do |_t, args| job_name = args[:name] # Fetch all the super admin emails so we can send a report enum = ScheduledJobs.send(job_name) - results = "" + results = '' enum.each do |lamb| - begin - result = lamb.call - results += "Success: #{result}\n" - rescue Exception => e - results += "Failure: #{e}\n" - end + result = lamb.call + results += "Success: #{result}\n" + rescue Exception => e + results += "Failure: #{e}\n" end - GenericMailer.delay.admin_notice({ + GenericMailer.delay.admin_notice( subject: "Scheduled job results on CommitChange for '#{job_name}'", - body: results.empty? ? "No jobs to run today." : results - }) + body: results.empty? ? 'No jobs to run today.' : results + ) end diff --git a/lib/tasks/seed.rake b/lib/tasks/seed.rake index 8d72629a..4ec8db2d 100644 --- a/lib/tasks/seed.rake +++ b/lib/tasks/seed.rake @@ -1,16 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later namespace :seed do - - task :np => :environment do - ActiveRecord::Base.transaction do - supers = Role.super_admins.includes(:user).map{|r| r.user} - n = Nonprofit.register(supers.last, name: "Testify #{rand(0..100)}", city: 'Albuquerque', state_code: 'NM') - n.verification_status = 'verified' - n.vetted = true - n.create_billing_subscription({billing_plan: BillingPlan.where(tier: 2).last}) - n.save! - supers.each{|user| user.roles.create(name: :nonprofit_admin, host: n)} - puts "New test nonprofit id: #{n.id}" - end - end + task np: :environment do + ActiveRecord::Base.transaction do + supers = Role.super_admins.includes(:user).map(&:user) + n = Nonprofit.register(supers.last, name: "Testify #{rand(0..100)}", city: 'Albuquerque', state_code: 'NM') + n.verification_status = 'verified' + n.vetted = true + n.create_billing_subscription(billing_plan: BillingPlan.where(tier: 2).last) + n.save! + supers.each { |user| user.roles.create(name: :nonprofit_admin, host: n) } + puts "New test nonprofit id: #{n.id}" + end + end end diff --git a/lib/tasks/settings.rake b/lib/tasks/settings.rake index fcb1fbb0..3a344add 100644 --- a/lib/tasks/settings.rake +++ b/lib/tasks/settings.rake @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later namespace :settings do @@ -5,33 +7,30 @@ namespace :settings do require File.expand_path('../../config/environment.rb', File.dirname(__FILE__)) end - desc "show settings" - task :show => :environment do + desc 'show settings' + task show: :environment do require 'pp' pp Settings.to_hash end - task :generate_json => :environment do - - cdn_url= URI(Settings.cdn.url) + task generate_json: :environment do + cdn_url = URI(Settings.cdn.url) cdn_url = cdn_url.to_s - if (Settings.button_config&.url) - cdn_url= URI(Settings.button_config.url).to_s + if Settings.button_config&.url + cdn_url = URI(Settings.button_config.url).to_s end - c = {button:{url:cdn_url,css:"#{cdn_url}/css/donate-button.v2.css"}} + c = { button: { url: cdn_url, css: "#{cdn_url}/css/donate-button.v2.css" } } open(File.expand_path('config/settings.json', Rails.root), 'w') do |f| f.write(c.to_json) end end - task :combine_translations => 'i18n:js:export' do + task combine_translations: 'i18n:js:export' do js_root = File.expand_path('public/javascripts', Rails.root) - #i18n = File.read(File.join(js_root, 'i18n.js')) + # i18n = File.read(File.join(js_root, 'i18n.js')) translations = File.read(File.join(js_root, 'translations.js')) open(File.join(js_root, '_final.js'), 'w') do |f| f.write("const I18n = require('i18n-js');\n" + translations + "\n window.I18n = I18n") end end - end - diff --git a/lib/timespan.rb b/lib/timespan.rb index 305d030e..d9f05d9c 100644 --- a/lib/timespan.rb +++ b/lib/timespan.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # For tracking and calculating timespans/time intervals # Relies on activesupport Timespan = Struct.new(:interval, :time_unit) do - - Units = ['week', 'day', 'month', 'year'] + Units = %w[week day month year].freeze TimeUnits = { '1_week' => 1.week.ago, '2_weeks' => 2.weeks.ago, @@ -13,35 +14,35 @@ Timespan = Struct.new(:interval, :time_unit) do '6_months' => 6.months.ago, '1_year' => 1.year.ago, '2_years' => 2.years.ago - } + }.freeze - # Test if end_date is past start_date by timespan - # eg: later_than_by?(Jun 13th, Jul 14th, 1.month) -> true - # Special case: - # later_than_by?(Jan 31st, Feb 28th, 1.month) -> true - def self.later_than_by?(start_date, end_date, timespan) - return (start_date + timespan) <= end_date - end + # Test if end_date is past start_date by timespan + # eg: later_than_by?(Jun 13th, Jul 14th, 1.month) -> true + # Special case: + # later_than_by?(Jan 31st, Feb 28th, 1.month) -> true + def self.later_than_by?(start_date, end_date, timespan) + (start_date + timespan) <= end_date + end - # Given an Integer (frequency) and a String (time unit), - # return the timespan object (ie. number of seconds) constituting the timespan - # timespan(1, 'minute') -> 60 - # timespan(1, 'month') -> 2592000 - def self.create(interval, time_unit) - raise(ArgumentError, "time_unit must be one of: #{Units}") unless Units.include?(time_unit) - return interval.send(time_unit.to_sym) - end + # Given an Integer (frequency) and a String (time unit), + # return the timespan object (ie. number of seconds) constituting the timespan + # timespan(1, 'minute') -> 60 + # timespan(1, 'month') -> 2592000 + def self.create(interval, time_unit) + raise(ArgumentError, "time_unit must be one of: #{Units}") unless Units.include?(time_unit) - def self.in_future?(datetime) - datetime > Time.current - end + interval.send(time_unit.to_sym) + end - def self.date_now_or_in_future?(date) - date >= Date.today - end + def self.in_future?(datetime) + datetime > Time.current + end - def self.in_past?(date) - date < Time.current - end + def self.date_now_or_in_future?(date) + date >= Date.today + end + def self.in_past?(date) + date < Time.current + end end diff --git a/lib/update/update_activities.rb b/lib/update/update_activities.rb index 89a96eae..1652d4cf 100644 --- a/lib/update/update_activities.rb +++ b/lib/update/update_activities.rb @@ -1,22 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module UpdateActivities - def self.for_supporter_notes(note) - user_email = Qx.select('email') - .from(:users) - .where(id: note[:user_id]) - .execute - .first['email'] + .from(:users) + .where(id: note[:user_id]) + .execute + .first['email'] Qx.update(:activities) - .set(json_data: {content: note[:content], user_email: user_email}.to_json) + .set(json_data: { content: note[:content], user_email: user_email }.to_json) .timestamps .where(attachment_id: note[:id]) .execute - - end + end end - diff --git a/lib/update/update_billing_subscriptions.rb b/lib/update/update_billing_subscriptions.rb index 5e15ae16..2a73e813 100644 --- a/lib/update/update_billing_subscriptions.rb +++ b/lib/update/update_billing_subscriptions.rb @@ -1,7 +1,8 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateBillingSubscriptions - def self.activate_from_trial(np_id) Qx.update(:billing_subscriptions) .set(status: 'active') diff --git a/lib/update/update_campaign_gift_option.rb b/lib/update/update_campaign_gift_option.rb index ba52f088..5163f2dc 100644 --- a/lib/update/update_campaign_gift_option.rb +++ b/lib/update/update_campaign_gift_option.rb @@ -1,10 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateCampaignGiftOption - - def self.update gift_option, params - gift_option.update_attributes params - return gift_option - end - + def self.update(gift_option, params) + gift_option.update_attributes params + gift_option + end end - diff --git a/lib/update/update_charges.rb b/lib/update/update_charges.rb index 0e3c957b..14450b4f 100644 --- a/lib/update/update_charges.rb +++ b/lib/update/update_charges.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateCharges + def self.disburse_all_with_payments(payment_ids) + Psql.execute(Qexpr.new.update(:charges, status: 'disbursed').where('payment_id IN ($ids)', ids: payment_ids).returning('id', 'status')) + end - def self.disburse_all_with_payments(payment_ids) - Psql.execute(Qexpr.new.update(:charges, status: 'disbursed').where("payment_id IN ($ids)", ids: payment_ids).returning('id', 'status')) - end - - def self.reverse_disburse_all_with_payments(payment_ids) - Charge.where("payment_id IN (?)", payment_ids).update_all(status: 'available') - end + def self.reverse_disburse_all_with_payments(payment_ids) + Charge.where('payment_id IN (?)', payment_ids).update_all(status: 'available') + end end diff --git a/lib/update/update_custom_field_joins.rb b/lib/update/update_custom_field_joins.rb index ef59f0b6..7b755237 100644 --- a/lib/update/update_custom_field_joins.rb +++ b/lib/update/update_custom_field_joins.rb @@ -1,23 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module UpdateCustomFieldJoins - # Delete custom field joins that have the same custom field master # Favor the most recent custom field join def self.delete_dupes(supporter_ids) # Bulk remove duplicate custom field joins, favoring the most recent one ids = Qx.select('ARRAY_AGG(custom_field_joins.id ORDER BY custom_field_joins.created_at DESC) AS ids') - .from(:custom_field_joins) - .where("custom_field_joins.supporter_id IN ($ids)", ids: supporter_ids) - .join("custom_field_masters cfms", "cfms.id = custom_field_joins.custom_field_master_id") - .group_by("cfms.name") - .having("COUNT(custom_field_joins) > 1") - .execute.map{|h| h['ids'][1..-1]}.flatten + .from(:custom_field_joins) + .where('custom_field_joins.supporter_id IN ($ids)', ids: supporter_ids) + .join('custom_field_masters cfms', 'cfms.id = custom_field_joins.custom_field_master_id') + .group_by('cfms.name') + .having('COUNT(custom_field_joins) > 1') + .execute.map { |h| h['ids'][1..-1] }.flatten return unless ids.any? + Qx.delete_from(:custom_field_joins) - .where("id IN ($ids)", ids: ids) + .where('id IN ($ids)', ids: ids) .execute end - end diff --git a/lib/update/update_disputes.rb b/lib/update/update_disputes.rb index 8f73f79c..b33360d3 100644 --- a/lib/update/update_disputes.rb +++ b/lib/update/update_disputes.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateDisputes - def self.disburse_all_with_payments(payment_ids) Psql.execute( - Qexpr.new.update(:disputes, {status: 'lost_and_paid'}).where("payment_id IN ($ids)", ids: payment_ids) + Qexpr.new.update(:disputes, status: 'lost_and_paid').where('payment_id IN ($ids)', ids: payment_ids) ) end end diff --git a/lib/update/update_donation.rb b/lib/update/update_donation.rb index ff680b82..15cb5150 100644 --- a/lib/update/update_donation.rb +++ b/lib/update/update_donation.rb @@ -1,77 +1,75 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateDonation - def self.from_followup(donation, params) donation.designation = params[:designation] if params[:designation].present? donation.dedication = params[:dedication] if params[:dedication].present? donation.comment = params[:comment] if params[:comment].present? donation.save - return donation + donation end # @param [Integer] donation_id the donation for the payment you wish to modify def self.update_payment(donation_id, data) - ParamValidation.new({id:donation_id, data: data}, - { - id: {required: true, is_reference: true}, - data: {required: true, is_hash: true} - }) + ParamValidation.new({ id: donation_id, data: data }, + id: { required: true, is_reference: true }, + data: { required: true, is_hash: true }) existing_payment = Payment.where('donation_id = ?', donation_id).last unless existing_payment raise ParamValidation::ValidationError.new("#{donation_id} is does not correspond to a valid donation", - {key: :id}) + key: :id) end is_offsite = !existing_payment.offsite_payment.nil? validations = { - designation: {is_a: String}, - dedication: {is_a: String}, - comment: {is_a: String}, - campaign_id: {is_reference: true, required:true}, - event_id: {is_reference: true, required: true} + designation: { is_a: String }, + dedication: { is_a: String }, + comment: { is_a: String }, + campaign_id: { is_reference: true, required: true }, + event_id: { is_reference: true, required: true } } if is_offsite # if offline test the other values (fee_total, gross_amount, check_number, date) # - validations.merge!({gross_amount: {is_integer: true, min: 1}, - fee_total: {is_integer: true}, - check_number: {is_a: String}, - date: {can_be_date: true}}) + validations.merge!(gross_amount: { is_integer: true, min: 1 }, + fee_total: { is_integer: true }, + check_number: { is_a: String }, + date: { can_be_date: true }) end ParamValidation.new(data, validations) - set_to_nil = {campaign: data[:campaign_id] == '', event: data[:event_id] == ''} + set_to_nil = { campaign: data[:campaign_id] == '', event: data[:event_id] == '' } # validate campaign and event ids if there and if they belong to nonprofit - if (set_to_nil[:campaign]) + if set_to_nil[:campaign] campaign = nil else campaign = Campaign.where('id = ?', data[:campaign_id]).first unless campaign - raise ParamValidation::ValidationError.new("#{data[:campaign_id]} is not a valid campaign", {key: :campaign_id}) + raise ParamValidation::ValidationError.new("#{data[:campaign_id]} is not a valid campaign", key: :campaign_id) end unless campaign.nonprofit == existing_payment.nonprofit - raise ParamValidation::ValidationError.new("#{data[:campaign_id]} campaign does not belong to this nonprofit for payment #{existing_payment.id}", {key: :campaign_id}) + raise ParamValidation::ValidationError.new("#{data[:campaign_id]} campaign does not belong to this nonprofit for payment #{existing_payment.id}", key: :campaign_id) end end - if (set_to_nil[:event]) + if set_to_nil[:event] event = nil else event = Event.where('id = ?', data[:event_id]).first unless event - raise ParamValidation::ValidationError.new("#{data[:event_id]} is not a valid event", {key: :event_id}) + raise ParamValidation::ValidationError.new("#{data[:event_id]} is not a valid event", key: :event_id) end unless event.nonprofit == existing_payment.nonprofit - raise ParamValidation::ValidationError.new("#{data[:event_id]} event does not belong to this nonprofit for payment #{existing_payment.id}", {key: :event_id}) + raise ParamValidation::ValidationError.new("#{data[:event_id]} event does not belong to this nonprofit for payment #{existing_payment.id}", key: :event_id) end end Qx.transaction do - donation = existing_payment.donation donation.designation = data[:designation] if data[:designation] @@ -87,47 +85,38 @@ module UpdateDonation donation.date = data[:date] if data[:date] end - # edits_to_payments if is_offsite - #if offline, set date, gross_amount, fee_total, net_amount + # if offline, set date, gross_amount, fee_total, net_amount existing_payment.towards = data[:designation] if data[:designation] existing_payment.date = data[:date] if data[:date] existing_payment.gross_amount = data[:gross_amount] if data[:gross_amount] existing_payment.fee_total = data[:fee_total] if data[:fee_total] existing_payment.net_amount = existing_payment.gross_amount - existing_payment.fee_total - if existing_payment.changed? - existing_payment.save! - end + existing_payment.save! if existing_payment.changed? else if donation.designation - Payment.where('donation_id = ?', donation.id).update_all(:towards => donation.designation, updated_at: Time.now) + Payment.where('donation_id = ?', donation.id).update_all(towards: donation.designation, updated_at: Time.now) end end - #if offsite, set check_number, date, gross_amount + # if offsite, set check_number, date, gross_amount if is_offsite offsite_payment = existing_payment.offsite_payment offsite_payment.check_number = data[:check_number] if data[:check_number] offsite_payment.date = data[:date] if data[:date] offsite_payment.gross_amount = data[:gross_amount] if data[:gross_amount] - if offsite_payment.changed? - offsite_payment.save! - end - end - if donation.changed? - donation.save! + offsite_payment.save! if offsite_payment.changed? end + donation.save! if donation.changed? existing_payment.reload ret = donation.attributes ret[:payment] = existing_payment.attributes - if is_offsite - ret[:offsite_payment] = offsite_payment.attributes - end + ret[:offsite_payment] = offsite_payment.attributes if is_offsite return ret end end @@ -140,16 +129,13 @@ module UpdateDonation donation.date = donation.created_at donation.save! - - payments = Payment.where('donation_id = ?', id).includes(:charge) - - payments.each {|p| + payments.each do |p| @payments_corrected.push(p.id) p.date = p.charge.created_at p.save! - } + end donation.save! @@ -159,14 +145,19 @@ module UpdateDonation def self.any_donations_with_created_at_after_date donation_ids = Set.new - CSV.foreach('bad_payments_2.csv').select {|row| true if Integer(row[0]) rescue false}.collect{|row| - is_int = true if Integer(row[0]) rescue false - if (is_int && Float(row[6]) > 0) - donation_ids.add(row[0]) + CSV.foreach('bad_payments_2.csv').select do |row| + true if Integer(row[0]) + rescue StandardError + false + end .collect do |row| + begin + is_int = true if Integer(row[0]) + rescue StandardError + false end - } + donation_ids.add(row[0]) if is_int && Float(row[6]) > 0 + end - return donation_ids + donation_ids end end - diff --git a/lib/update/update_email_lists.rb b/lib/update/update_email_lists.rb index 3f26035a..54dc3ddc 100644 --- a/lib/update/update_email_lists.rb +++ b/lib/update/update_email_lists.rb @@ -1,22 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module UpdateEmailLists - def self.populate_lists_on_mailchimp(npo_id) - lists = Qx.select("tag_master_id", "list_name", "mailchimp_list_id") - .from(:email_lists) - .where(nonprofit_id: npo_id) - .execute - post_data = Qx.select("supporters.email", "email_lists.mailchimp_list_id") - .from("email_lists") - .add_join("tag_masters", "tag_masters.id=email_lists.tag_master_id") - .add_join("tag_joins", "tag_joins.tag_master_id=tag_masters.id") - .add_join("supporters", "supporters.id=tag_joins.supporter_id") - .where("email_lists.nonprofit_id=$id", id: npo_id) - .execute - .map{|h| {method: 'POST', path: "lists/#{h['mailchimp_list_id']}/members", body: {email_address: h['email'], status: 'subscribed'}.to_json}} + lists = Qx.select('tag_master_id', 'list_name', 'mailchimp_list_id') + .from(:email_lists) + .where(nonprofit_id: npo_id) + .execute + post_data = Qx.select('supporters.email', 'email_lists.mailchimp_list_id') + .from('email_lists') + .add_join('tag_masters', 'tag_masters.id=email_lists.tag_master_id') + .add_join('tag_joins', 'tag_joins.tag_master_id=tag_masters.id') + .add_join('supporters', 'supporters.id=tag_joins.supporter_id') + .where('email_lists.nonprofit_id=$id', id: npo_id) + .execute + .map { |h| { method: 'POST', path: "lists/#{h['mailchimp_list_id']}/members", body: { email_address: h['email'], status: 'subscribed' }.to_json } } Mailchimp.perform_batch_operations(npo_id, post_data) end - end diff --git a/lib/update/update_email_settings.rb b/lib/update/update_email_settings.rb index 463a5cca..89956681 100644 --- a/lib/update/update_email_settings.rb +++ b/lib/update/update_email_settings.rb @@ -1,18 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateEmailSettings - def self.save(np_id, user_id, params) es = Psql.execute( Qexpr.new.select(:id).from(:email_settings) - .where("nonprofit_id=$id", id: np_id.to_i) - .where("user_id=$id", id: user_id) + .where('nonprofit_id=$id', id: np_id.to_i) + .where('user_id=$id', id: user_id) ).first if es.nil? - es = Psql.execute(Qexpr.new.insert('email_settings', [{nonprofit_id: np_id, user_id: user_id}], {no_timestamps: true})).first + es = Psql.execute(Qexpr.new.insert('email_settings', [{ nonprofit_id: np_id, user_id: user_id }], no_timestamps: true)).first end Psql.execute( Qexpr.new.update(:email_settings, params) - .where("id=$id", id: es['id']) + .where('id=$id', id: es['id']) .returning('*') ).first end diff --git a/lib/update/update_miscellaneous_np_info.rb b/lib/update/update_miscellaneous_np_info.rb index 1dae749d..2e0b37a6 100644 --- a/lib/update/update_miscellaneous_np_info.rb +++ b/lib/update/update_miscellaneous_np_info.rb @@ -1,23 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateMiscellaneousNpInfo def self.update(np_id, misc_settings) - ParamValidation.new({np_id: np_id, misc_settings:misc_settings}, - np_id: {:required => true, :is_integer => true}, - misc_settings: {:required => true, :is_hash => true}) + ParamValidation.new({ np_id: np_id, misc_settings: misc_settings }, + np_id: { required: true, is_integer: true }, + misc_settings: { required: true, is_hash: true }) np = Nonprofit.where('id = ?', np_id).first - raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", {key: :np_id}) unless np + raise ParamValidation::ValidationError.new("Nonprofit #{np_id} does not exist", key: :np_id) unless np + misc = MiscellaneousNpInfo.where('nonprofit_id = ?', np_id).first unless misc misc = MiscellaneousNpInfo.new misc.nonprofit = np end - if (misc_settings[:donate_again_url].present?) + if misc_settings[:donate_again_url].present? misc.donate_again_url = misc_settings[:donate_again_url] end - if (misc_settings[:change_amount_message].present?) - if (Format::HTML.has_only_empty_tags(misc_settings[:change_amount_message])) - misc.change_amount_message= nil; + if misc_settings[:change_amount_message].present? + if Format::HTML.has_only_empty_tags(misc_settings[:change_amount_message]) + misc.change_amount_message = nil else misc.change_amount_message = misc_settings[:change_amount_message] end @@ -26,4 +29,4 @@ module UpdateMiscellaneousNpInfo misc.save! misc end -end \ No newline at end of file +end diff --git a/lib/update/update_nonprofit.rb b/lib/update/update_nonprofit.rb index 78861949..4d890628 100644 --- a/lib/update/update_nonprofit.rb +++ b/lib/update/update_nonprofit.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'query/query_payments' require 'fetch/stripe/fetch_stripe_account' module UpdateNonprofit - # See the stripe docs for reference: => https://stripe.com/docs/connect/identity-verification - def self.verify_identity(np_id, legal_entity, tos=nil) - np = Qx.select("*").from(:nonprofits).where(id: np_id).execute.first + def self.verify_identity(np_id, legal_entity, tos = nil) + np = Qx.select('*').from(:nonprofits).where(id: np_id).execute.first legal_entity[:address][:country] = 'US' if legal_entity[:address] acct = FetchStripeAccount.with_account_id(np['stripe_account_id']) acct.legal_entity.phone_number = acct.support_phone = legal_entity[:phone_number] if legal_entity[:phone_number] @@ -18,48 +19,45 @@ module UpdateNonprofit acct.legal_entity.personal_id_number = legal_entity[:personal_id_number] if legal_entity[:personal_id_number] acct.legal_entity.type = 'company' acct.legal_entity.business_name = np['name'] - if tos - acct.tos_acceptance = tos - end + acct.tos_acceptance = tos if tos acct.save # Might as well update the nonprofit info if legal_entity[:address] && legal_entity[:business_tax_id] - np = Qx.update(:nonprofits).set({ - address: legal_entity[:address][:line1], - city: legal_entity[:address][:city], - state_code: legal_entity[:address][:state], - zip_code: legal_entity[:address][:postal_code], - ein: legal_entity[:business_tax_id], - verification_status: 'pending', - phone: legal_entity[:phone_number] - }) - .where(id: np_id) - .returning('*') - .execute.first + np = Qx.update(:nonprofits).set( + address: legal_entity[:address][:line1], + city: legal_entity[:address][:city], + state_code: legal_entity[:address][:state], + zip_code: legal_entity[:address][:postal_code], + ein: legal_entity[:business_tax_id], + verification_status: 'pending', + phone: legal_entity[:phone_number] + ) + .where(id: np_id) + .returning('*') + .execute.first else np = Qx.update(:nonprofits).set(verification_status: 'pending').where(id: np_id).returning('*').first end - return np + np end - # Update charges from pending to available if the nonprofit's balance on stripe can accommodate them # First, get net balance on Stripe, then get net balance on CC # Take the difference of those two, and mark as many oldest pending charges as 'available' as are less than or equal to that difference def self.mark_available_charges(npo_id) - stripe_account_id = Qx.select("stripe_account_id").from(:nonprofits).where(id: npo_id).ex.first['stripe_account_id'] + stripe_account_id = Qx.select('stripe_account_id').from(:nonprofits).where(id: npo_id).ex.first['stripe_account_id'] stripe_net_balance = Stripe::Balance.retrieve(stripe_account: stripe_account_id).available.first.amount cc_net_balance = QueryPayments.get_payout_totals(QueryPayments.ids_for_payout(npo_id))['net_amount'] - pending_payments = Qx.select("payments.net_amount", "charges.id AS charge_id") - .from(:payments) - .where("charges.status='pending'") - .and_where("payments.nonprofit_id=$id", id: npo_id) - .join("charges", "charges.payment_id=payments.id") - .order_by("payments.date ASC") - .execute + pending_payments = Qx.select('payments.net_amount', 'charges.id AS charge_id') + .from(:payments) + .where("charges.status='pending'") + .and_where('payments.nonprofit_id=$id', id: npo_id) + .join('charges', 'charges.payment_id=payments.id') + .order_by('payments.date ASC') + .execute return if pending_payments.empty? @@ -69,10 +67,8 @@ module UpdateNonprofit remaining_balance -= payment['net_amount'] true end - end.map{|h| h['charge_id']} + end.map { |h| h['charge_id'] } - Qx.update(:charges).set(status: 'available').where("id IN ($ids)", ids: charge_ids).execute if charge_ids.any? + Qx.update(:charges).set(status: 'available').where('id IN ($ids)', ids: charge_ids).execute if charge_ids.any? end - end - diff --git a/lib/update/update_order.rb b/lib/update/update_order.rb index 23738859..4936da86 100644 --- a/lib/update/update_order.rb +++ b/lib/update/update_order.rb @@ -1,15 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module UpdateOrder - # data is an array of hashes of: # - id : id of row to update - # - order: new order of row to update + # - order: new order of row to update def self.with_data(table_name, data) - vals = data.map{|h| "(#{h[:id].to_i}, #{h[:order].to_i})"}.join(", ") + vals = data.map { |h| "(#{h[:id].to_i}, #{h[:order].to_i})" }.join(', ') from_str = "(VALUES #{vals}) AS data(id, \"order\")" - return Qx.update("#{table_name}") + Qx.update(table_name.to_s) .set('"order"="data"."order"') .timestamps .from(from_str) @@ -17,6 +18,4 @@ module UpdateOrder .returning("#{table_name}.order", "#{table_name}.id") .execute end - end - diff --git a/lib/update/update_payouts.rb b/lib/update/update_payouts.rb index 37a795fa..257523f7 100644 --- a/lib/update/update_payouts.rb +++ b/lib/update/update_payouts.rb @@ -1,21 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdatePayouts - def self.reverse_with_stripe(payout_id, status, failure_message) - ParamValidation.new({payout_id:payout_id, status: status, failure_message: failure_message}, { - payout_id: {required: true, is_integer: true}, - status: {included_in:['pending', 'paid', 'canceled', 'failed'], required: true}, - failure_message: {not_blank: true, required: true} - }) + ParamValidation.new({ payout_id: payout_id, status: status, failure_message: failure_message }, + payout_id: { required: true, is_integer: true }, + status: { included_in: %w[pending paid canceled failed], required: true }, + failure_message: { not_blank: true, required: true }) payout = Payout.where('id = ?', payout_id).first unless payout - raise ParamValidation::ValidationError.new("No payout with id number: #{payout_id} ", [{key: :payout_id}]) + raise ParamValidation::ValidationError.new("No payout with id number: #{payout_id} ", [{ key: :payout_id }]) end - payment_ids = payout.payments.select('payments.id').map{|i| i.id}.to_a + payment_ids = payout.payments.select('payments.id').map(&:id).to_a if payment_ids.count < 1 - raise ArgumentError.new("No payments are available to reverse.") + raise ArgumentError, 'No payments are available to reverse.' end + now = Time.current Psql.transaction do @@ -26,16 +27,15 @@ module UpdatePayouts UpdateRefunds.reverse_disburse_all_with_payments(payment_ids) # Mark all disputes as lost_and_paid - #UpdateDisputes.disburse_all_with_payments(payment_ids) + # UpdateDisputes.disburse_all_with_payments(payment_ids) # Get gross total, total fees, net total, and total count # Create the payout record (whether it succeeded on Stripe or not) payout.status = status payout.failure_message = failure_message payout.save! - - #NonprofitMailer.delay.pending_payout_notification(payout['id'].to_i) + # NonprofitMailer.delay.pending_payout_notification(payout['id'].to_i) payout end end -end \ No newline at end of file +end diff --git a/lib/update/update_recurring_donations.rb b/lib/update/update_recurring_donations.rb index 7fb21985..2047b304 100644 --- a/lib/update/update_recurring_donations.rb +++ b/lib/update/update_recurring_donations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'query/query_recurring_donations' require 'insert/insert_supporter_notes' @@ -5,61 +7,55 @@ require 'format/date' require 'format/currency' module UpdateRecurringDonations - # Update the card id and name for a given recurring donation (provide rd['donation_id']) def self.update_card_id(rd, token) rd = rd&.with_indifferent_access - ParamValidation.new({rd: rd, token: token}, - { - rd: {is_hash: true, required: true}, - token: {format: UUID::Regex, required: true} - }) + ParamValidation.new({ rd: rd, token: token }, + rd: { is_hash: true, required: true }, + token: { format: UUID::Regex, required: true }) ParamValidation.new(rd, - { - id: {is_reference: true, required: true} - }) + id: { is_reference: true, required: true }) source_token = QuerySourceToken.get_and_increment_source_token(token, nil) tokenizable = source_token.tokenizable - - entities = RetrieveActiveRecordItems.retrieve_from_keys(rd, RecurringDonation => :id ) + entities = RetrieveActiveRecordItems.retrieve_from_keys(rd, RecurringDonation => :id) validate_entities(entities[:id], tokenizable) Qx.transaction do rec_don = entities[:id] donation = rec_don.donation - #TODO This is stupid but the two are used together inconsistently. We should scrap one or the other. + # TODO: This is stupid but the two are used together inconsistently. We should scrap one or the other. donation.card = tokenizable rec_don.card_id = tokenizable rec_don.n_failures = 0 rec_don.save! donation.save! - InsertSupporterNotes.create([{content: "This supporter updated their card for their recurring donation with ID #{rec_don.id}", supporter_id: rec_don.supporter.id, user_id: 540}]) + InsertSupporterNotes.create([{ content: "This supporter updated their card for their recurring donation with ID #{rec_don.id}", supporter_id: rec_don.supporter.id, user_id: 540 }]) end - return QueryRecurringDonations.fetch_for_edit(rd[:id])['recurring_donation'] + QueryRecurringDonations.fetch_for_edit(rd[:id])['recurring_donation'] end # Update the paydate for a given recurring donation (provide rd['id']) def self.update_paydate(rd, paydate) - return ValidationError.new(['Invalid paydate']) unless (1..28).include?(paydate.to_i) - Psql.execute(Qexpr.new.update(:recurring_donations, paydate: paydate).where("id=$id", id: rd['id'])) + return ValidationError.new(['Invalid paydate']) unless (1..28).cover?(paydate.to_i) + + Psql.execute(Qexpr.new.update(:recurring_donations, paydate: paydate).where('id=$id', id: rd['id'])) rd['paydate'] = paydate - return rd + rd end # @param [RecurringDonation] rd # @param [String] token # @param [Integer] amount def self.update_amount(rd, token, amount) - ParamValidation.new({amount: amount, rd: rd, token: token}, - {amount: {is_integer: true, min: 50, required:true}, - rd: {required:true, is_a: RecurringDonation}, - token: {required:true, format: UUID::Regex} - }) + ParamValidation.new({ amount: amount, rd: rd, token: token }, + amount: { is_integer: true, min: 50, required: true }, + rd: { required: true, is_a: RecurringDonation }, + token: { required: true, format: UUID::Regex }) source_token = QuerySourceToken.get_and_increment_source_token(token, nil) tokenizable = source_token.tokenizable @@ -68,63 +64,58 @@ module UpdateRecurringDonations previous_amount = rd.amount donation = rd.donation Qx.transaction do - #TODO This is stupid but the two are used together inconsistently. We should scrap one or the other. + # TODO: This is stupid but the two are used together inconsistently. We should scrap one or the other. rd.card = tokenizable rd.amount = amount - rd.n_failures= 0 + rd.n_failures = 0 donation.card = tokenizable donation.amount = amount rd.save! donation.save! end EmailJobQueue.queue(JobTypes::NonprofitRecurringDonationChangeAmountJob, rd.id, previous_amount) - EmailJobQueue.queue(JobTypes::DonorRecurringDonationChangeAmountJob,rd.id, previous_amount) + EmailJobQueue.queue(JobTypes::DonorRecurringDonationChangeAmountJob, rd.id, previous_amount) rd end - def self.update_from_start_dates - RecurringDonation.inactive.where("start_date >= ?", Date.today).update_all(active: true) + RecurringDonation.inactive.where('start_date >= ?', Date.today).update_all(active: true) end - def self.update_from_end_dates - RecurringDonation.active.where("end_date < ?", Date.today).update_all(active: false) + RecurringDonation.active.where('end_date < ?', Date.today).update_all(active: false) end - # Cancel a recurring donation (set active='f') and record the supporter/user email who did it - def self.cancel(rd_id, email, dont_notify_nonprofit=false) + def self.cancel(rd_id, email, dont_notify_nonprofit = false) Psql.execute( - Qexpr.new.update(:recurring_donations, { - active: false, - cancelled_by: email, - cancelled_at: Time.current - }) - .where("id=$id", id: rd_id.to_i) + Qexpr.new.update(:recurring_donations, + active: false, + cancelled_by: email, + cancelled_at: Time.current) + .where('id=$id', id: rd_id.to_i) ) rd = QueryRecurringDonations.fetch_for_edit(rd_id)['recurring_donation'] - InsertSupporterNotes.create([{supporter_id: rd['supporter_id'], content: "This supporter's recurring donation for $#{Format::Currency.cents_to_dollars(rd['amount'])} was cancelled by #{rd['cancelled_by']} on #{Format::Date.simple(rd['cancelled_at'])}", user_id: 540}]) - if (!dont_notify_nonprofit) + InsertSupporterNotes.create([{ supporter_id: rd['supporter_id'], content: "This supporter's recurring donation for $#{Format::Currency.cents_to_dollars(rd['amount'])} was cancelled by #{rd['cancelled_by']} on #{Format::Date.simple(rd['cancelled_at'])}", user_id: 540 }]) + unless dont_notify_nonprofit DonationMailer.delay.nonprofit_recurring_donation_cancellation(rd['donation_id']) end - return rd + rd end - def self.update(rd, params) params = set_defaults(params) if params[:donation] rd.donation.update_attributes(params[:donation]) return rd.donation unless rd.donation.valid? + params = params.except(:donation) end rd.update_attributes(params) - return rd + rd end - def self.set_defaults(params) if params[:donation] && params[:donation][:dollars] params[:donation][:amount] = Format::Currency.dollars_to_cents(params[:donation][:dollars]) @@ -141,17 +132,17 @@ module UpdateRecurringDonations params = params.except(:end_date_str) end - return params + params end # @param [RecurringDonation] rd # @param [Card] tokenizable def self.validate_entities(rd, tokenizable) - if (rd.cancelled_at) + if rd.cancelled_at raise ParamValidation::ValidationError.new("Recurring Donation #{rd.id} is already cancelled.", key: :id) end - if (tokenizable.deleted) + if tokenizable.deleted raise ParamValidation::ValidationError.new("Tokenized card #{tokenizable.id} is not valid.", key: :token) end @@ -159,6 +150,4 @@ module UpdateRecurringDonations raise ParamValidation::ValidationError.new("Supporter #{rd.supporter.id} does not own card #{tokenizable.id}", key: :token) end end - end - diff --git a/lib/update/update_refunds.rb b/lib/update/update_refunds.rb index c04cf048..f03f83b5 100644 --- a/lib/update/update_refunds.rb +++ b/lib/update/update_refunds.rb @@ -1,16 +1,17 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateRefunds - - def self.disburse_all_with_payments(payment_ids) + def self.disburse_all_with_payments(payment_ids) expr = Qx.update(:refunds) - .set(disbursed: true) - .timestamps - .where("payment_id IN ($ids)", ids: payment_ids) - .returning('*') - .execute - end + .set(disbursed: true) + .timestamps + .where('payment_id IN ($ids)', ids: payment_ids) + .returning('*') + .execute + end - def self.reverse_disburse_all_with_payments(payment_ids) - Refund.where("payment_id IN (?)", payment_ids).update_all(disbursed:false) - end + def self.reverse_disburse_all_with_payments(payment_ids) + Refund.where('payment_id IN (?)', payment_ids).update_all(disbursed: false) + end end diff --git a/lib/update/update_supporter.rb b/lib/update/update_supporter.rb index c74e379d..37addd8e 100644 --- a/lib/update/update_supporter.rb +++ b/lib/update/update_supporter.rb @@ -1,18 +1,19 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateSupporter - - def self.from_info(supporter, params) - supporter.update_attributes(params) - #GeocodeModel.delay.geocode(supporter) - return supporter - end + def self.from_info(supporter, params) + supporter.update_attributes(params) + # GeocodeModel.delay.geocode(supporter) + supporter + end # Bulk delete, meaning mark all supporters given by a query as deleted='t' def self.bulk_delete(np_id, supporter_ids) Qx.update(:supporters) .set(deleted: true) - .where("id IN ($ids)", ids: supporter_ids) - .and_where("nonprofit_id=$id", id: np_id) + .where('id IN ($ids)', ids: supporter_ids) + .and_where('nonprofit_id=$id', id: np_id) .returning('id') .execute end @@ -20,5 +21,4 @@ module UpdateSupporter def self.general_info(supporter_id, data) Qx.update(:supporters).set(data).where(id: supporter_id).returning('*').ex.last end - end diff --git a/lib/update/update_supporter_notes.rb b/lib/update/update_supporter_notes.rb index 0c0cdd41..99cfbe1c 100644 --- a/lib/update/update_supporter_notes.rb +++ b/lib/update/update_supporter_notes.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'qx' module UpdateSupporterNotes - def self.update(note) Qx.update(:supporter_notes) .set(content: note[:content], user_id: note[:user_id]) @@ -10,17 +11,15 @@ module UpdateSupporterNotes .where(id: note[:id]) .execute UpdateActivities.for_supporter_notes(note) - end + end # sets the deleted column to true on supporter_notes (soft delete) - # and then does a hard delete on the associated activity + # and then does a hard delete on the associated activity def self.delete(id) Qx.update(:supporter_notes) .set(deleted: true) .where(id: id) .execute Qx.delete_from(:activities).where(attachment_id: id).execute - end - + end end - diff --git a/lib/update/update_tickets.rb b/lib/update/update_tickets.rb index 393ba2a9..728c4aeb 100644 --- a/lib/update/update_tickets.rb +++ b/lib/update/update_tickets.rb @@ -1,17 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UpdateTickets + def self.update(data, current_user = nil) + ParamValidation.new(data, + event_id: { required: true, is_reference: true }, + ticket_id: { required: true, is_reference: true }, + token: { format: UUID::Regex }, + bid_id: { is_integer: true }, + # note: nothing to check? - def self.update(data, current_user=nil) - ParamValidation.new(data, { - event_id: {required:true, is_reference: true}, - ticket_id: {required: true, is_reference: true}, - token: {format: UUID::Regex}, - bid_id: {is_integer: true}, - #note: nothing to check? - - checked_in: {included_in: ['true', 'false', true, false]} - - }) + checked_in: { included_in: ['true', 'false', true, false] }) entities = RetrieveActiveRecordItems.retrieve_from_keys(data, Event => :event_id, Ticket => :ticket_id) validate_entities(entities) @@ -78,21 +77,21 @@ module UpdateTickets return { json: { error: "No ticket with id #{ticket_id} at event with id #{event_id}\n #{e.message}" }, status: :unprocessable_entity } rescue ActiveRecord::ActiveRecordError - return { json: { error: "There was a DB error. Please contact support" }, + return { json: { error: 'There was a DB error. Please contact support' }, status: :unprocessable_entity } end end def self.validate_entities(entities) - if (entities[:ticket_id].deleted) + if entities[:ticket_id].deleted raise ParamValidation::ValidationError.new("Ticket ID #{entities[:ticket_id].id} is deleted", key: :ticket_id) end - if (entities[:event_id].deleted) + if entities[:event_id].deleted raise ParamValidation::ValidationError.new("Event ID #{entities[:event_id].id} is deleted", key: :event_id) end - if (entities[:ticket_id].event != entities[:event_id]) + if entities[:ticket_id].event != entities[:event_id] raise ParamValidation::ValidationError.new("Ticket ID #{entities[:ticket_id].id} does not belong to event #{entities[:event_id].id}", key: :ticket_id) end end diff --git a/lib/uuid.rb b/lib/uuid.rb index 4fb82fe5..2bd69d34 100644 --- a/lib/uuid.rb +++ b/lib/uuid.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later module UUID - Regex = /\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?/ -end \ No newline at end of file + Regex = /\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?/.freeze +end diff --git a/lib/validation_error.rb b/lib/validation_error.rb index 1cf68a91..2d5f9aa0 100644 --- a/lib/validation_error.rb +++ b/lib/validation_error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later # A generalized, all purpose struct for database validation errors # .errors is simply array of error messages diff --git a/script/delayed_job b/script/delayed_job index edf19598..4f1b0b2b 100755 --- a/script/delayed_job +++ b/script/delayed_job @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) require 'delayed/command' diff --git a/script/rails b/script/rails index c5b1430b..12b00eff 100755 --- a/script/rails +++ b/script/rails @@ -1,11 +1,13 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. if ENV['RAILS_ENV'] == 'test' require 'simplecov' SimpleCov.start 'rails' - puts "required simplecov" + puts 'required simplecov' end -APP_PATH = File.expand_path('../../config/application', __FILE__) -require File.expand_path('../../config/boot', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) +require File.expand_path('../config/boot', __dir__) require 'rails/commands' diff --git a/spec/api/houdini/nonprofit_spec.rb b/spec/api/houdini/nonprofit_spec.rb index 396cf775..29d84555 100644 --- a/spec/api/houdini/nonprofit_spec.rb +++ b/spec/api/houdini/nonprofit_spec.rb @@ -1,26 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' -describe Houdini::V1::Nonprofit, :type => :request do +describe Houdini::V1::Nonprofit, type: :request do describe 'get' do - end describe 'post' do around(:each) do |example| - @old_bp =Settings.default_bp + @old_bp = Settings.default_bp example.run Settings.default_bp = @old_bp - end def expect_validation_errors(actual, input) expected_errors = input.with_indifferent_access[:errors] - expect(actual["errors"]).to match_array expected_errors + expect(actual['errors']).to match_array expected_errors end def create_errors(*wrapper_params) output = totally_empty_errors - wrapper_params.each {|i| output[:errors].push(h(params: [i], messages: gr_e('presence')))} + wrapper_params.each { |i| output[:errors].push(h(params: [i], messages: gr_e('presence'))) } output end @@ -28,57 +28,57 @@ describe Houdini::V1::Nonprofit, :type => :request do h.with_indifferent_access end - let(:totally_empty_errors) { + let(:totally_empty_errors) do { errors: [ - h(params: ["nonprofit[name]"], messages: gr_e("presence", "blank")), - h(params: ["nonprofit[zip_code]"], messages: gr_e("presence", "blank")), - h(params: ["nonprofit[state_code]"], messages: gr_e("presence", "blank")), - h(params: ["nonprofit[city]"], messages: gr_e("presence", "blank")), + h(params: ['nonprofit[name]'], messages: gr_e('presence', 'blank')), + h(params: ['nonprofit[zip_code]'], messages: gr_e('presence', 'blank')), + h(params: ['nonprofit[state_code]'], messages: gr_e('presence', 'blank')), + h(params: ['nonprofit[city]'], messages: gr_e('presence', 'blank')), - h(params: ["user[name]"], messages: gr_e("presence", "blank")), - h(params: ["user[email]"], messages: gr_e("presence", "blank")), - h(params: ["user[password]"], messages: gr_e("presence", "blank")), - h(params: ["user[password_confirmation]"], messages: gr_e("presence", "blank")), + h(params: ['user[name]'], messages: gr_e('presence', 'blank')), + h(params: ['user[email]'], messages: gr_e('presence', 'blank')), + h(params: ['user[password]'], messages: gr_e('presence', 'blank')), + h(params: ['user[password_confirmation]'], messages: gr_e('presence', 'blank')) ] - }.with_indifferent_access - } + end describe 'authorization' do - around(:each) {|e| + around(:each) do |e| Rails.configuration.action_controller.allow_forgery_protection = true e.run Rails.configuration.action_controller.allow_forgery_protection = false - } + end it 'rejects csrf' do post '/api/v1/nonprofit', params: {}, xhr: true - expect(response.code).to eq "401" + expect(response.code).to eq '401' end end it 'validates nothing' do input = {} post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "400" - expect_validation_errors(JSON.parse(response.body), create_errors("nonprofit", "user")) + expect(response.code).to eq '400' + expect_validation_errors(JSON.parse(response.body), create_errors('nonprofit', 'user')) end it 'validates url, email, phone ' do input = { - nonprofit: { - email: "noemeila", - phone: "notphone", - url: "" - }} + nonprofit: { + email: 'noemeila', + phone: 'notphone', + url: '' + } + } post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "400" - expected = create_errors("user") - expected[:errors].push(h(params:["nonprofit[email]"], messages: gr_e("regexp"))) - #expected[:errors].push(h(params:["nonprofit[phone]"], messages: gr_e("regexp"))) - #expected[:errors].push(h(params:["nonprofit[url]"], messages: gr_e("regexp"))) + expect(response.code).to eq '400' + expected = create_errors('user') + expected[:errors].push(h(params: ['nonprofit[email]'], messages: gr_e('regexp'))) + # expected[:errors].push(h(params:["nonprofit[phone]"], messages: gr_e("regexp"))) + # expected[:errors].push(h(params:["nonprofit[url]"], messages: gr_e("regexp"))) expect_validation_errors(JSON.parse(response.body), expected) end @@ -86,89 +86,84 @@ describe Houdini::V1::Nonprofit, :type => :request do it 'should reject unmatching passwords ' do input = { - user: { - email: "wmeil@email.com", - name: "name", - password: 'password', - password_confirmation: 'doesn\'t match' - } + user: { + email: 'wmeil@email.com', + name: 'name', + password: 'password', + password_confirmation: 'doesn\'t match' + } } post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "400" - expect(JSON.parse(response.body)['errors']).to include(h(params:["user[password]", "user[password_confirmation]"], messages: gr_e("is_equal_to"))) - + expect(response.code).to eq '400' + expect(JSON.parse(response.body)['errors']).to include(h(params: ['user[password]', 'user[password_confirmation]'], messages: gr_e('is_equal_to'))) end it 'attempts to make a slug copy and returns the proper errors' do - force_create(:nonprofit, slug: "n", state_code_slug: "wi", city_slug: "appleton") + force_create(:nonprofit, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton') input = { - nonprofit: {name: "n", state_code: "WI", city: "appleton", zip_code: 54915}, - user: {name: "Name", email: "em@em.com", password: "12345678", password_confirmation: "12345678"} + nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915 }, + user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' } } expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new) post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "400" + expect(response.code).to eq '400' - expect_validation_errors(JSON.parse(response.body), { - errors: [ - h( - params:["nonprofit[name]"], - messages:["has an invalid slug. Contact support for help."] - ) - ] - }) + expect_validation_errors(JSON.parse(response.body), + errors: [ + h( + params: ['nonprofit[name]'], + messages: ['has an invalid slug. Contact support for help.'] + ) + ]) end it 'errors on attempt to add user with email that already exists' do force_create(:user, email: 'em@em.com') input = { - nonprofit: {name: "n", state_code: "WI", city: "appleton", zip_code: 54915}, - user: {name: "Name", email: "em@em.com", password: "12345678", password_confirmation: "12345678"} + nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915 }, + user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' } } post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "400" - - expect_validation_errors(JSON.parse(response.body), { - errors: [ - h( - params:["user[email]"], - messages:["has already been taken"] - ) - ] - }) - + expect(response.code).to eq '400' + expect_validation_errors(JSON.parse(response.body), + errors: [ + h( + params: ['user[email]'], + messages: ['has already been taken'] + ) + ]) end - it "succeeds" do - force_create(:nonprofit, slug: "n", state_code_slug: "wi", city_slug: "appleton") + it 'succeeds' do + force_create(:nonprofit, slug: 'n', state_code_slug: 'wi', city_slug: 'appleton') input = { - nonprofit: {name: "n", state_code: "WI", city: "appleton", zip_code: 54915, url: 'www.cs.c', website: 'www.cs.c'}, - user: {name: "Name", email: "em@em.com", password: "12345678", password_confirmation: "12345678"} + nonprofit: { name: 'n', state_code: 'WI', city: 'appleton', zip_code: 54_915, url: 'www.cs.c', website: 'www.cs.c' }, + user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' } } bp = force_create(:billing_plan) Settings.default_bp.id = bp.id - #expect(Houdini::V1::Nonprofit).to receive(:sign_in) + # expect(Houdini::V1::Nonprofit).to receive(:sign_in) post '/api/v1/nonprofit', params: input, xhr: true - expect(response.code).to eq "201" + expect(response.code).to eq '201' our_np = Nonprofit.all[1] expected_np = { - name: "n", - state_code: "WI", - city: "appleton", - zip_code: "54915", - state_code_slug: "wi", - city_slug: "appleton", - slug: "n-00", - website: 'http://www.cs.c' + name: 'n', + state_code: 'WI', + city: 'appleton', + zip_code: '54915', + state_code_slug: 'wi', + city_slug: 'appleton', + slug: 'n-00', + website: 'http://www.cs.c' }.with_indifferent_access expected_np = our_np.attributes.with_indifferent_access.merge(expected_np) @@ -177,39 +172,33 @@ describe Houdini::V1::Nonprofit, :type => :request do expect(our_np.billing_subscription.billing_plan).to eq bp response_body = { - id: our_np.id + id: our_np.id }.with_indifferent_access expect(JSON.parse(response.body)).to eq response_body user = User.first expected_user = { - email: "em@em.com", - name: "Name" + email: 'em@em.com', + name: 'Name' } expected_user = user.attributes.with_indifferent_access.merge(expected_user) expect(our_np.roles.nonprofit_admins.count).to eq 1 expect(our_np.roles.nonprofit_admins.first.user.attributes).to eq expected_user - - end - - end end - def find_error_message(json, field_name) errors = json['errors'] - error = errors.select {|i| i["params"].any? {|j| j == field_name}}.first - return error if !error - return error["messages"] + error = errors.select { |i| i['params'].any? { |j| j == field_name } }.first + return error unless error + error['messages'] end def gr_e(*keys) - keys.map {|i| I18n.translate("grape.errors.messages." + i, locale: 'en')} - + keys.map { |i| I18n.translate('grape.errors.messages.' + i, locale: 'en') } end diff --git a/spec/api/support/api_shared_user_verification.rb b/spec/api/support/api_shared_user_verification.rb index ade50170..715bd6a8 100644 --- a/spec/api/support/api_shared_user_verification.rb +++ b/spec/api/support/api_shared_user_verification.rb @@ -1,61 +1,61 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'controllers/support/general_shared_user_context' RSpec.shared_context :api_shared_user_verification do include_context :general_shared_user_context - let(:user_as_np_admin) { + let(:user_as_np_admin) do __create_admin(nonprofit) - } + end - let(:user_as_other_np_admin) { + let(:user_as_other_np_admin) do __create_admin(other_nonprofit) - } + end - let(:user_as_np_associate){ + let(:user_as_np_associate) do __create_associate(nonprofit) - } + end - let(:user_as_other_np_associate){ + let(:user_as_other_np_associate) do __create_associate(other_nonprofit) - } + end - let(:unauth_user) { + let(:unauth_user) do force_create(:user) - } + end - - let(:campaign_editor) { + let(:campaign_editor) do __create(:campaign_editor, campaign) - } + end - let(:confirmed_user){ + let(:confirmed_user) do force_create(:user, confirmed_at: Time.current) - } + end - let(:event_editor) { - __create(:event_editor,event) - } + let(:event_editor) do + __create(:event_editor, event) + end - let(:super_admin) { + let(:super_admin) do __create(:super_admin, other_nonprofit) - } + end - let(:user_with_profile) { + let(:user_with_profile) do u = force_create(:user) force_create(:profile, user: u) u - } + end let(:all_users) do - {:user_as_np_admin => user_as_np_admin, - :user_as_other_np_admin => user_as_other_np_admin, - :user_as_np_associate => user_as_np_associate, - :user_as_other_np_associate => user_as_other_np_associate, - :unauth_user => unauth_user, - :campaign_editor => campaign_editor, - :event_editor => event_editor, - :super_admin => super_admin, - :user_with_profile => user_with_profile - } + { user_as_np_admin: user_as_np_admin, + user_as_other_np_admin: user_as_other_np_admin, + user_as_np_associate: user_as_np_associate, + user_as_other_np_associate: user_as_other_np_associate, + unauth_user: unauth_user, + campaign_editor: campaign_editor, + event_editor: event_editor, + super_admin: super_admin, + user_with_profile: user_with_profile } end let(:roles__open_to_all) do @@ -67,40 +67,37 @@ RSpec.shared_context :api_shared_user_verification do :campaign_editor, :event_editor, :super_admin, - :user_with_profile - ] + :user_with_profile] end let(:roles__open_to_np_associate) do - [:user_as_np_admin, + %i[user_as_np_admin - :user_as_np_associate, + user_as_np_associate - :super_admin - - ] + super_admin] end def __create(name, host) u = force_create(:user) - force_create(:role, user: u, name: name, host:host) + force_create(:role, user: u, name: name, host: host) u end def __create_admin(host) u = force_create(:user) - force_create(:role, user: u, name: :nonprofit_admin, host:host) + force_create(:role, user: u, name: :nonprofit_admin, host: host) u end def __create_associate(host) u = force_create(:user) - force_create(:role, user: u, name: :nonprofit_associate, host:host) + force_create(:role, user: u, name: :nonprofit_associate, host: host) u end def sign_in(user_to_signin) - post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: "json" + post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: 'json' end def sign_out @@ -110,38 +107,37 @@ RSpec.shared_context :api_shared_user_verification do def send(method, *args) case method when :get - return xhr(:get, *args) + xhr(:get, *args) when :post - return xhr(:post, *args) + xhr(:post, *args) when :delete - return xhr(:delete, *args) + xhr(:delete, *args) when :put - return xhr(:put, *args) + xhr(:put, *args) end end def accept(user_to_signin:, method:, action:, args:) new_user = user_to_signin - if (user_to_signin != nil && user_to_signin.is_a?(OpenStruct)) + if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct) new_user = user_to_signin.value end sign_in new_user if new_user # allows us to run the helpers but ignore what the controller action does # send(method, action, args) - expect(response.status).to eq(200), "expcted success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : "")} #{new_user&.attributes}" + expect(response.status).to eq(200), "expcted success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" sign_out end def reject(user_to_signin:, method:, action:, args:) - new_user = user_to_signin - if (user_to_signin != nil && user_to_signin.is_a?(OpenStruct)) + if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct) new_user = user_to_signin.value end sign_in new_user if new_user send(method, action, args) - expect(response.status).to eq(401), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : "")} #{new_user&.attributes}" + expect(response.status).to eq(401), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" sign_out end @@ -151,29 +147,26 @@ RSpec.shared_context :api_shared_user_verification do @method = details[:method] @successful_users = details[:successful_users] @action = details[:action] - @block_to_get_arguments_to_run = block || ->(_) {} #no-op + @block_to_get_arguments_to_run = block || ->(_) {} # no-op accept_test_for_nil = false - all_users.each do |k,v| + all_users.each do |k, v| os = OpenStruct.new os.key = k os.value = v if k.nil? - accept(user_to_signin: nil, method:@method, action: @action, args: @block_to_get_arguments_to_run.call(v)) + accept(user_to_signin: nil, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v)) accept_test_for_nil = true end if @successful_users.include? k - accept(user_to_signin: os, method:@method, action: @action, args: @block_to_get_arguments_to_run.call(v)) + accept(user_to_signin: os, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v)) else - reject(user_to_signin: os, method:@method, action: @action, args: @block_to_get_arguments_to_run.call(v)) + reject(user_to_signin: os, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(v)) end end unless accept_test_for_nil - reject(user_to_signin: nil, method:@method, action: @action, args: @block_to_get_arguments_to_run.call(nil)) + reject(user_to_signin: nil, method: @method, action: @action, args: @block_to_get_arguments_to_run.call(nil)) end end - end - - diff --git a/spec/controllers/aws_presigned_posts_spec.rb b/spec/controllers/aws_presigned_posts_spec.rb index 51e71c04..d36a52f3 100644 --- a/spec/controllers/aws_presigned_posts_spec.rb +++ b/spec/controllers/aws_presigned_posts_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe AwsPresignedPostsController, :type => :controller do +describe AwsPresignedPostsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do @@ -11,4 +13,4 @@ describe AwsPresignedPostsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/billing_subscriptions_spec.rb b/spec/controllers/billing_subscriptions_spec.rb index 0ec55691..e5c99e13 100644 --- a/spec/controllers/billing_subscriptions_spec.rb +++ b/spec/controllers/billing_subscriptions_spec.rb @@ -1,24 +1,26 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe BillingSubscriptionsController, :type => :controller do +describe BillingSubscriptionsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'create_trial' do - include_context :open_to_np_admin, :post, :create_trial, nonprofit_id: :__our_np + include_context :open_to_np_admin, :post, :create_trial, nonprofit_id: :__our_np end describe 'create' do - include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np + include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np end describe 'cancel' do - include_context :open_to_np_admin, :post, :cancel, nonprofit_id: :__our_np + include_context :open_to_np_admin, :post, :cancel, nonprofit_id: :__our_np end describe 'cancellation' do - include_context :open_to_np_admin, :get, :cancellation, nonprofit_id: :__our_np + include_context :open_to_np_admin, :get, :cancellation, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaign_gift_options_spec.rb b/spec/controllers/campaign_gift_options_spec.rb index 84d20f4f..11bbbcb9 100644 --- a/spec/controllers/campaign_gift_options_spec.rb +++ b/spec/controllers/campaign_gift_options_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe CampaignGiftOptionsController, :type => :controller do +describe CampaignGiftOptionsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'reject unauthorized' do @@ -11,14 +13,14 @@ describe CampaignGiftOptionsController, :type => :controller do end describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' end describe 'destroy' do - include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" + include_context :open_to_campaign_editor, :delete, :destroy, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' end describe 'update_order' do - include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" + include_context :open_to_campaign_editor, :put, :update_order, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' end end @@ -28,8 +30,8 @@ describe CampaignGiftOptionsController, :type => :controller do end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: "1" + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, campaign_id: :__our_campaign, id: '1' end end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaign_gifts_spec.rb b/spec/controllers/campaign_gifts_spec.rb index 06f3f599..52356cd7 100644 --- a/spec/controllers/campaign_gifts_spec.rb +++ b/spec/controllers/campaign_gifts_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe CampaignGiftsController, :type => :controller do +describe CampaignGiftsController, type: :controller do describe 'authorization' do include_context :shared_user_context @@ -12,4 +14,4 @@ describe CampaignGiftsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaigns/campaign_gift_options_spec.rb b/spec/controllers/campaigns/campaign_gift_options_spec.rb index 58221ca4..3bbad02a 100644 --- a/spec/controllers/campaigns/campaign_gift_options_spec.rb +++ b/spec/controllers/campaigns/campaign_gift_options_spec.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Campaigns::CampaignGiftOptionsController, :type => :controller do +describe Campaigns::CampaignGiftOptionsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'accept all' do describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaigns/donations_spec.rb b/spec/controllers/campaigns/donations_spec.rb index 11c40336..06be9a01 100644 --- a/spec/controllers/campaigns/donations_spec.rb +++ b/spec/controllers/campaigns/donations_spec.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Campaigns::DonationsController, :type => :controller do +describe Campaigns::DonationsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'reject unauthorized' do describe 'index' do - include_context :open_to_campaign_editor, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign + include_context :open_to_campaign_editor, :get, :index, nonprofit_id: :__our_np, campaign_id: :__our_campaign end end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaigns/supporters_spec.rb b/spec/controllers/campaigns/supporters_spec.rb index fcaf2d22..100d280c 100644 --- a/spec/controllers/campaigns/supporters_spec.rb +++ b/spec/controllers/campaigns/supporters_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Campaigns::SupportersController, :type => :controller do +describe Campaigns::SupportersController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'reject unauthorized' do @@ -11,4 +13,4 @@ describe Campaigns::SupportersController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/campaigns_spec.rb b/spec/controllers/campaigns_spec.rb index 4673e8b0..b95770c5 100644 --- a/spec/controllers/campaigns_spec.rb +++ b/spec/controllers/campaigns_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe CampaignsController, :type => :controller do +describe CampaignsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do @@ -19,48 +21,47 @@ describe CampaignsController, :type => :controller do end describe 'update' do - include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_campaign_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_campaign end describe 'soft_delete' do - include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_campaign_editor, :delete, :soft_delete, nonprofit_id: :__our_np, id: :__our_campaign end - end describe 'open to all' do describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_campaign end describe 'activities' do - include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_campaign end describe 'metrics' do - include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_campaign end describe 'timeline' do - include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_all, :get, :timeline, nonprofit_id: :__our_np, id: :__our_campaign end describe 'totals' do - include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, id: :__our_campaign + include_context :open_to_all, :get, :totals, nonprofit_id: :__our_np, id: :__our_campaign end describe 'peer_to_peer' do - include_context :open_to_all, :get, :peer_to_peer, nonprofit_id: :__our_np + include_context :open_to_all, :get, :peer_to_peer, nonprofit_id: :__our_np end end end describe 'routes' do - it "routes campaigns#index" do - expect(get: "/nonprofits/5/campaigns/4").to(route_to(controller: "campaigns", action: "show", nonprofit_id: "5", id: "4")) + it 'routes campaigns#index' do + expect(get: '/nonprofits/5/campaigns/4').to(route_to(controller: 'campaigns', action: 'show', nonprofit_id: '5', id: '4')) end end end diff --git a/spec/controllers/cards_spec.rb b/spec/controllers/cards_spec.rb index 3aac440b..8fd67de8 100644 --- a/spec/controllers/cards_spec.rb +++ b/spec/controllers/cards_spec.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe CardsController, :type => :controller do +describe CardsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'accept all' do describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end end -end \ No newline at end of file +end diff --git a/spec/controllers/direct_debit_details_spec.rb b/spec/controllers/direct_debit_details_spec.rb index 44f29060..72c068d6 100644 --- a/spec/controllers/direct_debit_details_spec.rb +++ b/spec/controllers/direct_debit_details_spec.rb @@ -1,16 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe DirectDebitDetailsController, :type => :controller do +describe DirectDebitDetailsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'open to all' do describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end - - end end -end \ No newline at end of file +end diff --git a/spec/controllers/email_settings_spec.rb b/spec/controllers/email_settings_spec.rb index 9b7c49dd..dcc76e12 100644 --- a/spec/controllers/email_settings_spec.rb +++ b/spec/controllers/email_settings_spec.rb @@ -1,21 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe EmailSettingsController, :type => :controller do +describe EmailSettingsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do - include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np + include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end describe 'index' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end - end - - end -end \ No newline at end of file +end diff --git a/spec/controllers/emails_spec.rb b/spec/controllers/emails_spec.rb index 26d1eb40..cc0c3d00 100644 --- a/spec/controllers/emails_spec.rb +++ b/spec/controllers/emails_spec.rb @@ -1,16 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe EmailsController, :type => :controller do +describe EmailsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do include_context :open_to_registered, :post, :create end - - end end -end \ No newline at end of file +end diff --git a/spec/controllers/event_discounts_spec.rb b/spec/controllers/event_discounts_spec.rb index 4a723b8f..b3775bfc 100644 --- a/spec/controllers/event_discounts_spec.rb +++ b/spec/controllers/event_discounts_spec.rb @@ -1,30 +1,30 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe EventDiscountsController, :type => :controller do +describe EventDiscountsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event end - + describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end - + describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end - - end - + describe 'open to all' do describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, id: "2" + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end end end -end \ No newline at end of file +end diff --git a/spec/controllers/events_spec.rb b/spec/controllers/events_spec.rb index 5d832eb6..7ae705c8 100644 --- a/spec/controllers/events_spec.rb +++ b/spec/controllers/events_spec.rb @@ -1,53 +1,51 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe EventsController, :type => :controller do +describe EventsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, id: :__our_event end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, id: :__our_event end describe 'duplicate' do - include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_event_editor, :post, :duplicate, nonprofit_id: :__our_np, id: :__our_event end describe 'soft_delete' do - include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :delete, :soft_delete, nonprofit_id: :__our_np, event_id: :__our_event end describe 'stats' do - include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_event_editor, :get, :stats, nonprofit_id: :__our_np, id: :__our_event end describe 'name_and_id' do - include_context :open_to_np_associate, :get, :name_and_id, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :name_and_id, nonprofit_id: :__our_np end end describe 'open to all' do describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np end describe 'listings' do - include_context :open_to_all, :get, :listings, nonprofit_id: :__our_np + include_context :open_to_all, :get, :listings, nonprofit_id: :__our_np end describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, id: :__our_event end describe 'activities' do - include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_all, :get, :activities, nonprofit_id: :__our_np, id: :__our_event end describe 'metrics' do - include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_event + include_context :open_to_all, :get, :metrics, nonprofit_id: :__our_np, id: :__our_event end - - - end - -end \ No newline at end of file +end diff --git a/spec/controllers/front_spec.rb b/spec/controllers/front_spec.rb index b64291c6..0161360b 100644 --- a/spec/controllers/front_spec.rb +++ b/spec/controllers/front_spec.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe FrontController, :type => :controller do +describe FrontController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'accept all' do describe 'index' do - include_context :open_to_all, :get, :index + include_context :open_to_all, :get, :index end end end it 'index redirects to onboard with no non-profits' do - get( :index) + get(:index) expect(response).to redirect_to onboard_url end @@ -37,6 +39,5 @@ describe FrontController, :type => :controller do get(:index) expect(response).to redirect_to profile_url(unauth_user.profile.id) end - end -end \ No newline at end of file +end diff --git a/spec/controllers/image_attachments_spec.rb b/spec/controllers/image_attachments_spec.rb index c38ec151..cfd6dab1 100644 --- a/spec/controllers/image_attachments_spec.rb +++ b/spec/controllers/image_attachments_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe ImageAttachmentsController, :type => :controller do +describe ImageAttachmentsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do @@ -15,4 +17,4 @@ describe ImageAttachmentsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/maps_spec.rb b/spec/controllers/maps_spec.rb index 6fcebd00..b70595f8 100644 --- a/spec/controllers/maps_spec.rb +++ b/spec/controllers/maps_spec.rb @@ -1,30 +1,30 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe MapsController, :type => :controller do +describe MapsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'all_supporters' do - include_context :open_to_super_admin, :get, :all_supporters + include_context :open_to_super_admin, :get, :all_supporters end describe 'all_npo_supporters' do - include_context :open_to_np_associate, :get, :all_npo_supporters, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :all_npo_supporters, nonprofit_id: :__our_np end describe 'specific_npo_supporters' do - include_context :open_to_np_associate, :get, :specific_npo_supporters, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :specific_npo_supporters, nonprofit_id: :__our_np end end describe 'open_to_all' do describe 'all_npos' do - include_context :open_to_all, :get, :all_npos, nonprofit_id: :__our_np + include_context :open_to_all, :get, :all_npos, nonprofit_id: :__our_np end - - end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/activities_spec.rb b/spec/controllers/nonprofits/activities_spec.rb index ec3dd383..dd284891 100644 --- a/spec/controllers/nonprofits/activities_spec.rb +++ b/spec/controllers/nonprofits/activities_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::ActivitiesController, :type => :controller do +describe Nonprofits::ActivitiesController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do @@ -11,4 +13,4 @@ describe Nonprofits::ActivitiesController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/bank_accounts_spec.rb b/spec/controllers/nonprofits/bank_accounts_spec.rb index a9a9c10b..f58bc0ca 100644 --- a/spec/controllers/nonprofits/bank_accounts_spec.rb +++ b/spec/controllers/nonprofits/bank_accounts_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::BankAccountsController, :type => :controller do +describe Nonprofits::BankAccountsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'create' do @@ -29,4 +31,4 @@ describe Nonprofits::BankAccountsController, :type => :controller do include_context :open_to_np_admin, :post, :resend_confirmation, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/button_spec.rb b/spec/controllers/nonprofits/button_spec.rb index cd60b48e..683d2e8e 100644 --- a/spec/controllers/nonprofits/button_spec.rb +++ b/spec/controllers/nonprofits/button_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::ButtonController, :type => :controller do +describe Nonprofits::ButtonController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'send_code' do @@ -20,7 +22,5 @@ describe Nonprofits::ButtonController, :type => :controller do describe 'advanced' do include_context :open_to_registered, :get, :advanced, nonprofit_id: :__our_np end - - end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/cards_spec.rb b/spec/controllers/nonprofits/cards_spec.rb index bf539727..f0568692 100644 --- a/spec/controllers/nonprofits/cards_spec.rb +++ b/spec/controllers/nonprofits/cards_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::CardsController, :type => :controller do +describe Nonprofits::CardsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'show' do @@ -13,4 +15,4 @@ describe Nonprofits::CardsController, :type => :controller do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/charges_spec.rb b/spec/controllers/nonprofits/charges_spec.rb index 0bc2f4fd..d6325ed5 100644 --- a/spec/controllers/nonprofits/charges_spec.rb +++ b/spec/controllers/nonprofits/charges_spec.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::ChargesController, :type => :controller do +describe Nonprofits::ChargesController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'get' do include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/custom_field_masters_spec.rb b/spec/controllers/nonprofits/custom_field_masters_spec.rb index a7bf7953..318f4146 100644 --- a/spec/controllers/nonprofits/custom_field_masters_spec.rb +++ b/spec/controllers/nonprofits/custom_field_masters_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::CustomFieldMastersController, :type => :controller do +describe Nonprofits::CustomFieldMastersController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'get payments' do @@ -17,4 +19,4 @@ describe Nonprofits::CustomFieldMastersController, :type => :controller do include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/custom_fields_joins_spec.rb b/spec/controllers/nonprofits/custom_fields_joins_spec.rb index ab3a4e2d..b58f1acf 100644 --- a/spec/controllers/nonprofits/custom_fields_joins_spec.rb +++ b/spec/controllers/nonprofits/custom_fields_joins_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::CustomFieldJoinsController, :type => :controller do +describe Nonprofits::CustomFieldJoinsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'index' do @@ -10,11 +12,11 @@ describe Nonprofits::CustomFieldJoinsController, :type => :controller do end describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: "1" + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: "1", supporter_id: 1 + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 1 end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/donations_spec.rb b/spec/controllers/nonprofits/donations_spec.rb index 79614910..f9c85070 100644 --- a/spec/controllers/nonprofits/donations_spec.rb +++ b/spec/controllers/nonprofits/donations_spec.rb @@ -1,25 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' require 'controllers/support/new_controller_user_context' require 'support/contexts/shared_donation_charge_context' -describe Nonprofits::DonationsController, :type => :controller do - +describe Nonprofits::DonationsController, type: :controller do describe 'rejects unauthenticated users' do describe 'index' do include_context :shared_user_context - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, id: "1" + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, id: '1' end - - describe 'update' do include_context :shared_user_context - include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: "1" + include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' end - - end describe 'accept all users' do describe 'create' do @@ -27,12 +24,12 @@ describe Nonprofits::DonationsController, :type => :controller do end describe 'follow up' do - include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np, id: "1" + include_context :open_to_all, :put, :followup, nonprofit_id: :__our_np, id: '1' end end end -describe '.create_offsite', :type => :request do +describe '.create_offsite', type: :request do describe 'create_offsite' do include_context :shared_donation_charge_context include_context :general_shared_user_context @@ -45,6 +42,6 @@ describe '.create_offsite', :type => :request do # donation: {campaign_id: campaign.id}} # end # end - #include_context :open_to_np_associate, :post, :create_offsite, nonprofit_id: :__our_np + # include_context :open_to_np_associate, :post, :create_offsite, nonprofit_id: :__our_np end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/email_lists_spec.rb b/spec/controllers/nonprofits/email_lists_spec.rb index 737f3e62..6c094e2e 100644 --- a/spec/controllers/nonprofits/email_lists_spec.rb +++ b/spec/controllers/nonprofits/email_lists_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::EmailListsController, :type => :controller do +describe Nonprofits::EmailListsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'index' do @@ -13,4 +15,4 @@ describe Nonprofits::EmailListsController, :type => :controller do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/imports_spec.rb b/spec/controllers/nonprofits/imports_spec.rb index 93f2f833..ac599957 100644 --- a/spec/controllers/nonprofits/imports_spec.rb +++ b/spec/controllers/nonprofits/imports_spec.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::ImportsController, :type => :controller do +describe Nonprofits::ImportsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'create' do include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb b/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb index 2c6f7720..7fb3d53d 100644 --- a/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb +++ b/spec/controllers/nonprofits/miscellaneous_np_infos_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::MiscellaneousNpInfosController, :type => :controller do +describe Nonprofits::MiscellaneousNpInfosController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'show' do @@ -13,4 +15,4 @@ describe Nonprofits::MiscellaneousNpInfosController, :type => :controller do include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/nonprofit_keys_spec.rb b/spec/controllers/nonprofits/nonprofit_keys_spec.rb index 13ed8c12..0832490d 100644 --- a/spec/controllers/nonprofits/nonprofit_keys_spec.rb +++ b/spec/controllers/nonprofits/nonprofit_keys_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::NonprofitKeysController, :type => :controller do +describe Nonprofits::NonprofitKeysController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'index' do @@ -17,4 +19,4 @@ describe Nonprofits::NonprofitKeysController, :type => :controller do include_context :open_to_np_associate, :get, :mailchimp_landing, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/payments_spec.rb b/spec/controllers/nonprofits/payments_spec.rb index 7750b6df..7c533242 100644 --- a/spec/controllers/nonprofits/payments_spec.rb +++ b/spec/controllers/nonprofits/payments_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::PaymentsController, :type => :controller do +describe Nonprofits::PaymentsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'get payments' do @@ -25,4 +27,4 @@ describe Nonprofits::PaymentsController, :type => :controller do include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/payouts_spec.rb b/spec/controllers/nonprofits/payouts_spec.rb index 82a5fc96..8060d17c 100644 --- a/spec/controllers/nonprofits/payouts_spec.rb +++ b/spec/controllers/nonprofits/payouts_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::PayoutsController, :type => :controller do +describe Nonprofits::PayoutsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'create' do @@ -16,7 +18,5 @@ describe Nonprofits::PayoutsController, :type => :controller do describe 'show' do include_context :open_to_np_associate, :get, :show, nonprofit_id: :__our_np, id: '1' end - - end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/recurring_donations_spec.rb b/spec/controllers/nonprofits/recurring_donations_spec.rb index 4ad14e70..e3de65a8 100644 --- a/spec/controllers/nonprofits/recurring_donations_spec.rb +++ b/spec/controllers/nonprofits/recurring_donations_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::RecurringDonationsController, :type => :controller do +describe Nonprofits::RecurringDonationsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'index' do @@ -24,8 +26,6 @@ describe Nonprofits::RecurringDonationsController, :type => :controller do describe 'update' do include_context :open_to_np_associate, :put, :update, nonprofit_id: :__our_np, id: '1' end - - end describe 'open for all' do @@ -33,4 +33,4 @@ describe Nonprofits::RecurringDonationsController, :type => :controller do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/reports_spec.rb b/spec/controllers/nonprofits/reports_spec.rb index 203d51e2..d401b78f 100644 --- a/spec/controllers/nonprofits/reports_spec.rb +++ b/spec/controllers/nonprofits/reports_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::ReportsController, :type => :controller do +describe Nonprofits::ReportsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'end_of_year' do @@ -13,4 +15,4 @@ describe Nonprofits::ReportsController, :type => :controller do include_context :open_to_np_associate, :get, :end_of_year_custom, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/supporter_emails_spec.rb b/spec/controllers/nonprofits/supporter_emails_spec.rb index 66410728..681aa5f2 100644 --- a/spec/controllers/nonprofits/supporter_emails_spec.rb +++ b/spec/controllers/nonprofits/supporter_emails_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::SupporterEmailsController, :type => :controller do +describe Nonprofits::SupporterEmailsController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'create' do @@ -13,4 +15,4 @@ describe Nonprofits::SupporterEmailsController, :type => :controller do include_context :open_to_np_associate, :post, :gmail, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/supporters_spec.rb b/spec/controllers/nonprofits/supporters_spec.rb index ac544e24..70cd8bfa 100644 --- a/spec/controllers/nonprofits/supporters_spec.rb +++ b/spec/controllers/nonprofits/supporters_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::SupportersController, :type => :controller do +describe Nonprofits::SupportersController, type: :controller do include_context :shared_user_context describe 'rejects unauthenticated users' do describe 'index' do @@ -47,4 +49,4 @@ describe Nonprofits::SupportersController, :type => :controller do include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/tag_joins_spec.rb b/spec/controllers/nonprofits/tag_joins_spec.rb index a9ff6327..70138d13 100644 --- a/spec/controllers/nonprofits/tag_joins_spec.rb +++ b/spec/controllers/nonprofits/tag_joins_spec.rb @@ -1,22 +1,22 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::TagJoinsController, :type => :controller do +describe Nonprofits::TagJoinsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'index' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1 + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np, supporter_id: 1 end - + describe 'modify' do - include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_associate, :post, :modify, nonprofit_id: :__our_np, id: '1' end - + describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 2 + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1', supporter_id: 2 end - - end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/tag_masters_spec.rb b/spec/controllers/nonprofits/tag_masters_spec.rb index 999f4072..7239c435 100644 --- a/spec/controllers/nonprofits/tag_masters_spec.rb +++ b/spec/controllers/nonprofits/tag_masters_spec.rb @@ -1,22 +1,24 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::TagMastersController, :type => :controller do +describe Nonprofits::TagMastersController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'index' do - include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np + include_context :open_to_np_associate, :get, :index, nonprofit_id: :__our_np end describe 'create' do - include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np + include_context :open_to_np_associate, :post, :create, nonprofit_id: :__our_np end describe 'destroy' do - include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_associate, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits/trackings_spec.rb b/spec/controllers/nonprofits/trackings_spec.rb index fd27c4f9..4ec0311c 100644 --- a/spec/controllers/nonprofits/trackings_spec.rb +++ b/spec/controllers/nonprofits/trackings_spec.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe Nonprofits::TrackingsController, :type => :controller do +describe Nonprofits::TrackingsController, type: :controller do include_context :shared_user_context describe 'open to all' do describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end end -end \ No newline at end of file +end diff --git a/spec/controllers/nonprofits_spec.rb b/spec/controllers/nonprofits_spec.rb index 67b6fe6f..8b74c98a 100644 --- a/spec/controllers/nonprofits_spec.rb +++ b/spec/controllers/nonprofits_spec.rb @@ -1,73 +1,73 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe NonprofitsController, :type => :controller do +describe NonprofitsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'update' do - include_context :open_to_np_associate, :put, :update, id: :__our_np + include_context :open_to_np_associate, :put, :update, id: :__our_np end describe 'dashboard' do - include_context :open_to_np_associate, :get, :dashboard, id: :__our_np + include_context :open_to_np_associate, :get, :dashboard, id: :__our_np end describe 'dashboard_metrics' do - include_context :open_to_np_associate, :get, :dashboard_metrics, id: :__our_np + include_context :open_to_np_associate, :get, :dashboard_metrics, id: :__our_np end describe 'verify_identity' do - include_context :open_to_np_associate, :put, :verify_identity, id: :__our_np + include_context :open_to_np_associate, :put, :verify_identity, id: :__our_np end describe 'recurring_donation_stats' do - include_context :open_to_np_associate, :get, :recurring_donation_stats, id: :__our_np + include_context :open_to_np_associate, :get, :recurring_donation_stats, id: :__our_np end describe 'profile_todos' do - include_context :open_to_np_associate, :get, :profile_todos, id: :__our_np + include_context :open_to_np_associate, :get, :profile_todos, id: :__our_np end describe 'dashboard_todos' do - include_context :open_to_np_associate, :get, :dashboard_todos, id: :__our_np + include_context :open_to_np_associate, :get, :dashboard_todos, id: :__our_np end describe 'payment_history' do - include_context :open_to_np_associate, :get, :payment_history, id: :__our_np + include_context :open_to_np_associate, :get, :payment_history, id: :__our_np end - - describe 'destroy' do - include_context :open_to_super_admin, :delete, :destroy, id: :__our_np + include_context :open_to_super_admin, :delete, :destroy, id: :__our_np end end describe 'open to all' do describe 'show' do - include_context :open_to_all, :get, :show, id: :__our_np + include_context :open_to_all, :get, :show, id: :__our_np end describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np end describe 'btn' do - include_context :open_to_all, :get, :btn, id: :__our_np + include_context :open_to_all, :get, :btn, id: :__our_np end describe 'supporter_form' do - include_context :open_to_all, :get, :supporter_form, id: :__our_np + include_context :open_to_all, :get, :supporter_form, id: :__our_np end describe 'custom_supporter' do - include_context :open_to_all, :post, :custom_supporter, id: :__our_np + include_context :open_to_all, :post, :custom_supporter, id: :__our_np end describe 'donate' do - include_context :open_to_all, :get, :donate, id: :__our_np + include_context :open_to_all, :get, :donate, id: :__our_np end describe 'search' do @@ -75,4 +75,4 @@ describe NonprofitsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/onboard_controller_spec.rb b/spec/controllers/onboard_controller_spec.rb index 0471da11..7e7b0dcc 100644 --- a/spec/controllers/onboard_controller_spec.rb +++ b/spec/controllers/onboard_controller_spec.rb @@ -1,5 +1,6 @@ +# frozen_string_literal: true + require 'rails_helper' -RSpec.describe OnboardController, :type => :controller do - +RSpec.describe OnboardController, type: :controller do end diff --git a/spec/controllers/profiles_spec.rb b/spec/controllers/profiles_spec.rb index 764f08b5..e777f38c 100644 --- a/spec/controllers/profiles_spec.rb +++ b/spec/controllers/profiles_spec.rb @@ -1,21 +1,23 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe ProfilesController, :type => :controller do +describe ProfilesController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'update' do - include_context :open_to_profile_owner, :put, :update, id: :__our_profile + include_context :open_to_profile_owner, :put, :update, id: :__our_profile end describe 'fundraisers' do - include_context :open_to_profile_owner, :get, :fundraisers, id: :__our_profile + include_context :open_to_profile_owner, :get, :fundraisers, id: :__our_profile end describe 'donations_history' do - include_context :open_to_profile_owner, :get, :donations_history, id: :__our_profile + include_context :open_to_profile_owner, :get, :donations_history, id: :__our_profile end end @@ -25,4 +27,4 @@ describe ProfilesController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/recurring_donations_spec.rb b/spec/controllers/recurring_donations_spec.rb index 122a04cc..d6d8e966 100644 --- a/spec/controllers/recurring_donations_spec.rb +++ b/spec/controllers/recurring_donations_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe RecurringDonationsController, :type => :controller do +describe RecurringDonationsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'open to all (note: edit token is checked inside methods)' do @@ -23,4 +25,4 @@ describe RecurringDonationsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/roles_spec.rb b/spec/controllers/roles_spec.rb index 6b746d62..364a17c7 100644 --- a/spec/controllers/roles_spec.rb +++ b/spec/controllers/roles_spec.rb @@ -1,20 +1,20 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe RolesController, :type => :controller do +describe RolesController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do - include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np + include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np end - + describe 'destroy' do - include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np, id: '1' + include_context :open_to_np_admin, :delete, :destroy, nonprofit_id: :__our_np, id: '1' end - - end end -end \ No newline at end of file +end diff --git a/spec/controllers/settings_spec.rb b/spec/controllers/settings_spec.rb index 31ac7c28..61f42021 100644 --- a/spec/controllers/settings_spec.rb +++ b/spec/controllers/settings_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe SettingsController, :type => :controller do +describe SettingsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do @@ -11,4 +13,4 @@ describe SettingsController, :type => :controller do end end end -end \ No newline at end of file +end diff --git a/spec/controllers/static_controller_spec.rb b/spec/controllers/static_controller_spec.rb index dc1a1a88..3c1ffc22 100644 --- a/spec/controllers/static_controller_spec.rb +++ b/spec/controllers/static_controller_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' -RSpec.describe StaticController, :type => :controller do - describe ".ccs" do +RSpec.describe StaticController, type: :controller do + describe '.ccs' do around(:each) do |example| example.run Settings.reload! @@ -11,36 +13,30 @@ RSpec.describe StaticController, :type => :controller do describe 'local_tar_gz' do before (:each) do Settings.merge!( - { - ccs: { - ccs_method: 'local_tar_gz', - } - }) + ccs: { + ccs_method: 'local_tar_gz' + } + ) end - it 'fails on git archive' do expect(Kernel).to receive(:system).and_return(false) get('ccs') expect(response.status).to eq 500 end - end it 'setup github' do - Settings.merge!( - { - ccs: { - ccs_method: 'github', - options: { - account: 'account', - repo: 'repo' - } - } - }) + Settings[:ccs] = { + ccs_method: 'github', + options: { + account: 'account', + repo: 'repo' + } + } expect(File).to receive(:read).with("#{Rails.root}/CCS_HASH").and_return("hash\n") get('ccs') - expect(response).to redirect_to "https://github.com/account/repo/tree/hash" + expect(response).to redirect_to 'https://github.com/account/repo/tree/hash' end end end diff --git a/spec/controllers/super_admins_spec.rb b/spec/controllers/super_admins_spec.rb index af6e5c46..418d551b 100644 --- a/spec/controllers/super_admins_spec.rb +++ b/spec/controllers/super_admins_spec.rb @@ -1,28 +1,28 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe SuperAdminsController, :type => :controller do +describe SuperAdminsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'search_nonprofits' do - include_context :open_to_super_admin, :get, :search_nonprofits + include_context :open_to_super_admin, :get, :search_nonprofits end describe 'search_profiles' do - include_context :open_to_super_admin, :get, :search_profiles + include_context :open_to_super_admin, :get, :search_profiles end describe 'search_fullcontact' do - include_context :open_to_super_admin, :get, :search_fullcontact + include_context :open_to_super_admin, :get, :search_fullcontact end describe 'index' do - include_context :open_to_super_admin, :get, :index + include_context :open_to_super_admin, :get, :index end - - end end -end \ No newline at end of file +end diff --git a/spec/controllers/support/new_controller_user_context.rb b/spec/controllers/support/new_controller_user_context.rb index 7c08bf81..37fb793d 100644 --- a/spec/controllers/support/new_controller_user_context.rb +++ b/spec/controllers/support/new_controller_user_context.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'support/contexts/general_shared_user_context' @@ -5,7 +7,7 @@ RSpec.shared_context :new_controller_user_context do include_context :general_shared_user_context def sign_in(user_to_signin) - post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: "json" + post_via_redirect 'users/sign_in', 'user[email]' => user_to_signin.email, 'user[password]' => user_to_signin.password, format: 'json' end def sign_out @@ -15,19 +17,19 @@ RSpec.shared_context :new_controller_user_context do def send(method, *args) case method when :get - return xhr(:get, *args) + xhr(:get, *args) when :post - return xhr(:post, *args) + xhr(:post, *args) when :delete - return xhr(:delete, *args) + xhr(:delete, *args) when :put - return xhr(:put, *args) + xhr(:put, *args) end end def accept(user_to_signin:, method:, action:, args:) new_user = user_to_signin - if (user_to_signin != nil && user_to_signin.is_a?(OpenStruct)) + if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct) new_user = user_to_signin.value end sign_in new_user if new_user @@ -35,19 +37,18 @@ RSpec.shared_context :new_controller_user_context do # expect_any_instance_of(described_class).to receive(action).and_return(ActionController::TestResponse.new(200)) # expect_any_instance_of(described_class).to receive(:render).and_return(nil) send(method, action, args) - expect(response.status).to_not eq(302), "expected success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : "")} #{new_user&.attributes}" + expect(response.status).to_not eq(302), "expected success for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" sign_out end def reject(user_to_signin:, method:, action:, args:) - new_user = user_to_signin - if (user_to_signin != nil && user_to_signin.is_a?(OpenStruct)) + if !user_to_signin.nil? && user_to_signin.is_a?(OpenStruct) new_user = user_to_signin.value end sign_in new_user if new_user send(method, action, args) - expect(response.status).to eq(302), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ":" : "")} #{new_user&.attributes}" + expect(response.status).to eq(302), "expected failure for user: #{(user_to_signin.is_a?(OpenStruct) ? user_to_signin.key.to_s + ':' : '')} #{new_user&.attributes}" sign_out end -end \ No newline at end of file +end diff --git a/spec/controllers/support/shared_user_context.rb b/spec/controllers/support/shared_user_context.rb index 3abe31f6..503c98e6 100644 --- a/spec/controllers/support/shared_user_context.rb +++ b/spec/controllers/support/shared_user_context.rb @@ -1,97 +1,92 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later - RSpec.shared_context :shared_user_context do + let(:nonprofit) { force_create(:nonprofit, published: true) } + let(:other_nonprofit) { force_create(:nonprofit) } - - let(:nonprofit) {force_create(:nonprofit, published:true)} - let(:other_nonprofit) { force_create(:nonprofit)} - - - let(:user_as_np_admin) { + let(:user_as_np_admin) do __create_admin(nonprofit) - } + end - - let(:user_as_other_np_admin) { + let(:user_as_other_np_admin) do __create_admin(other_nonprofit) - } + end - let(:user_as_np_associate){ + let(:user_as_np_associate) do __create_associate(nonprofit) - } + end - let(:user_as_other_np_associate){ + let(:user_as_other_np_associate) do __create_associate(other_nonprofit) - } + end - let(:unauth_user) { + let(:unauth_user) do force_create(:user) - } + end - let(:campaign) {force_create(:campaign, nonprofit: nonprofit)} - let(:campaign_editor) { + let(:campaign) { force_create(:campaign, nonprofit: nonprofit) } + let(:campaign_editor) do __create(:campaign_editor, campaign) - } + end - let(:confirmed_user){ + let(:confirmed_user) do force_create(:user, confirmed_at: Time.current) - } + end - let(:event) { + let(:event) do force_create(:event, nonprofit: nonprofit) - } + end - let(:event_editor) { - __create(:event_editor,event) - } + let(:event_editor) do + __create(:event_editor, event) + end - let(:super_admin) { - __create(:super_admin, other_nonprofit) - } + let(:super_admin) do + __create(:super_admin, other_nonprofit) + end - let(:user_with_profile) { + let(:user_with_profile) do u = force_create(:user) force_create(:profile, user: u) u - } - - + end def __create(name, host) u = force_create(:user) - force_create(:role, user: u, name: name, host:host) + force_create(:role, user: u, name: name, host: host) u end def __create_admin(host) u = force_create(:user) - force_create(:role, user: u, name: :nonprofit_admin, host:host) + force_create(:role, user: u, name: :nonprofit_admin, host: host) u end def __create_associate(host) u = force_create(:user) - force_create(:role, user: u, name: :nonprofit_associate, host:host) + force_create(:role, user: u, name: :nonprofit_associate, host: host) u end def send(method, *args) case method - when :get - return get(*args) - when :post - return post(*args) - when :delete - return delete(*args) - when :put - return put(*args) + when :get + get(*args) + when :post + post(*args) + when :delete + delete(*args) + when :put + put(*args) end end def accept(user_to_signin, method, action, *args) - without_json_response = [:cancellation, :all_npos].include?(action) - request.accept = "application/json" unless without_json_response + without_json_response = %i[cancellation all_npos confirmation peer_to_peer].include?(action) + request.accept = 'application/json' unless without_json_response sign_in user_to_signin if user_to_signin # allows us to run the helpers but ignore what the controller action does @@ -121,42 +116,38 @@ RSpec.shared_context :shared_user_context do def fix_args(*args) replacements = { - __our_np: nonprofit.id, - __our_campaign: campaign.id, - __our_event: event.id, - __our_profile: user_with_profile.profile.id + __our_np: nonprofit.id, + __our_campaign: campaign.id, + __our_event: event.id, + __our_profile: user_with_profile.profile.id } - args.collect{|i| + args.collect do |i| ret = i if replacements[i] ret = replacements[i] elsif i.is_a? Hash - ret = i.collect{|k,v | + ret = i.collect do |k, v| ret_v = v - if replacements[v] - ret_v = replacements[v] - end + ret_v = replacements[v] if replacements[v] - [k,ret_v] - }.to_h + [k, ret_v] + end.to_h end ret - }.to_a + end.to_a end - - end RSpec.shared_context :open_to_all do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'accepts no user' do accept(nil, method, action, *fixed_args) end @@ -200,14 +191,13 @@ RSpec.shared_context :open_to_all do |method, action, *args| it 'accept profile user' do accept(user_with_profile, method, action, *fixed_args) end - end RSpec.shared_context :open_to_np_associate do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ + let(:fixed_args) do fix_args(*args) - } + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -254,12 +244,11 @@ RSpec.shared_context :open_to_np_associate do |method, action, *args| end end - RSpec.shared_context :open_to_np_admin do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -307,9 +296,9 @@ end RSpec.shared_context :open_to_registered do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -355,12 +344,11 @@ RSpec.shared_context :open_to_registered do |method, action, *args| end end - RSpec.shared_context :open_to_campaign_editor do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -404,14 +392,13 @@ RSpec.shared_context :open_to_campaign_editor do |method, action, *args| it 'rejects profile user' do reject(user_with_profile, method, action, *fixed_args) end - end RSpec.shared_context :open_to_confirmed_users do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -455,14 +442,13 @@ RSpec.shared_context :open_to_confirmed_users do |method, action, *args| it 'rejects profile user' do reject(user_with_profile, method, action, *fixed_args) end - end RSpec.shared_context :open_to_event_editor do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -509,9 +495,9 @@ end RSpec.shared_context :open_to_super_admin do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) @@ -558,12 +544,11 @@ RSpec.shared_context :open_to_super_admin do |method, action, *args| end end - RSpec.shared_context :open_to_profile_owner do |method, action, *args| include_context :shared_user_context - let(:fixed_args){ - fix_args( *args) - } + let(:fixed_args) do + fix_args(*args) + end it 'rejects no user' do reject(nil, method, action, *fixed_args) diff --git a/spec/controllers/ticket_levels_spec.rb b/spec/controllers/ticket_levels_spec.rb index d9b5cd6f..7fb63bd9 100644 --- a/spec/controllers/ticket_levels_spec.rb +++ b/spec/controllers/ticket_levels_spec.rb @@ -1,34 +1,35 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe TicketLevelsController, :type => :controller do +describe TicketLevelsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do describe 'create' do - include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" + include_context :open_to_event_editor, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' end describe 'update_order' do - include_context :open_to_event_editor, :put, :update_order, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_event_editor, :put, :update_order, nonprofit_id: :__our_np, event_id: :__our_event end describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: "1" + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: '1' end - end describe 'open to all' do describe 'show' do - include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' + include_context :open_to_all, :get, :show, nonprofit_id: :__our_np, event_id: :__our_event, id: '2' end describe 'index' do - include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_all, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event end end end -end \ No newline at end of file +end diff --git a/spec/controllers/tickets_spec.rb b/spec/controllers/tickets_spec.rb index 23faaa04..f8121d81 100644 --- a/spec/controllers/tickets_spec.rb +++ b/spec/controllers/tickets_spec.rb @@ -1,38 +1,38 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' require 'controllers/support/shared_user_context' -describe TicketsController, :type => :controller do +describe TicketsController, type: :controller do describe 'authorization' do include_context :shared_user_context describe 'rejects unauthorized users' do - describe 'index' do include_context :open_to_event_editor, :get, :index, nonprofit_id: :__our_np, event_id: :__our_event end describe 'update' do - include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 + include_context :open_to_event_editor, :put, :update, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end describe 'destroy' do - include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 + include_context :open_to_event_editor, :delete, :destroy, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end describe 'delete_card_for_ticket' do - include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event, id: 11111 + include_context :open_to_np_associate, :post, :delete_card_for_ticket, nonprofit_id: :__our_np, event_id: :__our_event, id: 11_111 end end describe 'open to all' do describe 'create' do - include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event + include_context :open_to_all, :post, :create, nonprofit_id: :__our_np, event_id: :__our_event end describe 'add_note' do include_context :open_to_all, :put, :add_note, nonprofit_id: :__our_np, event_id: :__our_event, id: 1111 end - end end -end \ No newline at end of file +end diff --git a/spec/cve/cve_2014_2538_spec.rb b/spec/cve/cve_2014_2538_spec.rb index 53fcb21e..bc2b49ed 100644 --- a/spec/cve/cve_2014_2538_spec.rb +++ b/spec/cve/cve_2014_2538_spec.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later require 'rails_helper' -require "rack/ssl" +require 'rack/ssl' describe Rack::SSL do describe '.call' do - it "invalid uri returns 404" do + it 'invalid uri returns 404' do def test_invalid_uri_returns_404 # Can't test this with Rack::Test because it fails on the URI before it # even gets to Rack::SSL. Other webservers will pass this URI through. ssl = Rack::SSL.new(nil) - resp = ssl.call('PATH_INFO' => "https://example.org/path/