contentful-scheduler-custom 1.5.7.1.8 → 1.5.61
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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +2 -2
- data/CHANGELOG.md +4 -15
- data/README.md +71 -97
- data/contentful-scheduler.gemspec +2 -2
- data/example/Dockerfile +25 -0
- data/example/Gemfile +3 -2
- data/example/Procfile +2 -2
- data/example/Rakefile +7 -8
- data/example/config.ru +3 -3
- data/lib/contentful/scheduler/controller.rb +0 -11
- data/lib/contentful/scheduler/queue.rb +92 -97
- data/lib/contentful/scheduler/tasks/publish.rb +1 -1
- data/lib/contentful/scheduler/tasks/unpublish.rb +2 -2
- data/lib/contentful/scheduler/version.rb +1 -1
- data/spec/contentful/scheduler/controller_spec.rb +0 -18
- data/spec/contentful/scheduler/queue_spec.rb +1 -1
- data/spec/contentful/scheduler/tasks/publish_spec.rb +2 -2
- data/spec/contentful/scheduler/tasks/unpublish_spec.rb +5 -5
- data/spec/spec_helper.rb +1 -1
- metadata +7 -9
- data/lib/contentful/scheduler/auth.rb +0 -64
- data/spec/contentful/scheduler/auth_spec.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 769658f7e20d8100d0d242ecbc2750fe9d50fa63
|
4
|
+
data.tar.gz: 83e6f220e154493424b8a9665b88edbf9028b5da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3acd663eef65d4e0636b4e737fe98dcd36e9fba98b5155ee7a3908cf41a76c22705db789b009cef6f25a7cedf6cf3c37bde9ac2866402606c35b94d10e4d59a6
|
7
|
+
data.tar.gz: faa09d1bc36c064a1510c1f23064aa8ffd4ec5b497305ac3170d89234bb2630d12f4ce8d556db278d67ec37c15a3b1b499736206210c9221a04278ff5fe9f4f5
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,25 +2,14 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
-
##
|
6
|
-
|
7
|
-
|
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)
|
5
|
+
## 1.4.0
|
6
|
+
* Contentful Scheduler now supports future publishing for any existing enteries and
|
7
|
+
publishing ContentBlocks first before publishing the page.
|
19
8
|
|
20
9
|
## 0.2.1
|
21
10
|
|
22
11
|
### Fixed
|
23
|
-
*
|
12
|
+
* Fix time parsing.
|
24
13
|
|
25
14
|
## 0.2.0
|
26
15
|
|
data/README.md
CHANGED
@@ -7,18 +7,17 @@ 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.
|
11
11
|
|
12
12
|
## How does it work
|
13
|
-
`contentful-scheduler` provides a web endpoint to receive webhook calls from Contentful
|
14
|
-
|
15
|
-
|
16
|
-
If the value is a time in the future it will schedule the entry for publishing or unpublishing at the specified time.
|
17
|
-
|
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.
|
18
16
|
A background worker based on the popular `resque` gem will then proceed to actually make the publish call
|
19
|
-
against the Content Management API at the due time. For this the Entries you wish to publish
|
20
|
-
customizable Date field, which we advice to call `publishDate
|
21
|
-
|
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.
|
22
21
|
|
23
22
|
You can add multiple spaces to your configuration, making it useful if you have a milti-space setup.
|
24
23
|
|
@@ -31,7 +30,7 @@ You can add multiple spaces to your configuration, making it useful if you have
|
|
31
30
|
Add this line to your application's Gemfile:
|
32
31
|
|
33
32
|
```ruby
|
34
|
-
gem 'contentful-scheduler'
|
33
|
+
gem 'contentful-scheduler-custom'
|
35
34
|
```
|
36
35
|
|
37
36
|
And then execute:
|
@@ -40,7 +39,7 @@ And then execute:
|
|
40
39
|
|
41
40
|
Or install it yourself as:
|
42
41
|
|
43
|
-
$ gem install contentful-scheduler
|
42
|
+
$ gem install contentful-scheduler-custom
|
44
43
|
|
45
44
|
## Usage
|
46
45
|
|
@@ -56,7 +55,7 @@ If you want to roll out your own, you need to follow the next steps:
|
|
56
55
|
```ruby
|
57
56
|
source 'https://rubygems.org'
|
58
57
|
|
59
|
-
gem 'contentful-scheduler', '~>
|
58
|
+
gem 'contentful-scheduler-custom', '~>1.4'
|
60
59
|
gem 'contentful-management', '~> 1.0'
|
61
60
|
gem 'resque', '~> 1.0'
|
62
61
|
gem 'resque-scheduler', '~> 4.0'
|
@@ -91,11 +90,15 @@ config = {
|
|
91
90
|
spaces: {
|
92
91
|
'YOUR_SPACE_ID' => {
|
93
92
|
publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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'
|
99
102
|
}
|
100
103
|
},
|
101
104
|
}
|
@@ -156,114 +159,85 @@ Under the space settings menu choose webhook and add a new webhook pointing to `
|
|
156
159
|
|
157
160
|
Keep in mind that if you modify the defaults, the URL should be changed to the values specified in the configuration.
|
158
161
|
|
159
|
-
##
|
162
|
+
## Running in Heroku
|
160
163
|
|
161
|
-
|
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`.
|
162
166
|
|
163
|
-
|
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.
|
164
168
|
|
165
|
-
|
166
|
-
or through the [CMA](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/webhooks/webhook/create-update-a-webhook/console/ruby).
|
169
|
+
To run the `monitor` process, you'll require to run it from a different application pointing to the same Redis instance.
|
167
170
|
|
168
|
-
|
171
|
+
Make sure to change the `Procfile`'s `web` process to the following:
|
169
172
|
|
170
|
-
|
173
|
+
```
|
174
|
+
web: PORT=$PORT bundle exec env rake contentful:scheduler
|
175
|
+
```
|
171
176
|
|
172
|
-
|
177
|
+
That will allow Heroku to set it's own Port according to their policy.
|
173
178
|
|
174
|
-
|
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
|
-
```
|
179
|
+
The URL for the webhook then will be on port 80, so you should change it to: `http://YOUR_APPLICATION/scheduler`.
|
188
180
|
|
189
|
-
|
190
|
-
it will accept the request and queue your webhook for processing.
|
181
|
+
## Running in Production Mode
|
191
182
|
|
192
|
-
|
183
|
+
After verifying that application is working fine in development mode(run "foreman start" for development mode)
|
193
184
|
|
194
|
-
|
185
|
+
Run the following commands
|
195
186
|
|
196
|
-
|
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.
|
187
|
+
1. sudo foreman export -p5000 --app stp --user username_to_start_from systemd /etc/systemd/system/
|
199
188
|
|
200
|
-
|
189
|
+
Output will be like this:
|
201
190
|
|
202
|
-
|
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
|
203
201
|
|
204
|
-
|
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
|
-
```
|
202
|
+
2. cat /etc/systemd/system/stp-web@.service | head -n 10
|
218
203
|
|
219
|
-
|
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.
|
204
|
+
Output will be like this:
|
222
205
|
|
223
|
-
|
224
|
-
|
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
|
206
|
+
[Unit]
|
207
|
+
PartOf=stp-web.target
|
233
208
|
|
234
|
-
|
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
|
+
...
|
235
216
|
|
236
|
-
return false if token.nil?
|
237
217
|
|
238
|
-
|
239
|
-
end
|
240
|
-
}
|
241
|
-
}
|
242
|
-
}
|
243
|
-
}
|
244
|
-
```
|
218
|
+
3. Start only gunicorn on port 5700:
|
245
219
|
|
246
|
-
|
247
|
-
and assign it to all the applicable spaces in order to reduce the code duplication.
|
220
|
+
systemctl start stp-web@5700.service
|
248
221
|
|
249
|
-
|
222
|
+
4. Start whole target:
|
250
223
|
|
251
|
-
|
252
|
-
`git heroku push master`.
|
224
|
+
systemctl start stp.target
|
253
225
|
|
254
|
-
|
226
|
+
5. Enable whole target (start on OS boot):
|
255
227
|
|
256
|
-
|
228
|
+
systemctl enable stp.target
|
257
229
|
|
258
|
-
|
230
|
+
6. Restarting daemon
|
259
231
|
|
260
|
-
|
261
|
-
|
262
|
-
|
232
|
+
sudo systemctl daemon-reload
|
233
|
+
|
234
|
+
sudo systemctl restart stp.target
|
235
|
+
|
236
|
+
7. Optional
|
263
237
|
|
264
|
-
|
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.
|
265
240
|
|
266
|
-
The URL for the webhook then will be on port 80, so you should change it to: `http://YOUR_APPLICATION/scheduler`.
|
267
241
|
|
268
242
|
## Contributing
|
269
243
|
|
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency "contentful-webhook-listener", "~> 0.2"
|
23
23
|
spec.add_runtime_dependency "contentful-management", "~> 1.8"
|
24
24
|
spec.add_runtime_dependency "resque", "~> 1.27.4"
|
25
|
-
spec.add_runtime_dependency "resque-scheduler", "~> 4.
|
26
|
-
spec.add_runtime_dependency "redis", "~>
|
25
|
+
spec.add_runtime_dependency "resque-scheduler", "~> 4.2.1"
|
26
|
+
spec.add_runtime_dependency "redis", "~> 3.0"
|
27
27
|
spec.add_runtime_dependency "chronic", "~> 0.10"
|
28
28
|
|
29
29
|
spec.add_development_dependency "bundler", "~> 1.10"
|
data/example/Dockerfile
ADDED
@@ -0,0 +1,25 @@
|
|
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"]
|
data/example/Gemfile
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'contentful-scheduler-custom', '~>
|
3
|
+
gem 'contentful-scheduler-custom', '~>1.4'
|
4
4
|
gem 'contentful-management', '~> 1.0'
|
5
5
|
gem 'resque', '~> 1.0'
|
6
|
-
gem 'resque-scheduler', '
|
6
|
+
gem 'resque-scheduler', '4.2.1'
|
7
7
|
gem 'rake'
|
8
|
+
gem 'foreman', '~> 0.84.0'
|
data/example/Procfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
web:
|
1
|
+
web: PORT=$PORT bundle exec env 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,23 +1,22 @@
|
|
1
1
|
require 'contentful/scheduler'
|
2
|
-
require 'logger' # Optional
|
3
2
|
|
4
3
|
$stdout.sync = true
|
5
4
|
|
6
5
|
config = {
|
7
6
|
logger: Logger.new(STDOUT), # Defaults to NullLogger
|
8
|
-
port:
|
7
|
+
port: 8080, # Defaults to 8081
|
9
8
|
endpoint: '/scheduler', # Defaults to /scheduler
|
10
9
|
redis: {
|
11
|
-
host: '
|
12
|
-
port: '
|
13
|
-
password: '
|
10
|
+
host: 'scheduler-redis-db',
|
11
|
+
port: '6379',
|
12
|
+
password: 'password'
|
14
13
|
},
|
15
14
|
spaces: {
|
16
|
-
'
|
15
|
+
'qbra4qai2ti2' => {
|
17
16
|
publish_field: 'publishDate', # It specifies the field ID for your Publish Date in your Content Type
|
18
|
-
management_token: '
|
17
|
+
management_token: 'CFPAT-45f0c4258aa9b32e8a8b6ccebf64136386b31f3ec435cc17f540368d5416de02'
|
19
18
|
}
|
20
|
-
}
|
19
|
+
},
|
21
20
|
}
|
22
21
|
|
23
22
|
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: '
|
7
|
-
port: '
|
8
|
-
password: '
|
6
|
+
host: 'scheduler-redis-db',
|
7
|
+
port: '6379',
|
8
|
+
password: 'password'
|
9
9
|
}
|
10
10
|
Resque.redis = config
|
11
11
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'contentful/webhook/listener'
|
2
|
-
require_relative 'auth'
|
3
2
|
require_relative 'queue'
|
4
3
|
|
5
4
|
module Contentful
|
@@ -8,11 +7,6 @@ module Contentful
|
|
8
7
|
def create
|
9
8
|
return unless webhook.entry?
|
10
9
|
|
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
|
-
|
16
10
|
logger.info "Queueing - Space: #{webhook.space_id} - Entry: #{webhook.id}"
|
17
11
|
|
18
12
|
Queue.instance(logger).update_or_create(webhook)
|
@@ -24,11 +18,6 @@ module Contentful
|
|
24
18
|
def delete
|
25
19
|
return unless webhook.entry?
|
26
20
|
|
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
|
-
|
32
21
|
logger.info "Unqueueing - Space: #{webhook.space_id} - Entry: #{webhook.id}"
|
33
22
|
|
34
23
|
Queue.instance(logger).remove(webhook)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require_relative "tasks"
|
2
1
|
require 'chronic'
|
3
2
|
require 'contentful/webhook/listener'
|
3
|
+
require_relative "tasks"
|
4
4
|
|
5
5
|
module Contentful
|
6
6
|
module Scheduler
|
@@ -15,16 +15,17 @@ module Contentful
|
|
15
15
|
|
16
16
|
def update_or_create(webhook)
|
17
17
|
if publishable?(webhook)
|
18
|
-
|
18
|
+
success = update_or_create_for_publish(webhook)
|
19
19
|
updateContentBlocks(webhook, 'publish')
|
20
|
-
log_event_success(webhook,
|
20
|
+
log_event_success(webhook, success, 'publish', 'added to')
|
21
21
|
end
|
22
22
|
|
23
23
|
if unpublishable?(webhook)
|
24
|
-
|
24
|
+
success = update_or_create_for_unpublish(webhook)
|
25
25
|
updateContentBlocks(webhook, 'unpublish')
|
26
|
-
log_event_success(webhook,
|
26
|
+
log_event_success(webhook, success, 'unpublish', 'added to')
|
27
27
|
end
|
28
|
+
|
28
29
|
end
|
29
30
|
|
30
31
|
def update_or_create_for_publish(webhook)
|
@@ -74,45 +75,60 @@ module Contentful
|
|
74
75
|
log_event_success(webhook, success, 'publish', 'removed from')
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
78
|
+
def updateContentBlocks(webhook, type)
|
79
|
+
if isContentBlockAvailable(webhook)
|
80
|
+
webhook.fields['contentBlocks']['fi-FI'].each do |sys|
|
81
|
+
success = Resque.enqueue_at(
|
82
|
+
publish_date(webhook),
|
83
|
+
getScheduleType(type),
|
84
|
+
webhook.space_id,
|
85
|
+
sys['sys']['id'],
|
86
|
+
::Contentful::Scheduler.config[:spaces][webhook.space_id][:management_token]
|
87
|
+
)
|
88
|
+
if success
|
89
|
+
logger.info "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully added to " + type + " queue"
|
90
|
+
else
|
91
|
+
logger.warn "Webhook Content block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be added to " + type + " queue"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
91
95
|
end
|
92
96
|
|
93
|
-
def
|
94
|
-
if
|
95
|
-
|
97
|
+
def getScheduleType(type)
|
98
|
+
if type == 'unpublish'
|
99
|
+
return ::Contentful::Scheduler::Tasks::Unpublish
|
96
100
|
else
|
97
|
-
|
101
|
+
return ::Contentful::Scheduler::Tasks::Publish
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
105
|
+
def removeContentBlocks(webhook, type)
|
106
|
+
if isContentBlockAvailable(webhook)
|
107
|
+
webhook.fields['contentBlocks']['fi-FI'].each do |sys|
|
108
|
+
success = Resque.remove_delayed(
|
109
|
+
getScheduleType(type),
|
110
|
+
webhook.space_id,
|
111
|
+
sys['sys']['id'],
|
112
|
+
::Contentful::Scheduler.config[:management_token]
|
113
|
+
)
|
114
|
+
if success
|
115
|
+
logger.info "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} successfully removed from " + type + " queue"
|
116
|
+
else
|
117
|
+
logger.warn "Webhook Content Block {id: #{sys['sys']['id']}, space_id: #{webhook.space_id}} couldn't be removed from " + type + " queue"
|
118
|
+
end
|
119
|
+
end
|
106
120
|
end
|
121
|
+
end
|
107
122
|
|
108
|
-
|
123
|
+
def isContentBlockAvailable(webhook)
|
124
|
+
return !webhook.fields['contentBlocks'].nil?
|
109
125
|
end
|
110
126
|
|
111
|
-
def
|
127
|
+
def publishable?(webhook)
|
112
128
|
return false unless spaces.key?(webhook.space_id)
|
113
129
|
|
114
|
-
if
|
115
|
-
return !
|
130
|
+
if webhook_publish_field?(webhook)
|
131
|
+
return !webhook_publish_field(webhook).nil? && publish_is_future?(webhook)
|
116
132
|
end
|
117
133
|
|
118
134
|
false
|
@@ -122,22 +138,52 @@ module Contentful
|
|
122
138
|
publish_date(webhook) > Time.now.utc
|
123
139
|
end
|
124
140
|
|
125
|
-
def unpublish_is_future?(webhook)
|
126
|
-
unpublish_date(webhook) > Time.now.utc
|
127
|
-
end
|
128
|
-
|
129
141
|
def in_publish_queue?(webhook)
|
130
142
|
Resque.peek(::Contentful::Scheduler::Tasks::Publish, 0, -1).any? do |job|
|
131
143
|
job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
|
132
144
|
end
|
133
145
|
end
|
134
146
|
|
147
|
+
def remove_unpublish(webhook)
|
148
|
+
logger.info "In unpublish remove block" + unpublishable?(webhook) + in_unpublish_queue?(webhook)
|
149
|
+
return unless unpublishable?(webhook)
|
150
|
+
return unless in_unpublish_queue?(webhook)
|
151
|
+
|
152
|
+
|
153
|
+
success = Resque.remove_delayed(
|
154
|
+
::Contentful::Scheduler::Tasks::Unpublish,
|
155
|
+
webhook.space_id,
|
156
|
+
webhook.id,
|
157
|
+
::Contentful::Scheduler.config[:management_token]
|
158
|
+
)
|
159
|
+
|
160
|
+
logger.info "before unpublish content block remove block"
|
161
|
+
|
162
|
+
removeContentBlocks(webhook, 'unpublish')
|
163
|
+
|
164
|
+
log_event_success(webhook, success, 'unpublish', 'removed from')
|
165
|
+
end
|
166
|
+
|
135
167
|
def in_unpublish_queue?(webhook)
|
136
168
|
Resque.peek(::Contentful::Scheduler::Tasks::Unpublish, 0, -1).any? do |job|
|
137
169
|
job['args'][0] == webhook.space_id && job['args'][1] == webhook.id
|
138
170
|
end
|
139
171
|
end
|
140
172
|
|
173
|
+
def unpublish_is_future?(webhook)
|
174
|
+
unpublish_date(webhook) > Time.now.utc
|
175
|
+
end
|
176
|
+
|
177
|
+
def unpublishable?(webhook)
|
178
|
+
return false unless spaces.key?(webhook.space_id)
|
179
|
+
|
180
|
+
if webhook_unpublish_field?(webhook)
|
181
|
+
return !webhook_unpublish_field(webhook).nil? && unpublish_is_future?(webhook)
|
182
|
+
end
|
183
|
+
|
184
|
+
false
|
185
|
+
end
|
186
|
+
|
141
187
|
def publish_date(webhook)
|
142
188
|
date_field = webhook_publish_field(webhook)
|
143
189
|
date_field = date_field[date_field.keys[0]] if date_field.is_a? Hash
|
@@ -150,75 +196,16 @@ module Contentful
|
|
150
196
|
Chronic.parse(date_field).utc
|
151
197
|
end
|
152
198
|
|
153
|
-
def updateContentBlocks(webhook, type)
|
154
|
-
if isContentBlockAvailable(webhook, type)
|
155
|
-
webhook.fields['contentBlocks']['fi-FI'].each do |sys|
|
156
|
-
success = Resque.enqueue_at(
|
157
|
-
getPublishOrUnpublishDate(webhook, type),
|
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, type)
|
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, type)
|
191
|
-
logger.info "Content type is ==>> #{ type }"
|
192
|
-
logger.info "Content Fields are ===>>> #{webhook.fields['contentBlocks']}"
|
193
|
-
return !webhook.fields['contentBlocks'].nil?
|
194
|
-
end
|
195
|
-
|
196
|
-
def getScheduleType(type)
|
197
|
-
if type == 'publish'
|
198
|
-
::Contentful::Scheduler::Tasks::Publish
|
199
|
-
else
|
200
|
-
::Contentful::Scheduler::Tasks::Unpublish
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def getPublishOrUnpublishDate(webhook, type)
|
205
|
-
if type == 'publish'
|
206
|
-
publish_date(webhook)
|
207
|
-
else
|
208
|
-
unpublish_date(webhook)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
199
|
def spaces
|
213
200
|
config[:spaces]
|
214
201
|
end
|
215
202
|
|
216
203
|
def webhook_publish_field?(webhook)
|
217
|
-
webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:publish_field])
|
204
|
+
webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:publish_field])
|
218
205
|
end
|
219
206
|
|
220
207
|
def webhook_unpublish_field?(webhook)
|
221
|
-
webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:unpublish_field])
|
208
|
+
webhook.fields.key?(spaces.fetch(webhook.space_id, {})[:unpublish_field])
|
222
209
|
end
|
223
210
|
|
224
211
|
def webhook_publish_field(webhook)
|
@@ -229,6 +216,14 @@ module Contentful
|
|
229
216
|
webhook.fields[spaces[webhook.space_id][:unpublish_field]]
|
230
217
|
end
|
231
218
|
|
219
|
+
def log_event_success(webhook, success, event_kind, action)
|
220
|
+
if success
|
221
|
+
logger.info "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} successfully #{action} the #{event_kind} queue"
|
222
|
+
else
|
223
|
+
logger.warn "Webhook {id: #{webhook.id}, space_id: #{webhook.space_id}} couldn't be #{action} the #{event_kind} queue"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
232
227
|
private
|
233
228
|
|
234
229
|
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
|
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
|
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
|
@@ -9,10 +9,6 @@ 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
|
-
|
16
12
|
describe 'events' do
|
17
13
|
[:create, :save, :auto_save, :unarchive].each do |event|
|
18
14
|
it "creates or updates webhook metadata in publish queue on #{event}" do
|
@@ -46,19 +42,5 @@ describe Contentful::Scheduler::Controller do
|
|
46
42
|
end
|
47
43
|
end
|
48
44
|
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
|
63
45
|
end
|
64
46
|
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
|
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
|
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.config
|
24
|
+
::Contentful::Scheduler.class_variable_set(:@@config, {management_token: 'foobar'})
|
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
|
-
'
|
30
|
+
'foobar',
|
31
31
|
raise_errors: true,
|
32
|
-
application_name: 'contentful
|
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[:
|
39
|
+
described_class.perform('foo', 'bar', ::Contentful::Scheduler.config[:management_token])
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
data/spec/spec_helper.rb
CHANGED
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.
|
4
|
+
version: 1.5.61
|
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-
|
11
|
+
date: 2018-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: contentful-webhook-listener
|
@@ -58,28 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.
|
61
|
+
version: 4.2.1
|
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.
|
68
|
+
version: 4.2.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: redis
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: '3.0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: '3.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: chronic
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,19 +196,18 @@ files:
|
|
196
196
|
- README.md
|
197
197
|
- Rakefile
|
198
198
|
- contentful-scheduler.gemspec
|
199
|
+
- example/Dockerfile
|
199
200
|
- example/Gemfile
|
200
201
|
- example/Procfile
|
201
202
|
- example/Rakefile
|
202
203
|
- example/config.ru
|
203
204
|
- 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
|
212
211
|
- spec/contentful/scheduler/controller_spec.rb
|
213
212
|
- spec/contentful/scheduler/queue_spec.rb
|
214
213
|
- spec/contentful/scheduler/tasks/publish_spec.rb
|
@@ -240,7 +239,6 @@ signing_key:
|
|
240
239
|
specification_version: 4
|
241
240
|
summary: Customizable Scheduler for Contentful Entries.
|
242
241
|
test_files:
|
243
|
-
- spec/contentful/scheduler/auth_spec.rb
|
244
242
|
- spec/contentful/scheduler/controller_spec.rb
|
245
243
|
- spec/contentful/scheduler/queue_spec.rb
|
246
244
|
- spec/contentful/scheduler/tasks/publish_spec.rb
|
@@ -1,64 +0,0 @@
|
|
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,67 +0,0 @@
|
|
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
|