我正在使用Google日历的API,尝试存储令牌信息时遇到问题。通常,这是这样的:
#!/usr/bin/env ruby
require "google/apis/calendar_v3"
require "googleauth"
require "date"
require "fileutils"
require "googleauth/stores/file_token_store"
TOKEN_PATH = "token.yaml".freeze
CREDS = {"installed" => xyz}
def authorized
client_id = Google::Auth::ClientId.from_hash CREDS
token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store
user_id = "default"
credentials = authorizer.get_credentials user_id
end
只要token.yaml
文件存在于当前目录中,它就只会加载该文件。但是,我不想将此信息存储在文件中,而是将其加载到Ruby / Rails代码本身中。
我遇到了Use Google::Auth::Stores::FileTokenStore with database作为潜在的解决方法,但是我仍然遇到相同的问题。
以下是我的token_store.rb
文件的示例:
# token_store.rb
require "googleauth/stores/file_token_store"
module Google
module Auth
module Stores
class DatabaseTokenStore < Google::Auth::TokenStore
def new
{"client_id":"[redacted]","access_token":"[redacted]","refresh_token":"[redacted]","scope":["https://www.googleapis.com/auth/calendar.events"],"expiration_time_millis":1591721243000}.to_json
end
end
end
end
end
这是我的test.rb
文件:
#!/usr/bin/env ruby
require "google/apis/calendar_v3"
require "googleauth"
require "date"
require "fileutils"
require "pry"
require './token_store.rb'
include Google::Auth::Stores
OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze
APPLICATION_NAME = "[redacted]".freeze
# The file token.yaml stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
TOKEN_PATH = "token.yaml".freeze
SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR_EVENTS
CREDS = {"installed" =>{"client_id" => "[redacted]","project_id" =>"[redacted]","auth_uri" =>"https://accounts.google.com/o/oauth2/auth","token_uri" =>"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url" => "https://www.googleapis.com/oauth2/v1/certs","client_secret" =>"[redacted]","redirect_uris" => ["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
##
# Ensure valid credentials, either by restoring from the saved credentials
# files or intitiating an OAuth2 authorization. If authorization is required,
# the user's default browser will be launched to approve the request.
#
# @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
def authorize
client_id = Google::Auth::ClientId.from_hash CREDS
token_store = Google::Auth::Stores::DatabaseTokenStore.new
authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store
user_id = "default"
credentials = authorizer.get_credentials user_id
if credentials.nil?
url = authorizer.get_authorization_url base_url: OOB_URI
puts "Open the following URL in the browser and enter the " \
"resulting code after authorization:\n" + url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
credentials
end
# Initialize the API
calendar_id = "[redacted]"
service = Google::Apis::CalendarV3::CalendarService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
到达此行的时间:
credentials = authorizer.get_credentials user_id
出现以下错误:
[4] pry(main)> credentials = authorizer.get_credentials user_id
RuntimeError: Not implemented
from /Library/Ruby/Gems/2.6.0/gems/googleauth-0.12.0/lib/googleauth/token_store.rb:47:in `load'
如果我看一下token_store
,它似乎已经正确定义了:
[5] pry(main)> token_store
=> #<Google::Auth::Stores::DatabaseTokenStore:0x00007fc565bd7400>
尽管从文件中加载它看起来却大不相同:
[7] pry(main)> token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
=> #<Google::Auth::Stores::FileTokenStore:0x00007fc567942b70
@store=#<Psych::Store:0x00007fc567942b48 @abort=false, @filename="token.yaml", @lock=#<Thread::Mutex:0x00007fc567942a58>, @opt={}, @thread_safe=false, @ultra_safe=false>>
如何将token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
转换为从变量中加载数据而不必将其保存在本地?
解决方案尝试1
这是更新的test.rb
:
#!/usr/bin/env ruby
require "google/apis/calendar_v3"
require "googleauth"
require "date"
require "fileutils"
require "pry"
#require "googleauth/stores/file_token_store"
require './token_store.rb'
include Google::Auth::Stores
OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze
APPLICATION_NAME = "[redacted]".freeze
# The file token.yaml stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
TOKEN_PATH = "token.yaml".freeze
SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR_EVENTS
CREDS = {"installed" =>{"client_id" => "[redacted]","project_id" =>"[redacted]","auth_uri" =>"https://accounts.google.com/o/oauth2/auth","token_uri" =>"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url" => "https://www.googleapis.com/oauth2/v1/certs","client_secret" =>"ScD4aFP-xw5ulWTeSJnYWQPi","redirect_uris" => ["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
##
# Ensure valid credentials, either by restoring from the saved credentials
# files or intitiating an OAuth2 authorization. If authorization is required,
# the user's default browser will be launched to approve the request.
#
# @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
def authorize
client_id = Google::Auth::ClientId.from_hash CREDS
#token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
store = {"client_id":"[redacted]","access_token":"[redacted]","refresh_token":"1//0d_k9oyIPv5CeCgYIARAAGA0SNwF-L9IrWtHY2lpGHJSuz8Brh9whd8tEPIenoZaK_dpJO4_wkCCaByT45gRFEmncjDhPQyRCcEQ","scope":["https://www.googleapis.com/auth/calendar.events"],"expiration_time_millis":1591721243000}
token_store = Google::Auth::Stores::MemoryTokenStore.new(store: store)
authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store
user_id = "default"
credentials = authorizer.get_credentials user_id
if credentials.nil?
url = authorizer.get_authorization_url base_url: OOB_URI
puts "Open the following URL in the browser and enter the " \
"resulting code after authorization:\n" + url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
credentials
end
calendar_id = "[redacted]"
service = Google::Apis::CalendarV3::CalendarService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
# Insert event into calendar
event = Google::Apis::CalendarV3::Event.new({
:summary => 'event title',
:location => 'event address',
:description => 'event description',
:start => {
:date_time => '2020-06-28T09:00:00-07:00'
},
:end => {
:date_time => '2020-06-28T17:00:00-07:00'
}
})
service.insert_event(calendar_id, event)
这是我更新的token_store.rb
:
require "googleauth/stores/file_token_store"
module Google
module Auth
module Stores
class MemoryTokenStore < Google::Auth::TokenStore
def initialize(options = {})
@store = options[:store]
end
def load(id)
store[id]
end
def store(id, token)
store[id] = token
end
def delete(id)
store.delete(id)
end
end
end
end
end
运行./test.rb
时,发生以下错误:
Traceback (most recent call last):
5: from ./test.rb:51:in `<main>'
4: from ./test.rb:34:in `authorize'
3: from /Library/Ruby/Gems/2.6.0/gems/googleauth-0.12.0/lib/googleauth/user_authorizer.rb:127:in `get_credentials'
2: from /Library/Ruby/Gems/2.6.0/gems/googleauth-0.12.0/lib/googleauth/user_authorizer.rb:250:in `stored_token'
1: from /Users/nutella/Downloads/test/google-calendar/token_store.rb:11:in `load'
/Users/myuser/Downloads/test/google-calendar/token_store.rb:14:in `store': wrong number of arguments (given 0, expected 2) (ArgumentError)
答案 0 :(得分:1)
您至少需要实现load
方法(+ store
和delete
)。否则,它将引发Not implemented
错误(https://github.com/googleapis/google-auth-library-ruby/blob/master/lib/googleauth/token_store.rb#L47)。
require "googleauth/stores/file_token_store"
module Google
module Auth
module Stores
class StaticTokenStore < Google::Auth::TokenStore
def load(id)
{
"client_id": "[redacted]",
"access_token":"[redacted]",
"refresh_token":"[redacted]",
"scope": ["https://www.googleapis.com/auth/calendar.events"],
"expiration_time_millis":1591721243000
}.to_json
end
end
end
end
end
还请注意,在Ruby中,构造函数称为initialize
,而不是new
。此外,您没有将JSON数据分配给任何对象。所以这行不通:
def new
{"client_id":"[redacted]","access_token":"[redacted]","refresh_token":"[redacted]","scope":["https://www.googleapis.com/auth/calendar.events"],"expiration_time_millis":1591721243000}.to_json
end
https://www.geeksforgeeks.org/ruby-constructors/
这是内存中的存储器
module Google
module Auth
module Stores
class MemoryTokenStore < Google::Auth::TokenStore
attr_reader :store
def initialize(options = {})
@store = options[:store]
end
def load(id)
store[id]
end
def store(id, token)
store[id] = token
end
def delete(id)
store.delete(id)
end
end
end
end
end
store = {
"client_id": "[redacted]",
"access_token": "[redacted]",
"refresh_token": "[redacted]",
"scope": ["https://www.googleapis.com/auth/calendar.events"],
"expiration_time_millis": 1591721243000
}
Google::Auth::Stores::MemoryTokenStore.new(store: store)