gcal_mapper 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +32 -0
  2. data/.travis.yml +16 -0
  3. data/CHANGELOG.md +15 -0
  4. data/Gemfile +20 -0
  5. data/Guardfile +19 -0
  6. data/LICENSE +22 -0
  7. data/README.md +370 -0
  8. data/Rakefile +32 -0
  9. data/bin/ci/file/auth.yaml +7 -0
  10. data/bin/ci/file/bad_yaml.yaml +0 -0
  11. data/bin/ci/file/config.yaml +8 -0
  12. data/bin/ci/file/privatekey.p12 +0 -0
  13. data/bin/ci/travis_build.sh +4 -0
  14. data/bin/ci/vcr/GcalMapper_Authentification/access_token_should_exist_with_assertion_auth.yml +49 -0
  15. data/bin/ci/vcr/GcalMapper_Authentification/should_be_fasle_if_bad_client_email_is_given.yml +47 -0
  16. data/bin/ci/vcr/GcalMapper_Authentification_Assertion/should_have_access_token_attribute.yml +49 -0
  17. data/bin/ci/vcr/GcalMapper_Authentification_Assertion/should_have_refresh_token_attribute.yml +49 -0
  18. data/bin/ci/vcr/GcalMapper_Calendar/should_get_the_calendar_list.yml +190 -0
  19. data/bin/ci/vcr/GcalMapper_Calendar/should_get_the_events_list.yml +45 -0
  20. data/bin/ci/vcr/GcalMapper_Calendar/should_raise_error_if_the_calendar_id_isn_t_accessible.yml +56 -0
  21. data/bin/ci/vcr/GcalMapper_Calendar/should_raise_error_if_the_token_is_bad.yml +60 -0
  22. data/bin/ci/vcr/GcalMapper_Mapper/should_save_all_events.yml +232 -0
  23. data/bin/ci/vcr/GcalMapper_Mapper/should_save_events_only_once.yml +232 -0
  24. data/bin/gcal-mapper +108 -0
  25. data/gcal_mapper.gemspec +25 -0
  26. data/lib/gcal_mapper.rb +15 -0
  27. data/lib/gcal_mapper/authentification.rb +57 -0
  28. data/lib/gcal_mapper/authentification/assertion.rb +110 -0
  29. data/lib/gcal_mapper/authentification/base.rb +20 -0
  30. data/lib/gcal_mapper/authentification/oauth2.rb +68 -0
  31. data/lib/gcal_mapper/calendar.rb +51 -0
  32. data/lib/gcal_mapper/configuration.rb +23 -0
  33. data/lib/gcal_mapper/errors.rb +40 -0
  34. data/lib/gcal_mapper/mapper.rb +76 -0
  35. data/lib/gcal_mapper/mapper/active_record.rb +74 -0
  36. data/lib/gcal_mapper/mapper/dsl.rb +57 -0
  37. data/lib/gcal_mapper/mapper/simple.rb +97 -0
  38. data/lib/gcal_mapper/railtie.rb +8 -0
  39. data/lib/gcal_mapper/rest_request.rb +73 -0
  40. data/lib/gcal_mapper/sync.rb +159 -0
  41. data/lib/gcal_mapper/version.rb +4 -0
  42. data/spec/authentification/assertion_spec.rb +15 -0
  43. data/spec/authentification/base_spec.rb +18 -0
  44. data/spec/authentification/oauth2_spec.rb +15 -0
  45. data/spec/authentification_spec.rb +34 -0
  46. data/spec/calendar_spec.rb +33 -0
  47. data/spec/gcal_mapper_spec.rb +5 -0
  48. data/spec/mapper/active_record_spec.rb +46 -0
  49. data/spec/mapper/dsl_spec.rb +31 -0
  50. data/spec/mapper/simple_spec.rb +48 -0
  51. data/spec/mapper_spec.rb +32 -0
  52. data/spec/rest_request_spec.rb +5 -0
  53. data/spec/spec_helper.rb +51 -0
  54. data/spec/support/models/event.rb +25 -0
  55. data/spec/support/models/event_jeu.rb +22 -0
  56. data/spec/support/schema.rb +28 -0
  57. data/spec/sync_spec.rb +28 -0
  58. metadata +200 -0
