postfix_admin 0.1.1 → 0.1.2

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