postfix_admin 0.3.0 → 0.3.2
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 +4 -4
- data/.github/workflows/ci.yml +2 -4
- data/CHANGELOG.md +24 -14
- data/README.md +14 -0
- data/Rakefile +29 -0
- data/db/reset.rb +7 -0
- data/db/seeds.rb +26 -0
- data/docker-admin/config.local.php +3 -1
- data/docker-compose.yml +3 -8
- data/lib/postfix_admin/base.rb +11 -22
- data/lib/postfix_admin/cli.rb +140 -56
- data/lib/postfix_admin/doveadm.rb +31 -15
- data/lib/postfix_admin/{admin.rb → models/admin.rb} +21 -2
- data/lib/postfix_admin/models/alias.rb +63 -0
- data/lib/postfix_admin/{application_record.rb → models/application_record.rb} +2 -2
- data/lib/postfix_admin/{concerns → models/concerns}/existing_timestamp.rb +1 -2
- data/lib/postfix_admin/models/concerns/has_password.rb +16 -0
- data/lib/postfix_admin/{domain.rb → models/domain.rb} +66 -2
- data/lib/postfix_admin/models/domain_admin.rb +21 -0
- data/lib/postfix_admin/models/log.rb +22 -0
- data/lib/postfix_admin/models/mailbox.rb +143 -0
- data/lib/postfix_admin/models/quota2.rb +20 -0
- data/lib/postfix_admin/models.rb +8 -9
- data/lib/postfix_admin/runner.rb +68 -14
- data/lib/postfix_admin/version.rb +1 -1
- metadata +15 -14
- data/lib/postfix_admin/alias.rb +0 -46
- data/lib/postfix_admin/concerns/dovecot_cram_md5_password.rb +0 -29
- data/lib/postfix_admin/domain_admin.rb +0 -8
- data/lib/postfix_admin/log.rb +0 -5
- data/lib/postfix_admin/mail_domain.rb +0 -9
- data/lib/postfix_admin/mailbox.rb +0 -97
- data/lib/postfix_admin/quota.rb +0 -6
- /data/lib/postfix_admin/{concerns → models/concerns}/.keep +0 -0
@@ -1,5 +1,28 @@
|
|
1
|
+
require "postfix_admin/models/application_record"
|
2
|
+
|
1
3
|
module PostfixAdmin
|
2
4
|
class Domain < ApplicationRecord
|
5
|
+
# version: 1841
|
6
|
+
# > describe domain;
|
7
|
+
# +-------------+--------------+------+-----+---------------------+-------+
|
8
|
+
# | Field | Type | Null | Key | Default | Extra |
|
9
|
+
# +-------------+--------------+------+-----+---------------------+-------+
|
10
|
+
# | domain | varchar(255) | NO | PRI | NULL | |
|
11
|
+
# | description | varchar(255) | NO | | NULL | |
|
12
|
+
# | aliases | int(10) | NO | | 0 | |
|
13
|
+
# | mailboxes | int(10) | NO | | 0 | |
|
14
|
+
# | maxquota | bigint(20) | NO | | 0 | |
|
15
|
+
# | quota | bigint(20) | NO | | 0 | |
|
16
|
+
# | transport | varchar(255) | NO | | NULL | |
|
17
|
+
# | backupmx | tinyint(1) | NO | | 0 | |
|
18
|
+
# | created | datetime | NO | | 2000-01-01 00:00:00 | |
|
19
|
+
# | modified | datetime | NO | | 2000-01-01 00:00:00 | |
|
20
|
+
# | active | tinyint(1) | NO | | 1 | |
|
21
|
+
# +-------------+--------------+------+-----+---------------------+-------+
|
22
|
+
|
23
|
+
UNLIMITED = 0
|
24
|
+
DISABLED = -1
|
25
|
+
|
3
26
|
self.table_name = :domain
|
4
27
|
self.primary_key = :domain
|
5
28
|
|
@@ -31,6 +54,10 @@ module PostfixAdmin
|
|
31
54
|
has_many :rel_aliases, class_name: "Alias", foreign_key: :domain,
|
32
55
|
dependent: :destroy
|
33
56
|
|
57
|
+
# logs that belong to this domain
|
58
|
+
has_many :logs, class_name: "Log", foreign_key: :domain,
|
59
|
+
dependent: :destroy
|
60
|
+
|
34
61
|
# It causes errors to set `dependent: :destroy` as other columns
|
35
62
|
# because the domain_admins table doesn't have a single primary key.
|
36
63
|
#
|
@@ -45,6 +72,7 @@ module PostfixAdmin
|
|
45
72
|
# It works well with `dependent: :delete_all` instead.
|
46
73
|
#
|
47
74
|
# PostfixAdmin::DomainAdmin Destroy (0.4ms) DELETE FROM `domain_admins` WHERE `domain_admins`.`domain` = 'example.com'
|
75
|
+
# Domain <-> DomainAdmin <-> Admin
|
48
76
|
has_many :domain_admins, foreign_key: :domain, dependent: :delete_all
|
49
77
|
|
50
78
|
has_many :admins, through: :domain_admins
|
@@ -61,6 +89,22 @@ module PostfixAdmin
|
|
61
89
|
rel_aliases.pure
|
62
90
|
end
|
63
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
|
+
|
64
108
|
def aliases_str
|
65
109
|
max_num_str(aliases)
|
66
110
|
end
|
@@ -73,13 +117,33 @@ module PostfixAdmin
|
|
73
117
|
max_num_str(maxquota)
|
74
118
|
end
|
75
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
|
+
|
76
140
|
private
|
77
141
|
|
78
142
|
def max_num_str(num)
|
79
143
|
case num
|
80
|
-
when
|
144
|
+
when DISABLED
|
81
145
|
"Disabled"
|
82
|
-
when
|
146
|
+
when UNLIMITED
|
83
147
|
"Unlimited"
|
84
148
|
else
|
85
149
|
num.to_s
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "postfix_admin/models/application_record"
|
2
|
+
|
3
|
+
module PostfixAdmin
|
4
|
+
class DomainAdmin < ApplicationRecord
|
5
|
+
# version: 1841
|
6
|
+
# > describe domain_admins;
|
7
|
+
# +----------+--------------+------+-----+---------------------+-------+
|
8
|
+
# | Field | Type | Null | Key | Default | Extra |
|
9
|
+
# +----------+--------------+------+-----+---------------------+-------+
|
10
|
+
# | username | varchar(255) | NO | MUL | NULL | |
|
11
|
+
# | domain | varchar(255) | NO | | NULL | |
|
12
|
+
# | created | datetime | NO | | 2000-01-01 00:00:00 | |
|
13
|
+
# | active | tinyint(1) | NO | | 1 | |
|
14
|
+
# +----------+--------------+------+-----+---------------------+-------+
|
15
|
+
|
16
|
+
self.table_name = :domain_admins
|
17
|
+
|
18
|
+
belongs_to :admin, primary_key: :username, foreign_key: :username
|
19
|
+
belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "postfix_admin/models/application_record"
|
2
|
+
|
3
|
+
module PostfixAdmin
|
4
|
+
class Log < ApplicationRecord
|
5
|
+
# version: 1841
|
6
|
+
# > describe log;
|
7
|
+
# +-----------+--------------+------+-----+---------------------+----------------+
|
8
|
+
# | Field | Type | Null | Key | Default | Extra |
|
9
|
+
# +-----------+--------------+------+-----+---------------------+----------------+
|
10
|
+
# | timestamp | datetime | NO | MUL | 2000-01-01 00:00:00 | |
|
11
|
+
# | username | varchar(255) | NO | | NULL | |
|
12
|
+
# | domain | varchar(255) | NO | MUL | NULL | |
|
13
|
+
# | action | varchar(255) | NO | | NULL | |
|
14
|
+
# | data | text | NO | | NULL | |
|
15
|
+
# | id | int(11) | NO | PRI | NULL | auto_increment |
|
16
|
+
# +-----------+--------------+------+-----+---------------------+----------------+
|
17
|
+
|
18
|
+
self.table_name = :log
|
19
|
+
|
20
|
+
belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "postfix_admin/models/application_record"
|
2
|
+
require "postfix_admin/models/concerns/has_password"
|
3
|
+
|
4
|
+
module PostfixAdmin
|
5
|
+
class Mailbox < ApplicationRecord
|
6
|
+
# version: 1841
|
7
|
+
# > describe mailbox;
|
8
|
+
# +----------------+--------------+------+-----+---------------------+-------+
|
9
|
+
# | Field | Type | Null | Key | Default | Extra |
|
10
|
+
# +----------------+--------------+------+-----+---------------------+-------+
|
11
|
+
# | username | varchar(255) | NO | PRI | NULL | |
|
12
|
+
# | password | varchar(255) | NO | | NULL | |
|
13
|
+
# | name | varchar(255) | NO | | NULL | |
|
14
|
+
# | maildir | varchar(255) | NO | | NULL | |
|
15
|
+
# | quota | bigint(20) | NO | | 0 | |
|
16
|
+
# | local_part | varchar(255) | NO | | NULL | |
|
17
|
+
# | domain | varchar(255) | NO | MUL | NULL | |
|
18
|
+
# | created | datetime | NO | | 2000-01-01 00:00:00 | |
|
19
|
+
# | modified | datetime | NO | | 2000-01-01 00:00:00 | |
|
20
|
+
# | active | tinyint(1) | NO | | 1 | |
|
21
|
+
# | phone | varchar(30) | NO | | | |
|
22
|
+
# | email_other | varchar(255) | NO | | | |
|
23
|
+
# | token | varchar(255) | NO | | | |
|
24
|
+
# | token_validity | datetime | NO | | 2000-01-01 00:00:00 | |
|
25
|
+
# +----------------+--------------+------+-----+---------------------+-------+
|
26
|
+
|
27
|
+
UNLIMITED_QUOTA = 0
|
28
|
+
DISABLED_QUOTA = -1
|
29
|
+
|
30
|
+
self.table_name = :mailbox
|
31
|
+
self.primary_key = :username
|
32
|
+
|
33
|
+
include HasPassword
|
34
|
+
|
35
|
+
validates :username, presence: true, uniqueness: { case_sensitive: false },
|
36
|
+
format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
|
37
|
+
message: "must be a valid email address" }
|
38
|
+
validates :maildir, presence: true, uniqueness: { case_sensitive: false }
|
39
|
+
validates :local_part, presence: true
|
40
|
+
|
41
|
+
# quota (KB)
|
42
|
+
validates :quota, presence: true,
|
43
|
+
numericality: { only_integer: true,
|
44
|
+
greater_than_or_equal_to: 0 }
|
45
|
+
|
46
|
+
belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
|
47
|
+
has_one :alias, foreign_key: :address, dependent: :destroy
|
48
|
+
has_one :quota_usage, class_name: "Quota2", foreign_key: :username,
|
49
|
+
dependent: :destroy
|
50
|
+
|
51
|
+
validate on: :create do |mailbox|
|
52
|
+
domain = mailbox.rel_domain
|
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})"
|
63
|
+
mailbox.errors.add(:domain, message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# just in case
|
68
|
+
validate on: :update do |mailbox|
|
69
|
+
mailbox.errors.add(:username, 'cannot be changed') if mailbox.username_changed?
|
70
|
+
mailbox.errors.add(:local_part, 'cannot be changed') if mailbox.local_part_changed?
|
71
|
+
end
|
72
|
+
|
73
|
+
validate do |mailbox|
|
74
|
+
next if mailbox.quota == DISABLED_QUOTA
|
75
|
+
|
76
|
+
domain = mailbox.rel_domain
|
77
|
+
|
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)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
before_validation do |mailbox|
|
93
|
+
mailbox.name = "" if mailbox.name.nil?
|
94
|
+
mailbox.username = "#{mailbox.local_part}@#{mailbox.domain}"
|
95
|
+
mailbox.maildir ||= "#{mailbox.domain}/#{mailbox.username}/"
|
96
|
+
mailbox.build_alias(address: mailbox.username, goto: mailbox.username,
|
97
|
+
domain: mailbox.domain)
|
98
|
+
end
|
99
|
+
|
100
|
+
def quota_unlimited?
|
101
|
+
quota.zero?
|
102
|
+
end
|
103
|
+
|
104
|
+
def quota_mb
|
105
|
+
raise Error, "quota is out of range: #{quota}" if quota < 0
|
106
|
+
|
107
|
+
quota / KB_TO_MB
|
108
|
+
end
|
109
|
+
|
110
|
+
def quota_mb=(value)
|
111
|
+
raise Error, "quota is out of range: #{value}" if value < 0
|
112
|
+
|
113
|
+
self.quota = value * KB_TO_MB
|
114
|
+
end
|
115
|
+
|
116
|
+
def quota_usage_str(format: "%6.1f")
|
117
|
+
usage_mb = if quota_usage
|
118
|
+
usage_mb = quota_usage.bytes / KB_TO_MB.to_f
|
119
|
+
else
|
120
|
+
0.0
|
121
|
+
end
|
122
|
+
|
123
|
+
format % usage_mb
|
124
|
+
end
|
125
|
+
|
126
|
+
def quota_mb_str(format: "%6.1f")
|
127
|
+
case quota
|
128
|
+
when DISABLED_QUOTA
|
129
|
+
# It's not sure what 'disabled' means for quota.
|
130
|
+
"Disabled"
|
131
|
+
when UNLIMITED_QUOTA
|
132
|
+
"Unlimited"
|
133
|
+
else
|
134
|
+
quota_mb = quota / KB_TO_MB.to_f
|
135
|
+
format % quota_mb
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def quota_display_str(format: "%6.1f")
|
140
|
+
"%s / %s" % [quota_usage_str(format: format), quota_mb_str(format: format)]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "postfix_admin/models/application_record"
|
2
|
+
|
3
|
+
module PostfixAdmin
|
4
|
+
class Quota2 < ApplicationRecord
|
5
|
+
# version: 1841
|
6
|
+
# > describe quota2;
|
7
|
+
# +----------+--------------+------+-----+---------+-------+
|
8
|
+
# | Field | Type | Null | Key | Default | Extra |
|
9
|
+
# +----------+--------------+------+-----+---------+-------+
|
10
|
+
# | username | varchar(100) | NO | PRI | NULL | |
|
11
|
+
# | bytes | bigint(20) | NO | | 0 | |
|
12
|
+
# | messages | int(11) | NO | | 0 | |
|
13
|
+
# +----------+--------------+------+-----+---------+-------+
|
14
|
+
|
15
|
+
self.table_name = :quota2
|
16
|
+
self.primary_key = :username
|
17
|
+
|
18
|
+
belongs_to :rel_mailbox, class_name: "Mailbox", foreign_key: :username
|
19
|
+
end
|
20
|
+
end
|
data/lib/postfix_admin/models.rb
CHANGED
@@ -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/
|
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'
|
data/lib/postfix_admin/runner.rb
CHANGED
@@ -30,21 +30,70 @@ module PostfixAdmin
|
|
30
30
|
runner { @cli.show(name) }
|
31
31
|
end
|
32
32
|
|
33
|
-
desc "
|
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",
|
59
|
+
"Set up a domain (add a domain and an admin user for it)"
|
60
|
+
method_option :description, type: :string, aliases: "-d", desc: "description"
|
61
|
+
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
62
|
+
method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
|
34
63
|
def setup(domain_name, password)
|
35
|
-
runner
|
64
|
+
runner do
|
65
|
+
@cli.setup_domain(domain_name, password,
|
66
|
+
description: options[:description],
|
67
|
+
scheme: options[:scheme], rounds: options[:rounds])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "teardown example.com",
|
72
|
+
"Tear down a domain (delete a domain and an admin user for it)"
|
73
|
+
def teardown(domain_name)
|
74
|
+
runner { @cli.teardown_domain(domain_name) }
|
36
75
|
end
|
37
76
|
|
38
77
|
desc "admin_passwd admin@example.com new_password",
|
39
78
|
"Change the password of an admin user"
|
79
|
+
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
80
|
+
method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
|
40
81
|
def admin_passwd(user_name, password)
|
41
|
-
runner
|
82
|
+
runner do
|
83
|
+
@cli.change_admin_password(user_name, password,
|
84
|
+
scheme: options[:scheme], rounds: options[:rounds])
|
85
|
+
end
|
42
86
|
end
|
43
87
|
|
44
88
|
desc "account_passwd user@example.com new_password",
|
45
89
|
"Change the password of an account"
|
90
|
+
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
91
|
+
method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
|
46
92
|
def account_passwd(user_name, password)
|
47
|
-
runner
|
93
|
+
runner do
|
94
|
+
@cli.change_account_password(user_name, password,
|
95
|
+
scheme: options[:scheme], rounds: options[:rounds])
|
96
|
+
end
|
48
97
|
end
|
49
98
|
|
50
99
|
desc "add_domain example.com", "Add a new domain"
|
@@ -54,11 +103,11 @@ module PostfixAdmin
|
|
54
103
|
end
|
55
104
|
|
56
105
|
desc "edit_domain example.com", "Edit a domain"
|
57
|
-
method_option :aliases, type: :numeric, aliases: "-a", desc: "
|
58
|
-
method_option :mailboxes, type: :numeric, aliases: "-m", desc: "
|
59
|
-
method_option :maxquota, type: :numeric, aliases: "-q", desc: "
|
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)"
|
60
109
|
method_option :active, type: :boolean, desc: "Update active status"
|
61
|
-
method_option :description, type: :string, aliases: "-d", desc: "
|
110
|
+
method_option :description, type: :string, aliases: "-d", desc: "Update description"
|
62
111
|
def edit_domain(domain_name)
|
63
112
|
runner do
|
64
113
|
if options.size == 0
|
@@ -86,8 +135,9 @@ module PostfixAdmin
|
|
86
135
|
end
|
87
136
|
|
88
137
|
desc "add_account user@example.com password", "Add a new account"
|
89
|
-
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
90
138
|
method_option :name, type: :string, aliases: "-n", desc: "full name"
|
139
|
+
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
140
|
+
method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
|
91
141
|
def add_account(address, password)
|
92
142
|
runner do
|
93
143
|
if options[:scheme] == 'scheme'
|
@@ -98,7 +148,8 @@ module PostfixAdmin
|
|
98
148
|
warn "Specify name"
|
99
149
|
help('add_account')
|
100
150
|
else
|
101
|
-
@cli.add_account(address, password,
|
151
|
+
@cli.add_account(address, password, name: options[:name],
|
152
|
+
scheme: options[:scheme], rounds: options[:rounds])
|
102
153
|
end
|
103
154
|
end
|
104
155
|
end
|
@@ -106,11 +157,11 @@ module PostfixAdmin
|
|
106
157
|
|
107
158
|
desc "edit_account user@example.com", "Edit an account"
|
108
159
|
method_option :goto, type: :string, aliases: "-g",
|
109
|
-
desc: "mailboxes, addresses
|
160
|
+
desc: "Update mailboxes, addresses emails are delivered to"
|
110
161
|
method_option :quota, type: :numeric, aliases: "-q",
|
111
|
-
desc: "quota
|
162
|
+
desc: "Update quota limit (MB)"
|
112
163
|
method_option :name, type: :string, aliases: "-n",
|
113
|
-
desc: "full name"
|
164
|
+
desc: "Update full name"
|
114
165
|
method_option :active, type: :boolean,
|
115
166
|
desc: "Update active status"
|
116
167
|
def edit_account(address)
|
@@ -146,13 +197,16 @@ module PostfixAdmin
|
|
146
197
|
desc "add_admin admin@example.com password", "Add a new admin user"
|
147
198
|
method_option :super, type: :boolean, aliases: "-S", desc: "register as a super admin"
|
148
199
|
method_option :scheme, type: :string, aliases: "-s", desc: "password scheme"
|
200
|
+
method_option :rounds, type: :string, aliases: "-r", desc: "encryption rounds for BLF-CRYPT, SHA256-CRYPT and SHA512-CRYPT schemes"
|
149
201
|
def add_admin(user_name, password)
|
150
202
|
runner do
|
151
203
|
if options[:scheme] == 'scheme'
|
152
204
|
warn "Specify password scheme"
|
153
205
|
help('add_admin')
|
154
206
|
else
|
155
|
-
@cli.add_admin(user_name, password,
|
207
|
+
@cli.add_admin(user_name, password,
|
208
|
+
super_admin: options[:super], scheme: options[:scheme],
|
209
|
+
rounds: options[:rounds])
|
156
210
|
end
|
157
211
|
end
|
158
212
|
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.
|
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-
|
11
|
+
date: 2024-07-30 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/
|
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
|
data/lib/postfix_admin/alias.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module PostfixAdmin
|
2
|
-
class Alias < ApplicationRecord
|
3
|
-
self.table_name = :alias
|
4
|
-
self.primary_key = :address
|
5
|
-
|
6
|
-
validate on: :create do |a|
|
7
|
-
domain = a.rel_domain
|
8
|
-
if domain.aliases.zero? || a.mailbox
|
9
|
-
elsif domain.rel_aliases.pure.count >= domain.aliases
|
10
|
-
message = "already has the maximum number of aliases " \
|
11
|
-
"(maximum is #{domain.aliases} aliases)"
|
12
|
-
a.errors.add(:domain, message)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
validates :address, presence: true, uniqueness: { case_sensitive: false },
|
17
|
-
format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
|
18
|
-
message: "must be a valid email address" }
|
19
|
-
validates :goto, presence: true
|
20
|
-
|
21
|
-
belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
|
22
|
-
belongs_to :mailbox, foreign_key: :address, optional: true
|
23
|
-
|
24
|
-
scope :pure, -> { joins("LEFT OUTER JOIN mailbox ON alias.address = mailbox.username").where("mailbox.username" => nil) }
|
25
|
-
|
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
|
33
|
-
|
34
|
-
def mailbox?
|
35
|
-
!!mailbox
|
36
|
-
end
|
37
|
-
|
38
|
-
def pure_alias?
|
39
|
-
!mailbox
|
40
|
-
end
|
41
|
-
|
42
|
-
def gotos
|
43
|
-
goto.split(",")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -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
|
data/lib/postfix_admin/log.rb
DELETED