bps-google-api 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bb3f5af2dbe6a57df4945c7d082aab5e6f68edb
4
- data.tar.gz: 225fd27b21ae836d6d051bf32a81b96e17ed71f7
3
+ metadata.gz: 9db47ec4d8765e23f5eaf19a0d0fab4927fdde18
4
+ data.tar.gz: 3bdc229d7f57a1cb9a1efbb5d86b88f1b38c6117
5
5
  SHA512:
6
- metadata.gz: 031d62aac72e1de816ac5d309fed95d8886c7b205633f25c9accf6ca8e43fa389c62334943a57f9ed4a0f85c47583149daab492eff8be4db403b7018c90b09a7
7
- data.tar.gz: 3e5e6374f3731ba02d763d515bf3877d35e635a0c5f1f87a465ac8fb891581aa288a42c83eed1fbf93a963dba681115269a497efe864d71c31116f0580940e45
6
+ metadata.gz: 327541c28d54c819b6827cf1c7024c11a45de98efa04e873a36d8f834c8b99f3012afb61885608a65be911ce50fcf3daef7757e5e3fd8a9a3a9774bd207a20db
7
+ data.tar.gz: a2f81f09ec656b48000906fb7a566cafcda0d617c2aa3890415485d418e18ead19e2662ac42a5b11f059fef119a50d992e9124b4e6755dcf199146fa4fbe2e17
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bps-google-api (0.2.0)
4
+ bps-google-api (0.2.1)
5
5
  exp_retry (~> 0.0.11)
6
6
  fileutils (~> 1.2)
7
7
  google-api-client (~> 0.23.4)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'bps-google-api'
5
- s.version = '0.2.0'
5
+ s.version = '0.2.1'
6
6
  s.date = '2019-06-20'
7
7
  s.summary = 'Configured Google API'
8
8
  s.description = 'A configured Google API wrapper.'
data/lib/ext/hash.rb ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Import assert_valid_keys from Rails if not already defined
4
+ class Hash
5
+ def assert_valid_keys(*valid_keys)
6
+ valid_keys.flatten!
7
+
8
+ each_key do |k|
9
+ next if valid_keys.include?(k)
10
+
11
+ raise(
12
+ ArgumentError,
13
+ "Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}"
14
+ )
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ProgressBar
4
+ class Silent
5
+ def self.tty?
6
+ true
7
+ end
8
+
9
+ def self.print(str)
10
+ str
11
+ end
12
+
13
+ def self.flush
14
+ self
15
+ end
16
+ end
17
+ end
data/lib/google_api.rb CHANGED
@@ -14,4 +14,8 @@ module GoogleAPI
14
14
  require 'google_api/base'
15
15
  require 'google_api/calendar'
16
16
  require 'google_api/group'
17
+ require 'google_api/configured'
18
+
19
+ require 'ext/hash' unless defined?(Rails)
20
+ require 'ext/silent_progress_bar'
17
21
  end
@@ -36,8 +36,7 @@ module GoogleAPI
36
36
  end
37
37
 
38
38
  def last_token_path
39
- path = %w[tmp run last_page_token]
40
- File.join(root_path, *path)
39
+ File.join(root_path, 'tmp', 'run', 'last_page_token')
41
40
  end
42
41
  end
43
42
  end
@@ -37,7 +37,7 @@ module GoogleAPI
37
37
  url = authorizer.get_authorization_url(base_url: OOB_URI)
38
38
  puts("Open this URL to authorize:\n", url)
39
39
  print("\nResponse code: ")
40
- gets
40
+ ENV.key?('GOOGLE_AUTHORIZATION_CODE') ? ENV['GOOGLE_AUTHORIZATION_CODE'] : gets
41
41
  end
42
42
 
43
43
  def authorizer
