kabk 0.2.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.
Potentially problematic release.
This version of kabk might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +27 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +108 -0
- data/Kabk_logo.svg +33 -0
- data/LICENSE +21 -0
- data/README.md +101 -0
- data/doc/Kabk/Adapters/Base.html +854 -0
- data/doc/Kabk/Adapters/SequelAdapter.html +948 -0
- data/doc/Kabk/Adapters.html +120 -0
- data/doc/Kabk/ApiError.html +511 -0
- data/doc/Kabk/Auth/JwtStrategy.html +551 -0
- data/doc/Kabk/Auth.html +118 -0
- data/doc/Kabk/Concurrency.html +297 -0
- data/doc/Kabk/ConcurrencyConflictError.html +225 -0
- data/doc/Kabk/Error.html +140 -0
- data/doc/Kabk/ExportHandler.html +381 -0
- data/doc/Kabk/Field.html +2160 -0
- data/doc/Kabk/ForbiddenError.html +225 -0
- data/doc/Kabk/InvalidFieldError.html +136 -0
- data/doc/Kabk/InvalidOldPasswordError.html +225 -0
- data/doc/Kabk/NotFoundError.html +225 -0
- data/doc/Kabk/QueryBuilder.html +551 -0
- data/doc/Kabk/Registry.html +608 -0
- data/doc/Kabk/RelationHydrator.html +480 -0
- data/doc/Kabk/Resource.html +1986 -0
- data/doc/Kabk/ResourceBuilder.html +1002 -0
- data/doc/Kabk/RestEngine.html +879 -0
- data/doc/Kabk/SchemaRenderer.html +318 -0
- data/doc/Kabk/UnauthorizedError.html +225 -0
- data/doc/Kabk/UploadHandler.html +308 -0
- data/doc/Kabk/ValidationError.html +225 -0
- data/doc/Kabk/Validator.html +380 -0
- data/doc/Kabk.html +330 -0
- data/doc/_index.html +376 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +206 -0
- data/doc/css/style.css +1089 -0
- data/doc/file.README.html +149 -0
- data/doc/file_list.html +59 -0
- data/doc/frames.html +22 -0
- data/doc/index.html +149 -0
- data/doc/js/app.js +801 -0
- data/doc/js/full_list.js +334 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +910 -0
- data/doc/top-level-namespace.html +112 -0
- data/docs/API_REFERENCE.md +241 -0
- data/lib/kabk/adapters/base.rb +45 -0
- data/lib/kabk/adapters/sequel_adapter.rb +125 -0
- data/lib/kabk/concurrency.rb +30 -0
- data/lib/kabk/errors.rb +62 -0
- data/lib/kabk/export_handler.rb +43 -0
- data/lib/kabk/field.rb +97 -0
- data/lib/kabk/query_builder.rb +72 -0
- data/lib/kabk/registry.rb +41 -0
- data/lib/kabk/relation_hydrator.rb +107 -0
- data/lib/kabk/resource.rb +88 -0
- data/lib/kabk/resource_builder.rb +93 -0
- data/lib/kabk/rest_engine.rb +84 -0
- data/lib/kabk/schema_renderer.rb +69 -0
- data/lib/kabk/upload_handler.rb +24 -0
- data/lib/kabk/validator.rb +64 -0
- data/lib/kabk/version.rb +6 -0
- data/lib/kabk.rb +51 -0
- metadata +193 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "errors"
|
|
4
|
+
|
|
5
|
+
module Kabk
|
|
6
|
+
# Handles input sanitization (strong parameters) and validation
|
|
7
|
+
class Validator
|
|
8
|
+
# Sanitizes input parameters against defined fields and validates them
|
|
9
|
+
# @param resource [Kabk::Resource]
|
|
10
|
+
# @param params [Hash] Request payload
|
|
11
|
+
# @param is_update [Boolean] Is this a PUT/update request?
|
|
12
|
+
# @return [Hash] Sanitized parameters ready for Sequel
|
|
13
|
+
def self.validate_and_sanitize!(resource, params, is_update: false)
|
|
14
|
+
sanitized = {}
|
|
15
|
+
errors = {}
|
|
16
|
+
|
|
17
|
+
# Iterate through all non-readonly fields defined in the schema
|
|
18
|
+
resource.fields.each do |field|
|
|
19
|
+
next if field.primary_key || field.readonly
|
|
20
|
+
|
|
21
|
+
# Validate required fields, ignoring absent fields on update.
|
|
22
|
+
|
|
23
|
+
key_sym = field.name.to_sym
|
|
24
|
+
key_str = field.name.to_s
|
|
25
|
+
has_key = params.key?(key_sym) || params.key?(key_str)
|
|
26
|
+
value = params[key_sym] || params[key_str]
|
|
27
|
+
|
|
28
|
+
if field.required && !has_key && !is_update
|
|
29
|
+
errors[key_str] = ["This field is required"]
|
|
30
|
+
next
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
next unless has_key
|
|
34
|
+
|
|
35
|
+
if value.nil? || value.to_s.strip.empty?
|
|
36
|
+
if field.required
|
|
37
|
+
errors[key_str] = ["This field is required"]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Validate min/max length
|
|
42
|
+
if field.validation && field.type == "string" && value.is_a?(String)
|
|
43
|
+
min_len = field.validation[:min_length] || field.validation["min_length"]
|
|
44
|
+
max_len = field.validation[:max_length] || field.validation["max_length"]
|
|
45
|
+
|
|
46
|
+
errors[key_str] = ["Minimum length is #{min_len}"] if min_len && value.length < min_len
|
|
47
|
+
errors[key_str] = ["Maximum length is #{max_len}"] if max_len && value.length > max_len
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
sanitized[key_sym] = value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Ensure the concurrency field is included for OCC validation.
|
|
54
|
+
if resource.concurrency_field
|
|
55
|
+
c_field = resource.concurrency_field
|
|
56
|
+
sanitized[c_field.to_sym] = params[c_field.to_sym] || params[c_field.to_s] if params.key?(c_field.to_sym) || params.key?(c_field.to_s)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
raise ValidationError.new(fields: errors) unless errors.empty?
|
|
60
|
+
|
|
61
|
+
sanitized
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/kabk/version.rb
ADDED
data/lib/kabk.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "kabk/version"
|
|
4
|
+
require_relative "kabk/registry"
|
|
5
|
+
require_relative "kabk/resource"
|
|
6
|
+
require_relative "kabk/field"
|
|
7
|
+
require_relative "kabk/resource_builder"
|
|
8
|
+
require_relative "kabk/schema_renderer"
|
|
9
|
+
require_relative "kabk/errors"
|
|
10
|
+
require_relative "kabk/concurrency"
|
|
11
|
+
require_relative "kabk/validator"
|
|
12
|
+
require_relative "kabk/query_builder"
|
|
13
|
+
require_relative "kabk/relation_hydrator"
|
|
14
|
+
require_relative "kabk/rest_engine"
|
|
15
|
+
require_relative "kabk/upload_handler"
|
|
16
|
+
require_relative "kabk/export_handler"
|
|
17
|
+
require_relative "kabk/adapters/base"
|
|
18
|
+
require_relative "kabk/adapters/sequel_adapter"
|
|
19
|
+
|
|
20
|
+
# Core namespace and entrypoint for Kabk
|
|
21
|
+
module Kabk
|
|
22
|
+
# Register a new model as a resource
|
|
23
|
+
#
|
|
24
|
+
# @param name [String, Symbol] The unique identifier for the resource
|
|
25
|
+
# @param table [Class] The Model class (e.g. Sequel::Model)
|
|
26
|
+
# @param adapter [Kabk::Adapters::Base] Optional explicit adapter instance
|
|
27
|
+
# @yield Block evaluated in the context of a ResourceBuilder
|
|
28
|
+
def self.register(name:, table:, adapter: nil, &block)
|
|
29
|
+
resource = Resource.new(name: name, model_class: table)
|
|
30
|
+
builder = ResourceBuilder.new(resource)
|
|
31
|
+
builder.instance_eval(&block) if block_given?
|
|
32
|
+
|
|
33
|
+
# Fallbacks per protocol
|
|
34
|
+
resource.plural_name ||= "#{name}s"
|
|
35
|
+
resource.title ||= resource.plural_name.capitalize
|
|
36
|
+
resource.icon ||= "Database"
|
|
37
|
+
resource.api_path ||= "/api/admin/#{resource.plural_name}"
|
|
38
|
+
|
|
39
|
+
# Determine and assign adapter
|
|
40
|
+
if adapter
|
|
41
|
+
resource.adapter = adapter
|
|
42
|
+
elsif defined?(Sequel::Model) && table < Sequel::Model
|
|
43
|
+
resource.adapter = Adapters::SequelAdapter.new(resource)
|
|
44
|
+
else
|
|
45
|
+
raise ArgumentError, "Could not determine appropriate adapter for #{table}. Please provide an explicit adapter."
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Registry.instance.register(resource)
|
|
49
|
+
resource
|
|
50
|
+
end
|
|
51
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: kabk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Parham Taheri
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: concurrent-ruby
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: sequel
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '5.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: csv
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: yard
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.9'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.9'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: webrick
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: rubocop
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '1.21'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '1.21'
|
|
96
|
+
description: Framework-agnostic engine that provides resource registration, JSON schema
|
|
97
|
+
manifest generation, generic CRUD engine, server-side validation, and relation hydration.
|
|
98
|
+
email:
|
|
99
|
+
- Par_taheri@yahoo.com
|
|
100
|
+
executables: []
|
|
101
|
+
extensions: []
|
|
102
|
+
extra_rdoc_files: []
|
|
103
|
+
files:
|
|
104
|
+
- CHANGELOG.md
|
|
105
|
+
- Gemfile
|
|
106
|
+
- Gemfile.lock
|
|
107
|
+
- Kabk_logo.svg
|
|
108
|
+
- LICENSE
|
|
109
|
+
- README.md
|
|
110
|
+
- doc/Kabk.html
|
|
111
|
+
- doc/Kabk/Adapters.html
|
|
112
|
+
- doc/Kabk/Adapters/Base.html
|
|
113
|
+
- doc/Kabk/Adapters/SequelAdapter.html
|
|
114
|
+
- doc/Kabk/ApiError.html
|
|
115
|
+
- doc/Kabk/Auth.html
|
|
116
|
+
- doc/Kabk/Auth/JwtStrategy.html
|
|
117
|
+
- doc/Kabk/Concurrency.html
|
|
118
|
+
- doc/Kabk/ConcurrencyConflictError.html
|
|
119
|
+
- doc/Kabk/Error.html
|
|
120
|
+
- doc/Kabk/ExportHandler.html
|
|
121
|
+
- doc/Kabk/Field.html
|
|
122
|
+
- doc/Kabk/ForbiddenError.html
|
|
123
|
+
- doc/Kabk/InvalidFieldError.html
|
|
124
|
+
- doc/Kabk/InvalidOldPasswordError.html
|
|
125
|
+
- doc/Kabk/NotFoundError.html
|
|
126
|
+
- doc/Kabk/QueryBuilder.html
|
|
127
|
+
- doc/Kabk/Registry.html
|
|
128
|
+
- doc/Kabk/RelationHydrator.html
|
|
129
|
+
- doc/Kabk/Resource.html
|
|
130
|
+
- doc/Kabk/ResourceBuilder.html
|
|
131
|
+
- doc/Kabk/RestEngine.html
|
|
132
|
+
- doc/Kabk/SchemaRenderer.html
|
|
133
|
+
- doc/Kabk/UnauthorizedError.html
|
|
134
|
+
- doc/Kabk/UploadHandler.html
|
|
135
|
+
- doc/Kabk/ValidationError.html
|
|
136
|
+
- doc/Kabk/Validator.html
|
|
137
|
+
- doc/_index.html
|
|
138
|
+
- doc/class_list.html
|
|
139
|
+
- doc/css/common.css
|
|
140
|
+
- doc/css/full_list.css
|
|
141
|
+
- doc/css/style.css
|
|
142
|
+
- doc/file.README.html
|
|
143
|
+
- doc/file_list.html
|
|
144
|
+
- doc/frames.html
|
|
145
|
+
- doc/index.html
|
|
146
|
+
- doc/js/app.js
|
|
147
|
+
- doc/js/full_list.js
|
|
148
|
+
- doc/js/jquery.js
|
|
149
|
+
- doc/method_list.html
|
|
150
|
+
- doc/top-level-namespace.html
|
|
151
|
+
- docs/API_REFERENCE.md
|
|
152
|
+
- lib/kabk.rb
|
|
153
|
+
- lib/kabk/adapters/base.rb
|
|
154
|
+
- lib/kabk/adapters/sequel_adapter.rb
|
|
155
|
+
- lib/kabk/concurrency.rb
|
|
156
|
+
- lib/kabk/errors.rb
|
|
157
|
+
- lib/kabk/export_handler.rb
|
|
158
|
+
- lib/kabk/field.rb
|
|
159
|
+
- lib/kabk/query_builder.rb
|
|
160
|
+
- lib/kabk/registry.rb
|
|
161
|
+
- lib/kabk/relation_hydrator.rb
|
|
162
|
+
- lib/kabk/resource.rb
|
|
163
|
+
- lib/kabk/resource_builder.rb
|
|
164
|
+
- lib/kabk/rest_engine.rb
|
|
165
|
+
- lib/kabk/schema_renderer.rb
|
|
166
|
+
- lib/kabk/upload_handler.rb
|
|
167
|
+
- lib/kabk/validator.rb
|
|
168
|
+
- lib/kabk/version.rb
|
|
169
|
+
homepage: https://github.com/par-taheri/Kabk
|
|
170
|
+
licenses:
|
|
171
|
+
- MIT
|
|
172
|
+
metadata:
|
|
173
|
+
homepage_uri: https://github.com/par-taheri/Kabk
|
|
174
|
+
source_code_uri: https://github.com/par-taheri/Kabk
|
|
175
|
+
changelog_uri: https://github.com/par-taheri/Kabk/blob/main/CHANGELOG.md
|
|
176
|
+
rdoc_options: []
|
|
177
|
+
require_paths:
|
|
178
|
+
- lib
|
|
179
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - ">="
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: 3.1.0
|
|
184
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
|
+
requirements:
|
|
186
|
+
- - ">="
|
|
187
|
+
- !ruby/object:Gem::Version
|
|
188
|
+
version: '0'
|
|
189
|
+
requirements: []
|
|
190
|
+
rubygems_version: 4.0.16
|
|
191
|
+
specification_version: 4
|
|
192
|
+
summary: Core engine for Schema-Driven Dynamic Admin Specification (Protocol v1.6.0).
|
|
193
|
+
test_files: []
|