postfix_admin 0.1.0 → 0.2.0

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,32 +1,62 @@
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
- CONFIG_FILE = '~/.postfix_admin.conf'
7
+ @config_file = '~/.postfix_admin.conf'
7
8
  MIN_NUM_PASSWORD_CHARACTER = 5
8
9
 
9
10
  def initialize
10
11
  @config = load_config
11
- @base = PostfixAdmin::Base.new(@config)
12
+ @base = Base.new(@config)
12
13
  end
13
14
 
14
- def show(domain)
15
- show_summary(domain)
15
+ def self.config_file
16
+ @config_file
17
+ end
18
+
19
+ def self.config_file=(value)
20
+ @config_file = value
21
+ end
22
+
23
+ def db_setup
24
+ @base.db_setup
25
+ end
26
+
27
+ def show(name)
28
+ name = name.downcase if name
29
+
30
+ if name =~ /@/
31
+ if Admin.exists?(name)
32
+ show_admin_details(name)
33
+ end
34
+
35
+ if Mailbox.exists?(name)
36
+ show_account_details(name)
37
+ elsif Alias.exists?(name)
38
+ show_alias_details(name)
39
+ end
40
+
41
+ return
42
+ end
16
43
 
17
- if domain
18
- show_admin(domain)
19
- show_address(domain)
20
- show_alias(domain)
44
+ show_summary(name)
45
+
46
+ if name
47
+ show_admin(name)
48
+ show_address(name)
49
+ show_alias(name)
21
50
  else
22
51
  show_domain
23
52
  show_admin
24
53
  end
25
54
  end
26
55
 
27
- def show_summary(domain_name=nil)
56
+ def show_summary(domain_name = nil)
28
57
  title = "Summary"
29
58
  if domain_name
59
+ domain_name = domain_name.downcase
30
60
  domain_check(domain_name)
31
61
  title = "Summary of #{domain_name}"
32
62
  end
@@ -34,60 +64,85 @@ module PostfixAdmin
34
64
  report(title) do
35
65
  if domain_name
36
66
  domain = Domain.find(domain_name)
37
- puts "Mailboxes : %4d" % domain.mailboxes.count
38
- puts "Aliases : %4d" % domain.num_total_aliases
39
- puts "Quota : %4d MB" % domain.maxquota
67
+ puts "Mailboxes : %4d / %4s" % [domain.rel_mailboxes.count, max_str(domain.mailboxes)]
68
+ puts "Aliases : %4d / %4s" % [domain.pure_aliases.count, max_str(domain.aliases)]
69
+ puts "Max Quota : %4d MB" % domain.maxquota
70
+ puts "Active : %3s" % domain.active_str
40
71
  else
41
- puts "Domains : %4d" % Domain.all_without_special_domain.count
72
+ puts "Domains : %4d" % Domain.without_all.count
42
73
  puts "Admins : %4d" % Admin.count
43
74
  puts "Mailboxes : %4d" % Mailbox.count
44
- puts "Aliases : %4d" % Domain.num_total_aliases
75
+ puts "Aliases : %4d" % Alias.pure.count
45
76
  end
46
77
  end
47
78
  end
48
79
 
49
- def setup_domain(domain, password)
50
- admin = "admin@#{domain}"
51
- add_domain(domain)
80
+ def setup_domain(domain_name, password)
81
+ admin = "admin@#{domain_name}"
82
+ add_domain(domain_name)
52
83
  add_admin(admin, password)
53
- add_admin_domain(admin, domain)
84
+ add_admin_domain(admin, domain_name)
54
85
  end
55
86
 
56
- def show_domain
57
- index = " No. Domain Aliases Mailboxes Quota (MB)"
58
- report('Domains', index) do
59
- if Domain.all_without_special_domain.count == 0
60
- puts " No domains"
61
- else
62
- Domain.all_without_special_domain.each_with_index do |d, i|
63
- puts "%4d %-20s %3d /%3d %3d /%3d %10d" %
64
- [i+1, d.domain_name, d.num_total_aliases, d.maxaliases,
65
- d.mailboxes.count, d.maxmailboxes, d.maxquota]
66
- end
67
- end
87
+ def show_account_details(user_name)
88
+ account_check(user_name)
89
+ mailbox = Mailbox.find(user_name)
90
+ mail_alias = Alias.find(user_name)
91
+
92
+ report("Mailbox") do
93
+ puts "Address : %s" % mailbox.username
94
+ puts "Name : %s" % mailbox.name
95
+ puts "Password : %s" % mailbox.password
96
+ puts "Quota : %d MB" % max_str(mailbox.quota / KB_TO_MB)
97
+ puts "Go to : %s" % mail_alias.goto
98
+ puts "Active : %s" % mailbox.active_str
68
99
  end
