actn-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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}');