postfix_admin 0.3.0 → 0.3.1

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.
@@ -1,5 +1,18 @@
1
1
  module PostfixAdmin
2
2
  class Alias < ApplicationRecord
3
+ # version: 1841
4
+ # > describe alias;
5
+ # +----------+--------------+------+-----+---------------------+-------+
6
+ # | Field | Type | Null | Key | Default | Extra |
7
+ # +----------+--------------+------+-----+---------------------+-------+
8
+ # | address | varchar(255) | NO | PRI | NULL | |
9
+ # | goto | text | NO | | NULL | |
10
+ # | domain | varchar(255) | NO | MUL | NULL | |
11
+ # | created | datetime | NO | | 2000-01-01 00:00:00 | |
12
+ # | modified | datetime | NO | | 2000-01-01 00:00:00 | |
13
+ # | active | tinyint(1) | NO | | 1 | |
14
+ # +----------+--------------+------+-----+---------------------+-------+
15
+
3
16
  self.table_name = :alias
4
17
  self.primary_key = :address
5
18
 
@@ -21,15 +34,11 @@ module PostfixAdmin
21
34
  belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
22
35
  belongs_to :mailbox, foreign_key: :address, optional: true
23
36
 
37
+ # aliases which do not belong to any mailbox
24
38
  scope :pure, -> { joins("LEFT OUTER JOIN mailbox ON alias.address = mailbox.username").where("mailbox.username" => nil) }
25
39
 
26
- attribute :local_part, :string
27
-
28
- before_validation do |a|
29
- unless a.address
30
- a.address = "#{a.local_part}@#{a.domain}" unless a.local_part.empty?
31
- end
32
- end
40
+ # aliases which belong to a mailbox and have forwardings to other addresses
41
+ scope :forward, -> { joins("LEFT OUTER JOIN mailbox ON alias.address = mailbox.username").where("mailbox.username <> alias.goto") }
33
42
 
34
43
  def mailbox?
35
44
  !!mailbox
@@ -1,5 +1,5 @@
1
1
  require 'active_record'
2
- require 'postfix_admin/concerns/existing_timestamp'
2
+ require 'postfix_admin/models/concerns/existing_timestamp'
3
3
 
4
4
  module PostfixAdmin
5
5
  class ApplicationRecord < ActiveRecord::Base
@@ -14,5 +14,4 @@ module ExistingTimestamp
14
14
  ["modified"]
15
15
  end
16
16
  end
17
-
18
- end
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'active_support/concern'
2
+
3
+ module HasPassword
4
+ extend ActiveSupport::Concern
5
+
6
+ # example: {CRAM-MD5}, {BLF-CRYPT}, {PLAIN}
7
+ # return nil if no scheme prefix
8
+ def scheme_prefix
9
+ res = password&.match(/^\{.*?\}/)
10
+ if res
11
+ res[0]
12
+ else
13
+ nil
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,23 @@
1
1
  module PostfixAdmin
2
2
  class Domain < ApplicationRecord
3
+ # version: 1841
4
+ # > describe domain;
5
+ # +-------------+--------------+------+-----+---------------------+-------+
6
+ # | Field | Type | Null | Key | Default | Extra |
7
+ # +-------------+--------------+------+-----+---------------------+-------+
8
+ # | domain | varchar(255) | NO | PRI | NULL | |
9
+ # | description | varchar(255) | NO | | NULL | |
10
+ # | aliases | int(10) | NO | | 0 | |
11
+ # | mailboxes | int(10) | NO | | 0 | |
12
+ # | maxquota | bigint(20) | NO | | 0 | |
13
+ # | quota | bigint(20) | NO | | 0 | |
14
+ # | transport | varchar(255) | NO | | NULL | |
15
+ # | backupmx | tinyint(1) | NO | | 0 | |
16
+ # | created | datetime | NO | | 2000-01-01 00:00:00 | |
17
+ # | modified | datetime | NO | | 2000-01-01 00:00:00 | |
18
+ # | active | tinyint(1) | NO | | 1 | |
19
+ # +-------------+--------------+------+-----+---------------------+-------+
20
+
3
21
  self.table_name = :domain
4
22
  self.primary_key = :domain
5
23
 