@@ -61,12 +61,12 @@ module GoogleAPI
61
61
  {
62
62
  GOOGLE_CLIENT_ID: auth.client_id, GOOGLE_CLIENT_SECRET: auth.client_secret,
63
63
  GOOGLE_ACCESS_TOKEN: auth.access_token, GOOGLE_REFRESH_TOKEN: auth.refresh_token,
64
- GOOGLE_AUTH_SCOPES: auth.scope, GOOGLE_AUTH_EXP: expires_milli(auth.as_json['expires_at'])
64
+ GOOGLE_AUTH_SCOPES: auth.scope, GOOGLE_AUTH_EXP: expires_milli(auth.expires_at.to_s)
65
65
  }
66
66
  end
67
67
 
68
68
  def expires_milli(time)
69
- DateTime.strptime(time, '%Y-%m-%dT%H:%M:%S.%L%:z').to_i * 1000
69
+ Time.strptime(time, '%Y-%m-%d %H:%M:%S %:z').to_i * 1000
70
70
  end
71
71
 
72
72
  def store_key(path, key)
@@ -56,7 +56,7 @@ module GoogleAPI
56
56
  private
57
57
 
58
58
  def event(event_options)
59
- validate_event_options(event_options)
59
+ event_options.assert_valid_keys(VALID_EVENT_KEYS)
60
60
  event_options[:start] = date(event_options[:start])
61
61
  event_options[:end] = date(event_options[:end])
62
62
 
@@ -67,16 +67,5 @@ module GoogleAPI
67
67
  key = date&.is_a?(String) ? :date : :date_time
68
68
  Google::Apis::CalendarV3::EventDateTime.new(key => date, time_zone: ENV['TZ'])
69
69
  end
70
-
71
- def last_token_path
72
- path = %w[tmp run last_page_token]
73
- defined?(Rails) ? Rails.root.join(*path) : File.join(*path)
74
- end
75
-
76
- def validate_event_options(event_options)
77
- return unless event_options.respond_to?(:assert_valid_keys)
78
-
79
- event_options.assert_valid_keys(VALID_EVENT_KEYS)
80
- end
81
70
  end
82
71
  end
@@ -3,14 +3,16 @@
3
3
  module GoogleAPI
4
4
  class Calendar < GoogleAPI::Base
5
5
  module ClearTestCalendar
6
- def clear_test_calendar(page_token: nil, page_limit: 50, verbose: false)
6
+ def clear_test_calendar(page_token: nil, page_limit: 50, verbose: false, error: false)
7
+ raise Google::Apis::RateLimitError, '(Rate Limit Exceeded)' if error
8
+
7
9
  @verbose = verbose
8
10
  Google::Apis.logger.level = Logger::WARN
9
11
  choose_page_token(page_token)
10
12
  loop_over_pages(ENV['GOOGLE_CALENDAR_ID_TEST'], page_limit: page_limit)
11
13
  puts '*** Cleared all events!' if @verbose
12
14
  rescue Google::Apis::RateLimitError
13
- puts "\n\n*** Google::Apis::RateLimitError (Rate Limit Exceeded)"
15
+ puts "\n\n*** Google::Apis::RateLimitError (Rate Limit Exceeded)" if @verbose
14
16
  ensure
15
17
  log_last_page_token if token?
16
18
  end
@@ -58,10 +60,14 @@ module GoogleAPI
58
60
  end
59
61
 
60
62
  def progress_bar(total)
61
- ProgressBar.create(
63
+ bar_config = {
62
64
  title: 'Page cleared', starting_at: 0, total: total, progress_mark: ' ',
63
65
  remainder_mark: "\u{FF65}", format: "%a [%R/sec] %E | %b\u{15E7}%i %c/%C (%P%%) %t"
64
- )
66
+ }
67
+
68
+ bar_config = bar_config.merge(output: ProgressBar::Silent) if ENV.key?('HIDE_PROGRESS_BARS')
69
+
70
+ ProgressBar.create(bar_config)
65
71
  end
66
72
  end
