postfix_admin 0.2.1 → 0.3.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.
@@ -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