activerecord-s3-bucket-name-validator 0.1.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d92a2144185d4209736c4667fa431fcdfd6c03bc54f5438419418bfde54afd35
4
- data.tar.gz: f34996e4c9cca6eaa546937100d37d3b64d8d64cf94d3063b603ff7393232846
3
+ metadata.gz: 12b96ad2afb8713382346c19e7c7589e41014735d7481754e26a9d03329d7c7f
4
+ data.tar.gz: a4a67ed0a9e5dc9b30bc69faafe9f82f74b77df66f60c0cac9076158165a595f
5
5
  SHA512:
6
- metadata.gz: 75201a63526f505e40cdb651da3e40d128ea7484e6ee19b4c22784282346c93ae71f10b1a2c7061e6d4b9db0518e9551c5ac35117f0f2c2726bd20a60a2561d0
7
- data.tar.gz: a8b6e2f259af30265a5d3fbb434f72f35febc98a5cc481a32f463623bf7768c7739d68e971666d12d4eb635d3b405fce9ed353f79e80a209dc96168a7845e77d
6
+ metadata.gz: 0e8698e66b8494c850a9618d7ba8fa2cc5088511195f96991817293e2269fe0fa1f20c66872a066265fbee592d51cab5ab18bf7c4cd27158707352c0413e0d20
7
+ data.tar.gz: 395899fab1991707c6cdbcb04b61dba595d23952229963fd9717598c9e5a2a87670d271b69673987aafb279e04933084ae367abae5f93feeca75825116e84567
data/README.md CHANGED
@@ -4,6 +4,7 @@ ActiveModel validator for Amazon S3 bucket names. It implements the official AWS
4
4
  - General purpose buckets (classic S3)
5
5
  - Directory buckets (S3 Express One Zone)
6
6
  - S3 Tables buckets
7
+ - S3 vector buckets
7
8
 
8
9
  Works in any class using ActiveModel::Validations and in Rails/ActiveRecord models. Ships with i18n messages in multiple locales.
9
10
 
@@ -23,8 +24,8 @@ bundle install
23
24
 
24
25
  ## Compatibility
25
26
 
26
- - Ruby: 3.1, 3.2, 3.3, 3.4 (CI runs 3.2–3.4)
27
- - ActiveModel: 7.2, 8.0 (CI targets)
27
+ - Ruby: 3.1, 3.2, 3.3, 3.4, 4.0 (CI runs 3.2–4.0)
28
+ - ActiveModel: 7.2, 8.0, 8.1 (CI targets)
28
29
  - Rails/ActiveRecord: supported via ActiveModel::Validations (no Rails runtime dependency)
29
30
 
30
31
  ## Quickstart
@@ -49,15 +50,18 @@ end
49
50
 
50
51
  ## Options
51
52
 
52
- - `type` — `:general_purpose` (default), `:directory`, or `:table`
53
+ - `type` — `:general_purpose` (default), `:directory`, `:table`, or `:vector`
54
+ - `namespace` — `:account_regional` allows the official account-regional general-purpose bucket suffix (`-<account-id>-<region>-an`)
53
55
  - `transfer_acceleration` — when `true`, periods are forbidden for general-purpose buckets
54
56
 
55
57
  Examples:
56
58
 
57
59
  ```ruby
58
60
  validates :bucket_name, s3_bucket_name: { transfer_acceleration: true }
61
+ validates :bucket_name, s3_bucket_name: { namespace: :account_regional }
59
62
  validates :bucket_name, s3_bucket_name: { type: :directory }
60
63
  validates :bucket_name, s3_bucket_name: { type: :table }
64
+ validates :bucket_name, s3_bucket_name: { type: :vector }
61
65
  ```
62
66
 
63
67
  ## i18n
@@ -67,6 +71,7 @@ Error keys provided:
67
71
  - `activemodel.errors.messages.s3_bucket_name_invalid_transfer_acceleration`
68
72
  - `activemodel.errors.messages.s3_bucket_name_invalid_directory`
69
73
  - `activemodel.errors.messages.s3_bucket_name_invalid_table`
74
+ - `activemodel.errors.messages.s3_bucket_name_invalid_vector`
70
75
 
71
76
  Locales shipped: en, es, it, fr, de, pt-BR, ja, ko, zh-CN, zh-TW, ru, nl.
72
77
 