67
73
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleAPI
4
+ module Configured
5
+ require 'google_api/configured/calendar'
6
+ require 'google_api/configured/group'
7
+ end
8
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleAPI
4
+ module Configured
5
+ class Calendar
6
+ CALENDAR_API ||= GoogleAPI::Calendar.new
7
+
8
+ attr_reader :calendar_id
9
+
10
+ def initialize(calendar_id)
11
+ @calendar_id = calendar_id
12
+ end
13
+
14
+ def list(max_results: 2500, page_token: nil)
15
+ CALENDAR_API.list(calendar_id, max_results: max_results, page_token: page_token)
16
+ end
17
+
18
+ def create(event_options = {})
19
+ CALENDAR_API.create(calendar_id, event_options)
20
+ end
21
+
22
+ def get(event_id)
23
+ CALENDAR_API.get(calendar_id, event_id)
24
+ end
25
+
26
+ def update(event_id, event_options = {})
27
+ CALENDAR_API.update(calendar_id, event_id, event_options)
28
+ end
29
+
30
+ def delete(event_id)
31
+ CALENDAR_API.delete(calendar_id, event_id)
32
+ end
33
+
34
+ def permit(user = nil, email: nil)
35
+ CALENDAR_API.permit(calendar_id, user, email: email)
36
+ end
37
+
38
+ def unpermit(user = nil, calendar_rule_id: nil)
39
+ CALENDAR_API.unpermit(calendar_id, user, calendar_rule_id: calendar_rule_id)
40
+ end
41
+
42
+ def clear_test_calendar(page_token: nil, page_limit: 50, verbose: false, error: false)
43
+ CALENDAR_API.clear_test_calendar(
44
+ page_token: page_token, page_limit: page_limit, verbose: verbose, error: error
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleAPI
4
+ module Configured
5
+ class Group
6
+ GROUP_API ||= GoogleAPI::Group.new
7
+
8
+ attr_reader :group_id
9
+
10
+ def initialize(group_id)
11
+ @group_id = group_id
12
+ end
13
+
14
+ def get
15
+ GROUP_API.get(group_id)
16
+ end
17
+
18
+ def members
19
+ GROUP_API.members(group_id)
20
+ end
21
+
22
+ def add(email)
23
+ GROUP_API.add(group_id, email)
24
+ end
25
+
26
+ def remove(email)
27
+ GROUP_API.remove(group_id, email)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,27 +4,26 @@ module GoogleAPI
4
4
  class Group < GoogleAPI::Base
5
5
  SERVICE_CLASS = Google::Apis::AdminDirectoryV1::DirectoryService
6
6
 
7
- def initialize(id, auth: true)
8
- @group_id = id
7
+ def initialize(auth: true)
9
8
  super(auth: auth)
10
9
  end
11
10
 
12
- def get
13
- call(:get_group, @group_id)
11
+ def get(group_id)
12
+ call(:get_group, group_id)
14
13
  end
15
14
 
16
- def members
17
- call(:list_members, @group_id)
15
+ def members(group_id)
16
+ call(:list_members, group_id)
18
17
  end
19
18
 
20
- def add(email)
21
- call(:insert_member, @group_id, member(email))
19
+ def add(group_id, email)
20
+ call(:insert_member, group_id, member(email))
22
21
  rescue Google::Apis::ClientError
23
22
  :already_exists
24
23
  end
25
24
 
26
- def remove(email)
27
- call(:delete_member, @group_id, email)
25
+ def remove(group_id, email)
26
+ call(:delete_member, group_id, email)
28
27
  rescue Google::Apis::ClientError
29
28
  :not_found
30
29
  end
@@ -10,4 +10,24 @@ RSpec.describe GoogleAPI::Base do
10
10
  NameError, 'uninitialized constant GoogleAPI::Base::SERVICE_CLASS'
11
11
  )
12
12
  end