@@ -0,0 +1,23 @@
1
+ module GcalMapper
2
+ #
3
+ # Gem's configuration
4
+ #
5
+ class Configuration
6
+
7
+ attr_accessor :gid # name of the field that contains google event id
8
+ attr_accessor :fields # hash that contains all the field with their source config
9
+ attr_accessor :calendars # array that contains all the calendar id to fetch
10
+ attr_accessor :file # Auth file path
11
+ attr_accessor :client_email # Service account email
12
+ attr_accessor :user_email # email of user to impersonat
13
+ attr_accessor :password # passowrd for p12 key
14
+
15
+ # New configuration object
16
+ #
17
+ def initialize
18
+ @fields = {}
19
+ @calendars = []
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+
2
+
3
+ module GcalMapper
4
+ #
5
+ # An error which is raised when the authentification process fails
6
+ #
7
+ class AuthentificationError < StandardError
8
+ end
9
+
10
+ #
11
+ # An error which is raised when the yaml or p12 key does not contains what expected
12
+ #
13
+ class AuthFileError < StandardError
14
+ end
15
+
16
+ #
17
+ # An error which is raised when the http status code of the respose is not within 200..300
18
+ #
19
+ class ResponseStatusError < StandardError
20
+ end
21
+
22
+ #
23
+ # An exception which is raised when no calenards are accessible.
24
+ #
25
+ class CalendarAvailabilityError < StandardError
26
+ end
27
+
28
+ #
29
+ # An exception which is raised when specified calendar is not available.
30
+ #
31
+ class CalendarAccessibilityError < StandardError
32
+ end
33
+
34
+ #
35
+ # Error when there is error in user DSL
36
+ #
37
+ class DSLSyntaxError < StandardError
38
+ end
39
+
40
+ end
@@ -0,0 +1,76 @@
1
+ require 'gcal_mapper/mapper/dsl'
2
+ require 'gcal_mapper/mapper/active_record'
3
+ require 'gcal_mapper/mapper/simple'
4
+
5
+ module GcalMapper
6
+ #
7
+ # Provide dsl en sync methods
8
+ #
9
+ module Mapper
10
+
11
+ # setter for class varaible base
12
+ #
13
+ # @return [Class] class name of the includer
14
+ def self.base=(base)
15
+ @@base = base
16
+ end
17
+
18
+ # reader for class varaible base
19
+ #
20
+ # @return [Class] class name of the includer
21
+ def self.base
22
+ @@base
23
+ end
24
+
25
+ # setter for config class attributes
26
+ #
27
+ # @param [Configuration] config configuration class
28
+ def self.config=(config)
29
+ @@config = config
30
+ end
31
+
32
+ # getter for config class attributes
33
+ #
34
+ # @return [Configuration] configuration class
35
+ def self.config
36
+ @@config
37
+ end
38
+
39
+ # setter for adapter class attributes
40
+ #
41
+ # @param [Configuration] config configuration class
42
+ def self.adapter=(adapter)
43
+ @@adapter = adapter
44
+ end
45
+
46
+ # getter for adapter class attributes
47
+ #
48
+ # @return [Configuration] configuration class
49
+ def self.adapter
50
+ @@adapter
51
+ end
52
+
53
+ #
54
+ # module to add class methods to the includer
55
+ #
56
+ module ClassMethods
57
+
58
+ # provide dsl function
59
+ #
60
+ # @param [Block] block contain dsl of th caller
61
+ def calendar(&block)
62
+ Mapper.config = GcalMapper::Configuration.new
63
+ dsl = DSL.new(Mapper.config)
64
+ dsl.instance_eval(&block)
65
+ end
66
+
67
+ # synchronize methods for the caller
68
+ #
69
+ def synchronize_calendar
70
+ Sync.sync(Mapper.config, Mapper.base)
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,74 @@
1
+ require 'active_record'
2
+
3
+ module GcalMapper
4
+ module Mapper
5
+ #
6
+ # module to include when active record is in use
7
+ #
8
+ module ActiveRecord
9
+
10
+ # execute when the file is included
11
+ #
12
+ # @param [Class] base class of the includer
13
+ def self.included(base)
14
+ base.extend(GcalMapper::Mapper::ClassMethods)
15
+ Mapper.base = base
16
+ Mapper.adapter = ActiveRecord.new(base)
17
+ end
18
+
19
+ #
20
+ # Adapter for ActiveRecord
21
+ #
22
+ class ActiveRecord
23
+
24
+ def initialize(base)
25
+ @base = base
26
+ end
27
+
28
+ # create and save object using attributes
29
+ #
30
+ # @param [Hash] attributes all the attributes to save in the new object
31
+ # return [Object] createrd object
32
+ def create!(attributes)
33
+ @base.create(attributes)
34
+ end
35
+
36
+ # update an object
37
+ #
38
+ # @param [Int] id id of the object in the DB
39
+ # @param [Hash] attributes hash containing the field to update
40
+ # @return [Object] updated object
41
+ def update!(id, attributes)
42
+ obj = @base.find(id)
43
+ obj.update_attributes!(attributes)
44
+ end
45
+
46
+ # delet an object
47
+ #
48
+ # @param [Int] id id of the object in the DB
49
+ # @return [Object] the destroyed object
50
+ def delete!(id)
51
+ obj = @base.find(id)
52
+ obj.destroy
53
+ end
54
+
55
+ # Find all models
56
+ #
57
+ # @return [Array] all the object from a calss
58
+ def find_all
59
+ @base.all
60
+ end
61
+
62
+ # find an object from a field and a value
63
+ #
64
+ # @param [String] field name of the field where to search
65
+ # @param [String] value the value to find
66
+ # @return [Object] the finded object or nil
67
+ def find_by(field, value)
68
+ @base.send('find_by_' + field, value)
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,57 @@
1
+ module GcalMapper
2
+ module Mapper
3
+ #
4
+ # Provide DSL to configure gem
5
+ #
6
+ class DSL
7
+ VALID_FIELD_OPTIONS = [:source, :if_empty, :match, :default] # options available in DSL
8
+
9
+ # Intitialize config
10
+ #
11
+ def initialize(config)
12
+ @config = config
13
+ end
14
+
15
+ # Add new calendar id
16
+ #
17
+ # @param [string] id calendar id to add
18
+ def calendar (id)
19
+ @config.calendars.push(id)
20
+ end
21
+
22
+ # Add a new field
23
+ #
24
+ # @param [String] name DB field name
25
+ # @param [Hash] options contains source options used to fill the field
26
+ def field(name, options = {})
27
+ raise GcalMapper::DSLSyntaxError, 'Source option must be present' if !options.include?(:source)
28
+ raise GcalMapper::DSLSyntaxError, 'field option not available' if (options.keys != VALID_FIELD_OPTIONS & options.keys)
29
+
30
+ if options[:match]
31
+ raise GcalMapper::DSLSyntaxError, 'invalid regex' if options[:match].class != Regexp
32
+ end
33
+
34
+ @config.fields.merge!(name => options)
35
+ end
36
+
37
+ # Add authentification configuration
38
+ #
39
+ # @param [Hash] options contains the stuff to configure authetification
40
+ def configure(options = {})
41
+ raise GcalMapper::DSLSyntaxError, 'you must give a credential file' if options[:file].nil?
42
+ @config.file = options[:file]
43
+ @config.client_email = options[:client_email]
44
+ @config.user_email = options[:user_email]
45
+ @config.password = options[:password]
46
+ end
47
+
48
+ # Give the field in DB that is reserved to put event id given by google
49
+ #
50
+ # @param [String] name DB field name
51
+ def google_id(name)
52
+ @config.gid = name
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,97 @@
1
+ module GcalMapper
2
+ module Mapper
3
+ #
4
+ # module to include when no orm is used
5
+ #
6
+ module Simple
7
+
8
+ # execute when the file is included
9
+ #
10
+ # @param [Class] base class of the includer
11
+ def self.included(base)
12
+ base.extend(GcalMapper::Mapper::ClassMethods)
13
+ Mapper.base = base
14
+ Mapper.adapter = Simple.new(base)
15
+ end
16
+
17
+ #
18
+ # Adapter to use without an orm
19
+ #
20
+ class Simple
21
+ attr_reader :events # array of the synchronized events
22
+
23
+ # new object
24
+ #
25
+ # @param [class] klass class that need an adapter
26
+ def initialize(base)
27
+ @base = base
28
+ @events = []
29
+ end
30
+
31
+ # create and save object using attributes
32
+ #
33
+ # @param [Hash] attributes all the attributes to save in the new object
34
+ def create!(attributes)
35
+ obj = @base.new
36
+ obj.id = @events.count
37
+ attributes.each do |key, value|
38
+ obj.send(key+'=', value)
39
+ end
40
+
41
+ @events << obj
42
+ end
43
+
44
+ # update an object
45
+ #
46
+ # @param [Int] id id of the object in the DB
47
+ # @param [Hash] attributes hash containing the field to update
48
+ def update!(id, attributes)
49
+ obj = @events[id]
50
+ attributes.each do |key, value|
51
+ obj.send(key+'=', value)
52
+ end
53
+
54
+ @events << obj
55
+ end
56
+
57
+ # delet an object
58
+ #
59
+ # @param [Int] id id of the object in the DB
60
+ def delete!(id)
61
+ @events[id] = nil
62
+
63
+ @events.each_with_index do |item, index|
64
+ if item
65
+ if @events[index + 1]
66
+ item = @events[index + 1]
67
+ item.id =- 1
68
+ end
69
+ end
70
+ end
71
+
72
+ @events.delete(nil)
73
+ end
74
+
75
+ # Find all models
76
+ #
77
+ def find_all
78
+ @events
79
+ end
80
+
81
+ # find an object from a field and a value
82
+ #
83
+ # @param [String] field name of the field where to search
84
+ # @param [String] value the value to find
85
+ def find_by(field, value)
86
+ find_event = nil
87
+ @events.each do |event|
88
+ find_event = event if event.send(field) == value
89
+ end
90
+
91
+ find_event
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,8 @@
1
+ module GcalMapper
2
+ #
3
+ # Extends Rails framework
4
+ #
5
+ class Railtie < Rails::Railtie
6
+
7
+ end
8
+ end
@@ -0,0 +1,73 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module GcalMapper
5
+ #
6
+ # Make a REST get or post request
7
+ #
8
+ class RestRequest
9
+
10
+ attr_accessor :url # Complete url for the request
11
+ attr_accessor :options # Options for the REST request
12
+
13
+ # Initialize a new request
14
+ #
15
+ # @param [String] url the complete url of where to send the request
16
+ # @datarequest.rbparam [Hash] options contain all the options that can be included in REST request
17
+ def initialize (url, options = {})
18
+ @url = url
19
+ @options = options
20
+ end
21
+
22
+ # Set a proxy if the connection needs it
23
+ #
24
+ def proxy
25
+ http_proxy = ENV["http_proxy"]
26
+ URI.parse(http_proxy) rescue nil
27
+ end
28
+
29
+ # Execute REST request
30
+ #
31
+ # @return [Hash] a Json parsed hash that contains the body of the response.
32
+ def execute
33
+ options = {
34
+ :parameters => {}, :debug => false,
35
+ :http_timeout => 60, :method => :get,
36
+ :headers => {}, :redirect_count => 0,
37
+ :max_redirects => 10
38
+ }.merge(@options)
39
+ url = URI(@url)
40
+
41
+ if proxy
42
+ http = Net::HTTP::Proxy(proxy.host, proxy.port).new(url.host, url.port)
43
+ else
44
+ http = Net::HTTP.new(url.host, url.port)
45
+ end
46
+
47
+ if url.scheme == 'https'
48
+ http.use_ssl = true
49
+ end
50
+
51
+ http.open_timeout = http.read_timeout = options[:http_timeout]
52
+ http.set_debug_output $stderr if options[:debug]
53
+
54
+ request = case options[:method]
55
+ when :post
56
+ request = Net::HTTP::Post.new(url.request_uri)
57
+ request.set_form_data(options[:parameters])
58
+ request
59
+ else
60
+ request = Net::HTTP::Get.new(url.request_uri)
61
+ end
62
+
63
+ options[:headers].each { |key, value| request[key] = value }
64
+ response = http.request(request)
65
+ if !(200..300).include?(response.code.to_i)
66
+ raise GcalMapper::ResponseStatusError
67
+ end
68
+
69
+ JSON.parse(response.body)
70
+ end
71
+
72
+ end
73
+ end