@@ -76,12 +81,14 @@ Rails loads locales via a Railtie; plain ActiveModel loads them at require-time.
76
81
 
77
82
  - Length 3–63, allowed characters, begin/end alphanumeric
78
83
  - No adjacent periods; not IP-like (general purpose)
79
- - Reserved prefixes/suffixes per AWS docs (for example `xn--`, `sthree-`, `amzn-s3-demo-`, `-s3alias`, `--ol-s3`, `.mrap`, `--x-s3`, `--table-s3`)
84
+ - Reserved prefixes/suffixes per AWS docs (for example `xn--`, `sthree-`, `amzn-s3-demo-`, `-s3alias`, `--ol-s3`, `.mrap`, `--x-s3`, `--table-s3`, `-an`)
85
+ - Account-regional general-purpose buckets must use `bucket-name-prefix-accountId-region-an` and require `namespace: :account_regional`
80
86
  - Directory buckets must end with `--<zone-id>--x-s3`
81
87
  - S3 Tables buckets disallow periods and underscores
88
+ - S3 vector buckets disallow periods and underscores
82
89
  - Optional TA mode forbids periods
83
90
 
84
- Note: Global/partition uniqueness and immutability are service-side constraints and not enforced locally.
91
+ Note: namespace uniqueness and immutability are service-side constraints and not enforced locally.
85
92
 
86
93
  ## Examples
87
94
 
@@ -109,8 +116,8 @@ bundle install
109
116
  bundle exec rake test
110
117
 
111
118
  # With ActiveRecord integration (in-memory sqlite)
