Skip to content

Commit

Permalink
changed -c option to point to YAML file; read certificates from file;…
Browse files Browse the repository at this point in the history
… same processing for YAML and Redis; updated README
  • Loading branch information
Tilo Sloboda committed Jun 16, 2014
1 parent 8753fe3 commit df290fe
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 27 deletions.
105 changes: 105 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ And run `bundle install` to install the gems.

## Configuration

### Via Redis or YAML File

The configuration of Pushr can either be stored in Redis or in a YAML file. **The default is Redis.**

If you want to use a YAML file, you need to specify it via the `-c` option of the `pushr` daemon.
Note that this will also override any existing Redis configuration.
APNS certificates can be loaded from file. If a relative file name is given, it's assumed to be relative to the same path as the YAML config file.

### Redis

By default the gem tries to connect to a Redis instance at localhost. If you define the `PUSHR_URL` environment variable
it will use that. The configuration is stored in Redis and you add the configuration per push provider with the console
(`bundle console`):
Expand Down Expand Up @@ -68,6 +78,82 @@ You can have each provider per app_name and you can have more than one app_name.
the certificate for the APNS provider. If you only want to prepare the database with the configurations, you can set the
`enabled` switch to `false`. Only enabled configurations will be used by the daemon.

### YAML File

If a YAML file is used for configuration, it needs to follow the structure of the example below, and may contain only the desired sections.

The certificates will be read from files. For security reasons, you might not want to check-in the certificate files into your source code repository.

If no absolute path is given of the PEM files, the location is assumed to be relative to the location of the YAML file.

The following example of a YAML configuration file can be found under `./lib/generators/templates/pushr.yml`.


```
# Configurations for all Pushr Gems
---
# Android Messaging:
- type: Pushr::ConfigurationGcm
app: gcm-development
enabled: true
connections: 1
api: your-api-key-here
# Feedback Service for all APNS Connections:
- type: Pushr::ConfigurationApnsFeedback
app: apns-feedback
enabled: true
connections: 1
feedback_poll: 300 # seconds
# Apple Messaging:
- type: Pushr::ConfigurationApns
app: ios-development
enabled: true
connections: 1
skip_check_for_error: false
sandbox: true
certificate: filename.pem
- type: Pushr::ConfigurationApns
app: ios-development
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: true
certificate: pushr/ios-development.pem
- type: Pushr::ConfigurationApns
app: ios-production
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: false
certificate: pushr/ios-production.pem
- type: Pushr::ConfigurationApns
app: ios-beta
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: true
certificate: pushr/ios-beta.pem
- type: Pushr::ConfigurationApns
app: ios-enterprise
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: false
certificate: pushr/ios-enterprise.pem
```

### Generating Certificates for APNS

1. Open up Keychain Access and select the `Certificates` category in the sidebar.
Expand All @@ -94,6 +180,7 @@ Where `<options>` can be:
-f, --foreground Run in the foreground. Log is not written.
-p, --pid-file PATH Path to write PID file. Relative to Rails root unless absolute.
-b, --feedback-processor PATH Path to the feedback processor. Default: lib/push/feedback_processor.
-c, --configuration FILE Read the configuration from this YAML file (optional)
-v, --version Print this version of push.
-h, --help You're looking at it.

