postfix_admin 0.1.0 → 0.2.0

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