bps-google-api 0.0.6 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf5b7317c0e70c4602222332313db3921c89c60d868c87394fcbab4d1d366519
4
- data.tar.gz: 7662a0d33e7cfbcf6d0a48245ba549b14ee43cbcb9f3b0ec8808c3526482b19c
3
+ metadata.gz: 5ce9cad16163eed7195522f8af72a9ade306810c5b8681fc9021e0d88a73ad09
4
+ data.tar.gz: c0a75ead0679df9029efc37af6ffcccf5d54e0bb92d7a20c074fa65ddf5e8ac6
5
5
  SHA512:
6
- metadata.gz: a0087705245ea9279cd4d78e298273802f193dd255c74a95584875d24e65618dadd8dcf4837501ae701abbb892c9f0d814e25c17f61e2b98bc31d37a61681cd3
7
- data.tar.gz: dccc80c7769f29d7f4ab2b28255d25a4e2f80c11edd569488ad0b986d1d74c41a681dc8d4f0a6af4df6ff06545aed253a5190369ac292b8dfd685a2ddd2d10be
6
+ metadata.gz: 9a1a4fc67ab0d2906af307e00f411e28dee8e958518ba8dc6aee94171d3f5532960d12ece74ca1a8cfbbdc67241803379018df3e6b0d023aef88ccf6aabc1f07
7
+ data.tar.gz: '01429a10a6c172bb06e18877d24593e12def6ca3ba130acb18db7101f0bab529e93ae9dd2585f03892547a4c75727833acee796cd3a42809fea2c253fc82d7d4'
data/.rubocop.yml ADDED
@@ -0,0 +1,83 @@
1
+ require:
2
+ - rubocop-rspec
3
+ - rubocop-performance
4
+ AllCops:
5
+ TargetRubyVersion: 2.5
6
+ Exclude:
7
+ - bin/**/*
8
+ - config/**/*
9
+ - db/**/*
10
+ - vendor/**/*
11
+ - tmp/**/*
12
+
13
+ Layout/IndentFirstHashElement:
14
+ EnforcedStyle: consistent
15
+ Layout/AccessModifierIndentation:
16
+ EnforcedStyle: outdent
17
+ Layout/EmptyLinesAroundAccessModifier:
18
+ Enabled: true
19
+ Layout/AlignArray:
20
+ Enabled: true
21
+ Layout/AlignHash:
22
+ Enabled: true
23
+ Layout/EmptyLineAfterGuardClause:
24
+ Enabled: true
25
+ Layout/SpaceInsideBlockBraces:
26
+ EnforcedStyle: space
27
+ EnforcedStyleForEmptyBraces: no_space
28
+ Layout/SpaceInsideHashLiteralBraces:
29
+ EnforcedStyle: space
30
+ EnforcedStyleForEmptyBraces: no_space
31
+ Layout/SpaceInsideArrayLiteralBrackets:
32
+ EnforcedStyle: no_space
33
+
34
+ Lint/UnusedMethodArgument:
35
+ Enabled: true
36
+ Lint/UselessAssignment:
37
+ Enabled: true
38
+
39
+ Metrics/LineLength:
40
+ Max: 100
41
+ Metrics/MethodLength:
42
+ Enabled: true
43
+ Metrics/ClassLength:
44
+ Enabled: true
45
+ Max: 125
46
+ Metrics/ModuleLength:
47
+ Max: 125
48
+ Metrics/ParameterLists:
49
+ Enabled: true
50
+ Metrics/CyclomaticComplexity:
51
+ Enabled: true
52
+ Metrics/AbcSize:
53
+ Enabled: true
54
+
55
+ Naming/MemoizedInstanceVariableName:
56
+ Enabled: false
57
+ Naming/UncommunicativeMethodParamName:
58
+ Enabled: false
59
+
60
+ Rails/InverseOf:
61
+ Enabled: true
62
+
63
+ Style/Documentation:
64
+ Enabled: false
65
+ Style/FrozenStringLiteralComment:
66
+ Enabled: true
67
+ Style/NumericLiterals:
68
+ Enabled: true
69
+ Style/StringLiterals:
70
+ EnforcedStyle: single_quotes
71
+ Style/AndOr:
72
+ Enabled: true
73
+ Style/ClassCheck:
74
+ Enabled: true
75
+ Style/GuardClause:
76
+ Enabled: true
77
+
78
+ Security/Eval:
79
+ Enabled: true
80
+ Security/JSONLoad:
81
+ Enabled: true
82
+ Security/YAMLLoad:
83
+ Enabled: true
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
  gemspec