69
100
  end
70
101
 
71
- def add_domain(domain)
72
- if @base.add_domain(domain)
73
- puts %Q!"#{domain}" was successfully registered.!
102
+ def show_admin_details(name)
103
+ admin_check(name)
104
+ admin = Admin.find(name)
105
+
106
+ report("Admin") do
107
+ puts "Name : %s" % admin.username
108
+ puts "Password : %s" % admin.password
109
+ puts "Domains : %s" % (admin.super_admin? ? "ALL" : admin.rel_domains.count)
110
+ puts "Role : %s" % (admin.super_admin? ? "Super admin" : "Admin")
111
+ puts "Active : %s" % admin.active_str
74
112
  end
75
113
  end
76
114
 
77
- def super_admin(user_name, disable)
78
- unless Admin.exist?(user_name)
79
- raise Error, "Could not find admin #{user_name}"
115
+ def show_alias_details(name)
116
+ alias_check(name)
117
+ mail_alias = Alias.find(name)
118
+ report("Alias") do
119
+ puts "Address : %s" % mail_alias.address
120
+ puts "Go to : %s" % mail_alias.goto
121
+ puts "Active : %s" % mail_alias.active_str
80
122
  end
123
+ end
81
124
 
82
- if disable
83
- Admin.find(user_name).super_admin = false
84
- puts "Successfully disabled super admin flag of #{user_name}"
85
- else
86
- Admin.find(user_name).super_admin = true
87
- puts "Successfully enabled super admin flag of #{user_name}"
125
+ def show_domain
126
+ index = " No. Domain Aliases Mailboxes Quota (MB) Active"
127
+ report('Domains', index) do
128
+ if Domain.without_all.empty?
129
+ puts " No domains"
130
+ next
131
+ end
132
+
133
+ Domain.without_all.each_with_index do |d, i|
134
+ puts "%4d %-30s %3d /%3s %3d /%3s %10d %-3s" %
135
+ [i+1, d.domain, d.pure_aliases.count, max_str(d.aliases),
136
+ d.rel_mailboxes.count, max_str(d.mailboxes), d.maxquota, d.active_str]
137
+ end
88
138
  end
89
139
  end
90
140
 
141
+ def add_domain(domain_name)
142
+ @base.add_domain(domain_name)
143
+ puts_registered(domain_name, "a domain")
144
+ end
145
+
91
146
  def change_admin_password(user_name, password)
92
147
  change_password(Admin, user_name, password)
93
148
  end
@@ -96,124 +151,233 @@ module PostfixAdmin
96
151
  change_password(Mailbox, user_name, password)
97
152
  end
98
153
 
99
- def delete_domain(domain)
100
- if @base.delete_domain(domain)
101
- puts_deleted(domain)
154
+ def edit_admin(admin_name, options)
155
+ admin_check(admin_name)
156
+ admin = Admin.find(admin_name)
157
+
158
+ unless options[:super].nil?
159
+ admin.super_admin = options[:super]
102
160
  end
161
+
162
+ admin.active = options[:active] unless options[:active].nil?
163
+ admin.save!
164
+
165
+ puts "Successfully updated #{admin_name}"
166
+ show_admin_details(admin_name)
167
+ end
168
+
169
+ def edit_domain(domain_name, options)
170
+ domain_check(domain_name)
171
+ domain = Domain.find(domain_name)
172
+ domain.aliases = options[:aliases] if options[:aliases]
173
+ domain.mailboxes = options[:mailboxes] if options[:mailboxes]
174
+ domain.maxquota = options[:maxquota] if options[:maxquota]
175
+ domain.active = options[:active] unless options[:active].nil?
176
+ domain.save!
177
+
178
+ puts "Successfully updated #{domain_name}"
179
+ show_summary(domain_name)
103
180
  end
104
181
 
105
- def show_admin(domain=nil)
106
- admins = domain ? Admin.select{|a| a.has_domain?(domain)} : Admin.all
107
- index = " No. Admin Domains Password"
182
+ def delete_domain(domain_name)
183
+ @base.delete_domain(domain_name)
184
+ puts_deleted(domain_name)
185
+ end
186
+
187
+ def show_admin(domain_name = nil)
188
+ admins = domain_name ? Admin.select { |a| a.rel_domains.exists?(domain_name) } : Admin.all
189
+ index = " No. Admin Domains Active"
108
190
  report("Admins", index) do
