postfix_admin 0.1.1 → 0.2.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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +37 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +22 -0
- data/README.md +47 -32
- data/Rakefile +6 -0
- data/bin/console +18 -0
- data/docker-admin/Dockerfile +6 -0
- data/docker-admin/config.local.php +21 -0
- data/docker-app-2.5/Dockerfile +15 -0
- data/docker-app/Dockerfile +25 -0
- data/docker-app/docker-entrypoint.sh +5 -0
- data/docker-app/my.cnf +5 -0
- data/docker-compose.yml +46 -0
- data/docker-db/postfix.v1841.sql +383 -0
- data/{spec/postfix_test.sql → docker-db/postfix.v352.sql} +1 -28
- data/docker-db/postfix.v740.sql +269 -0
- data/{bin → exe}/postfix_admin +1 -0
- data/lib/postfix_admin.rb +1 -1
- data/lib/postfix_admin/admin.rb +62 -0
- data/lib/postfix_admin/alias.rb +65 -0
- data/lib/postfix_admin/application_record.rb +44 -0
- data/lib/postfix_admin/base.rb +120 -75
- data/lib/postfix_admin/cli.rb +173 -58
- data/lib/postfix_admin/concerns/.keep +0 -0
- data/lib/postfix_admin/concerns/dovecot_cram_md5_password.rb +30 -0
- data/lib/postfix_admin/concerns/existing_timestamp.rb +18 -0
- data/lib/postfix_admin/domain.rb +98 -0
- data/lib/postfix_admin/domain_admin.rb +8 -0
- data/lib/postfix_admin/doveadm.rb +37 -0
- data/lib/postfix_admin/log.rb +5 -0
- data/lib/postfix_admin/mail_domain.rb +9 -0
- data/lib/postfix_admin/mailbox.rb +89 -0
- data/lib/postfix_admin/models.rb +10 -170
- data/lib/postfix_admin/quota.rb +6 -0
- data/lib/postfix_admin/runner.rb +108 -36
- data/lib/postfix_admin/version.rb +1 -1
- data/postfix_admin.gemspec +22 -12
- metadata +80 -55
- data/spec/base_spec.rb +0 -235
- data/spec/cli_spec.rb +0 -286
- data/spec/models_spec.rb +0 -146
- data/spec/postfix_admin.conf +0 -5
- data/spec/runner_spec.rb +0 -194
- data/spec/spec_helper.rb +0 -159
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'postfix_admin/concerns/existing_timestamp'
|
3
|
+
|
4
|
+
module PostfixAdmin
|
5
|
+
class ApplicationRecord < ActiveRecord::Base
|
6
|
+
self.abstract_class = true
|
7
|
+
|
8
|
+
include ExistingTimestamp
|
9
|
+
|
10
|
+
RE_DOMAIN_NAME_LIKE_BASE = '([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}'
|
11
|
+
RE_EMAIL_LIKE_BASE = '[^@\s]+@([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}'
|
12
|
+
|
13
|
+
RE_DOMAIN_NAME_LIKE = /#{RE_DOMAIN_NAME_LIKE_BASE}/
|
14
|
+
RE_EMAIL_LIKE = /#{RE_EMAIL_LIKE_BASE}/
|
15
|
+
|
16
|
+
RE_DOMAIN_NAME_LIKE_WITH_ANCHORS = /\A#{RE_DOMAIN_NAME_LIKE_BASE}\z/
|
17
|
+
RE_EMAIL_LIKE_WITH_ANCHORS = /\A#{RE_EMAIL_LIKE_BASE}\z/
|
18
|
+
|
19
|
+
scope :active, -> { where(active: true) }
|
20
|
+
|
21
|
+
def inactive?
|
22
|
+
!active?
|
23
|
+
end
|
24
|
+
|
25
|
+
def active_str
|
26
|
+
active? ? "Active" : "Inactive"
|
27
|
+
end
|
28
|
+
|
29
|
+
# This is a workaround to set current time to timestamp columns when a record is created.
|
30
|
+
# Activerecord does not insert timestamps if default values are set for the columns.
|
31
|
+
before_create :set_current_time_to_timestamp_columns, if: :has_timestamp_columns?
|
32
|
+
|
33
|
+
def set_current_time_to_timestamp_columns
|
34
|
+
now = Time.now
|
35
|
+
self.created = now
|
36
|
+
self.modified = now
|
37
|
+
end
|
38
|
+
|
39
|
+
def has_timestamp_columns?
|
40
|
+
column_names = self.class.column_names
|
41
|
+
column_names.include?("created") && column_names.include?("modified")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/postfix_admin/base.rb
CHANGED
@@ -1,137 +1,170 @@
|
|
1
|
-
require 'postfix_admin/models'
|
2
1
|
require 'postfix_admin/error'
|
3
2
|
|
4
3
|
require 'date'
|
5
|
-
require '
|
4
|
+
require 'postfix_admin/models'
|
6
5
|
|
7
6
|
module PostfixAdmin
|
8
7
|
class Base
|
9
8
|
attr_reader :config
|
10
9
|
|
11
10
|
DEFAULT_CONFIG = {
|
12
|
-
'database' => '
|
11
|
+
'database' => 'mysql2://postfix:password@localhost/postfix',
|
13
12
|
'aliases' => 30,
|
14
13
|
'mailboxes' => 30,
|
15
|
-
'maxquota' => 100
|
14
|
+
'maxquota' => 100,
|
15
|
+
'scheme' => 'CRAM-MD5',
|
16
|
+
'passwordhash_prefix' => true
|
16
17
|
}
|
17
18
|
|
18
19
|
def initialize(config)
|
19
|
-
db_setup(config['database'])
|
20
20
|
@config = {}
|
21
|
+
@config[:database] = config['database']
|
21
22
|
@config[:aliases] = config['aliases'] || 30
|
22
23
|
@config[:mailboxes] = config['mailboxes'] || 30
|
23
24
|
@config[:maxquota] = config['maxquota'] || 100
|
24
|
-
@config[:
|
25
|
+
@config[:scheme] = config['scheme'] || 'CRAM-MD5'
|
26
|
+
@config[:passwordhash_prefix] = if config['passwordhash_prefix'].nil?
|
27
|
+
true
|
28
|
+
else
|
29
|
+
config['passwordhash_prefix']
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
|
-
def db_setup
|
28
|
-
|
29
|
-
|
33
|
+
def db_setup
|
34
|
+
raise "'database' parameter is required in '#{CLI.config_file}'" unless @config[:database]
|
35
|
+
|
36
|
+
uri = URI.parse(@config[:database])
|
37
|
+
|
38
|
+
if uri.scheme == "mysql"
|
39
|
+
uri.scheme = "mysql2"
|
40
|
+
warn("Deprecation Warning: Use 'mysql2' as a DB adopter instead of 'mysql' in '#{CLI.config_file}'")
|
41
|
+
end
|
42
|
+
|
43
|
+
if uri.scheme != "mysql2"
|
44
|
+
raise "'#{uri.scheme}' is not supported as a DB adopter. Use 'mysql2' instead in '#{CLI.config_file}'."
|
45
|
+
end
|
46
|
+
|
47
|
+
ActiveRecord::Base.establish_connection(uri.to_s)
|
48
|
+
|
49
|
+
rescue LoadError => e
|
50
|
+
raise e.message
|
30
51
|
end
|
31
52
|
|
32
53
|
def add_admin_domain(user_name, domain_name)
|
33
54
|
admin_domain_check(user_name, domain_name)
|
34
55
|
|
35
56
|
admin = Admin.find(user_name)
|
36
|
-
|
37
|
-
|
57
|
+
domain = Domain.find(domain_name)
|
58
|
+
|
59
|
+
if admin.has_domain?(domain)
|
60
|
+
raise Error, "#{user_name} is already registered as admin of #{domain_name}."
|
38
61
|
end
|
39
62
|
|
40
|
-
|
41
|
-
admin.domains << domain
|
63
|
+
admin.rel_domains << domain
|
42
64
|
admin.save or raise "Relation Error: Domain of Admin"
|
43
65
|
end
|
44
66
|
|
45
67
|
def delete_admin_domain(user_name, domain_name)
|
46
68
|
admin_domain_check(user_name, domain_name)
|
47
69
|
|
48
|
-
admin
|
49
|
-
|
50
|
-
|
70
|
+
admin = Admin.find(user_name)
|
71
|
+
domain_admin_query = admin.domain_admins.where(domain: domain_name)
|
72
|
+
|
73
|
+
unless domain_admin_query.take
|
74
|
+
raise Error, "#{user_name} is not registered as admin of #{domain_name}."
|
51
75
|
end
|
52
76
|
|
53
|
-
|
54
|
-
admin.domains.delete(domain)
|
55
|
-
admin.save or "Could not save Admin"
|
77
|
+
domain_admin_query.delete_all
|
56
78
|
end
|
57
79
|
|
58
80
|
def add_admin(username, password)
|
59
|
-
|
60
|
-
|
81
|
+
password_check(password)
|
82
|
+
|
83
|
+
if Admin.exists?(username)
|
84
|
+
raise Error, "#{username} is already registered as admin."
|
61
85
|
end
|
62
86
|
admin = Admin.new
|
63
87
|
admin.attributes = {
|
64
|
-
:
|
65
|
-
:
|
88
|
+
username: username,
|
89
|
+
password: password,
|
66
90
|
}
|
67
91
|
unless admin.save
|
68
|
-
raise "Could not save Admin #{admin.errors.map
|
92
|
+
raise "Could not save Admin #{admin.errors.map(&:to_s).join}"
|
69
93
|
end
|
70
94
|
end
|
71
95
|
|
72
|
-
def add_account(address, password)
|
96
|
+
def add_account(address, password, in_name = nil)
|
97
|
+
name = in_name || ''
|
98
|
+
password_check(password)
|
99
|
+
|
73
100
|
if address !~ /.+\@.+\..+/
|
74
101
|
raise Error, "Invalid mail address #{address}"
|
75
102
|
end
|
76
103
|
user, domain_name = address_split(address)
|
77
104
|
path = "#{domain_name}/#{address}/"
|
78
105
|
|
79
|
-
unless Domain.
|
106
|
+
unless Domain.exists?(domain_name)
|
80
107
|
raise Error, "Could not find domain #{domain_name}"
|
81
108
|
end
|
82
109
|
|
83
|
-
if Alias.
|
84
|
-
raise Error, "#{address} is already
|
110
|
+
if Alias.exists?(address)
|
111
|
+
raise Error, "#{address} is already registered."
|
85
112
|
end
|
86
113
|
|
87
114
|
domain = Domain.find(domain_name)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
:quota => @config[:mailbox_quota],
|
97
|
-
# :local_part => user,
|
115
|
+
|
116
|
+
attributes = {
|
117
|
+
username: address,
|
118
|
+
password: password,
|
119
|
+
name: name,
|
120
|
+
maildir: path,
|
121
|
+
local_part: user,
|
122
|
+
quota_mb: @config[:maxquota]
|
98
123
|
}
|
99
|
-
|
124
|
+
|
125
|
+
mailbox = Mailbox.new(attributes)
|
126
|
+
|
127
|
+
domain.rel_mailboxes << mailbox
|
128
|
+
|
100
129
|
unless domain.save
|
101
|
-
raise "Could not save Mailbox and Domain #{mailbox.errors.map
|
130
|
+
raise "Could not save Mailbox and Domain #{mailbox.errors.map(&:to_s).join} #{domain.errors.map(&:to_s).join}"
|
102
131
|
end
|
103
132
|
end
|
104
133
|
|
105
134
|
def add_alias(address, goto)
|
106
|
-
if Mailbox.
|
135
|
+
if Mailbox.exists?(address)
|
107
136
|
raise Error, "mailbox #{address} is already registered!"
|
108
137
|
end
|
109
|
-
if Alias.
|
138
|
+
if Alias.exists?(address)
|
110
139
|
raise Error, "alias #{address} is already registered!"
|
111
140
|
end
|
112
|
-
|
113
|
-
|
141
|
+
|
142
|
+
local_part, domain_name = address_split(address)
|
143
|
+
|
144
|
+
unless Domain.exists?(domain_name)
|
114
145
|
raise Error, "Invalid domain! #{domain_name}"
|
115
146
|
end
|
147
|
+
|
116
148
|
domain = Domain.find(domain_name)
|
117
149
|
|
118
|
-
|
119
|
-
|
120
|
-
:
|
121
|
-
:goto => goto,
|
150
|
+
attributes = {
|
151
|
+
local_part: local_part,
|
152
|
+
goto: goto
|
122
153
|
}
|
123
|
-
domain.
|
154
|
+
domain.rel_aliases << Alias.new(attributes)
|
124
155
|
domain.save or raise "Could not save Alias"
|
125
156
|
end
|
126
157
|
|
127
158
|
def delete_alias(address)
|
128
|
-
if Mailbox.
|
159
|
+
if Mailbox.exists?(address)
|
129
160
|
raise Error, "Can not delete mailbox by delete_alias. Use delete_account"
|
130
161
|
end
|
131
|
-
|
162
|
+
|
163
|
+
unless Alias.exists?(address)
|
132
164
|
raise Error, "#{address} is not found!"
|
133
165
|
end
|
134
|
-
|
166
|
+
|
167
|
+
Alias.where(address: address).delete_all
|
135
168
|
end
|
136
169
|
|
137
170
|
def add_domain(domain_name)
|
@@ -139,56 +172,65 @@ module PostfixAdmin
|
|
139
172
|
if domain_name !~ /.+\..+/
|
140
173
|
raise Error, "Ivalid domain! #{domain_name}"
|
141
174
|
end
|
142
|
-
if Domain.
|
175
|
+
if Domain.exists?(domain_name)
|
143
176
|
raise Error, "#{domain_name} is already registered!"
|
144
177
|
end
|
145
178
|
domain = Domain.new
|
146
179
|
domain.attributes = {
|
147
|
-
:
|
148
|
-
:
|
149
|
-
:
|
150
|
-
:
|
151
|
-
:
|
180
|
+
domain: domain_name,
|
181
|
+
description: domain_name,
|
182
|
+
aliases: @config[:aliases],
|
183
|
+
mailboxes: @config[:mailboxes],
|
184
|
+
maxquota: @config[:maxquota],
|
152
185
|
}
|
153
|
-
domain.save
|
186
|
+
domain.save!
|
154
187
|
end
|
155
188
|
|
156
189
|
def delete_domain(domain_name)
|
157
190
|
domain_name = domain_name.downcase
|
158
|
-
unless Domain.
|
191
|
+
unless Domain.exists?(domain_name)
|
159
192
|
raise Error, "Could not find domain #{domain_name}"
|
160
193
|
end
|
161
194
|
|
162
195
|
domain = Domain.find(domain_name)
|
163
|
-
domain.
|
164
|
-
domain.
|
165
|
-
|
166
|
-
domain.
|
196
|
+
domain.rel_mailboxes.delete_all
|
197
|
+
domain.rel_aliases.delete_all
|
198
|
+
|
199
|
+
admin_names = domain.admins.map(&:username)
|
200
|
+
|
201
|
+
domain.admins.delete_all
|
167
202
|
|
168
203
|
admin_names.each do |name|
|
169
|
-
next unless Admin.
|
204
|
+
next unless Admin.exists?(name)
|
205
|
+
|
170
206
|
admin = Admin.find(name)
|
171
|
-
|
207
|
+
|
208
|
+
# check if the admin is needed or not
|
209
|
+
if admin.rel_domains.empty?
|
210
|
+
admin.destroy
|
211
|
+
end
|
172
212
|
end
|
173
|
-
|
213
|
+
|
214
|
+
domain.destroy
|
174
215
|
end
|
175
216
|
|
176
217
|
def delete_admin(user_name)
|
177
|
-
unless Admin.
|
218
|
+
unless Admin.exists?(user_name)
|
178
219
|
raise Error, "Could not find admin #{user_name}"
|
179
220
|
end
|
221
|
+
|
180
222
|
admin = Admin.find(user_name)
|
181
|
-
admin.
|
182
|
-
admin.destroy
|
223
|
+
admin.rel_domains.delete_all
|
224
|
+
admin.destroy!
|
183
225
|
end
|
184
226
|
|
185
227
|
def delete_account(address)
|
186
|
-
unless Alias.
|
228
|
+
unless Alias.exists?(address) && Mailbox.exists?(address)
|
187
229
|
raise Error, "Could not find account #{address}"
|
188
230
|
end
|
189
231
|
|
190
|
-
Mailbox.
|
191
|
-
Alias.
|
232
|
+
Mailbox.where(username: address).delete_all
|
233
|
+
Alias.where(address: address).delete_all
|
192
234
|
end
|
193
235
|
|
194
236
|
def address_split(address)
|
@@ -198,9 +240,12 @@ module PostfixAdmin
|
|
198
240
|
private
|
199
241
|
|
200
242
|
def admin_domain_check(user_name, domain_name)
|
201
|
-
raise Error, "#{user_name} is not
|
202
|
-
raise Error, "Could not find domain #{domain_name}" unless Domain.
|
243
|
+
raise Error, "#{user_name} is not registered as admin." unless Admin.exists?(user_name)
|
244
|
+
raise Error, "Could not find domain #{domain_name}" unless Domain.exists?(domain_name)
|
203
245
|
end
|
204
246
|
|
247
|
+
def password_check(password)
|
248
|
+
raise Error, "Empty password" if password.nil? || password.empty?
|
249
|
+
end
|
205
250
|
end
|
206
251
|
end
|
data/lib/postfix_admin/cli.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
require 'postfix_admin'
|
3
|
+
require 'postfix_admin/doveadm'
|
3
4
|
|
4
5
|
module PostfixAdmin
|
5
6
|
class CLI
|
6
|
-
|
7
|
+
DEFAULT_CONFIG_PATH = '~/.postfix_admin.conf'
|
8
|
+
@config_file = DEFAULT_CONFIG_PATH
|
7
9
|
MIN_NUM_PASSWORD_CHARACTER = 5
|
8
10
|
|
9
11
|
def initialize
|
@@ -19,11 +21,24 @@ module PostfixAdmin
|
|
19
21
|
@config_file = value
|
20
22
|
end
|
21
23
|
|
24
|
+
def db_setup
|
25
|
+
@base.db_setup
|
26
|
+
end
|
27
|
+
|
22
28
|
def show(name)
|
23
29
|
name = name.downcase if name
|
24
30
|
|
25
31
|
if name =~ /@/
|
26
|
-
|
32
|
+
if Admin.exists?(name)
|
33
|
+
show_admin_details(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
if Mailbox.exists?(name)
|
37
|
+
show_account_details(name)
|
38
|
+
elsif Alias.exists?(name)
|
39
|
+
show_alias_details(name)
|
40
|
+
end
|
41
|
+
|
27
42
|
return
|
28
43
|
end
|
29
44
|
|
@@ -39,7 +54,7 @@ module PostfixAdmin
|
|
39
54
|
end
|
40
55
|
end
|
41
56
|
|
42
|
-
def show_summary(domain_name=nil)
|
57
|
+
def show_summary(domain_name = nil)
|
43
58
|
title = "Summary"
|
44
59
|
if domain_name
|
45
60
|
domain_name = domain_name.downcase
|
@@ -50,14 +65,15 @@ module PostfixAdmin
|
|
50
65
|
report(title) do
|
51
66
|
if domain_name
|
52
67
|
domain = Domain.find(domain_name)
|
53
|
-
puts "Mailboxes : %4d / %4s" % [domain.
|
54
|
-
puts "Aliases : %4d / %4s" % [domain.
|
68
|
+
puts "Mailboxes : %4d / %4s" % [domain.rel_mailboxes.count, max_str(domain.mailboxes)]
|
69
|
+
puts "Aliases : %4d / %4s" % [domain.pure_aliases.count, max_str(domain.aliases)]
|
55
70
|
puts "Max Quota : %4d MB" % domain.maxquota
|
71
|
+
puts "Active : %3s" % domain.active_str
|
56
72
|
else
|
57
|
-
puts "Domains : %4d" % Domain.
|
73
|
+
puts "Domains : %4d" % Domain.without_all.count
|
58
74
|
puts "Admins : %4d" % Admin.count
|
59
75
|
puts "Mailboxes : %4d" % Mailbox.count
|
60
|
-
puts "Aliases : %4d" %
|
76
|
+
puts "Aliases : %4d" % Alias.pure.count
|
61
77
|
end
|
62
78
|
end
|
63
79
|
end
|
@@ -69,34 +85,58 @@ module PostfixAdmin
|
|
69
85
|
add_admin_domain(admin, domain_name)
|
70
86
|
end
|
71
87
|
|
72
|
-
def
|
88
|
+
def show_account_details(user_name)
|
73
89
|
account_check(user_name)
|
74
90
|
mailbox = Mailbox.find(user_name)
|
75
91
|
mail_alias = Alias.find(user_name)
|
76
92
|
|
77
93
|
report("Mailbox") do
|
78
94
|
puts "Address : %s" % mailbox.username
|
95
|
+
puts "Name : %s" % mailbox.name
|
79
96
|
puts "Password : %s" % mailbox.password
|
80
97
|
puts "Quota : %d MB" % max_str(mailbox.quota / KB_TO_MB)
|
81
98
|
puts "Go to : %s" % mail_alias.goto
|
99
|
+
puts "Active : %s" % mailbox.active_str
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def show_admin_details(name)
|
104
|
+
admin_check(name)
|
105
|
+
admin = Admin.find(name)
|
106
|
+
|
107
|
+
report("Admin") do
|
108
|
+
puts "Name : %s" % admin.username
|
109
|
+
puts "Password : %s" % admin.password
|
110
|
+
puts "Domains : %s" % (admin.super_admin? ? "ALL" : admin.rel_domains.count)
|
111
|
+
puts "Role : %s" % (admin.super_admin? ? "Super admin" : "Admin")
|
112
|
+
puts "Active : %s" % admin.active_str
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def show_alias_details(name)
|
117
|
+
alias_check(name)
|
118
|
+
mail_alias = Alias.find(name)
|
119
|
+
report("Alias") do
|
120
|
+
puts "Address : %s" % mail_alias.address
|
121
|
+
puts "Go to : %s" % mail_alias.goto
|
122
|
+
puts "Active : %s" % mail_alias.active_str
|
82
123
|
end
|
83
124
|
end
|
84
125
|
|
85
126
|
def show_domain
|
86
|
-
index = " No. Domain Aliases Mailboxes Quota (MB)"
|
127
|
+
index = " No. Domain Aliases Mailboxes Quota (MB) Active"
|
87
128
|
report('Domains', index) do
|
88
|
-
if Domain.
|
129
|
+
if Domain.without_all.empty?
|
89
130
|
puts " No domains"
|
90
131
|
next
|
91
132
|
end
|
92
133
|
|
93
|
-
Domain.
|
94
|
-
puts "%4d %-30s %3d /%3s %3d /%3s %10d" %
|
95
|
-
[i+1, d.
|
96
|
-
d.
|
134
|
+
Domain.without_all.each_with_index do |d, i|
|
135
|
+
puts "%4d %-30s %3d /%3s %3d /%3s %10d %-3s" %
|
136
|
+
[i+1, d.domain, d.pure_aliases.count, max_str(d.aliases),
|
137
|
+
d.rel_mailboxes.count, max_str(d.mailboxes), d.maxquota, d.active_str]
|
97
138
|
end
|
98
139
|
end
|
99
|
-
|
100
140
|
end
|
101
141
|
|
102
142
|
def add_domain(domain_name)
|
@@ -104,18 +144,6 @@ module PostfixAdmin
|
|
104
144
|
puts_registered(domain_name, "a domain")
|
105
145
|
end
|
106
146
|
|
107
|
-
def super_admin(user_name, disable)
|
108
|
-
admin_check(user_name)
|
109
|
-
|
110
|
-
if disable
|
111
|
-
Admin.find(user_name).super_admin = false
|
112
|
-
puts "Successfully disabled super admin flag of #{user_name}"
|
113
|
-
else
|
114
|
-
Admin.find(user_name).super_admin = true
|
115
|
-
puts "Successfully enabled super admin flag of #{user_name}"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
147
|
def change_admin_password(user_name, password)
|
120
148
|
change_password(Admin, user_name, password)
|
121
149
|
end
|
@@ -124,13 +152,29 @@ module PostfixAdmin
|
|
124
152
|
change_password(Mailbox, user_name, password)
|
125
153
|
end
|
126
154
|
|
155
|
+
def edit_admin(admin_name, options)
|
156
|
+
admin_check(admin_name)
|
157
|
+
admin = Admin.find(admin_name)
|
158
|
+
|
159
|
+
unless options[:super].nil?
|
160
|
+
admin.super_admin = options[:super]
|
161
|
+
end
|
162
|
+
|
163
|
+
admin.active = options[:active] unless options[:active].nil?
|
164
|
+
admin.save!
|
165
|
+
|
166
|
+
puts "Successfully updated #{admin_name}"
|
167
|
+
show_admin_details(admin_name)
|
168
|
+
end
|
169
|
+
|
127
170
|
def edit_domain(domain_name, options)
|
128
171
|
domain_check(domain_name)
|
129
172
|
domain = Domain.find(domain_name)
|
130
|
-
domain.
|
131
|
-
domain.
|
173
|
+
domain.aliases = options[:aliases] if options[:aliases]
|
174
|
+
domain.mailboxes = options[:mailboxes] if options[:mailboxes]
|
132
175
|
domain.maxquota = options[:maxquota] if options[:maxquota]
|
133
|
-
domain.
|
176
|
+
domain.active = options[:active] unless options[:active].nil?
|
177
|
+
domain.save!
|
134
178
|
|
135
179
|
puts "Successfully updated #{domain_name}"
|
136
180
|
show_summary(domain_name)
|
@@ -141,9 +185,9 @@ module PostfixAdmin
|
|
141
185
|
puts_deleted(domain_name)
|
142
186
|
end
|
143
187
|
|
144
|
-
def show_admin(domain_name=nil)
|
145
|
-
admins = domain_name ? Admin.select{|a| a.
|
146
|
-
index = " No. Admin Domains
|
188
|
+
def show_admin(domain_name = nil)
|
189
|
+
admins = domain_name ? Admin.select { |a| a.rel_domains.exists?(domain_name) } : Admin.all
|
190
|
+
index = " No. Admin Domains Active"
|
147
191
|
report("Admins", index) do
|
148
192
|
if admins.empty?
|
149
193
|
puts " No admins"
|
@@ -151,18 +195,17 @@ module PostfixAdmin
|
|
151
195
|
end
|
152
196
|
|
153
197
|
admins.each_with_index do |a, i|
|
154
|
-
domains = a.super_admin? ? 'Super admin' : a.
|
155
|
-
puts "%4d %-40s %11s
|
198
|
+
domains = a.super_admin? ? 'Super admin' : a.rel_domains.count
|
199
|
+
puts "%4d %-40s %11s %-3s" % [i+1, a.username, domains, a.active_str]
|
156
200
|
end
|
157
201
|
end
|
158
|
-
|
159
202
|
end
|
160
203
|
|
161
204
|
def show_address(domain_name)
|
162
205
|
domain_check(domain_name)
|
163
206
|
|
164
|
-
mailboxes = Domain.find(domain_name).
|
165
|
-
index = " No. Email
|
207
|
+
mailboxes = Domain.find(domain_name).rel_mailboxes
|
208
|
+
index = " No. Email Name Quota (MB) Active Maildir"
|
166
209
|
report("Addresses", index) do
|
167
210
|
if mailboxes.empty?
|
168
211
|
puts " No addresses"
|
@@ -171,16 +214,15 @@ module PostfixAdmin
|
|
171
214
|
|
172
215
|
mailboxes.each_with_index do |m, i|
|
173
216
|
quota = m.quota.to_f/ KB_TO_MB.to_f
|
174
|
-
puts "%4d %-
|
217
|
+
puts "%4d %-30s %-20s %10s %-3s %s" % [i+1, m.username, m.name, max_str(quota.to_i), m.active_str, m.maildir]
|
175
218
|
end
|
176
219
|
end
|
177
|
-
|
178
220
|
end
|
179
221
|
|
180
222
|
def show_alias(domain_name)
|
181
223
|
domain_check(domain_name)
|
182
224
|
|
183
|
-
forwards, aliases = Domain.find(domain_name).
|
225
|
+
forwards, aliases = Domain.find(domain_name).rel_aliases.partition { |a| a.mailbox? }
|
184
226
|
|
185
227
|
forwards.delete_if do |f|
|
186
228
|
f.address == f.goto
|
@@ -192,21 +234,22 @@ module PostfixAdmin
|
|
192
234
|
|
193
235
|
def show_admin_domain(user_name)
|
194
236
|
admin = Admin.find(user_name)
|
195
|
-
if admin.
|
237
|
+
if admin.rel_domains.empty?
|
196
238
|
puts "\nNo domain in database"
|
197
239
|
return
|
198
240
|
end
|
199
241
|
|
200
242
|
report("Domains (#{user_name})", " No. Domain") do
|
201
|
-
admin.
|
202
|
-
puts "%4d %-30s" % [i+1, d.
|
243
|
+
admin.rel_domains.each_with_index do |d, i|
|
244
|
+
puts "%4d %-30s" % [i + 1, d.domain]
|
203
245
|
end
|
204
246
|
end
|
205
247
|
end
|
206
248
|
|
207
|
-
def add_admin(user_name, password, super_admin=false)
|
249
|
+
def add_admin(user_name, password, super_admin = false, scheme = nil)
|
208
250
|
validate_password(password)
|
209
|
-
|
251
|
+
|
252
|
+
@base.add_admin(user_name, hashed_password(password, scheme))
|
210
253
|
if super_admin
|
211
254
|
Admin.find(user_name).super_admin = true
|
212
255
|
puts_registered(user_name, "a super admin")
|
@@ -225,10 +268,12 @@ module PostfixAdmin
|
|
225
268
|
puts "#{domain_name} was successfully deleted from #{user_name}"
|
226
269
|
end
|
227
270
|
|
228
|
-
def add_account(address, password)
|
271
|
+
def add_account(address, password, scheme = nil, name = nil)
|
229
272
|
validate_password(password)
|
230
|
-
|
273
|
+
|
274
|
+
@base.add_account(address, hashed_password(password, scheme), name)
|
231
275
|
puts_registered(address, "an account")
|
276
|
+
show_account_details(address)
|
232
277
|
end
|
233
278
|
|
234
279
|
def add_alias(address, goto)
|
@@ -239,11 +284,30 @@ module PostfixAdmin
|
|
239
284
|
def edit_account(address, options)
|
240
285
|
mailbox_check(address)
|
241
286
|
mailbox = Mailbox.find(address)
|
287
|
+
mailbox.name = options[:name] if options[:name]
|
242
288
|
mailbox.quota = options[:quota] * KB_TO_MB if options[:quota]
|
243
|
-
mailbox.
|
289
|
+
mailbox.active = options[:active] unless options[:active].nil?
|
290
|
+
mailbox.save!
|
291
|
+
|
292
|
+
if options[:goto]
|
293
|
+
mail_alias = Alias.find(address)
|
294
|
+
mail_alias.goto = options[:goto]
|
295
|
+
mail_alias.save!
|
296
|
+
end
|
244
297
|
|
245
298
|
puts "Successfully updated #{address}"
|
246
|
-
|
299
|
+
show_account_details(address)
|
300
|
+
end
|
301
|
+
|
302
|
+
def edit_alias(address, options)
|
303
|
+
alias_check(address)
|
304
|
+
mail_alias = Alias.find(address)
|
305
|
+
mail_alias.goto = options[:goto] if options[:goto]
|
306
|
+
mail_alias.active = options[:active] unless options[:active].nil?
|
307
|
+
mail_alias.save or raise "Could not save Alias"
|
308
|
+
|
309
|
+
puts "Successfully updated #{address}"
|
310
|
+
show_alias_details(address)
|
247
311
|
end
|
248
312
|
|
249
313
|
def delete_alias(address)
|
@@ -261,17 +325,56 @@ module PostfixAdmin
|
|
261
325
|
puts_deleted(address)
|
262
326
|
end
|
263
327
|
|
328
|
+
def log
|
329
|
+
Log.all.each do |l|
|
330
|
+
time = l.timestamp.strftime("%Y-%m-%d %X %Z")
|
331
|
+
puts "#{time} #{l.username} #{l.domain} #{l.action} #{l.data}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def dump
|
336
|
+
puts "Admins"
|
337
|
+
puts "User Name,Password,Super Admin,Active"
|
338
|
+
Admin.all.each do |a|
|
339
|
+
puts [a.username, %Q!"#{a.password}"!, a.super_admin?, a.active].join(',')
|
340
|
+
end
|
341
|
+
puts
|
342
|
+
puts "Domains"
|
343
|
+
puts "Domain Name,Max Quota,Active"
|
344
|
+
Domain.without_all.each do |d|
|
345
|
+
puts [d.domain, d.maxquota, d.active].join(',')
|
346
|
+
end
|
347
|
+
puts
|
348
|
+
puts "Mailboxes"
|
349
|
+
puts "User Name,Name,Password,Quota,Maildir,Active"
|
350
|
+
Mailbox.all.each do |m|
|
351
|
+
puts [m.username, %Q!"#{m.name}"!, %Q!"#{m.password}"!, m.quota, %Q!"#{m.maildir}"!, m.active].join(',')
|
352
|
+
end
|
353
|
+
puts
|
354
|
+
puts "Aliases"
|
355
|
+
puts "Address,Go to,Active"
|
356
|
+
Alias.all.select { |a| !a.mailbox? }.each do |a|
|
357
|
+
puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
|
358
|
+
end
|
359
|
+
puts
|
360
|
+
puts "Forwards"
|
361
|
+
puts "Address,Go to,Active"
|
362
|
+
Alias.all.select { |a| a.mailbox? && a.goto != a.address }.each do |a|
|
363
|
+
puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
264
367
|
private
|
265
368
|
|
266
369
|
def show_alias_base(title, addresses)
|
267
|
-
report(title, " No. Address Go to") do
|
370
|
+
report(title, " No. Address Active Go to") do
|
268
371
|
if addresses.empty?
|
269
372
|
puts " No #{title.downcase}"
|
270
373
|
next
|
271
374
|
end
|
272
375
|
|
273
376
|
addresses.each_with_index do |a, i|
|
274
|
-
puts "%4d %-40s
|
377
|
+
puts "%4d %-40s %-3s %s" % [i+1, a.address, a.active_str, a.goto]
|
275
378
|
end
|
276
379
|
end
|
277
380
|
end
|
@@ -310,7 +413,7 @@ module PostfixAdmin
|
|
310
413
|
puts "-"*120
|
311
414
|
end
|
312
415
|
|
313
|
-
def report(title, index=nil)
|
416
|
+
def report(title, index = nil)
|
314
417
|
puts "\n[#{title}]"
|
315
418
|
print_line if index
|
316
419
|
puts index if index
|
@@ -320,7 +423,7 @@ module PostfixAdmin
|
|
320
423
|
end
|
321
424
|
|
322
425
|
def account_check(user_name)
|
323
|
-
unless Mailbox.
|
426
|
+
unless Mailbox.exists?(user_name) && Alias.exists?(user_name)
|
324
427
|
raise Error, %Q!Could not find account "#{user_name}"!
|
325
428
|
end
|
326
429
|
end
|
@@ -333,13 +436,17 @@ module PostfixAdmin
|
|
333
436
|
klass_check(Mailbox, address)
|
334
437
|
end
|
335
438
|
|
439
|
+
def alias_check(address)
|
440
|
+
klass_check(Alias, address)
|
441
|
+
end
|
442
|
+
|
336
443
|
def admin_check(user_name)
|
337
444
|
klass_check(Admin, user_name)
|
338
445
|
end
|
339
446
|
|
340
447
|
def klass_check(klass, name)
|
341
448
|
object_name = klass.name.gsub(/PostfixAdmin::/, '').downcase
|
342
|
-
raise Error, %Q!Could not find #{object_name} "#{name}"! unless klass.
|
449
|
+
raise Error, %Q!Could not find #{object_name} "#{name}"! unless klass.exists?(name)
|
343
450
|
end
|
344
451
|
|
345
452
|
def validate_password(password)
|
@@ -349,13 +456,13 @@ module PostfixAdmin
|
|
349
456
|
end
|
350
457
|
|
351
458
|
def change_password(klass, user_name, password)
|
352
|
-
raise Error, "Could not find #{user_name}" unless klass.
|
459
|
+
raise Error, "Could not find #{user_name}" unless klass.exists?(user_name)
|
353
460
|
|
354
461
|
validate_password(password)
|
355
462
|
|
356
463
|
obj = klass.find(user_name)
|
357
|
-
|
358
|
-
if obj.
|
464
|
+
|
465
|
+
if obj.update(password: hashed_password(password))
|
359
466
|
puts "the password of #{user_name} was successfully changed."
|
360
467
|
else
|
361
468
|
raise "Could not change password of #{klass.name}"
|
@@ -373,5 +480,13 @@ module PostfixAdmin
|
|
373
480
|
end
|
374
481
|
end
|
375
482
|
|
483
|
+
private
|
484
|
+
|
485
|
+
def hashed_password(password, in_scheme = nil)
|
486
|
+
prefix = @base.config[:passwordhash_prefix]
|
487
|
+
scheme = in_scheme || @base.config[:scheme]
|
488
|
+
puts "scheme: #{scheme}"
|
489
|
+
PostfixAdmin::Doveadm.password(password, scheme, prefix)
|
490
|
+
end
|
376
491
|
end
|
377
492
|
end
|