postfix_admin 0.1.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 03fe6501c97e53bf66c3fa2f783e8b2e40cc18da
4
- data.tar.gz: 0a7c400bee5d1f953ea9f2d03475b8c1e182653f
3
+ metadata.gz: afa77157060260499b49c44b35270deaf01ffde5
4
+ data.tar.gz: 00bc7f9dfb7e8b6b628b9dbe0b3660b6f6d52828
5
5
  SHA512:
6
- metadata.gz: b976ae17e338b7bd8154a092bb1d9ed91274b3cb1f008fc1d98e0b55b045dd28966e1d912cd35315bd75ce3005d2bad2e286d29d869967038e461c6867ad31e2
7
- data.tar.gz: 56b944669124660d726addfcd2258543845b61170ea68cae3189d7ff87b45e4d2809ba2a0bfbea274d8338ada8e10e64408e672713531043614c28dd6bc07275
6
+ metadata.gz: 3a82010397e072cfd3ab056a908b943ebc5f0aff711977944768e32fdf60ae7dd81651416a08e97fcd27114ed230ffacb9ebb3e1c4790719c1a3ecf801ef8bf2
7
+ data.tar.gz: 89bea8924bb55e225d4b286c28f10c97e5a8218481896fab6c6c8e2359171dc5391d334ad44bec814bc9214d76f1a50c7b459e2589194aaa0322a9a3f947b964
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ ## 0.1.2
2
+ * Support password hash by doveadm (external command)
3
+ * Show active status
4
+ * Don't show passwords using list format
5
+
6
+ ## 0.1.1, release 2013-05-10
7
+ * Fixed string length of password
8
+
9
+
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/postfix_admin.png)](https://rubygems.org/gems/postfix_admin)
2
+
1
3
  # PostfixAdmin
2
4
 
3
5
  Command Line Tools of Postfix Admin
@@ -26,23 +28,29 @@ List the postfix_admin subcommands as:
26
28
  $ postfix_admin
27
29
 
28
30
  ```
29
- postfix_admin account_passwd user@example.com new_password # Change password of account
30
- postfix_admin add_account user@example.com password # Add an account
31
- postfix_admin add_admin admin@example.com password # Add an admin user
32
- postfix_admin add_admin_domain admin@example.com example.com # Add admin_domain
33
- postfix_admin add_alias alias@example.com goto@example.net # Add an alias
34
- postfix_admin add_domain example.com # Add a domain
35
- postfix_admin admin_passwd admin@example.com new_password # Change password of admin
36
- postfix_admin delete_account user@example.com # Delete an account
37
- postfix_admin delete_admin admin@example.com # Delete an admin
38
- postfix_admin delete_alias alias@example.com # Delete an alias
39
- postfix_admin delete_domain example.com # Delete a domain
40
- postfix_admin help [TASK] # Describe available tasks or one specific task
41
- postfix_admin setup example.com password # Setup a domain
42
- postfix_admin show # List of domains
43
- postfix_admin summary [example.com] # Summarize the usage of PostfixAdmin
44
- postfix_admin super_admin admin@example.com # Enable super admin flag of an admin
45
- postfix_admin version # Show postfix_admin version
31
+ Commands:
32
+ postfix_admin account_passwd user@example.com new_password # Change password of account
33
+ postfix_admin add_account user@example.com password # Add an account
34
+ postfix_admin add_admin admin@example.com password # Add an admin user
35
+ postfix_admin add_admin_domain admin@example.com example.com # Add admin_domain
36
+ postfix_admin add_alias alias@example.com goto@example.net # Add an alias
37
+ postfix_admin add_domain example.com # Add a domain
38
+ postfix_admin admin_passwd admin@example.com new_password # Change password of admin
39
+ postfix_admin delete_account user@example.com # Delete an account
40
+ postfix_admin delete_admin admin@example.com # Delete an admin
41
+ postfix_admin delete_admin_domain admin@example.com example.com # Delete admin_domain
42
+ postfix_admin delete_alias alias@example.com # Delete an alias
43
+ postfix_admin delete_domain example.com # Delete a domain
44
+ postfix_admin dump # Dump all data
45
+ postfix_admin edit_account user@example.com # Edit an account
46
+ postfix_admin edit_domain example.com # Edit a domain limitation
47
+ postfix_admin help [COMMAND] # Describe available commands or one specific command
48
+ postfix_admin schemes # List all supported password schemes
49
+ postfix_admin setup example.com password # Setup a domain
50
+ postfix_admin show [example.com | admin@example.com | user@example.com] # Show domains or admins or mailboxes
51
+ postfix_admin summary [example.com] # Summarize the usage of PostfixAdmin
52
+ postfix_admin super_admin admin@example.com # Enable super admin flag of an admin
53
+ postfix_admin version # Show postfix_admin version
46
54
  ```
47
55
 
48
56
  ## Contributing
@@ -12,16 +12,26 @@ module PostfixAdmin
12
12
  'database' => 'mysql://postfix:password@localhost/postfix',
13
13
  'aliases' => 30,
14
14
  'mailboxes' => 30,
15
- 'maxquota' => 100
15
+ 'maxquota' => 100,
16
+ 'scheme' => 'CRAM-MD5',
16
17
  }
17
18
 
18
19
  def initialize(config)
19
20
  db_setup(config['database'])
21
+ if local_part_required?
22
+ eval <<"EOS"
23
+ class ::PostfixAdmin::Mailbox
24
+ property :local_part, String
25
+ end
26
+ EOS
27
+ DataMapper.finalize
28
+ end
20
29
  @config = {}
21
30
  @config[:aliases] = config['aliases'] || 30
22
31
  @config[:mailboxes] = config['mailboxes'] || 30
23
32
  @config[:maxquota] = config['maxquota'] || 100
24
33
  @config[:mailbox_quota] = @config[:maxquota] * KB_TO_MB
34
+ @config[:scheme] = config['scheme'] || 'CRAM-MD5'
25
35
  end
26
36
 
27
37
  def db_setup(database)
@@ -56,6 +66,8 @@ module PostfixAdmin
56
66
  end
57
67
 
58
68
  def add_admin(username, password)
69
+ password_check(password)
70
+
59
71
  if Admin.exist?(username)
60
72
  raise Error, "#{username} is already resistered as admin."
61
73
  end
@@ -69,7 +81,10 @@ module PostfixAdmin
69
81
  end
70
82
  end
71
83
 
72
- def add_account(address, password)
84
+ def add_account(address, password, in_name=nil)
85
+ name = in_name || ''
86
+ password_check(password)
87
+
73
88
  if address !~ /.+\@.+\..+/
74
89
  raise Error, "Invalid mail address #{address}"
75
90
  end
@@ -88,14 +103,20 @@ module PostfixAdmin
88
103
  domain.aliases << Alias.mailbox(address)
89
104
 
90
105
  mailbox = Mailbox.new
91
- mailbox.attributes = {
106
+ attributes = {
92
107
  :username => address,
93
108
  :password => password,
94
- :name => '',
109
+ :name => name,
95
110
  :maildir => path,
96
111
  :quota => @config[:mailbox_quota],
97
- # :local_part => user,
98
112
  }
113
+
114
+ if local_part_required?
115
+ attributes[:local_part] = user
116
+ end
117
+
118
+ mailbox.attributes = attributes
119
+
99
120
  domain.mailboxes << mailbox
100
121
  unless domain.save
101
122
  raise "Could not save Mailbox and Domain #{mailbox.errors.map{|e| e.to_s}.join} #{domain.errors.map{|e| e.to_s}.join}"
@@ -197,10 +218,18 @@ module PostfixAdmin
197
218
 
198
219
  private
199
220
 
221
+ # postfixadmin DB upgrade Number 495 loca_part added
222
+ def local_part_required?
223
+ Config.first.value.to_i >= 495
224
+ end
225
+
200
226
  def admin_domain_check(user_name, domain_name)
201
227
  raise Error, "#{user_name} is not resistered as admin." unless Admin.exist?(user_name)
202
228
  raise Error, "Could not find domain #{domain_name}" unless Domain.exist?(domain_name)
203
229
  end
204
230
 
231
+ def password_check(password)
232
+ raise Error, "Empty password" if password.nil? || password.empty?
233
+ end
205
234
  end
206
235
  end
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'postfix_admin'
3
+ require 'postfix_admin/doveadm'
3
4
 
4
5
  module PostfixAdmin
5
6
  class CLI
@@ -23,7 +24,16 @@ module PostfixAdmin
23
24
  name = name.downcase if name
24
25
 
25
26
  if name =~ /@/
26
- show_account(name)
27
+ if Admin.exist?(name)
28
+ show_admin_details(name)
29
+ end
30
+
31
+ if Mailbox.exist?(name)
32
+ show_account_details(name)
33
+ elsif Alias.exist?(name)
34
+ show_alias_details(name)
35
+ end
36
+
27
37
  return
28
38
  end
29
39
 
@@ -69,21 +79,44 @@ module PostfixAdmin
69
79
  add_admin_domain(admin, domain_name)
70
80
  end
71
81
 
72
- def show_account(user_name)
82
+ def show_account_details(user_name)
73
83
  account_check(user_name)
74
84
  mailbox = Mailbox.find(user_name)
75
85
  mail_alias = Alias.find(user_name)
76
86
 
77
87
  report("Mailbox") do
78
88
  puts "Address : %s" % mailbox.username
89
+ puts "Name : %s" % mailbox.name
79
90
  puts "Password : %s" % mailbox.password
80
91
  puts "Quota : %d MB" % max_str(mailbox.quota / KB_TO_MB)
81
92
  puts "Go to : %s" % mail_alias.goto
93
+ puts "Active : %s" % mailbox.active_str
94
+ end
95
+ end
96
+
97
+ def show_admin_details(name)
98
+ admin_check(name)
99
+ admin = Admin.find(name)
100
+
101
+ report("Admin") do
102
+ puts "Name : %s" % admin.username
103
+ puts "Password : %s" % admin.password
104
+ puts "Active : %s" % admin.active_str
105
+ end
106
+ end
107
+
108
+ def show_alias_details(name)
109
+ alias_check(name)
110
+ mail_alias = Alias.find(name)
111
+ report("Alias") do
112
+ puts "Address : %s" % mail_alias.address
113
+ puts "Go to : %s" % mail_alias.goto
114
+ puts "Active : %s" % mail_alias.active_str
82
115
  end
83
116
  end
84
117
 
85
118
  def show_domain
86
- index = " No. Domain Aliases Mailboxes Quota (MB)"
119
+ index = " No. Domain Aliases Mailboxes Quota (MB) Active"
87
120
  report('Domains', index) do
88
121
  if Domain.all_without_special_domain.empty?
89
122
  puts " No domains"
@@ -91,9 +124,9 @@ module PostfixAdmin
91
124
  end
92
125
 
93
126
  Domain.all_without_special_domain.each_with_index do |d, i|
94
- puts "%4d %-30s %3d /%3s %3d /%3s %10d" %
127
+ puts "%4d %-30s %3d /%3s %3d /%3s %10d %-3s" %
95
128
  [i+1, d.domain_name, d.num_total_aliases, max_str(d.maxaliases),
96
- d.mailboxes.count, max_str(d.maxmailboxes), d.maxquota]
129
+ d.mailboxes.count, max_str(d.maxmailboxes), d.maxquota, d.active_str]
97
130
  end
98
131
  end
99
132
 
@@ -143,7 +176,7 @@ module PostfixAdmin
143
176
 
144
177
  def show_admin(domain_name=nil)
145
178
  admins = domain_name ? Admin.select{|a| a.has_domain?(domain_name)} : Admin.all
146
- index = " No. Admin Domains Password"
179
+ index = " No. Admin Domains Active"
147
180
  report("Admins", index) do
148
181
  if admins.empty?
149
182
  puts " No admins"
@@ -152,7 +185,7 @@ module PostfixAdmin
152
185
 
153
186
  admins.each_with_index do |a, i|
154
187
  domains = a.super_admin? ? 'Super admin' : a.domains.count
155
- puts "%4d %-40s %11s %s" % [i+1, a.username, domains, a.password]
188
+ puts "%4d %-40s %11s %-3s" % [i+1, a.username, domains, a.active_str]
156
189
  end
157
190
  end
158
191
 
@@ -162,7 +195,7 @@ module PostfixAdmin
162
195
  domain_check(domain_name)
163
196
 
164
197
  mailboxes = Domain.find(domain_name).mailboxes
165
- index = " No. Email Quota (MB) Password Maildir"
198
+ index = " No. Email Name Quota (MB) Active Maildir"
166
199
  report("Addresses", index) do
167
200
  if mailboxes.empty?
168
201
  puts " No addresses"
@@ -171,7 +204,7 @@ module PostfixAdmin
171
204
 
172
205
  mailboxes.each_with_index do |m, i|
173
206
  quota = m.quota.to_f/ KB_TO_MB.to_f
174
- puts "%4d %-40s %10s %-15s %s" % [i+1, m.username, max_str(quota.to_i), m.password, m.maildir]
207
+ puts "%4d %-30s %-20s %10s %-3s %s" % [i+1, m.username, m.name, max_str(quota.to_i), m.active_str, m.maildir]
175
208
  end
176
209
  end
177
210
 
@@ -204,9 +237,10 @@ module PostfixAdmin
204
237
  end
205
238
  end
206
239
 
207
- def add_admin(user_name, password, super_admin=false)
240
+ def add_admin(user_name, password, super_admin=false, scheme=nil)
208
241
  validate_password(password)
209
- @base.add_admin(user_name, password)
242
+
243
+ @base.add_admin(user_name, hashed_password(password, scheme))
210
244
  if super_admin
211
245
  Admin.find(user_name).super_admin = true
212
246
  puts_registered(user_name, "a super admin")
@@ -225,10 +259,12 @@ module PostfixAdmin
225
259
  puts "#{domain_name} was successfully deleted from #{user_name}"
226
260
  end
227
261
 
228
- def add_account(address, password)
262
+ def add_account(address, password, scheme=nil, name=nil)
229
263
  validate_password(password)
230
- @base.add_account(address, password)
264
+
265
+ @base.add_account(address, hashed_password(password, scheme), name)
231
266
  puts_registered(address, "an account")
267
+ show_account_details(address)
232
268
  end
233
269
 
234
270
  def add_alias(address, goto)
@@ -239,11 +275,12 @@ module PostfixAdmin
239
275
  def edit_account(address, options)
240
276
  mailbox_check(address)
241
277
  mailbox = Mailbox.find(address)
278
+ mailbox.name = options[:name] if options[:name]
242
279
  mailbox.quota = options[:quota] * KB_TO_MB if options[:quota]
243
280
  mailbox.save or raise "Could not save Mailbox"
244
281
 
245
282
  puts "Successfully updated #{address}"
246
- show_account(address)
283
+ show_account_details(address)
247
284
  end
248
285
 
249
286
  def delete_alias(address)
@@ -261,17 +298,49 @@ module PostfixAdmin
261
298
  puts_deleted(address)
262
299
  end
263
300
 
301
+ def dump
302
+ puts "Admins"
303
+ puts "User Name,Password,Super Admin,Active"
304
+ Admin.all.each do |a|
305
+ puts [a.username, %Q!"#{a.password}"!, a.super_admin?, a.active].join(',')
306
+ end
307
+ puts
308
+ puts "Domains"
309
+ puts "Domain Name,Max Quota,Active"
310
+ Domain.all_without_special_domain.each do |d|
311
+ puts [d.domain_name, d.maxquota, d.active].join(',')
312
+ end
313
+ puts
314
+ puts "Mailboxes"
315
+ puts "User Name,Name,Password,Quota,Maildir,Active"
316
+ Mailbox.all.each do |m|
317
+ puts [m.username, %Q!"#{m.name}"!, %Q!"#{m.password}"!, m.quota, %Q!"#{m.maildir}"!, m.active].join(',')
318
+ end
319
+ puts
320
+ puts "Aliases"
321
+ puts "Address,Go to,Active"
322
+ Alias.all.select{|a| !a.mailbox? }.each do |a|
323
+ puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
324
+ end
325
+ puts
326
+ puts "Forwards"
327
+ puts "Address,Go to,Active"
328
+ Alias.all.select{|a| a.mailbox? && a.goto != a.address }.each do |a|
329
+ puts [a.address, %Q!"#{a.goto}"!, a.active].join(',')
330
+ end
331
+ end
332
+
264
333
  private
265
334
 
266
335
  def show_alias_base(title, addresses)
267
- report(title, " No. Address Go to") do
336
+ report(title, " No. Address Active Go to") do
268
337
  if addresses.empty?
269
338
  puts " No #{title.downcase}"
270
339
  next
271
340
  end
272
341
 
273
342
  addresses.each_with_index do |a, i|
274
- puts "%4d %-40s %s" % [i+1, a.address, a.goto]
343
+ puts "%4d %-40s %-3s %s" % [i+1, a.address, a.active_str, a.goto]
275
344
  end
276
345
  end
277
346
  end
@@ -333,6 +402,10 @@ module PostfixAdmin
333
402
  klass_check(Mailbox, address)
334
403
  end
335
404
 
405
+ def alias_check(address)
406
+ klass_check(Alias, address)
407
+ end
408
+
336
409
  def admin_check(user_name)
337
410
  klass_check(Admin, user_name)
338
411
  end
@@ -354,7 +427,7 @@ module PostfixAdmin
354
427
  validate_password(password)
355
428
 
356
429
  obj = klass.find(user_name)
357
- obj.password = password
430
+ obj.password = hashed_password(password)
358
431
  if obj.save
359
432
  puts "the password of #{user_name} was successfully changed."
360
433
  else
@@ -373,5 +446,13 @@ module PostfixAdmin
373
446
  end
374
447
  end
375
448
 
449
+ private
450
+
451
+ def hashed_password(password, in_scheme=nil)
452
+ scheme = in_scheme || @base.config[:scheme]
453
+ puts "scheme: #{scheme}"
454
+ PostfixAdmin::Doveadm.password(password, scheme)
455
+ end
456
+
376
457
  end
377
458
  end
@@ -0,0 +1,32 @@
1
+
2
+ require 'open3'
3
+ require 'shellwords'
4
+
5
+ module PostfixAdmin
6
+ class Doveadm
7
+ def self.schemes
8
+ result = `#{self.command_name} -l`
9
+ result.split
10
+ end
11
+
12
+ def self.password(in_password, in_scheme)
13
+ password = Shellwords.escape(in_password)
14
+ scheme = Shellwords.escape(in_scheme)
15
+ stdin, stdout, stderr = Open3.popen3("#{self.command_name} -s #{scheme} -p #{password}")
16
+ if stderr.readlines.to_s =~ /Fatal:/
17
+ raise Error, stderr.readlines
18
+ else
19
+ stdout.readlines.first.chomp.gsub("{#{scheme}}", "")
20
+ end
21
+ end
22
+
23
+ def self.command_name
24
+ begin
25
+ Open3.capture3("doveadm pw -l")[2].exited?
26
+ "doveadm pw"
27
+ rescue Errno::ENOENT
28
+ "dovecotpw"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,10 +1,23 @@
1
1
  require 'data_mapper'
2
2
 
3
3
  module PostfixAdmin
4
+ def self.flag_str(flag)
5
+ flag ? "YES" : "NO"
6
+ end
7
+
8
+ class Config
9
+ include ::DataMapper::Resource
10
+ property :id, Integer, :key => true
11
+ property :name, String
12
+ property :value, String
13
+ storage_names[:default] = 'config'
14
+ end
15
+
4
16
  class Admin
5
17
  include ::DataMapper::Resource
6
- property :username, String, :key => true
18
+ property :username, String, :key => true, :length => 0..255
7
19
  property :password, String, :length => 0..255
20
+ property :active, Boolean, :default => true
8
21
  property :created, DateTime, :default => DateTime.now
9
22
  property :modified, DateTime, :default => DateTime.now
10
23
 
@@ -12,6 +25,10 @@ module PostfixAdmin
12
25
  has n, :domains, :model => 'Domain', :through => :domain_admins, :via => :domain
13
26
  storage_names[:default] = 'admin'
14
27
 
28
+ def active_str
29
+ PostfixAdmin.flag_str(active)
30
+ end
31
+
15
32
  def has_domain?(domain_name)
16
33
  if super_admin?
17
34
  Domain.exist?(domain_name)
@@ -55,13 +72,14 @@ module PostfixAdmin
55
72
 
56
73
  class Domain
57
74
  include ::DataMapper::Resource
58
- property :domain_name, String, :field => 'domain', :key => true
75
+ property :domain_name, String, :field => 'domain', :key => true, :length => 0..255
59
76
  property :maxaliases, Integer, :field => 'aliases'
60
77
  property :maxmailboxes, Integer, :field => 'mailboxes'
61
78
  property :maxquota, Integer
62
- property :transport, String, :default => 'virtual'
79
+ property :transport, String, :default => 'virtual', :length => 0..255
63
80
  property :backupmx, Integer, :default => 0
64
- property :description, String
81
+ property :description, String, :length => 0..255
82
+ property :active, Boolean, :default => true
65
83
  property :created, DateTime, :default => DateTime.now
66
84
  property :modified, DateTime, :default => DateTime.now
67
85
 
@@ -96,13 +114,17 @@ module PostfixAdmin
96
114
  admins.clear
97
115
  save or raise "Could not save Domain"
98
116
  end
117
+
118
+ def active_str
119
+ PostfixAdmin.flag_str(active)
120
+ end
99
121
  end
100
122
 
101
123
  class DomainAdmin
102
124
  include ::DataMapper::Resource
103
125
  property :created, DateTime, :default => DateTime.now
104
- property :domain_name, String, :field => 'domain', :key => true
105
- property :username, String, :key => true
126
+ property :domain_name, String, :field => 'domain', :key => true, :length => 0..255
127
+ property :username, String, :key => true, :length => 0..255
106
128
 
107
129
  belongs_to :domain, :model => 'Domain', :child_key => :domain_name
108
130
  belongs_to :admin, :model => 'Admin', :child_key => :username
@@ -111,19 +133,22 @@ module PostfixAdmin
111
133
 
112
134
  class Mailbox
113
135
  include ::DataMapper::Resource
114
- property :username, String, :key => true
115
- property :name, String
136
+ property :username, String, :key => true, :length => 0..255
137
+ property :name, String, :length => 0..255
116
138
  property :domain_name, String, :field => 'domain'
117
139
  property :password, String, :length => 0..255
118
- property :maildir, String
140
+ property :maildir, String, :length => 0..255
119
141
  property :quota, Integer
120
- # property :local_part, String
142
+ property :active, Boolean, :default => true
121
143
  property :created, DateTime, :default => DateTime.now
122
144
  property :modified, DateTime, :default => DateTime.now
123
145
 
124
146
  belongs_to :domain, :model => 'Domain', :child_key => :domain_name
125
147
 
126
148
  storage_names[:default] = 'mailbox'
149
+ def active_str
150
+ PostfixAdmin.flag_str(active)
151
+ end
127
152
 
128
153
  def self.find(username)
129
154
  Mailbox.first(:username => username)
@@ -136,9 +161,10 @@ module PostfixAdmin
136
161
 
137
162
  class Alias
138
163
  include ::DataMapper::Resource
139
- property :address, String, :key => true
164
+ property :address, String, :key => true, :length => 0..255
140
165
  property :goto, Text
141
- property :domain_name, String, :field => 'domain'
166
+ property :domain_name, String, :field => 'domain', :length => 0..255
167
+ property :active, Boolean, :default => true
142
168
  property :created, DateTime, :default => DateTime.now
143
169
  property :modified, DateTime, :default => DateTime.now
144
170
 
@@ -146,6 +172,10 @@ module PostfixAdmin
146
172
 
147
173
  storage_names[:default] = 'alias'
148
174
 
175
+ def active_str
176
+ PostfixAdmin.flag_str(active)
177
+ end
178
+
149
179
  def self.mailbox(address)
150
180
  mail_alias = Alias.new
151
181
  mail_alias.attributes = {