@@ -31,6 +49,10 @@ module PostfixAdmin
31
49
  has_many :rel_aliases, class_name: "Alias", foreign_key: :domain,
32
50
  dependent: :destroy
33
51
 
52
+ # logs that belong to this domain
53
+ has_many :logs, class_name: "Log", foreign_key: :domain,
54
+ dependent: :destroy
55
+
34
56
  # It causes errors to set `dependent: :destroy` as other columns
35
57
  # because the domain_admins table doesn't have a single primary key.
36
58
  #
@@ -45,6 +67,7 @@ module PostfixAdmin
45
67
  # It works well with `dependent: :delete_all` instead.
46
68
  #
47
69
  # PostfixAdmin::DomainAdmin Destroy (0.4ms) DELETE FROM `domain_admins` WHERE `domain_admins`.`domain` = 'example.com'
70
+ # Domain <-> DomainAdmin <-> Admin
48
71
  has_many :domain_admins, foreign_key: :domain, dependent: :delete_all
49
72
 
50
73
  has_many :admins, through: :domain_admins
@@ -0,0 +1,19 @@
1
+ module PostfixAdmin
2
+ class DomainAdmin < ApplicationRecord
3
+ # version: 1841
4
+ # > describe domain_admins;
5
+ # +----------+--------------+------+-----+---------------------+-------+
6
+ # | Field | Type | Null | Key | Default | Extra |
7
+ # +----------+--------------+------+-----+---------------------+-------+
8
+ # | username | varchar(255) | NO | MUL | NULL | |
9
+ # | domain | varchar(255) | NO | | NULL | |
10
+ # | created | datetime | NO | | 2000-01-01 00:00:00 | |
11
+ # | active | tinyint(1) | NO | | 1 | |
12
+ # +----------+--------------+------+-----+---------------------+-------+
13
+
14
+ self.table_name = :domain_admins
15
+
16
+ belongs_to :admin, primary_key: :username, foreign_key: :username
17
+ belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module PostfixAdmin
2
+ class Log < ApplicationRecord
3
+ # version: 1841
4
+ # > describe log;
5
+ # +-----------+--------------+------+-----+---------------------+----------------+
6
+ # | Field | Type | Null | Key | Default | Extra |
7
+ # +-----------+--------------+------+-----+---------------------+----------------+
8
+ # | timestamp | datetime | NO | MUL | 2000-01-01 00:00:00 | |
9
+ # | username | varchar(255) | NO | | NULL | |
10
+ # | domain | varchar(255) | NO | MUL | NULL | |
11
+ # | action | varchar(255) | NO | | NULL | |
12
+ # | data | text | NO | | NULL | |
13
+ # | id | int(11) | NO | PRI | NULL | auto_increment |
14
+ # +-----------+--------------+------+-----+---------------------+----------------+
15
+
16
+ self.table_name = :log
17
+
18
+ belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
19
+ end
20
+ end
@@ -0,0 +1,126 @@
1
+ require 'postfix_admin/models/concerns/has_password'
2
+
3
+ module PostfixAdmin
4
+ class Mailbox < ApplicationRecord
5
+ # version: 1841
6
+ # > describe mailbox;
7
+ # +----------------+--------------+------+-----+---------------------+-------+
8
+ # | Field | Type | Null | Key | Default | Extra |
9
+ # +----------------+--------------+------+-----+---------------------+-------+
10
+ # | username | varchar(255) | NO | PRI | NULL | |
11
+ # | password | varchar(255) | NO | | NULL | |
12
+ # | name | varchar(255) | NO | | NULL | |
13
+ # | maildir | varchar(255) | NO | | NULL | |
14
+ # | quota | bigint(20) | NO | | 0 | |
15
+ # | local_part | varchar(255) | NO | | NULL | |
16
+ # | domain | varchar(255) | NO | MUL | NULL | |
17
+ # | created | datetime | NO | | 2000-01-01 00:00:00 | |
18
+ # | modified | datetime | NO | | 2000-01-01 00:00:00 | |
19
+ # | active | tinyint(1) | NO | | 1 | |
20
+ # | phone | varchar(30) | NO | | | |
21
+ # | email_other | varchar(255) | NO | | | |
22
+ # | token | varchar(255) | NO | | | |
23
+ # | token_validity | datetime | NO | | 2000-01-01 00:00:00 | |
24
+ # +----------------+--------------+------+-----+---------------------+-------+
25
+
26
+ self.table_name = :mailbox
27
+ self.primary_key = :username
28
+
29
+ include HasPassword
30
+
31
+ # attribute :quota_mb, :integer
32
+
33
+ validates :username, presence: true, uniqueness: { case_sensitive: false },
34
+ format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
35
+ message: "must be a valid email address" }
36
+ validates :maildir, presence: true, uniqueness: { case_sensitive: false }
37
+ validates :local_part, presence: true
38
+
39
+ # quota (KB)
40
+ validates :quota, presence: true,
41
+ numericality: { only_integer: true,
42
+ greater_than_or_equal_to: 0 }
43
+
44
+ belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
45
+ has_one :alias, foreign_key: :address, dependent: :destroy
46
+ has_one :quota_usage, class_name: "Quota2", foreign_key: :username,
47
+ dependent: :destroy
48
+
49
+ validate on: :create do |mailbox|
50
+ 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)"
54
+ mailbox.errors.add(:domain, message)
55
+ end
56
+ end
57
+
58
+ # just in case
59
+ validate on: :update do |mailbox|
60
+ mailbox.errors.add(:username, 'cannot be changed') if mailbox.username_changed?
61
+ mailbox.errors.add(:local_part, 'cannot be changed') if mailbox.local_part_changed?
62
+ end
63
+
64
+ validate do |mailbox|
65
+ next if mailbox.quota == -1
66
+
67
+ domain = mailbox.rel_domain
68
+
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
76
+ end
77
+ end
78
+
79
+ before_validation do |mailbox|
80
+ mailbox.name = "" if mailbox.name.nil?
81
+ mailbox.username = "#{mailbox.local_part}@#{mailbox.domain}"
82
+ mailbox.maildir ||= "#{mailbox.domain}/#{mailbox.username}/"
83
+ mailbox.build_alias(address: mailbox.username, goto: mailbox.username,
84
+ domain: mailbox.domain)
85
+ end
86
+
87
+ def quota_mb
88
+ raise Error, "quota is out of range: #{quota}" if quota < 0
89
+
90
+ quota / KB_TO_MB
91
+ end
92
+
93
+ def quota_mb=(value)
94
+ raise Error, "quota is out of range: #{value}" if value < 0
95
+
96
+ self.quota = value * KB_TO_MB
97
+ end
98
+
99
+ def quota_usage_str(format: "%6.1f")
100
+ usage_mb = if quota_usage
101
+ usage_mb = quota_usage.bytes / KB_TO_MB.to_f
102
+ else
103
+ 0.0
104
+ end
105
+
106
+ format % usage_mb
107
+ end
108
+
109
+ def quota_mb_str(format: "%6.1f")
110
+ case quota
111
+ when -1
112
+ # It's not sure what 'disabled' means for quota.
113
+ "Disabled"
114
+ when 0
115
+ "Unlimited"
116
+ else
117
+ quota_mb = quota / KB_TO_MB.to_f
118
+ format % quota_mb
119
+ end
120
+ end
121
+
122
+ def quota_display_str(format: "%6.1f")
123
+ "%s / %s" % [quota_usage_str(format: format), quota_mb_str(format: format)]
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,18 @@
1
+ module PostfixAdmin
2
+ class Quota2 < ApplicationRecord
3
+ # version: 1841
4
+ # > describe quota2;
5
+ # +----------+--------------+------+-----+---------+-------+
6
+ # | Field | Type | Null | Key | Default | Extra |
7
+ # +----------+--------------+------+-----+---------+-------+
8
+ # | username | varchar(100) | NO | PRI | NULL | |
9
+ # | bytes | bigint(20) | NO | | 0 | |
10
+ # | messages | int(11) | NO | | 0 | |
11
+ # +----------+--------------+------+-----+---------+-------+
12
+
13
+ self.table_name = :quota2
14
+ self.primary_key = :username
15
+
16
+ belongs_to :rel_mailbox, class_name: "Mailbox", foreign_key: :username
17
+ end
18
+ end
@@ -1,10 +1,9 @@
1
1
  require 'active_record'
