team_fastlane-sequel_base_service 1.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.adoc +110 -0
- data/README.adoc +44 -0
- data/app/controllers/api_base_controller.rb +8 -0
- data/app/controllers/concerns/responses.rb +50 -0
- data/app/controllers/health_check_controller.rb +21 -0
- data/bin/health_check +9 -0
- data/config/initializers/camelizer.rb +11 -0
- data/config/initializers/filter_parameter_logging.rb +8 -0
- data/config/initializers/migrations_table.rb +11 -0
- data/config/initializers/oracle_binding_variables.rb +56 -0
- data/config/routes.rb +5 -0
- data/lib/team_fastlane/sequel_base_service/database.rb +23 -0
- data/lib/team_fastlane/sequel_base_service/version.rb +7 -0
- data/lib/team_fastlane/sequel_base_service.rb +23 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6767b25b6ef83e0161e2cad7af91e84fc447bbf3314b0f085c5be03d872063ce
|
4
|
+
data.tar.gz: eaecbcd7fdb58e511358d0717973930d6f43a9de53adac084d701c245b84f25b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b4a54e6529d050852c5e3020eeb0e57c1a7cdc95f43b43d07603d571f0b8facd1fa6d4ede7eb405d1f4b7d19ac8d4a8fe71f1fdbae598b2400699ef5c1e2ce74
|
7
|
+
data.tar.gz: 1b826be91b18de3d89bbda6ae47dca68a1e560bab640e5604ca9dcd4c0981d45700216eb8a19ba1bac3009134f556020b45fe5ed325a47eaf8fda04e8346e78d
|
data/CHANGELOG.adoc
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
= Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on https://keepachangelog.com[Keep a Changelog],
|
6
|
+
and this project adheres to https://semver.org[Semantic Versioning].
|
7
|
+
|
8
|
+
== Unreleased
|
9
|
+
|
10
|
+
== [1.0.0] - 2023-08-01
|
11
|
+
=== Changed
|
12
|
+
Renamed and restructured for release on rubygems
|
13
|
+
|
14
|
+
== [0.6.0] - 2023-06-20
|
15
|
+
=== Added
|
16
|
+
- New method for handling validation errors
|
17
|
+
|
18
|
+
== [0.5.1] - 2022-11-14
|
19
|
+
=== Added
|
20
|
+
- `create_or_replace_view_with_grants` is now available
|
21
|
+
|
22
|
+
== [0.5.0] - 2022-09-12
|
23
|
+
=== Fixed
|
24
|
+
- health check endpoint actually does test the database now
|
25
|
+
|
26
|
+
== [0.4.0] - 2022-06-03
|
27
|
+
=== Added
|
28
|
+
- Default behavior for parameter filtering
|
29
|
+
|
30
|
+
== [0.3.1] - 2022-05-05
|
31
|
+
=== Changed
|
32
|
+
- Extend `create_view_with_grants` to prevent SQL injections.
|
33
|
+
|
34
|
+
== [0.3.0] - 2022-05-04
|
35
|
+
=== Added
|
36
|
+
- New `create_view_with_grants` methods that allows to set permissions while creating a view
|
37
|
+
|
38
|
+
== [0.2.1] - 2022-03-29
|
39
|
+
=== Updated
|
40
|
+
- olive_branch version updated to 4.0.1
|
41
|
+
|
42
|
+
== [0.2.0]- 2022-01-03
|
43
|
+
=== Removed
|
44
|
+
- the rubymine debug mode fix seems to be no longer necessary
|
45
|
+
|
46
|
+
== [0.1.0] - 2021-06-03
|
47
|
+
=== Added
|
48
|
+
- Allow to configure the migrations table.
|
49
|
+
|
50
|
+
== [0.0.14] - 2021-05-27
|
51
|
+
=== Changed
|
52
|
+
- Revert change of 0.0.13 and inherit from ActionController::Base again. It wasn't working correctly in our setup.
|
53
|
+
|
54
|
+
== [0.0.13] - 2021-05-17
|
55
|
+
=== Changed
|
56
|
+
- Inherit from ApplicationController instead of ActionController::Base
|
57
|
+
(link:https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsapplicationcontroller[Rubocop]).
|
58
|
+
|
59
|
+
== [0.0.12] - 2021-04-27
|
60
|
+
=== Changed
|
61
|
+
- Updated olive_branch dependency to v4.0.0.
|
62
|
+
|
63
|
+
== [0.0.11] - 2021-01-13
|
64
|
+
=== Added
|
65
|
+
- Save from ArgumentError with `unprocessable_entity` method.
|
66
|
+
|
67
|
+
== [0.0.10] - 2020-09-15
|
68
|
+
=== Changed
|
69
|
+
- Use SQL parser to achieve a more sound binding variable implementation
|
70
|
+
|
71
|
+
== [0.0.9] - 2020-08-20
|
72
|
+
=== Added
|
73
|
+
- Default option for sequel to not dump the schema on migrate
|
74
|
+
- Default option for sequel to ignore missing migration files
|
75
|
+
|
76
|
+
== [0.0.8] - 2020-08-20
|
77
|
+
=== Removed
|
78
|
+
- Migration execution on startup (this made way too much problems everywhere)
|
79
|
+
|
80
|
+
== [0.0.7] - 2020-08-18
|
81
|
+
=== Added
|
82
|
+
- Allows the addition of a schema to load in sequel
|
83
|
+
- Execute existing migrations on startup
|
84
|
+
|
85
|
+
== [0.0.6] - 2020-07-31
|
86
|
+
=== Added
|
87
|
+
- Allows to disable binding variables by setting Sequel::Oracle::Database.skip_binding_variables to true
|
88
|
+
|
89
|
+
== [0.0.5] - 2020-07-23
|
90
|
+
=== Added
|
91
|
+
- Added response method `no_content`.
|
92
|
+
|
93
|
+
=== Changed
|
94
|
+
- Use json instead of raw text body for error responses `not_found` and `unprocessable_entity`.
|
95
|
+
|
96
|
+
== [0.0.4] - 2020-07-21
|
97
|
+
=== Added
|
98
|
+
- Added response methods `created` and `unprocessable_entity`.
|
99
|
+
|
100
|
+
== [0.0.3] - 2020-07-21
|
101
|
+
=== Added
|
102
|
+
- Allow to configure a blacklist of values that are not substituted with binding variables.
|
103
|
+
|
104
|
+
== [0.0.2] - 2020-07-21
|
105
|
+
=== Added
|
106
|
+
- All Oracle SQL statements use binding variables by default.
|
107
|
+
|
108
|
+
== [0.0.1] - 2020-07-14
|
109
|
+
=== Added
|
110
|
+
- Initial gem version based on the team_fastlane_base_service.
|
data/README.adoc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
= Team Fastlane Base Service
|
2
|
+
|
3
|
+
A service base for a ruby micro service using Sequel
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
As described by the link:../README.adoc[main readme].
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
=== Health Check
|
12
|
+
|
13
|
+
You can use the link:../bin/health_check[health_check] executable to provide a method of checking the health of the server (database included).
|
14
|
+
For example within a docker file like this:
|
15
|
+
|
16
|
+
[source, Dockerfile]
|
17
|
+
----
|
18
|
+
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "bundle", "exec", "health_check" ]
|
19
|
+
----
|
20
|
+
|
21
|
+
This makes use of an exposed endpoint called `/health_check`, which you can only use for a custom ping to check for it.
|
22
|
+
|
23
|
+
=== Default responses
|
24
|
+
|
25
|
+
This also provides some default json responses to be used in your controller. See link:./app/controllers/concerns/responses.rb[responses.rb] for more details.
|
26
|
+
|
27
|
+
To use these responses let your `ApplicationController` inherit from `ApiBaseController` and you are set.
|
28
|
+
|
29
|
+
=== Oracle Binding Variables
|
30
|
+
|
31
|
+
This Gem automatically interrupts all Oracle DB statements and substitues the values with binding variables. +
|
32
|
+
It is possible to deactivate this behaviour:
|
33
|
+
|
34
|
+
```rb
|
35
|
+
Sequel::Oracle::Database.skip_binding_variables = true
|
36
|
+
```
|
37
|
+
|
38
|
+
Beware that this is a global setting which de-/activates binding variables for the whole application.
|
39
|
+
|
40
|
+
=== Parameter handling
|
41
|
+
|
42
|
+
You get automatically camelCase to snake_case transformation for the request and the reverse for responses via the olive_branch gem.
|
43
|
+
|
44
|
+
There will be a default parameter filtering enabled. It filters passwords of various key names in development and everything in production.
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Responses
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def bad_request(errors = {})
|
9
|
+
render json: errors, status: :bad_request
|
10
|
+
end
|
11
|
+
|
12
|
+
def created(body = {})
|
13
|
+
render json: body, status: :created
|
14
|
+
end
|
15
|
+
|
16
|
+
def no_content
|
17
|
+
render json: {}, status: :no_content
|
18
|
+
end
|
19
|
+
|
20
|
+
def not_found(body = {})
|
21
|
+
render json: body, status: :not_found
|
22
|
+
end
|
23
|
+
|
24
|
+
def ok(content = {})
|
25
|
+
render json: content, status: :ok
|
26
|
+
end
|
27
|
+
|
28
|
+
def technical_error(error, status: :internal_server_error)
|
29
|
+
Rails.logger.error("#{error.message}\n#{error.backtrace.join("\n")}")
|
30
|
+
response = {error: 'Something technical went wrong. Please try again later'}
|
31
|
+
if Rails.env.development?
|
32
|
+
response[:exception] = "#{error.class.name} : #{error.message}"
|
33
|
+
response[:trace] = error.backtrace[0, 10]
|
34
|
+
end
|
35
|
+
render json: response, status:
|
36
|
+
end
|
37
|
+
|
38
|
+
def unprocessable_entity(body = {})
|
39
|
+
render json: body, status: :unprocessable_entity
|
40
|
+
end
|
41
|
+
|
42
|
+
def unauthorized(error)
|
43
|
+
technical_error(error, status: :unauthorized)
|
44
|
+
end
|
45
|
+
|
46
|
+
def validation_error(error)
|
47
|
+
Rails.logger.warn("Malformed Request: #{error.message}") if Rails.env.production?
|
48
|
+
unprocessable_entity(exception: "#{error.class.name}: #{error.message}")
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class HealthCheckController < ApiBaseController
|
4
|
+
def check
|
5
|
+
return bad_request unless Sequel::Model.db.synchronize { |conn| Sequel::Model.db.valid_connection?(conn) }
|
6
|
+
|
7
|
+
ok
|
8
|
+
rescue StandardError
|
9
|
+
bad_request
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def bad_request(_errors = {})
|
15
|
+
render plain: 'Health Check failed', status: :bad_request
|
16
|
+
end
|
17
|
+
|
18
|
+
def ok(_content = {})
|
19
|
+
render plain: 'Health Check OK', status: :ok
|
20
|
+
end
|
21
|
+
end
|
data/bin/health_check
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'olive_branch'
|
4
|
+
|
5
|
+
rails_routes = ->(env) { env['PATH_INFO'].match(%r{^/rails}) }
|
6
|
+
|
7
|
+
Rails.application.middleware.use OliveBranch::Middleware,
|
8
|
+
inflection: 'camel',
|
9
|
+
exclude_params: rails_routes,
|
10
|
+
exclude_response: rails_routes,
|
11
|
+
content_type_check: ->(_) { true }
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Be sure to restart your server when you modify this file.
|
4
|
+
|
5
|
+
# Configure sensitive parameters which will be filtered from the log file.
|
6
|
+
Rails.application.config.filter_parameters += %i[passw secret token _key crypt salt certificate otp ssn]
|
7
|
+
|
8
|
+
Rails.application.config.filter_parameters += [/.*/] if Rails.env.production?
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oracle-sql-parser'
|
4
|
+
|
5
|
+
module Sequel
|
6
|
+
module Oracle
|
7
|
+
class Database < Sequel::Database
|
8
|
+
alias super_execute execute
|
9
|
+
|
10
|
+
class_attribute :parser, default: OracleSqlParser::Grammar::GrammarParser.new
|
11
|
+
class_attribute :skip_binding_variables, default: false
|
12
|
+
|
13
|
+
def execute(sql, opts = OPTS, &)
|
14
|
+
if skip_binding_variables
|
15
|
+
super_execute sql, opts, &
|
16
|
+
else
|
17
|
+
execute_with_binding_variables sql, opts, &
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def execute_with_binding_variables(sql, opts, &)
|
24
|
+
ast = parser.parse(sql)&.ast
|
25
|
+
if ast.present?
|
26
|
+
parameterized = ast.to_parameterized
|
27
|
+
bindings = parameterized.params.values.map(&:value)
|
28
|
+
super_execute parameterized.to_sql, opts.merge(arguments: bindings), &
|
29
|
+
else
|
30
|
+
super_execute sql, opts, &
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module SequelRails
|
38
|
+
module Railties
|
39
|
+
class LogSubscriber
|
40
|
+
Binding = Struct.new(:name, keyword_init: true)
|
41
|
+
|
42
|
+
alias super_sql sql
|
43
|
+
|
44
|
+
##
|
45
|
+
# Extends the sql logger of sequel-rails.
|
46
|
+
# Adds human-readable names for the binding variables.
|
47
|
+
def sql(event)
|
48
|
+
event.payload[:binds] = (event.payload[:binds] || []).map.with_index do |bind_value, index|
|
49
|
+
[Binding.new(name: "a#{index}:"), bind_value]
|
50
|
+
end
|
51
|
+
|
52
|
+
super_sql event
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TeamFastlane
|
4
|
+
module SequelBaseService
|
5
|
+
class Database
|
6
|
+
def self.create_view_with_grants(name:, definition:, grantees:)
|
7
|
+
db = Sequel::Model.db
|
8
|
+
db.create_view(name, definition)
|
9
|
+
grantees.each do |grantee|
|
10
|
+
db.run("GRANT SELECT ON \"#{name}\" TO #{db.literal(grantee.to_sym)}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.create_or_replace_view_with_grants(name:, definition:, grantees:)
|
15
|
+
Sequel::Model.db.drop_view(name)
|
16
|
+
rescue StandardError
|
17
|
+
# Rescue drop_view errors for cases where the view did not exist
|
18
|
+
ensure
|
19
|
+
create_view_with_grants(name:, definition:, grantees:)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'team_fastlane/sequel_base_service/database'
|
4
|
+
require 'team_fastlane/sequel_base_service/version'
|
5
|
+
|
6
|
+
module TeamFastlane
|
7
|
+
module SequelBaseService
|
8
|
+
class Engine < Rails::Engine
|
9
|
+
# Needed as long we have migrations scattered around the services
|
10
|
+
config.sequel.allow_missing_migration_files = true
|
11
|
+
|
12
|
+
# Because we only create views and no tables
|
13
|
+
config.sequel.schema_dump = false
|
14
|
+
|
15
|
+
# This is a hook for having a different schema than the database user in an oracle database
|
16
|
+
config.sequel.after_connect = -> do
|
17
|
+
if Sequel::Model.db.opts[:schema]
|
18
|
+
Sequel::Model.db.run("alter session set current_schema = \"#{Sequel::Model.db.opts[:schema]}\"")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: team_fastlane-sequel_base_service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Team Fastlane
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: olive_branch
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oracle-sql-parser
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
executables:
|
44
|
+
- health_check
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files:
|
47
|
+
- README.adoc
|
48
|
+
- CHANGELOG.adoc
|
49
|
+
files:
|
50
|
+
- CHANGELOG.adoc
|
51
|
+
- README.adoc
|
52
|
+
- app/controllers/api_base_controller.rb
|
53
|
+
- app/controllers/concerns/responses.rb
|
54
|
+
- app/controllers/health_check_controller.rb
|
55
|
+
- bin/health_check
|
56
|
+
- config/initializers/camelizer.rb
|
57
|
+
- config/initializers/filter_parameter_logging.rb
|
58
|
+
- config/initializers/migrations_table.rb
|
59
|
+
- config/initializers/oracle_binding_variables.rb
|
60
|
+
- config/routes.rb
|
61
|
+
- lib/team_fastlane/sequel_base_service.rb
|
62
|
+
- lib/team_fastlane/sequel_base_service/database.rb
|
63
|
+
- lib/team_fastlane/sequel_base_service/version.rb
|
64
|
+
homepage:
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata:
|
68
|
+
rubygems_mfa_required: 'true'
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.1'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubygems_version: 3.4.10
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Gem for an internal project
|
88
|
+
test_files: []
|