ass 0.0.2 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.md +83 -15
  2. data/VERSION +1 -1
  3. data/ass.yml +1 -6
  4. data/lib/ass.rb +71 -42
  5. metadata +53 -5
data/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  ass
2
2
  =======
3
- Apple Service Server written with Sinatra and Sequel(Sqlite3) with apple push notification and in app purchase support.
3
+ ####Apple Service Server was written with Ruby/Sinatra and Sequel(Sqlite3), it provides push notification and in app purchase service.####
4
4
 
5
5
  Feature:
6
6
  =======
7
7
 
8
- 1. rubygem, simple to install.
9
- 2. provide pem file is the only requirement.
10
- 3. no need to setup database, using sqlite3.
8
+ 1. 'ass' is a rubygem, simple to install.
9
+ 2. only need to provide pem file.
10
+ 3. no need to setup database(using sqlite3).
11
11
  4. provide default config file(ass.yml) with default value.
12
12
 
13
- Requirement
13
+ Sqlite3 Installation
14
14
  =======
15
15
 
16
- Sqlite3
17
- -------
18
-
19
16
  CentOS/Redhat:
20
17
 
21
18
  $ yum install sqlite3
@@ -31,8 +28,8 @@ FreeBSD:
31
28
 
32
29
  Mac:
33
30
 
34
- $ brew install sqlite3 # Homebrew
35
- $ port install sqlite3 # Macport
31
+ $ brew install sqlite # Homebrew
32
+ $ port install sqlite # Macport
36
33
 
37
34
  Installation
38
35
  =======
@@ -41,16 +38,87 @@ Installation
41
38
 
42
39
  Usage
43
40
  =======
44
- 1. under the current directory, provide single pem file combined with certificate and key, HOWTO ([Check this link](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12))
45
41
 
