symmetric-encryption 4.1.0.beta1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/symmetric_encryption/cipher.rb +9 -2
  3. data/lib/symmetric_encryption/cli.rb +13 -6
  4. data/lib/symmetric_encryption/config.rb +9 -6
  5. data/lib/symmetric_encryption/encoder.rb +6 -0
  6. data/lib/symmetric_encryption/extensions/mongoid/encrypted.rb +1 -0
  7. data/lib/symmetric_encryption/generator.rb +1 -1
  8. data/lib/symmetric_encryption/header.rb +7 -5
  9. data/lib/symmetric_encryption/key.rb +2 -0
  10. data/lib/symmetric_encryption/keystore/aws.rb +9 -9
  11. data/lib/symmetric_encryption/keystore/environment.rb +3 -2
  12. data/lib/symmetric_encryption/keystore/file.rb +1 -1
  13. data/lib/symmetric_encryption/keystore/memory.rb +1 -1
  14. data/lib/symmetric_encryption/keystore.rb +15 -16
  15. data/lib/symmetric_encryption/railtie.rb +7 -2
  16. data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +1 -0
  17. data/lib/symmetric_encryption/reader.rb +50 -58
  18. data/lib/symmetric_encryption/symmetric_encryption.rb +2 -1
  19. data/lib/symmetric_encryption/utils/aws.rb +6 -4
  20. data/lib/symmetric_encryption/utils/re_encrypt_files.rb +2 -2
  21. data/lib/symmetric_encryption/version.rb +1 -1
  22. data/lib/symmetric_encryption/writer.rb +33 -27
  23. data/lib/symmetric_encryption.rb +26 -5
  24. data/test/active_record_test.rb +25 -25
  25. data/test/cipher_test.rb +3 -3
  26. data/test/header_test.rb +1 -1
  27. data/test/keystore/aws_test.rb +7 -7
  28. data/test/keystore/file_test.rb +1 -1
  29. data/test/keystore_test.rb +2 -2
  30. data/test/mongoid_test.rb +15 -15
  31. data/test/reader_test.rb +28 -8
  32. data/test/symmetric_encryption_test.rb +2 -2
  33. data/test/test_db.sqlite3 +0 -0
  34. data/test/utils/aws_test.rb +1 -2
  35. data/test/writer_test.rb +48 -46
  36. metadata +23 -23
@@ -29,8 +29,13 @@ module SymmetricEncryption #:nodoc:
29
29
  config.before_configuration do
30
30
  # Check if already configured
31
31
  unless ::SymmetricEncryption.cipher?
32
- app_name = Rails::Application.subclasses.first.parent.to_s.underscore
33
- config_file = Rails.root.join('config', 'symmetric-encryption.yml')
32
+ app_name = Rails::Application.subclasses.first.parent.to_s.underscore
33
+ config_file =
34
+ if (env_var = ENV['SYMMETRIC_ENCRYPTION_CONFIG'])
35
+ Pathname.new File.expand_path(env_var)
36
+ else
37
+ Rails.root.join('config', 'symmetric-encryption.yml')
38
+ end
34
39
  if config_file.file?
35
40
  begin
36
41
  ::SymmetricEncryption::Config.load!(file_name: config_file, env: ENV['SYMMETRIC_ENCRYPTION_ENV'] || Rails.env)
@@ -14,6 +14,7 @@
14
14
  class SymmetricEncryptionValidator < ActiveModel::EachValidator
15
15
  def validate_each(record, attribute, value)
16
16
  return if value.blank? || SymmetricEncryption.encrypted?(value)
17
+
17
18
  record.errors.add(attribute, 'must be a value encrypted using SymmetricEncryption.encrypt')
18
19
  end
19
20
  end
@@ -76,7 +76,7 @@ module SymmetricEncryption
76
76
  # Notes:
77
77
  # * Do not use this method for reading large files.
78
78
  def self.read(file_name_or_stream, **args)
79
- self.open(file_name_or_stream, **args, &:read)
79
+ Reader.open(file_name_or_stream, **args, &:read)
80
80
  end
81
81
 
82
82
  # Decrypt an entire file.
@@ -90,22 +90,10 @@ module SymmetricEncryption
90
90
  # target: [String|IO]
