contentful-scheduler-custom 1.5.5 → 1.5.7.1.1

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: 488a4c42e0d829618efde8fdaf18953c81bafe63
4
- data.tar.gz: 0c92afbe94d2639d6dd1e9e9618224cdfb1850db
3
+ metadata.gz: db750774a8a2cfe5bc4ed62675d333d2aed6f54e
4
+ data.tar.gz: 0bd0169f942a00076035eeee33847b59cab31967
5
5
  SHA512:
6
- metadata.gz: bf1e2dc8b595901ee953edafd1e58ae965230791e32f0faf9a64aae8fd3451107c63aea1889923ace033381ab9458ca39e21b8ccb3bf88593d83c71e740c7043
7
- data.tar.gz: 6ef9ca2783f080851ef7d122c0cee760f362cea97f4b384bb13407101a2695991fb6624510ab0c552b4286548bc4ab366d3890d3484682a2c74906eb1402d1c7
6
+ metadata.gz: eb7537a86727e84ce6b7a27fdb47642a77533a7306ccbf43e749f9751f016d20df4017ebb053d65b441f44410a91b1ced8b8153e16616ed96534193933d36269
7
+ data.tar.gz: 499937e363723d4df684f7dd95a46d7f0185f02b0cf80e7e2cdaec6651e33c3fccf57c1b471761849adddb6d7cdc7b52d41beffa82aacaa3d183fd76739d5c52
data/.gitignore CHANGED
@@ -9,5 +9,3 @@
9
9
  /tmp/
10
10
  .DS_Store
11
11
  dump.rdb
12
- /.idea/
13
- /example/.rakeTasks
@@ -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
 
@@ -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'
@@ -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
@@ -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
@@ -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)
@@ -25,6 +36,9 @@ module Contentful
25
36
  alias_method :unpublish, :delete
26
37
  alias_method :archive, :delete
27
38
  alias_method :publish, :delete
39
+ alias_method :save, :delete
40
+ alias_method :auto_save, :delete
41
+ alias_method :unarchive, :delete
28
42
  end
29
43
  end
30
44
  end
@@ -15,17 +15,16 @@ module Contentful
15
15
 
16
16
  def update_or_create(webhook)
17
17
  if publishable?(webhook)
18
- success = update_or_create_for_publish(webhook)
18
+ successPublish = update_or_create_for_publish(webhook)
19
19
  updateContentBlocks(webhook, 'publish')
20
- log_event_success(webhook, success, 'publish', 'added to')
20
+ log_event_success(webhook, successPublish, 'publish', 'added to')
21
21
  end
22
22
 
23
23
  if unpublishable?(webhook)
24
- success = update_or_create_for_unpublish(webhook)
24
+ successUnpublish = update_or_create_for_unpublish(webhook)
25
25
  updateContentBlocks(webhook, 'unpublish')
26
- log_event_success(webhook, success, 'unpublish', 'added to')
26
+ log_event_success(webhook, successUnpublish, 'unpublish', 'added to')
27
27
  end
28
-
29
28
  end
30
29
 
31
30
  def update_or_create_for_publish(webhook)
@@ -55,8 +54,8 @@ module Contentful
55
54
  end
56
55
 
57
56
  def remove(webhook)
58
- remove_publish(webhook)
59
57
  remove_unpublish(webhook)
58
+ remove_publish(webhook)
60
59
  end
61
60
 
62
61
  def remove_publish(webhook)
@@ -75,11 +74,87 @@ module Contentful
75
74
  log_event_success(webhook, success, 'publish', 'removed from')
76
75
  end
77
76
 
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')
91
+ end
92
+
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"
96
+ else
97
+ logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
98
+ end
99
+ end
100
+
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)
106
+ end
107
+
108
+ false
109
+ end
110
+
111
+ def unpublishable?(webhook)
112
+ return false unless spaces.key?(webhook.space_id)
113
+
114
+ if webhook_unpublish_field?(webhook)
115
+ return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
116
+ end
117
+
118
+ false
119
+ end
120
+
121
+ def publish_is_future?(webhook)
122
+ publish_date(webhook) > Time.now.utc
123
+ end
124
+
125
+ def unpublish_is_future?(webhook)
126
+ unpublish_date(webhook) > Time.now.utc
127
+ end
128
+
129
+ def in_publish_queue?(webhook)
130
+ Resque.peek(::Contentful::Scheduler::Tasks::Publish, 0, -1).any? do |job|
131
+ job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
132
+ end
133
+ end
134
+
135
+ def in_unpublish_queue?(webhook)
136
+ Resque.peek(::Contentful::Scheduler::Tasks::Unpublish, 0, -1).any? do |job|
137
+ job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
138
+ end
139
+ end
140
+
141
+ def publish_date(webhook)
142
+ date_field = webhook_publish_field(webhook)
143
+ date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
144
+ Chronic.parse(date_field).utc
145
+ end
146
+
147
+ def unpublish_date(webhook)
148
+ date_field = webhook_unpublish_field(webhook)
149
+ date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
150
+ Chronic.parse(date_field).utc
151
+ end
152
+
78
153
  def updateContentBlocks(webhook, type)