109
- if admins.count == 0
191
+ if admins.empty?
110
192
  puts " No admins"
111
- else
112
- admins.each_with_index do |a, i|
113
- domains = a.super_admin? ? 'Super admin' : a.domains.count
114
- puts "%4d %-30s %11s %s" % [i+1, a.username, domains, a.password]
115
- end
193
+ next
116
194
  end
117
- end
118
195
 
196
+ admins.each_with_index do |a, i|
197
+ domains = a.super_admin? ? 'Super admin' : a.rel_domains.count
198
+ puts "%4d %-40s %11s %-3s" % [i+1, a.username, domains, a.active_str]
199
+ end
200
+ end
119
201
  end
120
202
 
121
- def show_address(domain)
122
- domain_check(domain)
203
+ def show_address(domain_name)
204
+ domain_check(domain_name)
123
205
 
124
- mailboxes = Domain.find(domain).mailboxes
125
- index = " No. Email Quota (MB) Password"
206
+ mailboxes = Domain.find(domain_name).rel_mailboxes
207
+ index = " No. Email Name Quota (MB) Active Maildir"
126
208
  report("Addresses", index) do
127
- if mailboxes.count == 0
209
+ if mailboxes.empty?
128
210
  puts " No addresses"
129
- else
130
- mailboxes.each_with_index do |m, i|
131
- quota = m.quota.to_f/1024000.0
132
- puts "%4d %-30s %10.1f %s" % [i+1, m.username, quota, m.password]
133
- end
211
+ next
134
212
  end
135
- end
136
213
 
214
+ mailboxes.each_with_index do |m, i|
215
+ quota = m.quota.to_f/ KB_TO_MB.to_f
216
+ puts "%4d %-30s %-20s %10s %-3s %s" % [i+1, m.username, m.name, max_str(quota.to_i), m.active_str, m.maildir]
217
+ end
218
+ end
137
219
  end
138
220
 
139
- def show_alias(domain)
140
- domain_check(domain)
221
+ def show_alias(domain_name)
222
+ domain_check(domain_name)
141
223
 
142
- aliases = Domain.find(domain).aliases.find_all do |mail_alias|
143
- mail_alias.address != mail_alias.goto
144
- end
224
+ forwards, aliases = Domain.find(domain_name).rel_aliases.partition { |a| a.mailbox? }
145
225
 
146
- index = " No. Address Go to"
147
- report("Aliases", index) do
148
- if aliases.count == 0
149
- puts " No aliases"
150
- else
151
- aliases.each_with_index do |a, i|
152
- puts "%4d %-30s %s" % [i+1, a.address, a.goto]
153
- end
154
- end
226
+ forwards.delete_if do |f|
227
+ f.address == f.goto
155
228
  end
156
229
 
230
+ show_alias_base("Forwards", forwards)
231
+ show_alias_base("Aliases", aliases)
157
232
  end
158
233
 
159
234
  def show_admin_domain(user_name)
160
235
  admin = Admin.find(user_name)
161
- if admin.domains.count == 0
236
+ if admin.rel_domains.empty?
162
237
  puts "\nNo domain in database"
163
238
  return
164
239
  end
240
+
165
241
  report("Domains (#{user_name})", " No. Domain") do
166
- admin.domains.each_with_index do |d, i|
167
- puts "%4d %-20s" % [i+1, d.domain_name]
242
+ admin.rel_domains.each_with_index do |d, i|
243
+ puts "%4d %-30s" % [i + 1, d.domain]
168
244
  end
169
245
  end
170
246
  end
171
247
 
172
- def add_admin(user_name, password, super_admin=false)
248
+ def add_admin(user_name, password, super_admin = false, scheme = nil)
173
249
  validate_password(password)
174
- if @base.add_admin(user_name, password)
175
- if super_admin
176
- Admin.find(user_name).super_admin = true
177
- puts_registered(user_name, "a super admin")
178
- else
179
- puts_registered(user_name, "an admin")
180
- end
250
+
251
+ @base.add_admin(user_name, hashed_password(password, scheme))
252
+ if super_admin
253
+ Admin.find(user_name).super_admin = true
254
+ puts_registered(user_name, "a super admin")
255
+ else
256
+ puts_registered(user_name, "an admin")
181
257
  end
182
258
  end
183
259
 
