actn-api 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.env +2 -0
  3. data/.gitignore +17 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/Procfile +11 -0
  8. data/README.md +130 -0
  9. data/Rakefile +16 -0
  10. data/actn-api.gemspec +33 -0
  11. data/apis/core/backend.rb +103 -0
  12. data/apis/core/frontend.rb +46 -0
  13. data/apis/public/connect.rb +40 -0
  14. data/apis/public/delete.rb +15 -0
  15. data/apis/public/query.rb +26 -0
  16. data/apis/public/upsert.rb +16 -0
  17. data/bin/actn-api +36 -0
  18. data/config/common.rb +16 -0
  19. data/config/core.rb +1 -0
  20. data/config/haproxy.cfg +73 -0
  21. data/config/public.rb +5 -0
  22. data/db/1_api.sql +9 -0
  23. data/db/schemas/client.json +41 -0
  24. data/db/schemas/user.json +23 -0
  25. data/lib/actn/api/client.rb +92 -0
  26. data/lib/actn/api/core.rb +35 -0
  27. data/lib/actn/api/goliath/params.rb +70 -0
  28. data/lib/actn/api/goliath/validator.rb +54 -0
  29. data/lib/actn/api/mw/auth.rb +122 -0
  30. data/lib/actn/api/mw/cors.rb +58 -0
  31. data/lib/actn/api/mw/no_xss.rb +28 -0
  32. data/lib/actn/api/public.rb +89 -0
  33. data/lib/actn/api/user.rb +59 -0
  34. data/lib/actn/api/version.rb +5 -0
  35. data/lib/actn/api.rb +16 -0
  36. data/test/actn/test_backend.rb +81 -0
  37. data/test/actn/test_client.rb +31 -0
  38. data/test/actn/test_connect.rb +42 -0
  39. data/test/actn/test_delete.rb +53 -0
  40. data/test/actn/test_frontend.rb +32 -0
  41. data/test/actn/test_query.rb +60 -0
  42. data/test/actn/test_upsert.rb +77 -0
  43. data/test/actn/test_user.rb +37 -0
  44. data/test/minitest_helper.rb +27 -0
  45. data/test/support/test.html +7 -0
  46. data/views/core/app.erb +1 -0
  47. data/views/public/connect.erb +123 -0
  48. metadata +258 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 807e280786d02db2159f98d45e26f1003261d70b
