team_fastlane-sequel_base_service 1.0.0

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
+ 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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApiBaseController < ActionController::Base
4
+ include Responses
5
+
6
+ rescue_from ArgumentError, with: :unprocessable_entity
7
+ rescue_from StandardError, with: :technical_error
8
+ end
@@ -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,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'net/http'
5
+
6
+ port = ENV.fetch('PORT', 3000)
7
+
8
+ health_check = Net::HTTP.get_response(URI("http://127.0.0.1:#{port}/health_check"))
9
+ raise health_check.body if health_check.code.to_i != 200
@@ -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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequel
4
+ class TimestampMigrator
5
+ def default_schema_table
6
+ Rails.application.config.schema_migrations_table
7
+ rescue NoMethodError
8
+ :team_fastlane_schema_migrations
9
+ end
10
+ end
11
+ end
@@ -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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ get '/health_check', to: 'health_check#check'
5
+ end
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TeamFastlane
4
+ module SequelBaseService
5
+ VERSION = '1.0.0'
6
+ end
7
+ 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: []