toolrack 0.9.0 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a6d6ade6a80e5efb3499f23135144ee8c0f58b53aa98b453981e74cb279237c
4
- data.tar.gz: f665002e707b8c53aa855bedefa8c50a18fa9b4a3162cc987cdd0d000f33bd37
3
+ metadata.gz: 6e976dbea0f65aaafda38f95d4ae09824a98b3286f92b36b56e8caa2bd1bc342
4
+ data.tar.gz: 985e060c28df014cdfdf507a78f5601f24918b10e405bd0879e1f6d00355cb3e
5
5
  SHA512:
6
- metadata.gz: eab1c799dc27d82fb55006baba5943bada9f9234d4e78266f8564638b86286129f5fd3938d42be729a62044411bcb686fc75bc59d127e106a6245d9fb85e11a8
7
- data.tar.gz: bf908f5e105b9e096b779de8c1e63d66057e8034c9a7eb996c6a01c1aca7e1e941f5cad68d6dedf329d26b49a6ec45fb121e33d2d452342c511ddc96f35b06bc
6
+ metadata.gz: 196a38ae3b58129c33713d02579ee2301888a7bec935fd5882c6ad775bdc090fcd80e563f6c072a1913c45127d5ec642fa1cfac99238ad9e44a4d29e59786fc9
7
+ data.tar.gz: c4d1173f3824c72652096e94834f829cf36740885df519cbf0e4f30393ea19e7dee2895221e31a7ba26a2a6e1de10d27fb5042f147c636b0d9dc4f58ce39e8f0
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Toolrack
2
2
 
3
- Toolrack just the collection of utilities that helps in my code clarity
3
+ Toolrack just the collection of utilities that helps in my code clarity and assistance since those utils too small to be a gem on its own.
4
4
 
5
5
  ## Installation
6
6
 
@@ -40,10 +40,21 @@ class EditController
40
40
  # enable instance method to access those uitilities
41
41
  include ToolRack::ConditionUtils
42
42
  include ToolRack::ExceptionUtils
43
+ include ToolRack::PasswordUtils
44
+ include ToolRack::RuntimeUtils
45
+ include ToolRack::DataConversionUtils
46
+
47
+ # there is also shortcut since I write it so often
48
+ include TR::CondUtils
49
+ include TR::ExpUtils
50
+ include TR::PassUtils
51
+ include TR::RTUtils
52
+ include TR::DataConvUtils
43
53
  end