79
154
  if isContentBlockAvailable(webhook)
80
155
  webhook.fields['contentBlocks']['fi-FI'].each do |sys|
81
156
  success = Resque.enqueue_at(
82
- publish_date(webhook),
157
+ getPublishOrUnpublishDate(webhook, type),
83
158
  getScheduleType(type),
84
159
  webhook.space_id,
85
160
  sys['sys']['id'],
@@ -94,14 +169,6 @@ module Contentful
94
169
  end
95
170
  end
96
171
 
97
- def getScheduleType(type)
98
- if type == 'unpublish'
99
- return ::Contentful::Scheduler::Tasks::Unpublish
100
- else
101
- return ::Contentful::Scheduler::Tasks::Publish
102
- end
103
- end
104
-
105
172
  def removeContentBlocks(webhook, type)
106
173
  if isContentBlockAvailable(webhook)
107
174
  webhook.fields['contentBlocks']['fi-FI'].each do |sys|
@@ -124,72 +191,20 @@ module Contentful
124
191
  return !webhook.fields['contentBlocks'].nil?
125
192
  end
126
193
 
127
- def publishable?(webhook)
128
- return false unless spaces.key?(webhook.space_id)
129
-
130
- if webhook_publish_field?(webhook)
131
- return !webhook_publish_field(webhook).nil? && publish_is_future?(webhook)
132
- end
133
-
134
- false
135
- end
136
-
137
- def publish_is_future?(webhook)
138
- publish_date(webhook) > Time.now.utc
139
- end
140
-
141
- def in_publish_queue?(webhook)
142
- Resque.peek(::Contentful::Scheduler::Tasks::Publish, 0, -1).any? do |job|
143
- job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
144
- end
145
- end
146
-
147
- def remove_unpublish(webhook)
148
- return unless unpublishable?(webhook)
149
- return unless in_unpublish_queue?(webhook)
150
-
151
- success = Resque.remove_delayed(
152
- ::Contentful::Scheduler::Tasks::Unpublish,
153
- webhook.space_id,
154
- webhook.id,
155
- ::Contentful::Scheduler.config[:management_token]
156
- )
157
-
158
- removeContentBlocks(webhook, 'unpublish')
159
-
160
- log_event_success(webhook, success, 'unpublish', 'removed from')
161
- end
162
-
163
- def in_unpublish_queue?(webhook)
164
- Resque.peek(::Contentful::Scheduler::Tasks::Unpublish, 0, -1).any? do |job|
165
- job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
194
+ def getScheduleType(type)
195
+ if type == 'publish'
196
+ ::Contentful::Scheduler::Tasks::Publish
197
+ else
198
+ ::Contentful::Scheduler::Tasks::Unpublish
166
199
  end
167
200
  end
168
201
 
169
- def unpublish_is_future?(webhook)
170
- unpublish_date(webhook) > Time.now.utc
171
- end
172
-
173
- def unpublishable?(webhook)
174
- return false unless spaces.key?(webhook.space_id)
175
-
176
- if webhook_unpublish_field?(webhook)
177
- return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
202
+ def getPublishOrUnpublishDate(webhook, type)
203
+ if type == 'publish'
204
+ publish_date(webhook)
205
+ else
206
+ unpublish_date(webhook)
178
207
  end
179
-
180
- false
181
- end
182
-
183
- def publish_date(webhook)
184
- date_field = webhook_publish_field(webhook)
185
- date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
186
- Chronic.parse(date_field).utc
187
- end
188
-
189
- def unpublish_date(webhook)
190
- date_field = webhook_unpublish_field(webhook)
191
- date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
192
- Chronic.parse(date_field).utc
193
208
  end
194
209
 
195
210
  def spaces
@@ -212,14 +227,6 @@ module Contentful
212
227
  webhook.fields[spaces[webhook.space_id][:unpublish_field]]
213
228
  end
214
229
 
215
- def log_event_success(webhook, success, event_kind, action)
216
- if success
217
- logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully #{action} the #{event_kind} queue"
218
- else
219
- logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
220
- end
221
- end
222
-
223
230
  private
224
231
 
225
232
  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.5"
3
+ VERSION = "1.5.7.1.1"
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
@@ -260,4 +260,4 @@ describe Contentful::Scheduler::Queue do
260
260
  end
261
261
  end
262
262
  end
263
- 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
@@ -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
@@ -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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful-scheduler-custom
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.5
4
+ version: 1.5.7.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Contentful GmbH (David Litvak Bruno0
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-11 00:00:00.000000000 Z
11
+ date: 2018-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: contentful-webhook-listener
@@ -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
@@ -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"]