contentful-scheduler-custom 1.5.5 → 1.5.7.1.1

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
  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"]