184
- def add_admin_domain(user_name, domain)
185
- if @base.add_admin_domain(user_name, domain)
186
- puts_registered(domain, "a domain of #{user_name}")
187
- end
260
+ def add_admin_domain(user_name, domain_name)
261
+ @base.add_admin_domain(user_name, domain_name)
262
+ puts_registered(domain_name, "a domain of #{user_name}")
188
263
  end
189
264
 
190
- def add_account(address, password)
265
+ def delete_admin_domain(user_name, domain_name)
266
+ @base.delete_admin_domain(user_name, domain_name)
267
+ puts "#{domain_name} was successfully deleted from #{user_name}"
268
+ end
269
+
270
+ def add_account(address, password, scheme = nil, name = nil)
191
271
  validate_password(password)
192
- if @base.add_account(address, password)
193
- puts_registered(address, "an account")
194
- end
272
+
273
+ @base.add_account(address, hashed_password(password, scheme), name)
274
+ puts_registered(address, "an account")
275
+ show_account_details(address)
195
276
  end
196
277
 
197
278
  def add_alias(address, goto)
198
- if @base.add_alias(address, goto)
199
- puts_registered("#{address}: #{goto}", "an alias")
279
+ @base.add_alias(address, goto)
280
+ puts_registered("#{address}: #{goto}", "an alias")
281
+ end
282
+
283
+ def edit_account(address, options)
284
+ mailbox_check(address)
285
+ mailbox = Mailbox.find(address)
286
+ mailbox.name = options[:name] if options[:name]
287
+ mailbox.quota = options[:quota] * KB_TO_MB if options[:quota]
288
+ mailbox.active = options[:active] unless options[:active].nil?
289
+ mailbox.save!
290
+
291
+ if options[:goto]
292
+ mail_alias = Alias.find(address)
293
+ mail_alias.goto = options[:goto]
294
+ mail_alias.save!
200
295
  end
296
+
297
+ puts "Successfully updated #{address}"
298
+ show_account_details(address)
299
+ end
300
+
301
+ def edit_alias(address, options)
302
+ alias_check(address)
303
+ mail_alias = Alias.find(address)
304
+ mail_alias.goto = options[:goto] if options[:goto]
305
+ mail_alias.active = options[:active] unless options[:active].nil?
306
+ mail_alias.save or raise "Could not save Alias"
307
+
308
+ puts "Successfully updated #{address}"
309
+ show_alias_details(address)
201
310
  end
202
311
 
203
312
  def delete_alias(address)
204
- puts_deleted(address) if @base.delete_alias(address)
313
+ @base.delete_alias(address)
314
+ puts_deleted(address)
205
315
  end
206
316
 
207
317
  def delete_admin(user_name)
208
- puts_deleted(user_name) if @base.delete_admin(user_name)
318
+ @base.delete_admin(user_name)
319
+ puts_deleted(user_name)
209
320
  end
210
321
 
211
322
  def delete_account(address)
212
- puts_deleted(address) if @base.delete_account(address)
323
+ @base.delete_account(address)
324
+ puts_deleted(address)
325
+ end
326
+
327
+ def log
328
+ Log.all.each do |l|
329
+ time = l.timestamp.strftime("%Y-%m-%d %X %Z")
330
+ puts "#{time} #{l.username} #{l.domain} #{l.action} #{l.data}"
331
+ end
332
+ end
333
+
334
+ def dump
335
+ puts "Admins"
336
+ puts "User Name,Password,Super Admin,Active"
337
+ Admin.all.each do |a|
338
+ puts [a.username, %Q!"#{a.password}"!, a.super_admin?, a.active].join(',')
339
+ end
340
+ puts
341
+ puts "Domains"
342
+ puts "Domain Name,Max Quota,Active"
343
+ Domain.without_all.each do |d|
344
+ puts [d.domain, d.maxquota, d.active].join(',')
345
+ end
346
+ puts
347
+ puts "Mailboxes"
348
+ puts "User Name,Name,Password,Quota,Maildir,Active"
349
+ Mailbox.all.each do |m|
350
+ puts [m.username, %Q!"#{m.name}"!, %Q!"#{m.password}"!, m.quota, %Q!"#{m.maildir}"!, m.active].join(',')
351
+ end
352
+ puts
353
+ puts "Aliases"
354
+ puts "Address,Go to,Active"
355
+ Alias.all.select { |a| !a.mailbox? }.each do |a|
356
+ puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
357
+ end
358
+ puts
359
+ puts "Forwards"
360
+ puts "Address,Go to,Active"
361
+ Alias.all.select { |a| a.mailbox? && a.goto != a.address }.each do |a|
362
+ puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
363
+ end
213
364
  end
