postfix_admin 0.1.1 → 0.2.1

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