91
91
  # Target file_name or IOStream
92
92
  #
93
- # block_size: [Integer]
94
- # Number of bytes to read into memory for each read.
95
- # For very large files using a larger block size is faster.
96
- # Default: 65535
97
- #
98
93
  # Notes:
99
94
  # * The file contents are streamed so that the entire file is _not_ loaded into memory.
100
- def self.decrypt(source:, target:, block_size: 65_535, **args)
101
- target_ios = target.is_a?(String) ? ::File.open(target, 'wb') : target
102
- bytes_written = 0
103
- self.open(source, **args) do |input_ios|
104
- bytes_written += target_ios.write(input_ios.read(block_size)) until input_ios.eof?
105
- end
106
- bytes_written
107
- ensure
108
- target_ios.close if target_ios&.respond_to?(:closed?) && !target_ios.closed?
95
+ def self.decrypt(source:, target:, **args)
96
+ Reader.open(source, **args) { |input_file| IO.copy_stream(input_file, target) }
109
97
  end
110
98
 
111
99
  # Returns [true|false] whether the file or stream contains any data
@@ -132,6 +120,7 @@ module SymmetricEncryption
132
120
  @version = version
133
121
  @header_present = false
134
122
  @closed = false
123
+ @read_buffer = ''.b
135
124
 
136
125
  raise(ArgumentError, 'Buffer size cannot be smaller than 128') unless @buffer_size >= 128
137
126
 
@@ -170,6 +159,7 @@ module SymmetricEncryption
170
159
  # ensure that the encrypted stream is closed before the stream itself is closed
171
160
  def close(close_child_stream = true)
172
161
  return if closed?
162
+
173
163
  @ios.close if close_child_stream
174
164
  @closed = true
175
165
  end
@@ -194,35 +184,25 @@ module SymmetricEncryption
194
184
  #
195
185
  # At end of file, it returns nil if no more data is available, or the last
196
186
  # remaining bytes
197
- def read(length = nil)
198
- data = nil
199
- if length
200
- return '' if length.zero?
201
- return nil if eof?
202
- # Read length bytes
203
- read_block while (@read_buffer.length < length) && !@ios.eof?
204
- if @read_buffer.empty?
205
- data = nil
206
- elsif @read_buffer.length > length
207
- data = @read_buffer.slice!(0..length - 1)
187
+ def read(length = nil, outbuf = nil)
188
+ data = outbuf.to_s.clear
189
+ remaining_length = length
190
+
191
+ until remaining_length == 0 || eof?
192
+ read_block(remaining_length) if @read_buffer.empty?
193
+
194
+ if remaining_length && remaining_length < @read_buffer.length
195
+ data << @read_buffer.slice!(0, remaining_length)
208
196
  else
209
- data = @read_buffer
210
- @read_buffer = ''
211
- end
212
- else
213
- # Capture anything already in the buffer
214
- data = @read_buffer
215
- @read_buffer = ''
216
-
217
- unless @ios.eof?
218
- # Read entire file
219
- buf = @ios.read || ''
220
- data << @stream_cipher.update(buf) if buf && !buf.empty?
221
- data << @stream_cipher.final
197
+ data << @read_buffer
198
+ @read_buffer.clear
222
199
  end
200
+
201
+ remaining_length = length - data.length if length
223
202
  end
203
+
224
204
  @pos += data.length
225
- data
205
+ data unless data.empty? && length && length.positive?
226
206
  end
227
207
 
228
208
  # Reads a single decrypted line from the file up to and including the optional sep_string.
@@ -242,12 +222,14 @@ module SymmetricEncryption
242
222
  # Read more data until we get the sep_string
243
223
  while (index = @read_buffer.index(sep_string)).nil? && !@ios.eof?
244
224
  break if length && @read_buffer.length >= length
225
+
245
226
  read_block
246
227
  end
247
228
  index ||= -1
248
- data = @read_buffer.slice!(0..index)
249
- @pos += data.length
229
+ data = @read_buffer.slice!(0..index)
230
+ @pos += data.length
250
231
  return nil if data.empty? && eof?
232
+
251
233
  data
252
234
  end
253
235
 
@@ -272,7 +254,7 @@ module SymmetricEncryption
272
254
 