214
365
 
215
366
  private
216
367
 
368
+ def show_alias_base(title, addresses)
369
+ report(title, " No. Address Active Go to") do
370
+ if addresses.empty?
371
+ puts " No #{title.downcase}"
372
+ next
373
+ end
374
+
375
+ addresses.each_with_index do |a, i|
376
+ puts "%4d %-40s %-3s %s" % [i+1, a.address, a.active_str, a.goto]
377
+ end
378
+ end
379
+ end
380
+
217
381
  def puts_registered(name, as_str)
218
382
  puts %Q!"#{name}" was successfully registered as #{as_str}.!
219
383
  end
@@ -223,7 +387,7 @@ module PostfixAdmin
223
387
  end
224
388
 
225
389
  def config_file
226
- config_file = File.expand_path(CONFIG_FILE)
390
+ config_file = File.expand_path(CLI.config_file)
227
391
  end
228
392
 
229
393
  def load_config
@@ -237,18 +401,18 @@ module PostfixAdmin
237
401
  end
238
402
  end
239
403
 
240
- def create_config(config_file)
241
- open(config_file, 'w') do |f|
242
- f.write PostfixAdmin::Base::DEFAULT_CONFIG.to_yaml
404
+ def create_config(file)
405
+ open(file, 'w') do |f|
406
+ f.write Base::DEFAULT_CONFIG.to_yaml
243
407
  end
244
- File.chmod(0600, config_file)
408
+ File.chmod(0600, file)
245
409
  end
246
410
 
247
411
  def print_line
248
- puts "-"*100
412
+ puts "-"*120
249
413
  end
250
414
 
251
- def report(title, index=nil)
415
+ def report(title, index = nil)
252
416
  puts "\n[#{title}]"
253
417
  print_line if index
254
418
  puts index if index
@@ -257,12 +421,33 @@ module PostfixAdmin
257
421
  print_line
258
422
  end
259
423
 
260
- def domain_check(domain_name)
261
- unless Domain.exist?(domain_name)
262
- raise Error, %Q!Could not find domain "#{domain_name}"!
424
+ def account_check(user_name)
425
+ unless Mailbox.exists?(user_name) && Alias.exists?(user_name)
426
+ raise Error, %Q!Could not find account "#{user_name}"!
263
427
  end
264
428
  end
265
429
 
430
+ def domain_check(domain_name)
431
+ klass_check(Domain, domain_name)
432
+ end
433
+
434
+ def mailbox_check(address)
435
+ klass_check(Mailbox, address)
436
+ end
437
+
438
+ def alias_check(address)
439
+ klass_check(Alias, address)
440
+ end
441
+
442
+ def admin_check(user_name)
443
+ klass_check(Admin, user_name)
444
+ end
445
+
446
+ def klass_check(klass, name)
447
+ object_name = klass.name.gsub(/PostfixAdmin::/, '').downcase
448
+ raise Error, %Q!Could not find #{object_name} "#{name}"! unless klass.exists?(name)
449
+ end
450
+
266
451
  def validate_password(password)
267
452
  if password.size < MIN_NUM_PASSWORD_CHARACTER
268
453
  raise ArgumentError, "Password is too short. It should be larger than #{MIN_NUM_PASSWORD_CHARACTER}"
@@ -270,19 +455,36 @@ module PostfixAdmin
270
455
  end
271
456
 
272
457
  def change_password(klass, user_name, password)
273
- unless klass.exist?(user_name)
274
- raise Error, "Could not find #{user_name}"
275
- end
458
+ raise Error, "Could not find #{user_name}" unless klass.exists?(user_name)
459
+
276
460
  validate_password(password)
277
461
 
278
462
  obj = klass.find(user_name)
279
- obj.password = password
280
- if obj.save
463
+
464
+ if obj.update(password: hashed_password(password))
281
465
  puts "the password of #{user_name} was successfully changed."
282
466
  else
283
467
  raise "Could not change password of #{klass.name}"
284
468
  end
285
469
  end
286
470
 
471
+ def max_str(value)
472
+ case value
473
+ when 0
474
+ '--'
475
+ when -1
476
+ '0'
477
+ else
478
+ value.to_s
479
+ end
480
+ end
481
+
482
+ private
483
+
484
+ def hashed_password(password, in_scheme = nil)
485
+ scheme = in_scheme || @base.config[:scheme]
486
+ puts "scheme: #{scheme}"
487
+ PostfixAdmin::Doveadm.password(password, scheme)
488
+ end
287
489
  end
288
490
  end