postfix_admin 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9877c43c00661c60c1fee5e200211c97cd4cdc8d53593985c3e49f8296d27b9
4
- data.tar.gz: 9d9744f09e0a9e3ccdc72af138a4879824f3cd00bc3a1a111d0320a30007ee84
3
+ metadata.gz: 79176db25ca525f4d2031a41bf66f35895ae7d96d944af8e607c75f7654a1916
4
+ data.tar.gz: 5d3f6f207505ff525e4e192d6d03747bb5c7cf08e90dad5d313d93893bbb8601
5
5
  SHA512:
6
- metadata.gz: 86dfd30f6793fd6c13d09e532d7499f2e040dbe654f1bf86299d79b518a96906b6e208fd87c9bbda631d577ccfe39fb08f910e9cc41617be00425c84860d03f2
7
- data.tar.gz: f553b648aefc912877d3bcc149258a1d529caa457827f24b04bc4c5d4b45d7fc1397c4189c56ba0e800360320b6295b92abbde0ff344dc56d764995d8d88c448
6
+ metadata.gz: be19b8e778bf216deb66d9cc922d75022fb32425036def3a8b0642086a56b81b899bf3ec5070f667926b085354a3803da82f9d9b1e09075bae181876e67ac59f
7
+ data.tar.gz: 6af8ea674a934b5c522880a8c7f5a0c2d1a9c41959e626280f781ff6e6b62065b870830ee288582d49cafe91c83f8c42e535b61d9c62809c510fbdf396f72174
data/CHANGELOG.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.3.2
4
+ * Added `-d` (description) option for the `setup` subcommand
5
+
3
6
  ## 0.3.1
4
- + Added `admins`, `domains`, `accounts`, `aliases` and `forwards` subcommands
7
+ * Added `admins`, `domains`, `accounts`, `aliases` and `forwards` subcommands
5
8
  * Added `teardown` subcommand for the opposite operation of `setup`
6
9
  * `delete_domain` subcommand removes logs associated with the domain
7
10
  * Added `-s` (scheme) and `-r` (rounds) options for subcommands that require password arguments