Expand All @@ -113,6 +200,24 @@ Pushr::MessageApns.new(
content_available: 1).save
```


Silent Push Notification via APNS:

```ruby
Push::MessageApns.create(
app: 'app_name',
device: '<APNS device_token here>',
alert: nil,
sound: nil,
badge: 1,
content_available: 1, # see footnote
expiry: 1.day.to_i,
attributes_for_device: nil)
```

Use `content_available: 1` if the iOS device should start your app upon receiving the silent push notification.


GCM:
```ruby
Pushr::MessageGcm.new(
Expand Down
4 changes: 2 additions & 2 deletions bin/pushr
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ ARGV.options do |opts|
settings.foreground = true
end

opts.on('-c PATH', '--configuration PATH', 'Get the configuration from a YAML file') do |path|
settings.configuration_path = path
opts.on('-c FILE', '--configuration FILE', 'Read the configuration from this YAML file') do |file|
settings.configuration_file = file
end

opts.on('-p PATH', '--pid-file PATH', String,
Expand Down
61 changes: 61 additions & 0 deletions lib/generators/templates/pushr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Configurations for all Pushr Gems
---

# Android Messaging:

- type: Pushr::ConfigurationGcm
app: gcm-development
enabled: true
connections: 1
api: your-api-key-here


# Feedback Service for all APNS Connections:

- type: Pushr::ConfigurationApnsFeedback
app: apns-feedback
enabled: true
connections: 1
feedback_poll: 300 # seconds

# Apple Messaging:

- type: Pushr::ConfigurationApns
app: ios-development
enabled: true
connections: 1
skip_check_for_error: false
sandbox: true
certificate: filename.pem

- type: Pushr::ConfigurationApns
app: ios-development
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: true
certificate: pushr/ios-development.pem

- type: Pushr::ConfigurationApns
app: ios-production
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: false
certificate: pushr/ios-production.pem

- type: Pushr::ConfigurationApns
app: ios-beta
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: true
certificate: pushr/ios-beta.pem

- type: Pushr::ConfigurationApns
app: ios-enterprise
enabled: true
connections: 1
# skip_check_for_error: true
sandbox: false
certificate: pushr/ios-enterprise.pem
40 changes: 30 additions & 10 deletions lib/pushr/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module Pushr
class Configuration
include ActiveModel::Validations

validates :app, presence: true
validates :connections, presence: true
validates :connections, numericality: { greater_than: 0, only_integer: true }
Expand Down Expand Up @@ -31,24 +30,45 @@ def delete
end

def self.all
configurations = Pushr::Core.redis { |conn| conn.hgetall('pushr:configurations') }
configurations.each { |key, config| configurations[key] = instantiate(config, key) }
configurations.values
if Pushr::Daemon.config.configuration_file # only set if file exists
read_from_yaml_file
else
read_from_redis
end
end

def self.find(key)
config = Pushr::Core.redis { |conn| conn.hget('pushr:configurations', key) }
instantiate(config, key)
end

def self.instantiate(config, id)
hsh = ::MultiJson.load(config).merge!(id: id)
klass = hsh['type'].split('::').reduce(Object) { |a, e| a.const_get e }
klass.new(hsh)
end

def to_json
MultiJson.dump(to_hash)
end

private

def read_from_yaml_file
filename = Pushr::Daemon.config.configuration_file
configs = File.open( filename ) { |fd| YAML.load(fd) }
configs.map do |hsh|
klass = hsh['type'].split('::').reduce(Object) { |a, e| a.const_get e }
klass.new(hsh)
end
end
end

def read_from_redis
configurations = Pushr::Core.redis { |conn| conn.hgetall('pushr:configurations') }
configurations.each { |key, config| configurations[key] = instantiate(config, key) }
configurations.values
end

def self.instantiate(config, id)
hsh = ::MultiJson.load(config).merge!(id: id)
klass = hsh['type'].split('::').reduce(Object) { |a, e| a.const_get e }
klass.new(hsh)
end

end
end
2 changes: 1 addition & 1 deletion lib/pushr/daemon/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class << self
attr_reader :apps

def load
@apps = Pushr::Daemon.config.configurations.keep_if { |c| c.enabled == true }.map { |c| App.new(c) }
@apps = Pushr::Configuration.all.keep_if { |c| c.enabled == true }.map { |c| App.new(c) }
end

def total_connections
Expand Down
24 changes: 10 additions & 14 deletions lib/pushr/daemon/settings.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Pushr
module Daemon
class Settings
attr_reader :pid_file, :configuration_path
attr_reader :pid_file, :configuration_file
attr_accessor :foreground, :error_notification, :feedback_processor, :stats_processor

def initialize
Expand All @@ -10,28 +10,24 @@ def initialize
@feedback_processor = nil
@stats_processor = nil
@pid_file = nil
@configuration_path = nil
@configuration_file = nil
end

def pid_file=(arg)
@pid_file = File.join(Dir.pwd, arg) if arg && !Pathname.new(arg).absolute?
end

def configuration_path=(arg)
@configuration_path = File.join(Dir.pwd, arg) if arg && !Pathname.new(arg).absolute?
end

def configurations
if configuration_path
configs = File.open('config.yml') { |fd| YAML.load(fd) }
configs.map do |hsh|
klass = hsh['type'].split('::').reduce(Object) { |a, e| a.const_get e }
klass.new(hsh)
def configuration_file=(filename)
if filename
filename = File.join(Dir.pwd,filename) if ! Pathname.new(filename).absolute?
if File.file?(filename)
@configuration_file = filename
else
Pushr::Daemon.logger.error("can not find config file: #{filename}")
end
else
Pushr::Configuration.all
end
end

end
end
end

0 comments on commit df290fe

Please sign in to comment.