2
- require 'postfix_admin/application_record'
3
- require 'postfix_admin/admin'
4
- require 'postfix_admin/domain'
5
- require 'postfix_admin/mailbox'
6
- require 'postfix_admin/alias'
7
- require 'postfix_admin/domain_admin'
8
- require 'postfix_admin/log'
9
- require 'postfix_admin/mail_domain'
10
- require 'postfix_admin/quota'
2
+ require 'postfix_admin/models/application_record'
3
+ require 'postfix_admin/models/admin'
4
+ require 'postfix_admin/models/domain'
5
+ require 'postfix_admin/models/mailbox'
6
+ require 'postfix_admin/models/alias'
7
+ require 'postfix_admin/models/domain_admin'
8
+ require 'postfix_admin/models/log'
9
+ require 'postfix_admin/models/quota2'
@@ -30,21 +30,66 @@ module PostfixAdmin
30
30
  runner { @cli.show(name) }
31
31
  end
32
32
 
33
- desc "setup example.com password", "Set up a domain"
33
+ desc "admins", "List all admin users"
34
+ def admins
35
+ runner { @cli.show_admins }
36
+ end
37
+
38
+ desc "domains", "List all domains"
39
+ def domains
40
+ runner { @cli.show_domains }
41
+ end
42
+
43
+ desc "accounts", "List all accounts"
44
+ def accounts
45
+ runner { @cli.show_accounts }
46
+ end
47
+
48
+ desc "aliases", "List all aliases"
49
+ def aliases
50
+ runner { @cli.show_aliases }
51
+ end
52
+
53
+ desc "forwards", "List all forwards"
54
+ def forwards
55
+ runner { @cli.show_forwards }
56
+ end
57
+
58
+ desc "setup example.com password", "Set up a domain (add a domain and an admin user for it)"
59
+ method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
60
+ method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
34
61
  def setup(domain_name, password)
35
- runner { @cli.setup_domain(domain_name, password) }
62
+ runner do
63
+ @cli.setup_domain(domain_name, password,
64
+ scheme: options[:scheme], rounds: options[:rounds])
65
+ end
66
+ end
67
+
68
+ desc "teardown example.com", "Tear down a domain (delete a domain and an admin user for it)"
69
+ def teardown(domain_name)
70
+ runner { @cli.teardown_domain(domain_name) }
36
71
  end
37
72
 
38
73
  desc "admin_passwd admin@example.com new_password",
39
74
  "Change the password of an admin user"
75
+ method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
76
+ method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
40
77
  def admin_passwd(user_name, password)
41
- runner { @cli.change_admin_password(user_name, password) }
78
+ runner do
79
+ @cli.change_admin_password(user_name, password,
80
+ scheme: options[:scheme], rounds: options[:rounds])
81
+ end
42
82
  end
43
83
 
44
84
  desc "account_passwd user@example.com new_password",
45
85
  "Change the password of an account"
86
+ method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
87
+ method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
46
88
  def account_passwd(user_name, password)
47
- runner { @cli.change_account_password(user_name, password) }
89
+ runner do
90
+ @cli.change_account_password(user_name, password,
91
+ scheme: options[:scheme], rounds: options[:rounds])
92
+ end
48
93
  end
49
94
 
50
95
  desc "add_domain example.com", "Add a new domain"
@@ -86,8 +131,9 @@ module PostfixAdmin
86
131
  end
87
132
 
88
133
  desc "add_account user@example.com password", "Add a new account"
89
- method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
90
134
  method_option :name, type: :string, aliases: "-n", desc: "full name"
135
+ method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
136
+ method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
91
137
  def add_account(address, password)
92
138
  runner do
93
139
  if options[:scheme] == 'scheme'
@@ -98,7 +144,8 @@ module PostfixAdmin
98
144
  warn "Specify name"
99
145
  help('add_account')
100
146
  else
101
- @cli.add_account(address, password, options[:scheme], options[:name])
147
+ @cli.add_account(address, password, name: options[:name],
148
+ scheme: options[:scheme], rounds: options[:rounds])
102
149
  end
103
150
  end
104
151
  end
@@ -146,13 +193,16 @@ module PostfixAdmin
146
193
  desc "add_admin admin@example.com password", "Add a new admin user"
147
194
  method_option :super, type: :boolean, aliases: "-S", desc: "register as a super admin"
148
195
  method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
196
+ method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
149
197
  def add_admin(user_name, password)
150
198
  runner do
151
199
  if options[:scheme] == 'scheme'
152
200
  warn "Specify password scheme"
153
201
  help('add_admin')
154
202
  else
155
- @cli.add_admin(user_name, password, options[:super], options[:scheme])
203
+ @cli.add_admin(user_name, password,
204
+ super_admin: options[:super], scheme: options[:scheme],
205
+ rounds: options[:rounds])
156
206
  end
157
207
  end
158
208
  end
@@ -1,3 +1,3 @@
1
1
  module PostfixAdmin
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
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.0
4
+ version: 0.3.1
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-06-15 00:00:00.000000000 Z
11
+ date: 2024-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -154,6 +154,8 @@ files:
154
154
  - Rakefile
155
155
  - Thorfile
156
156
  - bin/console
157
+ - db/reset.rb
158
+ - db/seeds.rb
157
159
  - docker-admin/Dockerfile
158
160
  - docker-admin/config.local.php
159
161
  - docker-app/Dockerfile
@@ -164,23 +166,22 @@ files:
164
166
  - docker-db/postfix.v740.sql
165
167
  - exe/postfix_admin
166
168
  - lib/postfix_admin.rb
167
- - lib/postfix_admin/admin.rb
168
- - lib/postfix_admin/alias.rb
169
- - lib/postfix_admin/application_record.rb
170
169
  - lib/postfix_admin/base.rb
171
170
  - lib/postfix_admin/cli.rb
172
- - lib/postfix_admin/concerns/.keep
173
- - lib/postfix_admin/concerns/dovecot_cram_md5_password.rb
174
- - lib/postfix_admin/concerns/existing_timestamp.rb
175
- - lib/postfix_admin/domain.rb
176
- - lib/postfix_admin/domain_admin.rb
177
171
  - lib/postfix_admin/doveadm.rb
178
172
  - lib/postfix_admin/error.rb
179
- - lib/postfix_admin/log.rb
180
- - lib/postfix_admin/mail_domain.rb
181
- - lib/postfix_admin/mailbox.rb
182
173
  - lib/postfix_admin/models.rb
183
- - lib/postfix_admin/quota.rb
174
+ - lib/postfix_admin/models/admin.rb
175
+ - lib/postfix_admin/models/alias.rb
176
+ - lib/postfix_admin/models/application_record.rb
177
+ - lib/postfix_admin/models/concerns/.keep
178
+ - lib/postfix_admin/models/concerns/existing_timestamp.rb
179
+ - lib/postfix_admin/models/concerns/has_password.rb
180
+ - lib/postfix_admin/models/domain.rb
181
+ - lib/postfix_admin/models/domain_admin.rb
182
+ - lib/postfix_admin/models/log.rb
183
+ - lib/postfix_admin/models/mailbox.rb
184
+ - lib/postfix_admin/models/quota2.rb
184
185
  - lib/postfix_admin/runner.rb
185
186
  - lib/postfix_admin/version.rb
186
187
  - postfix_admin.gemspec
