contentful-scheduler-custom 1.5.67 → 1.5.68

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
  SHA1:
3
- metadata.gz: 3d700df18af4a308431bcb931a581304e7253751
4
- data.tar.gz: 8c12adcb7d1e97ccb06edc3baa080117d9ff04c6
3
+ metadata.gz: b23896e7b4befb25af78b9981bca9d0edb92b06a
4
+ data.tar.gz: 2393d45d988a62464cc77e0bdb06c33daf2413dc
5
5
  SHA512:
6
- metadata.gz: d341ff8a1576fb285344e4a055f27b9ffd58e8b9bd39c7010c53204b4c5e325303ccbb609101e677ea647a560ef3193cee8ed7e10dd9e7d0f4238abc8a57c725
7
- data.tar.gz: 075f6a3126ee8ce47d3e29cf8db24b0325bdc1c158205d39dcb57569b6981ce878731148f235d3655ecc70b603d4da842cbd453a11404839c78d3689e1b17aca
6
+ metadata.gz: 5f6103151ddb2b5528ad24ece7ac9ceba192a279bca59d70528e5573d37bdbd5202ad59773b1cc3d29d3dcd338fdc78249f4721ea3530f05d66758014fcd1210
7
+ data.tar.gz: b1d756756538ea4beb14583978b48b23e58e64fe5972481d6efe21f8407c96544b7c3657aca816d80c4042f47e3ca24131782f7ad378db9f935469eb04dcd01c
data/.gitignore CHANGED
@@ -9,5 +9,3 @@
9
9
  /tmp/
10
10
  .DS_Store
11
11
  dump.rdb
12
- /.idea/
13
- /example/.rakeTasks
data/CHANGELOG.md CHANGED
@@ -2,14 +2,25 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 1.4.0
6
- * Contentful Scheduler now supports future publishing for any existing enteries and
7
- publishing ContentBlocks first before publishing the page.
5
+ ## 0.5.0
6
+ ### Added
7
+ * Added support for scheduled unpublishing. [#10](https://github.com/contentful/contentful-scheduler.rb/issues/10)
8
+
9
+ ## 0.4.0
10
+ ### Fixed
11
+ * Fixed User Agent Header to comply with specification.
12
+
13
+ ### Added
14
+ * Added authentication mechanisms. [#9](https://github.com/contentful/contentful-scheduler.rb/issues/9)
15
+
16
+ ## 0.3.0
17
+ ### Added
18
+ * Added possibility to republish already published content. [#5](https://github.com/contentful/contentful-scheduler.rb/issues/5)
8
19
 
9
20
  ## 0.2.1
10
21
 
11
22
  ### Fixed
12
- * Fix time parsing.
23
+ * Fixed time parsing.
13
24
 
14
25
  ## 0.2.0
15
26
 
data/README.md CHANGED
@@ -7,17 +7,18 @@ Scheduling Server for Contentful entries.
7
7
 
8
8
  ## What does `contentful-scheduler` do?
9
9
  The aim of `contentful-scheduler` is to have developers setting up their Contentful
10
- entries for scheduled publishing.
10
+ entries for scheduled publishing and unpublishing.
11
11
 
12
12
  ## How does it work
13
- `contentful-scheduler` provides a web endpoint to receive webhook calls from Contentful,
14
- every time the endpoint recieves a call it looks for the value of the field defined in the configuration,
15
- if the value is a time in the future it will schedule the entry for publishing at the specified time.
13
+ `contentful-scheduler` provides a web endpoint to receive webhook calls from Contentful.
14
+
15
+ Every time the endpoint recieves a call it looks for the value of the field defined in the configuration.
16
+ If the value is a time in the future it will schedule the entry for publishing or unpublishing at the specified time.
17
+
16
18
  A background worker based on the popular `resque` gem will then proceed to actually make the publish call
17
- against the Content Management API at the due time. For this the Entries you wish to publish require a
18
- customizable Date field, which we advice to call `publishDate`, this field can be configured inside your
19
- `Rakefile` and is specific per-space(supports multiple spaces), also please make sure contentBlocks are valid
20
- as per logic contentBlocks are published first then the page is published, so if there is any contentBlocks missing publishing won't work.
19
+ against the Content Management API at the due time. For this the Entries you wish to publish or unpublish require a
20
+ customizable Date field, which we advice to call `publishDate` for the publishing action and `unpublishDate` for the unpublishing action,
21
+ this field can be configured inside your `Rakefile` and is specific per-space.
21
22
 
22
23
  You can add multiple spaces to your configuration, making it useful if you have a milti-space setup.
23
24
 
@@ -30,7 +31,7 @@ You can add multiple spaces to your configuration, making it useful if you have
30
31
  Add this line to your application's Gemfile:
31
32
 
32
33
  ```ruby
33
- gem 'contentful-scheduler-custom'
34
+ gem 'contentful-scheduler'
34
35
  ```
35
36
 
36
37
  And then execute:
@@ -39,7 +40,7 @@ And then execute:
39
40
 
40
41
  Or install it yourself as:
41
42
 
42
- $ gem install contentful-scheduler-custom
43
+ $ gem install contentful-scheduler
43
44
 
44
45
  ## Usage
45
46
 
@@ -55,7 +56,7 @@ If you want to roll out your own, you need to follow the next steps:
55
56
  ```ruby
56
57
  source 'https://rubygems.org'
57
58
 
58
- gem 'contentful-scheduler-custom', '~>1.4'
59
+ gem 'contentful-scheduler', '~> 0.1'
59
60
  gem 'contentful-management', '~> 1.0'
60
61
  gem 'resque', '~> 1.0'
61
62
  gem 'resque-scheduler', '~> 4.0'
@@ -90,15 +91,11 @@ config = {
90
91
  spaces: {
91
92
  'YOUR_SPACE_ID' => {
92
93
  publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
93
- management_token: 'YOUR_TOKEN'
94
- },
95
- 'YOUR_SPACE_ID' => {
96
- publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
97
- management_token: 'YOUR_TOKEN'
98
- },
99
- 'YOUR_SPACE_ID' => {
100
- publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
101
- management_token: 'YOUR_TOKEN'
94
+ unpublish_field: 'unpublishDate', # Optional - It specifies the field ID for your Unpublish Date in your Content Type
95
+ management_token: 'YOUR_TOKEN',
96
+ auth: { # This is optional
97
+ # ... content in this section will be explained in a separate section ...
98
+ }
102
99
  }
103
100
  },
104
101
  }
@@ -159,85 +156,114 @@ Under the space settings menu choose webhook and add a new webhook pointing to `
159
156
 
160
157
  Keep in mind that if you modify the defaults, the URL should be changed to the values specified in the configuration.
161
158
 
162
- ## Running in Heroku
159
+ ## Authentication
163
160
 
164
- Heroku offers various Redis plugins, select the one of your liking, add the credentials into your configuration, and proceed to
165
- `git heroku push master`.
161
+ You may want to provide an additional layer of security to your scheduler server, therefore an additional option to add space based authentication is provided.
166
162
 
167
- This will get your application set up and running. It will require 4 dynos, so a free plan isn't enough for it to run.
163
+ There are two available authentication methods. Static string matching and lambda validations, which will be explained in the next section.
168
164
 
169
- To run the `monitor` process, you'll require to run it from a different application pointing to the same Redis instance.
165
+ Any of both mechanisms require you to add additional headers to your webhook set up, which can be done through the [Contentful Web App](https://app.contentful.com),
166
+ or through the [CMA](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/webhooks/webhook/create-update-a-webhook/console/ruby).
170
167
 
171
- Make sure to change the `Procfile`'s `web` process to the following:
168
+ ### Authentication via static token matching
172
169
 
173
- ```
174
- web: PORT=$PORT bundle exec env rake contentful:scheduler
175
- ```
170
+ The simplest authentication mechanism, is to provide a static set of valid strings that are considered valid when found in a determined header.
176
171
 
177
- That will allow Heroku to set it's own Port according to their policy.
172
+ For example:
178
173
 
179
- The URL for the webhook then will be on port 80, so you should change it to: `http://YOUR_APPLICATION/scheduler`.
174
+ ```ruby
175
+ config = {
176
+ # ... the rest of the config ...
177
+ spaces: {
178
+ 'my_space' => {
179
+ # ... the rest of the space specific configuration ...
180
+ auth: {
181
+ key: 'X-Webhook-Server-Auth-Header',
182
+ valid_tokens: ['some_valid_static_token']
183
+ }
184
+ }
185
+ }
186
+ }
187
+ ```
180
188
 
181
- ## Running in Production Mode
189
+ The above example, whenever your webhook sends the `X-Webhook-Server-Auth-Header` with a value of `some_valid_static_token`,
190
+ it will accept the request and queue your webhook for processing.
182
191
 
183
- After verifying that application is working fine in development mode(run "foreman start" for development mode)
192
+ You can provide multiple or a single token. If a single token is provided, it's not necessary to include it in an array.
184
193
 
185
- Run the following commands
194
+ ### Authentication via lambda
186
195
 
187
- 1. sudo foreman export -p5000 --app stp --user username_to_start_from systemd /etc/systemd/system/
196
+ A more complicated solution, but far more secure, is the ability to execute a lambda as the validator function.
197
+ This allows you define a function for authentication. This function can call an external authentication service,
198
+ make checks against a database or do internal processing.
188
199
 
189
- Output will be like this:
200
+ The function must return a truthy/falsey value in order for the authentication to be successful/unsuccessful.
190
201
 
191
- [foreman export] cleaning up directory: /etc/systemd/system//graphical.target.wants
192
- [foreman export] writing: stp-web@.service
193
- [foreman export] creating: stp-web.target.wants
194
- [foreman export] symlinking: stp-web.target.wants/stp-web@5000.service -> ../stp-web@.service
195
- [foreman export] writing: stp-web.target
196
- [foreman export] writing: stp-celery@.service
197
- [foreman export] creating: stp-celery.target.wants
198
- [foreman export] symlinking: stp-celery.target.wants/stp-celery@5100.service -> ../stp-celery@.service
199
- [foreman export] writing: stp-celery.target
200
- [foreman export] writing: stp.target
202
+ For example, we validate that the token provided is either `foo` or `bar`:
201
203
 
202
- 2. cat /etc/systemd/system/stp-web@.service | head -n 10
204
+ ```ruby
205
+ config = {
206
+ # ... the rest of the config ...
207
+ spaces: {
208
+ 'my_space' => {
209
+ # ... the rest of the space specific configuration ...
210
+ auth: {
211
+ key: 'X-Webhook-Server-Auth-Header',
212
+ validation: -> (value) { /^(foo|bar)$/ =~ value }
213
+ }
214
+ }
215
+ }
216
+ }
217
+ ```
203
218
 
204
- Output will be like this:
219
+ Or a more complicated example, checking if the header is a valid OAuth token, and then making a request to our OAuth database.
220
+ For this example we'll consider you have a table called `tokens` and are using [DataMapper](https://datamapper.org) as a ORM,
221
+ and have a `valid?` method checking if the token is not expired.
205
222
 
206
- [Unit]
207
- PartOf=stp-web.target
223
+ ```ruby
224
+ config = {
225
+ # ... the rest of the config ...
226
+ spaces: {
227
+ 'my_space' => {
228
+ # ... the rest of the space specific configuration ...
229
+ auth: {
230
+ key: 'X-Webhook-Server-Auth-Header',
231
+ validation: proc do |value|
232
+ return false unless /^Bearer \w+/ =~ value
208
233
 
209
- [Service]
210
- User=username_to_start_from
211
- WorkingDirectory=/srv/stp/
212
- Environment=PORT=%i
213
- ... HERE OTHER DIRICTIVES FROM YOUR .env file ...
214
- Environment=DEBUG=0
215
- ...
234
+ token = Token.first(token: value.gsub('Bearer ', ''))
216
235
 
236
+ return false if token.nil?
217
237
 
218
- 3. Start only gunicorn on port 5700:
238
+ token.valid?
239
+ end
240
+ }
241
+ }
242
+ }
243
+ }
244
+ ```
219
245
 
220
- systemctl start stp-web@5700.service
246
+ If you have multiple spaces and all share the same auth strategy, you can extract the authentication method to a variable,
247
+ and assign it to all the applicable spaces in order to reduce the code duplication.
221
248
 
222
- 4. Start whole target:
249
+ ## Running in Heroku
223
250
 
224
- systemctl start stp.target
251
+ Heroku offers various Redis plugins, select the one of your liking, add the credentials into your configuration, and proceed to
252
+ `git heroku push master`.
225
253
 
226
- 5. Enable whole target (start on OS boot):
254
+ This will get your application set up and running. It will require 4 dynos, so a free plan isn't enough for it to run.
227
255
 
228
- systemctl enable stp.target
256
+ To run the `monitor` process, you'll require to run it from a different application pointing to the same Redis instance.
229
257
 
230
- 6. Restarting daemon
258
+ Make sure to change the `Procfile`'s `web` process to the following:
231
259
 
232
- sudo systemctl daemon-reload
233
-
234
- sudo systemctl restart stp.target
235
-
236
- 7. Optional
260
+ ```
261
+ web: PORT=$PORT bundle exec env rake contentful:scheduler
262
+ ```
237
263
 
238
- You can also simply define port when call foreman export -pXXXX, but it should be multiple of 1000,
239
- e.g. 1000, 2000, 3000, 45000 etc.
264
+ That will allow Heroku to set it's own Port according to their policy.
240
265
 
266
+ The URL for the webhook then will be on port 80, so you should change it to: `http://YOUR_APPLICATION/scheduler`.
241
267
 
242
268
  ## Contributing
243
269
 
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_runtime_dependency "contentful-webhook-listener", "~> 0.2"
23
23
  spec.add_runtime_dependency "contentful-management", "~> 1.8"
24
- spec.add_runtime_dependency "resque", "~> 1.27.4"
25
- spec.add_runtime_dependency "resque-scheduler", "~> 4.2.1"
24
+ spec.add_runtime_dependency "resque", "~> 1.0"
25
+ spec.add_runtime_dependency "resque-scheduler", "~> 4.0"
26
26
  spec.add_runtime_dependency "redis", "~> 3.0"
27
27
  spec.add_runtime_dependency "chronic", "~> 0.10"
28
28
 
data/example/Gemfile CHANGED
@@ -1,8 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'contentful-scheduler-custom', '~>1.4'
3
+ gem 'contentful-scheduler', '~> 0.1'
4
4
  gem 'contentful-management', '~> 1.0'
5
5
  gem 'resque', '~> 1.0'
6
- gem 'resque-scheduler', '4.2.1'
6
+ gem 'resque-scheduler', '~> 4.0'
7
7
  gem 'rake'
8
- gem 'foreman', '~> 0.84.0'
data/example/Procfile CHANGED
@@ -1,4 +1,4 @@
1
- web: PORT=$PORT bundle exec env rake contentful:scheduler
1
+ web: env bundle exec rake contentful:scheduler
2
2
  monitor: env bundle exec rackup
3
3
  resque: env bundle exec rake resque:work
4
- resque_scheduler: env bundle exec rake resque:scheduler
4
+ resque_scheduler: env bundle exec rake resque:scheduler
data/example/Rakefile CHANGED
@@ -1,22 +1,23 @@
1
1
  require 'contentful/scheduler'
2
+ require 'logger' # Optional
2
3
 
3
4
  $stdout.sync = true
4
5
 
5
6
  config = {
6
7
  logger: Logger.new(STDOUT), # Defaults to NullLogger
7
- port: 8080, # Defaults to 8081
8
+ port: 32123, # Defaults to 32123
8
9
  endpoint: '/scheduler', # Defaults to /scheduler
9
10
  redis: {
10
- host: 'scheduler-redis-db',
11
- port: '6379',
12
- password: 'password'
11
+ host: 'YOUR_REDIS_HOST',
12
+ port: 'YOUR_REDIS_PORT',
13
+ password: 'YOUR_REDIS_PASSWORD'
13
14
  },
14
15
  spaces: {
15
- 'qbra4qai2ti2' => {
16
+ 'YOUR_SPACE_ID' => {
16
17
  publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
17
- management_token: 'CFPAT-45f0c4258aa9b32e8a8b6ccebf64136386b31f3ec435cc17f540368d5416de02'
18
+ management_token: 'YOUR_TOKEN'
18
19
  }
19
- },
20
+ }
20
21
  }
21
22
 
22
23
  namespace :contentful do
data/example/config.ru CHANGED
@@ -3,9 +3,9 @@ require 'resque/server'
3
3
  require 'resque/scheduler/server'
4
4
 
5
5
  config = {
6
- host: 'scheduler-redis-db',
7
- port: '6379',
8
- password: 'password'
6
+ host: 'YOUR_REDIS_HOST',
7
+ port: 'YOUR_REDIS_PORT',
8
+ password: 'YOUR_REDIS_PASSWORD'
9
9
  }
10
10
  Resque.redis = config
11
11
 
@@ -0,0 +1,64 @@
1
+ module Contentful
2
+ module Scheduler
3
+ class Auth
4
+ attr_reader :webhook
5
+
6
+ def initialize(webhook)
7
+ @webhook = webhook
8
+ end
9
+
10
+ def auth
11
+ return true if auth_config.nil?
12
+
13
+ return verify_key_value_config if key_value_config?
14
+ return verify_lambda_config if lambda_config?
15
+
16
+ false
17
+ end
18
+
19
+ private
20
+
21
+ def key_value_config?
22
+ auth_config.key?(:key) && auth_config.key?(:valid_tokens)
23
+ end
24
+
25
+ def verify_key_value_config
26
+ value = webhook.raw_headers[auth_config[:key]]
27
+
28
+ return false if value.nil?
29
+
30
+ valid_tokens = auth_config[:valid_tokens]
31
+
32
+ return valid_tokens.include?(value) if valid_tokens.is_a?(::Array)
33
+ valid_tokens == value
34
+ end
35
+
36
+ def lambda_config?
37
+ auth_config.key?(:key) && auth_config.key?(:validation)
38
+ end
39
+
40
+ def verify_lambda_config
41
+ value = webhook.raw_headers[auth_config[:key]]
42
+
43
+ return false if value.nil?
44
+
45
+ validation = auth_config[:validation]
46
+
47
+ return false unless validation.is_a?(::Proc)
48
+
49
+ validation[value]
50
+ end
51
+
52
+ def auth_config
53
+ ::Contentful::Scheduler.config
54
+ .fetch(:spaces, {})
55
+ .fetch(space_id, {})
56
+ .fetch(:auth, nil)
57
+ end
58
+
59
+ def space_id
60
+ webhook.space_id
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,4 +1,5 @@
1
1
  require 'contentful/webhook/listener'
2
+ require_relative 'auth'
2
3
  require_relative 'queue'
3
4
 
4
5
  module Contentful
@@ -7,6 +8,11 @@ module Contentful
7
8
  def create
8
9
  return unless webhook.entry?
9
10
 
11
+ if !Auth.new(webhook).auth
12
+ logger.warn "Skipping - Authentication failed for Space: #{webhook.space_id} - Entry: #{webhook.id}"
13
+ return
14
+ end
15
+
10
16
  logger.info "Queueing - Space: #{webhook.space_id} - Entry: #{webhook.id}"
11
17
 
12
18
  Queue.instance(logger).update_or_create(webhook)
@@ -18,6 +24,11 @@ module Contentful
18
24
  def delete
19
25
  return unless webhook.entry?
20
26
 
27
+ if !Auth.new(webhook).auth
28
+ logger.warn "Skipping - Authentication failed for Space: #{webhook.space_id} - Entry: #{webhook.id}"
29
+ return
30
+ end
31
+
21
32
  logger.info "Unqueueing - Space: #{webhook.space_id} - Entry: #{webhook.id}"
22
33
 
23
34
  Queue.instance(logger).remove(webhook)
@@ -21,11 +21,10 @@ module Contentful
21
21
  end
22
22
 
23
23
  if unpublishable?(webhook)
24
- success = update_or_create_for_unpublish(webhook)
24
+ success = update_or_create_for_unpublish(webhook) && success
25
25
  updateContentBlocks(webhook, 'unpublish')
26
26
  log_event_success(webhook, success, 'unpublish', 'added to')
27
27
  end
28
-
29
28
  end
30
29
 
31
30
  def update_or_create_for_publish(webhook)
@@ -55,17 +54,14 @@ module Contentful
55
54
  end
56
55
 
57
56
  def remove(webhook)
58
- remove_unpublish(webhook)
59
57
  remove_publish(webhook)
58
+ remove_unpublish(webhook)
60
59
  end
61
60
 
62
61
  def remove_publish(webhook)
63
- logger.info "In publish remove block #{publishable?(webhook)} with #{in_publish_queue?(webhook)}"
64
62
  return unless publishable?(webhook)
65
63
  return unless in_publish_queue?(webhook)
66
64
 
67
- logger.info "before before publish content block remove block"
68
-
69
65
  success = Resque.remove_delayed(
70
66
  ::Contentful::Scheduler::Tasks::Publish,
71
67
  webhook.space_id,
@@ -73,67 +69,50 @@ module Contentful
73
69
  ::Contentful::Scheduler.config[:management_token]
74
70
  )
75
71
 
76
- logger.info "before publish content block remove block"
77
-
78
72
  removeContentBlocks(webhook, 'publish')
79
73
 
80
74
  log_event_success(webhook, success, 'publish', 'removed from')
81
75
  end
82
76
 
83
- def updateContentBlocks(webhook, type)
84
- if isContentBlockAvailable(webhook)
85
- webhook.fields['contentBlocks']['fi-FI'].each do |sys|
86
- success = Resque.enqueue_at(
87
- publish_date(webhook),
88
- getScheduleType(type),
89
- webhook.space_id,
90
- sys['sys']['id'],
91
- ::Contentful::Scheduler.config[:spaces][webhook.space_id][:management_token]
92
- )
93
- if success
94
- logger.info "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully added to " + type + " queue"
95
- else
96
- logger.warn "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be added to " + type + " queue"
97
- end
98
- end
99
- end
77
+ def remove_unpublish(webhook)
78
+ return unless unpublishable?(webhook)
79
+ return unless in_unpublish_queue?(webhook)
80
+
81
+ success = Resque.remove_delayed(
82
+ ::Contentful::Scheduler::Tasks::Unpublish,
83
+ webhook.space_id,
84
+ webhook.id,
85
+ ::Contentful::Scheduler.config[:management_token]
86
+ )
87
+
88
+ removeContentBlocks(webhook, 'unpublish')
89
+
90
+ log_event_success(webhook, success, 'unpublish', 'removed from')
100
91
  end
101
92
 
102
- def getScheduleType(type)
103
- if type == 'unpublish'
104
- return ::Contentful::Scheduler::Tasks::Unpublish
93
+ def log_event_success(webhook, success, event_kind, action)
94
+ if success
95
+ logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully #{action} the #{event_kind} queue"
105
96
  else
106
- return ::Contentful::Scheduler::Tasks::Publish
97
+ logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
107
98
  end
108
99
  end
109
100
 
110
- def removeContentBlocks(webhook, type)
111
- if isContentBlockAvailable(webhook)
112
- webhook.fields['contentBlocks']['fi-FI'].each do |sys|
113
- success = Resque.remove_delayed(
114
- getScheduleType(type),
115
- webhook.space_id,
116
- sys['sys']['id'],
117
- ::Contentful::Scheduler.config[:management_token]
118
- )
119
- if success
120
- logger.info "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully removed from " + type + " queue"
121
- else
122
- logger.warn "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be removed from " + type + " queue"
123
- end
124
- end
101
+ def publishable?(webhook)
102
+ return false unless spaces.key?(webhook.space_id)
103
+
104
+ if webhook_publish_field?(webhook)
105
+ return !webhook_publish_field(webhook).nil? && publish_is_future?(webhook)
125
106
  end
126
- end
127
107
 
128
- def isContentBlockAvailable(webhook)
129
- return !webhook.fields['contentBlocks'].nil?
108
+ false
130
109
  end
131
110
 
132
- def publishable?(webhook)
111
+ def unpublishable?(webhook)
133
112
  return false unless spaces.key?(webhook.space_id)
134
113
 
135
- if webhook_publish_field?(webhook)
136
- return !webhook_publish_field(webhook).nil? && publish_is_future?(webhook)
114
+ if webhook_unpublish_field?(webhook)
115
+ return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
137
116
  end
138
117
 
139
118
  false
@@ -143,53 +122,22 @@ module Contentful
143
122
  publish_date(webhook) > Time.now.utc
144
123
  end
145
124
 
125
+ def unpublish_is_future?(webhook)
126
+ unpublish_date(webhook) > Time.now.utc
127
+ end
128
+
146
129
  def in_publish_queue?(webhook)
147
130
  Resque.peek(::Contentful::Scheduler::Tasks::Publish, 0, -1).any? do |job|
148
131
  job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
149
132
  end
150
133
  end
151
134
 
152
- def remove_unpublish(webhook)
153
- logger.info "In unpublish remove block #{unpublishable?(webhook)} with #{in_unpublish_queue?(webhook)}"
154
- return unless unpublishable?(webhook)
155
- return unless in_unpublish_queue?(webhook)
156
-
157
- logger.info "before before unpublish content block remove block"
158
-
159
- success = Resque.remove_delayed(
160
- ::Contentful::Scheduler::Tasks::Unpublish,
161
- webhook.space_id,
162
- webhook.id,
163
- ::Contentful::Scheduler.config[:management_token]
164
- )
165
-
166
- logger.info "before unpublish content block remove block"
167
-
168
- removeContentBlocks(webhook, 'unpublish')
169
-
170
- log_event_success(webhook, success, 'unpublish', 'removed from')
171
- end
172
-
173
135
  def in_unpublish_queue?(webhook)
174
136
  Resque.peek(::Contentful::Scheduler::Tasks::Unpublish, 0, -1).any? do |job|
175
137
  job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
176
138
  end
177
139
  end
178
140
 
179
- def unpublish_is_future?(webhook)
180
- unpublish_date(webhook) > Time.now.utc
181
- end
182
-
183
- def unpublishable?(webhook)
184
- return false unless spaces.key?(webhook.space_id)
185
-
186
- if webhook_unpublish_field?(webhook)
187
- return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
188
- end
189
-
190
- false
191
- end
192
-
193
141
  def publish_date(webhook)
194
142
  date_field = webhook_publish_field(webhook)
195
143
  date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
@@ -202,6 +150,55 @@ module Contentful
202
150
  Chronic.parse(date_field).utc
203
151
  end
204
152
 
153
+ def updateContentBlocks(webhook, type)
154
+ if isContentBlockAvailable(webhook)
155
+ webhook.fields['contentBlocks']['fi-FI'].each do |sys|
156
+ success = Resque.enqueue_at(
157
+ publish_date(webhook),
158
+ getScheduleType(type),
159
+ webhook.space_id,
160
+ sys['sys']['id'],
161
+ ::Contentful::Scheduler.config[:spaces][webhook.space_id][:management_token]
162
+ )
163
+ if success
164
+ logger.info "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully added to " + type + " queue"
165
+ else
166
+ logger.warn "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be added to " + type + " queue"
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ def removeContentBlocks(webhook, type)
173
+ if isContentBlockAvailable(webhook)
174
+ webhook.fields['contentBlocks']['fi-FI'].each do |sys|
175
+ success = Resque.remove_delayed(
176
+ getScheduleType(type),
177
+ webhook.space_id,
178
+ sys['sys']['id'],
179
+ ::Contentful::Scheduler.config[:management_token]
180
+ )
181
+ if success
182
+ logger.info "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully removed from " + type + " queue"
183
+ else
184
+ logger.warn "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be removed from " + type + " queue"
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ def isContentBlockAvailable(webhook)
191
+ return !webhook.fields['contentBlocks'].nil?
192
+ end
193
+
194
+ def getScheduleType(type)
195
+ if type == 'unpublish'
196
+ return ::Contentful::Scheduler::Tasks::Unpublish
197
+ else
198
+ return ::Contentful::Scheduler::Tasks::Publish
199
+ end
200
+ end
201
+
205
202
  def spaces
206
203
  config[:spaces]
207
204
  end
@@ -222,14 +219,6 @@ module Contentful
222
219
  webhook.fields[spaces[webhook.space_id][:unpublish_field]]
223
220
  end
224
221
 
225
- def log_event_success(webhook, success, event_kind, action)
226
- if success
227
- logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully #{action} the #{event_kind} queue"
228
- else
229
- logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
230
- end
231
- end
232
-
233
222
  private
234
223
 
235
224
  def initialize(logger)
@@ -10,7 +10,7 @@ module Contentful
10
10
  client = ::Contentful::Management::Client.new(
11
11
  token,
12
12
  raise_errors: true,
13
- application_name: 'contentful-scheduler',
13
+ application_name: 'contentful.scheduler',
14
14
  application_version: Contentful::Scheduler::VERSION
15
15
  )
16
16
  client.entries.find(space_id, entry_id).publish
@@ -10,7 +10,7 @@ module Contentful
10
10
  client = ::Contentful::Management::Client.new(
11
11
  token,
12
12
  raise_errors: true,
13
- application_name: 'contentful-scheduler',
13
+ application_name: 'contentful.scheduler',
14
14
  application_version: Contentful::Scheduler::VERSION
15
15
  )
16
16
  client.entries.find(space_id, entry_id).unpublish
@@ -18,4 +18,4 @@ module Contentful
18
18
  end
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -1,5 +1,5 @@
1
1
  module Contentful
2
2
  module Scheduler
3
- VERSION = "1.5.67"
3
+ VERSION = "1.5.68"
4
4
  end
5
5
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Contentful::Scheduler::Auth do
4
+ before :each do
5
+ Contentful::Scheduler.config = base_config
6
+ end
7
+
8
+ describe 'auth' do
9
+ context 'when no auth is provided' do
10
+ it 'always returns true' do
11
+ webhook = WebhookDouble.new('id', 'no_auth')
12
+ expect(described_class.new(webhook).auth).to be_truthy
13
+ end
14
+ end
15
+
16
+ context 'when providing token array auth' do
17
+ it 'false when key not found' do
18
+ webhook = WebhookDouble.new('id', 'valid_token_array')
19
+ expect(described_class.new(webhook).auth).to be_falsey
20
+ end
21
+
22
+ it 'false when key found but value not matched' do
23
+ webhook = WebhookDouble.new('id', 'valid_token_array', {}, {}, {'auth' => 'not_valid'})
24
+ expect(described_class.new(webhook).auth).to be_falsey
25
+ end
26
+
27
+ it 'true when key found and value matched' do
28
+ webhook = WebhookDouble.new('id', 'valid_token_array', {}, {}, {'auth' => 'test_1'})
29
+ expect(described_class.new(webhook).auth).to be_truthy
30
+ end
31
+ end
32
+
33
+ context 'when providing token string auth' do
34
+ it 'false when key not found' do
35
+ webhook = WebhookDouble.new('id', 'valid_token_string')
36
+ expect(described_class.new(webhook).auth).to be_falsey
37
+ end
38
+
39
+ it 'false when key found but value not matched' do
40
+ webhook = WebhookDouble.new('id', 'valid_token_string', {}, {}, {'auth' => 'not_valid'})
41
+ expect(described_class.new(webhook).auth).to be_falsey
42
+ end
43
+
44
+ it 'true when key found and value matched' do
45
+ webhook = WebhookDouble.new('id', 'valid_token_string', {}, {}, {'auth' => 'test_2'})
46
+ expect(described_class.new(webhook).auth).to be_truthy
47
+ end
48
+ end
49
+
50
+ context 'when providing lambda auth' do
51
+ it 'false when key not found' do
52
+ webhook = WebhookDouble.new('id', 'lambda_auth')
53
+ expect(described_class.new(webhook).auth).to be_falsey
54
+ end
55
+
56
+ it 'false when key found but value not matched' do
57
+ webhook = WebhookDouble.new('id', 'lambda_auth', {}, {}, {'auth' => 'not_valid'})
58
+ expect(described_class.new(webhook).auth).to be_falsey
59
+ end
60
+
61
+ it 'true when key found and value matched' do
62
+ webhook = WebhookDouble.new('id', 'lambda_auth', {}, {}, {'auth' => 'test'})
63
+ expect(described_class.new(webhook).auth).to be_truthy
64
+ end
65
+ end
66
+ end
67
+ end
@@ -9,6 +9,10 @@ describe Contentful::Scheduler::Controller do
9
9
  let(:queue) { ::Contentful::Scheduler::Queue.instance }
10
10
  subject { described_class.new server, logger, timeout }
11
11
 
12
+ before :each do
13
+ Contentful::Scheduler.config = base_config
14
+ end
15
+
12
16
  describe 'events' do
13
17
  [:create, :save, :auto_save, :unarchive].each do |event|
14
18
  it "creates or updates webhook metadata in publish queue on #{event}" do
@@ -42,5 +46,19 @@ describe Contentful::Scheduler::Controller do
42
46
  end
43
47
  end
44
48
  end
49
+
50
+ describe 'auth' do
51
+ context 'on auth failure' do
52
+ let(:body) { {sys: { id: 'invalid_auth', space: { sys: { id: 'valid_token_string' } } }, fields: {} } }
53
+
54
+ it 'will stop the queueing process' do
55
+ expect(queue).not_to receive(:update_or_create)
56
+
57
+ headers['X-Contentful-Topic'] = "ContentfulManagement.Entry.save"
58
+ request = RequestDummy.new(headers, body)
59
+ subject.respond(request, MockResponse.new).join
60
+ end
61
+ end
62
+ end
45
63
  end
46
64
  end
@@ -1,7 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'contentful/management'
4
-
5
3
  describe Contentful::Scheduler::Queue do
6
4
  let(:config) { base_config }
7
5
  subject { described_class.instance }
@@ -262,4 +260,4 @@ describe Contentful::Scheduler::Queue do
262
260
  end
263
261
  end
264
262
  end
265
- end
263
+ end
@@ -29,7 +29,7 @@ describe Contentful::Scheduler::Tasks::Publish do
29
29
  expect(::Contentful::Management::Client).to receive(:new).with(
30
30
  'foo',
31
31
  raise_errors: true,
32
- application_name: 'contentful-scheduler',
32
+ application_name: 'contentful.scheduler',
33
33
  application_version: Contentful::Scheduler::VERSION
34
34
  ) { mock_client }
35
35
  expect(mock_client).to receive(:entries) { mock_entries }
@@ -39,4 +39,4 @@ describe Contentful::Scheduler::Tasks::Publish do
39
39
  described_class.perform('foo', 'bar', ::Contentful::Scheduler.config[:spaces]['foo'][:management_token])
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class MockEntry
4
- def unpublish
4
+ def publish
5
5
  end
6
6
  end
7
7
 
@@ -21,22 +21,22 @@ describe Contentful::Scheduler::Tasks::Unpublish do
21
21
  let(:mock_entry) { MockEntry.new }
22
22
 
23
23
  before :each do
24
- ::Contentful::Scheduler.class_variable_set(:@@config, {management_token: 'foobar'})
24
+ ::Contentful::Scheduler.config = base_config
25
25
  end
26
26
 
27
27
  describe 'class methods' do
28
28
  it '::perform' do
29
29
  expect(::Contentful::Management::Client).to receive(:new).with(
30
- 'foobar',
30
+ 'foo',
31
31
  raise_errors: true,
32
- application_name: 'contentful-scheduler',
32
+ application_name: 'contentful.scheduler',
33
33
  application_version: Contentful::Scheduler::VERSION
34
34
  ) { mock_client }
35
35
  expect(mock_client).to receive(:entries) { mock_entries }
36
36
  expect(mock_entries).to receive(:find).with('foo', 'bar') { mock_entry }
37
37
  expect(mock_entry).to receive(:unpublish)
38
38
 
39
- described_class.perform('foo', 'bar', ::Contentful::Scheduler.config[:management_token])
39
+ described_class.perform('foo', 'bar', ::Contentful::Scheduler.config[:spaces]['foo'][:management_token])
40
40
  end
41
41
  end
42
42
  end
data/spec/spec_helper.rb CHANGED
@@ -120,4 +120,4 @@ end
120
120
  RSpec.configure do |config|
121
121
  config.filter_run :focus => true
122
122
  config.run_all_when_everything_filtered = true
123
- end
123
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful-scheduler-custom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.67
4
+ version: 1.5.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - Contentful GmbH (David Litvak Bruno0
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.27.4
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.27.4
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: resque-scheduler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 4.2.1
61
+ version: '4.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 4.2.1
68
+ version: '4.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -196,18 +196,19 @@ files:
196
196
  - README.md
197
197
  - Rakefile
198
198
  - contentful-scheduler.gemspec
199
- - example/Dockerfile
200
199
  - example/Gemfile
201
200
  - example/Procfile
202
201
  - example/Rakefile
203
202
  - example/config.ru
204
203
  - lib/contentful/scheduler.rb
204
+ - lib/contentful/scheduler/auth.rb
205
205
  - lib/contentful/scheduler/controller.rb
206
206
  - lib/contentful/scheduler/queue.rb
207
207
  - lib/contentful/scheduler/tasks.rb
208
208
  - lib/contentful/scheduler/tasks/publish.rb
209
209
  - lib/contentful/scheduler/tasks/unpublish.rb
210
210
  - lib/contentful/scheduler/version.rb
211
+ - spec/contentful/scheduler/auth_spec.rb
211
212
  - spec/contentful/scheduler/controller_spec.rb
212
213
  - spec/contentful/scheduler/queue_spec.rb
213
214
  - spec/contentful/scheduler/tasks/publish_spec.rb
@@ -239,6 +240,7 @@ signing_key:
239
240
  specification_version: 4
240
241
  summary: Customizable Scheduler for Contentful Entries.
241
242
  test_files:
243
+ - spec/contentful/scheduler/auth_spec.rb
242
244
  - spec/contentful/scheduler/controller_spec.rb
243
245
  - spec/contentful/scheduler/queue_spec.rb
244
246
  - spec/contentful/scheduler/tasks/publish_spec.rb
data/example/Dockerfile DELETED
@@ -1,25 +0,0 @@
1
- FROM ruby:2.5
2
- MAINTAINER Bugs Bunny <bbunny@rubyplus.com>
3
-
4
-
5
-
6
- # Install gems
7
- ENV APP_HOME /app
8
- ENV HOME /root
9
- RUN mkdir $APP_HOME
10
- RUN chmod -R 777 /app
11
- RUN chmod -R 777 /root
12
-
13
-
14
- WORKDIR $APP_HOME
15
- COPY Gemfile* $APP_HOME/
16
- RUN bundle install
17
-
18
- # Upload source
19
- COPY . $APP_HOME
20
-
21
- # Start server
22
- ENV PORT 8080
23
- EXPOSE 8080
24
- USER 1001
25
- CMD ["foreman", "start"]