Merge branch 'jsonp'

1.0
Fernando Blat 14 years ago
commit 9969c1b2a2

@ -2,7 +2,7 @@ class Api::Json::TablesController < ApplicationController
skip_before_filter :verify_authenticity_token
before_filter :login_required
before_filter :api_authorization_required
before_filter :load_table, :except => [:index, :create, :query]
# Get the list of tables of a user
@ -26,7 +26,8 @@ class Api::Json::TablesController < ApplicationController
@tables = Table.select(:id,:user_id,:name,:privacy).all
respond_to do |format|
format.json do
render :json => @tables.map{ |table| {:id => table.id, :name => table.name, :privacy => table_privacy_text(table)} }.to_json
render :json => @tables.map{ |table| {:id => table.id, :name => table.name, :privacy => table_privacy_text(table)} }.to_json,
:callback => params[:callback]
end
end
end
@ -47,7 +48,8 @@ class Api::Json::TablesController < ApplicationController
def show
respond_to do |format|
format.json do
render :json => @table.to_json(:owner => current_user, :rows_per_page => params[:rows_per_page], :page => params[:page])
render :json => @table.to_json(:owner => current_user, :rows_per_page => params[:rows_per_page], :page => params[:page]),
:callback => params[:callback]
end
end
end
@ -67,7 +69,7 @@ class Api::Json::TablesController < ApplicationController
def query
respond_to do |format|
format.json do
render :json => current_user.run_query(params[:query]).to_json
render :json => current_user.run_query(params[:query]).to_json, :callback => params[:callback]
end
end
end
@ -82,7 +84,7 @@ class Api::Json::TablesController < ApplicationController
def schema
respond_to do |format|
format.json do
render :json => @table.schema.to_json
render :json => @table.schema.to_json, :callback => params[:callback]
end
end
end
@ -97,7 +99,7 @@ class Api::Json::TablesController < ApplicationController
@table.toggle_privacy!
respond_to do |format|
format.json do
render :json => { :privacy => table_privacy_text(@table) }.to_json
render :json => { :privacy => table_privacy_text(@table) }.to_json, :callback => params[:callback]
end
end
end
@ -128,12 +130,13 @@ class Api::Json::TablesController < ApplicationController
begin
@table.set_all(params)
if @table.save
render :json => params.merge(@table.reload.values).to_json, :status => 200
render :json => params.merge(@table.reload.values).to_json, :status => 200, :callback => params[:callback]
else
render :json => { :errors => @table.errors.full_messages}.to_json, :status => 400
render :json => { :errors => @table.errors.full_messages}.to_json, :status => 400, :callback => params[:callback]
end
rescue => e
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json, :status => 400 and return
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json,
:status => 400, :callback => params[:callback] and return
end
end
end
@ -166,22 +169,25 @@ class Api::Json::TablesController < ApplicationController
begin
if params[:what] == 'add'
resp = @table.add_column!(params[:column])
render :json => resp.to_json, :status => 200 and return
render :json => resp.to_json, :status => 200, :callback => params[:callback] and return
elsif params[:what] == 'drop'
@table.drop_column!(params[:column])
render :json => ''.to_json, :status => 200 and return
render :json => ''.to_json, :status => 200, :callback => params[:callback] and return
else
resp = @table.modify_column!(params[:column])
render :json => resp.to_json, :status => 200 and return
render :json => resp.to_json, :status => 200, :callback => params[:callback] and return
end
rescue => e
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json, :status => 400 and return
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json, :status => 400,
:callback => params[:callback] and return
end
else
render :json => { :errors => ["column parameter can't be blank"] }.to_json, :status => 400 and return
render :json => { :errors => ["column parameter can't be blank"] }.to_json, :status => 400,
:callback => params[:callback] and return
end
else
render :json => { :errors => ["what parameter has an invalid value"] }.to_json, :status => 400 and return
render :json => { :errors => ["what parameter has an invalid value"] }.to_json, :status => 400,
:callback => params[:callback] and return
end
end
end
@ -207,7 +213,7 @@ class Api::Json::TablesController < ApplicationController
@table.insert_row!(params)
respond_to do |format|
format.json do
render :json => ''.to_json, :status => 200
render :json => ''.to_json, :status => 200, :callback => params[:callback]
end
end
end
@ -237,11 +243,13 @@ class Api::Json::TablesController < ApplicationController
else
case resp
when 404
render :json => { :errors => ["row with id = #{params[:row_id]} not found"] }.to_json, :status => 400 and return
render :json => { :errors => ["row with id = #{params[:row_id]} not found"] }.to_json,
:status => 400, :callback => params[:callback] and return
end
end
else
render :json => { :errors => ["row_id can't be blank"] }.to_json, :status => 400 and return
render :json => { :errors => ["row_id can't be blank"] }.to_json,
:status => 400, :callback => params[:callback] and return
end
end
end
@ -256,7 +264,7 @@ class Api::Json::TablesController < ApplicationController
# * body: _nothing_
def delete
@table.destroy
render :json => ''.to_json, :status => 200, :location => dashboard_path
render :json => ''.to_json, :status => 200, :location => dashboard_path, :callback => params[:callback]
end
# Create a new table
@ -282,12 +290,14 @@ class Api::Json::TablesController < ApplicationController
end
@table.force_schema = params[:schema] if params[:schema]
if @table.valid? && @table.save
render :json => { :id => @table.id }.to_json, :status => 200, :location => table_path(@table)
render :json => { :id => @table.id }.to_json, :status => 200, :location => table_path(@table),
:callback => params[:callback]
else
render :json => { :errors => @table.errors.full_messages }.to_json, :status => 400
render :json => { :errors => @table.errors.full_messages }.to_json, :status => 400, :callback => params[:callback]
end
rescue => e
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json, :status => 400 and return
render :json => { :errors => [translate_error(e.message.split("\n").first)] }.to_json,
:status => 400, :callback => params[:callback] and return
end
protected