data/README.md CHANGED
@@ -35,6 +35,20 @@ Execute the `postfix_admin` command to generate your config file at `~/.postfix_
35
35
  Edit the file for your environment:
36
36
 
37
37
  $ vi ~/.postfix_admin.conf
38
+ ---
39
+ database: mysql2://postfix:password@localhost/postfix
40
+ aliases: 30
41
+ mailboxes: 30
42
+ maxquota: 100
43
+ scheme: CRAM-MD5
44
+
45
+ The configuration file format is as follows:
46
+
47
+ database: mysql2://<username>:<password>@<host>/<database>
48
+ aliases: Default maximum number of aliases allowed per domain
49
+ mailboxes: Default maximum number of mailboxes allowed per domain
50
+ maxquota: Default maximum quota (in MB) allowed per mailbox for a domain
51
+ scheme: Default password scheme
38
52
 
39
53
  You can see the domains on your host if the `database` parameter is set properly:
40
54
 
data/docker-compose.yml CHANGED
@@ -3,7 +3,6 @@
3
3
  # Run tests on service app
4
4
  # You may need to run tests on Docker because of its requirement of `doveadm` command.
5
5
  # docker compose exec app bundle exec rake setup_test_db
6
- # docker compose exec app bundle exec rake test
7
6
  # docker compose exec app bundle exec rake spec
8
7
  #
9
8
  # rspec spec/runner_spec.rb
@@ -122,12 +122,13 @@ module PostfixAdmin
122
122
 
123
123
  attributes = {
124
124
  address: address,
125
- goto: goto
125
+ goto: goto,
126
+ domain: domain_name
126
127
  }
127
128
 
128
- domain.rel_aliases << Alias.new(attributes)
129
+ new_alias = Alias.new(attributes)
129
130
 
130
- raise_save_error(domain) unless domain.save
131
+ raise_save_error(new_alias) unless new_alias.save
131
132
  end
132
133
 
133
134
  def delete_alias(address)
@@ -153,7 +154,7 @@ module PostfixAdmin
153
154
  raise_error "Domain has already been registered: #{domain_name}"
154
155
  end
155
156
 
156
- new_description = description || domain_name
157
+ new_description = description || ""
157
158
 
158
159
  domain = Domain.new
159
160
  domain.attributes = {
@@ -206,7 +207,8 @@ module PostfixAdmin
206
207
  end
207
208
 
208
209
  def raise_save_error(obj)
209
- raise_error "Failed to save #{obj.class}: #{obj.errors.full_messages.join(', ')}"
210
+ massage = obj.errors.full_messages.join(', ')
211
+ raise_error "Failed to save #{obj.class}: #{massage}"
210
212
  end
211
213
 
212
214
  def address_split(address)
@@ -60,6 +60,8 @@ module PostfixAdmin
60
60
  show_domains
61
61
  puts
62
62
  show_admins
63
+ puts
64
+ show_recent_logs
63
65
  end
64
66
  end
65
67
 
@@ -71,11 +73,23 @@ module PostfixAdmin
71
73
  end
72
74
  end
73
75
 
76
+ def show_recent_logs
77
+ if Log.count.zero?
78
+ puts "No logs"
79
+ return
80
+ end
81
+
82
+ logs = Log.last(10)
83
+ puts_title("Recent Logs")
84
+ puts_log_table(logs)
85
+ end
86
+
74
87
  # Set up a domain
75
88
  # Add a domain, add an admin, and grant the admin access to the domain
76
- def setup_domain(domain_name, password, scheme: nil, rounds: nil)
89
+ def setup_domain(domain_name, password, description: nil,
90
+ scheme: nil, rounds: nil)
77
91
  admin = "admin@#{domain_name}"
78
- add_domain(domain_name)
92
+ add_domain(domain_name, description: description)
79
93
  add_admin(admin, password, scheme: scheme, rounds: rounds)
80
94
  add_admin_domain(admin, domain_name)
81
95
  end
@@ -139,6 +153,7 @@ module PostfixAdmin
139
153
  "Active", "Description"]
140
154
 
141
155
  puts_title("Domains")
156
+
142
157
  if Domain.without_all.empty?
143
158
  puts "No domains"
144
159
  return
@@ -146,9 +161,7 @@ module PostfixAdmin
146
161
 
147
162
  Domain.without_all.each_with_index do |d, i|
148
163
  no = i + 1
149
- aliases_str = "%4d / %4s" % [d.pure_aliases.count, d.aliases_str]
150
- mailboxes_str = "%4d / %4s" % [d.rel_mailboxes.count, d.mailboxes_str]
151
- rows << [no.to_s, d.domain, aliases_str, mailboxes_str,
164
+ rows << [no.to_s, d.domain, d.alias_usage_display_str, d.mailbox_usage_display_str,
152
165
  d.maxquota_str, d.active_str, d.description]
153
166
  end
154
167
 
@@ -207,6 +220,7 @@ module PostfixAdmin
207
220
  headings = ["No.", "Admin", "Domains", "Active", "Scheme Prefix"]
208
221
 
209
222
  puts_title("Admins")
223
+
210
224
  if admins.empty?
211
225
  puts "No admins"
212
226
  return
@@ -235,6 +249,7 @@ module PostfixAdmin
235
249
  "Scheme Prefix", "Maildir"]
236
250
 
237
251
  puts_title("Accounts")
252
+
238
253
  if mailboxes.empty?
239
254
  puts "No accounts"
240
255
  return
@@ -276,6 +291,7 @@ module PostfixAdmin
276
291
  def show_admin_domain(user_name)
277
292
  admin = Admin.find(user_name)
278
293
  puts_title("Admin Domains (#{user_name})")
294
+
279
295
  if admin.rel_domains.empty?
280
296
  puts "\nNo domains for #{user_name}"
281
297
  return
@@ -286,6 +302,7 @@ module PostfixAdmin
286
302
  no = i + 1
287
303
  rows << [no.to_s, d.domain]
288
304
  end
305
+
289
306
  puts_table(rows: rows, headings: %w[No. Domain])
290
307
  end
291
308
 
@@ -331,7 +348,7 @@ module PostfixAdmin
331
348
 
332
349
  def edit_account(address, options)
333
350
  quota = options[:quota]
334
- raise "Invalid Quota value: #{quota}" if quota && quota <= 0
351
+ raise "Invalid Quota value: #{quota}" if quota && quota < 0
335
352
 
336
353
  mailbox_check(address)
337
354
  mailbox = Mailbox.find(address)
@@ -377,7 +394,7 @@ module PostfixAdmin
377
394
  end
378
395
 
379
396
  def log(domain: nil, last: nil)
380
- headings = %w[Timestamp Admin Domain Action Data]
397
+ headings = %w[No. Timestamp Admin Domain Action Data]
381
398
  rows = []
382
399
 
383
400
  logs = if domain
@@ -388,10 +405,17 @@ module PostfixAdmin
388
405
 
389
406
  logs = logs.last(last) if last
390
407
 
391
- logs.each do |l|
408
+ puts_log_table(logs)
409
+ end
410
+
411
+ def puts_log_table(logs)
412
+ headings = %w[No. Timestamp Admin Domain Action Data]
413
+ rows = []
414
+ logs.each_with_index do |l, i|
415
+ no = i + 1
392
416
  # TODO: Consider if zone should be included ('%Z').
393
417
  time = l.timestamp.strftime("%Y-%m-%d %X")
394
- rows << [time, l.username, l.domain, l.action, l.data]
418
+ rows << [no, time, l.username, l.domain, l.action, l.data]
395
419
  end
396
420
 
397
421
  puts_table(headings: headings, rows: rows)
@@ -404,24 +428,28 @@ module PostfixAdmin
404
428
  puts [a.username, %Q!"#{a.password}"!, a.super_admin?, a.active].join(',')
405
429
  end
406
430
  puts
431
+
407
432
  puts "Domains"
408
433
  puts "Domain Name,Max Quota,Active"
409
434
  Domain.without_all.each do |d|
410
435
  puts [d.domain, d.maxquota, d.active].join(',')
411
436
  end
412
437
  puts
438
+
413
439
  puts "Mailboxes"
414
440
  puts "User Name,Name,Password,Quota,Maildir,Active"
415
441
  Mailbox.all.each do |m|
416
442
  puts [m.username, %Q!"#{m.name}"!, %Q!"#{m.password}"!, m.quota, %Q!"#{m.maildir}"!, m.active].join(',')
417
443
  end
418
444
  puts
445
+
419
446
  puts "Aliases"
420
447
  puts "Address,Go to,Active"
421
448
  Alias.all.select { |a| !a.mailbox? }.each do |a|
422
449
  puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
423
450
  end
424
451
  puts
452
+
425
453
  puts "Forwards"
426
454
  puts "Address,Go to,Active"
427
455
  Alias.all.select { |a| a.mailbox? && a.goto != a.address }.each do |a|
@@ -438,6 +466,7 @@ module PostfixAdmin
438
466
  rows << ["Admins", Admin.count]
439
467
  rows << ["Mailboxes", Mailbox.count]
440
468
  rows << ["Aliases", Alias.pure.count]
469
+ rows << ["Logs", Log.count]
441
470
 
442
471
  puts_title(title)
443
472
  puts_table(rows: rows)
@@ -449,8 +478,8 @@ module PostfixAdmin
449
478
 
450
479
  rows = []
451
480
  domain = Domain.find(domain_name)
452
- rows << ["Mailboxes", "%4d / %4s" % [domain.rel_mailboxes.count, domain.mailboxes_str]]
453
- rows << ["Aliases", "%4d / %4s" % [domain.pure_aliases.count, domain.aliases_str]]
481
+ rows << ["Mailboxes", domain.mailbox_usage_display_str]
482
+ rows << ["Aliases", domain.alias_usage_display_str]
454
483
  rows << ["Max Quota (MB)", domain.maxquota_str]
455
484
  rows << ["Active", domain.active_str]
456
485
  rows << ["Description", domain.description]
@@ -505,6 +534,7 @@ module PostfixAdmin
505
534
  puts "configure file: #{config_file} was generated.\nPlease execute after edit it."
506
535
  exit
507
536
  end
537
+
508
538
  open(config_file) do |f|
509
539
  YAML.load(f.read)
510
540
  end
@@ -1,4 +1,5 @@
1
- require 'postfix_admin/models/concerns/has_password'
1
+ require "postfix_admin/models/application_record"
2
+ require "postfix_admin/models/concerns/has_password"
2
3
 
3
4
  module PostfixAdmin
4
5
  class Admin < ApplicationRecord
@@ -1,3 +1,5 @@
1
+ require "postfix_admin/models/application_record"
2
+
1
3
  module PostfixAdmin
2
4
  class Alias < ApplicationRecord
3
5
  # version: 1841
@@ -18,10 +20,16 @@ module PostfixAdmin
18
20
 
19
21
  validate on: :create do |a|
20
22
  domain = a.rel_domain
21
- if domain.aliases.zero? || a.mailbox
22
- elsif domain.rel_aliases.pure.count >= domain.aliases
23
- message = "already has the maximum number of aliases " \
24
- "(maximum is #{domain.aliases} aliases)"
23
+
24
+ if domain.alias_unlimited?
25
+ # unlimited: do nothing
26
+ elsif domain.alias_disabled?
27
+ # disabled
28
+ a.errors.add(:domain, "has a disabled status for aliases")
29
+ elsif domain.pure_alias_count >= domain.aliases
30
+ # exceeding alias limit
31
+ message = "has already reached the maximum number of aliases " \
32
+ "(maximum: #{domain.aliases})"
25
33
  a.errors.add(:domain, message)
26
34
  end
27
35
  end
@@ -1,5 +1,5 @@
1
- require 'active_record'
2
- require 'postfix_admin/models/concerns/existing_timestamp'
1
+ require "active_record"
2
+ require "postfix_admin/models/concerns/existing_timestamp"
3
3
 
4
4
  module PostfixAdmin
5
5
  class ApplicationRecord < ActiveRecord::Base
@@ -1,3 +1,5 @@
1
+ require "postfix_admin/models/application_record"
2
+
1
3
  module PostfixAdmin
2
4
  class Domain < ApplicationRecord
3
5
  # version: 1841
@@ -18,6 +20,9 @@ module PostfixAdmin
18
20
  # | active | tinyint(1) | NO | | 1 | |
19
21
  # +-------------+--------------+------+-----+---------------------+-------+
20
22
 
23
+ UNLIMITED = 0
24
+ DISABLED = -1
25
+
21
26
  self.table_name = :domain
22
27
  self.primary_key = :domain
23
28
 
@@ -84,6 +89,22 @@ module PostfixAdmin
84
89
  rel_aliases.pure
85
90
  end
86
91
 
92
+ def mailbox_count
93
+ rel_mailboxes.count
94
+ end
95
+
96
+ def pure_alias_count
97
+ pure_aliases.count
98
+ end
99
+
100
+ def mailbox_usage_display_str
101
+ "%4d / %4s" % [mailbox_count, mailboxes_str]
102
+ end
103
+
104
+ def alias_usage_display_str
105
+ "%4d / %4s" % [pure_alias_count, aliases_str]
106
+ end
107
+
87
108
  def aliases_str
88
109
  max_num_str(aliases)
89
110
  end
@@ -96,13 +117,33 @@ module PostfixAdmin
96
117
  max_num_str(maxquota)
97
118
  end
98
119
 
120
+ def mailbox_unlimited?
121
+ mailboxes == UNLIMITED
122
+ end
123
+
124
+ def alias_unlimited?
125
+ aliases == UNLIMITED
126
+ end
127
+
128
+ def maxquota_unlimited?
129
+ maxquota.zero?
130
+ end
131
+
132
+ def mailbox_disabled?
133
+ mailboxes == DISABLED
134
+ end
135
+
136
+ def alias_disabled?
137
+ aliases == DISABLED
138
+ end
139
+
99
140
  private
100
141
 
101
142
  def max_num_str(num)
102
143
  case num
103
- when -1
144
+ when DISABLED
104
145
  "Disabled"
105
- when 0
146
+ when UNLIMITED
106
147
  "Unlimited"
107
148
  else
108
149
  num.to_s
@@ -1,3 +1,5 @@
1
+ require "postfix_admin/models/application_record"
2
+
1
3
  module PostfixAdmin
2
4
  class DomainAdmin < ApplicationRecord
3
5
  # version: 1841
@@ -1,3 +1,5 @@
1
+ require "postfix_admin/models/application_record"
2
+
1
3
  module PostfixAdmin
2
4
  class Log < ApplicationRecord
3
5
  # version: 1841
@@ -1,4 +1,5 @@
1
- require 'postfix_admin/models/concerns/has_password'
1
+ require "postfix_admin/models/application_record"
2
+ require "postfix_admin/models/concerns/has_password"
2
3
 
3
4
  module PostfixAdmin
4
5
  class Mailbox < ApplicationRecord
@@ -23,13 +24,14 @@ module PostfixAdmin
23
24
  # | token_validity | datetime | NO | | 2000-01-01 00:00:00 | |
24
25
  # +----------------+--------------+------+-----+---------------------+-------+
25
26
 
27
+ UNLIMITED_QUOTA = 0
28
+ DISABLED_QUOTA = -1
29
+
26
30
  self.table_name = :mailbox
27
31
  self.primary_key = :username
28
32
 
29
33
  include HasPassword
30
34
 
31
- # attribute :quota_mb, :integer
32
-
33
35
  validates :username, presence: true, uniqueness: { case_sensitive: false },
34
36
  format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
35
37
  message: "must be a valid email address" }
@@ -48,9 +50,16 @@ module PostfixAdmin
48
50
 
49
51
  validate on: :create do |mailbox|
50
52
  domain = mailbox.rel_domain
51
- if !domain.mailboxes.zero? && domain.rel_mailboxes.count >= domain.mailboxes
52
- message = "already has the maximum number of mailboxes " \
53
- "(maximum is #{domain.mailboxes} mailboxes)"
53
+
54
+ if domain.mailbox_unlimited?
55
+ # unlimited: do nothing
56
+ elsif domain.mailbox_disabled?
57
+ # disabled
58
+ mailbox.errors.add(:domain, "has a disabled status for mailboxes")
59
+ elsif domain.mailbox_count >= domain.mailboxes
60
+ # exceeding mailbox limit
61
+ message = "has already reached the maximum number of mailboxes " \
62
+ "(maximum: #{domain.mailboxes})"
54
63
  mailbox.errors.add(:domain, message)
55
64
  end
56
65
  end
@@ -62,17 +71,21 @@ module PostfixAdmin
62
71
  end
63
72
 
64
73
  validate do |mailbox|
65
- next if mailbox.quota == -1
74
+ next if mailbox.quota == DISABLED_QUOTA
66
75
 
67
76
  domain = mailbox.rel_domain
68
77
 
69
- unless domain.maxquota.zero?
70
- if mailbox.quota.zero?
71
- mailbox.errors.add(:quota, "cannot be 0")
72
- elsif mailbox.quota_mb > domain.maxquota
73
- message = "must be less than or equal to #{domain.maxquota} (MB)"
74
- mailbox.errors.add(:quota, message)
75
- end
78
+ next if domain.maxquota_unlimited?
79
+
80
+ # Quota limit
81
+ message = "must be less than or equal to #{domain.maxquota} MB"
82
+ if mailbox.quota_unlimited?
83
+ # trying to set quota to 0 (unlimited) even when domain's maxquota is not unlimited
84
+ mailbox.errors.add(:quota, "cannot be set to 0 (unlimited)")
85
+ mailbox.errors.add(:quota, message)
86
+ elsif mailbox.quota_mb > domain.maxquota
87
+ # trying to set quota to value greater than domain's maxquota
88
+ mailbox.errors.add(:quota, message)
76
89
  end
77
90
  end
78
91
 
@@ -84,6 +97,10 @@ module PostfixAdmin
84
97
  domain: mailbox.domain)
85
98
  end
86
99
 
100
+ def quota_unlimited?
101
+ quota.zero?
102
+ end
103
+
87
104
  def quota_mb
88
105
  raise Error, "quota is out of range: #{quota}" if quota < 0
89
106
 
@@ -108,10 +125,10 @@ module PostfixAdmin
108
125
 
109
126
  def quota_mb_str(format: "%6.1f")
110
127
  case quota
111
- when -1
128
+ when DISABLED_QUOTA
112
129
  # It's not sure what 'disabled' means for quota.
113
130
  "Disabled"
114
- when 0
131
+ when UNLIMITED_QUOTA
115
132
  "Unlimited"
116
133
  else
117
134
  quota_mb = quota / KB_TO_MB.to_f
@@ -1,3 +1,5 @@
1
+ require "postfix_admin/models/application_record"
2
+
1
3
  module PostfixAdmin
2
4
  class Quota2 < ApplicationRecord
3
5
  # version: 1841
@@ -55,17 +55,21 @@ module PostfixAdmin
55
55
  runner { @cli.show_forwards }
56
56
  end
57
57
 
58
- desc "setup example.com password", "Set up a domain (add a domain and an admin user for it)"
58
+ desc "setup example.com password",
59
+ "Set up a domain (add a domain and an admin user for it)"
60
+ method_option :description, type: :string, aliases: "-d", desc: "description"
59
61
  method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
60
62
  method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
61
63
  def setup(domain_name, password)
62
64
  runner do
63
65
  @cli.setup_domain(domain_name, password,
66
+ description: options[:description],
64
67
  scheme: options[:scheme], rounds: options[:rounds])
65
68
  end
66
69
  end
67
70
 
68
- desc "teardown example.com", "Tear down a domain (delete a domain and an admin user for it)"
71
+ desc "teardown example.com",
72
+ "Tear down a domain (delete a domain and an admin user for it)"
69
73
  def teardown(domain_name)
70
74
  runner { @cli.teardown_domain(domain_name) }
71
75
  end
@@ -99,11 +103,11 @@ module PostfixAdmin
99
103
  end
100
104
 
101
105
  desc "edit_domain example.com", "Edit a domain"
102
- method_option :aliases, type: :numeric, aliases: "-a", desc: "Edit aliases limitation"
103
- method_option :mailboxes, type: :numeric, aliases: "-m", desc: "Edit mailboxes limitation"
104
- method_option :maxquota, type: :numeric, aliases: "-q", desc: "Edit max quota limitation"
106
+ method_option :aliases, type: :numeric, aliases: "-a", desc: "Update aliase limit"
107
+ method_option :mailboxes, type: :numeric, aliases: "-m", desc: "Update mailboxe limit"
108
+ method_option :maxquota, type: :numeric, aliases: "-q", desc: "Update maximum quota limit (MB)"
105
109
  method_option :active, type: :boolean, desc: "Update active status"
106
- method_option :description, type: :string, aliases: "-d", desc: "Edit description"
110
+ method_option :description, type: :string, aliases: "-d", desc: "Update description"
107
111
  def edit_domain(domain_name)
108
112
  runner do
109
113
  if options.size == 0
@@ -153,11 +157,11 @@ module PostfixAdmin
153
157
 
154
158
  desc "edit_account user@example.com", "Edit an account"
155
159
  method_option :goto, type: :string, aliases: "-g",
156
- desc: "mailboxes, addresses e-mails are delivered to"
160
+ desc: "Update mailboxes, addresses emails are delivered to"
157
161
  method_option :quota, type: :numeric, aliases: "-q",
158
- desc: "quota limitation (MB)"
162
+ desc: "Update quota limit (MB)"
159
163
  method_option :name, type: :string, aliases: "-n",
160
- desc: "full name"
164
+ desc: "Update full name"
161
165
  method_option :active, type: :boolean,
162
166
  desc: "Update active status"
163
167
  def edit_account(address)
@@ -1,3 +1,3 @@
1
1
  module PostfixAdmin
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postfix_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hitoshi Kurokawa
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-10 00:00:00.000000000 Z
11
+ date: 2024-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor