calendar-to-queue 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +5 -0
  5. data/Rakefile +37 -0
  6. data/app/assets/javascripts/calendar_to_queue/application.js +13 -0
  7. data/app/assets/stylesheets/calendar_to_queue/application.css +15 -0
  8. data/app/controllers/calendar_to_queue/application_controller.rb +9 -0
  9. data/app/controllers/calendar_to_queue/google_calendar_push_controller.rb +28 -0
  10. data/app/helpers/calendar_to_queue/application_helper.rb +4 -0
  11. data/app/models/calendar_to_queue/google_calendar_push.rb +59 -0
  12. data/app/models/calendar_to_queue/queue.rb +53 -0
  13. data/app/views/layouts/calendar_to_queue/application.html.erb +14 -0
  14. data/config/routes.rb +3 -0
  15. data/db/migrate/20160229221448_create_calendar_to_queue_google_calendar_pushes.rb +15 -0
  16. data/db/migrate/20160229224219_create_calendar_to_queue_queues.rb +9 -0
  17. data/lib/calendar_to_queue.rb +32 -0
  18. data/lib/calendar_to_queue/access_control/admin_authentication.rb +20 -0
  19. data/lib/calendar_to_queue/access_control/admin_authorization.rb +8 -0
  20. data/lib/calendar_to_queue/configuration.rb +38 -0
  21. data/lib/calendar_to_queue/engine.rb +5 -0
  22. data/lib/calendar_to_queue/version.rb +3 -0
  23. data/lib/tasks/calendar_to_queue_tasks.rake +4 -0
  24. data/test/calendar_to_queue_test.rb +7 -0
  25. data/test/controllers/calendar_to_queue/google_calendar_push_controller_test.rb +13 -0
  26. data/test/dummy/README.rdoc +28 -0
  27. data/test/dummy/Rakefile +6 -0
  28. data/test/dummy/app/assets/javascripts/application.js +13 -0
  29. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  30. data/test/dummy/app/controllers/application_controller.rb +5 -0
  31. data/test/dummy/app/helpers/application_helper.rb +2 -0
  32. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  33. data/test/dummy/bin/bundle +3 -0
  34. data/test/dummy/bin/rails +4 -0
  35. data/test/dummy/bin/rake +4 -0
  36. data/test/dummy/bin/setup +29 -0
  37. data/test/dummy/config.ru +4 -0
  38. data/test/dummy/config/application.rb +26 -0
  39. data/test/dummy/config/boot.rb +5 -0
  40. data/test/dummy/config/database.yml +25 -0
  41. data/test/dummy/config/environment.rb +5 -0
  42. data/test/dummy/config/environments/development.rb +41 -0
  43. data/test/dummy/config/environments/production.rb +79 -0
  44. data/test/dummy/config/environments/test.rb +42 -0
  45. data/test/dummy/config/initializers/assets.rb +11 -0
  46. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  47. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  48. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  49. data/test/dummy/config/initializers/inflections.rb +16 -0
  50. data/test/dummy/config/initializers/mime_types.rb +4 -0
  51. data/test/dummy/config/initializers/session_store.rb +3 -0
  52. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/test/dummy/config/locales/en.yml +23 -0
  54. data/test/dummy/config/routes.rb +4 -0
  55. data/test/dummy/config/secrets.yml +22 -0
  56. data/test/dummy/public/404.html +67 -0
  57. data/test/dummy/public/422.html +67 -0
  58. data/test/dummy/public/500.html +66 -0
  59. data/test/dummy/public/favicon.ico +0 -0
  60. data/test/fixtures/calendar_to_queue/queues.yml +11 -0
  61. data/test/integration/navigation_test.rb +8 -0
  62. data/test/models/calendar_to_queue/google_calendar_push_test.rb +9 -0
  63. data/test/models/calendar_to_queue/queue_test.rb +9 -0
  64. data/test/test_helper.rb +21 -0
  65. metadata +193 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6417d2361f6ed7a6269d446c346b5029e74954b6
4
+ data.tar.gz: cc274e815f1f78c952ae356c068e6ee448906407
5
+ SHA512:
6
+ metadata.gz: 8a45a8dcf323c41ed08412861695ca5ed446bfc4535870fb3f1db7bf1cbd1ab47b3af81fd77c2054151f8e70315e94df19717ccc63efbf70842a848d1cd1a511
7
+ data.tar.gz: 7bc24954e52adf11f91a4ef4f7a73b486c0e5936dcb1d1fd168868368a72466307942a0b2c481a08fd2d6016f2143aaef36c3b6297f744241a06acdf73e53b04
@@ -0,0 +1,3 @@
1
+ = 0.0.1
2
+
3
+ Initial Version
@@ -0,0 +1,20 @@
1
+ Copyright 2016 John Naegle
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ = CalendarToQueue
2
+
3
+ Mountable endpoint for Calendar Push Notifications from Google Calenders that
4
+ are placed into AWS Message Queues or a database for consumption.
5
+
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'CalendarToQueue'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,9 @@
1
+ module CalendarToQueue
2
+ class ApplicationController < ActionController::Base
3
+ # Authentication module must have `authenticate` method
4
+ include CalendarToQueue.config.admin_auth.to_s.constantize
5
+
6
+ # Authorization module must have `authorize` method
7
+ include CalendarToQueue.config.admin_authorization.to_s.constantize
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ require_dependency "calendar_to_queue/application_controller"
2
+
3
+ module CalendarToQueue
4
+
5
+ #
6
+ # Reciever for push notifications from watched resources in Google Calendar
7
+ #
8
+ class GoogleCalendarPushController < ApplicationController
9
+ def create
10
+ GoogleCalendarPush.new(create_params).process
11
+ head :ok
12
+ end
13
+
14
+ # https://developers.google.com/google-apps/calendar/v3/push#understanding-the-notification-message-format
15
+ def create_params
16
+ {
17
+ channel_id: request.headers['X-Goog-Channel-ID'],
18
+ message_number: request.headers['X-Goog-Message-Number'],
19
+ resource_id: request.headers['X-Goog-Resource-ID'],
20
+ state: request.headers['X-Goog-Resource-State'],
21
+ resource_uri: request.headers['X-Goog-Resource-URI'],
22
+ expiration: request.headers['X-Goog-Channel-Expiration'],
23
+ token: request.headers['X-Goog-Channel-Token']
24
+ }
25
+ end
26
+ private :create_params
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ module CalendarToQueue
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,59 @@
1
+ module CalendarToQueue
2
+ class GoogleCalendarPush < ActiveRecord::Base
3
+ def process
4
+ if self.token.blank?
5
+ log("No Token", :warn)
6
+ else
7
+ send_to_queue if queue?
8
+ save if persist?
9
+ end
10
+
11
+ unless queue?
12
+ log("Token: #{self.token}")
13
+ end
14
+ end
15
+
16
+ def payload
17
+ attributes.slice('channel_id', 'message_number', 'resource_id', 'state', 'resource_uri', 'expiration', 'token')
18
+ end
19
+
20
+ def send_to_queue
21
+ log("Sending to queue")
22
+ CalendarToQueue::Queue.deliver(self)
23
+ end
24
+ private :send_to_queue
25
+
26
+ # A-Z, a-z, 0-9, underscore(_), hyphen(-), and period (.). The
27
+ # name must not start or end with a period, and it should not
28
+ # have successive periods. The name is case sensitive and must
29
+ # be unique among all attribute names for the message. The name
30
+ # can be up to 256 characters long. The name cannot start with
31
+ # "AWS." or "Amazon." (or any variations in casing) because
32
+ # these prefixes are reserved for use by Amazon Web Services.
33
+ def queue_name
34
+ match_data = (token_hash['queue']||'').match(/^((?!(aws|amazon|\.))[a-z,0-9,_,\-,\.]{1,256})$/i)
35
+ match_data[0] if match_data
36
+ end
37
+
38
+ def queue?
39
+ queue_name.present?
40
+ end
41
+ private :queue?
42
+
43
+ def persist?
44
+ (token_hash['persist'] || '').match(/^(yes|true|1)$/i)
45
+ end
46
+ private :persist?
47
+
48
+ def token_hash
49
+ @token_hash ||= (token ||'').split('&').map {|x| x.split("=") }.to_h
50
+ end
51
+
52
+ def log(msg, level=:info)
53
+ CalendarToQueue.logger.send(level, "Google Calendar Push: ChannelId: #{self.channel_id}, MessageNumber: #{self.message_number}, ResourceId: #{self.resource_id}, State: #{self.state} - #{msg}")
54
+ end
55
+ private :log
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,53 @@
1
+ module CalendarToQueue
2
+ class Queue < ActiveRecord::Base
3
+
4
+ def self.deliver(push)
5
+ unless push.queue_name.blank?
6
+ queue = lookup(push.queue_name)
7
+ queue.deliver(push)
8
+ end
9
+ end
10
+
11
+ def deliver(push)
12
+ begin
13
+ CalendarToQueue::Queue.client.send_message({
14
+ queue_url: url,
15
+ message_body: JSON.generate(push.payload),
16
+ })
17
+ rescue Aws::SQS::Errors::ServiceError => e
18
+ CalendarToQueue.logger.error("Error sending to queue #{self.name}, push: #{}AWS QUEUE: #{e.context}: #{e.code}")
19
+ end
20
+ end
21
+
22
+ # Creates or finds
23
+ def self.lookup(name)
24
+ find_by_name(name) || create_queue(name)
25
+ end
26
+
27
+ def self.create_queue(name)
28
+ create(name: name)
29
+ end
30
+
31
+ after_create do
32
+ begin
33
+ response = client.create_queue(queue_name: name)
34
+ self.update_attributes(url: response.queue_url)
35
+ rescue Aws::SQS::Errors::ServiceError => e
36
+ CalendarToQueue.logger.error("Error creating AWS QUEUE: #{e.context}: #{e.code}")
37
+ end
38
+ end
39
+
40
+ def client
41
+ CalendarToQueue::Queue.client
42
+ end
43
+ private :client
44
+
45
+ def self.client
46
+ @@client ||= Aws::SQS::Client.new(
47
+ region: 'us-east-1',
48
+ access_key_id: CalendarToQueue.config.aws_access_key_id,
49
+ secret_access_key: CalendarToQueue.config.aws_secret_access_key
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>CalendarToQueue</title>
5
+ <%= stylesheet_link_tag "calendar_to_queue/application", media: "all" %>
6
+ <%= javascript_include_tag "calendar_to_queue/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,3 @@
1
+ CalendarToQueue::Engine.routes.draw do
2
+ resources :google_calendar_push, only: [:create]
3
+ end
@@ -0,0 +1,15 @@
1
+ class CreateCalendarToQueueGoogleCalendarPushes < ActiveRecord::Migration
2
+ def change
3
+ create_table :calendar_to_queue_google_calendar_pushes do |t|
4
+ t.string :channel_id
5
+ t.integer :message_number
6
+ t.string :resource_id
7
+ t.string :state
8
+ t.string :resource_uri
9
+ t.timestamp :expiration
10
+ t.string :token
11
+
12
+ t.timestamps null: false
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ class CreateCalendarToQueueQueues < ActiveRecord::Migration
2
+ def change
3
+ create_table :calendar_to_queue_queues do |t|
4
+ t.string :name
5
+ t.string :url
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ require "calendar_to_queue/engine"
2
+ require_relative 'calendar_to_queue/configuration'
3
+ require_relative 'calendar_to_queue/access_control/admin_authentication'
4
+ require_relative 'calendar_to_queue/access_control/admin_authorization'
5
+
6
+ module CalendarToQueue
7
+ class << self
8
+
9
+ # Modify CalendarToQueue configuration
10
+ # Example:
11
+ # CalendarToQueue.configure do |config|
12
+ # end
13
+ def configure
14
+ yield configuration
15
+ end
16
+
17
+ # Accessor for ComfortableMexicanSofa::Configuration
18
+ def configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+ alias :config :configuration
22
+
23
+ def logger=(new_logger)
24
+ @logger = new_logger
25
+ end
26
+
27
+ def logger
28
+ @logger ||= Rails.logger
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ module CalendarToQueue::AccessControl
2
+ module AdminAuthentication
3
+ # Set username and password in config/initializers/calendar_2_queue.rb
4
+ # Like this:
5
+ # CalendarToQueue::AccessControl::AdminAuthentication = 'myname'
6
+ # CalendarToQueue::AccessControl::AdminAuthentication = 'mypassword'
7
+
8
+ mattr_accessor :username,
9
+ :password
10
+
11
+ # Simple http_auth. When implementing some other form of authentication
12
+ # this method should return +true+ if everything is great, or redirect user
13
+ # to some other page, thus denying access to cms admin section.
14
+ def authenticate
15
+ authenticate_or_request_with_http_basic do |username, password|
16
+ self.username == username && self.password == password
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module CalendarToQueue::AccessControl
2
+ module AdminAuthorization
3
+ # By default there's no authorization of any kind
4
+ def authorize
5
+ true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ class CalendarToQueue::Configuration
4
+
5
+ # Module that will handle authentication to access queue-admin area
6
+ attr_accessor :admin_auth
7
+
8
+ # Module that will handle authorization against admin queue resources
9
+ attr_accessor :admin_authorization
10
+
11
+ # AWS access_key for sending pushes to AWS SQS
12
+ # defaults to ENV['AWS_ACCESS_KEY_ID']
13
+ attr_accessor :aws_access_key_id
14
+
15
+ # AWS secret access key for sending pushes to AWS SQS
16
+ # defaults to ENV['AWS_SECRET_ACCESS_KEY']
17
+ attr_accessor :aws_secret_access_key
18
+
19
+ # AWS Region
20
+ #
21
+ # Note: if you create an Amazon EC2 instance or an Amazon SQS queue in one region, the instance
22
+ # or queue is independent from instances or queues in another region.
23
+ #
24
+ # https://docs.aws.amazon.com/general/latest/gr/rande.html
25
+ #
26
+ # defaults to us-east-1
27
+ attr_accessor :aws_region
28
+
29
+ # Configuration defaults
30
+ def initialize
31
+ @admin_auth = 'CalendarToQueue::AccessControl::AdminAuthentication'
32
+ @admin_authorization = 'CalendarToQueue::AccessControl::AdminAuthorization'
33
+ @aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
34
+ @aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
35
+ @aws_region = 'us-east-1'
36
+ end
37
+
38
+ end
@@ -0,0 +1,5 @@
1
+ module CalendarToQueue
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace CalendarToQueue
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module CalendarToQueue
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :calendar_to_queue do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class CalendarToQueueTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, CalendarToQueue
6
+ end
7
+ end