postfix_admin 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,46 +8,41 @@ module PostfixAdmin
8
8
  attr_reader :config
9
9
 
10
10
  DEFAULT_CONFIG = {
11
- 'database' => 'mysql2://postfix:password@localhost/postfix',
12
- 'aliases' => 30,
13
- 'mailboxes' => 30,
14
- 'maxquota' => 100,
15
- 'scheme' => 'CRAM-MD5',
16
- 'passwordhash_prefix' => true
17
- }
11
+ "database" => "mysql2://postfix:password@localhost/postfix",
12
+ "aliases" => 30,
13
+ "mailboxes" => 30,
14
+ "maxquota" => 100,
15
+ "scheme" => "CRAM-MD5",
16
+ "passwordhash_prefix" => true
17
+ }.freeze
18
18
 
19
19
  def initialize(config)
20
20
  @config = {}
21
- @config[:database] = config['database']
22
- @config[:aliases] = config['aliases'] || 30
23
- @config[:mailboxes] = config['mailboxes'] || 30
24
- @config[:maxquota] = config['maxquota'] || 100
25
- @config[:scheme] = config['scheme'] || 'CRAM-MD5'
26
- @config[:passwordhash_prefix] = if config['passwordhash_prefix'].nil?
27
- true
21
+ @config[:database] = config["database"]
22
+ @config[:aliases] = config["aliases"] || DEFAULT_CONFIG["aliases"]
23
+ @config[:mailboxes] = config["mailboxes"] || DEFAULT_CONFIG["mailboxes"]
24
+ @config[:maxquota] = config["maxquota"] || DEFAULT_CONFIG["maxquota"]
25
+ @config[:scheme] = config["scheme"] || DEFAULT_CONFIG["scheme"]
26
+ @config[:passwordhash_prefix] = if config.has_key?("passwordhash_prefix")
27
+ config["passwordhash_prefix"]
28
28
  else
29
- config['passwordhash_prefix']
29
+ DEFAULT_CONFIG["passwordhash_prefix"]
30
30
  end
31
31
  end
32
32
 
33
33
  def db_setup
34
- raise "'database' parameter is required in '#{CLI.config_file}'" unless @config[:database]
34
+ database = ENV.fetch("DATABASE_URL") { @config[:database] }
35
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}'")
36
+ unless database
37
+ raise_error "'database' parameter is required in '#{CLI.config_file}' or specify 'DATABASE_URL' environment variable"
41
38
  end
42
39
 
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
40
+ uri = URI.parse(database)
46
41
 
47
42
  ActiveRecord::Base.establish_connection(uri.to_s)
48
43
 
49
44
  rescue LoadError => e
50
- raise e.message
45
+ raise_error e.message
51
46
  end
52
47
 
53
48
  def add_admin_domain(user_name, domain_name)
@@ -57,11 +52,11 @@ module PostfixAdmin
57
52
  domain = Domain.find(domain_name)
58
53
 
59
54
  if admin.has_domain?(domain)
60
- raise Error, "#{user_name} is already registered as admin of #{domain_name}."
55
+ raise_error "Admin '#{user_name}' has already been registered for Domain '#{domain_name}'"
61
56
  end
62
57
 
63
58
  admin.rel_domains << domain
64
- admin.save or raise "Relation Error: Domain of Admin"
59
+ admin.save || raise_error("Relation Error: Domain of Admin")
65
60
  end
66
61
 
67
62
  def delete_admin_domain(user_name, domain_name)
@@ -71,135 +66,116 @@ module PostfixAdmin
71
66
  domain_admin_query = admin.domain_admins.where(domain: domain_name)
72
67
 
73
68
  unless domain_admin_query.take
74
- raise Error, "#{user_name} is not registered as admin of #{domain_name}."
69
+ raise_error "#{user_name} is not registered as admin of #{domain_name}."
75
70
  end
76
71
 
77
72
  domain_admin_query.delete_all
78
73
  end
79
74
 
80
75
  def add_admin(username, password)
81
- password_check(password)
76
+ validate_password(password)
82
77
 
83
78
  if Admin.exists?(username)
84
- raise Error, "#{username} is already registered as admin."
79
+ raise_error "Admin has already been registered: #{username}"
85
80
  end
81
+
86
82
  admin = Admin.new
