WIP
This commit is contained in:
parent
25c7cd7c6a
commit
30b2df23e2
22 changed files with 459 additions and 33 deletions
38
Gemfile.lock
38
Gemfile.lock
|
@ -116,7 +116,7 @@ GEM
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (1.4.4)
|
bootsnap (1.4.4)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
builder (3.2.4)
|
builder (3.2.3)
|
||||||
bunny (2.14.2)
|
bunny (2.14.2)
|
||||||
amq-protocol (~> 2.3, >= 2.3.0)
|
amq-protocol (~> 2.3, >= 2.3.0)
|
||||||
byebug (11.0.1)
|
byebug (11.0.1)
|
||||||
|
@ -132,7 +132,7 @@ GEM
|
||||||
coercible (1.0.0)
|
coercible (1.0.0)
|
||||||
descendants_tracker (~> 0.0.1)
|
descendants_tracker (~> 0.0.1)
|
||||||
colorize (0.8.1)
|
colorize (0.8.1)
|
||||||
concurrent-ruby (1.1.6)
|
concurrent-ruby (1.1.5)
|
||||||
config (1.7.2)
|
config (1.7.2)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
deep_merge (~> 1.2, >= 1.2.1)
|
deep_merge (~> 1.2, >= 1.2.1)
|
||||||
|
@ -143,7 +143,7 @@ GEM
|
||||||
unicode_utils (~> 1.4)
|
unicode_utils (~> 1.4)
|
||||||
crack (0.4.3)
|
crack (0.4.3)
|
||||||
safe_yaml (~> 1.0.0)
|
safe_yaml (~> 1.0.0)
|
||||||
crass (1.0.6)
|
crass (1.0.4)
|
||||||
css_parser (1.7.0)
|
css_parser (1.7.0)
|
||||||
addressable
|
addressable
|
||||||
dante (0.2.0)
|
dante (0.2.0)
|
||||||
|
@ -155,10 +155,10 @@ GEM
|
||||||
deep_merge (1.2.1)
|
deep_merge (1.2.1)
|
||||||
descendants_tracker (0.0.4)
|
descendants_tracker (0.0.4)
|
||||||
thread_safe (~> 0.3, >= 0.3.1)
|
thread_safe (~> 0.3, >= 0.3.1)
|
||||||
devise (4.7.1)
|
devise (4.6.2)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 4.1.0)
|
railties (>= 4.1.0, < 6.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-async (1.0.0)
|
devise-async (1.0.0)
|
||||||
|
@ -201,7 +201,7 @@ GEM
|
||||||
dry-logic (~> 0.5, >= 0.5.0)
|
dry-logic (~> 0.5, >= 0.5.0)
|
||||||
dry-types (~> 0.14.0)
|
dry-types (~> 0.14.0)
|
||||||
equalizer (0.0.11)
|
equalizer (0.0.11)
|
||||||
erubi (1.9.0)
|
erubi (1.8.0)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
factory_bot (5.0.2)
|
factory_bot (5.0.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
|
@ -260,7 +260,7 @@ GEM
|
||||||
httparty (0.17.0)
|
httparty (0.17.0)
|
||||||
mime-types (~> 3.0)
|
mime-types (~> 3.0)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
i18n (1.8.2)
|
i18n (1.6.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
i18n-js (3.3.0)
|
i18n-js (3.3.0)
|
||||||
i18n (>= 0.6.6)
|
i18n (>= 0.6.6)
|
||||||
|
@ -276,7 +276,7 @@ GEM
|
||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
railties (>= 4)
|
railties (>= 4)
|
||||||
request_store (~> 1.0)
|
request_store (~> 1.0)
|
||||||
loofah (2.5.0)
|
loofah (2.2.3)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.7.1)
|
mail (2.7.1)
|
||||||
|
@ -293,7 +293,7 @@ GEM
|
||||||
mini_magick (4.9.5)
|
mini_magick (4.9.5)
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.2)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
minitest (5.14.0)
|
minitest (5.11.3)
|
||||||
msgpack (1.3.1)
|
msgpack (1.3.1)
|
||||||
multi_json (1.13.1)
|
multi_json (1.13.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
|
@ -307,7 +307,7 @@ GEM
|
||||||
require_all
|
require_all
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nio4r (2.4.0)
|
nio4r (2.4.0)
|
||||||
nokogiri (1.10.9)
|
nokogiri (1.10.3)
|
||||||
mini_portile2 (~> 2.4.0)
|
mini_portile2 (~> 2.4.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
parallel (1.17.0)
|
parallel (1.17.0)
|
||||||
|
@ -331,11 +331,7 @@ GEM
|
||||||
puma (>= 2.7, < 5)
|
puma (>= 2.7, < 5)
|
||||||
rabl (0.14.1)
|
rabl (0.14.1)
|
||||||
activesupport (>= 2.3.14)
|
activesupport (>= 2.3.14)
|
||||||
<<<<<<< HEAD
|
|
||||||
rack (2.0.9)
|
rack (2.0.9)
|
||||||
=======
|
|
||||||
rack (2.2.2)
|
|
||||||
>>>>>>> Update to Rack
|
|
||||||
rack-accept (0.4.5)
|
rack-accept (0.4.5)
|
||||||
rack (>= 0.4)
|
rack (>= 0.4)
|
||||||
rack-attack (5.4.2)
|
rack-attack (5.4.2)
|
||||||
|
@ -361,8 +357,8 @@ GEM
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.3.0)
|
rails-html-sanitizer (1.2.0)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.2, >= 2.2.2)
|
||||||
rails-i18n (5.1.3)
|
rails-i18n (5.1.3)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 5.0, < 6)
|
railties (>= 5.0, < 6)
|
||||||
|
@ -398,13 +394,13 @@ GEM
|
||||||
rspec-mocks (~> 3.8.0)
|
rspec-mocks (~> 3.8.0)
|
||||||
rspec-core (3.8.2)
|
rspec-core (3.8.2)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.8.0)
|
||||||
rspec-expectations (3.8.6)
|
rspec-expectations (3.8.4)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.8.0)
|
||||||
rspec-mocks (3.8.2)
|
rspec-mocks (3.8.1)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.8.0)
|
||||||
rspec-rails (3.8.3)
|
rspec-rails (3.8.2)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
|
@ -412,7 +408,7 @@ GEM
|
||||||
rspec-expectations (~> 3.8.0)
|
rspec-expectations (~> 3.8.0)
|
||||||
rspec-mocks (~> 3.8.0)
|
rspec-mocks (~> 3.8.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.8.0)
|
||||||
rspec-support (3.8.3)
|
rspec-support (3.8.2)
|
||||||
rubocop (0.72.0)
|
rubocop (0.72.0)
|
||||||
jaro_winkler (~> 1.5.1)
|
jaro_winkler (~> 1.5.1)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
|
@ -475,7 +471,7 @@ GEM
|
||||||
timecop (0.9.1)
|
timecop (0.9.1)
|
||||||
traceroute (0.8.0)
|
traceroute (0.8.0)
|
||||||
rails (>= 3.0.0)
|
rails (>= 3.0.0)
|
||||||
tzinfo (1.2.7)
|
tzinfo (1.2.5)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (4.1.20)
|
uglifier (4.1.20)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
|
|
81
app/controllers/api/nonprofits_controller.rb
Normal file
81
app/controllers/api/nonprofits_controller.rb
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
class Api::NonprofitsController < ApplicationController
|
||||||
|
|
||||||
|
# requires :nonprofit, type: Hash do
|
||||||
|
# requires :name, type: String, desc: 'Organization Name', allow_blank: false, 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' }
|
||||||
|
# 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' }
|
||||||
|
def create
|
||||||
|
model = CreateModel.new(clean_params)
|
||||||
|
np = nil
|
||||||
|
u = nil
|
||||||
|
raise ActiveRecord::RecordInvalid
|
||||||
|
Qx.transaction do
|
||||||
|
raise Errors::MessageInvalid.new(model) unless model.valid?
|
||||||
|
model.save!
|
||||||
|
end
|
||||||
|
# Qx.transaction do
|
||||||
|
# byebug
|
||||||
|
# np = ::Nonprofit.new(OnboardAccounts.set_nonprofit_defaults(clean_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(clean_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
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean_params
|
||||||
|
params.permit(nonprofit: [:name, :zip_code, :state_code, :city], user: [:name, :email, :password])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
41
app/models/base.rb
Normal file
41
app/models/base.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
|
||||||
|
class Base
|
||||||
|
include ActiveModel::Model
|
||||||
|
include ActiveModel::Validations
|
||||||
|
include ActiveModel::Validations::Callbacks
|
||||||
|
|
||||||
|
|
||||||
|
def self.validate_nested_attribute(*attributes)
|
||||||
|
validates_with NestedAttributesValidator, _merge_attributes(attributes)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def _merge_attributes(attr_names)
|
||||||
|
options = attr_names.extract_options!.symbolize_keys
|
||||||
|
attr_names.flatten!
|
||||||
|
options[:attributes] = attr_names
|
||||||
|
options
|
||||||
|
end
|
||||||
|
|
||||||
|
class NestedAttributesValidator < ActiveModel::EachValidator
|
||||||
|
def initialize(options)
|
||||||
|
@model_class = options[:model_class]
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
inner_validator = @model_class.new(value) unless value.is_a? @model_class
|
||||||
|
return if inner_validator.valid?
|
||||||
|
add_nested_errors_for(record, attribute, inner_validator)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_nested_errors_for(record, attribute, other_validator)
|
||||||
|
record.errors.messages[attribute] = other_validator.errors.messages
|
||||||
|
record.errors.details[attribute] = other_validator.errors.details
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
48
app/models/create_model.rb
Normal file
48
app/models/create_model.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
class CreateModel < Base
|
||||||
|
attr_accessor :nonprofit, :user
|
||||||
|
validates_presence_of :user
|
||||||
|
validates_presence_of :nonprofit
|
||||||
|
validate_nested_attribute :user, model_class: User
|
||||||
|
validate_nested_attribute :nonprofit, model_class: Nonprofit
|
||||||
|
|
||||||
|
before_validation do
|
||||||
|
nonprofit = Nonprofit.create(nonprofit) if !nonprofit.is_a? Nonprofit
|
||||||
|
user = User.create(user) if !nonprofit.is_a? Nonprofit
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
if valid?
|
||||||
|
if nonprofit.save!
|
||||||
|
if user.save!
|
||||||
|
role = user.roles.build(host: nonprofit, name: 'nonprofit_admin')
|
||||||
|
role.save!
|
||||||
|
|
||||||
|
billing_plan = BillingPlan.find(Settings.default_bp.id)
|
||||||
|
b_sub = nonprofit.build_billing_subscription(billing_plan: billing_plan, status: 'active')
|
||||||
|
b_sub.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# 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}]"],
|
||||||
|
# value message: error
|
||||||
|
# )
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# raise Grape::Exceptions::ValidationErrors.new(errors: errors.flatten)
|
||||||
|
# else
|
||||||
|
# raise e
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
|
||||||
|
def save!
|
||||||
|
raise 'runtime' unless save
|
||||||
|
end
|
||||||
|
end
|
5
app/models/errors/active_model_error.rb
Normal file
5
app/models/errors/active_model_error.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
class Errors::ActiveModelError < StandardError
|
||||||
|
|
||||||
|
end
|
17
app/models/errors/message_invalid.rb
Normal file
17
app/models/errors/message_invalid.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
class Errors::MessageInvalid < Errors::ActiveModelError
|
||||||
|
|
||||||
|
attr_reader :record
|
||||||
|
def initialize(record=nil)
|
||||||
|
if record
|
||||||
|
@record = record
|
||||||
|
errors = @record.errors.full_messages.join(", ")
|
||||||
|
message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid")
|
||||||
|
else
|
||||||
|
message = "Record invalid"
|
||||||
|
end
|
||||||
|
|
||||||
|
super(message)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -106,6 +106,10 @@ class Nonprofit < ApplicationRecord
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after_validation(on: :create) do
|
||||||
|
correct_nonunique_slug
|
||||||
|
end
|
||||||
|
|
||||||
# Register (create) a nonprofit with an initial admin
|
# Register (create) a nonprofit with an initial admin
|
||||||
def self.register(user, params)
|
def self.register(user, params)
|
||||||
np = create ConstructNonprofit.construct(user, params)
|
np = create ConstructNonprofit.construct(user, params)
|
||||||
|
@ -148,6 +152,16 @@ class Nonprofit < ApplicationRecord
|
||||||
end
|
end
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def correct_nonunique_slug
|
||||||
|
if errors[:slug]
|
||||||
|
begin
|
||||||
|
slug = SlugNonprofitNamingAlgorithm.new(self.state_code_slug, self.city_slug).create_copy_name(self.slug)
|
||||||
|
self.slug = slug
|
||||||
|
rescue UnableToCreateNameCopyError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def full_address
|
def full_address
|
||||||
Format::Address.full_address(address, city, state_code)
|
Format::Address.full_address(address, city, state_code)
|
||||||
|
|
|
@ -14,7 +14,7 @@ require "action_mailer/railtie"
|
||||||
require "action_view/railtie"
|
require "action_view/railtie"
|
||||||
# require "action_cable/engine"
|
# require "action_cable/engine"
|
||||||
# require "sprockets/railtie"
|
# require "sprockets/railtie"
|
||||||
# require "rails/test_unit/railtie"
|
require "rails/test_unit/railtie"
|
||||||
|
|
||||||
# Require the gems listed in Gemfile, including any gems
|
# Require the gems listed in Gemfile, including any gems
|
||||||
# you've limited to :test, :development, or :production.
|
# you've limited to :test, :development, or :production.
|
||||||
|
@ -24,6 +24,7 @@ Bundler.require(*Rails.groups)
|
||||||
|
|
||||||
module Commitchange
|
module Commitchange
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
|
config.load_defaults '5.0'
|
||||||
# Settings in config/environments/* take precedence over those specified here.
|
# Settings in config/environments/* take precedence over those specified here.
|
||||||
# Application configuration should go into files in config/initializers
|
# Application configuration should go into files in config/initializers
|
||||||
# -- all .rb files in that directory are automatically loaded.
|
# -- all .rb files in that directory are automatically loaded.
|
||||||
|
@ -32,9 +33,9 @@ module Commitchange
|
||||||
# config.autoload_paths += %W(#{config.root}/extras)
|
# config.autoload_paths += %W(#{config.root}/extras)
|
||||||
config.eager_load_paths += Dir["#{config.root}/lib/**/", ""]
|
config.eager_load_paths += Dir["#{config.root}/lib/**/", ""]
|
||||||
|
|
||||||
config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
|
# config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
|
||||||
config.paths.add File.join('app', 'listeners'), glob: File.join('**', '*.rb')
|
config.paths.add File.join('app', 'listeners'), glob: File.join('**', '*.rb')
|
||||||
config.eager_load_paths += Dir[Rails.root.join('app', 'api', '*'), Rails.root.join('app', 'listeners', '*')]
|
# config.eager_load_paths += Dir[Rails.root.join('app', 'api', '*'), Rails.root.join('app', 'listeners', '*')]
|
||||||
|
|
||||||
# Only load the plugins named here, in the order given (default is alphabetical).
|
# 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.
|
# :all can be used as a placeholder for all plugins not explicitly named.
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
mount Houdini::API => '/api'
|
|
||||||
|
|
||||||
if Rails.env == 'development'
|
if Rails.env == 'development'
|
||||||
get '/button_debug/embedded' => 'button_debug#embedded'
|
get '/button_debug/embedded' => 'button_debug#embedded'
|
||||||
|
@ -12,6 +11,10 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
get 'onboard' => 'onboard#index'
|
get 'onboard' => 'onboard#index'
|
||||||
|
|
||||||
|
namespace(:api) do
|
||||||
|
resources(:nonprofits)
|
||||||
|
end
|
||||||
|
|
||||||
resources(:emails, only: [:create])
|
resources(:emails, only: [:create])
|
||||||
resources(:settings, only: [:index])
|
resources(:settings, only: [:index])
|
||||||
resources(:campaign_gifts, only: [:create])
|
resources(:campaign_gifts, only: [:create])
|
||||||
|
@ -254,5 +257,7 @@ Rails.application.routes.draw do
|
||||||
get '/static/terms_and_privacy' => 'static#terms_and_privacy'
|
get '/static/terms_and_privacy' => 'static#terms_and_privacy'
|
||||||
get '/static/ccs' => 'static#ccs'
|
get '/static/ccs' => 'static#ccs'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
root to: 'front#index'
|
root to: 'front#index'
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe Houdini::V1::Nonprofit, type: :request do
|
describe 'HOUDINI NOnprofit_spec', type: :request do
|
||||||
describe 'get' do
|
describe 'get' do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects csrf' do
|
it 'rejects csrf' do
|
||||||
post '/api/v1/nonprofit', params: {}, xhr: true
|
post '/api/nonprofits', params: {}, xhr: true
|
||||||
expect(response.code).to eq '400'
|
expect(response.code).to eq '400'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'validates nothing' do
|
it 'validates nothing' do
|
||||||
input = {}
|
input = {}
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '400'
|
expect(response.code).to eq '400'
|
||||||
expect_validation_errors(JSON.parse(response.body), create_errors('nonprofit', 'user'))
|
expect_validation_errors(JSON.parse(response.body), create_errors('nonprofit', 'user'))
|
||||||
end
|
end
|
||||||
|
@ -73,7 +73,7 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
url: ''
|
url: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '400'
|
expect(response.code).to eq '400'
|
||||||
expected = create_errors('user')
|
expected = create_errors('user')
|
||||||
expected[:errors].push(h(params: ['nonprofit[email]'], messages: gr_e('regexp')))
|
expected[:errors].push(h(params: ['nonprofit[email]'], messages: gr_e('regexp')))
|
||||||
|
@ -93,7 +93,7 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
password_confirmation: 'doesn\'t match'
|
password_confirmation: 'doesn\'t match'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '400'
|
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(JSON.parse(response.body)['errors']).to include(h(params: ['user[password]', 'user[password_confirmation]'], messages: gr_e('is_equal_to')))
|
||||||
end
|
end
|
||||||
|
@ -107,7 +107,7 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
|
|
||||||
expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new)
|
expect_any_instance_of(SlugNonprofitNamingAlgorithm).to receive(:create_copy_name).and_raise(UnableToCreateNameCopyError.new)
|
||||||
|
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '400'
|
expect(response.code).to eq '400'
|
||||||
|
|
||||||
expect_validation_errors(JSON.parse(response.body),
|
expect_validation_errors(JSON.parse(response.body),
|
||||||
|
@ -127,7 +127,7 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||||
}
|
}
|
||||||
|
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '400'
|
expect(response.code).to eq '400'
|
||||||
|
|
||||||
expect_validation_errors(JSON.parse(response.body),
|
expect_validation_errors(JSON.parse(response.body),
|
||||||
|
@ -151,7 +151,7 @@ describe Houdini::V1::Nonprofit, type: :request do
|
||||||
|
|
||||||
# expect(Houdini::V1::Nonprofit).to receive(:sign_in)
|
# expect(Houdini::V1::Nonprofit).to receive(:sign_in)
|
||||||
|
|
||||||
post '/api/v1/nonprofit', params: input, xhr: true
|
post '/api/nonprofits', params: input, xhr: true
|
||||||
expect(response.code).to eq '201'
|
expect(response.code).to eq '201'
|
||||||
|
|
||||||
our_np = Nonprofit.all[1]
|
our_np = Nonprofit.all[1]
|
||||||
|
|
218
spec/controllers/api/nonprofits_controller_spec.rb
Normal file
218
spec/controllers/api/nonprofits_controller_spec.rb
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Api::NonprofitsController, type: :request do
|
||||||
|
it 'do things' do
|
||||||
|
|
||||||
|
post '/api/nonprofits', params: {nonprofit: {name: 'hathatoh'}, user: {email: 'thoahtoa'}}
|
||||||
|
|
||||||
|
byebug
|
||||||
|
expect(response.code).to eq 400
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe 'get' do
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'post' do
|
||||||
|
around(:each) do |example|
|
||||||
|
@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
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_errors(*wrapper_params)
|
||||||
|
output = totally_empty_errors
|
||||||
|
wrapper_params.each { |i| output[:errors].push(h(params: [i], messages: gr_e('presence'))) }
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
def h(h = {})
|
||||||
|
h.with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
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: ['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) 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 :create, params: {}, xhr: true
|
||||||
|
expect(response.code).to eq '400'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'validates nothing' do
|
||||||
|
input = {}
|
||||||
|
post :create, params: input, xhr: true
|
||||||
|
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: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post :create, 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_validation_errors(JSON.parse(response.body), expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should reject unmatching passwords ' do
|
||||||
|
input = {
|
||||||
|
|
||||||
|
user: {
|
||||||
|
email: 'wmeil@email.com',
|
||||||
|
name: 'name',
|
||||||
|
password: 'password',
|
||||||
|
password_confirmation: 'doesn\'t match'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post :create, 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')))
|
||||||
|
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')
|
||||||
|
input = {
|
||||||
|
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 :create, params: input, xhr: true
|
||||||
|
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.']
|
||||||
|
)
|
||||||
|
])
|
||||||
|
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: 54_915 },
|
||||||
|
user: { name: 'Name', email: 'em@em.com', password: '12345678', password_confirmation: '12345678' }
|
||||||
|
}
|
||||||
|
|
||||||
|
expect do
|
||||||
|
post :create, params: input, xhr: true
|
||||||
|
end.to raise_error {|error|
|
||||||
|
|
||||||
|
expect(error).to be_a Errors::MessageInvalid
|
||||||
|
}
|
||||||
|
byebug
|
||||||
|
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')
|
||||||
|
input = {
|
||||||
|
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)
|
||||||
|
|
||||||
|
post :create, params: input, xhr: true
|
||||||
|
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'
|
||||||
|
}.with_indifferent_access
|
||||||
|
|
||||||
|
expected_np = our_np.attributes.with_indifferent_access.merge(expected_np)
|
||||||
|
expect(our_np.attributes).to eq expected_np
|
||||||
|
|
||||||
|
expect(our_np.billing_subscription.billing_plan).to eq bp
|
||||||
|
|
||||||
|
response_body = {
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
|
||||||
|
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 unless error
|
||||||
|
|
||||||
|
error['messages']
|
||||||
|
end
|
||||||
|
|
||||||
|
def gr_e(*keys)
|
||||||
|
keys.map { |i| I18n.translate('grape.errors.messages.' + i, locale: 'en') }
|
||||||
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue