postfix_admin 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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