87
83
  admin.attributes = {
88
84
  username: username,
89
- password: password,
85
+ password: password
90
86
  }
91
- unless admin.save
92
- raise "Could not save Admin #{admin.errors.map(&:to_s).join}"
93
- end
94
- end
95
-
96
- def add_account(address, password, in_name = nil)
97
- name = in_name || ''
98
- password_check(password)
99
-
100
- if address !~ /.+\@.+\..+/
101
- raise Error, "Invalid mail address #{address}"
102
- end
103
- user, domain_name = address_split(address)
104
- path = "#{domain_name}/#{address}/"
105
87
 
106
- unless Domain.exists?(domain_name)
107
- raise Error, "Could not find domain #{domain_name}"
108
- end
88
+ raise_save_error(admin) unless admin.save
89
+ end
109
90
 
110
- if Alias.exists?(address)
111
- raise Error, "#{address} is already registered."
112
- end
91
+ # Adds an email account that consists of a Mailbox and an Alias.
92
+ def add_account(address, password, name: "")
93
+ validate_account(address, password)
113
94
 
114
- domain = Domain.find(domain_name)
95
+ local_part, domain_name = address_split(address)
96
+ domain_must_exist!(domain_name)
115
97
 
116
98
  attributes = {
117
- username: address,
118
- password: password,
119
- name: name,
120
- maildir: path,
121
- local_part: user,
122
- quota_mb: @config[:maxquota]
99
+ local_part: local_part,
100
+ domain: domain_name,
101
+ password: password,
102
+ name: name,
103
+ quota_mb: @config[:maxquota]
123
104
  }
124
105
 
106
+ # An Alias also will be added when a Mailbox is saved.
125
107
  mailbox = Mailbox.new(attributes)
126
108
 
127
- domain.rel_mailboxes << mailbox
128
-
129
- unless domain.save
130
- raise "Could not save Mailbox and Domain #{mailbox.errors.map(&:to_s).join} #{domain.errors.map(&:to_s).join}"
131
- end
109
+ raise_save_error(mailbox) unless mailbox.save
132
110
  end
133
111
 
134
112
  def add_alias(address, goto)
135
113
  if Mailbox.exists?(address)
136
- raise Error, "mailbox #{address} is already registered!"
137
- end
138
- if Alias.exists?(address)
139
- raise Error, "alias #{address} is already registered!"
114
+ raise_error "Mailbox has already been registered: #{address}"
140
115
  end
141
116
 
142
- local_part, domain_name = address_split(address)
117
+ alias_must_not_exist!(address)
143
118
 
144
- unless Domain.exists?(domain_name)
145
- raise Error, "Invalid domain! #{domain_name}"
146
- end
119
+ local_part, domain_name = address_split(address)
147
120
 
148
- domain = Domain.find(domain_name)
121
+ domain = find_domain(domain_name)
149
122
 
150
123
  attributes = {
151
124
  local_part: local_part,
152
125
  goto: goto
153
126
  }
127
+
154
128
  domain.rel_aliases << Alias.new(attributes)
155
- domain.save or raise "Could not save Alias"
129
+
130
+ raise_save_error(domain) unless domain.save
156
131
  end
157
132
 
158
133
  def delete_alias(address)
159
134
  if Mailbox.exists?(address)
160
- raise Error, "Can not delete mailbox by delete_alias. Use delete_account"
135
+ raise_error "Can not delete mailbox by delete_alias. Use delete_account"
161
136
  end
162
137
 
163
138
  unless Alias.exists?(address)
164
- raise Error, "#{address} is not found!"
139
+ raise_error "#{address} is not found!"
165
140
  end
166
141
 
167
142
  Alias.where(address: address).delete_all
168
143
  end
169
144
 
170
- def add_domain(domain_name)
145
+ def add_domain(domain_name, description: nil)
171
146
  domain_name = domain_name.downcase
172
- if domain_name !~ /.+\..+/
173
- raise Error, "Ivalid domain! #{domain_name}"
147
+
148
+ unless valid_domain_name?(domain_name)
149
+ raise_error "Invalid domain name: #{domain_name}"
174
150
  end
151
+
175
152
  if Domain.exists?(domain_name)
176
- raise Error, "#{domain_name} is already registered!"
153
+ raise_error "Domain has already been registered: #{domain_name}"
177
154
  end