273
255
  # Rewind back to the beginning of the file
274
256
  def rewind
275
- @read_buffer = ''
257
+ @read_buffer.clear
276
258
  @ios.rewind
277
259
  read_header
278
260
  end
@@ -307,10 +289,10 @@ module SymmetricEncryption
307
289
  # Read and decrypt entire file a block at a time to get its total
308
290
  # unencrypted size
309
291
  size = 0
310
- until eof
292
+ until eof?
311
293
  read_block
312
- size += @read_buffer.size
313
- @read_buffer = ''
294
+ size += @read_buffer.size
295
+ @read_buffer.clear
314
296
  end
315
297
  rewind
316
298
  offset = size + amount
@@ -328,7 +310,7 @@ module SymmetricEncryption
328
310
  @pos = 0
329
311
 
330
312
  # Read first block and check for the header
331
- buf = @ios.read(@buffer_size)
313
+ buf = @ios.read(@buffer_size, @output_buffer ||= ''.b)
332
314
 
333
315
  # Use cipher specified in header, or global cipher if it has no header
334
316
  iv, key, cipher_name, cipher = nil
@@ -353,20 +335,30 @@ module SymmetricEncryption
353
335
  @stream_cipher.key = key || cipher.send(:key)
354
336
  @stream_cipher.iv = iv || cipher.iv
355
337
 
356
- # First call to #update should return an empty string anyway
357
- if buf && !buf.empty?
358
- @read_buffer = @stream_cipher.update(buf)
359
- @read_buffer << @stream_cipher.final if @ios.eof?
360
- else
361
- @read_buffer = ''
362
- end
338
+ decrypt(buf)
363
339
  end
364
340
 
365
341
  # Read a block of data and append the decrypted data in the read buffer
366
- def read_block
367
- buf = @ios.read(@buffer_size)
368
- @read_buffer << @stream_cipher.update(buf) if buf && !buf.empty?
369
- @read_buffer << @stream_cipher.final if @ios.eof?
342
+ def read_block(length = nil)
343
+ buf = @ios.read(length || @buffer_size, @output_buffer ||= ''.b)
344
+ decrypt(buf)
345
+ end
346
+
347
+ # Decrypts the given chunk of data and returns the result
348
+ if defined?(JRuby)
349
+ def decrypt(buf)
350
+ return if buf.nil? || buf.empty?
351
+
352
+ @read_buffer << @stream_cipher.update(buf)
353
+ @read_buffer << @stream_cipher.final if @ios.eof?
354
+ end
355
+ else
356
+ def decrypt(buf)
357
+ return if buf.nil? || buf.empty?
358
+
359
+ @read_buffer << @stream_cipher.update(buf, @cipher_buffer ||= ''.b)
360
+ @read_buffer << @stream_cipher.final if @ios.eof?
361
+ end
370
362
  end
371
363
 
372
364
  def closed?
@@ -55,6 +55,7 @@ module SymmetricEncryption
55
55
  end
56
56
 
57
57
  return @@cipher if version.nil? || (@@cipher.version == version)
58
+
58
59
  secondary_ciphers.find { |c| c.version == version } || (@@cipher if version.zero?)
59
60
  end
60
61
 
@@ -264,7 +265,7 @@ module SymmetricEncryption
264
265
  # encoded_str.end_with?("\n") ? SymmetricEncryption.cipher(0) : SymmetricEncryption.cipher
265
266
  # end
266
267
  def self.select_cipher(&block)
267
- @@select_cipher = block ? block : nil
268
+ @@select_cipher = block || nil
268
269
  end
269
270
 
270
271
  # Load the Encryption Configuration from a YAML file
@@ -15,7 +15,7 @@ module SymmetricEncryption
15
15
  AWS_KEY_SPEC_MAP = {
16
16
  'aes-256-cbc' => 'AES_256',
17
17
  'aes-128-cbc' => 'AES_128'
18
- }
18
+ }.freeze
19
19
 
20
20
  # TODO: Move to Keystore::Aws
21
21
  # Rotate the Customer Master key in each of the supplied regions.
@@ -68,6 +68,7 @@ module SymmetricEncryption
68
68
  def key_spec(cipher_name)
69
69
  key_spec = AWS_KEY_SPEC_MAP[cipher_name]
