Class: BulletTrain::SuperScaffolding::Scaffolders::OauthProviderScaffolder

Inherits:
BulletTrain::SuperScaffolding::Scaffolder show all
Defined in:
lib/bullet_train/super_scaffolding/scaffolders/oauth_provider_scaffolder.rb

Instance Attribute Summary

Attributes inherited from BulletTrain::SuperScaffolding::Scaffolder

#argv

Instance Method Summary collapse

Methods inherited from BulletTrain::SuperScaffolding::Scaffolder

#initialize

Constructor Details

This class inherits a constructor from BulletTrain::SuperScaffolding::Scaffolder

Instance Method Details

#runObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/bullet_train/super_scaffolding/scaffolders/oauth_provider_scaffolder.rb', line 5

def run
  unless argv.count >= 5
    puts ""
    puts "šŸš…  usage: bin/super-scaffold oauth-provider <omniauth_gem> <gems_provider_name> <our_provider_name> <PROVIDER_API_KEY_ENV_VAR_NAME> <PROVIDER_API_SECRET_ENV_VAR_NAME> [options]"
    puts ""
    puts "E.g. what we actually did to start Shopify off:"
    puts "  bin/super-scaffold oauth-provider omniauth-shopify-oauth2 shopify Oauth::ShopifyAccount SHOPIFY_API_KEY SHOPIFY_API_SECRET_KEY --icon=ti-shopping-cart"
    puts "  (Please note here that the SHOPIFY_API_KEY and SHOPIFY_API_SECRET_KEY strings are not the actual values, just the names we give to the environment variables.)"
    puts ""
    puts "Options:"
    puts ""
    puts "  --icon={ti-*}: Specify an icon."
    puts ""
    puts "For a list of readily available provider strategies, see https://github.com/omniauth/omniauth/wiki/List-of-Strategies ."
    puts ""
    exit
  end

  _, omniauth_gem, gems_provider_name, our_provider_name, api_key, api_secret = *ARGV

  if omniauth_gem == "omniauth-stripe-connect"
    puts "Stripe is already available for use and does not need any scaffolding to be done.".green
    puts "Just add your `STRIPE_CLIENT_ID` and `STRIPE_SECRET_KEY` values to application.yml"
    puts "and you should be able to use Stripe as an OAuth provider out of the box."
    exit
  end

  unless (match = our_provider_name.match(/Oauth::(.*)Account/))
    puts "\nšŸšØ Your provider name must match the pattern of `Oauth::{Name}Account`, e.g. `Oauth::StripeAccount`\n".red
    return
  end

  options = {
    omniauth_gem: omniauth_gem,
    gems_provider_name: gems_provider_name,
    our_provider_name: match[1],
    api_key: api_key,
    api_secret: api_secret
  }

  unless File.exist?(oauth_transform_string("./app/models/oauth/stripe_account.rb", options)) &&
      File.exist?(oauth_transform_string("./app/models/integrations/stripe_installation.rb", options)) &&
      File.exist?(oauth_transform_string("./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb", options))

    oauth_model_data = {
      "Oauth::StripeAccount": "rails generate model Oauth::StripeAccount uid:string data:jsonb user:references",
      "Integrations::StripeInstallation": "rails generate model Integrations::StripeInstallation team:references oauth_stripe_account:references name:string",
      "Webhooks::Incoming::Oauth::StripeAccountWebhook": "rails generate model Webhooks::Incoming::Oauth::StripeAccountWebhook data:jsonb processed_at:datetime verified_at:datetime oauth_stripe_account:references"
    }

    # Transform class names and model migrations.
    transformed_data = {}
    oauth_model_data.each do |key, value|
      transformed_data[oauth_transform_string(key.to_s, options)] = oauth_transform_string(value, options)
    end

    if @options["skip-migration-generation"]
      undefined_models = transformed_data.keys.each { |key| key.safe_constantize.nil? }
      if undefined_models.any?
        puts ""
        puts "We could not find the following models:".red
        undefined_models.each { |model| puts "  #{model}".red }
        puts ""
        puts "šŸšØ Before doing the actual Super Scaffolding, you'll need to generate the models like so:".red
        puts ""
        transformed_data.each { |_, migration| puts "  #{migration}".red }
        puts ""
        puts "However, don't do the `rake db:migrate` until after you re-run Super Scaffolding, as it will need to update some settings in those migrations.".red
        puts ""
        return
      end
    else
      transformed_data.each do |klass, generation_command|
        puts "Generating #{klass} model with '#{generation_command}'".green
        generation_thread = Thread.new { `#{generation_command}` }
        generation_thread.join # Wait for the process to finish.
      end
    end
  end

  icon_name = nil
  if @options["icon"].present?
    icon_name = @options["icon"]
  else
    puts "OK, great! Let's do this! By default providers will appear with a dollar symbol,"
    puts "but after you hit enter I'll open a page where you can view other icon options."
    puts "When you find one you like, hover your mouse over it and then come back here and"
    puts "and enter the name of the icon you want to use."
    if TerminalCommands.can_open?
      TerminalCommands.open_file_or_link("http://light.pinsupreme.com/icon_fonts_themefy.html")
    else
      puts "Sorry! We can't open these URLs automatically on your platform, but you can visit them manually:"
      puts ""
      puts "  http://light.pinsupreme.com/icon_fonts_themefy.html"
    end
    puts ""
    puts "Did you find an icon you wanted to use? Enter the name here or hit enter to just"
    puts "use the dollar symbol:"
    icon_name = $stdin.gets.chomp
    puts ""
    unless icon_name.length > 0 || icon_name.downcase == "y"
      icon_name = "icon-puzzle"
    end
  end

  options[:icon] = icon_name

  empty_transformer = Scaffolding::Transformer.new("", "")

  [

    # User OAuth.
    "./app/models/oauth/stripe_account.rb",
    "./app/models/concerns/oauth/stripe_accounts/base.rb",
    "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
    "./app/models/concerns/webhooks/incoming/oauth/stripe_account_webhooks/base.rb",
    "./app/controllers/account/oauth/stripe_accounts_controller.rb",
    "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb",
    "./app/views/account/oauth/stripe_accounts",
    "./test/models/oauth/stripe_account_test.rb",
    "./test/factories/oauth/stripe_accounts.rb",
    "./config/locales/en/oauth/stripe_accounts.en.yml",
    "./app/views/devise/shared/oauth/_stripe.html.erb",

    # Team Integration.
    "./app/models/integrations/stripe_installation.rb",
    "./app/models/concerns/integrations/stripe_installations/base.rb",
    # './app/serializers/api/v1/integrations/stripe_installation_serializer.rb',
    "./app/controllers/account/integrations/stripe_installations_controller.rb",
    "./app/views/account/integrations/stripe_installations",
    "./test/models/integrations/stripe_installation_test.rb",
    "./test/factories/integrations/stripe_installations.rb",
    "./config/locales/en/integrations/stripe_installations.en.yml",

    # Webhook.
    "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
    "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb"

  ].each do |name|
    if File.directory?(empty_transformer.resolve_template_path(name))
      oauth_scaffold_directory(name, options)
    else
      oauth_scaffold_file(name, options)
    end
  end

  oauth_scaffold_add_line_to_file("./app/views/devise/shared/_oauth.html.erb", "<%= render 'devise/shared/oauth/stripe', verb: verb if stripe_enabled? %>", "<%# šŸš… super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/views/account/users/_oauth.html.erb", "<%= render 'account/oauth/stripe_accounts/index', context: @user, stripe_accounts: @user.oauth_stripe_accounts if stripe_enabled? %>", "<% # šŸš… super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
  oauth_scaffold_add_line_to_file("./config/initializers/devise.rb", "config.omniauth :stripe_connect, ENV['STRIPE_CLIENT_ID'], ENV['STRIPE_SECRET_KEY'], {\n    ## specify options for your oauth provider here, e.g.:\n    # scope: 'read_products,read_orders,write_content',\n  }\n", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/controllers/account/oauth/omniauth_callbacks_controller.rb", "def stripe_connect\n    callback(\"Stripe\", team_id_from_env)\n  end\n", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/models/team.rb", "has_many :integrations_stripe_installations, class_name: 'Integrations::StripeInstallation', dependent: :destroy if stripe_enabled?", "# šŸš… add oauth providers above.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/models/user.rb", "has_many :oauth_stripe_accounts, class_name: 'Oauth::StripeAccount' if stripe_enabled?", "# šŸš… add oauth providers above.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./config/locales/en/oauth.en.yml", "stripe_connect: Stripe", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/views/account/shared/_menu.html.erb", "<%= render 'account/integrations/stripe_installations/menu_item' if stripe_enabled? %>", "<%# šŸš… super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
  oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_account_webhooks if stripe_enabled?", "# šŸš… super scaffolding will insert new oauth provider webhooks above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_accounts if stripe_enabled?", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_installations if stripe_enabled?", "# šŸš… super scaffolding will insert new integration installations above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./Gemfile", "gem 'omniauth-stripe-connect'", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./lib/bullet_train_oauth_scaffolder_support.rb", "def stripe_enabled?\n  ENV['STRIPE_CLIENT_ID'].present? && ENV['STRIPE_SECRET_KEY'].present?\nend\n", "# šŸš… super scaffolding will insert new oauth providers above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./lib/bullet_train_oauth_scaffolder_support.rb", "stripe_enabled?,", "# šŸš… super scaffolding will insert new oauth provider checks above this line.", options, prepend: true)
  oauth_scaffold_add_line_to_file("./app/models/ability.rb", "if stripe_enabled?\n        can [:read, :create, :destroy], Oauth::StripeAccount, user_id: user.id\n        can :manage, Integrations::StripeInstallation, team_id: user.team_ids\n        can :destroy, Integrations::StripeInstallation, oauth_stripe_account: {user_id: user.id}\n      end\n", "# šŸš… super scaffolding will insert any new oauth providers above.", options, prepend: true)

  # find the database migration that defines this relationship.
  migration_file_name = `grep "create_table #{oauth_transform_string(":oauth_stripe_accounts", options)}" db/migrate/*`.split(":").first
  empty_transformer.replace_in_file(migration_file_name, "null: false", "null: true")

  migration_file_name = `grep "create_table #{oauth_transform_string(":integrations_stripe_installations", options)}" db/migrate/*`.split(":").first
  empty_transformer.replace_in_file(migration_file_name,
    oauth_transform_string("t.references :oauth_stripe_account, null: false, foreign_key: true", options),
    oauth_transform_string('t.references :oauth_stripe_account, null: false, foreign_key: true, index: {name: "index_stripe_installations_on_oauth_stripe_account_id"}', options))

  migration_file_name = `grep "create_table #{oauth_transform_string(":webhooks_incoming_oauth_stripe_account_webhooks", options)}" db/migrate/*`.split(":").first
  empty_transformer.replace_in_file(migration_file_name, "null: false", "null: true")
  empty_transformer.replace_in_file(migration_file_name, "foreign_key: true", oauth_transform_string('foreign_key: true, index: {name: "index_stripe_webhooks_on_oauth_stripe_account_id"}', options))

  puts ""
  puts "šŸŽ‰"
  puts ""
  puts "You'll probably need to `bundle install`.".green
  puts ""
  puts "You'll need to configure API keys for this provider in `config/application.yml`, like so:"
  puts ""
  puts oauth_transform_string("  STRIPE_CLIENT_ID: ...", options)
  puts oauth_transform_string("  STRIPE_SECRET_KEY: ...", options)
  puts ""
  puts "If the OAuth provider asks you for some whitelisted callback URLs, the URL structure for those is as so:"
  puts ""
  path = "users/auth/stripe_connect/callback"
  puts oauth_transform_string("  https://yourdomain.co/#{path}", options)
  puts oauth_transform_string("  https://yourtunnel.ngrok.io/#{path}", options)
  puts oauth_transform_string("  http://localhost:3000/#{path}", options)
  puts ""
  puts "If you're able to specify an endpoint to receive webhooks from this provider, use this URL:"
  puts ""
  path = "webhooks/incoming/oauth/stripe_account_webhooks"
  puts oauth_transform_string("  https://yourdomain.co/#{path}", options)
  puts oauth_transform_string("  https://yourtunnel.ngrok.io/#{path}", options)
  puts oauth_transform_string("  http://localhost:3000/#{path}", options)
  puts ""
  puts ""
  puts "If you'd like to edit how your Bullet Train application refers to this provider, just edit the locale file at `config/locales/en/oauth.en.yml`."
  puts ""
  puts "And finally, if you need to specify any custom authorizations or options for your OAuth integration with this provider, you can configure those in `config/initializers/devise.rb`."
  puts ""
end