postfix_admin 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +7 -5
- data/Dockerfile +24 -0
- data/README.md +22 -15
- data/Rakefile +5 -0
- data/bin/console +18 -0
- data/docker-compose.yml +24 -0
- data/docker-entrypoint.sh +5 -0
- data/{bin → exe}/postfix_admin +1 -0
- data/lib/postfix_admin.rb +1 -1
- data/lib/postfix_admin/admin.rb +52 -0
- data/lib/postfix_admin/alias.rb +65 -0
- data/lib/postfix_admin/application_record.rb +44 -0
- data/lib/postfix_admin/base.rb +98 -88
- data/lib/postfix_admin/cli.rb +50 -46
- data/lib/postfix_admin/concerns/.keep +0 -0
- data/lib/postfix_admin/concerns/dovecot_cram_md5_password.rb +30 -0
- data/lib/postfix_admin/concerns/existing_timestamp.rb +18 -0
- data/lib/postfix_admin/domain.rb +98 -0
- data/lib/postfix_admin/domain_admin.rb +8 -0
- data/lib/postfix_admin/doveadm.rb +1 -1
- data/lib/postfix_admin/log.rb +5 -0
- data/lib/postfix_admin/mail_domain.rb +9 -0
- data/lib/postfix_admin/mailbox.rb +89 -0
- data/lib/postfix_admin/models.rb +10 -213
- data/lib/postfix_admin/quota.rb +6 -0
- data/lib/postfix_admin/runner.rb +39 -36
- data/lib/postfix_admin/version.rb +1 -1
- data/postfix_admin.gemspec +20 -13
- metadata +49 -50
- data/spec/base_spec.rb +0 -253
- data/spec/cli_spec.rb +0 -300
- data/spec/doveadm_spec.rb +0 -35
- data/spec/models_spec.rb +0 -195
- data/spec/postfix_admin.conf +0 -5
- data/spec/postfix_test.sql +0 -250
- data/spec/runner_spec.rb +0 -370
- data/spec/spec_helper.rb +0 -201
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a83f945f0f977fc80b8715b899af26d908b3d6b1169d27fae9cf92089bac5082
|
4
|
+
data.tar.gz: f8f63116ece1064079b99f986fc26778c4f4affc28ae8dbd3beca3496a595186
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22f7cc6d351d3a7e63ba95e653ac21f4b1eeebaebb5a717810477ab0d700dbb3199eeee042ca34909aee1c959bb7d27fe705d1c332895e7bb38ae0cc1f3e9120
|
7
|
+
data.tar.gz: 821bb8bac75277e3faf303f1db8292256cc9bbcf40cb2de6f63f9c3c38e40f84c5739849edc159ddec8bf262d9fa9e5ea8f9bac15e8dce37f2691f0a017e2772
|
data/.rubocop.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
* Switched its object-relational mapper from DataMapper to ActiveRecord
|
3
|
+
* Stored password hash includes scheme prefix: like `{CRAM-MD5}`, `{PLAIN}`
|
4
|
+
|
1
5
|
## 0.1.4
|
2
|
-
*
|
6
|
+
* Added "log" subcommand
|
3
7
|
|
4
8
|
## 0.1.3
|
5
9
|
* Support for activation and deactivation of domain, admin and account
|
6
|
-
*
|
10
|
+
* Added "edit_admin" subcommand
|
7
11
|
|
8
12
|
## 0.1.2
|
9
|
-
* Support password hash by doveadm (external
|
13
|
+
* Support password hash by doveadm (external subcommand)
|
10
14
|
* Show active status
|
11
15
|
* Don't show passwords using list format
|
12
16
|
|
13
17
|
## 0.1.1, release 2013-05-10
|
14
18
|
* Fixed string length of password
|
15
|
-
|
16
|
-
|
data/Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
FROM centos:8
|
2
|
+
|
3
|
+
RUN dnf -y module enable ruby:2.6 \
|
4
|
+
&& dnf -y install \
|
5
|
+
ruby ruby-devel mariadb-devel sqlite-devel gcc make redhat-rpm-config \
|
6
|
+
mariadb dovecot git \
|
7
|
+
&& dnf clean all
|
8
|
+
|
9
|
+
WORKDIR /app
|
10
|
+
|
11
|
+
COPY Gemfile postfix_admin.gemspec ./
|
12
|
+
COPY ./lib/postfix_admin/version.rb ./lib/postfix_admin/version.rb
|
13
|
+
|
14
|
+
RUN gem install bundler && bundle install
|
15
|
+
|
16
|
+
COPY spec/postfix_admin.conf /root/.postfix_admin.conf
|
17
|
+
|
18
|
+
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
19
|
+
RUN chmod +x /docker-entrypoint.sh
|
20
|
+
ENTRYPOINT ["/docker-entrypoint.sh"]
|
21
|
+
|
22
|
+
EXPOSE 80
|
23
|
+
|
24
|
+
CMD ["/sbin/init"]
|
data/README.md
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/postfix_admin.png)](https://rubygems.org/gems/postfix_admin)
|
2
2
|
|
3
|
-
#
|
3
|
+
# postfix_admin
|
4
4
|
|
5
|
-
Command Line Tools
|
5
|
+
Command Line Tools for Postfix Admin
|
6
6
|
|
7
7
|
## Description
|
8
8
|
|
9
|
-
Postfix Admin Web
|
9
|
+
* Postfix Admin (Original Web-based Application)
|
10
|
+
+ Web Site http://postfixadmin.sourceforge.net/
|
11
|
+
+ GitHub https://github.com/postfixadmin/postfixadmin
|
10
12
|
|
11
|
-
|
13
|
+
* Postfix Admin 3.2 is supported.
|
12
14
|
|
13
|
-
|
14
|
-
PostgreSQL is not supported.
|
15
|
+
* MySQL/MariaDB is supported.
|
15
16
|
|
16
|
-
|
17
|
+
* Other database engines are not supported.
|
17
18
|
|
18
19
|
## Installation
|
19
20
|
|
@@ -21,6 +22,18 @@ Install postfix_admin as:
|
|
21
22
|
|
22
23
|
$ gem install postfix_admin
|
23
24
|
|
25
|
+
Just execute `postfix_admin` command to generate your config file: `~/.postfix_admin.conf`
|
26
|
+
|
27
|
+
$ postfix_admin
|
28
|
+
|
29
|
+
Edit the file for your environment:
|
30
|
+
|
31
|
+
$ vi ~/.postfix_admin.conf
|
32
|
+
|
33
|
+
You can see domains on your host if the `database` parameter is set properly:
|
34
|
+
|
35
|
+
$ postfix_admin show
|
36
|
+
|
24
37
|
## Usage
|
25
38
|
|
26
39
|
List the postfix_admin subcommands as:
|
@@ -44,19 +57,13 @@ Commands:
|
|
44
57
|
postfix_admin dump # Dump all data
|
45
58
|
postfix_admin edit_account user@example.com # Edit an account
|
46
59
|
postfix_admin edit_admin admin@example.com # Edit an admin user
|
60
|
+
postfix_admin edit_alias alias@example.com # Edit an alias
|
47
61
|
postfix_admin edit_domain example.com # Edit a domain limitation
|
48
62
|
postfix_admin help [COMMAND] # Describe available commands or one specific command
|
63
|
+
postfix_admin log # Show action logs
|
49
64
|
postfix_admin schemes # List all supported password schemes
|
50
65
|
postfix_admin setup example.com password # Setup a domain
|
51
66
|
postfix_admin show [example.com | admin@example.com | user@example.com] # Show domains or admins or mailboxes
|
52
67
|
postfix_admin summary [example.com] # Summarize the usage of PostfixAdmin
|
53
68
|
postfix_admin version # Show postfix_admin version
|
54
69
|
```
|
55
|
-
|
56
|
-
## Contributing
|
57
|
-
|
58
|
-
1. Fork it
|
59
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
60
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
61
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
62
|
-
5. Create new Pull Request
|
data/Rakefile
CHANGED
data/bin/console
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "postfix_admin"
|
5
|
+
require "postfix_admin/cli"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
cli = PostfixAdmin::CLI.new
|
11
|
+
cli.db_setup
|
12
|
+
include PostfixAdmin
|
13
|
+
|
14
|
+
require "pry"
|
15
|
+
Pry.start
|
16
|
+
|
17
|
+
# require "irb"
|
18
|
+
# IRB.start(__FILE__)
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
version: '3.8'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build: .
|
6
|
+
tty: true
|
7
|
+
ports:
|
8
|
+
- '7080:80'
|
9
|
+
volumes:
|
10
|
+
- .:/app
|
11
|
+
- /sys/fs/cgroup:/sys/fs/cgroup:ro
|
12
|
+
tmpfs:
|
13
|
+
- /tmp
|
14
|
+
- /run
|
15
|
+
stop_signal: SIGRTMIN+3
|
16
|
+
db:
|
17
|
+
image: mariadb:10
|
18
|
+
volumes:
|
19
|
+
- ./spec/postfix.v1841.sql:/docker-entrypoint-initdb.d/postfix.sql
|
20
|
+
environment:
|
21
|
+
- MYSQL_RANDOM_ROOT_PASSWORD=yes
|
22
|
+
- MYSQL_USER=postfix
|
23
|
+
- MYSQL_PASSWORD=password
|
24
|
+
- MYSQL_DATABASE=postfix
|
data/{bin → exe}/postfix_admin
RENAMED
data/lib/postfix_admin.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'postfix_admin/concerns/dovecot_cram_md5_password'
|
2
|
+
|
3
|
+
module PostfixAdmin
|
4
|
+
class Admin < ApplicationRecord
|
5
|
+
self.table_name = :admin
|
6
|
+
self.primary_key = :username
|
7
|
+
|
8
|
+
include DovecotCramMD5Password
|
9
|
+
|
10
|
+
validates :username, presence: true, uniqueness: { case_sensitive: false },
|
11
|
+
format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
|
12
|
+
message: "must be a valid email address" }
|
13
|
+
|
14
|
+
has_many :domain_admins, foreign_key: :username, dependent: :delete_all
|
15
|
+
has_many :rel_domains, through: :domain_admins
|
16
|
+
|
17
|
+
attr_accessor :domain_ids
|
18
|
+
attribute :form_super_admin, :boolean, default: false
|
19
|
+
|
20
|
+
# just in case
|
21
|
+
validate on: :update do |admin|
|
22
|
+
admin.errors.add(:username, 'cannot be changed') if admin.username_changed?
|
23
|
+
end
|
24
|
+
|
25
|
+
def super_admin?
|
26
|
+
if @super_admin.nil?
|
27
|
+
@super_admin = rel_domains.exists?("ALL")
|
28
|
+
else
|
29
|
+
@super_admin
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def super_admin=(value)
|
34
|
+
if value
|
35
|
+
domain_ids = self.rel_domain_ids.dup
|
36
|
+
domain_ids << "ALL"
|
37
|
+
self.rel_domain_ids = domain_ids
|
38
|
+
save!
|
39
|
+
else
|
40
|
+
domain_admins.where(domain: "ALL").delete_all
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_admin?(admin)
|
45
|
+
self == admin || super_admin?
|
46
|
+
end
|
47
|
+
|
48
|
+
def has_domain?(domain)
|
49
|
+
!rel_domains.where(domain: ["ALL", domain.domain]).empty?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module PostfixAdmin
|
2
|
+
class Alias < ApplicationRecord
|
3
|
+
self.table_name = :alias
|
4
|
+
self.primary_key = :address
|
5
|
+
|
6
|
+
validate on: :create do |a|
|
7
|
+
domain = a.rel_domain
|
8
|
+
if domain.aliases.zero? || a.mailbox
|
9
|
+
elsif domain.rel_aliases.pure.count >= domain.aliases
|
10
|
+
message = "already has the maximum number of aliases " \
|
11
|
+
"(maximum is #{domain.aliases} aliases)"
|
12
|
+
a.errors.add(:domain, message)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
validates :address, presence: true, uniqueness: { case_sensitive: false },
|
17
|
+
format: { with: RE_EMAIL_LIKE_WITH_ANCHORS,
|
18
|
+
message: "must be a valid email address" }
|
19
|
+
validates :goto, presence: true
|
20
|
+
|
21
|
+
belongs_to :rel_domain, class_name: "Domain", foreign_key: :domain
|
22
|
+
belongs_to :mailbox, foreign_key: :address, optional: true
|
23
|
+
|
24
|
+
scope :pure, -> { joins("LEFT OUTER JOIN mailbox ON alias.address = mailbox.username").where("mailbox.username" => nil) }
|
25
|
+
|
26
|
+
attribute :local_part, :string
|
27
|
+
attr_writer :forward_addresses
|
28
|
+
|
29
|
+
def forward_addresses
|
30
|
+
if @forward_addresses.nil?
|
31
|
+
if goto.nil?
|
32
|
+
[nil]
|
33
|
+
else
|
34
|
+
goto.split(",") + [nil]
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@forward_addresses
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
before_validation do |a|
|
42
|
+
unless a.address
|
43
|
+
a.address = "#{a.local_part}@#{a.domain}" unless a.local_part.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
unless a.forward_addresses.empty?
|
47
|
+
forward_addresses = a.forward_addresses.dup
|
48
|
+
forward_addresses.delete_if { |f| f.blank? }
|
49
|
+
a.goto = forward_addresses.join(",")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def mailbox?
|
54
|
+
!!mailbox
|
55
|
+
end
|
56
|
+
|
57
|
+
def pure_alias?
|
58
|
+
!mailbox
|
59
|
+
end
|
60
|
+
|
61
|
+
def gotos
|
62
|
+
goto.split(",")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'postfix_admin/concerns/existing_timestamp'
|
3
|
+
|
4
|
+
module PostfixAdmin
|
5
|
+
class ApplicationRecord < ActiveRecord::Base
|
6
|
+
self.abstract_class = true
|
7
|
+
|
8
|
+
include ExistingTimestamp
|
9
|
+
|
10
|
+
RE_DOMAIN_NAME_LIKE_BASE = '([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}'
|
11
|
+
RE_EMAIL_LIKE_BASE = '[^@\s]+@([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}'
|
12
|
+
|
13
|
+
RE_DOMAIN_NAME_LIKE = /#{RE_DOMAIN_NAME_LIKE_BASE}/
|
14
|
+
RE_EMAIL_LIKE = /#{RE_EMAIL_LIKE_BASE}/
|
15
|
+
|
16
|
+
RE_DOMAIN_NAME_LIKE_WITH_ANCHORS = /\A#{RE_DOMAIN_NAME_LIKE_BASE}\z/
|
17
|
+
RE_EMAIL_LIKE_WITH_ANCHORS = /\A#{RE_EMAIL_LIKE_BASE}\z/
|
18
|
+
|
19
|
+
scope :active, -> { where(active: true) }
|
20
|
+
|
21
|
+
def inactive?
|
22
|
+
!active?
|
23
|
+
end
|
24
|
+
|
25
|
+
def active_str
|
26
|
+
active? ? "Active" : "Inactive"
|
27
|
+
end
|
28
|
+
|
29
|
+
# This is a workaround to set current time to timestamp columns when a record is created.
|
30
|
+
# Activerecord does not insert timestamps if default values are set for the columns.
|
31
|
+
before_create :set_current_time_to_timestamp_columns, if: :has_timestamp_columns?
|
32
|
+
|
33
|
+
def set_current_time_to_timestamp_columns
|
34
|
+
now = Time.now
|
35
|
+
self.created = now
|
36
|
+
self.modified = now
|
37
|
+
end
|
38
|
+
|
39
|
+
def has_timestamp_columns?
|
40
|
+
column_names = self.class.column_names
|
41
|
+
column_names.include?("created") && column_names.include?("modified")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/postfix_admin/base.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
|
-
require 'postfix_admin/models'
|
2
1
|
require 'postfix_admin/error'
|
3
2
|
|
4
3
|
require 'date'
|
5
|
-
require '
|
4
|
+
require 'postfix_admin/models'
|
6
5
|
|
7
6
|
module PostfixAdmin
|
8
7
|
class Base
|
9
8
|
attr_reader :config
|
10
9
|
|
11
10
|
DEFAULT_CONFIG = {
|
12
|
-
'database' => '
|
11
|
+
'database' => 'mysql2://postfix:password@localhost/postfix',
|
13
12
|
'aliases' => 30,
|
14
13
|
'mailboxes' => 30,
|
15
14
|
'maxquota' => 100,
|
@@ -17,71 +16,78 @@ module PostfixAdmin
|
|
17
16
|
}
|
18
17
|
|
19
18
|
def initialize(config)
|
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
|
29
19
|
@config = {}
|
20
|
+
@config[:database] = config['database']
|
30
21
|
@config[:aliases] = config['aliases'] || 30
|
31
22
|
@config[:mailboxes] = config['mailboxes'] || 30
|
32
23
|
@config[:maxquota] = config['maxquota'] || 100
|
33
|
-
@config[:mailbox_quota] = @config[:maxquota] * KB_TO_MB
|
34
24
|
@config[:scheme] = config['scheme'] || 'CRAM-MD5'
|
35
25
|
end
|
36
26
|
|
37
|
-
def db_setup
|
38
|
-
|
39
|
-
|
27
|
+
def db_setup
|
28
|
+
raise "'database' parameter is required in '#{CLI.config_file}'" unless @config[:database]
|
29
|
+
|
30
|
+
uri = URI.parse(@config[:database])
|
31
|
+
|
32
|
+
if uri.scheme == "mysql"
|
33
|
+
uri.scheme = "mysql2"
|
34
|
+
warn("Deprecation Warning: Use 'mysql2' as a DB adopter instead of 'mysql' in '#{CLI.config_file}'")
|
35
|
+
end
|
36
|
+
|
37
|
+
if uri.scheme != "mysql2"
|
38
|
+
raise "'#{uri.scheme}' is not supported as a DB adopter. Use 'mysql2' instead in '#{CLI.config_file}'."
|
39
|
+
end
|
40
|
+
|
41
|
+
ActiveRecord::Base.establish_connection(uri.to_s)
|
42
|
+
|
43
|
+
rescue LoadError => e
|
44
|
+
raise e.message
|
40
45
|
end
|
41
46
|
|
42
47
|
def add_admin_domain(user_name, domain_name)
|
43
48
|
admin_domain_check(user_name, domain_name)
|
44
49
|
|
45
50
|
admin = Admin.find(user_name)
|
46
|
-
|
47
|
-
|
51
|
+
domain = Domain.find(domain_name)
|
52
|
+
|
53
|
+
if admin.has_domain?(domain)
|
54
|
+
raise Error, "#{user_name} is already registered as admin of #{domain_name}."
|
48
55
|
end
|
49
56
|
|
50
|
-
|
51
|
-
admin.domains << domain
|
57
|
+
admin.rel_domains << domain
|
52
58
|
admin.save or raise "Relation Error: Domain of Admin"
|
53
59
|
end
|
54
60
|
|
55
61
|
def delete_admin_domain(user_name, domain_name)
|
56
62
|
admin_domain_check(user_name, domain_name)
|
57
63
|
|
58
|
-
admin
|
59
|
-
|
60
|
-
|
64
|
+
admin = Admin.find(user_name)
|
65
|
+
domain_admin_query = admin.domain_admins.where(domain: domain_name)
|
66
|
+
|
67
|
+
unless domain_admin_query.take
|
68
|
+
raise Error, "#{user_name} is not registered as admin of #{domain_name}."
|
61
69
|
end
|
62
70
|
|
63
|
-
|
64
|
-
admin.domains.delete(domain)
|
65
|
-
admin.save or "Could not save Admin"
|
71
|
+
domain_admin_query.delete_all
|
66
72
|
end
|
67
73
|
|
68
74
|
def add_admin(username, password)
|
69
75
|
password_check(password)
|
70
76
|
|
71
|
-
if Admin.
|
72
|
-
raise Error, "#{username} is already
|
77
|
+
if Admin.exists?(username)
|
78
|
+
raise Error, "#{username} is already registered as admin."
|
73
79
|
end
|
74
80
|
admin = Admin.new
|
75
81
|
admin.attributes = {
|
76
|
-
:
|
77
|
-
:
|
82
|
+
username: username,
|
83
|
+
password: password,
|
78
84
|
}
|
79
85
|
unless admin.save
|
80
|
-
raise "Could not save Admin #{admin.errors.map
|
86
|
+
raise "Could not save Admin #{admin.errors.map(&:to_s).join}"
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
84
|
-
def add_account(address, password, in_name=nil)
|
90
|
+
def add_account(address, password, in_name = nil)
|
85
91
|
name = in_name || ''
|
86
92
|
password_check(password)
|
87
93
|
|
@@ -91,68 +97,68 @@ EOS
|
|
91
97
|
user, domain_name = address_split(address)
|
92
98
|
path = "#{domain_name}/#{address}/"
|
93
99
|
|
94
|
-
unless Domain.
|
100
|
+
unless Domain.exists?(domain_name)
|
95
101
|
raise Error, "Could not find domain #{domain_name}"
|
96
102
|
end
|
97
103
|
|
98
|
-
if Alias.
|
99
|
-
raise Error, "#{address} is already
|
104
|
+
if Alias.exists?(address)
|
105
|
+
raise Error, "#{address} is already registered."
|
100
106
|
end
|
101
107
|
|
102
108
|
domain = Domain.find(domain_name)
|
103
|
-
domain.aliases << Alias.mailbox(address)
|
104
109
|
|
105
|
-
mailbox = Mailbox.new
|
106
110
|
attributes = {
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
111
|
+
username: address,
|
112
|
+
password: password,
|
113
|
+
name: name,
|
114
|
+
maildir: path,
|
115
|
+
local_part: user,
|
116
|
+
quota_mb: @config[:maxquota]
|
112
117
|
}
|
113
118
|
|
114
|
-
|
115
|
-
attributes[:local_part] = user
|
116
|
-
end
|
119
|
+
mailbox = Mailbox.new(attributes)
|
117
120
|
|
118
|
-
|
121
|
+
domain.rel_mailboxes << mailbox
|
119
122
|
|
120
|
-
domain.mailboxes << mailbox
|
121
123
|
unless domain.save
|
122
|
-
raise "Could not save Mailbox and Domain #{mailbox.errors.map
|
124
|
+
raise "Could not save Mailbox and Domain #{mailbox.errors.map(&:to_s).join} #{domain.errors.map(&:to_s).join}"
|
123
125
|
end
|
124
126
|
end
|
125
127
|
|
126
128
|
def add_alias(address, goto)
|
127
|
-
if Mailbox.
|
129
|
+
if Mailbox.exists?(address)
|
128
130
|
raise Error, "mailbox #{address} is already registered!"
|
129
131
|
end
|
130
|
-
if Alias.
|
132
|
+
if Alias.exists?(address)
|
131
133
|
raise Error, "alias #{address} is already registered!"
|
132
134
|
end
|
133
|
-
|
134
|
-
|
135
|
+
|
136
|
+
local_part, domain_name = address_split(address)
|
137
|
+
|
138
|
+
unless Domain.exists?(domain_name)
|
135
139
|
raise Error, "Invalid domain! #{domain_name}"
|
136
140
|
end
|
141
|
+
|
137
142
|
domain = Domain.find(domain_name)
|
138
143
|
|
139
|
-
|
140
|
-
|
141
|
-
:
|
142
|
-
:goto => goto,
|
144
|
+
attributes = {
|
145
|
+
local_part: local_part,
|
146
|
+
goto: goto
|
143
147
|
}
|
144
|
-
domain.
|
148
|
+
domain.rel_aliases << Alias.new(attributes)
|
145
149
|
domain.save or raise "Could not save Alias"
|
146
150
|
end
|
147
151
|
|
148
152
|
def delete_alias(address)
|
149
|
-
if Mailbox.
|
153
|
+
if Mailbox.exists?(address)
|
150
154
|
raise Error, "Can not delete mailbox by delete_alias. Use delete_account"
|
151
155
|
end
|
152
|
-
|
156
|
+
|
157
|
+
unless Alias.exists?(address)
|
153
158
|
raise Error, "#{address} is not found!"
|
154
159
|
end
|
155
|
-
|
160
|
+
|
161
|
+
Alias.where(address: address).delete_all
|
156
162
|
end
|
157
163
|
|
158
164
|
def add_domain(domain_name)
|
@@ -160,56 +166,65 @@ EOS
|
|
160
166
|
if domain_name !~ /.+\..+/
|
161
167
|
raise Error, "Ivalid domain! #{domain_name}"
|
162
168
|
end
|
163
|
-
if Domain.
|
169
|
+
if Domain.exists?(domain_name)
|
164
170
|
raise Error, "#{domain_name} is already registered!"
|
165
171
|
end
|
166
172
|
domain = Domain.new
|
167
173
|
domain.attributes = {
|
168
|
-
:
|
169
|
-
:
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:
|
174
|
+
domain: domain_name,
|
175
|
+
description: domain_name,
|
176
|
+
aliases: @config[:aliases],
|
177
|
+
mailboxes: @config[:mailboxes],
|
178
|
+
maxquota: @config[:maxquota],
|
173
179
|
}
|
174
|
-
domain.save
|
180
|
+
domain.save!
|
175
181
|
end
|
176
182
|
|
177
183
|
def delete_domain(domain_name)
|
178
184
|
domain_name = domain_name.downcase
|
179
|
-
unless Domain.
|
185
|
+
unless Domain.exists?(domain_name)
|
180
186
|
raise Error, "Could not find domain #{domain_name}"
|
181
187
|
end
|
182
188
|
|
183
189
|
domain = Domain.find(domain_name)
|
184
|
-
domain.
|
185
|
-
domain.
|
186
|
-
|
187
|
-
domain.
|
190
|
+
domain.rel_mailboxes.delete_all
|
191
|
+
domain.rel_aliases.delete_all
|
192
|
+
|
193
|
+
admin_names = domain.admins.map(&:username)
|
194
|
+
|
195
|
+
domain.admins.delete_all
|
188
196
|
|
189
197
|
admin_names.each do |name|
|
190
|
-
next unless Admin.
|
198
|
+
next unless Admin.exists?(name)
|
199
|
+
|
191
200
|
admin = Admin.find(name)
|
192
|
-
|
201
|
+
|
202
|
+
# check if the admin is needed or not
|
203
|
+
if admin.rel_domains.empty?
|
204
|
+
admin.destroy
|
205
|
+
end
|
193
206
|
end
|
194
|
-
|
207
|
+
|
208
|
+
domain.destroy
|
195
209
|
end
|
196
210
|
|
197
211
|
def delete_admin(user_name)
|
198
|
-
unless Admin.
|
212
|
+
unless Admin.exists?(user_name)
|
199
213
|
raise Error, "Could not find admin #{user_name}"
|
200
214
|
end
|
215
|
+
|
201
216
|
admin = Admin.find(user_name)
|
202
|
-
admin.
|
203
|
-
admin.destroy
|
217
|
+
admin.rel_domains.delete_all
|
218
|
+
admin.destroy!
|
204
219
|
end
|
205
220
|
|
206
221
|
def delete_account(address)
|
207
|
-
unless Alias.
|
222
|
+
unless Alias.exists?(address) && Mailbox.exists?(address)
|
208
223
|
raise Error, "Could not find account #{address}"
|
209
224
|
end
|
210
225
|
|
211
|
-
Mailbox.
|
212
|
-
Alias.
|
226
|
+
Mailbox.where(username: address).delete_all
|
227
|
+
Alias.where(address: address).delete_all
|
213
228
|
end
|
214
229
|
|
215
230
|
def address_split(address)
|
@@ -218,14 +233,9 @@ EOS
|
|
218
233
|
|
219
234
|
private
|
220
235
|
|
221
|
-
# postfixadmin DB upgrade Number 495 loca_part added
|
222
|
-
def local_part_required?
|
223
|
-
Config.first.value.to_i >= 495
|
224
|
-
end
|
225
|
-
|
226
236
|
def admin_domain_check(user_name, domain_name)
|
227
|
-
raise Error, "#{user_name} is not
|
228
|
-
raise Error, "Could not find domain #{domain_name}" unless Domain.
|
237
|
+
raise Error, "#{user_name} is not registered as admin." unless Admin.exists?(user_name)
|
238
|
+
raise Error, "Could not find domain #{domain_name}" unless Domain.exists?(domain_name)
|
229
239
|
end
|
230
240
|
|
231
241
|
def password_check(password)
|