postfix_admin 0.1.1 → 0.2.1

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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +2 -0
  5. data/CHANGELOG.md +22 -0
  6. data/README.md +47 -32
  7. data/Rakefile +6 -0
  8. data/bin/console +18 -0
  9. data/docker-admin/Dockerfile +6 -0
  10. data/docker-admin/config.local.php +21 -0
  11. data/docker-app-2.5/Dockerfile +15 -0
  12. data/docker-app/Dockerfile +25 -0
  13. data/docker-app/docker-entrypoint.sh +5 -0
  14. data/docker-app/my.cnf +5 -0
  15. data/docker-compose.yml +46 -0
  16. data/docker-db/postfix.v1841.sql +383 -0
  17. data/{spec/postfix_test.sql → docker-db/postfix.v352.sql} +1 -28
  18. data/docker-db/postfix.v740.sql +269 -0
  19. data/{bin → exe}/postfix_admin +1 -0
  20. data/lib/postfix_admin.rb +1 -1
  21. data/lib/postfix_admin/admin.rb +62 -0
  22. data/lib/postfix_admin/alias.rb +65 -0
  23. data/lib/postfix_admin/application_record.rb +44 -0
  24. data/lib/postfix_admin/base.rb +120 -75
  25. data/lib/postfix_admin/cli.rb +173 -58
  26. data/lib/postfix_admin/concerns/.keep +0 -0
  27. data/lib/postfix_admin/concerns/dovecot_cram_md5_password.rb +30 -0
  28. data/lib/postfix_admin/concerns/existing_timestamp.rb +18 -0
  29. data/lib/postfix_admin/domain.rb +98 -0
  30. data/lib/postfix_admin/domain_admin.rb +8 -0
  31. data/lib/postfix_admin/doveadm.rb +37 -0
  32. data/lib/postfix_admin/log.rb +5 -0
  33. data/lib/postfix_admin/mail_domain.rb +9 -0
  34. data/lib/postfix_admin/mailbox.rb +89 -0
  35. data/lib/postfix_admin/models.rb +10 -170
  36. data/lib/postfix_admin/quota.rb +6 -0
  37. data/lib/postfix_admin/runner.rb +108 -36
  38. data/lib/postfix_admin/version.rb +1 -1
  39. data/postfix_admin.gemspec +22 -12
  40. metadata +80 -55
  41. data/spec/base_spec.rb +0 -235
  42. data/spec/cli_spec.rb +0 -286
  43. data/spec/models_spec.rb +0 -146
  44. data/spec/postfix_admin.conf +0 -5
  45. data/spec/runner_spec.rb +0 -194
  46. data/spec/spec_helper.rb +0 -159