13
+
14
+ context 'with a valid subclass' do
15
+ subject { GoogleAPI::Calendar }
16
+
17
+ it 'returns the correct last token path' do
18
+ expect(subject.new.send(:last_token_path)).to eql('./tmp/run/last_page_token')
19
+ end
20
+
21
+ it 'returns an array from authorize with reveal' do
22
+ expect(subject.new(auth: false).authorize!(reveal: true)).to be_a(Array)
23
+ end
24
+
25
+ let(:reauth) { proc(subject.new(auth: false).authorize!(refresh: true)) }
26
+
27
+ it 'reauthorizes' do
28
+ silently do
29
+ expect { reauth.call }.to raise_error(Signet::AuthorizationError)
30
+ end
31
+ end
32
+ end
13
33
  end
@@ -3,73 +3,130 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe GoogleAPI::Calendar do
6
- subject { described_class.new }
7
-
8
- it 'has a service class' do
9
- expect { subject.send(:service_class) }.not_to raise_error
6
+ def test_event
7
+ {
8
+ summary: 'API Test Event',
9
+ description: 'This is a test event generated by the API gem.',
10
+ start: DateTime.strptime('201906051200', '%Y%m%d%H%M'),
11
+ end: DateTime.strptime('201906051400', '%Y%m%d%H%M')
12
+ }
10
13
  end
11
14
 
12
- it 'has the correct service class' do
13
- expect(subject.send(:service_class)).to eql(Google::Apis::CalendarV3::CalendarService)
15
+ describe 'service class' do
16
+ subject { described_class.new }
17
+
18
+ it 'does not raise an error' do
19
+ expect { subject.send(:service_class) }.not_to raise_error
20
+ end
21
+
22
+ it 'is the correct class' do
23
+ expect(subject.send(:service_class)).to eql(Google::Apis::CalendarV3::CalendarService)
24
+ end
14
25
  end
15
26
 
