webflow_sync 0.1.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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