webflow_sync 0.1.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14705897f82379cd4aa7b11ceda57374b6066d26b96344318ec4089048c377bb
4
- data.tar.gz: b17539c21bc34e339ddd12843831fcf61294876d6bc136d6ac7abbced15826fb
3
+ metadata.gz: f5541d8efea25526da9e623513853d0b2727c0d473251162cc2db71d729ee3c5
4
+ data.tar.gz: 45ffc209e988d291a010618debf173530bdecdb1686caf9a23653214265cd300
5
5
  SHA512:
6
- metadata.gz: fb9e2b651a04fd77506a3c869c5b33716131fa765ad413ac6180ca5c1805e141bb6b3b7310c4a8dbdc3f6e71782e7a1bf1a62bdbb78b8c224d8ef3c0669c3e74
7
- data.tar.gz: e6bcaf360ecf06bbaf08f78664715dceea5f10a3f529912f9d445aaa39fbe769b4c0fc4c11c583d5e6977e5e3885dc90c17b3a1c8f17c404b585140a3de57dc0
6
+ metadata.gz: e850f8be00f87fe2ebd9ede70cf0adf9d7cceeb0d02cf4b8afafbdb17472915717017e6d8a632562c80dc5acc460cb0cbcb3c655b08c5046cef323800abe7779
7
+ data.tar.gz: 606363c28363aeaf7cd8f3a27859db3a8d5c0db929af486fc0456b27e5ba1ff917d56180e5152a959c337fdc787b016a20335c11dd4ab3ad64c9fec86ef2f800
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- ![build](https://github.com/vfonic/webflow_sync/workflows/build/badge.svg)
1
+ [![Build Status](https://github.com/vfonic/webflow_sync/workflows/build/badge.svg)](https://github.com/vfonic/webflow_sync/actions)
2
+
2
3
 
3
4
  # WebflowSync
4
5
 
@@ -28,6 +29,14 @@ bundle exec rails generate webflow_sync:install
28
29
 
29
30
  ## Usage
30
31
 
32
+ ### Generate and set WebFlow API token
33
+
34
+ Run API token Rails generator and follow instructions:
35
+
36
+ ```bash
37
+ bundle exec rails generate webflow_sync:api_token_flow
38
+ ```
39
+
31
40
  ### Add WebflowSync to models
32
41
 
33
42
  For each model that you want to sync to WebFlow, you need to run the collection generator:
@@ -53,6 +62,79 @@ For example, for `Article` model:
53
62
 
54
63
  Your WebFlow collection `slug` should be `"articles"`.
55
64
 
65
+ ### Set `webflow_site_id`
66
+
67
+ There are couple of ways how you can set the `webflow_site_id` to be used.
68
+
69
+ #### Set `webflow_site_id` through configuration
70
+
71
+ In `config/initializers/webflow_sync.rb` you can specify `webflow_site_id`:
72
+
73
+ ```ruby
74
+ WebflowSync.configure do |config|
75
+ config.webflow_site_id = ENV.fetch('WEBFLOW_SITE_ID')
76
+ end
77
+ ```
78
+
79
+ #### Set `webflow_site_id` for each model individually
80
+
81
+ You can set `webflow_site_id` per model, or even per record.
82
+
83
+ To do this, override the `#webflow_site_id` method provided by `WebflowSync::ItemSync` in your ActiveRecord model.
84
+
85
+ For example, you could have `Site` model in your codebase:
86
+
87
+ ```ruby
88
+ # app/models/site.rb
89
+ class Site < ApplicationRecord
90
+ has_many :articles
91
+ end
92
+
93
+ # app/models/article.rb
94
+ class Article < ApplicationRecord
95
+ include WebflowSync::ItemSync
96
+
97
+ belongs_to :site
98
+
99
+ def webflow_site_id
100
+ self.site.webflow_site_id
101
+ end
102
+ end
103
+ ```
104
+
105
+ ### Customize fields to synchronize
106
+
107
+ By default, WebflowSync calls `#as_webflow_json` on a record to get the fields that it needs to push to WebFlow. `#as_webflow_json` simply calls `#as_json` in its default implementation. To change this behavior, you can override `#as_json` in your model:
108
+
109
+ ```ruby
110
+ # app/models/article.rb
111
+ class Article < ApplicationRecord
112
+ include WebflowSync::ItemSync
113
+
114
+ def as_json
115
+ {
116
+ title: self.title.capitalize,
117
+ slug: self.title.parameterize,
118
+ published_at: self.created_at,
119
+ image: self.image_url
120
+ }
121
+ end
122
+ end
123
+ ```
124
+
125
+ Or if you already use `#as_json` for some other use-case and cannot modify it, you can also override `#as_webflow_json` method. Here's the default `#as_webflow_json` implementation (you don't need to add this to your model):
126
+
127
+ ```ruby
128
+ # app/models/article.rb
129
+ class Article < ApplicationRecord
130
+ include WebflowSync::ItemSync
131
+
132
+ def as_webflow_json
133
+ self.as_json
134
+ end
135
+ end
136
+ ```
137
+
56
138
  ### Run the initial sync
57
139
 
58
140
  After setting up which models you want to sync to WebFlow, you can run the initial sync for each of the models:
@@ -77,6 +159,11 @@ This gem silently "fails" (does nothing) when `webflow_site_id` or `webflow_item
77
159
 
78
160
  PRs welcome!
79
161
 
162
+ ## Thanks and Credits
163
+
164
+ This gem wouldn't be possible without the amazing work of [webflow-ruby](https://github.com/penseo/webflow-ruby) gem. Thank you, @phoet!
165
+
166
+
80
167
  ## License
81
168
 
82
169
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -10,3 +10,6 @@ load 'rails/tasks/statistics.rake'
10
10
  require 'bundler/gem_tasks'
11
11
 
12
12
  require 'stylecheck/rake_tasks' unless Rails.env.production?
13
+
14
+ load 'rspec/rails/tasks/rspec.rake'
15
+ task default: :spec
@@ -7,8 +7,18 @@ module WebflowSync
7
7
  model_class.where(webflow_item_id: nil).find_each do |record|
8
8
  next if record.webflow_site_id.blank?
9
9
 
10
- WebflowSync::Api.new(record.webflow_site_id).create_item(record, collection_slug)
10
+ client(record.webflow_site_id).create_item(record, collection_slug)
11
11
  end
12
12
  end
13
+
14
+ private
15
+
16
+ def client(site_id)
17
+ if @client&.site_id == site_id
18
+ @client
19
+ else
20
+ @client = WebflowSync::Api.new(site_id)
21
+ end
22
+ end
13
23
  end
14
24
  end
@@ -7,7 +7,7 @@ module WebflowSync
7
7
  record = model_class.find_by(id: id)
8
8
  return if record.blank?
9
9
  return if record.webflow_site_id.blank?
10
- return if record.webflow_item_id.blank?
10
+ return WebflowSync::CreateItemJob.perform_now(collection_slug, id) if record.webflow_item_id.blank?
11
11
 
12
12
  WebflowSync::Api.new(record.webflow_site_id).update_item(record, collection_slug)
13
13
  end
@@ -8,24 +8,38 @@ module WebflowSync
8
8
  @site_id = site_id
9
9
  end
10
10
 
11
- def create_item(record, collection_slug)
11
+ def create_item(record, collection_slug) # rubocop:disable Metrics/MethodLength
12
12
  collection = find_webflow_collection(collection_slug)
13
- response = client.create_item(collection['_id'], record.as_webflow_json, live: true)
13
+ response = client.create_item(
14
+ collection['_id'],
15
+ record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true
16
+ )
14
17
 
15
- record.update!(webflow_item_id: response['_id'])
18
+ # use update_column to skip callbacks to prevent WebflowSync::ItemSync to kick off
19
+ if record.update_column(:webflow_item_id, response['_id']) # rubocop:disable Rails/SkipsModelValidations
20
+ puts "Created #{record.inspect} in #{collection_slug}"
21
+ response
22
+ else
23
+ raise "Failed to store webflow_item_id: '#{response['_id']}' " \
24
+ "after creating item in WebFlow collection #{record.inspect}"
25
+ end
16
26
  end
17
27
 
18
28
  def update_item(record, collection_slug)
19
29
  collection = find_webflow_collection(collection_slug)
20
- client.update_item(
30
+ response = client.update_item(
21
31
  { '_cid' => collection['_id'], '_id' => record.webflow_item_id },
22
- record.as_webflow_json, live: true
32
+ record.as_webflow_json.reverse_merge(_archived: false, _draft: false), live: true
23
33
  )
34
+ puts "Updated #{record.inspect} in #{collection_slug}"
35
+ response
24
36
  end
25
37
 
26
38
  def delete_item(collection_slug, webflow_item_id)
27
39
  collection = find_webflow_collection(collection_slug)
28
- client.delete_item({ '_cid' => collection['_id'], '_id' => webflow_item_id })
40
+ response = client.delete_item({ '_cid' => collection['_id'], '_id' => webflow_item_id })
41
+ puts "Deleted #{webflow_item_id} from #{collection_slug}"
42
+ response
29
43
  end
30
44
 
31
45
  private
@@ -39,10 +53,10 @@ module WebflowSync
39
53
  end
40
54
 
41
55
  def find_webflow_collection(collection_slug)
42
- result = collections.find { |collection| collection['slug'] == collection_slug }
43
- raise "Cannot find collection #{collection_slug} for Webflow site #{site_id}" unless result
56
+ response = collections.find { |collection| collection['slug'] == collection_slug }
57
+ raise "Cannot find collection #{collection_slug} for Webflow site #{site_id}" unless response
44
58
 
45
- result
59
+ response
46
60
  end
47
61
  end
48
62
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+
5
+ module WebflowSync
6
+ module Generators
7
+ class ApiTokenFlowGenerator < Rails::Generators::Base
8
+ desc 'Generates Omniauth flow for authenticating WebFlow application to get WebFlow API token'
9
+
10
+ source_root File.expand_path('templates/api_token', __dir__)
11
+
12
+ def generate
13
+ gem 'omniauth-webflow'
14
+ run 'bundle install'
15
+ template 'webflow_callback_controller.rb.erb', 'app/controllers/webflow_callback_controller.rb'
16
+ template 'omniauth_webflow.rb.erb', 'config/initializers/omniauth_webflow.rb'
17
+ route "post '/auth/webflow/callback', to: 'webflow_callback#index'"
18
+ route "get '/auth/webflow/callback', to: 'webflow_callback#index'"
19
+
20
+ puts <<~END_OF_INSTRUCTIONS.indent(4)
21
+
22
+
23
+ We've generated all the files needed to successfully authenticate
24
+ with WebFlow to get API token.
25
+ There are couple of steps left to get the token:
26
+
27
+ 1. Download ngrok: https://ngrok.com/download
28
+ 2. Run `ngrok http 3000`
29
+ 3. Copy the URL that ngrok gives you (something like: https://dd7cc807bf91.ngrok.io)
30
+ 4. Go to: https://webflow.com/dashboard/account/integrations
31
+ 5. Register New Application
32
+ 6. In "Redirect URI" put: https://dd7cc807bf91.ngrok.io/auth/webflow/callback
33
+ 7. Save
34
+ 8. Copy client ID and client secret to ENV variables or add
35
+ them directly in config/initializers/omniauth_webflow.rb
36
+ 9. Start rails server locally
37
+ 10. Go to https://dd7cc807bf91.ngrok.io/auth/webflow
38
+ 11. Finally authenticate, beware which permissions to give
39
+ (some are "allow access", some are "restrict access", it's confusing)
40
+ 12. Copy the rendered API token and put it in ENV.fetch('WEBFLOW_API_TOKEN')
41
+ 13. After you've got the API token, you probably don't need
42
+ the Omniauth WebFlow code so you can remove the code that this
43
+ generator created from your codebase.
44
+ It is also a security issue to leave the Omniauth endpoint in your
45
+ codebase, that has the ability to generate API tokens for your WebFlow
46
+ account!!!
47
+
48
+ Easy.
49
+
50
+
51
+ END_OF_INSTRUCTIONS
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.config.middleware.use OmniAuth::Builder do
2
+ provider :webflow, ENV.fetch('WEBFLOW_CLIENT_ID'), ENV.fetch('WEBFLOW_CLIENT_SECRET')
3
+ end
@@ -0,0 +1,8 @@
1
+ class WebflowCallbackController < ApplicationController
2
+ skip_before_action :verify_authenticity_token, only: :index
3
+
4
+ # Go to /auth/webflow to start oauth flow
5
+ def index
6
+ render plain: request.env['omniauth.auth'].dig('credentials', 'token')
7
+ end
8
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  WebflowSync.configure do |config|
4
+ # config.api_token = ENV.fetch('WEBFLOW_API_TOKEN')
4
5
  # config.skip_webflow_sync = Rails.env.test? # default
5
6
  config.webflow_site_id = ENV.fetch('WEBFLOW_SITE_ID')
6
7
  end
@@ -6,7 +6,10 @@ module WebflowSync
6
6
 
7
7
  def configure
8
8
  self.configuration ||= Configuration.new
9
- yield(configuration)
9
+ yield(self.configuration)
10
+
11
+ self.configuration.api_token ||= ENV.fetch('WEBFLOW_API_TOKEN')
12
+ defined?(self.configuration.skip_webflow_sync) or self.configuration.skip_webflow_sync = !Rails.env.production?
10
13
  end
11
14
 
12
15
  private
@@ -16,9 +19,10 @@ module WebflowSync
16
19
 
17
20
  class Configuration
18
21
  attr_accessor :skip_webflow_sync, :webflow_site_id
22
+ attr_reader :api_token
19
23
 
20
- def initialize
21
- @skip_webflow_sync = Rails.env.test?
24
+ def api_token=(value)
25
+ @api_token = Webflow.config.api_token = value
22
26
  end
23
27
  end
24
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebflowSync
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.5'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webflow_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Viktor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-29 00:00:00.000000000 Z
11
+ date: 2021-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -139,11 +139,14 @@ files:
139
139
  - app/models/concerns/webflow_sync/callbacks.rb
140
140
  - app/models/concerns/webflow_sync/item_sync.rb
141
141
  - app/services/webflow_sync/api.rb
142
+ - lib/generators/webflow_sync/api_token_flow_generator.rb
142
143
  - lib/generators/webflow_sync/collection_generator.rb
143
144
  - lib/generators/webflow_sync/install_generator.rb
145
+ - lib/generators/webflow_sync/templates/api_token/omniauth_webflow.rb.erb
146
+ - lib/generators/webflow_sync/templates/api_token/webflow_callback_controller.rb.erb
144
147
  - lib/generators/webflow_sync/templates/migration.rb.erb
145
148
  - lib/generators/webflow_sync/templates/webflow_sync.rb
146
- - lib/tasks/webflow_sync_tasks.rake
149
+ - lib/tasks/webflow_sync.rake
147
150
  - lib/webflow_sync.rb
148
151
  - lib/webflow_sync/configuration.rb
149
152
  - lib/webflow_sync/engine.rb