70
70
  raise("OpenSSL Cipher: #{cipher_name} has not yet been mapped to an AWS key spec.") unless key_spec
71
+
71
72
  key_spec
72
73
  end
73
74
 
@@ -112,9 +113,9 @@ module SymmetricEncryption
112
113
  resp = client.create_key(
113
114
  description: 'Symmetric Encryption for Ruby Customer Masker Key',
114
115
  tags: [
115
- {tag_key: 'CreatedAt', tag_value: Time.now.to_s},
116
- {tag_key: 'CreatedBy', tag_value: whoami}
117
- ]
116
+ {tag_key: 'CreatedAt', tag_value: Time.now.to_s},
117
+ {tag_key: 'CreatedBy', tag_value: whoami}
118
+ ]
118
119
  )
119
120
  resp.key_metadata.key_id
120
121
  end
@@ -130,6 +131,7 @@ module SymmetricEncryption
130
131
  yield
131
132
  rescue ::Aws::KMS::Errors::NotFoundException
132
133
  raise if attempt >= 2
134
+
133
135
  create_master_key
134
136
  attempt += 1
135
137
  retry
@@ -68,8 +68,8 @@ module SymmetricEncryption
68
68
  line.force_encoding(SymmetricEncryption::UTF8_ENCODING)
69
69
  output_lines <<
70
70
  if line.valid_encoding? && (result = line.match(r))
71
- encrypted = result[0]
72
- new_value = re_encrypt(encrypted)
71
+ encrypted = result[0]
72
+ new_value = re_encrypt(encrypted)
73
73
  if new_value != encrypted
74
74
  hits += 1
75
75
  line.gsub(encrypted, new_value)
@@ -1,3 +1,3 @@
1
1
  module SymmetricEncryption
2
- VERSION = '4.1.0.beta1'.freeze
2
+ VERSION = '4.1.0'.freeze
3
3
  end
@@ -21,7 +21,7 @@ module SymmetricEncryption
21
21
  # compress: [true|false]
22
22
  # Uses Zlib to compress the data before it is encrypted and
23
23
  # written to the file/stream.
24
- # Default: false
24
+ # Default: true, unless the file_name extension indicates it is already compressed.
25
25
  #
26
26
  # Note: Compression occurs before encryption
27
27
  #
@@ -47,11 +47,16 @@ module SymmetricEncryption
47
47
  # ensure
48
48
  # csv.close if csv
49
49
  # end
50
- def self.open(file_name_or_stream, compress: false, **args)
51
- ios = file_name_or_stream.is_a?(String) ? ::File.open(file_name_or_stream, 'wb') : file_name_or_stream
50
+ def self.open(file_name_or_stream, compress: nil, **args)
51
+ if file_name_or_stream.is_a?(String)
52
+ file_name_or_stream = ::File.open(file_name_or_stream, 'wb')
53
+ compress = !(/\.(zip|gz|gzip|xls.|)\z/i === file_name_or_stream) if compress.nil?
54
+ else
55
+ compress = true if compress.nil?
56
+ end
52
57
 
53
58
  begin
54
- file = new(ios, compress: compress, **args)
59
+ file = new(file_name_or_stream, compress: compress, **args)
55
60
  file = Zlib::GzipWriter.new(file) if compress
56
61
  block_given? ? yield(file) : file
57
62
  ensure
@@ -64,7 +69,7 @@ module SymmetricEncryption
64
69
  # Notes:
65
70
  # * Do not use this method for writing large files.
66
71
  def self.write(file_name_or_stream, data, **args)
67
- self.open(file_name_or_stream, **args) { |f| f.write(data) }
72
+ Writer.open(file_name_or_stream, **args) { |f| f.write(data) }
68
73
  end
69
74
 
70
75
  # Encrypt an entire file.
@@ -82,22 +87,10 @@ module SymmetricEncryption
82
87
  # Whether to compress the target file prior to encryption.
83
88
  # Default: false
84
89
  #
85
- # block_size: [Integer]
86
- # Number of bytes to read into memory for each read.
87
- # For very large files using a larger block size is faster.
88
- # Default: 65535
89
- #
90
90
  # Notes:
91
91
  # * The file contents are streamed so that the entire file is _not_ loaded into memory.