16
- describe 'list' do
17
- it 'returns not found for a nonexistent calendar' do
18
- expect { subject.list('not-a-calendar') }.to raise_error(
27
+ context 'with an invalid calendar' do
28
+ let(:test_cal_id) { 'not-a-calendar' }
29
+
30
+ subject { GoogleAPI::Configured::Calendar.new(test_cal_id) }
31
+
32
+ it 'returns not found from list' do
33
+ expect { subject.list }.to raise_error(
19
34
  Google::Apis::ClientError, 'notFound: Not Found'
20
35
  )
21
36
  end
22
- end
23
37
 
24
- describe 'create' do
25
- it 'returns not found for a nonexistent calendar' do
26
- expect { subject.create('not-a-calendar') }.to raise_error(
38
+ it 'returns not found from create' do
39
+ expect { subject.create }.to raise_error(
27
40
  Google::Apis::ClientError, 'notFound: Not Found'
28
41
  )
29
42
  end
30
- end
31
43
 
32
- describe 'get' do
33
- it 'returns not found for a nonexistent calendar' do
34
- expect { subject.get('not-a-calendar', 'not-an-event') }.to raise_error(
44
+ it 'returns not found from get' do
45
+ expect { subject.get('not-an-event') }.to raise_error(
35
46
  Google::Apis::ClientError, 'notFound: Not Found'
36
47
  )
37
48
  end
38
- end
39
49
 
40
- describe 'update' do
41
- it 'returns not found for a nonexistent calendar' do
42
- expect { subject.update('not-a-calendar', 'not-an-event') }.to raise_error(
50
+ it 'returns not found from update' do
51
+ expect { subject.update('not-an-event') }.to raise_error(
43
52
  Google::Apis::ClientError, 'notFound: Not Found'
44
53
  )
45
54
  end
46
- end
47
55
 
48
- describe 'delete' do
49
- it 'returns event not found for a nonexistent calendar' do
50
- expect(subject.delete('not-a-calendar', 'not-an-event')).to eql(
56
+ it 'returns event not found from delete' do
57
+ expect(subject.delete('not-an-event')).to eql(
51
58
  :event_not_found
52
59
  )
53
60
  end
54
- end
55
61
 
56
- describe 'permit' do
57
- it 'returns nil for a nonexistent calendar' do
58
- expect(subject.permit('not-a-calendar', email: 'not-a-user')).to be_nil
62
+ it 'returns nil from permit' do
63
+ expect(subject.permit(email: 'not-a-user')).to be_nil
59
64
  end
60
- end
61
65
 
62
- describe 'unpermit' do
63
- it 'returns permission not found for a nonexistent calendar' do
64
- expect(subject.unpermit('not-a-calendar', calendar_rule_id: 'not-a-user')).to eql(
65
- :permission_not_found
66
- )
66
+ it 'returns permission not found from unpermit' do
67
+ expect(subject.unpermit(calendar_rule_id: 'not-a-user')).to eql(:permission_not_found)
67
68
  end
68
69
  end
69
70
 
70
- describe 'clear test calendar' do
71
- it 'does not raise any errors' do
72
- expect { subject.clear_test_calendar }.not_to raise_error
71
+ context 'with a valid calendar' do
72
+ let(:test_cal_id) { ENV['GOOGLE_CALENDAR_ID_TEST'] }
73
+
74
+ subject { GoogleAPI::Configured::Calendar.new(test_cal_id) }
75
+
76
+ it 'returns a list' do
77
+ expect(subject.list).to be_a(Google::Apis::CalendarV3::Events)
78
+ end
79
+
80
+ it 'creates an event' do
81
+ expect(subject.create(test_event)).to be_a(Google::Apis::CalendarV3::Event)
82
+ end
83
+
84
+ it 'gets an event ' do
85
+ event = subject.create(test_event)
86
+ expect(subject.get(event.id)).to be_a(Google::Apis::CalendarV3::Event)
87
+ end
88
+
89
+ it 'updates an event' do
90
+ event = subject.create(test_event)
91
+ updated_test_event = test_event.merge(description: 'Updated.')
92
+ subject.update(event.id, updated_test_event)
93
+ updated_event = subject.get(event.id)
94
+
95
+ expect(updated_event.description).to eql('Updated.')
96
+ end
97
+
98
+ it 'deletes an event' do
99
+ event = subject.create(test_event)
100
+
101
+ expect(subject.delete(event.id)).to eql('')
102
+ end
103
+
104
+ it 'returns nil from permit' do
105
+ expect(subject.permit(email: 'not-a-user')).to be_nil
106
+ end
107
+
108
+ it 'returns permission not found from unpermit' do
109
+ expect(subject.unpermit(calendar_rule_id: 'not-a-user')).to eql(:permission_not_found)
110
+ end
111
+
112
+ describe 'clear test calendar' do
113
+ it 'does not raise any errors' do
114
+ expect { subject.clear_test_calendar }.not_to raise_error
115
+ end
116
+
117
+ it 'rescues from an unhandled rate limit exception' do
118
+ expect { subject.clear_test_calendar(error: true) }.not_to raise_error
119
+ end
120
+
121
+ it 'does not raise any errors with verbose' do
122
+ subject.create(test_event)
123
+
124
+ silently do
125
+ expect do
126
+ GoogleAPI::Configured::Calendar.new('test').clear_test_calendar(verbose: true)
127
+ end.not_to raise_error
128
+ end
129
+ end
73
130
  end
74
131
  end
75
132
  end
@@ -3,41 +3,47 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe GoogleAPI::Group do
6
- subject { described_class.new('test-group@example.com') }
6
+ describe 'service class' do
7
+ subject { described_class.new }
7
8
 
8
- it 'has a service class' do
9
- expect { subject.send(:service_class) }.not_to raise_error
10
- end
9
+ it 'has a service class' do
10
+ expect { subject.send(:service_class) }.not_to raise_error
11
+ end
11
12
 
12
- it 'has the correct service class' do
13
- expect(subject.send(:service_class)).to eql(Google::Apis::AdminDirectoryV1::DirectoryService)
13
+ it 'has the correct service class' do
14
+ expect(subject.send(:service_class)).to eql(Google::Apis::AdminDirectoryV1::DirectoryService)
15
+ end
14
16
  end
15
17
 
16
- describe 'get' do
17
- it 'returns not found for a nonexistent group' do
18
- expect { subject.get }.to raise_error(
19
- Google::Apis::ClientError, 'forbidden: Not Authorized to access this resource/api'
20
- )
18
+ context 'with an invalid group' do
19
+ subject { GoogleAPI::Configured::Group.new('test-group@example.com') }
20
+
21
+ describe 'get' do
22
+ it 'returns not found for a nonexistent group' do
23
+ expect { subject.get }.to raise_error(
24
+ Google::Apis::ClientError, 'forbidden: Not Authorized to access this resource/api'
25
+ )
26
+ end
21
27
  end
22
- end
23
28
 
24
- describe 'members' do
25
- it 'returns forbidden for a nonexistent group' do
26
- expect { subject.members }.to raise_error(
27
- Google::Apis::ClientError, 'forbidden: Not Authorized to access this resource/api'
28
- )
29
+ describe 'members' do
30
+ it 'returns forbidden for a nonexistent group' do
31
+ expect { subject.members }.to raise_error(
32
+ Google::Apis::ClientError, 'forbidden: Not Authorized to access this resource/api'
33
+ )
34
+ end
29
35
  end
30
- end
31
36
 
32
- describe 'add' do
33
- it 'returns not found for a nonexistent group' do
34
- expect(subject.add('test-member@example.com')).to eql(:already_exists)
37
+ describe 'add' do
38
+ it 'returns not found for a nonexistent group' do
39
+ expect(subject.add('test-member@example.com')).to eql(:already_exists)
40
+ end
35
41
  end
36
- end
37
42
 
38
- describe 'remove' do
39
- it 'returns not found for a nonexistent group' do
40
- expect(subject.remove('test-member@example.com')).to eql(:not_found)
43
+ describe 'remove' do
44
+ it 'returns not found for a nonexistent group' do
45
+ expect(subject.remove('test-member@example.com')).to eql(:not_found)
46
+ end
41
47
  end
42
48
  end
43
49
  end
data/spec/spec_helper.rb CHANGED
@@ -5,12 +5,25 @@ Bundler.setup
5
5
  require 'simplecov'
6
6
  SimpleCov.start do
7
7
  add_filter '/spec'
8
+ add_filter '/lib/ext'
8
9
  end
10
+ SimpleCov.minimum_coverage(100)
9
11
 
10
12
  require 'google_api'
11
13
 
14
+ def silently
15
+ original_stdout = $stdout
16
+ $stdout = File.new(File.join('tmp', 'null'), 'w')
17
+ yield
18
+ $stdout = original_stdout
19
+ end
20
+
12
21
  RSpec.configure do |config|
13
22
  config.before(:suite) do
14
- FileUtils.mkdir_p('tmp/run')
23
+ FileUtils.mkdir_p(File.join('tmp', 'run'))
24
+ FileUtils.rm(Dir.glob(File.join('config', 'keys', '*')))
25
+
26
+ ENV['GOOGLE_AUTHORIZATION_CODE'] = 'test-auth-code'
27
+ ENV['HIDE_PROGRESS_BARS'] = 'true'
15
28
  end
16
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bps-google-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
@@ -120,11 +120,16 @@ files:
120
120
  - Gemfile.lock
121
121
  - Readme.md
122
122
  - bps-google-api.gemspec
123
+ - lib/ext/hash.rb
124
+ - lib/ext/silent_progress_bar.rb
123
125
  - lib/google_api.rb
124
126
  - lib/google_api/base.rb
125
127
  - lib/google_api/base/authorization.rb
126
128
  - lib/google_api/calendar.rb
127
129
  - lib/google_api/calendar/clear_test_calendar.rb
130
+ - lib/google_api/configured.rb
131
+ - lib/google_api/configured/calendar.rb
132
+ - lib/google_api/configured/group.rb
128
133
  - lib/google_api/group.rb
129
134
  - spec/.rubocop.yml
130
135
  - spec/lib/google_api/base_spec.rb