dao 0.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +35 -0
- data/Rakefile +6 -3
- data/TODO +37 -0
- data/dao.gemspec +30 -0
- data/db/dao.yml +8 -0
- data/lib/dao.rb +84 -5
- data/lib/dao/active_record.rb +76 -0
- data/lib/dao/api.rb +9 -0
- data/lib/dao/api/context.rb +38 -0
- data/lib/dao/api/dsl.rb +50 -0
- data/lib/dao/api/endpoints.rb +190 -0
- data/lib/dao/api/initializers.rb +71 -0
- data/lib/dao/api/modes.rb +85 -0
- data/lib/dao/blankslate.rb +5 -0
- data/lib/dao/data.rb +58 -0
- data/lib/dao/db.rb +183 -0
- data/lib/dao/endpoint.rb +16 -0
- data/lib/dao/engine.rb +7 -0
- data/lib/dao/errors.rb +238 -0
- data/lib/dao/exceptions.rb +2 -0
- data/lib/dao/form.rb +236 -0
- data/lib/dao/mode.rb +41 -0
- data/lib/dao/mongo_mapper.rb +70 -0
- data/lib/dao/params.rb +109 -0
- data/lib/dao/path.rb +149 -0
- data/lib/dao/rails.rb +15 -0
- data/lib/dao/rails/app/api.rb +55 -0
- data/lib/dao/rails/app/controllers/api_controller.rb +99 -0
- data/lib/dao/rails/lib/generators/dao/USAGE +9 -0
- data/lib/dao/rails/lib/generators/dao/api_generator.rb +3 -0
- data/lib/dao/rails/lib/generators/dao/dao_generator.rb +27 -0
- data/lib/dao/rails/lib/generators/dao/templates/api.rb +55 -0
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +99 -0
- data/lib/dao/result.rb +87 -0
- data/lib/dao/slug.rb +11 -0
- data/lib/dao/status.rb +223 -0
- data/lib/dao/stdext.rb +10 -0
- data/lib/dao/support.rb +62 -0
- data/lib/dao/validations.rb +115 -0
- data/sample/rails_app/Gemfile +33 -0
- data/sample/rails_app/Gemfile.lock +88 -0
- data/sample/rails_app/README +1 -0
- data/sample/rails_app/Rakefile +7 -0
- data/sample/rails_app/app/api.rb +55 -0
- data/sample/rails_app/app/controllers/api_controller.rb +99 -0
- data/sample/rails_app/app/controllers/application_controller.rb +3 -0
- data/sample/rails_app/app/helpers/application_helper.rb +2 -0
- data/sample/rails_app/app/views/layouts/application.html.erb +14 -0
- data/sample/rails_app/config.ru +4 -0
- data/sample/rails_app/config/application.rb +51 -0
- data/sample/rails_app/config/boot.rb +13 -0
- data/sample/rails_app/config/database.yml +22 -0
- data/sample/rails_app/config/environment.rb +5 -0
- data/sample/rails_app/config/environments/development.rb +26 -0
- data/sample/rails_app/config/environments/production.rb +49 -0
- data/sample/rails_app/config/environments/test.rb +35 -0
- data/sample/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/sample/rails_app/config/initializers/inflections.rb +10 -0
- data/sample/rails_app/config/initializers/mime_types.rb +5 -0
- data/sample/rails_app/config/initializers/secret_token.rb +7 -0
- data/sample/rails_app/config/initializers/session_store.rb +8 -0
- data/sample/rails_app/config/locales/en.yml +5 -0
- data/sample/rails_app/config/routes.rb +62 -0
- data/sample/rails_app/db/development.sqlite3 +0 -0
- data/sample/rails_app/db/seeds.rb +7 -0
- data/sample/rails_app/doc/README_FOR_APP +2 -0
- data/sample/rails_app/log/development.log +27 -0
- data/sample/rails_app/log/production.log +0 -0
- data/sample/rails_app/log/server.log +0 -0
- data/sample/rails_app/log/test.log +0 -0
- data/sample/rails_app/public/404.html +26 -0
- data/sample/rails_app/public/422.html +26 -0
- data/sample/rails_app/public/500.html +26 -0
- data/sample/rails_app/public/favicon.ico +0 -0
- data/sample/rails_app/public/images/rails.png +0 -0
- data/sample/rails_app/public/index.html +239 -0
- data/sample/rails_app/public/javascripts/application.js +2 -0
- data/sample/rails_app/public/javascripts/controls.js +965 -0
- data/sample/rails_app/public/javascripts/dragdrop.js +974 -0
- data/sample/rails_app/public/javascripts/effects.js +1123 -0
- data/sample/rails_app/public/javascripts/prototype.js +6001 -0
- data/sample/rails_app/public/javascripts/rails.js +175 -0
- data/sample/rails_app/public/robots.txt +5 -0
- data/sample/rails_app/script/rails +6 -0
- data/sample/rails_app/test/performance/browsing_test.rb +9 -0
- data/sample/rails_app/test/test_helper.rb +13 -0
- data/test/dao_test.rb +271 -0
- data/test/helper.rb +15 -0
- data/test/testing.rb +74 -0
- metadata +137 -9
data/lib/dao/path.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
module Dao
|
2
|
+
class Path < ::String
|
3
|
+
class Error < ::StandardError; end
|
4
|
+
class Error::Params < Error; end
|
5
|
+
|
6
|
+
class << Path
|
7
|
+
def for(*args)
|
8
|
+
new(absolute_path_for(*args))
|
9
|
+
end
|
10
|
+
|
11
|
+
def paths_for(arg, *args)
|
12
|
+
path = [arg, *args].flatten.compact.join('/')
|
13
|
+
path.gsub!(%r|[.]+/|, '/')
|
14
|
+
path.squeeze!('/')
|
15
|
+
path.sub!(%r|^/|, '')
|
16
|
+
path.sub!(%r|/$|, '')
|
17
|
+
paths = path.split('/')
|
18
|
+
end
|
19
|
+
|
20
|
+
def absolute_path_for(arg, *args)
|
21
|
+
('/' + paths_for(arg, *args).join('/')).squeeze('/')
|
22
|
+
end
|
23
|
+
|
24
|
+
def cast(*args)
|
25
|
+
if args.size == 1
|
26
|
+
value = args.first
|
27
|
+
value.is_a?(self) ? value : self.for(value)
|
28
|
+
else
|
29
|
+
self.for(*args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def params?(string)
|
34
|
+
string.to_s =~ %r{/:[^/]+}
|
35
|
+
end
|
36
|
+
alias_method('=~', 'params?')
|
37
|
+
|
38
|
+
def absolute?(string)
|
39
|
+
string.to_s =~ %r|^\s*/|
|
40
|
+
end
|
41
|
+
|
42
|
+
def keys_for(path)
|
43
|
+
path = absolute_path_for(path)
|
44
|
+
path.scan(%r{/:[^/]+}).map{|key| key.sub(%r{^/:}, '')}
|
45
|
+
end
|
46
|
+
|
47
|
+
def expand!(path, params = {})
|
48
|
+
params = Map.for(params)
|
49
|
+
path.keys.each do |key|
|
50
|
+
path.gsub!(%r{/:#{ Regexp.escape(key) }\b}, params[key])
|
51
|
+
end
|
52
|
+
path
|
53
|
+
end
|
54
|
+
|
55
|
+
def pattern_for(path)
|
56
|
+
path = absolute_path_for(path)
|
57
|
+
re = path.gsub(%r{/:[^/]+}, '/([^/]+)')
|
58
|
+
/^#{ re }$/i
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_params(enumerable, keys)
|
62
|
+
params = Map.new
|
63
|
+
keys = Array(keys)
|
64
|
+
case enumerable
|
65
|
+
when Array
|
66
|
+
keys.each_with_index{|key, index| params[key] = enumerable[index]}
|
67
|
+
when Hash
|
68
|
+
enumerable = Map.for(enumerable)
|
69
|
+
keys.each{|key| params[key] = enumerable[key]}
|
70
|
+
else
|
71
|
+
raise(ArgumentError, enumerable.class.name)
|
72
|
+
end
|
73
|
+
params
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_accessor :result
|
78
|
+
attr_accessor :keys
|
79
|
+
attr_accessor :pattern
|
80
|
+
attr_accessor :params
|
81
|
+
attr_accessor :endpoint
|
82
|
+
|
83
|
+
def initialize(*args, &block)
|
84
|
+
super(args.join('/'), &block)
|
85
|
+
normalize!
|
86
|
+
compile!
|
87
|
+
end
|
88
|
+
|
89
|
+
def params?
|
90
|
+
Path.params?(self)
|
91
|
+
end
|
92
|
+
|
93
|
+
def normalize!
|
94
|
+
replace(Path.absolute_path_for(self))
|
95
|
+
end
|
96
|
+
|
97
|
+
def compile!
|
98
|
+
@keys = Path.keys_for(self)
|
99
|
+
@pattern = Path.pattern_for(self)
|
100
|
+
@params = Map.new
|
101
|
+
@path = dup
|
102
|
+
end
|
103
|
+
|
104
|
+
def expand(params)
|
105
|
+
dup.expand!(params)
|
106
|
+
end
|
107
|
+
|
108
|
+
class ParamsError < ::StandardError; end
|
109
|
+
|
110
|
+
def expand!(params)
|
111
|
+
replace(@path.dup)
|
112
|
+
@params = extract_params(params)
|
113
|
+
keys.each do |key|
|
114
|
+
next if @params[key].nil?
|
115
|
+
re = %r{/:#{ Regexp.escape(key) }\b}
|
116
|
+
val = "/#{ @params[key] }"
|
117
|
+
self.gsub!(re, val)
|
118
|
+
end
|
119
|
+
raise(Error::Params, "#{ self }(#{ @params.inspect })") if params?
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
def absolute?
|
124
|
+
Path.absolute?(self)
|
125
|
+
end
|
126
|
+
|
127
|
+
def match(other)
|
128
|
+
matched, *matches = @pattern.match(other).to_a
|
129
|
+
matched ? expand(matches) : false
|
130
|
+
end
|
131
|
+
|
132
|
+
def match!(other)
|
133
|
+
matched, *matches = @pattern.match(other).to_a
|
134
|
+
matched ? expand!(matches) : false
|
135
|
+
end
|
136
|
+
|
137
|
+
def extract_params(enumerable)
|
138
|
+
Path.extract_params(enumerable, @keys)
|
139
|
+
end
|
140
|
+
|
141
|
+
def +(other)
|
142
|
+
Path.for(super)
|
143
|
+
end
|
144
|
+
|
145
|
+
def to_yaml(*args, &block)
|
146
|
+
"#{ self }".to_yaml(*args, &block)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/dao/rails.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
if defined?(Rails)
|
2
|
+
module Dao
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
GEM_DIR = File.expand_path(__FILE__ + '/../../../')
|
5
|
+
ROOT_DIR = File.join(GEM_DIR, 'lib/dao/rails')
|
6
|
+
#APP_DIR = File.join(ROOT_DIR, 'app')
|
7
|
+
|
8
|
+
### https://gist.github.com/af7e572c2dc973add221
|
9
|
+
|
10
|
+
paths.path = ROOT_DIR
|
11
|
+
### config.autoload_paths << APP_DIR
|
12
|
+
### $LOAD_PATH.push(File.join(Rails.root.to_s, 'app'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Api =
|
2
|
+
Dao.api do
|
3
|
+
|
4
|
+
description 'ping!'
|
5
|
+
endpoint('/ping'){
|
6
|
+
data.update :time => Time.now
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
## this is simply a suggest way to model your api. it is not required.
|
13
|
+
#
|
14
|
+
attr_accessor :effective_user
|
15
|
+
attr_accessor :real_user
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
options = args.extract_options!.to_options!
|
19
|
+
effective_user = args.shift || options[:effective_user] || options[:user]
|
20
|
+
real_user = args.shift || options[:real_user] || effective_user
|
21
|
+
@effective_user = user_for(effective_user) if effective_user
|
22
|
+
@real_user = user_for(real_user) if real_user
|
23
|
+
@real_user ||= @effective_user
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_for(arg)
|
27
|
+
User.find(arg)
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method('user', 'effective_user')
|
31
|
+
alias_method('user=', 'effective_user=')
|
32
|
+
|
33
|
+
def api
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def logged_in?
|
38
|
+
@effective_user and @real_user
|
39
|
+
end
|
40
|
+
|
41
|
+
def user?
|
42
|
+
logged_in?
|
43
|
+
end
|
44
|
+
|
45
|
+
def current_user
|
46
|
+
effective_user
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_user?
|
50
|
+
!!effective_user
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
unloadable(Api)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class APIController < ApplicationController
|
2
|
+
layout false
|
3
|
+
|
4
|
+
skip_before_filter true
|
5
|
+
skip_before_filter :verify_authenticity_token
|
6
|
+
|
7
|
+
before_filter :setup_api
|
8
|
+
|
9
|
+
### skip_before_filter :set_current_user if Rails.env.production?
|
10
|
+
|
11
|
+
##
|
12
|
+
# /api/foo/2/bar/4 -> api.call('/foo/2/bar/4')
|
13
|
+
#
|
14
|
+
def call
|
15
|
+
path = params[:path]
|
16
|
+
mode = params['mode'] || (request.get? ? 'read' : 'write')
|
17
|
+
|
18
|
+
result = api.mode(mode).call(path, params)
|
19
|
+
|
20
|
+
respond_with(result)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
#
|
25
|
+
def index
|
26
|
+
json = json_for(api.index)
|
27
|
+
|
28
|
+
respond_to do |wants|
|
29
|
+
wants.json{ render(:json => json) }
|
30
|
+
wants.html{ render(:text => json, :content_type => 'text/plain') }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def respond_with(result)
|
37
|
+
json = json_for(result)
|
38
|
+
|
39
|
+
respond_to do |wants|
|
40
|
+
wants.json{ render :json => json, :status => result.status.code }
|
41
|
+
wants.html{ render :text => json, :status => result.status.code, :content_type => 'text/plain' }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# if you don't have yajl-ruby and yajl/json_gem loaded your json will suck
|
46
|
+
#
|
47
|
+
def json_for(object)
|
48
|
+
if Rails.env.production?
|
49
|
+
::JSON.generate(object)
|
50
|
+
else
|
51
|
+
::JSON.pretty_generate(object, :max_nesting => 0)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_api
|
56
|
+
email, password = http_basic_auth_info
|
57
|
+
|
58
|
+
if !email.blank? and !password.blank?
|
59
|
+
user = User.find_by_email(email)
|
60
|
+
if user.password == password
|
61
|
+
@api = Api.new(user)
|
62
|
+
else
|
63
|
+
render(:nothing => true, :status => :unauthorized)
|
64
|
+
return
|
65
|
+
end
|
66
|
+
else
|
67
|
+
if defined?(current_user)
|
68
|
+
if current_user
|
69
|
+
@api = Api.new(current_user)
|
70
|
+
else
|
71
|
+
render(:nothing => true, :status => :unauthorized)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
@api = Api.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def api
|
80
|
+
@api
|
81
|
+
end
|
82
|
+
|
83
|
+
def http_basic_auth
|
84
|
+
@http_basic_auth ||= (
|
85
|
+
request.env['HTTP_AUTHORIZATION'] ||
|
86
|
+
request.env['X-HTTP_AUTHORIZATION'] ||
|
87
|
+
request.env['X_HTTP_AUTHORIZATION'] ||
|
88
|
+
request.env['REDIRECT_X_HTTP_AUTHORIZATION'] ||
|
89
|
+
''
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def http_basic_auth_info
|
94
|
+
username, password =
|
95
|
+
ActiveSupport::Base64.decode64(http_basic_auth.split.last.to_s).split(/:/, 2)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
ApiController = APIController ### rails is a bitch - shut her up
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class DaoGenerator < Rails::Generators::NamedBase
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
|
4
|
+
def copy_api_file
|
5
|
+
copy_file("api.rb", "app/api.rb")
|
6
|
+
|
7
|
+
copy_file("api_controller.rb", "app/controllers/api_controller.rb")
|
8
|
+
|
9
|
+
route("match 'api/*path' => 'api#call', :as => 'api'")
|
10
|
+
route("match 'api' => 'api#index', :as => 'api_index'")
|
11
|
+
|
12
|
+
gem("yajl-ruby")
|
13
|
+
|
14
|
+
application(
|
15
|
+
<<-__
|
16
|
+
|
17
|
+
config.after_initialize do
|
18
|
+
require 'app/api.rb'
|
19
|
+
require 'yajl/json_gem'
|
20
|
+
end
|
21
|
+
|
22
|
+
config.autoload_paths += %w( app )
|
23
|
+
|
24
|
+
__
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Api =
|
2
|
+
Dao.api do
|
3
|
+
|
4
|
+
description 'ping!'
|
5
|
+
endpoint('/ping'){
|
6
|
+
data.update :time => Time.now
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
## this is simply a suggest way to model your api. it is not required.
|
13
|
+
#
|
14
|
+
attr_accessor :effective_user
|
15
|
+
attr_accessor :real_user
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
options = args.extract_options!.to_options!
|
19
|
+
effective_user = args.shift || options[:effective_user] || options[:user]
|
20
|
+
real_user = args.shift || options[:real_user] || effective_user
|
21
|
+
@effective_user = user_for(effective_user) if effective_user
|
22
|
+
@real_user = user_for(real_user) if real_user
|
23
|
+
@real_user ||= @effective_user
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_for(arg)
|
27
|
+
User.find(arg)
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method('user', 'effective_user')
|
31
|
+
alias_method('user=', 'effective_user=')
|
32
|
+
|
33
|
+
def api
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def logged_in?
|
38
|
+
@effective_user and @real_user
|
39
|
+
end
|
40
|
+
|
41
|
+
def user?
|
42
|
+
logged_in?
|
43
|
+
end
|
44
|
+
|
45
|
+
def current_user
|
46
|
+
effective_user
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_user?
|
50
|
+
!!effective_user
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
unloadable(Api)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class APIController < ApplicationController
|
2
|
+
layout false
|
3
|
+
|
4
|
+
skip_before_filter true
|
5
|
+
skip_before_filter :verify_authenticity_token
|
6
|
+
|
7
|
+
before_filter :setup_api
|
8
|
+
|
9
|
+
### skip_before_filter :set_current_user if Rails.env.production?
|
10
|
+
|
11
|
+
##
|
12
|
+
# /api/foo/2/bar/4 -> api.call('/foo/2/bar/4')
|
13
|
+
#
|
14
|
+
def call
|
15
|
+
path = params[:path]
|
16
|
+
mode = params['mode'] || (request.get? ? 'read' : 'write')
|
17
|
+
|
18
|
+
result = api.mode(mode).call(path, params)
|
19
|
+
|
20
|
+
respond_with(result)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
#
|
25
|
+
def index
|
26
|
+
json = json_for(api.index)
|
27
|
+
|
28
|
+
respond_to do |wants|
|
29
|
+
wants.json{ render(:json => json) }
|
30
|
+
wants.html{ render(:text => json, :content_type => 'text/plain') }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def respond_with(result)
|
37
|
+
json = json_for(result)
|
38
|
+
|
39
|
+
respond_to do |wants|
|
40
|
+
wants.json{ render :json => json, :status => result.status.code }
|
41
|
+
wants.html{ render :text => json, :status => result.status.code, :content_type => 'text/plain' }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# if you don't have yajl-ruby and yajl/json_gem loaded your json will suck
|
46
|
+
#
|
47
|
+
def json_for(object)
|
48
|
+
if Rails.env.production?
|
49
|
+
::JSON.generate(object)
|
50
|
+
else
|
51
|
+
::JSON.pretty_generate(object, :max_nesting => 0)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def setup_api
|
56
|
+
email, password = http_basic_auth_info
|
57
|
+
|
58
|
+
if !email.blank? and !password.blank?
|
59
|
+
user = User.find_by_email(email)
|
60
|
+
if user.password == password
|
61
|
+
@api = Api.new(user)
|
62
|
+
else
|
63
|
+
render(:nothing => true, :status => :unauthorized)
|
64
|
+
return
|
65
|
+
end
|
66
|
+
else
|
67
|
+
if defined?(current_user)
|
68
|
+
if current_user
|
69
|
+
@api = Api.new(current_user)
|
70
|
+
else
|
71
|
+
render(:nothing => true, :status => :unauthorized)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
@api = Api.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def api
|
80
|
+
@api
|
81
|
+
end
|
82
|
+
|
83
|
+
def http_basic_auth
|
84
|
+
@http_basic_auth ||= (
|
85
|
+
request.env['HTTP_AUTHORIZATION'] ||
|
86
|
+
request.env['X-HTTP_AUTHORIZATION'] ||
|
87
|
+
request.env['X_HTTP_AUTHORIZATION'] ||
|
88
|
+
request.env['REDIRECT_X_HTTP_AUTHORIZATION'] ||
|
89
|
+
''
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def http_basic_auth_info
|
94
|
+
username, password =
|
95
|
+
ActiveSupport::Base64.decode64(http_basic_auth.split.last.to_s).split(/:/, 2)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
ApiController = APIController ### rails is a bitch - shut her up
|