ft 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ task :default => :test
2
+
3
+ desc "Run all tests"
4
+ task :test do
5
+ require "cutest"
6
+
7
+ files = Dir["./test/*.rb"]
8
+
9
+ if !files.include?("./test/private.rb")
10
+ $stderr.puts("Couldn't find a test/private.rb file, so skipping tests that require authentication.\nIf you want to run them, take a look at test/private.example.rb")
11
+ files.delete("./test/authenticated.rb")
12
+ end
13
+
14
+ Cutest.run(files)
15
+ end
data/ft.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "ft"
3
- s.version = "0.0.1"
3
+ s.version = "0.0.2"
4
4
  s.summary = "Low-level interface to Google's Fusion Tables + CLI tool"
5
5
  s.authors = ["Damian Janowski"]
6
6
  s.email = ["djanowski@dimaion.com"]
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.files = Dir[
16
16
  "*.gemspec",
17
+ "CHANGELOG.*",
17
18
  "LICENSE",
18
19
  "README*",
19
20
  "Rakefile",
data/lib/ft.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "csv"
2
2
  require "net/http/persistent"
3
+ require "net/https"
3
4
 
4
5
  class FusionTables
5
6
  Error = Class.new(RuntimeError)
@@ -13,15 +14,16 @@ class FusionTables
13
14
  end
14
15
  end
15
16
 
17
+ # Queries the Fusion Tables API with the given SQL and returns an
18
+ # array of arrays for rows and columns.
16
19
  def query(sql)
17
- url = URL.dup
18
-
19
- url.query = "sql=#{URI.escape(sql)}"
20
- res = http.request(url)
20
+ res = process_sql(sql)
21
21
 
22
22
  case res
23
23
  when Net::HTTPOK
24
24
  CSV.parse(res.body.force_encoding(Encoding::UTF_8))
25
+ when Net::HTTPFound
26
+ raise Error.new("Authentication required. See #{self.class}#authenticate")
25
27
  when Net::HTTPBadRequest
26
28
  message = CGI.unescapeHTML(res.body[%r[<title>(.*)</title>]i, 1])
27
29
  raise Error.new("#{message}. SQL was: #{sql}")
@@ -29,5 +31,71 @@ class FusionTables
29
31
  raise "Got #{res.class}: #{res.body}"
30
32
  end
31
33
  end
34
+
35
+ # Authenticates against Google using your email and password.
36
+ #
37
+ # Note that this method uses the ClientLogin mechanism and it
38
+ # only stores the resulting token as an instance variable. Your
39
+ # credentials are discarded after the authentication process.
40
+ def authenticate(email, password)
41
+ uri = URI.parse("https://www.google.com/accounts/ClientLogin")
42
+
43
+ http = Net::HTTP.new(uri.host, uri.port)
44
+ http.use_ssl = true
45
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
46
+
47
+ request = Net::HTTP::Post.new(uri.request_uri)
48
+
49
+ request.set_form_data({
50
+ "accountType" => "GOOGLE",
51
+ "Email" => email,
52
+ "Passwd" => password,
53
+ "service" => "fusiontables"
54
+ })
55
+
56
+ response = http.request(request)
57
+
58
+ case response
59
+ when Net::HTTPOK
60
+ @token = response.body[/^Auth=(.*)$/, 1]
61
+ return true
62
+ else
63
+ @token = nil
64
+ return false
65
+ end
66
+ end
67
+
68
+ # Prevents any authorization tokens from being exposed in error logs
69
+ # and the like.
70
+ def inspect
71
+ "#<#{self.class}>"
72
+ end
73
+
74
+ # Safely quotes a value.
75
+ def self.quote(value)
76
+ "'#{value.to_s.gsub("'", "\\\\'")}'"
77
+ end
78
+
79
+ protected
80
+
81
+ # Takes SQL and queries the Fusion Tables API.
82
+ def process_sql(sql)
83
+ url = URL.dup
84
+
85
+ if @token
86
+ http.headers["Authorization"] = "GoogleLogin auth=#{@token}"
87
+ end
88
+
89
+ if sql =~ /^select/i
90
+ url.query = "sql=#{URI.escape(sql)}"
91
+ res = http.request(url)
92
+ else
93
+ req = Net::HTTP::Post.new(url.path)
94
+ req.set_form_data(sql: sql)
95
+ res = http.request(url, req)
96
+ end
97
+
98
+ res
99
+ end
32
100
  end
33
101
  end
@@ -0,0 +1,48 @@
1
+ require "cutest"
2
+ require "./lib/ft"
3
+ require "./test/private"
4
+
5
+ setup do
6
+ [FusionTables::Connection.new, ENV["EMAIL"], ENV["PASSWORD"], ENV["PRIVATE_TABLE_ID"]]
7
+ end
8
+
9
+ test "authenticated SELECTs" do |conn, email, password, table_id|
10
+ conn.authenticate(email, password)
11
+
12
+ result = conn.query("SELECT Client, Invoice FROM #{table_id}")
13
+
14
+ assert_equal result, [
15
+ ["Client", "Invoice"],
16
+ ["Madalyn Streich", "1"],
17
+ ["Mr. Vincenza Bailey", "2"]
18
+ ]
19
+
20
+ assert conn.inspect !~ /token/
21
+ end
22
+
23
+ test "INSERT" do |conn, email, password, table_id|
24
+ conn.authenticate(email, password)
25
+
26
+ begin
27
+ result = conn.query("INSERT INTO #{table_id} (Client) VALUES ('Foo')")
28
+
29
+ assert_equal result[0][0], "rowid"
30
+ assert result[1][0] =~ /^\d+$/
31
+ ensure
32
+ conn.query("DELETE FROM #{table_id} WHERE ROWID = '#{result[1][0]}'") if result
33
+ end
34
+ end
35
+
36
+ test "DELETE" do |conn, email, password, table_id|
37
+ conn.authenticate(email, password)
38
+
39
+ result = conn.query("INSERT INTO #{table_id} (Client) VALUES ('Foo')")
40
+
41
+ rowid = result[1][0]
42
+
43
+ conn.query("DELETE FROM #{table_id} WHERE ROWID = '#{rowid}'")
44
+
45
+ result = conn.query("SELECT ROWID FROM #{table_id} WHERE ROWID = '#{rowid}'")
46
+
47
+ assert_equal result[1], nil
48
+ end
data/test/ft.rb CHANGED
@@ -16,3 +16,13 @@ test "raises errors" do |conn|
16
16
  conn.query("SELECT foo FROM 1310767")
17
17
  end
18
18
  end
19
+
20
+ test "raises on authentication errors" do |conn|
21
+ assert_raise FusionTables::Error do
22
+ conn.query("INSERT INTO 1310767 (Name) VALUES ('Foo')")
23
+ end
24
+ end
25
+
26
+ test "quoting" do |conn|
27
+ assert_equal FusionTables::Connection.quote("C'mon"), %q{'C\'mon'}
28
+ end
@@ -0,0 +1,8 @@
1
+ # This example works with OS X's keychain, but you can set the variables
2
+ # as you please.
3
+ #
4
+
5
+ # ENV["EMAIL"] = "<your google account email>" # If not already in your shell.
6
+ ENV["PASSWORD"] = `security 2>&1 find-internet-password -g -s www.google.com -a #{ENV["EMAIL"]}`[/^password: "(.*)"/, 1]
7
+
8
+ ENV["PRIVATE_TABLE_ID"] = "<your private table id>"
data/test/private.rb ADDED
@@ -0,0 +1,3 @@
1
+ ENV["EMAIL"] = "damian.janowski@gmail.com"
2
+ ENV["PASSWORD"] = `security 2>&1 find-internet-password -g -s www.google.com -a #{ENV["EMAIL"]}`[/^password: "(.*)"/, 1]
3
+ ENV["PRIVATE_TABLE_ID"] = "1340856"
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ft
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Damian Janowski
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-18 00:00:00 -03:00
13
+ date: 2011-08-26 00:00:00 -03:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -57,10 +57,14 @@ extra_rdoc_files: []
57
57
 
58
58
  files:
59
59
  - ft.gemspec
60
+ - Rakefile
60
61
  - bin/ft
61
62
  - lib/ft.rb
63
+ - test/authenticated.rb
62
64
  - test/cli.rb
63
65
  - test/ft.rb
66
+ - test/private.example.rb
67
+ - test/private.rb
64
68
  has_rdoc: true
65
69
  homepage: http://github.com/djanowski/ft
66
70
  licenses: []