@ -10,6 +10,14 @@ class ApplicationController < ActionController::Base
protected
def api_authorization_required
api_authenticated? || authenticated? || not_authorized
end
def api_authenticated?
env['warden'].authenticate(:api_key)
end
def render_404
respond_to do |format|
format.html do

@ -22,7 +22,14 @@ class SessionsController < ApplicationController
def unauthenticated
flash[:alert] = 'Your account or your password is not ok'
render :action => 'new' and return
respond_to do |format|
format.html do
render :action => 'new' and return
end
format.json do
render :nothing => true, :status => 401
end
end
end
end

@ -0,0 +1,9 @@
# coding: UTF-8
class APIKey < Sequel::Model(:api_keys)
def user
User[:id => user_id]
end
end

@ -121,4 +121,11 @@ class User < Sequel::Model
Table.filter(:user_id => self.id).order(:id).reverse
end
def create_key(domain)
raise "domain argument can't be blank" if domain.blank?
key = self.class.secure_digest(domain)
APIKey.create :api_key => key, :user_id => self.id, :domain => domain
key
end
end

@ -1,5 +1,5 @@
Rails.configuration.middleware.use RailsWarden::Manager do |manager|
manager.default_strategies :password
manager.default_strategies :password, :api_key
manager.failure_app = SessionsController
end
@ -26,4 +26,26 @@ Warden::Strategies.add(:password) do
fail!
end
end
end
Warden::Strategies.add(:api_key) do
def authenticate!
if params[:api_key]
if api_key = APIKey[:api_key => params[:api_key]]
if api_key.domain == request.host
success!(api_key.user)
else
fail!
end
else
fail!
end
else
fail!
end
end
def fail!
render :status => 401, :nothing => true
end
end

@ -0,0 +1,16 @@
class ApiKeysMigration < Sequel::Migration
def up
create_table :api_keys do
primary_key :id
String :api_key, :null => false, :unique => true, :index => true
Integer :user_id, :null => false
String :domain, :null => false
end
end
def down
drop_table :api_keys
end
end

@ -1,5 +1,15 @@
Sequel.migration do
up do
create_table(:api_keys, :ignore_index_errors=>true) do
primary_key :id
String :api_key, :text=>true, :null=>false
Integer :user_id, :null=>false
String :domain, :text=>true, :null=>false
index [:api_key]
index [:api_key], :name=>:api_keys_api_key_key, :unique=>true
end
create_table(:schema_migrations) do
String :filename, :text=>true, :null=>false
@ -40,6 +50,7 @@ Sequel.migration do
String :database_name, :text=>true
String :username, :text=>true, :null=>false
Integer :tables_count, :default=>0, :null=>false
String :keys, :text=>true
index [:email], :name=>:users_email_key, :unique=>true
index [:username], :name=>:users_username_key, :unique=>true
@ -47,6 +58,6 @@ Sequel.migration do
end
down do
drop_table(:schema_migrations, :tags, :user_tables, :users)
drop_table(:api_keys, :schema_migrations, :tags, :user_tables, :users)
end
end

@ -539,4 +539,31 @@ feature "Tables JSON API" do
json_response['rows'][1].symbolize_keys[:name_of_species].should == "Eulagisca gigantea"
end
scenario "Run a query against a table using JSONP and key authorization" do
Capybara.current_driver = :selenium
user = create_user
api_key = user.create_key "example.org"
api_key2 = user.create_key "127.0.0.1"
post_json "/api/json/tables", {
:api_key => api_key,
:name => "antantaric species",
:file => Rack::Test::UploadedFile.new("#{Rails.root}/db/fake_data/import_csv_1.csv", "text/csv")
}
response.status.should == 200
response.location.should =~ /tables\/(\d+)$/
json_response = JSON(response.body)
table_id = response.location.match(/\/(\d+)$/)[1].to_i
FileUtils.cp("#{Rails.root}/spec/support/test_jsonp.html", "#{Rails.root}/public/")
visit "/test_jsonp.html?api_key=#{api_key2}"
page.find("div#results").text.should == "Barrukia cristata"
FileUtils.rm("#{Rails.root}/public/test_jsonp.html")
end
end

@ -128,4 +128,14 @@ describe User do
end
end
it "can have different keys for accessing via JSONP API requrests" do
user = create_user
lambda {
user.create_key ""
}.should raise_error
key = user.create_key "mymashup.com"
api_key = APIKey.filter(:user_id => user.id, :domain => 'mymashup.com').first
api_key.api_key.should == key
end
end

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>JSONP getJSON Jquery cross domain example</title>
<script src="/javascripts/jquery.min.js" type="text/javascript"></script>
<script>
$.extend({
getUrlVars: function(){
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
},
getUrlVar: function(name){
return $.getUrlVars()[name];
}
});
$(document).ready(function() {
$.ajax({
url: "/api/json/tables/query",
data: ({api_key: $.getUrlVar('api_key'), query: "select * from antantaric_species where family='Polynoidae' limit 10"}),
dataType: "jsonp",
success: function( data ) {
if(data != null) {
$('div#time').html(data.time).css("color","blue");
$('div#results').html(data.rows[0].name_of_species).css("color","green");
}
},
error: function(req, textStatus, e) {
alert(textStatus);
}
});
});
</script>
</head>
<body>
<div id="time">
</div>
<div id="results">
No results
</div>
</body>
</html>
Loading…
Cancel
Save