155
+
156
+ new_description = description || domain_name
157
+
178
158
  domain = Domain.new
179
159
  domain.attributes = {
180
160
  domain: domain_name,
181
- description: domain_name,
161
+ description: new_description,
182
162
  aliases: @config[:aliases],
183
163
  mailboxes: @config[:mailboxes],
184
- maxquota: @config[:maxquota],
164
+ maxquota: @config[:maxquota]
185
165
  }
186
166
  domain.save!
187
167
  end
188
168
 
189
169
  def delete_domain(domain_name)
190
170
  domain_name = domain_name.downcase
191
- unless Domain.exists?(domain_name)
192
- raise Error, "Could not find domain #{domain_name}"
193
- end
194
171
 
195
- domain = Domain.find(domain_name)
196
- domain.rel_mailboxes.delete_all
197
- domain.rel_aliases.delete_all
172
+ domain = find_domain(domain_name)
198
173
 
199
174
  admin_names = domain.admins.map(&:username)
200
175
 
201
- domain.admins.delete_all
176
+ domain.destroy!
202
177
 
178
+ # Remove admins who had the deleted domain only
203
179
  admin_names.each do |name|
204
180
  next unless Admin.exists?(name)
205
181
 
@@ -207,16 +183,14 @@ module PostfixAdmin
207
183
 
208
184
  # check if the admin is needed or not
209
185
  if admin.rel_domains.empty?
210
- admin.destroy
186
+ admin.destroy!
211
187
  end
212
188
  end
213
-
214
- domain.destroy
215
189
  end
216
190
 
217
191
  def delete_admin(user_name)
218
192
  unless Admin.exists?(user_name)
219
- raise Error, "Could not find admin #{user_name}"
193
+ raise_error "Could not find admin #{user_name}"
220
194
  end
221
195
 
222
196
  admin = Admin.find(user_name)
@@ -226,26 +200,72 @@ module PostfixAdmin
226
200
 
227
201
  def delete_account(address)
228
202
  unless Alias.exists?(address) && Mailbox.exists?(address)
229
- raise Error, "Could not find account #{address}"
203
+ raise_error "Could not find account: #{address}"
230
204
  end
231
205
 
232
206
  Mailbox.where(username: address).delete_all
233
207
  Alias.where(address: address).delete_all
234
208
  end
235
209
 
210
+ private
211
+
212
+ def find_domain(domain_name)
213
+ domain_must_exist!(domain_name)
214
+ Domain.find(domain_name)
215
+ end
216
+
217
+ def raise_error(message)
218
+ raise PostfixAdmin::Error, message
219
+ end
220
+
221
+ def raise_save_error(obj)
222
+ raise_error "Failed to save #{obj.class}: #{obj.errors.full_messages.join(', ')}"
223
+ end
224
+
236
225
  def address_split(address)
237
226
  address.split('@')
238
227
  end
239
228
 
240
- private
229
+ def valid_domain_name?(domain_name)
230
+ /.+\..+/.match?(domain_name)
231
+ end
232
+
233
+ def valid_email_address?(address)
234
+ /.+@.+\..+/.match?(address)
235
+ end
236
+
237
+ def domain_must_exist!(domain_name)
238
+ unless Domain.exists?(domain_name)
239
+ raise_error "Could not find domain: #{domain_name}"
240
+ end
241
+ end
242
+
243
+ def alias_must_not_exist!(address)
244
+ if Alias.exists?(address)
245
+ raise_error "Alias has already been registered: #{address}"
246
+ end
247
+ end
241
248
 
242
249
  def admin_domain_check(user_name, domain_name)
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)
250
+ unless Admin.exists?(user_name)
251
+ raise_error "#{user_name} is not registered as admin."
252
+ end
253
+
254
+ domain_must_exist!(domain_name)
255
+ end
256
+
257
+ def validate_password(password)
258
+ raise_error "Empty password" if password.nil? || password.empty?
245
259
  end
246
260
 
247
- def password_check(password)
248
- raise Error, "Empty password" if password.nil? || password.empty?
261
+ def validate_account(address, password)
262
+ validate_password(password)
263
+
264
+ unless valid_email_address?(address)
265
+ raise_error "Invalid email address: #{address}"
266
+ end
267
+
268
+ alias_must_not_exist!(address)
249
269
  end
250
270
  end
251
271
  end