flashover 0.0.1

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.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ flashover (0.0.1)
5
+ redis (>= 3.0.2)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ rake (10.0.3)
11
+ redis (3.0.2)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ flashover!
18
+ rake (>= 10.0.0)
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ I really don't care.
data/README ADDED
@@ -0,0 +1 @@
1
+ # Flashover
data/Rakefile ADDED
@@ -0,0 +1,107 @@
1
+ require 'rubygems'
2
+ require './env'
3
+ require 'rake'
4
+ require 'date'
5
+
6
+ #############################################################################
7
+ #
8
+ # Helper functions
9
+ #
10
+ #############################################################################
11
+
12
+ def name
13
+ @name ||= Dir['*.gemspec'].first.split('.').first
14
+ end
15
+
16
+ def version
17
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
18
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
19
+ end
20
+
21
+ def date
22
+ Date.today.to_s
23
+ end
24
+
25
+ def rubyforge_project
26
+ name
27
+ end
28
+
29
+ def gemspec_file
30
+ "#{name}.gemspec"
31
+ end
32
+
33
+ def gem_file
34
+ "#{name}-#{version}.gem"
35
+ end
36
+
37
+ def replace_header(head, header_name)
38
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
39
+ end
40
+
41
+ #############################################################################
42
+ #
43
+ # Packaging tasks
44
+ #
45
+ #############################################################################
46
+
47
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
48
+ task :release => :build do
49
+ unless `git branch` =~ /^\* master$/
50
+ puts "You must be on the master branch to release!"
51
+ exit!
52
+ end
53
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
54
+ sh "git tag v#{version}"
55
+ sh "git push origin master"
56
+ sh "git push origin v#{version}"
57
+ sh "gem push pkg/#{name}-#{version}.gem"
58
+ end
59
+
60
+ desc "Build #{gem_file} into the pkg directory"
61
+ task :build => :gemspec do
62
+ sh "mkdir -p pkg"
63
+ sh "gem build #{gemspec_file}"
64
+ sh "mv #{gem_file} pkg"
65
+ end
66
+
67
+ desc "Generate #{gemspec_file}"
68
+ task :gemspec => :validate do
69
+ # read spec file and split out manifest section
70
+ spec = File.read(gemspec_file)
71
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
72
+
73
+ # replace name version and date
74
+ replace_header(head, :name)
75
+ replace_header(head, :version)
76
+ replace_header(head, :date)
77
+ #comment this out if your rubyforge_project has a different name
78
+ replace_header(head, :rubyforge_project)
79
+
80
+ # determine file list from git ls-files
81
+ files = `git ls-files`.
82
+ split("\n").
83
+ sort.
84
+ reject { |file| file =~ /^\./ }.
85
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
86
+ map { |file| " #{file}" }.
87
+ join("\n")
88
+
89
+ # piece file back together and write
90
+ manifest = " s.files = %w[\n#{files}\n ]\n"
91
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
92
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
93
+ puts "Updated #{gemspec_file}"
94
+ end
95
+
96
+ desc "Validate #{gemspec_file}"
97
+ task :validate do
98
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
99
+ unless libfiles.empty?
100
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
101
+ exit!
102
+ end
103
+ unless Dir['VERSION*'].empty?
104
+ puts "A `VERSION` file at root level violates Gem best practices."
105
+ exit!
106
+ end
107
+ end
data/env.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ $:.unshift File.dirname(__FILE__) + "/lib"
5
+
6
+ require "flashover"
data/flashover.gemspec ADDED
@@ -0,0 +1,62 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+ s.rubygems_version = '1.3.5'
5
+
6
+ ## Leave these as is they will be modified for you by the rake gemspec task.
7
+ ## If your rubyforge_project name is different, then edit it and comment out
8
+ ## the sub! line in the Rakefile
9
+ s.name = 'flashover'
10
+ s.version = '0.0.1'
11
+ s.date = '2013-02-06'
12
+ # s.rubyforge_project = 'flashover'
13
+
14
+ ## Make sure your summary is short. The description may be as long
15
+ ## as you like.
16
+ s.summary = "Flashover - Rentify's event firehose"
17
+ s.description = "Fires events down a hose towards the Great Unknown."
18
+
19
+ ## List the primary authors. If there are a bunch of authors, it's probably
20
+ ## better to set the email to an email list or something. If you don't have
21
+ ## a custom homepage, consider using your GitHub URL or the like.
22
+ s.authors = ["Luke Carpenter"]
23
+ s.email = 'x@rubynerd.net'
24
+ s.homepage = 'http://engineering.rentify.com'
25
+
26
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
27
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
28
+ s.require_paths = %w[lib]
29
+
30
+ ## Specify any RDoc options here. You'll want to add your README and
31
+ ## LICENSE files to the extra_rdoc_files list.
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.extra_rdoc_files = %w[README LICENSE]
34
+
35
+ ## List your runtime dependencies here. Runtime dependencies are those
36
+ ## that are needed for an end user to actually USE your code.
37
+ s.add_dependency('redis', [">= 3.0.2"])
38
+
39
+ s.add_development_dependency('rake', [">= 10.0.0"])
40
+
41
+ ## Leave this section as-is. It will be automatically generated from the
42
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
43
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
44
+ # = MANIFEST =
45
+ s.files = %w[
46
+ Gemfile
47
+ Gemfile.lock
48
+ LICENSE
49
+ README
50
+ Rakefile
51
+ env.rb
52
+ flashover.gemspec
53
+ lib/flashover.rb
54
+ spec/flashover_spec.rb
55
+ spec/spec_helper.rb
56
+ ]
57
+ # = MANIFEST =
58
+
59
+ ## Test files will be grabbed from the file list. Make sure the path glob
60
+ ## matches what you actually use.
61
+ s.test_files = s.files.select { |path| path =~ /^spec\/_spec.*\.rb/ }
62
+ end
data/lib/flashover.rb ADDED
@@ -0,0 +1,130 @@
1
+ require "json"
2
+ require "redis"
3
+
4
+ class Flashover
5
+
6
+ VERSION = "0.0.1"
7
+
8
+ MESSAGE_TYPES = [
9
+ :sms,
10
+ :phone,
11
+ :email,
12
+ :page_view,
13
+ :generic,
14
+ :backup
15
+ ].freeze
16
+
17
+ attr_accessor :redis, :environment
18
+
19
+ def initialize redis, passphrase, salt
20
+ @redis = redis
21
+ @crypto = Crypto.new passphrase, salt
22
+ end
23
+
24
+ # 'type' dictates the message pipeline payload is shoved down
25
+ # can be:
26
+ # -> :sms
27
+ # -> :phone_call
28
+ # -> :email
29
+ # -> :page_view
30
+ # -> :generic
31
+ def event type, payload
32
+ begin
33
+ @redis.publish(convert_symbol_to_channel(type), build_payload(payload))
34
+ true
35
+ rescue Errno::ETIMEDOUT => ex
36
+ Airbrake.notify(ex)
37
+ Rails.logger.error "Flashover TIMEOUT @ #{Time.now.ctime}"
38
+ false
39
+ rescue => ex
40
+ Airbrake.notify(ex)
41
+ Rails.logger.error "BANG @ Flashover#event => #{ex.class} -> '#{ex.message}'"
42
+ false
43
+ end
44
+ end
45
+
46
+ def listen &blk
47
+ raise MaryPoppins.new("block must have two args") unless blk.arity == 2
48
+
49
+ @redis.subscribe(redis_message_types) do |on|
50
+ on.message do |channel, message|
51
+ yield convert_channel_to_symbol(channel), parse_message(message)
52
+ end
53
+ end
54
+ end
55
+
56
+ MESSAGE_TYPES.each do |message_type|
57
+ define_method message_type do |payload|
58
+ event message_type, payload
59
+ end
60
+ end
61
+
62
+ private
63
+ def encrypt(plaintext)
64
+ @crypto.encrypt plaintext
65
+ end
66
+
67
+ def decrypt(ciphertext)
68
+ @crypto.decrypt ciphertext
69
+ end
70
+
71
+ def build_payload(payload)
72
+ encrypt JSON.generate payload
73
+ end
74
+
75
+ def parse_message(message)
76
+ JSON.parse(decrypt message)
77
+ end
78
+
79
+ def build_message_from_payload(payload)
80
+ encrypt JSON.generate(payload)
81
+ end
82
+
83
+
84
+ def redis_message_types
85
+ @redis_message_types ||= MESSAGE_TYPES.map do |message_type|
86
+ "flashover:pubsub:#{environment}:#{message_type.to_s}"
87
+ end
88
+ end
89
+
90
+ def convert_channel_to_symbol channel
91
+ channel.split(":").last.to_sym
92
+ end
93
+
94
+ def convert_symbol_to_channel symbol
95
+ "flashover:pubsub:#{environment}:#{symbol.to_s}"
96
+ end
97
+
98
+ def environment
99
+ @environment || ENV["FLASHOVER_ENV"] || ENV["RAILS_ENV"] || "development"
100
+ end
101
+
102
+ class Crypto
103
+
104
+ def initialize(passphrase, salt)
105
+ raise MaryPoppins.new("salt needs to be 8 chars long") unless salt.length == 8
106
+ @passphrase = passphrase
107
+ @salt = salt
108
+ end
109
+
110
+ def encrypt plaintext
111
+ encryptor = OpenSSL::Cipher::Cipher.new 'AES-256-CBC'
112
+ encryptor.encrypt
113
+ encryptor.pkcs5_keyivgen @passphrase, @salt
114
+
115
+ encrypted = encryptor.update plaintext
116
+ encrypted << encryptor.final
117
+ end
118
+
119
+ def decrypt ciphertext
120
+ decryptor = OpenSSL::Cipher::Cipher.new 'AES-256-CBC'
121
+ decryptor.decrypt
122
+ decryptor.pkcs5_keyivgen @passphrase, @salt
123
+
124
+ decrypted = decryptor.update ciphertext
125
+ decrypted << decryptor.final
126
+ end
127
+ end
128
+
129
+ class MaryPoppins < StandardError; end
130
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe Flashover do
4
+ describe "incoming events" do
5
+ it "should publish a message to redis" do
6
+ redis = Object.new
7
+ redis.should_receive(:publish).with("flashover:pubsub:test:sms", anything) { true }
8
+
9
+ flashover = Flashover.new redis, "password"
10
+ flashover.sms "hello" => "world"
11
+ end
12
+
13
+ it "should encrypt the payload" do
14
+ Flashover::Crypto.any_instance.should_receive(:encrypt).with(anything) { "" }
15
+
16
+ redis = Object.new
17
+ redis.should_receive(:publish).with("flashover:pubsub:test:sms", anything) { true }
18
+
19
+ flashover = Flashover.new redis, "password"
20
+ flashover.sms "hello" => "world"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ Dir.glob("./lib/**/*.rb").each{ |f| require f }
2
+
3
+ class Airbrake
4
+ class << self
5
+
6
+ @@exceptions = []
7
+
8
+ def notify exception
9
+ @@exceptions << exception
10
+ end
11
+ end
12
+ end
13
+
14
+ require "json"
15
+ require "rails"
16
+
17
+ Rails.logger = Logger.new "/dev/null"
18
+
19
+ ENV["RAILS_ENV"] = "test"
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flashover
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Luke Carpenter
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 10.0.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 10.0.0
46
+ description: Fires events down a hose towards the Great Unknown.
47
+ email: x@rubynerd.net
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files:
51
+ - README
52
+ - LICENSE
53
+ files:
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - LICENSE
57
+ - README
58
+ - Rakefile
59
+ - env.rb
60
+ - flashover.gemspec
61
+ - lib/flashover.rb
62
+ - spec/flashover_spec.rb
63
+ - spec/spec_helper.rb
64
+ homepage: http://engineering.rentify.com
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ segments:
78
+ - 0
79
+ hash: 3880441880579916259
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.23
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: Flashover - Rentify's event firehose
92
+ test_files: []