@@ -1,146 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
- require 'postfix_admin/models'
3
-
4
- describe PostfixAdmin::Admin do
5
- before do
6
- db_initialize
7
- end
8
-
9
- it ".exist?" do
10
- Admin.exist?('admin@example.com').should === true
11
- Admin.exist?('all@example.com').should === true
12
- Admin.exist?('unknown@example.com').should === false
13
- end
14
-
15
- it "#super_admin?" do
16
- Admin.find('admin@example.com').super_admin?.should === false
17
- Admin.find('all@example.com').super_admin?.should === true
18
- end
19
-
20
- describe "#super_admin=" do
21
- it "enable super admin flag" do
22
- lambda{ Admin.find('all@example.com').super_admin = false }.should_not raise_error
23
- Admin.find('all@example.com').super_admin?.should === false
24
- end
25
-
26
- it "should not delete 'ALL' domain" do
27
- Admin.find('all@example.com').super_admin = false
28
- Domain.exist?('ALL').should be_true
29
- end
30
-
31
- it "disable super admin flag" do
32
- lambda{ Admin.find('admin@example.com').super_admin = true }.should_not raise_error
33
- Admin.find('admin@example.com').super_admin?.should === true
34
- end
35
- end
36
-
37
- describe "#has_domain?" do
38
- it "returns true when the admin has privileges for the domain" do
39
- Admin.find('admin@example.com').has_domain?('example.com').should === true
40
- end
41
-
42
- it "returns false when the admin does not have privileges for the domain" do
43
- Admin.find('admin@example.com').has_domain?('example.org').should === false
44
- end
45
-
46
- it "returns false when unknown domain" do
47
- Admin.find('admin@example.com').has_domain?('unknown.example.com').should === false
48
- end
49
-
50
- it "returns true when super admin and exist domain" do
51
- Admin.find('all@example.com').has_domain?('example.com').should === true
52
- end
53
-
54
- it "returns false when super admin and unknown domain" do
55
- Admin.find('all@example.com').has_domain?('unknown.example.com').should === false
56
- end
57
- end
58
- end
59
-
60
- describe PostfixAdmin::Domain do
61
- before do
62
- db_initialize
63
- @base = PostfixAdmin::Base.new({'database' => 'sqlite::memory:'})
64
- end
65
-
66
- it ".exist?" do
67
- Domain.exist?('example.com').should === true
68
- Domain.exist?('example.org').should === true
69
- Domain.exist?('unknown.example.com').should === false
70
- end
71
-
72
- describe "#num_total_aliases and .num_total_aliases" do
73
- it "when only alias@example.com" do
74
- Domain.num_total_aliases.should be(1)
75
- Domain.find('example.com').num_total_aliases.should be(1)
76
- end
77
-
78
- it "should increase one if you add an alias" do
79
- @base.add_alias('new_alias@example.com', 'goto@example.jp')
80
- Domain.num_total_aliases.should be(2)
81
- Domain.find('example.com').num_total_aliases.should be(2)
82
- end
83
-
84
- it "should not increase if you add an account" do
85
- @base.add_account('user2@example.com', 'password')
86
- Domain.num_total_aliases.should be(1)
87
- Domain.find('example.com').num_total_aliases.should be(1)
88
- end
89
-
90
- it ".num_total_aliases should not increase if you add an account and an aliase for other domain" do
91
- @base.add_account('user@example.org', 'password')
92
- Domain.num_total_aliases.should be(1)
93
- Domain.find('example.com').num_total_aliases.should be(1)
94
- @base.add_alias('new_alias@example.org', 'goto@example.jp')
95
- Domain.num_total_aliases.should be(2)
96
- Domain.find('example.com').num_total_aliases.should be(1)
97
- end
98
- end
99
- end
100
-
101
- describe PostfixAdmin::Mailbox do
102
- before do
103
- db_initialize
104
- end
105
-
106
- describe ".exist?" do
107
- it "returns true for exist account (mailbox)" do
108
- Mailbox.exist?('user@example.com').should === true
109
- end
110
-
111
- it "returns false for alias" do
112
- Mailbox.exist?('alias@example.com').should === false
113
- end
114
-
115
- it "returns false for unknown account (mailbox)" do
116
- Mailbox.exist?('unknown@unknown.example.com').should === false
117
- end
118
- end
119
- end
120
-
121
- describe PostfixAdmin::Alias do
122
- before do
123
- db_initialize
124
- end
125
-
126
- describe ".exist?" do
127
- it "returns true when exist alias and account" do
128
- Alias.exist?('user@example.com').should === true
129
- Alias.exist?('alias@example.com').should === true
130
- end
131
-
132
- it "returns false when unknown alias" do
133
- Alias.exist?('unknown@unknown.example.com').should === false
134
- end
135
- end
136
-
137
- describe ".mailbox?" do
138
- it "when there is same address in maiboxes returns true" do
139
- Alias.find('user@example.com').mailbox?.should === true
140
- end
141
-
142
- it "when there is no same address in maiboxes returns false" do
143
- Alias.find('alias@example.com').mailbox?.should === false
144
- end
145
- end
146
- end
@@ -1,5 +0,0 @@
1
- ---
2
- database: 'sqlite::memory:'
3
- aliases: 30
4
- mailboxes: 30
5
- maxquota: 100
@@ -1,194 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
- require 'postfix_admin/runner'
3
-
4
- describe PostfixAdmin::Runner do
5
- before do
6
- db_initialize
7
- end
8
-
9
- it "version" do
10
- capture(:stdout){ Runner.start(["version"]) }.should =~ /postfix_admin \d+\.\d+\.\d/
11
- end
12
-
13
- it "summary" do
14
- capture(:stdout){ Runner.start(["summary"]) }.should =~ /\[Summary\]/
15
- capture(:stdout){ Runner.start(["summary", "example.com"]) }.should =~ /\[Summary of example.com\]/
16
- end
17
-
18
- describe "show" do
19
- it "shows information of example.com" do
20
- capture(:stdout){ Runner.start(["show"]) }.should =~ /example.com\s+1\s+\/\s+30\s+1\s+\/\s+30\s+100/
21
- end
22
-
23
- it "shows information of admin@example.com" do
24
- capture(:stdout){ Runner.start(["show"]) }.should =~ /admin@example.com\s+1\s+password/
25
- end
26
-
27
- it "show the detail of example.com" do
28
- capture(:stdout){ Runner.start(["show", "example.com"]) }.should =~ /user@example.com\s+100\s+password/
29
- end
30
-
31
- it "when no admins, no aliases and no addresses" do
32
- Admin.find('all@example.com').super_admin = false
33
- out = capture(:stdout){ Runner.start(["show", "example.org"]) }
34
- out.should =~ /No admins/
35
- out.should =~ /No addresses/
36
- out.should =~ /No aliases/
37
- end
38
-
39
- it "shows information of an account" do
40
- capture(:stdout){ Runner.start(["show", "user@example.com"]) }.should =~ /user@example.com/
41
- end
42
-
43
- it "when no domains" do
44
- capture(:stdout){ Runner.start(['delete_domain', 'example.com']) }.should =~ EX_DELETED
45
- capture(:stdout){ Runner.start(['delete_domain', 'example.org']) }.should =~ EX_DELETED
46
- capture(:stdout){ Runner.start(["show"]) }.should =~ /No domains/
47
- end
48
- end
49
-
50
- it "setup" do
51
- capture(:stdout){ Runner.start(['setup', 'example.net', 'password']) }.should =~ EX_REGISTERED
52
- capture(:stdout){ Runner.start(['delete_domain', 'example.net']) }.should =~ EX_DELETED
53
- end
54
-
55
- describe "super_admin" do
56
- it "can enable super admin flag of an admin" do
57
- capture(:stdout){ Runner.start(['super', 'admin@example.com']) }.should =~ /Successfully enabled/
58
- end
59
-
60
- it "can disable super admin flag of an admin (--disable)" do
61
- capture(:stdout){ Runner.start(['super', 'admin@example.com', '--disable']) }.should =~ /Successfully disabled/
62
- end
63
-
64
- it "can use -d option as --disable" do
65
- capture(:stdout){ Runner.start(['super', 'admin@example.com', '-d']) }.should =~ /Successfully disabled/
66
- end
67
- end
68
-
69
- describe "admin_passwd" do
70
- it "can change password of an admin" do
71
- capture(:stdout){ Runner.start(['admin_passwd', 'admin@example.com', 'new_password']) }.should =~ /successfully changed/
72
- end
73
-
74
- it "can not use too short password (< 5)" do
75
- capture(:stderr){ Runner.start(['admin_passwd', 'admin@example.com', '124']) }.should =~ /too short/
76
- end
77
-
78
- it "can not use for unknown admin" do
79
- capture(:stderr){ Runner.start(['admin_passwd', 'unknown@example.com', 'new_password']) }.should =~ /Could not find/
80
- end
81
- end
82
-
83
- describe "account_passwd" do
84
- it "can change password of an account" do
85
- capture(:stdout){ Runner.start(['account_passwd', 'user@example.com', 'new_password']) }.should =~ /successfully changed/
86
- end
87
-
88
- it "can not use too short password (< 5)" do
89
- capture(:stderr){ Runner.start(['account_passwd', 'user@example.com', '1234']) }.should =~ /too short/
90
- end
91
-
92
- it "can not use for unknown account" do
93
- capture(:stderr){ Runner.start(['account_passwd', 'unknown@example.com', 'new_password']) }.should =~ /Could not find/
94
- end
95
- end
96
-
97
- describe "add_alias and delete_alias" do
98
- it "can add and delete an new alias." do
99
- capture(:stdout){ Runner.start(['add_alias', 'new_alias@example.com', 'goto@example.jp']) }.should =~ EX_REGISTERED
100
- capture(:stdout){ Runner.start(['delete_alias', 'new_alias@example.com']) }.should =~ EX_DELETED
101
- end
102
-
103
- it "can not delete mailbox alias." do
104
- capture(:stderr){ Runner.start(['delete_alias', 'user@example.com']) }.should =~ /Can not delete mailbox/
105
- end
106
-
107
- it "can not add an alias for existed mailbox" do
108
- capture(:stderr){ Runner.start(['add_alias', 'user@example.com', 'goto@example.jp']) }.should =~ /mailbox user@example.com is already registered!/
109
- end
110
- end
111
-
112
- describe "add_admin" do
113
- it "can add an new admin" do
114
- capture(:stdout){ Runner.start(['add_admin', 'admin@example.jp', 'password']) }.should =~ EX_REGISTERED
115
- end
116
-
117
- it "can use long password" do
118
- capture(:stdout){ Runner.start(['add_admin', 'admin@example.jp', '9c5e77f2da26fc03e9fa9e13ccd77aeb50c85539a4d90b70812715aea9ebda1d']) }.should =~ EX_REGISTERED
119
- end
120
-
121
- it "--super option" do
122
- capture(:stdout){ Runner.start(['add_admin', 'admin@example.jp', 'password', '--super']) }.should =~ /registered as a super admin/
123
- end
124
-
125
- it "-s (--super) option" do
126
- capture(:stdout){ Runner.start(['add_admin', 'admin@example.jp', 'password', '-s']) }.should =~ /registered as a super admin/
127
- end
128
- end
129
-
130
- describe "edit_domain" do
131
- it "when no options, shows usage" do
132
- capture(:stderr){ Runner.start(['edit_domain', 'example.com']) }.should =~ /Use one or more options/
133
- end
134
-
135
- it "can edit limitations of domain" do
136
- capture(:stdout){ Runner.start(['edit_domain', 'example.com', '--aliases', '40', '--mailboxes', '40', '--maxquota', '400']) }.should =~ /Successfully updated/
137
- end
138
-
139
- it "aliases options -a, -m, -q" do
140
- capture(:stdout){ Runner.start(['edit_domain', 'example.com', '-a', '40', '-m', '40', '-m', '400']) }.should =~ /Successfully updated/
141
- end
142
-
143
- it "can not use unknown domain" do
144
- capture(:stderr){ Runner.start(['edit_domain', 'unknown.example.com', '--aliases', '40', '--mailboxes', '40', '--maxquota', '400'])}.should =~ /Could not find/
145
- end
146
- end
147
-
148
- describe "edit_account" do
149
- it "when no options, shows usage" do
150
- capture(:stderr){ Runner.start(['edit_account', 'user@example.com']) }.should =~ /Use one or more options/
151
- end
152
-
153
- it "can edit quota limitation" do
154
- output = capture(:stdout){ Runner.start(['edit_account', 'user@example.com', '--quota', '50'])}
155
- output.should =~ /Successfully updated/
156
- output.should =~ /Quota/
157
- end
158
-
159
- it "can use alias -q option" do
160
- capture(:stdout){ Runner.start(['edit_account', 'user@example.com', '-q', '50'])}.should =~ /Successfully updated/
161
- end
162
- end
163
-
164
- it "add_admin_domain" do
165
- capture(:stdout){ Runner.start(['add_admin_domain', 'admin@example.com', 'example.org']) }.should =~ EX_REGISTERED
166
- end
167
-
168
- it "delete_admin_domain" do
169
- capture(:stdout){ Runner.start(['delete_admin_domain', 'admin@example.com', 'example.com']) }.should =~ EX_DELETED
170
- end
171
-
172
- it "delete_admin" do
173
- capture(:stdout){ Runner.start(['delete_admin', 'admin@example.com']) }.should =~ EX_DELETED
174
- end
175
-
176
- it "add_account and delete_account" do
177
- capture(:stdout){ Runner.start(['add_account', 'user2@example.com', 'password']) }.should =~ EX_REGISTERED
178
- capture(:stdout){ Runner.start(['delete_account', 'user2@example.com']) }.should =~ EX_DELETED
179
- end
180
-
181
- it "add_account can use long passwrod" do
182
- capture(:stdout){ Runner.start(['add_account', 'user2@example.com', '9c5e77f2da26fc03e9fa9e13ccd77aeb50c85539a4d90b70812715aea9ebda1d']) }.should =~ EX_REGISTERED
183
- end
184
-
185
- it "add and delete methods" do
186
- lambda { Runner.start(['add_domain', 'example.net']) }.should_not raise_error
187
- Runner.start(['add_admin', 'admin@example.net', 'password'])
188
- Runner.start(['add_admin_domain', 'admin@example.net', 'example.net'])
189
-
190
- lambda { Runner.start(['add_account', 'user1@example.net', 'password']) }.should_not raise_error
191
- lambda { Runner.start(['add_account', 'user2@example.net', 'password']) }.should_not raise_error
192
- lambda { Runner.start(['delete_domain', 'example.net']) }.should_not raise_error
193
- end
194
- end
@@ -1,159 +0,0 @@
1
-
2
- $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
-
4
- require 'postfix_admin'
5
- require 'postfix_admin/cli'
6
-
7
-
8
- include PostfixAdmin
9
-
10
- # [fixtures]
11
- # Domain:
12
- # ALL
13
- # example.com
14
- # example.org
15
- #
16
- # Admin:
17
- # all@example.com Super Admin
18
- # admin@example.com
19
- #
20
- # Mailbox, Alias:
21
- # user@example.com
22
- #
23
- # Alias:
24
- # alias@example.com -> goto@example.jp
25
-
26
- def config_initialize
27
- CLI.config_file = File.join(File.dirname(__FILE__) , 'postfix_admin.conf')
28
- end
29
-
30
- def db_clear
31
- DomainAdmin.all.destroy
32
- Mailbox.all.destroy
33
- Alias.all.destroy
34
- Domain.all.destroy
35
- Admin.all.destroy
36
- end
37
-
38
- def create_domain(domain_name)
39
- domain = Domain.new
40
- domain.attributes = {
41
- :domain_name => domain_name,
42
- :description => domain_name,
43
- :maxaliases => 30,
44
- :maxmailboxes => 30,
45
- :maxquota => 100,
46
- }
47
- domain.save
48
- end
49
-
50
- def db_initialize
51
- db_clear
52
-
53
- create_domain('ALL')
54
- create_domain('example.com')
55
- create_domain('example.org')
56
-
57
- username = "admin@example.com"
58
- admin = Admin.new
59
- admin.attributes = {
60
- :username => username,
61
- :password => 'password',
62
- }
63
- admin.save
64
-
65
- domain = Domain.find('example.com')
66
- domain.admins << admin
67
- domain.save
68
-
69
- all_admin = Admin.new
70
- all_admin.attributes = {
71
- :username => 'all@example.com',
72
- :password => 'password',
73
- }
74
- all_admin.save
75
-
76
- all_domain = Domain.find('ALL')
77
- all_domain.admins << all_admin
78
- all_domain.save
79
-
80
- address = "user@example.com"
81
- mail_alias = Alias.new
82
- mail_alias.attributes = {
83
- :address => address,
84
- :goto => address,
85
- }
86
- domain.aliases << mail_alias
87
-
88
- forward = Alias.new
89
- forward.attributes = {
90
- :address => 'alias@example.com',
91
- :goto => 'goto@example.jp',
92
- }
93
- domain.aliases << forward
94
-
95
- domain.save
96
-
97
- path = "example.com/user@example.com/"
98
- mailbox = Mailbox.new
99
- mailbox.attributes = {
100
- :username => address,
101
- :password => 'password',
102
- :name => '',
103
- :maildir => path,
104
- :quota => 100 * KB_TO_MB,
105
- # :local_part => user,
106
- }
107
- domain.mailboxes << mailbox
108
- domain.save
109
- end
110
-
111
- DataMapper.setup(:default, 'sqlite::memory:')
112
- DataMapper.finalize
113
- DataMapper.auto_migrate!
114
- db_initialize
115
- config_initialize
116
-
117
- module PostfixAdmin
118
- class Base
119
-
120
- # without DataMapper setup
121
- def db_setup(database)
122
- unless database
123
- raise ArgumentError
124
- end
125
- end
126
- end
127
- end
128
-
129
- EX_DELETED = /successfully deleted/
130
- EX_REGISTERED = /successfully registered/
131
-
132
- RSpec.configure do |config|
133
- config.before do
134
- ARGV.replace []
135
- end
136
-
137
- def capture(stream)
138
- begin
139
- stream = stream.to_s
140
- eval "$#{stream} = StringIO.new"
141
- yield
142
- result = eval("$#{stream}").string
143
- ensure
144
- eval("$#{stream} = #{stream.upcase}")
145
- end
146
-
147
- result
148
- end
149
-
150
- def source_root
151
- File.join(File.dirname(__FILE__), 'fixtures')
152
- end
153
-
154
- def destination_root
155
- File.join(File.dirname(__FILE__), 'sandbox')
156
- end
157
-
158
- alias :silence :capture
159
- end