koromo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 274989dcaa69f9b1c7d25faa5697bc9a645c43b1
4
+ data.tar.gz: f2f827427f6fd76bfb0fa7fd871ac8a3bef99b9f
5
+ SHA512:
6
+ metadata.gz: 29d602aeb709c3564889119de0e6f2f850e62e4d8febfbdeaed197875d0f24867e15221e92464dac57f1b6cf208492384cd767933e61dd71cb9dc9e990e68586
7
+ data.tar.gz: 2d0bb77811fe6f7dd17a67b06e9ce55251586dd82a6b9807e472d2fadec56785bf9ba8c6aebafaa5eae56a9092c04d139c6f061433e5c384ebb4ae10c5f991f3
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Ken J.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # koromo
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/koromo.svg)](https://badge.fury.io/rb/koromo) [![Code Climate](https://codeclimate.com/github/kenjij/koromo/badges/gpa.svg)](https://codeclimate.com/github/kenjij/koromo)
4
+
5
+ A proxy server for MS SQL Server to present as a RESTful service.
6
+
7
+ ## Requirements
8
+
9
+ - Ruby 2.0.0 <=
10
+ - FreeTDS library (uses the [tiny_tds](https://rubygems.org/gems/tiny_tds/) gem)
11
+
12
+ ## Getting Started
13
+
14
+ ### Install
15
+
16
+ ```
17
+ $ gem install koromo
18
+ ```
19
+
20
+ ### Use
21
+
22
+ ```
23
+ $ koromo start -c config.yml
24
+ ```
25
+
26
+ ### Examples
27
+
28
+ Config file.
29
+
30
+ ```
31
+ $ koromo_config
32
+ ```
33
+
data/bin/koromo ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ require 'kajiki'
3
+ require 'thin'
4
+ require 'koromo'
5
+
6
+
7
+ opts = Kajiki.preset_options(:server, {config: true})
8
+
9
+ Kajiki.run(opts) do |cmd|
10
+ case cmd
11
+ when 'start'
12
+ Thin::Server.start(opts[:address], opts[:port]) do
13
+ run Koromo::Server.new(opts)
14
+ end
15
+ end
16
+ end
data/bin/koromo_config ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ puts IO.read(File.expand_path('../../lib/koromo/config-example.yml',__FILE__))
data/koromo.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+ require 'koromo/version'
3
+
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'koromo'
7
+ s.version = Koromo::Version
8
+ s.authors = ['Ken J.']
9
+ s.email = ['kenjij@gmail.com']
10
+ s.summary = %q{MS SQL Server RESTful access proxy}
11
+ s.description = %q{A proxy server for MS SQL Server to present as a RESTful service.}
12
+ s.homepage = 'https://github.com/kenjij/koromo'
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_runtime_dependency 'kajiki', '~> 1.1'
20
+ s.add_runtime_dependency 'thin', '~> 1.6'
21
+ s.add_runtime_dependency 'sinatra', '~> 1.4'
22
+ s.add_runtime_dependency 'tiny_tds', '~> 1.0'
23
+ s.add_runtime_dependency 'sequel', '~> 4.0'
24
+ end
@@ -0,0 +1,64 @@
1
+ ---
2
+ # TDS options
3
+ :mssql:
4
+ # The database server user
5
+ :user: username
6
+ # The user password
7
+ :password: p4sSw0rD
8
+ # Used if :dataserver blank; can be an hostname or an IP address
9
+ :host: 192.168.0.100
10
+ # Defaults to 1433; only used if :host is configured
11
+ :port: 1433
12
+ # The default database to use
13
+ :database: master
14
+ # Other TDS options can be configure as well; default examples below
15
+ # :login_timeout: 60
16
+ # :timeout: 5
17
+ # :encoding: UTF-8
18
+ # :azure: false
19
+
20
+ :global:
21
+ :pretty_json: YES
22
+ # Basic security by requiring strings below to be passed in "auth" param
23
+ :auth_tokens:
24
+ :any:
25
+ - sEcReT_sTrInG_0N3
26
+ - SeCrEt_StRiNg_7W0
27
+
28
+ # API definitions
29
+ :resources:
30
+ # Name of the resource available via API
31
+ :resource1:
32
+ # Name of the DB table
33
+ :table: :table1
34
+ # Name of columns to return from the table
35
+ :columns:
36
+ - :id
37
+ - :name
38
+ - :description
39
+ - :date
40
+ # Name of the column to search when resource ID is present
41
+ :key: :id
42
+ # Optional; otherwise restricted to 10
43
+ :limit: 25
44
+ # Optional
45
+ :order: :date
46
+ # Optional; defaults to ASC without this option present
47
+ :desc: true
48
+ # Settings for GET calls
49
+ :get:
50
+ # Return as Hash or Array
51
+ :class: Hash
52
+ # Optional only with Hash; response will become a simple key-value pair
53
+ :value: :name
54
+ :books:
55
+ :table: :books
56
+ :columns:
57
+ - :id
58
+ - :isbn
59
+ - :title
60
+ - :author
61
+ - :date
62
+ :key: :isbn
63
+ :get:
64
+ :class: Array
@@ -0,0 +1,21 @@
1
+ require 'yaml'
2
+
3
+ module Koromo
4
+
5
+ # Load YAML config file
6
+ # @param path [String] config file
7
+ # @return [Object] config; a shared instance
8
+ def self.load_config(path)
9
+ raise 'config file missing' unless path
10
+ @config ||= YAML.load_file(path)
11
+ if file = @config[:require_file]
12
+ require File.expand_path(file, path)
13
+ end
14
+ end
15
+
16
+ # see #self.load_config
17
+ def self.config
18
+ @config
19
+ end
20
+
21
+ end
@@ -0,0 +1,54 @@
1
+ require 'json'
2
+
3
+ module Koromo
4
+
5
+ module Helper
6
+
7
+ # Convert object into JSON, optionally pretty-format
8
+ # @param obj [Object] any Ruby object
9
+ # @param opts [Hash] any JSON options
10
+ # @return [String] JSON string
11
+ def json_with_object(obj, pretty: nil, opts: nil)
12
+ return '{}' if obj.nil?
13
+ pretty ||= Koromo.config[:global][:pretty_json]
14
+ if pretty
15
+ opts = {
16
+ indent: ' ',
17
+ space: ' ',
18
+ object_nl: "\n",
19
+ array_nl: "\n"
20
+ }
21
+ end
22
+ JSON.fast_generate(json_format_value(obj), opts)
23
+ end
24
+
25
+ # Return Ruby object/value to JSON standard format
26
+ # @param val [Object]
27
+ # @return [Object]
28
+ def json_format_value(val)
29
+ case val
30
+ when Array
31
+ val.map { |v| json_format_value(v) }
32
+ when Hash
33
+ val.reduce({}) { |h, (k, v)| h.merge({k => json_format_value(v)}) }
34
+ when BigDecimal
35
+ # val.to_s('F')
36
+ val.to_f
37
+ when String
38
+ val.encode!('UTF-8', {invalid: :replace, undef: :replace})
39
+ when Time
40
+ val.utc.iso8601
41
+ else
42
+ val
43
+ end
44
+ end
45
+
46
+ def valid_token?(token, method = :any)
47
+ tokens = Koromo.config[:global][:auth_tokens][method]
48
+ return true if tokens.nil?
49
+ tokens.include?(token)
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,87 @@
1
+ require 'sinatra/base'
2
+ require 'logger'
3
+ require 'koromo/config'
4
+ require 'koromo/helper'
5
+ require 'koromo/sql'
6
+
7
+ module Koromo
8
+
9
+ # The Sinatra server
10
+ class Server < Sinatra::Base
11
+
12
+ attr_reader :rack_opts
13
+ # attr_reader :config
14
+
15
+ def initialize(opts)
16
+ super()
17
+ @rack_opts = opts
18
+ Koromo.load_config(rack_opts[:config])
19
+ end
20
+
21
+ def slogger
22
+ return logger if settings.logging
23
+ @slogger ||= Logger.new(STDOUT)
24
+ return @slogger
25
+ end
26
+
27
+ helpers Helper, SQL
28
+
29
+ configure do
30
+ set :environment, :production
31
+ enable :logging
32
+ disable :static, :dump_errors
33
+ end
34
+
35
+ before do
36
+ # @jsonp_callback = params[:callback]
37
+ halt 401 unless valid_token?(params[:auth])
38
+ setup_sql(Koromo.config)
39
+ end
40
+
41
+ get '/:resource' do |r|
42
+ result = get_resource(r, params: params)
43
+ if result
44
+ json_with_object(result)
45
+ else
46
+ fail Sinatra::NotFound
47
+ end
48
+ end
49
+
50
+ get '/:resource/:id' do |r, id|
51
+ fail Sinatra::NotFound if /\W/ =~ id
52
+ result = get_resource(r, id: id, params: params)
53
+ if result
54
+ json_with_object(result)
55
+ else
56
+ fail Sinatra::NotFound
57
+ end
58
+ end
59
+
60
+ not_found do
61
+ json_with_object({message: 'Huh, nothing here.'})
62
+ end
63
+
64
+ error 401 do
65
+ json_with_object({message: 'Oops, need a valid auth.'})
66
+ end
67
+
68
+ error do
69
+ status 500
70
+ err = env['sinatra.error']
71
+ slogger.error "#{err.class.name} - #{err}"
72
+ json_with_object({message: 'Yikes, internal error.'})
73
+ end
74
+
75
+ after do
76
+ content_type 'application/json'
77
+ # if @jsonp_callback
78
+ # content_type 'application/javascript'
79
+ # body @jsonp_callback + '(' + json_with_object(@body_object) + ')'
80
+ # else
81
+ # content_type 'application/json'
82
+ # body json_with_object(@body_object, {pretty: config[:global][:pretty_json]})
83
+ # end
84
+ end
85
+
86
+ end
87
+ end
data/lib/koromo/sql.rb ADDED
@@ -0,0 +1,96 @@
1
+ require 'sequel'
2
+
3
+
4
+ module Koromo
5
+
6
+ module SQL
7
+
8
+ def setup_sql(conf)
9
+ @config = conf
10
+ # Sequel connection setup
11
+ # Sequel.application_timezone = :local
12
+ # Sequel.database_timezone = :utc
13
+ Sequel::Model.db = Sequel.connect({adapter: 'tinytds'}.merge(config[:mssql]))
14
+ end
15
+
16
+ def config
17
+ @config
18
+ end
19
+
20
+ def config_for_resource(name)
21
+ name = name.to_sym
22
+ c = config[:resources][name]
23
+ c[:limit] ||= 10
24
+ c
25
+ end
26
+
27
+ # Get model classes
28
+ def model_for_resource(name)
29
+ name = name.to_sym
30
+ @models ||= {}
31
+ return nil unless rc = config_for_resource(name)
32
+ if @models[name].nil?
33
+ m = Class.new(Sequel::Model)
34
+ m.set_dataset(rc[:table])
35
+ @models[name] = m
36
+ end
37
+ @models[name]
38
+ end
39
+
40
+ def run_query(query)
41
+ result = mssql.execute(query)
42
+ records = []
43
+ result.each(cache_rows: false) do |row|
44
+ record = {}
45
+ row.each { |k, v| record[k] = convert_value(v) }
46
+ records.push record
47
+ end
48
+ records
49
+ # rescue => e
50
+ # puts e.message
51
+ # raise
52
+ end
53
+
54
+ def get_resource(name, **args)
55
+ return nil unless model = model_for_resource(name)
56
+ p args[:params]
57
+ conf = config_for_resource(name)
58
+ set = model.select(*conf[:columns])
59
+ if args[:id]
60
+ array = set.where(conf[:key] => args[:id]).all
61
+ else
62
+ if args[:params]
63
+ p_limit = args[:params][:limit]
64
+ p_limit = p_limit.to_i if p_limit.class == String
65
+ p_order = args[:params][:order]
66
+ p_desc = true if args[:params][:desc]
67
+ p_desc = false if args[:params][:asc]
68
+ end
69
+ p_limit ||= conf[:limit]
70
+ p_order ||= conf[:order]
71
+ p_desc ||= conf[:desc]
72
+ set = set.limit(p_limit)
73
+ set = (p_desc ? set.reverse_order(p_order) : set.order(p_order))
74
+ p set.sql
75
+ array = set.all
76
+ end
77
+ return nil if array.empty?
78
+ case conf[:get][:class]
79
+ when 'Hash'
80
+ result = {}
81
+ key = conf[:key]
82
+ val = conf[:get][:value]
83
+ array.each do |r|
84
+ rec = r.values
85
+ result.store(rec.delete(key), val ? rec[val] : rec)
86
+ end
87
+ when 'Array'
88
+ result = array.map{ |r| r.values }
89
+ end
90
+ return result[0] if args[:id] && result.class == Array
91
+ result
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,5 @@
1
+ module Koromo
2
+
3
+ Version = '0.0.1'
4
+
5
+ end
data/lib/koromo.rb ADDED
@@ -0,0 +1 @@
1
+ require 'koromo/server'
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: koromo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ken J.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kajiki
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thin
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tiny_tds
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sequel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
83
+ description: A proxy server for MS SQL Server to present as a RESTful service.
84
+ email:
85
+ - kenjij@gmail.com
86
+ executables:
87
+ - koromo
88
+ - koromo_config
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - LICENSE
93
+ - README.md
94
+ - bin/koromo
95
+ - bin/koromo_config
96
+ - koromo.gemspec
97
+ - lib/koromo.rb
98
+ - lib/koromo/config-example.yml
99
+ - lib/koromo/config.rb
100
+ - lib/koromo/helper.rb
101
+ - lib/koromo/server.rb
102
+ - lib/koromo/sql.rb
103
+ - lib/koromo/version.rb
104
+ homepage: https://github.com/kenjij/koromo
105
+ licenses:
106
+ - MIT
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 2.4.3
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: MS SQL Server RESTful access proxy
128
+ test_files: []