@@ -1,29 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module DovecotCramMD5Password
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- validates :password_unencrypted, length: { minimum: 5 }, allow_blank: true
8
- validates_confirmation_of :password_unencrypted, allow_blank: true
9
-
10
- validate do |record|
11
- record.errors.add(:password_unencrypted, :blank) unless record.password.present?
12
- end
13
-
14
- attr_reader :password_unencrypted
15
- end
16
-
17
- def password_unencrypted=(unencrypted_password)
18
- if unencrypted_password.nil?
19
- self.password = nil
20
- elsif !unencrypted_password.empty?
21
- @password_unencrypted = unencrypted_password
22
- self.password = DovecotCrammd5.calc(unencrypted_password)
23
- end
24
- end
25
-
26
- def authenticate(unencrypted_password)
27
- password == DovecotCrammd5.calc(unencrypted_password) && self
28
- end
29
- end
@@ -1,8 +0,0 @@
1
- module PostfixAdmin
2
- class DomainAdmin < ApplicationRecord
3
- self.table_name = :domain_admins
4
-
5
- belongs_to :admin, primary_key: :username, foreign_key: :username
6
- belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
7
- end
8
- end
@@ -1,5 +0,0 @@
1
- module PostfixAdmin
2
- class Log < ApplicationRecord
3
- self.table_name = :log
4
- end
5
- end
@@ -1,9 +0,0 @@
1
- module PostfixAdmin
2
- class MailDomain < ApplicationRecord
3
- self.table_name = :domain
4
- self.primary_key = :domain
5
-
6
- has_many :addresses, class_name: "Mailbox", foreign_key: :domain,
7
- dependent: :destroy
8
- end
9
- end
@@ -1,97 +0,0 @@
1
- module PostfixAdmin
2
- class Mailbox < ApplicationRecord
3
- self.table_name = :mailbox
4
- self.primary_key = :username
5
-
6
- include DovecotCramMD5Password
7
-
8
- attribute :quota_mb, :integer
9
-
10
- validates :username, presence: true, uniqueness: { case_sensitive: false },
11
- format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
12
- message: "must be a valid email address" }
13
- validates :maildir, presence: true, uniqueness: { case_sensitive: false }
14
- validates :local_part, presence: true
15
-
16
- # quota (KB)
17
- validates :quota, presence: true,
18
- numericality: { only_integer: true,
19
- greater_than_or_equal_to: 0 }
20
-
21
- # quota (MB), which actually doesn't exist in DB
22
- validates :quota_mb, presence: true,
23
- numericality: { only_integer: true,
24
- greater_than_or_equal_to: 0 }
25
-
26
- belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
27
- has_one :alias, foreign_key: :address, dependent: :destroy
28
- has_one :quota_usage, class_name: "Quota", foreign_key: :username,
29
- dependent: :destroy
30
-
31
- validate on: :create do |mailbox|
32
- domain = mailbox.rel_domain
33
- if !domain.mailboxes.zero? && domain.rel_mailboxes.count >= domain.mailboxes
34
- message = "already has the maximum number of mailboxes " \
35
- "(maximum is #{domain.mailboxes} mailboxes)"
36
- mailbox.errors.add(:domain, message)
37
- end
38
- end
39
-
40
- # just in case
41
- validate on: :update do |mailbox|
42
- mailbox.errors.add(:username, 'cannot be changed') if mailbox.username_changed?
43
- mailbox.errors.add(:local_part, 'cannot be changed') if mailbox.local_part_changed?
44
- end
45
-
46
- validate do |mailbox|
47
- domain = mailbox.rel_domain
48
-
49
- unless domain.maxquota.zero?
50
- if mailbox.quota_mb.zero?
51
- mailbox.errors.add(:quota_mb, "cannot be 0")
52
- elsif mailbox.quota_mb > domain.maxquota
53
- message = "must be less than or equal to #{domain.maxquota} (MB)"
54
- mailbox.errors.add(:quota_mb, message)
55
- end
56
- end
57
- end
58
-
59
- before_validation do |mailbox|
60
- mailbox.name = "" if mailbox.name.nil?
61
- if mailbox.quota_mb
62
- mailbox.quota = mailbox.quota_mb * KB_TO_MB
63
- elsif mailbox.quota
64
- mailbox.quota_mb = mailbox.quota / KB_TO_MB
65
- else
66
- mailbox.quota_mb = 0
67
- mailbox.quota = 0
68
- end
69
- mailbox.username = "#{mailbox.local_part}@#{mailbox.domain}"
70
- mailbox.maildir ||= "#{mailbox.domain}/#{mailbox.username}/"
71
- mailbox.build_alias(local_part: mailbox.local_part, goto: mailbox.username,
72
- domain: mailbox.domain)
73
- end
74
-
75
- def quota_usage_str
76
- if quota_usage
77
- usage_mb = quota_usage.bytes / KB_TO_MB
78
- usage_mb.to_s
79
- else
80
- "0"
81
- end
82
- end
83
-
84
- def quota_mb_str
85
- case quota
86
- when -1
87
- # It's not sure what 'disabled' means for quota.
88
- "Disabled"
89
- when 0
90
- "Unlimited"
91
- else
92
- mb_size = quota / KB_TO_MB
93
- mb_size.to_s
94
- end
95
- end
96
- end
97
- end
@@ -1,6 +0,0 @@
1
- module PostfixAdmin
2
- class Quota < ApplicationRecord
3
- self.table_name = :quota2
4
- self.primary_key = :username
5
- end
6
- end