112
- AR_INTEGRATION=1 ACTIVERECORD_VERSION="~> 8.0" bundle install
113
- AR_INTEGRATION=1 ACTIVERECORD_VERSION="~> 8.0" bundle exec rake test
119
+ AR_INTEGRATION=1 ACTIVERECORD_VERSION="~> 8.1" bundle install
120
+ AR_INTEGRATION=1 ACTIVERECORD_VERSION="~> 8.1" bundle exec rake test
114
121
  ```
115
122
 
116
123
  ## License
@@ -1,18 +1,17 @@
1
-
2
1
  lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require "activerecord/s3/bucket/name/validator/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "activerecord-s3-bucket-name-validator"
8
- spec.version = Activerecord::S3::Bucket::Name::Validator::VERSION
9
- spec.authors = ["Claudio Poli"]
10
- spec.email = ["masterkain@gmail.com"]
6
+ spec.name = "activerecord-s3-bucket-name-validator"
7
+ spec.version = Activerecord::S3::Bucket::Name::Validator::VERSION
8
+ spec.authors = ["Claudio Poli"]
9
+ spec.email = ["masterkain@gmail.com"]
11
10
 
12
- spec.summary = %q{ActiveModel/ActiveRecord validator for Amazon S3 bucket naming rules}
13
- spec.description = %q{Validate S3 bucket names on your models against the official AWS rules (general purpose, directory buckets, and S3 Tables).}
14
- spec.homepage = "https://github.com/icoretech/activerecord-s3-bucket-name-validator"
15
- spec.license = "MIT"
11
+ spec.summary = "ActiveModel/ActiveRecord validator for Amazon S3 bucket naming rules"
12
+ spec.description = "Validate S3 bucket names on your models against the official AWS rules (general purpose, directory buckets, S3 Tables, and S3 Vectors)."
13
+ spec.homepage = "https://github.com/icoretech/activerecord-s3-bucket-name-validator"
14
+ spec.license = "MIT"
16
15
 
17
16
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
17
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -29,12 +28,16 @@ Gem::Specification.new do |spec|
29
28
  end
30
29
 
31
30
  # Specify which files should be added to the gem when it is released.
32
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
33
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
34
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
35
- end
36
- spec.bindir = "exe"
37
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ # Keep the package lean: include library code, locales, and top-level docs only.
32
+ spec.files = Dir[
33
+ "lib/**/*",
34
+ "config/locales/**/*",
35
+ "README*",
36
+ "LICENSE*",
37
+ "*.gemspec"
38
+ ]
39
+ spec.bindir = "exe"
40
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
41
  spec.require_paths = ["lib"]
39
42
 
40
43
  spec.required_ruby_version = ">= 3.1"
@@ -47,4 +50,5 @@ Gem::Specification.new do |spec|
47
50
  spec.add_development_dependency "bundler", ">= 1.17"
48
51
  spec.add_development_dependency "rake", ">= 10.0"
49
52
  spec.add_development_dependency "minitest", ">= 5.0"
53
+ spec.add_development_dependency "simplecov", ">= 0.22"
50
54
  end
@@ -6,4 +6,5 @@ de:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "darf keine Punkte enthalten, wenn S3 Transfer Acceleration verwendet wird"
7
7
  s3_bucket_name_invalid_directory: "ist kein gültiger S3-Verzeichnis-Bucket-Name (3–63 Zeichen; Kleinbuchstaben, Ziffern oder Bindestriche; muss mit --<zone-id>--x-s3 enden; reservierte Präfixe/Suffixe nicht erlaubt)"
8
8
  s3_bucket_name_invalid_table: "ist kein gültiger S3-Tables-Bucket-Name (3–63 Zeichen; Kleinbuchstaben, Ziffern oder Bindestriche; keine Punkte oder Unterstriche; keine reservierten Präfixe/Suffixe)"
9
+ s3_bucket_name_invalid_vector: "ist kein gültiger S3-Vectors-Bucket-Name (3–63 Zeichen; Kleinbuchstaben, Ziffern oder Bindestriche; keine Punkte oder Unterstriche; beginnt/endet alphanumerisch)"
9
10
  s3_bucket_name_invalid: "ist kein gültiger S3-Bucket-Name"
@@ -6,4 +6,5 @@ en:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "cannot contain periods when using S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "is not a valid S3 directory bucket name (3–63 chars; lowercase letters, numbers or hyphens; must end with --<zone-id>--x-s3; reserved prefixes/suffixes not allowed)"
8
8
  s3_bucket_name_invalid_table: "is not a valid S3 Tables bucket name (3–63 chars; lowercase letters, numbers or hyphens; no periods or underscores; reserved prefixes/suffixes not allowed)"
9
+ s3_bucket_name_invalid_vector: "is not a valid S3 Vectors bucket name (3–63 chars; lowercase letters, numbers or hyphens; no periods or underscores; start/end alphanumeric)"
9
10
  s3_bucket_name_invalid: "is not a valid S3 bucket name"
@@ -6,4 +6,5 @@ es:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "no puede contener puntos cuando se usa S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "no es un nombre de bucket de directorio S3 válido (3–63 caracteres; letras minúsculas, números o guiones; debe terminar con --<zone-id>--x-s3; prefijos/sufijos reservados no permitidos)"
8
8
  s3_bucket_name_invalid_table: "no es un nombre de bucket S3 Tables válido (3–63 caracteres; letras minúsculas, números o guiones; sin puntos ni guiones bajos; sin prefijos/sufijos reservados)"
9
+ s3_bucket_name_invalid_vector: "no es un nombre de bucket S3 Vectors válido (3–63 caracteres; letras minúsculas, números o guiones; sin puntos ni guiones bajos; empieza y termina alfanumérico)"
9
10
  s3_bucket_name_invalid: "no es un nombre de bucket S3 válido"
@@ -6,4 +6,5 @@ fr:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "ne peut pas contenir de points avec S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "n’est pas un nom de bucket de répertoire S3 valide (3–63 caractères ; lettres minuscules, chiffres ou tirets ; doit se terminer par --<zone-id>--x-s3 ; préfixes/suffixes réservés interdits)"
8
8
  s3_bucket_name_invalid_table: "n’est pas un nom de bucket S3 Tables valide (3–63 caractères ; lettres minuscules, chiffres ou tirets ; sans points ni underscores ; pas de préfixes/suffixes réservés)"
9
+ s3_bucket_name_invalid_vector: "n’est pas un nom de bucket S3 Vectors valide (3–63 caractères ; lettres minuscules, chiffres ou tirets ; sans points ni underscores ; commence et se termine par un caractère alphanumérique)"
9
10
  s3_bucket_name_invalid: "n’est pas un nom de bucket S3 valide"
@@ -6,4 +6,5 @@ it:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "non può contenere punti quando si usa S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "non è un nome bucket directory S3 valido (3–63 caratteri; lettere minuscole, numeri o trattini; deve terminare con --<zone-id>--x-s3; prefissi/suffissi riservati non consentiti)"
8
8
  s3_bucket_name_invalid_table: "non è un nome bucket S3 Tables valido (3–63 caratteri; lettere minuscole, numeri o trattini; senza punti o underscore; senza prefissi/suffissi riservati)"
9
+ s3_bucket_name_invalid_vector: "non è un nome bucket S3 Vectors valido (3–63 caratteri; lettere minuscole, numeri o trattini; senza punti o underscore; inizia/termina alfanumerico)"
9
10
  s3_bucket_name_invalid: "non è un nome bucket S3 valido"
@@ -6,4 +6,5 @@ ja:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "S3 Transfer Acceleration を使用する場合、ピリオドは使用できません"
7
7
  s3_bucket_name_invalid_directory: "有効な S3 ディレクトリバケット名ではありません(3~63 文字、小文字の英字・数字・ハイフン、末尾に --<zone-id>--x-s3 必須、予約済みの接頭/接尾辞不可)"
8
8
  s3_bucket_name_invalid_table: "有効な S3 Tables バケット名ではありません(3~63 文字、小文字の英字・数字・ハイフン、ピリオドおよびアンダースコア不可、予約済みの接頭/接尾辞不可)"
9
+ s3_bucket_name_invalid_vector: "有効な S3 Vectors バケット名ではありません(3~63 文字、小文字の英字・数字・ハイフン、ピリオドおよびアンダースコア不可、先頭/末尾は英数字)"
9
10
  s3_bucket_name_invalid: "有効な S3 バケット名ではありません"
@@ -6,4 +6,5 @@ ko:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "S3 Transfer Acceleration 사용 시 점(.)을 포함할 수 없습니다"
7
7
  s3_bucket_name_invalid_directory: "유효한 S3 디렉터리 버킷 이름이 아닙니다(3–63자; 소문자, 숫자 또는 하이픈; '--<zone-id>--x-s3'로 끝나야 함; 예약된 접두사/접미사 금지)"
8
8
  s3_bucket_name_invalid_table: "유효한 S3 Tables 버킷 이름이 아닙니다(3–63자; 소문자, 숫자 또는 하이픈; 점/밑줄 금지; 예약된 접두사/접미사 금지)"
9
+ s3_bucket_name_invalid_vector: "유효한 S3 Vectors 버킷 이름이 아닙니다(3–63자; 소문자, 숫자 또는 하이픈; 점/밑줄 금지; 시작/끝은 영숫자)"
9
10
  s3_bucket_name_invalid: "유효한 S3 버킷 이름이 아닙니다"
@@ -6,4 +6,5 @@ nl:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "mag geen punten bevatten wanneer S3 Transfer Acceleration wordt gebruikt"
7
7
  s3_bucket_name_invalid_directory: "is geen geldige S3-directorybucketnaam (3–63 tekens; kleine letters, cijfers of koppeltekens; moet eindigen op --<zone-id>--x-s3; gereserveerde voor-/achtervoegsels niet toegestaan)"
8
8
  s3_bucket_name_invalid_table: "is geen geldige S3 Tables-bucketnaam (3–63 tekens; kleine letters, cijfers of koppeltekens; geen punten of underscores; geen gereserveerde voor-/achtervoegsels)"
9
+ s3_bucket_name_invalid_vector: "is geen geldige S3 Vectors-bucketnaam (3–63 tekens; kleine letters, cijfers of koppeltekens; geen punten of underscores; begint/eindigt alfanumerisch)"
9
10
  s3_bucket_name_invalid: "is geen geldige S3-bucketnaam"
@@ -6,4 +6,5 @@ pt-BR:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "não pode conter pontos ao usar S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "não é um nome de bucket de diretório S3 válido (3–63 caracteres; letras minúsculas, números ou hífens; deve terminar com --<zone-id>--x-s3; prefixos/sufixos reservados não permitidos)"
8
8
  s3_bucket_name_invalid_table: "não é um nome de bucket S3 Tables válido (3–63 caracteres; letras minúsculas, números ou hífens; sem pontos ou underscores; sem prefixos/sufixos reservados)"
9
+ s3_bucket_name_invalid_vector: "não é um nome de bucket S3 Vectors válido (3–63 caracteres; letras minúsculas, números ou hífens; sem pontos ou underscores; começa/termina alfanumérico)"
9
10
  s3_bucket_name_invalid: "não é um nome de bucket S3 válido"
@@ -6,4 +6,5 @@ ru:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "нельзя использовать точки при S3 Transfer Acceleration"
7
7
  s3_bucket_name_invalid_directory: "недопустимое имя каталожного S3 бакета (3–63 символа; строчные буквы, цифры или дефисы; должно заканчиваться на --<zone-id>--x-s3; зарезервированные префиксы/суффиксы запрещены)"
8
8
  s3_bucket_name_invalid_table: "недопустимое имя бакета S3 Tables (3–63 символа; строчные буквы, цифры или дефисы; без точек и нижних подчёркиваний; зарезервированные префиксы/суффиксы запрещены)"
9
+ s3_bucket_name_invalid_vector: "недопустимое имя бакета S3 Vectors (3–63 символа; строчные буквы, цифры или дефисы; без точек и нижних подчёркиваний; начинается/заканчивается буквенно-цифровым символом)"
9
10
  s3_bucket_name_invalid: "недопустимое имя S3 бакета"
@@ -6,4 +6,5 @@ zh-CN:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "使用 S3 Transfer Acceleration 时,名称中不能包含点(.)"
7
7
  s3_bucket_name_invalid_directory: "不是有效的 S3 目录存储桶名称(3–63 个字符;小写字母、数字或连字符;必须以 --<zone-id>--x-s3 结尾;不得使用保留的前缀/后缀)"
8
8
  s3_bucket_name_invalid_table: "不是有效的 S3 Tables 存储桶名称(3–63 个字符;小写字母、数字或连字符;不允许点或下划线;不得使用保留的前缀/后缀)"
9
+ s3_bucket_name_invalid_vector: "不是有效的 S3 Vectors 存储桶名称(3–63 个字符;小写字母、数字或连字符;不允许点或下划线;首尾必须为字母或数字)"
9
10
  s3_bucket_name_invalid: "不是有效的 S3 存储桶名称"
@@ -6,4 +6,5 @@ zh-TW:
6
6
  s3_bucket_name_invalid_transfer_acceleration: "使用 S3 Transfer Acceleration 時,名稱中不可包含點(.)"
7
7
  s3_bucket_name_invalid_directory: "不是有效的 S3 目錄儲存貯體名稱(3–63 個字元;小寫字母、數字或連字號;必須以 --<zone-id>--x-s3 結尾;不得使用保留的前/後綴)"
8
8
  s3_bucket_name_invalid_table: "不是有效的 S3 Tables 儲存貯體名稱(3–63 個字元;小寫字母、數字或連字號;不可有點或底線;不得使用保留的前/後綴)"
9
+ s3_bucket_name_invalid_vector: "不是有效的 S3 Vectors 儲存貯體名稱(3–63 個字元;小寫字母、數字或連字號;不可有點或底線;開頭與結尾必須為英數字)"
9
10
  s3_bucket_name_invalid: "不是有效的 S3 儲存貯體名稱"
@@ -16,4 +16,3 @@ module Activerecord
16
16
  end
17
17
  end
18
18
  end
19
-
@@ -3,7 +3,7 @@ module Activerecord
3
3
  module Bucket
4
4
  module Name
5
5
  module Validator
6
- VERSION = "0.1.2"
6
+ VERSION = "0.2.0"
7
7
  end
8
8
  end
9
9
  end
@@ -23,14 +23,15 @@ end
23
23
  begin
24
24
  locales_glob = File.expand_path("../../../../../config/locales/*.yml", __FILE__)
25
25
  I18n.load_path += Dir[locales_glob] if Dir.exist?(File.dirname(locales_glob))
26
- rescue StandardError
26
+ rescue
27
27
  # ignore i18n loading errors
28
28
  end
29
29
 
30
30
  # Usage in a model:
31
31
  # validates :bucket_name, s3_bucket_name: { type: :general_purpose }
32
32
  # Options:
33
- # :type => :general_purpose (default), :directory, or :table
33
+ # :type => :general_purpose (default), :directory, :table, or :vector
34
+ # :namespace => :account_regional for general-purpose account regional bucket names
34
35
  # :transfer_acceleration => true to forbid periods for TA buckets
35
36
  class S3BucketNameValidator < ActiveModel::EachValidator
36
37
  RESERVED_PREFIXES_GENERAL = %w[xn-- sthree- amzn-s3-demo-].freeze
@@ -44,25 +45,32 @@ class S3BucketNameValidator < ActiveModel::EachValidator
44
45
  return if blank_ok?(value)
45
46
 
46
47
  valid = case type
47
- when :general_purpose then validate_general_purpose(value, transfer_acceleration: !!options[:transfer_acceleration])
48
- when :directory then validate_directory_bucket(value)
49
- when :table then validate_table_bucket(value)
50
- else
51
- record.errors.add(attribute, :invalid, message: "unknown bucket type: #{type}")
52
- false
53
- end
48
+ when :general_purpose
49
+ validate_general_purpose(
50
+ value,
51
+ transfer_acceleration: !!options[:transfer_acceleration],
52
+ namespace: options[:namespace]
53
+ )
54
+ when :directory then validate_directory_bucket(value)
55
+ when :table then validate_table_bucket(value)
56
+ when :vector then validate_vector_bucket(value)
57
+ else
58
+ record.errors.add(attribute, :invalid, message: "unknown bucket type: #{type}")
59
+ false
60
+ end
54
61
 
55
62
  unless valid
56
63
  error_key = if type == :general_purpose && options[:transfer_acceleration] && value.include?(".")
57
- :s3_bucket_name_invalid_transfer_acceleration
58
- else
59
- case type
60
- when :general_purpose then :s3_bucket_name_invalid_general
61
- when :directory then :s3_bucket_name_invalid_directory
62
- when :table then :s3_bucket_name_invalid_table
63
- else :s3_bucket_name_invalid
64
- end
65
- end
64
+ :s3_bucket_name_invalid_transfer_acceleration
65
+ else
66
+ case type
67
+ when :general_purpose then :s3_bucket_name_invalid_general
68
+ when :directory then :s3_bucket_name_invalid_directory
69
+ when :table then :s3_bucket_name_invalid_table
70
+ when :vector then :s3_bucket_name_invalid_vector
71
+ else :s3_bucket_name_invalid
72
+ end
73
+ end
66
74
  record.errors.add(attribute, error_key)
67
75
  end
68
76
  end
@@ -76,25 +84,27 @@ class S3BucketNameValidator < ActiveModel::EachValidator
76
84
  end
77
85
 
78
86
  # Based on AWS docs: General purpose bucket naming rules
79
- def validate_general_purpose(name, transfer_acceleration: false)
87
+ def validate_general_purpose(name, transfer_acceleration: false, namespace: nil)
80
88
  return false unless length_between?(name, 3, 63)
81
- return false unless name =~ /\A[a-z0-9.-]+\z/
89
+ return false unless /\A[a-z0-9.-]+\z/.match?(name)
82
90
  return false unless begins_and_ends_with_alnum?(name)
83
91
  return false if name.include?("..")
84
92
  return false if ip_like?(name)
85
93
  return false unless RESERVED_PREFIXES_GENERAL.none? { |p| name.start_with?(p) }
86
94
  return false unless RESERVED_SUFFIXES_GENERAL.none? { |s| name.end_with?(s) }
87
95
  return false if transfer_acceleration && name.include?(".")
96
+ return false if name.end_with?("-an") && namespace != :account_regional
97
+ return false if namespace == :account_regional && !account_regional_name?(name)
88
98
  true
89
99
  end
90
100
 
91
101
  # Based on AWS docs: Directory bucket naming rules (S3 Express One Zone)
92
102
  def validate_directory_bucket(name)
93
103
  return false unless length_between?(name, 3, 63)
94
- return false unless name =~ /\A[a-z0-9-]+\z/
104
+ return false unless /\A[a-z0-9-]+\z/.match?(name)
95
105
  return false unless begins_and_ends_with_alnum?(name)
96
106
  # must contain --<zone-id>--x-s3 suffix
97
- return false unless name =~ /--[a-z0-9-]+--x-s3\z/
107
+ return false unless /--[a-z0-9-]+--x-s3\z/.match?(name)
98
108
  # reserved prefixes/suffixes still apply
99
109
  return false if name.start_with?("xn--", "sthree-", "sthree-configurator", "amzn-s3-demo-")
100
110
  return false if name.end_with?("-s3alias", "--ol-s3", ".mrap", "--table-s3")
@@ -104,13 +114,21 @@ class S3BucketNameValidator < ActiveModel::EachValidator
104
114
  # Based on AWS docs: S3 Tables bucket naming rules
105
115
  def validate_table_bucket(name)
106
116
  return false unless length_between?(name, 3, 63)
107
- return false unless name =~ /\A[a-z0-9-]+\z/
117
+ return false unless /\A[a-z0-9-]+\z/.match?(name)
108
118
  return false unless begins_and_ends_with_alnum?(name)
109
119
  return false unless RESERVED_PREFIXES_TABLE.none? { |p| name.start_with?(p) }
110
120
  return false unless RESERVED_SUFFIXES_TABLE.none? { |s| name.end_with?(s) }
111
121
  true
112
122
  end
113
123
 
124
+ # Based on AWS docs: S3 vector bucket naming rules
125
+ def validate_vector_bucket(name)
126
+ return false unless length_between?(name, 3, 63)
127
+ return false unless /\A[a-z0-9-]+\z/.match?(name)
128
+ return false unless begins_and_ends_with_alnum?(name)
129
+ true
130
+ end
131
+
114
132
  def length_between?(str, min, max)
115
133
  str.length.between?(min, max)
116
134
  end
@@ -122,4 +140,8 @@ class S3BucketNameValidator < ActiveModel::EachValidator
122
140
  def ip_like?(str)
123
141
  str =~ /\A(?:\d{1,3}\.){3}\d{1,3}\z/
124
142
  end
143
+
144
+ def account_regional_name?(str)
145
+ /\A.+-\d{12}-[a-z0-9-]+-\d-an\z/.match?(str)
146
+ end
125
147
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-s3-bucket-name-validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Poli
@@ -85,26 +85,31 @@ dependencies:
85
85
  - - ">="
86
86
  - !ruby/object:Gem::Version
87
87
  version: '5.0'
88
+ - !ruby/object:Gem::Dependency
89
+ name: simplecov
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0.22'
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0.22'
88
102
  description: Validate S3 bucket names on your models against the official AWS rules
89
- (general purpose, directory buckets, and S3 Tables).
103
+ (general purpose, directory buckets, S3 Tables, and S3 Vectors).
90
104
  email:
91
105
  - masterkain@gmail.com
92
106
  executables: []
93
107
  extensions: []
94
108
  extra_rdoc_files: []
95
109
  files:
96
- - ".github/workflows/release.yaml"
97
- - ".github/workflows/test.yml"
98
- - ".gitignore"
99
- - ".ruby-version"
100
- - Gemfile
101
- - Gemfile.lock
102
110
  - LICENSE.txt
103
111
  - README.md
104
- - Rakefile
105
112
  - activerecord-s3-bucket-name-validator.gemspec
106
- - bin/console
107
- - bin/setup
108
113
  - config/locales/de.yml
109
114
  - config/locales/en.yml
110
115
  - config/locales/es.yml
@@ -1,28 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- tags:
6
- - v*
7
- workflow_dispatch:
8
-
9
- permissions:
10
- contents: read
11
- id-token: write
12
-
13
- jobs:
14
- release:
15
- runs-on: ubuntu-latest
16
- steps:
17
- - uses: actions/checkout@v5
18
- - name: Set up Ruby
19
- uses: ruby/setup-ruby@v1
20
- with:
21
- ruby-version: '3.4'
22
- bundler-cache: false
23
- - name: Configure RubyGems credentials (OIDC)
24
- uses: rubygems/configure-rubygems-credentials@v1.0.0
25
- - name: Build gem
26
- run: gem build *.gemspec
27
- - name: Push gem
28
- run: gem push *.gem
@@ -1,77 +0,0 @@
1
- name: Test
2
-
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches: [ main, master ]
7
- pull_request:
8
- branches: [ main, master ]
9
- schedule:
10
- - cron: "0 0 * * 0"
11
-
12
- permissions:
13
- contents: read
14
-
15
- concurrency:
16
- group: test-${{ github.ref }}
17
- cancel-in-progress: true
18
-
19
- jobs:
20
- test:
21
- strategy:
22
- matrix:
23
- ruby: ["3.2", "3.3", "3.4"]
24
- activemodel: ["~> 7.2", "~> 8.0"]
25
- runs-on: ubuntu-latest
26
-
27
- steps:
28
- - uses: actions/checkout@v5
29
- - name: Set up Environment Variables
30
- run: |
31
- echo "ACTIVEMODEL_VERSION=${{ matrix.activemodel }}" >> $GITHUB_ENV
32
-
33
- - name: Set up Ruby
34
- uses: ruby/setup-ruby@v1
35
- with:
36
- ruby-version: ${{ matrix.ruby }}
37
- bundler-cache: false
38
- - name: Prepare Gemfile for matrix
39
- run: |
40
- bundle config set frozen false
41
- bundle lock --add-platform ruby --add-platform x86_64-linux || true
42
- if [ -n "${{ matrix.activemodel }}" ]; then
43
- bundle lock --update activemodel || true
44
- fi
45
- - name: Install dependencies
46
- run: bundle install --jobs 4 --retry 1
47
-
48
- - name: Run tests
49
- run: bundle exec rake test
50
-
51
- ar_integration:
52
- strategy:
53
- matrix:
54
- ruby: ["3.2", "3.3", "3.4"]
55
- activerecord: ["~> 7.2", "~> 8.0"]
56
- runs-on: ubuntu-latest
57
-
58
- steps:
59
- - uses: actions/checkout@v5
60
- - name: Set up Environment Variables
61
- run: |
62
- echo "AR_INTEGRATION=1" >> $GITHUB_ENV
63
- echo "ACTIVERECORD_VERSION=${{ matrix.activerecord }}" >> $GITHUB_ENV
64
- - name: Set up Ruby
65
- uses: ruby/setup-ruby@v1
66
- with:
67
- ruby-version: ${{ matrix.ruby }}
68
- bundler-cache: false
69
- - name: Prepare Gemfile for AR matrix
70
- run: |
71
- bundle config set frozen false
72
- bundle lock --add-platform ruby --add-platform x86_64-linux || true
73
- bundle lock --update activerecord sqlite3 || true
74
- - name: Install dependencies
75
- run: bundle install --jobs 4 --retry 1
76
- - name: Run integration tests
77
- run: bundle exec rake test
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- /vendor/
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 3.4.3
data/Gemfile DELETED
@@ -1,18 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Allow CI to pin a specific ActiveModel version via env var
6
- am_ver = ENV["ACTIVEMODEL_VERSION"]
7
- gem "activemodel", am_ver if am_ver
8
-
9
- # Optional: ActiveRecord integration testing
10
- if ENV["AR_INTEGRATION"] == "1"
11
- ar_ver = ENV["ACTIVERECORD_VERSION"]
12
- gem "activerecord", ar_ver || ">= 7.0", "< 9"
13
- sqlite_req = (ar_ver && ar_ver.start_with?("~> 8")) ? ">= 2.1" : ">= 1.6"
14
- gem "sqlite3", sqlite_req
15
- end
16
-
17
- # Specify your gem's dependencies in activerecord-s3-bucket-name-validator.gemspec
18
- gemspec
data/Gemfile.lock DELETED
@@ -1,53 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- activerecord-s3-bucket-name-validator (0.1.0)
5
- activemodel (>= 7.0, < 9)
6
- i18n (>= 1.0)
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- activemodel (8.0.3)
12
- activesupport (= 8.0.3)
13
- activesupport (8.0.3)
14
- base64
15
- benchmark (>= 0.3)
16
- bigdecimal
17
- concurrent-ruby (~> 1.0, >= 1.3.1)
18
- connection_pool (>= 2.2.5)
19
- drb
20
- i18n (>= 1.6, < 2)
21
- logger (>= 1.4.2)
22
- minitest (>= 5.1)
23
- securerandom (>= 0.3)
24
- tzinfo (~> 2.0, >= 2.0.5)
25
- uri (>= 0.13.1)
26
- base64 (0.3.0)
27
- benchmark (0.4.1)
28
- bigdecimal (3.2.3)
29
- concurrent-ruby (1.3.5)
30
- connection_pool (2.5.4)
31
- drb (2.2.3)
32
- i18n (1.14.7)
33
- concurrent-ruby (~> 1.0)
34
- logger (1.7.0)
35
- minitest (5.25.5)
36
- rake (13.3.0)
37
- securerandom (0.4.1)
38
- tzinfo (2.0.6)
39
- concurrent-ruby (~> 1.0)
40
- uri (1.0.3)
41
-
42
- PLATFORMS
43
- arm64-darwin-24
44
- ruby
45
-
46
- DEPENDENCIES
47
- activerecord-s3-bucket-name-validator!
48
- bundler (>= 1.17)
49
- minitest (>= 5.0)
50
- rake (>= 10.0)
51
-
52
- BUNDLED WITH
53
- 2.6.7
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- end
9
-
10
- task :default => :test
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "activerecord/s3/bucket/name/validator"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here