44
54
  ```
45
55
 
46
- Currently it has 3 modules:
56
+ Currently it has 5 modules:
57
+
47
58
  * Condition Utilities
48
59
  * is\_empty?(obj) - I found that I've type the condition if not (x.nil? and x.empty?) too frequent that I think this is very best to turn this into a function. The empty test shall take the following test in sequence:
49
60
  * First test is x.nil?. If it is return true
@@ -77,6 +88,45 @@ Currently it has 3 modules:
77
88
  * raise\_if\_false(obj, message, error) - As the name implied
78
89
  * raise\_if\_true(obj, message, error) - As the name implied
79
90
 
80
-
81
-
91
+ * Runtime utils - Tired rewriting this in other project. Detect if the running system is on which operating system / runtime. The function is pretty self descriptive
92
+ * RuntimeUtils.on\_windows?
93
+ * RuntimeUtils.on\_mac?
94
+ * RuntimeUtils.on\_linux?
95
+ * RuntimeUtils.on\_ruby?
96
+ * RuntimeUtils.on\_jruby?
97
+
98
+ * Password utils - Generate random password with designated complexity
99
+ * generate\_random\_password(length, options = { complexity: \<value\>, enforce\_quality: \<true/false\> })
100
+ * length - length of the required generated password
101
+ * options[:complexity]:
102
+ * 1 - lowercase alphabet
103
+ * 2 - lower + upper case alphabet [alpha]
104
+ * 3 - lower + upper + number [alpha numeric]
105
+ * 4 - lower + upper + number + symbol
106
+ * options[:enforce\_quality]
107
+ * true - generated password is guaranteed to contain the required complexity. E.g. if complexity 4 is required, the password MUST contain lower, upper, number and symbol as its output or a new password that comply to the complexity shall be regenerated. This process is repeated until the required complexity is achieved
108
+ * false - The rules of the complexity is relexed. E.g. if complexity 4 is requested, the output might not have symbol in it.
109
+ * gen\_rand\_pass(length, options = { }) & gen\_pass(length, options = { })
110
+ * Alias for method generate\_random\_password
111
+
112
+ * all\_lowercase\_alpha?(str)
113
+ * all\_uppercase\_alpha?(str)
114
+ * all\_alpha?(str)
115
+ * all\_number?(str)
116
+ * all\_symbol?(str)
117
+ * all\_alpha\_numeric?(str)
118
+ * all\_alpha\_numeric\_and\_symbol?(str)
119
+ * All methods above starts with all_\* is to check for strict compliance to the required output. E.g. if all\_alpha?(str) is used, the input str MUST be all alpha to get a true status
120
+
121
+ * has\_lowercase\_alpha?(str)
122
+ * has\_uppercase\_alpha?(str)
123
+ * has\_alpha?(str)
124
+ * has\_number?(str)
125
+ * has\_symbol?(str)
126
+ * has\_alpha\_numeric?(str)
127
+ * has\_alpha\_numeric\_or\_symbol?(str)
128
+ * All methods above start with has_\* is just to check if the given str contains the required specification. E.g string 'abcdE' will still get true status if pass to has\_lowercase\_alpha?(str). But value 1234 or '1234' or '$%^&' pass to has\_lowercase\_alpha?(str) shall return false.
129
+
130
+
131
+ Check out the rspec folder for usage
82
132
 
@@ -5,18 +5,297 @@ module Antrapol
5
5
  module ToolRack
6
6
  module PasswordUtils
7
7
  include Antrapol::ToolRack::ConditionUtils
8
+
9
+ class PasswordUtilsError < StandardError; end
10
+
11
+ # complexity
12
+ # 1 : lowercase alphabet
13
+ # 2 : lower + upper alphabet
14
+ # 3 : lower + upper + number
15
+ # 4 : lower + upper + number + symbol
16
+ def generate_random_password(length = 12, opts = { complexity: 4, enforce_quality: true })
17
+
8
18
 
9
- def generate_random_password(length = 12)
10
19
  length = 12 if is_empty?(length)
11
20
  length = length.to_i
12
21
  length = 12 if length <= 0
13
22
 
14
- antropy = ('!'..'~').to_a
15
- antropy.sort_by { SecureRandom.random_number }.join[0...length]
23
+ logger.debug "Length : #{length}"
24
+
25
+ if not_empty?(opts)
26
+ complexity = opts[:complexity] || 4
27
+
28
+ raise PasswordUtilsError, "Password length too short but complexity too high. Not able generate the password with required complexity." if length <= complexity
29
+
30
+ enforce_quality = opts[:enforce_quality] || true
31
+ end
32
+
33
+ complexity = 4 if is_empty?(complexity)
34
+ complexity = 4 if complexity > 4
35
+ complexity = 1 if complexity < 1
36
+
37
+ logger.debug "Complexity : #{complexity}"
38
+
39
+ enforce_quality = true if is_empty?(enforce_quality) or not is_bool?(enforce_quality)
40
+
41
+ res = []
42
+ antropy = [("a".."z"),("A".."Z"),(0..9),("!".."?")]
43
+ selection = antropy[0..complexity-1].map { |s| s.to_a }.flatten
44
+
45
+ fres = nil
46
+ loop do
47
+
48
+ len = length
49
+ processed = 0
50
+ loop do
51
+ #res += selection.sample(length)
52
+ res += selection.sort_by { SecureRandom.random_number }
53
+ break if res.length >= length
54
+ end
55
+
56
+ fres = res[0...length].join
57
+
58
+ if enforce_quality
59
+ case complexity
60
+ when 1
61
+ if all_lowercase_alpha?(fres)
62
+ break
63
+ else
64
+ logger.debug "Failed lowercase alpha quality check. #{fres} - Regenerating..."
65
+ res.clear
66
+ end
67
+ when 2
68
+ st, dst = all_alpha?(fres)
69
+ if st
70
+ break
71
+ else
72
+ logger.debug "Failed all alpha quality check. #{dst} - Regenerating..."
73
+ res.clear
74
+ end
75
+ when 3
76
+ st, dst = all_alpha_numeric?(fres)
77
+ if st
78
+ break
79
+ else
80
+ logger.debug "Failed alpha numeric quality check. #{dst} - Regenerating"
81
+ res.clear
82
+ end
83
+ when 4
84
+ st, dst = all_alpha_numeric_and_symbol?(fres)
85
+ if st
86
+ break
87
+ else
88
+ logger.debug "Failed alpha numeric + symbol quality check. #{fres} / #{dst} - Regenerating"
89
+ res.clear
90
+ end
91
+ else
92
+ logger.debug "Unknown complexity?? #{complexity}"
93
+ break
94
+ end
95
+ else
96
+ break
97
+ end
98
+
99
+ end
100
+
101
+ fres
102
+
103
+ #length = 12 if is_empty?(length)
104
+ #length = length.to_i
105
+ #length = 12 if length <= 0
106
+
107
+ #antropy = ('!'..'~').to_a
108
+ #antropy.sort_by { SecureRandom.random_number }.join[0...length]
16
109
  end
17
110
  alias_method :gen_rand_pass, :generate_random_password
18
111
  alias_method :gen_pass, :generate_random_password
19
112
 
113
+ def all_lowercase_alpha?(str)
114
+ return false if is_empty?(str) or not str.is_a?(String)
115
+
116
+ s = str.split("")
117
+ lalpha = ('a'..'z').to_a
118
+
119
+ (s.difference(lalpha).length == 0)
120
+ end
121
+
122
+ def has_lowercase_alpha?(str)
123
+ return false if is_empty?(str) or not str.is_a?(String)
124
+
125
+ s = str.split("")
126
+ lalpha = ('a'..'z').to_a
127
+
128
+ (s & lalpha).length > 0
129
+ end
130
+
131
+ def all_uppercase_alpha?(str)
132
+ return false if is_empty?(str) or not str.is_a?(String)
133
+
134
+ s = str.split("")
135
+ ualpha = ('A'..'Z').to_a
136
+
137
+ s.difference(ualpha).length == 0
138
+ end
139
+
140
+ def has_uppercase_alpha?(str)
141
+ return false if is_empty?(str) or not str.is_a?(String)
142
+
143
+ s = str.split("")
144
+ ualpha = ('A'..'Z').to_a
145
+
146
+ (s & ualpha).length > 0
147
+ end
148
+
149
+ def all_alpha?(str)
150
+ return false if is_empty?(str) or not str.is_a?(String)
151
+
152
+ s = str.split("")
153
+ lalpha = ('a'..'z').to_a
154
+ ualpha = ('A'..'Z').to_a
155
+ num = ('0'..'9').to_a
156
+ sym = ('!'..'?').to_a
157
+
158
+ alpha = [lalpha, ualpha].flatten
159
+
160
+ t1 = (alpha.difference(s).length == 0)
161
+ t2 = (alpha.difference(s).length == 0)
162
+
163
+ t3 = (s & num).length > 0
164
+ t4 = (s & sym).length > 0
165
+
166
+ [!(t1 or t2 or t3 or t4), res = { has_lower_alpha: t1, has_upper_alpha: t2, has_num: t3, has_symbol: t4 }]
167
+ end
168
+
169
+ def has_alpha?(str)
170
+ return false if is_empty?(str) or not str.is_a?(String)
171
+
172
+ s = str.split("")
173
+ lalpha = ('a'..'z').to_a
174
+ ualpha = ('A'..'Z').to_a
175
+ alpha = [lalpha, ualpha].flatten
176
+
177
+ (alpha & s).length > 0
178
+ end
179
+
180
+ def has_number?(str)
181
+ return false if is_empty?(str)
182
+
183
+ str = str.to_s if not str.is_a?(String)
184
+
185
+ s = str.split("")
186
+ num = ('0'..'9').to_a
187
+
188
+ (s & num).length > 0
189
+
190
+ end
191
+
192
+ def all_number?(str)
193
+ return false if is_empty?(str)
194
+
195
+ str = str.to_s if not str.is_a?(String)
196
+
197
+ s = str.split("")
198
+ num = ('0'..'9').to_a
199
+
200
+ !(s.difference(num).length > 0)
201
+
202
+ end
203
+
204
+ def all_symbol?(str)
205
+ return false if is_empty?(str)
206
+
207
+ s = str.split("")
208
+ sym = ('!'..'?').to_a
209
+ !(s.difference(sym).length > 0)
210
+
211
+ end
212
+
213
+ def has_symbol?(str)
214
+ return false if is_empty?(str)
215
+
216
+ s = str.split("")
217
+ sym = ('!'..'?').to_a
218
+
219
+ p (s & sym)
220
+ (s & sym).length > 0
221
+ end
222
+
223
+
224
+ def all_alpha_numeric?(str)
225
+ return false if is_empty?(str)
226
+
227
+ s = str.split("")
228
+ lalpha = ('a'..'z').to_a
229
+ ualpha = ('A'..'Z').to_a
230
+ num = ('0'..'9').to_a
231
+ sym = ('!'..'?').to_a
232
+ sym = sym.difference(num)
233
+
234
+ t1 = ((s & lalpha).length > 0)
235
+ t2 = ((s & ualpha).length > 0)
236
+ t3 = ((s & num).length > 0)
237
+
238
+ t4 = ((s & sym).length > 0)
239
+
240
+ [(t1 and t2 and t3 and !t4), res = { has_lower_alpha: t1, has_upper_alpha: t2, has_num: t3, has_symbol: t4 }]
241
+ end
242
+
243
+ def has_alpha_numeric?(str)
244
+ return false if is_empty?(str)
245
+
246
+ s = str.split("")
247
+ lalpha = ('a'..'z').to_a
248
+ ualpha = ('A'..'Z').to_a
249
+ num = ('0'..'9').to_a
250
+ alphanum = [lalpha, ualpha, num].flatten
251
+
252
+ (s & alphanum).length > 0
253
+
254
+ end
255
+
256
+ def all_alpha_numeric_and_symbol?(str)
257
+ return false if is_empty?(str)
258
+
259
+ s = str.split("")
260
+ lalpha = ('a'..'z').to_a
261
+ ualpha = ('A'..'Z').to_a
262
+ num = ('0'..'9').to_a
263
+ sym = ('!'..'?').to_a
264
+ sym = sym.difference(num)
265
+
266
+ t1 = ((s & lalpha).length > 0)
267
+ t2 = ((s & ualpha).length > 0)
268
+ t3 = ((s & num).length > 0)
269
+ t4 = ((s & sym).length > 0)
270
+
271
+ [(t1 and t2 and t3 and t4), res = { has_lower_alpha: t1, has_upper_alpha: t2, has_num: t3, has_symbol: t4 }]
272
+ end
273
+
274
+ def has_alpha_numeric_or_symbol?(str)
275
+ return false if is_empty?(str)
276
+
277
+ s = str.split("")
278
+ lalpha = ('a'..'z').to_a
279
+ ualpha = ('A'..'Z').to_a
280
+ num = ('0'..'9').to_a
281
+ sym = ('!'..'?').to_a
282
+ sym = sym.difference(num)
283
+
284
+ t1 = ((s & lalpha).length > 0)
285
+ t2 = ((s & ualpha).length > 0)
286
+ t3 = ((s & num).length > 0)
287
+ t4 = ((s & sym).length > 0)
288
+
289
+ [(t1 or t2 or t3 or t4), res = { has_lower_alpha: t1, has_upper_alpha: t2, has_num: t3, has_symbol: t4 }]
290
+ end
291
+
292
+ private
293
+ def logger
294
+ logger = Antrapol::ToolRack::Logger.instance.glogger
295
+ logger.tag = :pass_utils
296
+ logger
297
+ end
298
+
20
299
  end
21
300
  end
22
301
  end
@@ -1,6 +1,6 @@
1
1
  module Antrapol
2
2
  module ToolRack
3
- VERSION = "0.9.0"
3
+ VERSION = "0.10.0"
4
4
  end
5
5
  end
6
6
 
data/lib/toolrack.rb CHANGED
@@ -22,8 +22,20 @@ module Antrapol
22
22
  end
23
23
 
24
24
  ToolRack = Antrapol::ToolRack
25
- ToolRack::DataConv = Antrapol::ToolRack::DataConversionUtils
25
+ TR = ToolRack
26
+
27
+ ToolRack::DataConvUtils = Antrapol::ToolRack::DataConversionUtils
28
+ TR::DataConvUtils = ToolRack::DataConvUtils
29
+
26
30
  ToolRack::CondUtils = ToolRack::ConditionUtils
31
+ TR::CondUtils = ToolRack::ConditionUtils
32
+
27
33
  ToolRack::PassUtils = ToolRack::PasswordUtils
34
+ TR::PassUtils = ToolRack::PasswordUtils
35
+
36
+ ToolRack::ExpUtils = ToolRack::ExceptionUtils
37
+ TR::ExpUtils = ToolRack::ExpUtils
28
38
 
39
+ ToolRack::RTUtils = ToolRack::RuntimeUtils
40
+ TR::RTUtils = ToolRack::RTUtils
29
41
 
data/toolrack.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.summary = %q{Collection of simple utilities but I find it increase clarity}
10
10
  spec.description = %q{Just collections of utilities}
11
11
  spec.homepage = "https://github.com/chrisliaw/toolrack"
12
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
13
13
 
14
14
  #spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toolrack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-08 00:00:00.000000000 Z
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tlogger
@@ -88,7 +88,7 @@ licenses: []
88
88
  metadata:
89
89
  homepage_uri: https://github.com/chrisliaw/toolrack
90
90
  source_code_uri: https://github.com/chrisliaw/toolrack
91
- post_install_message:
91
+ post_install_message:
92
92
  rdoc_options: []
93
93
  require_paths:
94
94
  - lib
@@ -96,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
96
  requirements:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
- version: 2.3.0
99
+ version: 2.6.0
100
100
  required_rubygems_version: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - ">="
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  version: '0'
105
105
  requirements: []
106
106
  rubygems_version: 3.2.22
107
- signing_key:
107
+ signing_key:
108
108
  specification_version: 4
109
109
  summary: Collection of simple utilities but I find it increase clarity
110
110
  test_files: []