92
- def self.encrypt(source:, target:, block_size: 65_535, **args)
93
- source_ios = source.is_a?(String) ? ::File.open(source, 'rb') : source
94
- bytes_written = 0
95
- self.open(target, **args) do |output_file|
96
- bytes_written += output_file.write(source_ios.read(block_size)) until source_ios.eof?
97
- end
98
- bytes_written
99
- ensure
100
- source_ios.close if source_ios&.respond_to?(:closed?) && !source_ios.closed?
92
+ def self.encrypt(source:, target:, **args)
93
+ Writer.open(target, **args) { |output_file| IO.copy_stream(source, output_file) }
101
94
  end
102
95
 
103
96
  # Encrypt data before writing to the supplied stream
@@ -149,6 +142,7 @@ module SymmetricEncryption
149
142
  # ensure that the encrypted stream is closed before the stream itself is closed.
150
143
  def close(close_child_stream = true)
151
144
  return if closed?
145
+
152
146
  if size.positive?
153
147
  final = @stream_cipher.final
154
148
  @ios.write(final) unless final.empty?
@@ -160,14 +154,26 @@ module SymmetricEncryption
160
154
  # Write to the IO Stream as encrypted data.
161
155
  #
162
156
  # Returns [Integer] the number of bytes written.
163
- def write(data)
164
- return unless data
165
-
166
- bytes = data.to_s
167
- @size += bytes.size
168
- partial = @stream_cipher.update(bytes)
169
- @ios.write(partial) unless partial.empty?
170
- data.length
157
+ if defined?(JRuby)
158
+ def write(data)
159
+ return unless data
160
+
161
+ bytes = data.to_s
162
+ @size += bytes.size
163
+ partial = @stream_cipher.update(bytes)
164
+ @ios.write(partial) unless partial.empty?
165
+ data.length
166
+ end
167
+ else
168
+ def write(data)
169
+ return unless data
170
+
171
+ bytes = data.to_s
172
+ @size += bytes.size
173
+ partial = @stream_cipher.update(bytes, @cipher_buffer ||= ''.b)
174
+ @ios.write(partial) unless partial.empty?
175
+ data.length
176
+ end
171
177
  end
172
178
 
173
179
  # Write to the IO Stream as encrypted data.
@@ -29,12 +29,33 @@ end
29
29
  # @formatter:on
30
30
 
31
31
  # Add support for other libraries only if they have already been loaded
32
- require 'symmetric_encryption/railtie' if defined?(Rails)
33
- if defined?(ActiveRecord::Base) && !defined?(AttrEncrypted::Version)
34
- require 'symmetric_encryption/extensions/active_record/base'
32
+
33
+ begin
34
+ require 'rails/railtie'
35
+ require 'symmetric_encryption/railtie' if defined?(Rails)
36
+ rescue LoadError
35
37
  end
36
- require 'symmetric_encryption/railties/symmetric_encryption_validator' if defined?(ActiveModel)
37
- require 'symmetric_encryption/extensions/mongoid/encrypted' if defined?(Mongoid)
38
+
39
+ begin
40
+ require 'active_record'
41
+ if defined?(ActiveRecord::Base) && !defined?(AttrEncrypted::Version)
42
+ require 'symmetric_encryption/extensions/active_record/base'
43
+ end
44
+ rescue LoadError
45
+ end
46
+
47
+ begin
48
+ require 'active_model'
49
+ require 'symmetric_encryption/railties/symmetric_encryption_validator' if defined?(ActiveModel)
50
+ rescue LoadError
51
+ end
52
+
53
+ begin
54
+ require 'mongoid'
55
+ require 'symmetric_encryption/extensions/mongoid/encrypted' if defined?(Mongoid)
56
+ rescue LoadError
57
+ end
58
+
38
59
  if defined?(MongoMapper)
39
60
  warn 'MongoMapper support is deprecated. Upgrade to Mongoid.'
40
61
  require 'symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key'
@@ -119,26 +119,26 @@ class ActiveRecordTest < Minitest::Test
119
119
  let :user do
