Skip to content

Commit

Permalink
added a Gemfile for bundler, make it a real Sinatra App, make it read…
Browse files Browse the repository at this point in the history
…y for deploying, added conf files
  • Loading branch information
ben committed Jan 24, 2011
1 parent c5914e8 commit 5b094bc
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 128 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
database.yml
config.yml
*.pid
*.log
6 changes: 6 additions & 0 deletions Gemfile
@@ -0,0 +1,6 @@
source "http://rubygems.org"

gem "sinatra", "~> 1.1.0"
gem "activerecord", "~> 3.0.0", :require => "active_record"
gem "mysql", "~> 2.8.1"

32 changes: 32 additions & 0 deletions Gemfile.lock
@@ -0,0 +1,32 @@
GEM
remote: http://rubygems.org/
specs:
activemodel (3.0.0)
activesupport (= 3.0.0)
builder (~> 2.1.2)
i18n (~> 0.4.1)
activerecord (3.0.0)
activemodel (= 3.0.0)
activesupport (= 3.0.0)
arel (~> 1.0.0)
tzinfo (~> 0.3.23)
activesupport (3.0.0)
arel (1.0.1)
activesupport (~> 3.0.0)
builder (2.1.2)
i18n (0.4.1)
mysql (2.8.1)
rack (1.2.1)
sinatra (1.1.2)
rack (~> 1.1)
tilt (~> 1.2)
tilt (1.2.2)
tzinfo (0.3.23)

PLATFORMS
ruby

DEPENDENCIES
activerecord (~> 3.0.0)
mysql (~> 2.8.1)
sinatra (~> 1.1.0)
3 changes: 3 additions & 0 deletions config.ru
@@ -0,0 +1,3 @@
require 'lib/api.rb'
run Sinatra::Application

14 changes: 14 additions & 0 deletions config_example.yml
@@ -0,0 +1,14 @@
environment: production
chdir: /var/www/api
address: 127.0.0.1
user: www-data
group: www-data
port: 4567
pid: /var/www/api/server.pid
rackup: /var/www/api/config.ru
log: /var/www/api/api.log
max_conns: 1024
timeout: 30
max_persistent_conns: 512
daemonize: true

7 changes: 7 additions & 0 deletions database_example.yml
@@ -0,0 +1,7 @@
database: api
adapter: mysql
host: localhost
username: db_user
password: db_pass
encoding: utf8

117 changes: 117 additions & 0 deletions lib/api.rb
@@ -0,0 +1,117 @@
require 'lib/config'

#TODO:
#add config.yml / ensure that there is a db connection
#do paging
#handle put, post, delete requests ('/:model/:id')
##validate which columns can be changed / are needed
#handle parametrized requests (do this in a generic way, which means allow every parameter which is a table column of the model too)
##add more parameters like limit

set :root, APP_ROOT

get '/' do
#TODO: throw other error her, maybe a help message
throw_error 405
end

#request a list in rest/rails style
get '/:model' do
logger(params[:key],params[:model])
validate params
Datatable.set_table_name("data_#{params[:model]}")
output Datatable.find(:all, :select => only_permitted_columns, :limit => params[:limit]), params[:format]
end

#per model requests
#create
post '/:model/:id' do
#TODO
end

#read
get '/:model/:id' do
#TODO
end

#update
put '/:model/:id' do
#TODO
end

#delete
delete '/:model/:id' do
#TODO
end

private

#validating every request
#TODO: validate if model exists (or let the error "No permission(s) to do this." for now)
def validate params

throw_error 401 if params[:key].nil?
throw_error 405 unless params[:key].match(/^[A-Za-z0-9]*$/)
throw_error 405 unless params[:model].match(/^[A-Za-z0-9]*$/)


throw_error 405 unless params[:limit].match(/^[0-9]*$/) unless params[:limit].nil?
params[:limit] = 10 if params[:limit].to_i > 10 unless params[:limit].nil?

@user = User.find(:first, :conditions => [ "single_access_token = ?", params[:key]])
throw_error 401 if @user.nil?

#TODO: connect permissions and user through the models (rails style)
@permissions = Permission.find(:all, :joins=> :users, :conditions => {:access => get_action(request.env['REQUEST_METHOD']), :tabelle => params[:model], :users => { :id => @user.id } })
throw_error 403 if @permissions.empty?
end

#error handling
def throw_error code
#TODO: add more output information here, maybe a help message
halt code, output({"error" => "Authentication failed"}) if code == 401
halt code, output({"error" => "No permission(s) to do this."}) if code == 403
#TODO: add which parameter is wrong or missing
halt code, output({"error" => "wrong parameter format"}) if code == 405
end

#map request_method to db access names
def get_action request_method
case request_method
when 'POST': 'create'
when 'GET': 'read'
when 'PUT': 'update'
when 'DELETE': 'delete'
end
end

#generate resulting output
#output data
#output data format
def output *args
if args[1] == "xml"
content_type 'text/xml', :charset => 'utf-8'
"#{args[0].to_xml(:skip_instruct => false, :skip_types => true)}"
else
#ensure that result is a json object everytime, not a json object or an array of json objects (like facebook)
#FIXME: do this in a better and more reliable way
h = Hash.new
if args[0].is_a?(Array)
h['data'] = args[0]
else
h = args[0]
end
content_type 'text/plain', :charset => 'utf-8'
"#{h.to_json()}"
end
end

#specify only the colums we have rights to
def only_permitted_columns
columns = Array.new()
@permissions.each do |per|
columns += [per.spalte]
end
columns
end

121 changes: 0 additions & 121 deletions lib/app.rb

This file was deleted.

31 changes: 24 additions & 7 deletions lib/config.rb
@@ -1,8 +1,25 @@
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "root",
:password => "",
:database => "api"
)
require 'rubygems'
require 'bundler'
Bundler.require(:default)

APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))

module ActiveRecord
class Base

class << self
alias :old_connection :connection
def connection
self.verify_active_connections!
old_connection
end
end

end
end

ActiveRecord::Base.establish_connection(YAML.load_file(APP_ROOT + '/database.yml'))

require APP_ROOT + '/lib/models.rb'
require APP_ROOT + '/lib/helpers.rb'

0 comments on commit 5b094bc

Please sign in to comment.