acrylic 0.2.3 → 0.4.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 +4 -4
- data/lib/bits.rb +27 -0
- data/lib/cascade.rb +6 -6
- data/lib/validator.rb +76 -0
- data/lib/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c867a949c6d7b81cf0e358387cf9ee06bb2cb460901eb089492f589e5c1e31f
|
|
4
|
+
data.tar.gz: c66069736873cab0183f99cb2832c8339eabb4540af63b8b99208678eaa81cc9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08c812a7ab32c4672692ad5989fc04a32467e0bab0ec6a4174b3d54f0bfd85d011e0ffe822f52ea889366156469d62e4bd9d30147ef680082f3ae2bbd5a40734'
|
|
7
|
+
data.tar.gz: f4f0f3326cba037385f1618733ae41f40ed7bd1e80bea879c9a368d940faeabcf7a245fed7ff5bc4a350570d5982828dfd4b14c048e618f0427ea3f91bec67d6
|
data/lib/bits.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
|
|
1
3
|
class Object
|
|
2
4
|
def containerize
|
|
3
5
|
if self.is_a? Array then self else [self].compact end
|
|
@@ -18,4 +20,29 @@ class Hash
|
|
|
18
20
|
def self.from_keys keys, value = nil
|
|
19
21
|
keys.map do |k| [k, value] end.to_h
|
|
20
22
|
end
|
|
23
|
+
|
|
24
|
+
def self.from_values values
|
|
25
|
+
k = -1
|
|
26
|
+
values.map do |v|
|
|
27
|
+
k += 1
|
|
28
|
+
[k, v]
|
|
29
|
+
end.to_h
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# recursively converts hash to ostruct.
|
|
33
|
+
def structize
|
|
34
|
+
OpenStruct.new (map do |k, v| [k, if v.is_a? Hash then v.structize else v end] end.to_h)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# recursively convert keys to symbols
|
|
38
|
+
def with_sym_keys
|
|
39
|
+
map do |k, v| [k.to_sym, if v.is_a? Hash then v.with_sym_keys else v end] end.to_h
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class Array
|
|
44
|
+
# like sort by, but sorts entries with same index
|
|
45
|
+
def sort_by_stable &proc
|
|
46
|
+
Hash.from_values(self).sort_by do |k, v| [proc.call(v), k] end.to_h.values
|
|
47
|
+
end
|
|
21
48
|
end
|
data/lib/cascade.rb
CHANGED
|
@@ -5,17 +5,15 @@ module Acrylic
|
|
|
5
5
|
ROUTES = []
|
|
6
6
|
|
|
7
7
|
class Route
|
|
8
|
-
# list of HTTP verbs the request will be matched against.
|
|
9
|
-
attr_reader :verbs
|
|
10
|
-
|
|
11
8
|
# list of path rules (wildcards or regexps)
|
|
12
9
|
attr_reader :paths
|
|
10
|
+
attr_reader :priority
|
|
13
11
|
|
|
14
12
|
def initialize args, handler
|
|
15
13
|
@handler = handler
|
|
16
14
|
|
|
15
|
+
@priority = args[:priority] or 0 # defualt priority
|
|
17
16
|
@paths = args[:path].containerize
|
|
18
|
-
@verbs = (args[:verb] or :GET).containerize.map do |verb| verb.downcase.to_sym end
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
# transforms a rule from string (e.g. "/User/<id>") to wildcard
|
|
@@ -50,7 +48,7 @@ module Acrylic
|
|
|
50
48
|
|
|
51
49
|
def match? req
|
|
52
50
|
# match against paths
|
|
53
|
-
(path_match? req.path)
|
|
51
|
+
(path_match? req.path)
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
def call req, *args
|
|
@@ -66,8 +64,10 @@ module Acrylic
|
|
|
66
64
|
config = OpenStruct.new
|
|
67
65
|
|
|
68
66
|
# loop through all the routes to find a final one
|
|
69
|
-
|
|
67
|
+
# (and sort them by priority descending and index)
|
|
68
|
+
Acrylic::ROUTES.sort_by_stable do |route| route.priority end.each do |route|
|
|
70
69
|
next unless route.match? req
|
|
70
|
+
puts route.priority
|
|
71
71
|
|
|
72
72
|
res = route.call config, req, *(route.args_for_path req.path)
|
|
73
73
|
|
data/lib/validator.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Acrylic
|
|
2
|
+
|
|
3
|
+
# a schema is a hash that validates another hash.
|
|
4
|
+
# values in the schema represent conditions to validate the object against.
|
|
5
|
+
# e.g.
|
|
6
|
+
# {
|
|
7
|
+
# email: [:email, [:length, (..32)]]
|
|
8
|
+
# username: [:not_null, [:length, (..32)]]
|
|
9
|
+
# password: [:not_null, [:length, (8..32)]]
|
|
10
|
+
# }
|
|
11
|
+
#
|
|
12
|
+
# string keys in the object are automatically converted to symbols.
|
|
13
|
+
|
|
14
|
+
module Validators
|
|
15
|
+
def email val
|
|
16
|
+
# shamelessly stolen from https://github.com/zombor/Validator/blob/master/lib/validation/rule/email.rb
|
|
17
|
+
email_address = begin
|
|
18
|
+
letter = 'a-zA-Z'
|
|
19
|
+
digit = '0-9'
|
|
20
|
+
atext = "[#{letter}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]"
|
|
21
|
+
dot_atom_text = "#{atext}+([.]#{atext}*)+"
|
|
22
|
+
dot_atom = dot_atom_text
|
|
23
|
+
no_ws_ctl = '\x01-\x08\x11\x12\x14-\x1f\x7f'
|
|
24
|
+
qtext = "[^#{no_ws_ctl}\\x0d\\x22\\x5c]" # Non-whitespace, non-control character except for \ and "
|
|
25
|
+
text = '[\x01-\x09\x11\x12\x14-\x7f]'
|
|
26
|
+
quoted_pair = "(\\x5c#{text})"
|
|
27
|
+
qcontent = "(?:#{qtext}|#{quoted_pair})"
|
|
28
|
+
quoted_string = "[\"]#{qcontent}+[\"]"
|
|
29
|
+
atom = "#{atext}+"
|
|
30
|
+
word = "(?:#{atom}|#{quoted_string})"
|
|
31
|
+
obs_local_part = "#{word}([.]#{word})*"
|
|
32
|
+
local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})"
|
|
33
|
+
dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]"
|
|
34
|
+
dcontent = "(?:#{dtext}|#{quoted_pair})"
|
|
35
|
+
domain_literal = "\\[#{dcontent}+\\]"
|
|
36
|
+
obs_domain = "#{atom}([.]#{atom})+"
|
|
37
|
+
domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})"
|
|
38
|
+
addr_spec = "#{local_part}\@#{domain}"
|
|
39
|
+
pattern = /\A#{addr_spec}\z/u
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
!!email_address.match(val)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def not_null val; not val.nil? end
|
|
46
|
+
def length val, range; range.include? val.length end
|
|
47
|
+
def range val, range; range.include? val end
|
|
48
|
+
def regex val, expr; expr.match? val end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def valid? object, schema
|
|
52
|
+
object = object.with_sym_keys
|
|
53
|
+
schema.each do |key, conditions|
|
|
54
|
+
value = object[key]
|
|
55
|
+
|
|
56
|
+
# apply conditions
|
|
57
|
+
if conditions.is_a? Hash
|
|
58
|
+
return false unless value.is_a? Hash
|
|
59
|
+
return false unless valid? value, conditions
|
|
60
|
+
else
|
|
61
|
+
conditions = conditions.containerize
|
|
62
|
+
|
|
63
|
+
# check every condition (in order)
|
|
64
|
+
conditions.each do |condition|
|
|
65
|
+
condition = condition.containerize
|
|
66
|
+
opcode, *args = condition
|
|
67
|
+
if opcode == :default then value = args[0] if value.nil?
|
|
68
|
+
else return false unless Validators.instance_method(opcode).bind(nil).call value, *args
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
return true
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: acrylic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- fmixolydian
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-01-
|
|
10
|
+
date: 2026-01-04 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rack
|
|
@@ -66,6 +66,7 @@ files:
|
|
|
66
66
|
- lib/cascade.rb
|
|
67
67
|
- lib/cascade/errors.rb
|
|
68
68
|
- lib/kronos.rb
|
|
69
|
+
- lib/validator.rb
|
|
69
70
|
- lib/version.rb
|
|
70
71
|
homepage: https://codeberg.org/fmixolydian/acrylic
|
|
71
72
|
licenses:
|