120
120
  User.new(
121
121
  # Encrypted Attribute
122
- bank_account_number: bank_account_number,
122
+ bank_account_number: bank_account_number,
123
123
  # Encrypted Attribute
124
124
  social_security_number: social_security_number,
125
125
  name: person_name,
126
126
  # data type specific fields
127
- string_value: STRING_VALUE,
128
- long_string_value: LONG_STRING_VALUE,
129
- binary_string_value: BINARY_STRING_VALUE,
130
- integer_value: INTEGER_VALUE,
131
- float_value: FLOAT_VALUE,
132
- decimal_value: DECIMAL_VALUE,
133
- datetime_value: DATETIME_VALUE,
134
- time_value: TIME_VALUE,
135
- date_value: DATE_VALUE,
136
- true_value: true,
137
- false_value: false,
138
- data_yaml: hash_data.dup,
139
- data_json: hash_data.dup,
140
- text: 'hello',
141
- number: '21'
127
+ string_value: STRING_VALUE,
128
+ long_string_value: LONG_STRING_VALUE,
129
+ binary_string_value: BINARY_STRING_VALUE,
130
+ integer_value: INTEGER_VALUE,
131
+ float_value: FLOAT_VALUE,
132
+ decimal_value: DECIMAL_VALUE,
133
+ datetime_value: DATETIME_VALUE,
134
+ time_value: TIME_VALUE,
135
+ date_value: DATE_VALUE,
136
+ true_value: true,
137
+ false_value: false,
138
+ data_yaml: hash_data.dup,
139
+ data_json: hash_data.dup,
140
+ text: 'hello',
141
+ number: '21'
142
142
  )
143
143
  end
144
144
 
@@ -167,17 +167,17 @@ class ActiveRecordTest < Minitest::Test
167
167
  describe ':random_iv' do
168
168
  it 'false' do
169
169
  user.social_security_number = social_security_number
170
- assert first_value = user.social_security_number
170
+ assert first_value = user.social_security_number
171
171
  # Assign the same value
172
172
  user.social_security_number = social_security_number
173
173
  assert_equal first_value, user.social_security_number
174
174
  end
175
175
 
176
176
  it 'true' do
177
- user.string_value = STRING_VALUE
177
+ user.string_value = STRING_VALUE
178
178
  assert first_value = user.encrypted_string_value
179
- user.string_value = 'blah'
180
- user.string_value = STRING_VALUE
179
+ user.string_value = 'blah'
180
+ user.string_value = STRING_VALUE
181
181
  refute_equal first_value, user.encrypted_string_value
182
182
  end
183
183
 
@@ -200,7 +200,7 @@ class ActiveRecordTest < Minitest::Test
200
200
 
201
201
  it 'does not change when equal' do
202
202
  user.save!
203
- before = user.encrypted_string_value
203
+ before = user.encrypted_string_value
204
204
  user.string_value = STRING_VALUE
205
205
  refute user.string_value_changed?
206
206
  assert_equal before, user.encrypted_string_value
@@ -405,7 +405,7 @@ class ActiveRecordTest < Minitest::Test
405
405
 
406
406
  describe '#reload' do
407
407
  it 'reverts changes' do
408
- new_bank_account_number = '444444444'
408
+ new_bank_account_number = '444444444'
409
409
  user.bank_account_number = new_bank_account_number
410
410
  assert_equal new_bank_account_number, user.bank_account_number
411
411
 
@@ -416,8 +416,8 @@ class ActiveRecordTest < Minitest::Test
416
416
  end
417
417
 
418
418
  it 'reverts changes to encrypted field' do
419
- new_bank_account_number = '111111111'
420
- new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
419
+ new_bank_account_number = '111111111'
420
+ new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
421
421
  user.encrypted_bank_account_number = new_encrypted_bank_account_number
422
422
  assert_equal new_encrypted_bank_account_number, user.encrypted_bank_account_number
423
423
  assert_equal new_bank_account_number, user.bank_account_number
@@ -591,7 +591,7 @@ class ActiveRecordTest < Minitest::Test
591
591
  UniqueUser.destroy_all
592
592
  @email = 'whatever@not-unique.com'
593
593
  @username = 'gibby007'
594
- user = UniqueUser.create!(email: @email)
594
+ user = UniqueUser.create!(email: @email)
595
595
  @email_user = UniqueUser.create!(username: @username)
596
596
  end
597
597