4
+ data.tar.gz: 9b4cf9eae9b9013c4fbe6c67cefe8c05d052dfea
5
+ SHA512:
6
+ metadata.gz: 59e325499327105f37db20082cba9c8f188c24319693c57c457a5f799bffceceb94da8a01b11b900b3d15b53d418f421ce94c8e1932701eee89f1e3670966398
7
+ data.tar.gz: 6c4c0f4184b3e6f0a6cdc119357128ce01d3b54979bc8167ce486972be09432ff11fd70b77c3e2c3045bd56ec31ea18c83044100f7f35866fc6a1ade8a14081b
data/.env ADDED
@@ -0,0 +1,2 @@
1
+ DATABASE_URL=postgres://localhost:5432/actn_development
2
+ SECRET=1fd4f0fcb4c1be3c0f59dc4ee207dfe4e380d04933449f939b97f1682fd236c24c52ce66ac7aeb79b5528e9a0cee76e83c82554e3b2c70307d3519350e3ba632
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in actn-api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Onur Uyar
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Procfile ADDED
@@ -0,0 +1,11 @@
1
+ web-pub-connect: bundle exec actn-api public/connect -p 6000 -sv -c config/public.rb
2
+ web-pub-query: bundle exec actn-api public/query -p 6001 -sv -c config/public.rb
3
+ web-pub-upsert: bundle exec actn-api public/upsert -p 6002 -sv -c config/public.rb
4
+ web-pub-delete: bundle exec actn-api public/delete -p 6003 -sv -c config/public.rb
5
+
6
+ web-core-back: bundle exec actn-api core/backend -p 7000 -sv -c config/core.rb
7
+ web-core-front: bundle exec actn-api core/frontend -p 7001 -sv -c config/core.rb
8
+
9
+ worker-jobs: bundle exec rake jobs:work
10
+
11
+ web: haproxy -f ./config/haproxy.cfg
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Actn::Api
2
+
3
+ Actn.io Core & Public APIs
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'actn-api'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install actn-api
18
+
19
+ ## Usage
20
+
21
+
22
+ ### Core Api
23
+
24
+ **HEADERS**
25
+
26
+ Origin:
27
+ X_APIKEY:
28
+ X_SECRET:
29
+ Content-Type: application/json"
30
+
31
+ **POST /:set**
32
+
33
+ creates record on set
34
+
35
+ **GET /:set**
36
+
37
+ fetches all/scoped records
38
+ params where, select, page, limit
39
+
40
+ **GET /:set/:id**
41
+
42
+ fetches record with given id
43
+
44
+ **PUT /:set/:id**
45
+
46
+ updates record
47
+
48
+ **DELETE /:set/:id**
49
+
50
+ destroy record
51
+
52
+ ### Models
53
+
54
+ name,[table_schema,schema,indexes,hooks]
55
+
56
+
57
+ ```
58
+ curl \
59
+ -H "Origin: http://localhost:5000" \
60
+ -H "X_APIKEY: 2b2efa40a38c6091de9aad0e42432559" \
61
+ -H "X_SECRET: d2bd70f91b102d8897019834f8ff6e18" \
62
+ -H "Content-Type: application/json" \
63
+ -d '{"name":"ModelName","schema":{"title":"Model Name","type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"age":{"description":"Age in years","type":"integer","minimum":0}},"required":["first_name","last_name"]},"indexes":[{"cols":{"apikey":"text"},"unique":true}],"hooks":{"after_create":[{"name":"Trace","run_at":"Time.now + 2 # 2 seconds later"},{"name":"Trace"}]}}' \
64
+ -X POST "http://core.lvh.me:5000/api/models"
65
+ ```
66
+
67
+ ### Clients
68
+
69
+ domain
70
+
71
+ ### User
72
+
73
+ first_name, last_name, email, password, password_confirmation, [phone]
74
+
75
+
76
+
77
+ ### JSON Api
78
+
79
+ First you need to load js client
80
+ ```
81
+ <script id="actn" src="http://api.YOUR_DOMAIN.actn.io/client?apikey=YOUR_API_KEY"></script>
82
+ ```
83
+
84
+ Then you can use cors api via js client
85
+
86
+ ```
87
+ actn.post({
88
+ path: "/:set(/:anything/:can/:go/:after/:set)",
89
+ data: {"name": "hello"},
90
+ success: function(data){},
91
+ error: function(errors){}
92
+ })
93
+ actn.get({
94
+ path: "/:set(/:anything/:can/:go/:after/:set)",
95
+ data: {
96
+ select: 'field,names',
97
+ where:{
98
+ not: { active: true },
99
+ or: { age: { ">": 20, "<": 50} },
100
+ name: [ "!=", "Igor" ],
101
+ name: "Bonzo"
102
+ },
103
+ order_by: "age",
104
+ },
105
+ success: function(data){},
106
+ error: function(errors){}
107
+ })
108
+ actn.put({
109
+ path: "/:set(/:anything/:can/:go/:after/:set)",
110
+ data: {"uuid": "uuid-12345", "name": "hello"},
111
+ success: function(data){},
112
+ error: function(errors){}
113
+ })
114
+ actn.delete({
115
+ path: "/:set(/:anything/:can/:go/:after/:set)",
116
+ data: {"uuid": "uuid-12345"},
117
+ success: function(data){},
118
+ error: function(errors){}
119
+ })
120
+
121
+ options =
122
+ ```
123
+
124
+ ## Contributing
125
+
126
+ 1. Fork it ( http://github.com/<my-github-username>/actn-api/fork )
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/**/test*.rb']
7
+ end
8
+
9
+ task :default => :test
10
+
11
+ ENV['DATABASE_URL'] ||= "postgres://localhost:5432/actn_#{ENV['RACK_ENV'] ||= "development"}"
12
+
13
+ require 'actn/api'
14
+
15
+ load "actn/db/tasks/db.rake"
16
+ load "actn/jobs/tasks/jobs.rake"
data/actn-api.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'actn/api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "actn-api"
8
+ spec.version = Actn::Api::VERSION
9
+ spec.authors = ["Onur Uyar"]
10
+ spec.email = ["me@onuruyar.com"]
11
+ spec.summary = %q{Actn.io API}
12
+ spec.homepage = "https://github.com/hackberry-gh/actn-api"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["apis","lib","views","config"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "minitest"
23
+ spec.add_development_dependency "em-http-request"
24
+
25
+ spec.add_dependency "oj"
26
+ spec.add_dependency "goliath"
27
+ spec.add_dependency "rack_csrf"
28
+ spec.add_dependency "tilt"
29
+ spec.add_dependency "helmet"
30
+
31
+ spec.add_dependency 'actn-db'
32
+ spec.add_dependency 'actn-jobs'
33
+ end
@@ -0,0 +1,103 @@
1
+ require 'actn/api/core'
2
+
3
+ class Backend < Actn::Api::Core
4
+
5
+ use Goliath::Rack::BarrierAroundwareFactory, Actn::Api::Mw::Auth, with_session: true
6
+
7
+ helpers do
8
+
9
+ def set
10
+ env['set'] ||= Actn::DB::Set.new(:core, params[:set])
11
+ end
12
+
13
+ def model
14
+ env['model'] ||= params[:set].classify.constantize
15
+ end
16
+
17
+ def name
18
+ env['name'] ||= params[:set].singularize
19
+ end
20
+
21
+ def criteria
22
+ env['criteria'] ||= begin
23
+ criteria = query || {}
24
+ criteria['where'] ||= {}
25
+ criteria['limit'] ||= limit
26
+ criteria['offset'] = offset
27
+ criteria
28
+ end
29
+ end
30
+
31
+ def limit
32
+ 50
33
+ end
34
+
35
+ def page
36
+ ((query['page'] || 1).to_i - 1)
37
+ end
38
+
39
+ def offset
40
+ limit * page
41
+ end
42
+
43
+ def record
44
+ unless record = model.find(params[:uuid])
45
+ raise Goliath::Validation::Error.new(404,"Record not found")
46
+ end
47
+ record
48
+ end
49
+
50
+ def authenticate!
51
+ raise Goliath::Validation::Error(401,"Unauthorized") unless current_user
52
+ end
53
+
54
+ def current_user
55
+ User.find(session[:user_uuid])
56
+ end
57
+
58
+ def query
59
+ params['query']
60
+ end
61
+
62
+ def data
63
+ params['data']
64
+ end
65
+
66
+ end
67
+
68
+ before "*" do
69
+ content_type :json
70
+ authenticate!
71
+ end
72
+
73
+ get "/:set" do
74
+ set.query(criteria)
75
+ end
76
+
77
+ get "/:set/:uuid" do
78
+ set.find(params[:uuid])
79
+ end
80
+
81
+ post "/:set" do
82
+ created = model.create(data)
83
+ if created.persisted?
84
+ created.to_json
85
+ else
86
+ status 406
87
+ created.errors.to_json
88
+ end
89
+ end
90
+
91
+ put "/:set/:uuid" do
92
+ unless record.update(data)
93
+ status 406
94
+ record.errors.to_json
95
+ else
96
+ record.to_json
97
+ end
98
+ end
99
+
100
+ delete "/:set/:uuid" do
101
+ record.destroy.to_json
102
+ end
103
+ end
@@ -0,0 +1,46 @@
1
+ require 'actn/api/core'
2
+ require 'tilt/erb'
3
+
4
+ class Frontend < Actn::Api::Core
5
+
6
+ settings[:public_folder] = "#{Actn::Api.root}/public"
7
+ settings[:views_folder] = "#{Actn::Api.root}/views"
8
+
9
+ helpers do
10
+
11
+ def signin
12
+ session[:user_uuid] = User.find_for_auth(data)
13
+ end
14
+
15
+ def signout
16
+ session[:user_uuid] = nil
17
+ end
18
+
19
+ def query
20
+ params['query']
21
+ end
22
+
23
+ def data
24
+ params['data']
25
+ end
26
+
27
+ end
28
+
29
+ post "/signin" do
30
+ content_type :json
31
+ raise Goliath::Validation::Error(401,"Unauthorized") unless signin
32
+ OK
33
+ end
34
+
35
+ delete "/signout" do
36
+ content_type :json
37
+ signout
38
+ OK
39
+ end
40
+
41
+ get "*" do
42
+ content_type :html
43
+ erb :'core/app'
44
+ end
45
+
46
+ end
@@ -0,0 +1,40 @@
1
+ require 'actn/api/public'
2
+ require 'actn/core_ext/string'
3
+ require 'goliath/rack/templates'
4
+ require 'tilt/erb'
5
+
6
+ class Connect < Actn::Api::Public
7
+
8
+ include Goliath::Rack::Templates
9
+
10
+ ##
11
+ # GET /connect.js, renders actn.io js api client
12
+
13
+ def response(env)
14
+ authorize!
15
+
16
+ [
17
+ 200, CT_JS, erb(:'public/connect', {}, {
18
+
19
+ host: env['HTTP_HOST'], apikey: query['apikey'],
20
+
21
+ csrf: Rack::Csrf.token(env), ttl: Client::TTL * 1000
22
+
23
+ } )
24
+ ]
25
+ end
26
+
27
+ private
28
+
29
+ def authorize!
30
+ begin
31
+ puts env['HTTP_REFERER'].to_domain, query['apikey']
32
+ client = Client.find_for_auth(env['HTTP_REFERER'].to_domain, query['apikey'])
33
+ puts "CLIENT #{client.inspect}"
34
+ client.set_session env['rack.session'].id
35
+ rescue
36
+ raise Goliath::Validation::UnauthorizedError.new
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,15 @@
1
+ require 'actn/api/public'
2
+
3
+ class Delete < Actn::Api::Public
4
+
5
+ use Goliath::Rack::Validation::RequestMethod, %w(DELETE OPTIONS)
6
+
7
+ ##
8
+ # GET /table_name?query={ where: { uuid: 1 } }
9
+
10
+ def process table, path
11
+
12
+ Actn::DB::Set[table].delete({uuid: query['uuid']})
13
+ end
14
+
15
+ end
@@ -0,0 +1,26 @@
1
+ require 'actn/api/public'
2
+
3
+ class Query < Actn::Api::Public
4
+
5
+ use Goliath::Rack::Validation::RequestMethod, %w(GET HEAD OPTIONS)
6
+
7
+ ##
8
+ # GET /table_name?query={ where: { uuid: 1 } }
9
+
10
+ def process table, path
11
+
12
+ unless query['unscoped']
13
+
14
+ query['where'] ||= {}
15
+
16
+ query['where']['path'] = path
17
+
18
+ end
19
+
20
+ query['limit'] ||= limit
21
+ query['offset'] = offset
22
+
23
+ Actn::DB::Set[table].query(query)
24
+ end
25
+
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'actn/api/public'
2
+
3
+ class Upsert < Actn::Api::Public
4
+
5
+ use Goliath::Rack::Validation::RequestMethod, %w(GET POST PUT PATCH OPTIONS)
6
+
7
+ ##
8
+ # POST /table_name
9
+
10
+ def process table, path
11
+ data['path'] = path
12
+ puts data.inspect
13
+ Actn::DB::Set[table].validate_and_upsert(data)
14
+ end
15
+
16
+ end
data/bin/actn-api ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort unless api_name = ARGV.shift
4
+ if api_name == "console"
5
+ api_name = "public/query"
6
+ ARGV << "-C"
7
+ require "actn/db"
8
+ require "actn/jobs"
9
+ end
10
+
11
+ $stdout.sync = true
12
+ $stderr.sync = true
13
+
14
+ $LOAD_PATH.unshift File.expand_path('../', __FILE__)
15
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
16
+
17
+ ENV['DATABASE_URL'] ||= "postgres://localhost:5432/actn_#{ENV['RACK_ENV'] ||= "development"}"
18
+
19
+ require 'i18n'
20
+ require "actn/api"
21
+ require "active_support/inflector"
22
+ require "goliath/api"
23
+ require "goliath/runner"
24
+ require "#{api_name}"
25
+
26
+ unless api_name == "console"
27
+ ARGV[ARGV.length-1] = "#{Actn::Api.gem_root}/#{ARGV[ARGV.length-1]}"
28
+ end
29
+
30
+ I18n.enforce_available_locales = false
31
+
32
+ api_class = api_name.classify.demodulize.constantize
33
+ runner = Goliath::Runner.new(ARGV, nil)
34
+ runner.api = api_class.new
35
+ runner.app = Goliath::Rack::Builder.build(api_class, runner.api)
36
+ runner.run
data/config/common.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'oj'
2
+ require 'i18n'
3
+
4
+ require 'actn/api/client'
5
+ require 'actn/api/user'
6
+ require 'actn/db/model'
7
+ require 'actn/jobs/job'
8
+ require 'actn/paths'
9
+
10
+ Oj.default_options = { time_format: :ruby, mode: :compat }
11
+ I18n.enforce_available_locales = false
12
+
13
+ ::Client = Actn::Api::Client unless Object.const_defined? "Client"
14
+ ::User = Actn::Api::User unless Object.const_defined? "User"
15
+ ::Model = Actn::DB::Model unless Object.const_defined? "Model"
16
+ ::Job = Actn::Jobs::Job unless Object.const_defined? "Job"
data/config/core.rb ADDED
@@ -0,0 +1 @@
1
+ import("common")
@@ -0,0 +1,73 @@
1
+ global
2
+ pidfile /var/run/haproxy-id.pid
3
+ user root
4
+ maxconn 2048
5
+
6
+ defaults
7
+ mode http
8
+
9
+ timeout connect 5000ms
10
+ timeout client 30000ms
11
+ timeout server 30000ms
12
+
13
+ stats enable
14
+ stats auth admin:password
15
+ stats uri /monitor
16
+ stats refresh 5s
17
+ retries 5
18
+
19
+ option httpchk GET /status
20
+ option redispatch
21
+ option httpclose
22
+ option abortonclose
23
+ option forwardfor
24
+ option http-server-close
25
+
26
+ balance roundrobin
27
+
28
+ frontend actn-api
29
+
30
+ bind :5000
31
+
32
+ monitor-uri /haproxy
33
+
34
+
35
+ acl a_pub_host hdr_beg(host) -i api.
36
+ acl a_pub_connect_path path /connect
37
+ acl a_pub_query_method method GET HEAD OPTIONS
38
+ acl a_pub_upsert_method method POST PUT PATCH
39
+ acl a_pub_delete_method method DELETE
40
+
41
+
42
+ acl a_core_host hdr_beg(host) -i core.
43
+ acl a_core_api_path path_beg /api
44
+
45
+
46
+ use_backend b_pub_connect if a_pub_connect_path a_pub_host
47
+ use_backend b_pub_query if a_pub_query_method a_pub_host
48
+ use_backend b_pub_upsert if a_pub_upsert_method a_pub_host
49
+ use_backend b_pub_delete if a_pub_delete_method a_pub_host
50
+
51
+ use_backend b_core_back if a_core_api_path a_core_host
52
+ use_backend b_core_front if a_core_host
53
+
54
+
55
+ backend b_pub_connect
56
+ server srv_pub_connect_1 localhost:6000
57
+
58
+ backend b_pub_query
59
+ server srv_pub_query_1 localhost:6001
60
+
61
+ backend b_pub_upsert
62
+ server srv_pub_upsert_1 localhost:6002
63
+
64
+ backend b_pub_delete
65
+ server srv_pub_delete_1 localhost:6003
66
+
67
+
68
+ backend b_core_back
69
+ reqrep ^([^\ :]*)\ /api/(.*) \1\ /\2
70
+ server srv_core_back_1 localhost:7000
71
+
72
+ backend b_core_front
73
+ server srv_core_front_1 localhost:7001
data/config/public.rb ADDED
@@ -0,0 +1,5 @@
1
+ import("common")
2
+
3
+ config[:template] = {
4
+ :views => "#{Actn::Api.gem_root}/views",
5
+ }
data/db/1_api.sql ADDED
@@ -0,0 +1,9 @@
1
+ SET search_path TO public;
2
+
3
+ SELECT plv8_startup();
4
+
5
+ SELECT __create_table('core','clients');
6
+ SELECT __create_index('core','clients', '{"cols": { "apikey": "text", "domain": "text" },"unique": true}');
7
+
8
+ SELECT __create_table('core','users');
9
+ SELECT __create_index('core','users', '{"cols": {"email": "text"},"unique": true}');