helios 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +50 -21
- data/README.md +27 -2
- data/helios.gemspec +10 -6
- data/lib/helios.rb +10 -4
- data/lib/helios/backend.rb +29 -22
- data/lib/helios/backend/data.rb +10 -5
- data/lib/helios/backend/in-app-purchase.rb +4 -2
- data/lib/helios/backend/newsstand.rb +97 -0
- data/lib/helios/backend/passbook.rb +8 -2
- data/lib/helios/backend/push-notification.rb +25 -12
- data/lib/helios/commands/console.rb +4 -10
- data/lib/helios/commands/new.rb +0 -1
- data/lib/helios/commands/server.rb +4 -1
- data/lib/helios/frontend.rb +6 -14
- data/lib/helios/frontend/images/helios.svg +33 -0
- data/lib/helios/frontend/javascripts/helios.coffee +39 -3
- data/lib/helios/frontend/javascripts/helios/collections.coffee +10 -2
- data/lib/helios/frontend/javascripts/helios/models.coffee +4 -1
- data/lib/helios/frontend/javascripts/helios/router.coffee +13 -1
- data/lib/helios/frontend/javascripts/helios/views.coffee +82 -8
- data/lib/helios/frontend/javascripts/vendor/jquery/jquery.fileupload-ui.js +807 -0
- data/lib/helios/frontend/javascripts/vendor/jquery/jquery.fileupload.js +1201 -0
- data/lib/helios/frontend/javascripts/vendor/jquery/jquery.ui.widget.js +530 -0
- data/lib/helios/frontend/javascripts/vendor/linkheaders.js +117 -0
- data/lib/helios/frontend/stylesheets/_iphone.sass +1 -1
- data/lib/helios/frontend/stylesheets/screen.sass +2 -6
- data/lib/helios/frontend/templates/{entities.jst.tpl → data/entities.jst.tpl} +0 -0
- data/lib/helios/frontend/templates/{receipts.jst.tpl → in-app-purchase/receipts.jst.tpl} +0 -0
- data/lib/helios/frontend/templates/navigation.jst.tpl +31 -0
- data/lib/helios/frontend/templates/newsstand/issues.jst.tpl +16 -0
- data/lib/helios/frontend/templates/newsstand/new.jst.tpl +28 -0
- data/lib/helios/frontend/templates/{passes.jst.tpl → passbook/passes.jst.tpl} +0 -0
- data/lib/helios/frontend/templates/{compose.jst.tpl → push-notification/compose.jst.tpl} +0 -0
- data/lib/helios/frontend/templates/{devices.jst.tpl → push-notification/devices.jst.tpl} +0 -0
- data/lib/helios/frontend/views/index.haml +4 -28
- data/lib/helios/templates/.env.erb +1 -0
- data/lib/helios/templates/.gitignore +3 -0
- data/lib/helios/version.rb +1 -1
- metadata +86 -20
- data/lib/helios/frontend/stylesheets/_bariol.scss +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 804589d0f2e0ada259f0b9fed0746db10843ef8c
|
4
|
+
data.tar.gz: 05599e5a5f8d21b616dd6ae7e0cfdfd2cf33e34b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12d3ceb7bf25ea1040f3ecb0faffbe2dd433a4733c407cb4f86ccb43db471d623759a678089f10f4f45740ec1dc1d9f3e90b1b07dd393aaae684da4944632053
|
7
|
+
data.tar.gz: 58e382a519b93419ee86cb8a195c80fed29693bbe2ae0f588355dab9e7f22629be19b6fb1f870b45ca711fc72a7355900951a59b593e357aefb1967084ae976f
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
helios (0.2.
|
4
|
+
helios (0.2.2)
|
5
5
|
coffee-script (~> 2.2)
|
6
6
|
commander (~> 4.1)
|
7
7
|
compass (~> 0.12)
|
8
|
+
core_data
|
9
|
+
fog (~> 1.10)
|
8
10
|
foreman (~> 0.63)
|
9
11
|
haml (>= 3.1)
|
12
|
+
houston (~> 0.2)
|
10
13
|
json (~> 1.7)
|
11
14
|
rack-contrib (~> 1.1)
|
12
|
-
rack-core-data (~> 0.3)
|
13
15
|
rack-in-app-purchase (~> 0.1)
|
16
|
+
rack-newsstand (~> 0.1)
|
14
17
|
rack-passbook (~> 0.1)
|
15
18
|
rack-push-notification (~> 0.4)
|
19
|
+
rack-scaffold
|
16
20
|
rails-database-url (~> 1.0)
|
17
21
|
sinatra (~> 1.3)
|
18
|
-
sinatra-assetpack (~> 0.
|
19
|
-
sinatra-backbone (~> 0.1.
|
22
|
+
sinatra-assetpack (~> 0.2.2)
|
23
|
+
sinatra-backbone (~> 0.1.1)
|
20
24
|
sinatra-contrib (~> 1.3)
|
21
25
|
sinatra-param (~> 0.1)
|
22
26
|
sinatra-support (~> 1.2)
|
@@ -29,6 +33,7 @@ GEM
|
|
29
33
|
i18n (= 0.6.1)
|
30
34
|
multi_json (~> 1.0)
|
31
35
|
backports (3.3.0)
|
36
|
+
builder (3.2.0)
|
32
37
|
chunky_png (1.2.8)
|
33
38
|
coffee-script (2.2.0)
|
34
39
|
coffee-script-source
|
@@ -40,55 +45,77 @@ GEM
|
|
40
45
|
chunky_png (~> 1.2)
|
41
46
|
fssm (>= 0.2.7)
|
42
47
|
sass (~> 3.1)
|
48
|
+
core_data (0.1.1)
|
49
|
+
nokogiri (~> 1.4)
|
43
50
|
diff-lcs (1.2.4)
|
44
51
|
dotenv (0.7.0)
|
45
52
|
eventmachine (1.0.3)
|
53
|
+
excon (0.21.0)
|
46
54
|
execjs (1.4.0)
|
47
55
|
multi_json (~> 1.0)
|
56
|
+
fog (1.11.1)
|
57
|
+
builder
|
58
|
+
excon (~> 0.20)
|
59
|
+
formatador (~> 0.2.0)
|
60
|
+
json (~> 1.7)
|
61
|
+
mime-types
|
62
|
+
net-scp (~> 1.1)
|
63
|
+
net-ssh (>= 2.1.3)
|
64
|
+
nokogiri (~> 1.5.0)
|
65
|
+
ruby-hmac
|
48
66
|
foreman (0.63.0)
|
49
67
|
dotenv (>= 0.7)
|
50
68
|
thor (>= 0.13.6)
|
69
|
+
formatador (0.2.4)
|
51
70
|
fssm (0.2.10)
|
52
71
|
haml (4.0.2)
|
53
72
|
tilt
|
54
73
|
highline (1.6.18)
|
55
|
-
houston (0.
|
56
|
-
commander (~> 4.1
|
57
|
-
json
|
74
|
+
houston (0.2.2)
|
75
|
+
commander (~> 4.1)
|
76
|
+
json
|
58
77
|
i18n (0.6.1)
|
59
78
|
jsmin (1.0.1)
|
60
79
|
json (1.7.7)
|
61
|
-
|
80
|
+
mime-types (1.23)
|
81
|
+
multi_json (1.7.3)
|
82
|
+
net-scp (1.1.0)
|
83
|
+
net-ssh (>= 2.6.5)
|
84
|
+
net-ssh (2.6.7)
|
62
85
|
nokogiri (1.5.9)
|
86
|
+
plist (3.1.0)
|
63
87
|
rack (1.5.2)
|
64
88
|
rack-contrib (1.1.0)
|
65
89
|
rack (>= 0.9.1)
|
66
|
-
rack-
|
67
|
-
activesupport (>= 3.0)
|
68
|
-
nokogiri (~> 1.4)
|
90
|
+
rack-in-app-purchase (0.1.0)
|
69
91
|
rack (~> 1.4)
|
70
|
-
rack-contrib (~> 1.1)
|
71
92
|
sequel (~> 3.37)
|
72
93
|
sinatra (~> 1.3)
|
73
|
-
|
74
|
-
rack-
|
94
|
+
venice
|
95
|
+
rack-newsstand (0.1.1)
|
96
|
+
builder (>= 3.0)
|
97
|
+
plist (~> 3.1)
|
75
98
|
rack (~> 1.4)
|
76
99
|
sequel (~> 3.37)
|
77
100
|
sinatra (~> 1.3)
|
78
|
-
venice
|
79
101
|
rack-passbook (0.1.1)
|
80
102
|
rack (~> 1.4)
|
81
103
|
sequel (~> 3.37)
|
82
104
|
sinatra (~> 1.3)
|
83
105
|
rack-protection (1.5.0)
|
84
106
|
rack
|
85
|
-
rack-push-notification (0.4.
|
86
|
-
houston (~> 0.1.1)
|
107
|
+
rack-push-notification (0.4.1)
|
87
108
|
rack (~> 1.4)
|
88
109
|
rack-contrib (~> 1.1)
|
89
110
|
sequel (~> 3.37)
|
90
111
|
sinatra (~> 1.3)
|
91
112
|
sinatra-param (~> 0.1)
|
113
|
+
rack-scaffold (0.0.1)
|
114
|
+
activesupport (>= 3.0)
|
115
|
+
rack (~> 1.4)
|
116
|
+
rack-contrib (~> 1.1)
|
117
|
+
sinatra (~> 1.3)
|
118
|
+
sinatra-param (~> 0.1)
|
92
119
|
rack-test (0.6.2)
|
93
120
|
rack (>= 1.0)
|
94
121
|
rails-database-url (1.0.0)
|
@@ -101,13 +128,15 @@ GEM
|
|
101
128
|
rspec-expectations (2.13.0)
|
102
129
|
diff-lcs (>= 1.1.3, < 2.0)
|
103
130
|
rspec-mocks (2.13.1)
|
104
|
-
|
105
|
-
|
131
|
+
ruby-hmac (0.4.0)
|
132
|
+
sass (3.2.9)
|
133
|
+
sequel (3.47.0)
|
106
134
|
sinatra (1.4.2)
|
107
135
|
rack (~> 1.5, >= 1.5.2)
|
108
136
|
rack-protection (~> 1.4)
|
109
137
|
tilt (~> 1.3, >= 1.3.4)
|
110
|
-
sinatra-assetpack (0.
|
138
|
+
sinatra-assetpack (0.2.2)
|
139
|
+
backports
|
111
140
|
jsmin
|
112
141
|
rack-test
|
113
142
|
sinatra
|
@@ -127,7 +156,7 @@ GEM
|
|
127
156
|
sinatra (>= 1.0)
|
128
157
|
terminal-table (1.4.5)
|
129
158
|
thor (0.18.1)
|
130
|
-
tilt (1.
|
159
|
+
tilt (1.4.1)
|
131
160
|
venice (0.1.0)
|
132
161
|
commander (~> 4.1)
|
133
162
|
json
|
data/README.md
CHANGED
@@ -76,7 +76,7 @@ Bundler.require
|
|
76
76
|
|
77
77
|
run Helios::Application.new do
|
78
78
|
service :data, model: 'path/to/DataModel.xcdatamodel'
|
79
|
-
service :push_notification
|
79
|
+
service :push_notification, apn_certificate: 'path/to/apple_push_notification.pem', apn_environment: 'development'
|
80
80
|
service :in_app_purchase
|
81
81
|
service :passbook
|
82
82
|
end
|
@@ -102,7 +102,7 @@ Helios can be run as Rails middleware by adding this to the configuration block
|
|
102
102
|
```ruby
|
103
103
|
config.middleware.use Helios::Application do
|
104
104
|
service :data, model: 'path/to/DataModel.xcdatamodel'
|
105
|
-
service :push_notification
|
105
|
+
service :push_notification, apn_certificate: 'path/to/apple_push_notification.pem', apn_environment: 'development'
|
106
106
|
service :in_app_purchase
|
107
107
|
service :passbook
|
108
108
|
end
|
@@ -164,6 +164,10 @@ Each entity in the specified data model will have a `Sequel::Model` subclass cre
|
|
164
164
|
<td><tt>DELETE /devices/:token</tt></td>
|
165
165
|
<td>Unregister a device from receiving push notifications</td>
|
166
166
|
</tr>
|
167
|
+
<tr>
|
168
|
+
<td><tt>POST /message</tt></td>
|
169
|
+
<td>Send out a push notification to some devices</td>
|
170
|
+
</tr>
|
167
171
|
</table>
|
168
172
|
|
169
173
|
---
|
@@ -266,6 +270,12 @@ To run Helios in development mode on `localhost`, run the `server` command:
|
|
266
270
|
|
267
271
|
$ helios server
|
268
272
|
|
273
|
+
### Testing Push Notifications
|
274
|
+
|
275
|
+
Once you have registered a device and set up your certificate, try this:
|
276
|
+
|
277
|
+
$ curl -X POST -d 'payload={"aps": {"alert":"Blastoff!"}}' http://localhost:5000/message
|
278
|
+
|
269
279
|
### Running the Helios Console
|
270
280
|
|
271
281
|
You can start an IRB session with the runtime environment of the Helios application with the `console` command:
|
@@ -311,6 +321,21 @@ didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
|
311
321
|
}
|
312
322
|
```
|
313
323
|
|
324
|
+
### Converting Your Push Notification Certificate
|
325
|
+
|
326
|
+
> These instructions come from the [APN on Rails](https://github.com/PRX/apn_on_rails) project.
|
327
|
+
|
328
|
+
Once you have the certificate from Apple for your application, export your key
|
329
|
+
and the apple certificate as p12 files. Here is a quick walkthrough on how to do this:
|
330
|
+
|
331
|
+
1. Click the disclosure arrow next to your certificate in Keychain Access and select the certificate and the key.
|
332
|
+
2. Right click and choose `Export 2 items…`.
|
333
|
+
3. Choose the p12 format from the drop down and name it `cert.p12`.
|
334
|
+
|
335
|
+
Now covert the p12 file to a pem file:
|
336
|
+
|
337
|
+
$ openssl pkcs12 -in cert.p12 -out apple_push_notification.pem -nodes -clcerts
|
338
|
+
|
314
339
|
## Coming Attractions
|
315
340
|
|
316
341
|
There's still a lot to do to make Helios even better. Here are some ideas that are at the top of the list:
|
data/helios.gemspec
CHANGED
@@ -16,27 +16,31 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.add_dependency "commander", "~> 4.1"
|
17
17
|
s.add_dependency "foreman", "~> 0.63"
|
18
18
|
s.add_dependency "rack-contrib", "~> 1.1"
|
19
|
-
s.add_dependency "rack-core-data", "~> 0.3"
|
20
19
|
s.add_dependency "rack-push-notification", "~> 0.4"
|
21
20
|
s.add_dependency "rack-in-app-purchase", "~> 0.1"
|
22
21
|
s.add_dependency "rack-passbook", "~> 0.1"
|
22
|
+
s.add_dependency "rack-newsstand", "~> 0.1"
|
23
|
+
s.add_dependency "rack-scaffold"
|
24
|
+
s.add_dependency "core_data"
|
23
25
|
s.add_dependency "json", "~> 1.7"
|
24
26
|
s.add_dependency "coffee-script", "~> 2.2"
|
25
27
|
s.add_dependency "sinatra", "~> 1.3"
|
26
28
|
s.add_dependency "sinatra-contrib", "~> 1.3"
|
27
|
-
s.add_dependency "sinatra-assetpack", "~> 0.
|
28
|
-
s.add_dependency "sinatra-backbone", "~> 0.1.
|
29
|
+
s.add_dependency "sinatra-assetpack", "~> 0.2.2"
|
30
|
+
s.add_dependency "sinatra-backbone", "~> 0.1.1"
|
29
31
|
s.add_dependency "sinatra-param", "~> 0.1"
|
30
32
|
s.add_dependency "sinatra-support", "~> 1.2"
|
31
33
|
s.add_dependency "haml", ">= 3.1"
|
32
34
|
s.add_dependency "compass", "~> 0.12"
|
33
35
|
s.add_dependency "zurb-foundation", "4.1.2"
|
34
36
|
s.add_dependency "rails-database-url", "~> 1.0"
|
37
|
+
s.add_dependency "fog", "~> 1.10"
|
38
|
+
s.add_dependency "houston", "~> 0.2"
|
35
39
|
|
36
|
-
s.add_development_dependency "rake"
|
37
|
-
s.add_development_dependency "rspec"
|
40
|
+
s.add_development_dependency "rake"
|
41
|
+
s.add_development_dependency "rspec"
|
38
42
|
|
39
|
-
s.files = Dir["./**/*"].reject{|file| file =~ /\.\/(bin|example|log|pkg|script|spec|test|vendor)/} + Dir.glob("./lib/helios/templates", File::FNM_DOTMATCH)
|
43
|
+
s.files = Dir["./**/*"].reject{|file| file =~ /\.\/(bin|example|log|pkg|script|spec|test|vendor)/} + Dir.glob("./lib/helios/templates/*", File::FNM_DOTMATCH)
|
40
44
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
41
45
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
42
46
|
s.require_paths = ["lib"]
|
data/lib/helios.rb
CHANGED
@@ -3,11 +3,17 @@ require 'rack'
|
|
3
3
|
module Helios
|
4
4
|
class Application
|
5
5
|
def initialize(app = nil, options = {}, &block)
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
@app = Rack::Builder.new do
|
7
|
+
map '/admin' do
|
8
|
+
use Rack::Auth::Basic, "Restricted Area" do |username, password|
|
9
|
+
username == (ENV['HELIOS_ADMIN_USERNAME'] || "") and password == (ENV['HELIOS_ADMIN_PASSWORD'] || "")
|
10
|
+
end if ENV['HELIOS_ADMIN_USERNAME'] or ENV['HELIOS_ADMIN_PASSWORD']
|
9
11
|
|
10
|
-
|
12
|
+
run Helios::Frontend.new
|
13
|
+
end
|
14
|
+
|
15
|
+
run Helios::Backend.new(&block)
|
16
|
+
end
|
11
17
|
end
|
12
18
|
|
13
19
|
def call(env)
|
data/lib/helios/backend.rb
CHANGED
@@ -1,22 +1,31 @@
|
|
1
1
|
require 'rack'
|
2
2
|
|
3
3
|
module Helios
|
4
|
-
class Backend < Rack::
|
4
|
+
class Backend < Rack::Builder
|
5
|
+
DEFAULT_PATHS = {
|
6
|
+
data: '/'
|
7
|
+
}
|
8
|
+
|
5
9
|
require 'rails-database-url' if const_defined?(:Rails)
|
6
10
|
|
7
|
-
def initialize(&block)
|
8
|
-
|
11
|
+
def initialize(*args, &block)
|
12
|
+
raise ArgumentError, "Missing block" unless block_given?
|
13
|
+
super(&nil)
|
9
14
|
|
10
|
-
|
11
|
-
service :data, model: Dir['**/*.xcdatamodeld'].first rescue false
|
12
|
-
service :push_notification
|
13
|
-
service :in_app_purchase
|
14
|
-
service :passbook
|
15
|
-
} unless block_given?
|
15
|
+
@services = {}
|
16
16
|
|
17
17
|
instance_eval(&block)
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
+
def call(env)
|
21
|
+
return super(env) unless env["REQUEST_METHOD"] == "OPTIONS" and env["REQUEST_PATH"] == "/"
|
22
|
+
|
23
|
+
links = []
|
24
|
+
@services.each do |path, middleware|
|
25
|
+
links << %{<#{path}>; rel="#{middleware}"}
|
26
|
+
end
|
27
|
+
|
28
|
+
[206, {"Link" => links.join("\n")}, []]
|
20
29
|
end
|
21
30
|
|
22
31
|
private
|
@@ -28,30 +37,28 @@ module Helios
|
|
28
37
|
begin
|
29
38
|
middleware = Helios::Backend.const_get(constantize(identifier))
|
30
39
|
rescue NameError
|
31
|
-
raise LoadError, "Could not find matching service for #{identifier.inspect}. You may need to install an additional gem (such as helios-#{identifier})."
|
40
|
+
raise LoadError, "Could not find matching service for #{identifier.inspect} (Helios::Backend::#{constantize(identifier)}). You may need to install an additional gem (such as helios-#{identifier})."
|
32
41
|
end
|
33
42
|
end
|
34
43
|
|
35
|
-
|
44
|
+
path = "/#{(options.delete(:root) || DEFAULT_PATHS[identifier] || identifier)}".squeeze("/")
|
45
|
+
|
46
|
+
map path do
|
47
|
+
instance_eval(&block) if block_given?
|
48
|
+
run middleware.new(self, options)
|
49
|
+
end
|
36
50
|
|
37
|
-
@services
|
51
|
+
@services[path] = middleware
|
38
52
|
end
|
39
53
|
|
40
54
|
def constantize(identifier)
|
41
55
|
identifier.to_s.split(/([[:alpha:]]*)/).select{|c| /[[:alpha:]]/ === c}.map(&:capitalize).join("")
|
42
56
|
end
|
43
57
|
end
|
44
|
-
|
45
|
-
module Administerable
|
46
|
-
attr_accessor :admin
|
47
|
-
|
48
|
-
def admin?
|
49
|
-
!!@admin
|
50
|
-
end
|
51
|
-
end
|
52
58
|
end
|
53
59
|
|
54
60
|
require 'helios/backend/data'
|
55
|
-
require 'helios/backend/push-notification'
|
56
61
|
require 'helios/backend/in-app-purchase'
|
57
62
|
require 'helios/backend/passbook'
|
63
|
+
require 'helios/backend/push-notification'
|
64
|
+
require 'helios/backend/newsstand'
|
data/lib/helios/backend/data.rb
CHANGED
@@ -1,21 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'core_data'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
require 'rack/scaffold'
|
5
|
+
|
6
|
+
require 'sinatra/base'
|
2
7
|
require 'sinatra/param'
|
3
8
|
|
9
|
+
|
4
10
|
class Helios::Backend::Data < Sinatra::Base
|
5
11
|
helpers Sinatra::Param
|
6
12
|
|
7
13
|
def initialize(app, options = {})
|
8
|
-
super(Rack::
|
14
|
+
super(Rack::Scaffold.new(options))
|
9
15
|
|
10
|
-
@model =
|
16
|
+
@model = CoreData::DataModel.new(options[:model]) rescue nil
|
11
17
|
end
|
12
18
|
|
13
19
|
before do
|
14
20
|
content_type :json
|
15
21
|
end
|
16
22
|
|
17
|
-
options '/' do
|
18
|
-
pass unless self.class < Helios::Administerable
|
23
|
+
options '/resources' do
|
19
24
|
|
20
25
|
links = []
|
21
26
|
@model.entities.each do |entity|
|
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'rack/in-app-purchase'
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
2
4
|
require 'sinatra/param'
|
3
5
|
|
4
6
|
class Helios::Backend::InAppPurchase < Sinatra::Base
|
5
7
|
helpers Sinatra::Param
|
6
8
|
|
7
|
-
def initialize(app, options = {})
|
9
|
+
def initialize(app, options = {}, &block)
|
8
10
|
super(Rack::InAppPurchase.new)
|
9
11
|
end
|
10
|
-
|
12
|
+
|
11
13
|
before do
|
12
14
|
content_type :json
|
13
15
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rack/newsstand'
|
2
|
+
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'sinatra/param'
|
5
|
+
|
6
|
+
require 'fog'
|
7
|
+
|
8
|
+
class Helios::Backend::Newsstand < Sinatra::Base
|
9
|
+
helpers Sinatra::Param
|
10
|
+
|
11
|
+
def initialize(app, options = {}, &block)
|
12
|
+
super(Rack::Newsstand.new)
|
13
|
+
|
14
|
+
@storage = Fog::Storage.new(options[:storage]) if options[:storage]
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
content_type :json
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/issues/?' do
|
22
|
+
pass unless request.accept? 'application/json'
|
23
|
+
|
24
|
+
param :q, String
|
25
|
+
|
26
|
+
issues = Rack::Newsstand::Issue.dataset
|
27
|
+
issues = issues.filter("tsv @@ to_tsquery('english', ?)", "#{params[:q]}:*") if params[:q] and not params[:q].empty?
|
28
|
+
|
29
|
+
if params[:page] or params[:per_page]
|
30
|
+
param :page, Integer, default: 1, min: 1
|
31
|
+
param :per_page, Integer, default: 100, in: (1..100)
|
32
|
+
|
33
|
+
{
|
34
|
+
issues: issues.limit(params[:per_page], (params[:page] - 1) * params[:per_page]).naked.all,
|
35
|
+
page: params[:page],
|
36
|
+
total: issues.count
|
37
|
+
}.to_json
|
38
|
+
else
|
39
|
+
param :limit, Integer, default: 100, in: (1..100)
|
40
|
+
param :offset, Integer, default: 0, min: 0
|
41
|
+
|
42
|
+
{
|
43
|
+
issues: issues.limit(params[:limit], params[:offset]).naked.all
|
44
|
+
}.to_json
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
head '/issues/new?' do
|
49
|
+
status 503 and return unless @storage
|
50
|
+
|
51
|
+
status 204
|
52
|
+
end
|
53
|
+
|
54
|
+
post '/issues/?' do
|
55
|
+
status 503 and return unless @storage
|
56
|
+
|
57
|
+
param :name, String, empty: false
|
58
|
+
param :summary, String
|
59
|
+
|
60
|
+
issue = Rack::Newsstand::Issue.new(params)
|
61
|
+
|
62
|
+
if issue.valid?
|
63
|
+
directory = @storage.directories.create(key: "newsstand-issue-#{issue.name}-#{Time.now.to_i}", public: true)
|
64
|
+
|
65
|
+
covers, assets = {}, []
|
66
|
+
[:covers, :assets].each do |attribute|
|
67
|
+
(params[attribute] || []).each do |f|
|
68
|
+
file = directory.files.create(
|
69
|
+
key: File.basename(f[:filename]),
|
70
|
+
body: File.open(f[:tempfile]),
|
71
|
+
public: true
|
72
|
+
)
|
73
|
+
|
74
|
+
case attribute
|
75
|
+
when :covers
|
76
|
+
covers["SOURCE"] = file.public_url
|
77
|
+
when :assets
|
78
|
+
assets << file.public_url
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
issue.set(cover_urls: covers, asset_urls: assets)
|
84
|
+
|
85
|
+
if issue.save
|
86
|
+
status 201
|
87
|
+
issue.to_json
|
88
|
+
else
|
89
|
+
status 400
|
90
|
+
{errors: issue.errors}.to_json
|
91
|
+
end
|
92
|
+
else
|
93
|
+
status 400
|
94
|
+
{errors: issue.errors}.to_json
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|