data/Readme.md CHANGED
@@ -32,16 +32,16 @@ GOOGLE_ACCESS_TOKEN
32
32
  GOOGLE_REFRESH_TOKEN
33
33
  GOOGLE_AUTH_EXP
34
34
 
35
- GOOGLE_AUTH_SCOPE_CALENDAR
36
- GOOGLE_AUTH_SCOPE_GROUP
37
-
38
- GOOGLE_CALENDAR_ID_GEN
39
- GOOGLE_CALENDAR_ID_EDUC
40
35
  GOOGLE_CALENDAR_ID_TEST
36
+
37
+ TZ # Timezone
41
38
  ```
42
39
 
43
40
  ## Usage
44
41
 
42
+ If no configuration is available, `.new` will automatically run `.authorize!`
43
+ and return a URL to generate an authorization token.
44
+
45
45
  ```ruby
46
46
  calendar = GoogleAPI::Calendar.new
47
47
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Gem::Specification.new do |s|
2
4
  s.name = 'bps-google-api'
3
- s.version = '0.0.6'
4
- s.date = '2019-04-11'
5
+ s.version = '0.1.0'
6
+ s.date = '2019-06-15'
5
7
  s.summary = 'Configured Google API'
6
8
  s.description = 'A configured Google API wrapper.'
7
9
  s.homepage = 'http://rubygems.org/gems/bps-google-api'
@@ -11,8 +13,8 @@ Gem::Specification.new do |s|
11
13
  s.require_paths = %w[lib]
12
14
  s.files = `git ls-files`.split("\n")
13
15
 
14
- s.add_runtime_dependency 'google-api-client', '~> 0.23.4'
15
16
  s.add_runtime_dependency 'exp_retry', '~> 0.0.8'
16
- s.add_runtime_dependency 'ruby-progressbar', '~> 1.10'
17
17
  s.add_runtime_dependency 'fileutils', '~> 1.2'
18
+ s.add_runtime_dependency 'google-api-client', '~> 0.23.4'
19
+ s.add_runtime_dependency 'ruby-progressbar', '~> 1.10'
18
20
  end
@@ -2,26 +2,31 @@
2
2
 
3
3
  module GoogleAPI
4
4
  class Base
5
- include GoogleAPI::Concerns::Base::Authorization
5
+ RETRIES ||= [
6
+ Google::Apis::TransmissionError, Google::Apis::ServerError,
7
+ Google::Apis::RateLimitError, Errno::ECONNRESET
8
+ ].freeze
6
9
 
7
- def initialize(auth: true)
8
- self.authorize! if auth
9
- end
10
+ include GoogleAPI::Base::Authorization
10
11
 
11
- def self.root_path
12
- defined?(Rails) ? Rails.root : './'
12
+ def initialize(auth: true)
13
+ authorize! if auth
13
14
  end
14
15
 
15
16
  private
16
17
 
18
+ def service_class
19
+ self.class::SERVICE_CLASS
20
+ end
21
+
17
22
  def service
18
23
  raise 'No service class defined.' unless defined?(service_class)
19
24
 
20
25
  @service ||= service_class.new
21
26
  end
22
27
 
23
- def root_path
24
- self.class.root_path
28
+ def call(method, *args)
29
+ ExpRetry.for(exception: RETRIES) { service.send(method, *args) }
25
30
  end
26
31
  end