46
- 2. edit ass.yml. (when you run ass first time, it will generate this file) ([Check this link](https://raw.github.com/eiffelqiu/ass/master/ass.yml))
42
+ Prepare pem file:
43
+
44
+ under the current directory, provide single pem file combined with certificate and key(name pattern: appid_mode.pem), HOWTO ([Check this link](http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12))
45
+
46
+ cert.pem:
47
+ openssl x509 -in aps_development.cer -inform der -out cert.pem
48
+
49
+ key.pem:
50
+ $ openssl pkcs12 -nocerts -in key.p12 -out key.pem
51
+ $ Enter Import Password:
52
+ $ MAC verified OK
53
+ $ Enter PEM pass phrase:
54
+ $ Verifying - Enter PEM pass phrase:
55
+
56
+ Development Profile:
57
+ cat cert.pem key.pem > appid_development.pem
58
+
59
+ Distribution Profile:
60
+ cat cert.pem key.pem > appid_production.pem
47
61
 
48
- 3. provide a cron script under current directory, default named "cron" according to ass.yml
49
62
 
50
- 4. start ass server, default port is 4567(sinatra's default port)
63
+ * start ass server, default port is 4567 (sinatra's default port)
51
64
 
52
65
  ![ass usage](https://raw.github.com/eiffelqiu/ass/master/doc/capture1.png)
53
66
 
67
+ Configuration (ass.yml)
68
+ =======
69
+
70
+ when you run 'ass' first time, it will generate 'ass.yml' config file under current directory. ([Check this link](https://raw.github.com/eiffelqiu/ass/master/ass.yml))
71
+
72
+ port: 4567 ## ASS server port, default is sinatra's port number: 4567
73
+ mode: development ## 'development' or 'production' mode, you should provide pem file ({appid}_{mode}.pem) accordingly(such as, app1_development.pem, app1_production.pem).
74
+ cron: cron ## cron job file name, ASS server will generate a demo 'cron' file for demostration only under current directory.
75
+ timer: 0 # how often you run the cron job, unit: minute. when set with 0, means no cron job execute.
76
+ apps:
77
+ - app1 ## appid you want to supprt APNS, ASS Server can give push notification support for many iOS apps, just list the appid here.
78
+
79
+
80
+ FAQ:
81
+ =======
82
+
83
+ 1. How to register notification? (Client Side)
84
+ -------
85
+
86
+ In AppDelegate file, add methods below to register device token
87
+
88
+ - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
89
+ {
90
+ NSString * tokenAsString = [[[deviceToken description]
91
+ stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]
92
+ stringByReplacingOccurrencesOfString:@" " withString:@""];
93
+ NSString *urlAsString = [NSString stringWithFormat:@"http://serverIP:4567/v1/apps/app1/%@", token];
94
+ NSURL *url = [NSURL URLWithString:urlAsString];
95
+ NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
96
+ [urlRequest setTimeoutInterval:30.0f];
97
+ [urlRequest setHTTPMethod:@"GET"];
98
+ NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
99
+ [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:nil];
100
+ }
101
+
102
+ - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
103
+ {
104
+ NSLog(@"Failed to get token, error: %@", error);
105
+ }
106
+
107
+ 2. How to send push notification? (Server Side)
108
+ -------
109
+
110
+ run **curl** command to send push notification message, whatever shell.
111
+
112
+ $ curl http://localhost:4567/v1/apps/app1/push/{message}/{pid}
113
+
114
+ Note:
115
+
116
+ param1 (message): push notification message you want to send, remember the message should be html escaped
117
+
118
+ param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest
119
+
120
+
121
+
54
122
  Contributing to ass
55
123
  =======
56
124
 
@@ -65,5 +133,5 @@ Contributing to ass
65
133
  Copyright
66
134
  =======
67
135
 
68
- Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for further details.
136
+ #####Copyright (c) 2012 Eiffel Qiu. See LICENSE.txt for further details.#####
69
137
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.9
data/ass.yml CHANGED
@@ -1,11 +1,6 @@
1
1
  port: 4567
2
2
  mode: development
3
3
  cron: cron
4
- timer: 0 # minute
5
- development:
6
- - certificate : ck_dev.pem
7
- production:
8
- - certificate : ck_prod.pem
4
+ timer: 0
9
5
  apps:
10
6
  - app1
11
- - app2
data/lib/ass.rb CHANGED
@@ -15,20 +15,20 @@ require 'yaml'
15
15
  ############################################################
16
16
  ## Initilization Setup
17
17
  ############################################################
18
- lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
19
- root_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
20
- unless $LOAD_PATH.include?(lib_dir)
21
- $LOAD_PATH << lib_dir
18
+ LIBDIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
19
+ ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
20
+ unless $LOAD_PATH.include?(LIBDIR)
21
+ $LOAD_PATH << LIBDIR
22
22
  end
23
23
 
24
24
  unless File.exist?("#{Dir.pwd}/ass.yml") then
25
25
  puts 'create config file: ass.yml'
26
- system "cp #{root_dir}/ass.yml #{Dir.pwd}/ass.yml"
26
+ system "cp #{ROOTDIR}/ass.yml #{Dir.pwd}/ass.yml"
27
27
  end
28
28
 
29
29
  unless File.exist?("#{Dir.pwd}/cron") then
30
30
  puts "create a demo 'cron' script"
31
- system "cp #{root_dir}/cron #{Dir.pwd}/cron"
31
+ system "cp #{ROOTDIR}/cron #{Dir.pwd}/cron"
32
32
  end
33
33
 
34
34
  ############################################################
@@ -36,21 +36,37 @@ end
36
36
  ############################################################
37
37
  env = ENV['SINATRA_ENV'] || "development"
38
38
  config = YAML.load_file("#{Dir.pwd}/ass.yml")
39
- $timer = config['timer'] || 1
39
+ $timer = "#{config['timer']}".to_i
40
40
  $cron = config['cron'] || 'cron'
41
41
  $port = config['port'] || 4567
42
42
  $mode = config['mode'] || env
43
- $certificate = config["#{$mode}"][0]['certificate'] || 'ck.pem'
44
- ROOTDIR = File.expand_path(File.join(File.dirname(__FILE__), '..'))
45
- VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
43
+ $VERSION = File.open("#{ROOTDIR}/VERSION", "rb").read
46
44
  $apps = config['apps'] || []
47
45
 
48
46
  ############################################################
49
47
  ## Certificate Key Setup
50
48
  ############################################################
51
49
 
52
- unless File.exist?("#{Dir.pwd}/#{$certificate}") then
53
- puts "1: please provide certificate key pem file under current directory"
50
+ $certkey = {}
51
+ def check_cert
52
+ $apps.each { |app|
53
+ unless File.exist?("#{Dir.pwd}/#{app}_#{$mode}.pem") then
54
+ puts "Please provide #{app}_#{$mode}.pem under '#{Dir.pwd}/' directory"
55
+ return false;
56
+ else
57
+ puts "'#{app}'s #{$mode} PEM: (#{app}_#{$mode}.pem)"
58
+ certfile = File.read("#{Dir.pwd}/#{app}_#{$mode}.pem")
59
+ openSSLContext = OpenSSL::SSL::SSLContext.new
60
+ openSSLContext.cert = OpenSSL::X509::Certificate.new(certfile)
61
+ openSSLContext.key = OpenSSL::PKey::RSA.new(certfile)
62
+ $certkey["#{app}"] = openSSLContext
63
+ end
64
+ }
65
+ return true
66
+ end
67
+
68
+ unless check_cert then
69
+ puts "1: please provide certificate key pem file under current directory, name should be: appid_dev.pem for development and appid_prod.pem for production"
54
70
  puts "2: edit your ass.yml under current directory"
55
71
  puts "3: run ass"
56
72
  puts "4: iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:"
@@ -61,91 +77,103 @@ unless File.exist?("#{Dir.pwd}/#{$certificate}") then
61
77
  exit
62
78
  else
63
79
  puts "*"*80
64
- puts "Simple Push Notification Server is Running (#{VERSION}) ..."
80
+ puts "Apple Service Server(#{$VERSION}) is Running ..."
81
+ puts "Push Notification Service: Enabled"
65
82
  puts "Mode: #{$mode}"
66
83
  puts "Port: #{$port}"
67
- puts "Certificate File: '#{Dir.pwd}/#{$certificate}'"
68
- puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".squeeze.strip == "0"
84
+ puts "Cron Job: '#{Dir.pwd}/#{$cron}' script is running every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'} " unless "#{$timer}".to_i == 0
69
85
  puts "*"*80
70
86
  end
71
87
 
72
- $cert = File.read("#{Dir.pwd}/#{$certificate}")
73
- $openSSLContext = OpenSSL::SSL::SSLContext.new
74
- $openSSLContext.cert = OpenSSL::X509::Certificate.new($cert)
75
- $openSSLContext.key = OpenSSL::PKey::RSA.new($cert)
76
-
77
88
  ############################################################
78
89
  ## Sequel Database Setup
79
90
  ############################################################
80
91
 
81
- DB = nil;
82
-
83
- unless File.exist?("#{Dir.pwd}/push.db") then
84
- DB = Sequel.connect("sqlite://#{Dir.pwd}/push.db")
92
+ unless File.exist?("#{Dir.pwd}/ass.db") then
93
+ $DB = Sequel.connect("sqlite://#{Dir.pwd}/ass.db")
85
94
 
86
- DB.create_table :tokens do
95
+ $DB.create_table :tokens do
87
96
  primary_key :id
88
- String :app, :unique => true, :null => false
97
+ String :app, :unique => false, :null => false
89
98
  String :token, :unique => true, :null => false, :size => 100
90
99
  index [:app, :token]
91
100
  end
92
101
 
93
- DB.create_table :pushes do
102
+ $DB.create_table :pushes do
94
103
  primary_key :id
95
104
  String :pid, :unique => true, :null => false, :size => 100
96
105
  index :pid
97
106
  end
98
107
  else
99
- DB = Sequel.connect("sqlite://#{Dir.pwd}/push.db")
108
+ $DB = Sequel.connect("sqlite://#{Dir.pwd}/ass.db")
100
109
  end
101
110
 
102
- Token = DB[:tokens]
103
- Push = DB[:pushes]
111
+ Token = $DB[:tokens]
112
+ Push = $DB[:pushes]
104
113
 
105
114
  ############################################################
106
115
  ## Timer Job Setup
107
116
  ############################################################
108
117
  scheduler = Rufus::Scheduler.start_new
109
118
 
110
- unless "#{$timer}".squeeze.strip == "0"
119
+ unless $timer == 0 then
111
120
  scheduler.every "#{$timer}m" do
112
121
  puts "running job: '#{Dir.pwd}/#{$cron}' every #{$timer} #{($timer == 1) ? 'minute' : 'minutes'}"
113
122
  system "./#{$cron}"
114
123
  end
115
124
  else
125
+ puts "1: How to register notification? (Client Side)"
116
126
  puts
117
- puts "*"*80
118
- puts "How to register notification?"
119
- puts
120
- puts "iOS Client: in AppDelegate file, didRegisterForRemoteNotificationsWithDeviceToken method should access url below:"
127
+ puts "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:"
121
128
  $apps.each { |app|
122
129
  puts "'#{app}'s registration url: http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken"
123
130
  }
124
131
  puts
125
- puts "How to send push notification?"
132
+ puts "2: How to send push notification? (Server Side)"
126
133
  puts
127
134
  $apps.each { |app|
128
135
  puts "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}"
129
136
  }
130
137
  puts
131
138
  puts "Note:"
132
- puts "message: notification message you want to send, remember the message should be html escaped"
133
- puts "pid: unique id that you mark the message, for example current timestamp"
139
+ puts "param1 (message): push notification message you want to send, remember the message should be html escaped"
140
+ puts "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest"
134
141
  puts
135
142
  puts "*"*80
136
- puts
137
143
  end
138
144
 
139
145
  ############################################################
140
- ## Simple Push Notification Server based on Sinatra
146
+ ## Apple Service Server based on Sinatra
141
147
  ############################################################
142
148
 
143
149
  class App < Sinatra::Base
144
150
 
145
151
  set :port, "#{$port}".to_i
152
+
153
+ if "#{$mode}".strip == 'development' then
154
+ set :show_exceptions, true
155
+ set :dump_errors, true
156
+ else
157
+ set :show_exceptions, false
158
+ set :dump_errors, false
159
+ end
146
160
 
147
161
  get '/' do
148
- puts "Simple Push Notification Server"
162
+ o = "Apple Service Server #{$VERSION} <br/><br/>" +
163
+ "author: Eiffel(Q) <br/>email: eiffelqiu@gmail.com<br/><br/>"
164
+ o += "1: How to register notification? (Client Side)<br/><br/>"
165
+ o += "In AppDelegate file, inside didRegisterForRemoteNotificationsWithDeviceToken method access url below to register device token:<br/><br/>"
166
+ $apps.each { |app|
167
+ o += "'#{app}': http://serverIP:#{$port}/v1/apps/#{app}/DeviceToken<br/>"
168
+ }
169
+ o += "<br/>2: How to send push notification? (Server Side)<br/><br/>"
170
+ $apps.each { |app|
171
+ o += "curl http://localhost:#{$port}/v1/apps/#{app}/push/{message}/{pid}<br/>"
172
+ }
173
+ o += "<br/>Note:<br/>"
174
+ o += "param1 (message): push notification message you want to send, remember the message should be html escaped<br/>"
175
+ o += "param2 (pid ): unique string to mark the message, for example current timestamp or md5/sha1 digest<br/>"
176
+ o
149
177
  end
150
178
 
151
179
  $apps.each { |app|
@@ -170,6 +198,7 @@ class App < Sinatra::Base
170
198
  @exist = Push.first(:pid => pid)
171
199
 
172
200
  unless @exist
201
+ openSSLContext = $certkey["#{app}"]
173
202
  # Connect to port 2195 on the server.
174
203
  sock = nil
175
204
  if $mode == 'production' then
@@ -178,7 +207,7 @@ class App < Sinatra::Base
178
207
  sock = TCPSocket.new('gateway.sandbox.push.apple.com', 2195)
179
208
  end
180
209
  # do our SSL handshaking
181
- sslSocket = OpenSSL::SSL::SSLSocket.new(sock, $openSSLContext)
210
+ sslSocket = OpenSSL::SSL::SSLSocket.new(sock, openSSLContext)
182
211
  sslSocket.connect
183
212
  #Push.create( :pid => pid )
184
213
  Push.insert(:pid => pid)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-12 00:00:00.000000000 Z
12
+ date: 2012-09-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sqlite3
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thin
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: sinatra
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -171,6 +187,38 @@ dependencies:
171
187
  - - ~>
172
188
  - !ruby/object:Gem::Version
173
189
  version: 1.8.4
190
+ - !ruby/object:Gem::Dependency
191
+ name: sqlite3
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ type: :runtime
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: thin
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :runtime
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
174
222
  - !ruby/object:Gem::Dependency
175
223
  name: sinatra
176
224
  requirement: !ruby/object:Gem::Requirement
@@ -251,7 +299,7 @@ dependencies:
251
299
  - - ! '>='
252
300
  - !ruby/object:Gem::Version
253
301
  version: 3.2.8
254
- description: Simple Push Notification Server written with Sinatra and Sequel(Sqlite3)
302
+ description: Apple Service Server written with Sinatra and Sequel(Sqlite3)
255
303
  email: eiffelqiu@gmail.com
256
304
  executables:
257
305
  - ass
@@ -283,7 +331,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
283
331
  version: '0'
284
332
  segments:
285
333
  - 0
286
- hash: -3175766109456070451
334
+ hash: -54990434379922484
287
335
  required_rubygems_version: !ruby/object:Gem::Requirement
288
336
  none: false
289
337
  requirements:
@@ -295,5 +343,5 @@ rubyforge_project: ass
295
343
  rubygems_version: 1.8.21
296
344
  signing_key:
297
345
  specification_version: 3
298
- summary: Simple Push Notification Server
346
+ summary: Apple Service Server
299
347
  test_files: []