27
32
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleAPI
4
+ class Base
5
+ module Authorization
6
+ OOB_URI ||= 'urn:ietf:wg:oauth:2.0:oob'
7
+ AUTH_SCOPES ||= [
8
+ Google::Apis::AdminDirectoryV1::AUTH_ADMIN_DIRECTORY_GROUP,
9
+ Google::Apis::CalendarV3::AUTH_CALENDAR
10
+ ].freeze
11
+ TOKEN_SCOPES ||= [
12
+ '"https://www.googleapis.com/auth/admin.directory.group"',
13
+ '"https://www.googleapis.com/auth/calendar"'
14
+ ].freeze
15
+
16
+ def authorize!(refresh: false, reveal: false)
17
+ token_file
18
+ auth = authorize(refresh: refresh)
19
+ service.authorization = auth
20
+ return true unless reveal
21
+
22
+ [auth, auth_keys(auth)]
23
+ end
24
+
25
+ private
26
+
27
+ def authorize(user_id = 'default', refresh: false)
28
+ @credentials = authorizer.get_credentials(user_id)
29
+ return @credentials unless @credentials.nil? || refresh
30
+
31
+ @credentials = authorizer.get_and_store_credentials_from_code(
32
+ user_id: user_id, code: request_authorization, base_url: OOB_URI
33
+ )
34
+ end
35
+
36
+ def request_authorization
37
+ url = authorizer.get_authorization_url(base_url: OOB_URI)
38
+ puts("Open this URL to authorize:\n", url)
39
+ print("\nResponse code: ")
40
+ gets
41
+ end
42
+
43
+ def authorizer
44
+ @authorizer ||= Google::Auth::UserAuthorizer.new(
45
+ auth_client_id, AUTH_SCOPES, auth_token_store
46
+ )
47
+ end
48
+
49
+ def auth_client_id
50
+ client_id_file
51
+ Google::Auth::ClientId.from_hash(
52
+ JSON.parse(File.read('config/keys/google_api_client.json'))
53
+ )
54
+ end
55
+
56
+ def auth_token_store
57
+ Google::Auth::Stores::FileTokenStore.new(file: 'config/keys/google_token.yaml')
58
+ end
59
+
60
+ def auth_keys(auth)
61
+ {
62
+ GOOGLE_CLIENT_ID: auth.client_id, GOOGLE_CLIENT_SECRET: auth.client_secret,
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'])
65
+ }
66
+ end
67
+
68
+ def expires_milli(time)
69
+ DateTime.strptime(time, '%Y-%m-%dT%H:%M:%S.%L%:z').to_i * 1000
70
+ end
71
+
72
+ def store_key(path, key)
73
+ return if File.exist?(path)
74
+
75
+ File.open(path, 'w+') do |f|
76
+ File.chmod(0o600, f)
77
+ block_given? ? yield(f) : f.write(key)
78
+ end
79
+ end
80
+
81
+ def client_id_file
82
+ store_key(
83
+ File.join(Rails.root, 'config/keys/google_api_client.json'),
84
+ <<~KEY
85
+ {"installed":{"client_id":"#{ENV['GOOGLE_CLIENT_ID']}","project_id":"charming-scarab-208718",
86
+ "auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token",
87
+ "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"#{ENV['GOOGLE_CLIENT_SECRET']}",
88
+ "redirect_uris":["#{OOB_URI}","http://localhost"]}}
89
+ KEY
90
+ )
91
+ end
92
+
93
+ def token_file
94
+ store_key(
95
+ File.join(Rails.root, 'config/keys/google_token.yaml'),
96
+ <<~KEY
97
+ ---
98
+ default: '{"client_id":"#{ENV['GOOGLE_CLIENT_ID']}","access_token":"#{ENV['GOOGLE_ACCESS_TOKEN']}",
99
+ "refresh_token":"#{ENV['GOOGLE_REFRESH_TOKEN']}","scope":[#{TOKEN_SCOPES.join(',')}],
100
+ "expiration_time_millis":#{ENV['GOOGLE_AUTH_EXP']}}'
101
+ KEY
102
+ )
103
+ end
104
+ end
105
+ end
106
+ end
@@ -2,54 +2,66 @@
2
2
 
3
3
  module GoogleAPI
4
4
  class Calendar < GoogleAPI::Base
5
- include GoogleAPI::Concerns::Calendar::ClearTestCalendar
6
- include GoogleAPI::Concerns::Calendar::Permission
5
+ include GoogleAPI::Calendar::ClearTestCalendar
7
6
 
8
- LAST_TOKEN_PATH ||= "#{root_path}/tmp/run/last_page_token"
7
+ SERVICE_CLASS = Google::Apis::CalendarV3::CalendarService
8
+ LAST_TOKEN_PATH ||= Rails.root.join('tmp', 'run', 'last_page_token')
9
+ VALID_EVENT_KEYS ||= %i[
10
+ summary start end description location recurrence conference_data conference_data_version
11
+ ].freeze
9
12
 
10
13
  def create(calendar_id, event_options = {})
11
- service.insert_event(calendar_id, event(event_options), conference_data_version: 1)
14
+ call(:insert_event, calendar_id, event(event_options), conference_data_version: 1)
12
15
  end
13
16
 
14
17
  def list(calendar_id, max_results: 2500, page_token: nil)
15
- service.list_events(calendar_id, max_results: max_results, page_token: page_token)
18
+ call(:list_events, calendar_id, max_results: max_results, page_token: page_token)
16
19
  end
17
20
 
18
21
  def get(calendar_id, event_id)
19
- service.get_event(calendar_id, event_id)
22
+ call(:get_event, calendar_id, event_id)
20
23
  end
21
24
 
22
25
  def update(calendar_id, event_id, event_options = {})
23
- service.update_event(calendar_id, event_id, event(event_options))
26
+ call(:update_event, calendar_id, event_id, event(event_options))
24
27
  end
25
28
 
26
29
  def delete(calendar_id, event_id)
27
- service.delete_event(calendar_id, event_id)
30
+ call(:delete_event, calendar_id, event_id)
28
31
  rescue Google::Apis::ClientError
29
32
  :event_not_found
30
33
  end
31
34
 
32
- private
35
+ def permit(calendar, user)
36
+ rule = Google::Apis::CalendarV3::AclRule.new(
37
+ scope: { type: 'user', value: user.email }, role: 'writer'
38
+ )
39
+
40
+ result = call(:insert_acl, calendar, rule)
41
+ user.update(calendar_rule_id: result.id)
42
+ end
33
43
 
34
- def service_class
35
- Google::Apis::CalendarV3::CalendarService
44
+ def unpermit(calendar, user)
45
+ call(:delete_acl, calendar, user&.calendar_rule_id)
46
+ rescue Google::Apis::ClientError
47
+ :permission_not_found
48
+ ensure
49
+ user.update(calendar_rule_id: nil)
36
50
  end
37
51
 
52
+ private
53
+
38
54
  def event(event_options)
39
- event_options.assert_valid_keys(valid_event_keys)
55
+ event_options.assert_valid_keys(VALID_EVENT_KEYS)
40
56
  event_options[:start] = date(event_options[:start])
41
57
  event_options[:end] = date(event_options[:end])
42
58
 
43
59
  Google::Apis::CalendarV3::Event.new(event_options.reject { |_, v| v.nil? })
44
60
  end
45
61
 
46
- def valid_event_keys
47
- %i[summary start end description location recurrence conference_data conference_data_version]
48
- end
49
-
50
62
  def date(date)
51
63
  key = date&.is_a?(String) ? :date : :date_time
52
- Google::Apis::CalendarV3::EventDateTime.new(key => date, time_zone: 'America/Detroit')
64
+ Google::Apis::CalendarV3::EventDateTime.new(key => date, time_zone: ENV['TZ'])
53
65
  end
54
66
  end
55
67
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleAPI
4
+ class Calendar
5
+ module ClearTestCalendar
6
+ def clear_test_calendar(page_token: nil, page_limit: 50)
7
+ Google::Apis.logger.level = Logger::WARN
8
+ choose_page_token(page_token)
9
+ loop_over_pages(ENV['GOOGLE_CALENDAR_ID_TEST'], page_limit: page_limit)
10
+ puts '*** Cleared all events!'
11
+ rescue Google::Apis::RateLimitError
12
+ puts "\n\n*** Google::Apis::RateLimitError (Rate Limit Exceeded)"
13
+ ensure
14
+ log_last_page_token unless @page_token.blank?
15
+ end
16
+
17
+ private
18
+
19
+ def choose_page_token(page_token)
20
+ last_token = GoogleAPI::Calendar::LAST_TOKEN_PATH
21
+ @page_token ||= File.read(last_token) if File.exist?(last_token)
22
+ @page_token = page_token if page_token.present?
23
+ end
24
+
25
+ def loop_over_pages(cal_id, page_limit: 50)
26
+ puts "*** Starting with page token: #{@page_token}" if @page_token.present?
27
+
28
+ page_limit -= 1 while (@page_token = clear_page(cal_id)) && page_limit.positive?
29
+ end
30
+
31
+ def clear_page(cal_id)
32
+ response = list(cal_id, page_token: @page_token)
33
+ clear_events_from_page(cal_id, response.items) unless response.items.blank?
34
+ response.next_page_token
35
+ end
36
+
37
+ def clear_events_from_page(cal_id, items)
38
+ puts "*** Page token: #{@page_token}"
39
+ pb = progress_bar(items.count)
40
+ items&.each_with_index do |event, _index|
41
+ ExpRetry.for(exception: Calendar::RETRIES) do
42
+ delete(cal_id, event.id)
43
+ pb.increment
44
+ end
45
+ end
46
+ end
47
+
48
+ def log_last_page_token
49
+ puts "\n\n*** Last page token cleared: #{@page_token}"
50
+ File.open(GoogleAPI::Calendar::LAST_TOKEN_PATH, 'w+') do |f|
51
+ f.write(@page_token)
52
+ end
53
+ puts "\n*** Token stored in #{GoogleAPI::Calendar::LAST_TOKEN_PATH}"
54
+ end
55
+
56
+ def progress_bar(total)
57
+ ProgressBar.create(
58
+ title: 'Page cleared', starting_at: 0, total: total, progress_mark: ' ',
59
+ remainder_mark: "\u{FF65}", format: "%a [%R/sec] %E | %b\u{15E7}%i %c/%C (%P%%) %t"
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
@@ -2,37 +2,35 @@
2
2
 
3
3
  module GoogleAPI
4
4
  class Group < GoogleAPI::Base
5
- def initialize(id, auth: false)
5
+ SERVICE_CLASS = Google::Apis::AdminDirectoryV1::DirectoryService
6
+
7
+ def initialize(id, auth: true)
6
8
  @group_id = id
7
9
  super(auth: auth)
8
10
  end
9
11
 
10
12
  def get
11
- service.get_group(@group_id)
13
+ call(:get_group, @group_id)
12
14
  end
13
15
 
14
16
  def members
15
- service.list_members(@group_id)
17
+ call(:list_members, @group_id)
16
18
  end
17
19
 
18
20
  def add(email)
19
- service.insert_member(@group_id, member(email))
20
- rescue Google::Apis::ClientError, 'duplicate: Member already exists.'
21
+ call(:insert_member, @group_id, member(email))
22
+ rescue Google::Apis::ClientError
21
23
  :already_exists
22
24
  end
23
25
 
24
26
  def remove(email)
25
- service.delete_member(@group_id, email)
26
- rescue Google::Apis::ClientError, '(required: Missing required field: memberKey)'
27
+ call(:delete_member, @group_id, email)
28
+ rescue Google::Apis::ClientError
27
29
  :not_found
28
30
  end
29
31
 
30
32
  private
31
33
 
32
- def service_class
33
- Google::Apis::AdminDirectoryV1::DirectoryService
34
- end
35
-
36
34
  def member(email)
37
35
  Google::Apis::AdminDirectoryV1::Member.new(email: email)
38
36
  end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bps-google-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-11 00:00:00.000000000 Z
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: google-api-client
14
+ name: exp_retry
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.23.4
19
+ version: 0.0.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.23.4
26
+ version: 0.0.8
27
27
  - !ruby/object:Gem::Dependency
28
- name: exp_retry
28
+ name: fileutils
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.8
33
+ version: '1.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.8
40
+ version: '1.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: ruby-progressbar
42
+ name: google-api-client
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.10'
47
+ version: 0.23.4
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.10'
54
+ version: 0.23.4
55
55
  - !ruby/object:Gem::Dependency
56
- name: fileutils
56
+ name: ruby-progressbar
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.2'
61
+ version: '1.10'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.2'
68
+ version: '1.10'
69
69
  description: A configured Google API wrapper.
70
70
  email: julian@fiander.one
71
71
  executables: []
@@ -73,17 +73,16 @@ extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
75
  - ".gitignore"
76
+ - ".rubocop.yml"
76
77
  - Gemfile
77
78
  - Gemfile.lock
78
79
  - Readme.md
79
80
  - bps-google-api.gemspec
80
81
  - lib/google_api.rb
81
82
  - lib/google_api/base.rb
83
+ - lib/google_api/base/authorization.rb
82
84
  - lib/google_api/calendar.rb
83
- - lib/google_api/concerns.rb
84
- - lib/google_api/concerns/base/authorization.rb
85
- - lib/google_api/concerns/calendar/clear_test_calendar.rb
86
- - lib/google_api/concerns/calendar/permission.rb
85
+ - lib/google_api/calendar/clear_test_calendar.rb
87
86
  - lib/google_api/group.rb
88
87
  homepage: http://rubygems.org/gems/bps-google-api
89
88
  licenses:
@@ -104,7 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
103
  - !ruby/object:Gem::Version
105
104
  version: '0'
106
105
  requirements: []
107
- rubygems_version: 3.0.2
106
+ rubyforge_project:
107
+ rubygems_version: 2.7.6
108
108
  signing_key:
109
109
  specification_version: 4
110
110
  summary: Configured Google API
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GoogleAPI
4
- module Concerns
5
- module Base
6
- require 'google_api/concerns/base/authorization'
7
- end
8
-
9
- module Calendar
10
- require 'google_api/concerns/calendar/clear_test_calendar'
11
- require 'google_api/concerns/calendar/permission'
12
- end
13
- end
14
- end
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GoogleAPI::Concerns::Base
4
- module Authorization
5
- OOB_URI ||= 'urn:ietf:wg:oauth:2.0:oob'
6
- AUTH_SCOPES ||= [
7
- Google::Apis::AdminDirectoryV1::AUTH_ADMIN_DIRECTORY_GROUP,
8
- Google::Apis::CalendarV3::AUTH_CALENDAR
9
- ].freeze
10
-
11
- def authorize!(refresh: false, reveal: false)
12
- client_id_file
13
- token_file
14
-
15
- auth = authorize(refresh: refresh)
16
- service.authorization = auth
17
- return true unless reveal
18
-
19
- [auth, auth_keys(auth)]
20
- end
21
-
22
- private
23
-
24
- def authorize(user_id = 'default', refresh: false)
25
- @credentials = authorizer.get_credentials(user_id)
26
- return @credentials unless @credentials.nil? || refresh
27
-
28
- @credentials = authorizer.get_and_store_credentials_from_code(
29
- user_id: user_id, code: request_authorization, base_url: OOB_URI
30
- )
31
- end
32
-
33
- def request_authorization
34
- url = authorizer.get_authorization_url(base_url: OOB_URI)
35
- puts("Open this URL to authorize:\n", url)
36
- print("\nResponse code: ")
37
- gets
38
- end
39
-
40
- def authorizer
41
- @authorizer ||= Google::Auth::UserAuthorizer.new(auth_client_id, AUTH_SCOPES, auth_token_store)
42
- end
43
-
44
- def auth_client_id
45
- client_id_file
46
- Google::Auth::ClientId.from_hash(JSON.parse(File.read('config/keys/google_api_client.json')))
47
- end
48
-
49
- def auth_token_store
50
- Google::Auth::Stores::FileTokenStore.new(file: 'config/keys/google_token.yaml')
51
- end
52
-
53
- def auth_keys(auth)
54
- {
55
- GOOGLE_CLIENT_ID: auth.client_id, GOOGLE_CLIENT_SECRET: auth.client_secret,
56
- GOOGLE_ACCESS_TOKEN: auth.access_token, GOOGLE_REFRESH_TOKEN: auth.refresh_token,
57
- GOOGLE_AUTH_SCOPES: auth.scope, GOOGLE_AUTH_EXP: expires_milli(auth.as_json['expires_at'])
58
- }
59
- end
60
-
61
- def expires_milli(time)
62
- DateTime.strptime(time, '%Y-%m-%dT%H:%M:%S.%L%:z').to_i * 1000
63
- end
64
-
65
- def store_key(path, key)
66
- return if File.exist?(path)
67
-
68
- ensure_file(path)
69
- File.open(path, 'w+') do |f|
70
- File.chmod(0600, f)
71
- block_given? ? yield(f) : f.write(key)
72
- end
73
- end
74
-
75
- def ensure_file(path)
76
- path = path.split('/')
77
- file = path.pop
78
- path = path.join('/')
79
- FileUtils.mkdir_p(path)
80
- end
81
-
82
- def client_id_file
83
- store_key(
84
- File.join(root_path, 'config/keys/google_api_client.json'),
85
- <<~KEY
86
- {"installed":{"client_id":"#{ENV['GOOGLE_CLIENT_ID']}","project_id":"charming-scarab-208718",
87
- "auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token",
88
- "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"#{ENV['GOOGLE_CLIENT_SECRET']}",
89
- "redirect_uris":["#{OOB_URI}","http://localhost"]}}
90
- KEY
91
- )
92
- end
93
-
94
- def token_file
95
- store_key(
96
- File.join(root_path, 'config/keys/google_token.yaml'),
97
- <<~KEY
98
- ---
99
- default: '{"client_id":"#{ENV['GOOGLE_CLIENT_ID']}","access_token":"#{ENV['GOOGLE_ACCESS_TOKEN']}",
100
- "refresh_token":"#{ENV['GOOGLE_REFRESH_TOKEN']}","scope":[#{scopes}],
101
- "expiration_time_millis":#{ENV['GOOGLE_AUTH_EXP']}}'
102
- KEY
103
- )
104
- end
105
-
106
- def scopes
107
- ENV.select { |k, v| k =~ /GOOGLE_AUTH_SCOPE_/ }.values.map { |s| "\"#{s}\"" }.join(',')
108
- end
109
- end
110
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GoogleAPI::Concerns::Calendar
4
- module ClearTestCalendar
5
- RETRIABLE_EXCEPTIONS = [
6
- Google::Apis::RateLimitError,
7
- Google::Apis::TransmissionError
8
- ].freeze
9
-
10
- def clear_test_calendar(page_token: nil, page_limit: 50)
11
- Google::Apis.logger.level = Logger::WARN
12
- set_page_token(page_token)
13
- loop_over_pages(ENV['GOOGLE_CALENDAR_ID_TEST'], page_limit: page_limit)
14
- puts '*** Cleared all events!'
15
- rescue Google::Apis::RateLimitError
16
- puts "\n\n*** Google::Apis::RateLimitError (Rate Limit Exceeded)"
17
- ensure
18
- log_last_page_token unless @page_token.blank?
19
- end
20
-
21
- private
22
-
23
- def set_page_token(page_token)
24
- last_token = GoogleAPI::Calendar::LAST_TOKEN_PATH
25
- @page_token ||= File.read(last_token) if File.exist?(last_token)
26
- @page_token = page_token if page_token.present?
27
- end
28
-
29
- def loop_over_pages(cal_id, page_limit: 50)
30
- puts "*** Starting with page token: #{@page_token}" if @page_token.present?
31
-
32
- while (@page_token = clear_page(cal_id)) && page_limit.positive?
33
- page_limit -= 1
34
- end
35
- end
36
-
37
- def clear_page(cal_id)
38
- response = list(cal_id, page_token: @page_token)
39
- clear_events_from_page(cal_id, response.items) unless response.items.blank?
40
- response.next_page_token
41
- end
42
-
43
- def clear_events_from_page(cal_id, items)
44
- puts "*** Page token: #{@page_token}"
45
- pb = progress_bar(items.count)
46
- items&.each_with_index do |event, index|
47
- ExpRetry.for(exception: RETRIABLE_EXCEPTIONS) do
48
- delete(cal_id, event.id)
49
- pb.increment
50
- end
51
- end
52
- end
53
-
54
- def log_last_page_token
55
- puts "\n\n*** Last page token cleared: #{@page_token}"
56
- File.open(GoogleAPI::Calendar::LAST_TOKEN_PATH, 'w+') do |f|
57
- f.write(@page_token)
58
- end
59
- puts "\n*** Token stored in #{GoogleAPI::Calendar::LAST_TOKEN_PATH}"
60
- end
61
-
62
- def progress_bar(total)
63
- ProgressBar.create(
64
- title: 'Page cleared', starting_at: 0, total: total, progress_mark: ' ',
65
- remainder_mark: "\u{FF65}", format: "%a [%R/sec] %E | %b\u{15E7}%i %c/%C (%P%%) %t"
66
- )
67
- end
68
- end
69
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GoogleAPI::Concerns::Calendar
4
- module Permission
5
- def permit(calendar, user)
6
- rule = Google::Apis::CalendarV3::AclRule.new(
7
- scope: { type: 'user', value: user.email }, role: 'writer'
8
- )
9
-
10
- result = service.insert_acl(calendar, rule)
11
- user.update(calendar_rule_id: result.id)
12
- end
13
-
14
- def unpermit(calendar, user)
15
- service.delete_acl(calendar, user&.calendar_rule_id)
16
- rescue Google::Apis::ClientError
17
- :permission_not_found
18
- ensure
19
- user.update(calendar_rule_id: nil)
20
- end
21
- end
22
- end