mailshears 0.0.3 → 0.0.4
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.
- checksums.yaml +5 -5
- data/doc/TODO +19 -0
- data/lib/common/agendav_plugin.rb +2 -2
- data/lib/common/davical_plugin.rb +2 -2
- data/lib/common/postfixadmin_plugin.rb +5 -5
- data/lib/common/roundcube_plugin.rb +3 -3
- data/lib/mv/mv_runner.rb +3 -3
- data/lib/mv/plugins/agendav.rb +2 -2
- data/lib/mv/plugins/davical.rb +1 -1
- data/lib/mv/plugins/postfixadmin.rb +1 -1
- data/lib/mv/plugins/roundcube.rb +1 -1
- data/lib/rm/plugins/agendav.rb +1 -1
- data/lib/rm/plugins/davical.rb +1 -1
- data/lib/rm/plugins/postfixadmin.rb +2 -2
- data/lib/rm/plugins/roundcube.rb +2 -2
- data/mailshears.gemspec +2 -2
- data/test/mailshears_test.rb +4 -4
- data/test/sql/postfixadmin.sql +3 -3
- data/test/sql/roundcube.sql +5 -5
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e00eaa9dfa4eba0f52b9ab26ad79bbf4bd1730260d81278488dc7710834a0ec7
|
4
|
+
data.tar.gz: 1b823e702d0abf5fd5b6b73ecbc166f0ea5c5a75adaa0851133b7b0df80b62e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b8a0ed3e568320d72bc6990e23c8f02619e9a642d322cf8ac9329a2cad8359d3af4e1a0d132a9610622ea6c544c03d5df781c6f62dc2f8f6b24dbe55dbee8e1
|
7
|
+
data.tar.gz: 148d00fea24eff0a94da79869cd7e71ee1f1d27d49c1bfe433951b6c578ecf22c41e6e6eeaa7d8f90f45ac44d69e70f37f6f60283048066098266109594af7f2
|
data/doc/TODO
CHANGED
@@ -20,3 +20,22 @@
|
|
20
20
|
"prefs" table, but all of the shares (and principals?) have URLs
|
21
21
|
instead of usernames. We don't parse the URLs, and instead rely
|
22
22
|
on doing find/replace of substrings in e.g. AgendavMv.
|
23
|
+
|
24
|
+
In particular, this means that AgenDAV pruning does not work! If
|
25
|
+
a user with default preferences is deleted, we don't notice.
|
26
|
+
|
27
|
+
* mailshears --help crashes before doing what it should just do:
|
28
|
+
|
29
|
+
$ mailshears --help
|
30
|
+
ERROR: prune mode takes no additional arguments.
|
31
|
+
|
32
|
+
* The "pretend mode" output is missing the destination information:
|
33
|
+
|
34
|
+
# mailshears mv "test1@example.com" "test2@example.com"
|
35
|
+
mailshears, 2020-01-30 14:40:09 -0500 (Plugin: MvPlugin)
|
36
|
+
--------------------------------------------------------
|
37
|
+
AgendavMv - Would move user test1@example.com (User not found) to .
|
38
|
+
DavicalMv - Would move user test1@example.com (User not found) to .
|
39
|
+
DovecotMv - Would move user test1@example.com (/var/spool/mail/vhosts/example.com/test1) to .
|
40
|
+
PostfixadminMv - Would move user test1@example.com to .
|
41
|
+
RoundcubeMv - Would move user test1@example.com (User not found) to .
|
@@ -42,7 +42,7 @@ module AgendavPlugin
|
|
42
42
|
sql_query = 'SELECT username FROM prefs;'
|
43
43
|
|
44
44
|
begin
|
45
|
-
connection.
|
45
|
+
connection.sync_exec(sql_query) do |result|
|
46
46
|
users = result.field_values('username')
|
47
47
|
end
|
48
48
|
ensure
|
@@ -65,7 +65,7 @@ module AgendavPlugin
|
|
65
65
|
|
66
66
|
sql_query = 'SELECT count(*) FROM shares;'
|
67
67
|
begin
|
68
|
-
connection.
|
68
|
+
connection.sync_exec(sql_query) do |result|
|
69
69
|
count = result.getvalue(0,0).to_i()
|
70
70
|
end
|
71
71
|
ensure
|
@@ -55,7 +55,7 @@ module DavicalPlugin
|
|
55
55
|
sql_query = 'SELECT username FROM usr WHERE user_no > 1;'
|
56
56
|
|
57
57
|
begin
|
58
|
-
connection.
|
58
|
+
connection.sync_exec(sql_query) do |result|
|
59
59
|
usernames = result.field_values('username')
|
60
60
|
end
|
61
61
|
ensure
|
@@ -88,7 +88,7 @@ module DavicalPlugin
|
|
88
88
|
sql_query += 'WHERE usr.username = $1;'
|
89
89
|
|
90
90
|
begin
|
91
|
-
connection.
|
91
|
+
connection.sync_exec_params(sql_query, [user.to_s()]) do |result|
|
92
92
|
if result.num_tuples > 0
|
93
93
|
principal_id = result[0]['principal_id']
|
94
94
|
end
|
@@ -43,7 +43,7 @@ module PostfixadminPlugin
|
|
43
43
|
sql_query = "SELECT domain FROM domain WHERE domain <> 'ALL';"
|
44
44
|
|
45
45
|
begin
|
46
|
-
connection.
|
46
|
+
connection.sync_exec(sql_query) do |result|
|
47
47
|
domains = result.field_values('domain')
|
48
48
|
end
|
49
49
|
ensure
|
@@ -68,7 +68,7 @@ module PostfixadminPlugin
|
|
68
68
|
sql_query = 'SELECT username FROM mailbox;'
|
69
69
|
|
70
70
|
begin
|
71
|
-
connection.
|
71
|
+
connection.sync_exec(sql_query) do |result|
|
72
72
|
users = result.field_values('username')
|
73
73
|
end
|
74
74
|
ensure
|
@@ -104,7 +104,7 @@ module PostfixadminPlugin
|
|
104
104
|
begin
|
105
105
|
# Now replace each Domain with its string representation and pass
|
106
106
|
# those in as our individual parameters.
|
107
|
-
connection.
|
107
|
+
connection.sync_exec_params(sql_query, domains.map{ |d| d.to_s() }) do |result|
|
108
108
|
usernames = result.field_values('username')
|
109
109
|
end
|
110
110
|
ensure
|
@@ -131,7 +131,7 @@ module PostfixadminPlugin
|
|
131
131
|
sql_query = 'SELECT address,goto FROM alias;'
|
132
132
|
|
133
133
|
begin
|
134
|
-
results = connection.
|
134
|
+
results = connection.sync_exec(sql_query)
|
135
135
|
results.each do |row|
|
136
136
|
# row should be a hash
|
137
137
|
aliases << row
|
@@ -163,7 +163,7 @@ module PostfixadminPlugin
|
|
163
163
|
sql_query = 'SELECT COUNT(domain) as count FROM domain WHERE domain = $1;'
|
164
164
|
|
165
165
|
begin
|
166
|
-
connection.
|
166
|
+
connection.sync_exec_params(sql_query, [domain.to_s()]) do |result|
|
167
167
|
return false if result.ntuples() < 1
|
168
168
|
count = result.getvalue(0,0).to_i()
|
169
169
|
|
@@ -47,12 +47,12 @@ module RoundcubePlugin
|
|
47
47
|
def list_users()
|
48
48
|
usernames = []
|
49
49
|
|
50
|
-
connection = PG::Connection.
|
50
|
+
connection = PG::Connection.new(@db_hash)
|
51
51
|
|
52
52
|
sql_query = 'SELECT username FROM users;'
|
53
53
|
|
54
54
|
begin
|
55
|
-
connection.
|
55
|
+
connection.sync_exec(sql_query) do |result|
|
56
56
|
usernames = result.field_values('username')
|
57
57
|
end
|
58
58
|
ensure
|
@@ -79,7 +79,7 @@ module RoundcubePlugin
|
|
79
79
|
sql_query = 'SELECT user_id FROM users WHERE username = $1;'
|
80
80
|
|
81
81
|
begin
|
82
|
-
connection.
|
82
|
+
connection.sync_exec_params(sql_query, [user.to_s()]) do |result|
|
83
83
|
if result.num_tuples > 0
|
84
84
|
user_id = result[0]['user_id']
|
85
85
|
end
|
data/lib/mv/mv_runner.rb
CHANGED
@@ -38,17 +38,17 @@ class MvRunner
|
|
38
38
|
msg += "."
|
39
39
|
report(plugin, msg)
|
40
40
|
|
41
|
-
rescue NonexistentUserError
|
41
|
+
rescue NonexistentUserError
|
42
42
|
# This means that the SOURCE user didn't exist, since a
|
43
43
|
# nonexistent destination user is perfectly expected.
|
44
44
|
report(plugin, "Source user #{src.to_s()} not found.")
|
45
|
-
rescue NonexistentDomainError
|
45
|
+
rescue NonexistentDomainError
|
46
46
|
# This could mean that the source domain doesn't exist, but in
|
47
47
|
# that case, we just report that the source user doesn't
|
48
48
|
# exist. So a nonexistent domain refers to a nonexistent
|
49
49
|
# DESTINATION domain.
|
50
50
|
report(plugin, "Destination domain #{dst.domainpart()} not found.")
|
51
|
-
rescue UserAlreadyExistsError
|
51
|
+
rescue UserAlreadyExistsError
|
52
52
|
report(plugin, "Destination user #{dst.to_s()} already exists.")
|
53
53
|
end
|
54
54
|
end
|
data/lib/mv/plugins/agendav.rb
CHANGED
@@ -40,7 +40,7 @@ class AgendavMv
|
|
40
40
|
# The "prefs" table uses the normal username as a key...
|
41
41
|
# This should be harmless if the source user does not exist.
|
42
42
|
sql_query0 = 'UPDATE prefs SET username = $1 WHERE username = $2;'
|
43
|
-
connection.
|
43
|
+
connection.sync_exec_params(sql_query0, [dst.to_s(), src.to_s()])
|
44
44
|
|
45
45
|
# But the "shares" table uses encoded principal URLs. For the
|
46
46
|
# "shares" table, we need to do a find/replace on the username
|
@@ -58,7 +58,7 @@ class AgendavMv
|
|
58
58
|
sql_queries << 'UPDATE shares SET "with"=REPLACE("with", $2, $1);'
|
59
59
|
|
60
60
|
sql_queries.each do |sql_query|
|
61
|
-
connection.
|
61
|
+
connection.sync_exec_params(sql_query, [encoded_dst, encoded_src])
|
62
62
|
end
|
63
63
|
ensure
|
64
64
|
# Make sure the connection gets closed even if a query explodes.
|
data/lib/mv/plugins/davical.rb
CHANGED
@@ -33,7 +33,7 @@ class DavicalMv
|
|
33
33
|
|
34
34
|
connection = PG::Connection.new(@db_hash)
|
35
35
|
begin
|
36
|
-
connection.
|
36
|
+
connection.sync_exec_params(sql_query, [dst.to_s(), src.to_s()])
|
37
37
|
ensure
|
38
38
|
# Make sure the connection gets closed even if the query explodes.
|
39
39
|
connection.close()
|
@@ -59,7 +59,7 @@ class PostfixadminMv
|
|
59
59
|
{:value => dst.domainpart(), :type => varchar},
|
60
60
|
{:value => dst.localpart(), :type => varchar},
|
61
61
|
{:value => src.to_s(), :type => varchar}]
|
62
|
-
connection.
|
62
|
+
connection.sync_exec_params(sql_query, params)
|
63
63
|
end
|
64
64
|
ensure
|
65
65
|
# Make sure the connection gets closed even if a query explodes.
|
data/lib/mv/plugins/roundcube.rb
CHANGED
@@ -34,7 +34,7 @@ class RoundcubeMv
|
|
34
34
|
|
35
35
|
connection = PG::Connection.new(@db_hash)
|
36
36
|
begin
|
37
|
-
connection.
|
37
|
+
connection.sync_exec_params(sql_query, [dst.to_s(), src.to_s()])
|
38
38
|
ensure
|
39
39
|
# Make sure the connection gets closed even if the query explodes.
|
40
40
|
connection.close()
|
data/lib/rm/plugins/agendav.rb
CHANGED
@@ -47,7 +47,7 @@ class AgendavRm
|
|
47
47
|
connection = PG::Connection.new(@db_hash)
|
48
48
|
begin
|
49
49
|
sql_queries.each do |sql_query|
|
50
|
-
connection.
|
50
|
+
connection.sync_exec_params(sql_query, [user.to_s()])
|
51
51
|
end
|
52
52
|
ensure
|
53
53
|
# Make sure the connection gets closed even if a query explodes.
|
data/lib/rm/plugins/davical.rb
CHANGED
@@ -27,7 +27,7 @@ class DavicalRm
|
|
27
27
|
|
28
28
|
connection = PG::Connection.new(@db_hash)
|
29
29
|
begin
|
30
|
-
connection.
|
30
|
+
connection.sync_exec_params(sql_query, [user.to_s()])
|
31
31
|
ensure
|
32
32
|
# Make sure the connection gets closed even if the query explodes.
|
33
33
|
connection.close()
|
@@ -56,7 +56,7 @@ class PostfixadminRm
|
|
56
56
|
sql_queries.each do |sql_query|
|
57
57
|
varchar = 1043 # from pg_type.h
|
58
58
|
params = [{:value => user.to_s(), :type => varchar}]
|
59
|
-
connection.
|
59
|
+
connection.sync_exec_params(sql_query, params)
|
60
60
|
end
|
61
61
|
ensure
|
62
62
|
# Make sure the connection gets closed even if a query explodes.
|
@@ -103,7 +103,7 @@ class PostfixadminRm
|
|
103
103
|
|
104
104
|
begin
|
105
105
|
sql_queries.each do |sql_query|
|
106
|
-
connection.
|
106
|
+
connection.sync_exec_params(sql_query, [domain.to_s()])
|
107
107
|
end
|
108
108
|
ensure
|
109
109
|
# Make sure the connection gets closed even if a query explodes.
|
data/lib/rm/plugins/roundcube.rb
CHANGED
@@ -29,10 +29,10 @@ class RoundcubeRm
|
|
29
29
|
# records associated with user_id too.
|
30
30
|
sql_query = 'DELETE FROM users WHERE user_id = $1::int;'
|
31
31
|
|
32
|
-
connection = PG::Connection.
|
32
|
+
connection = PG::Connection.new(@db_hash)
|
33
33
|
|
34
34
|
begin
|
35
|
-
connection.
|
35
|
+
connection.sync_exec_params(sql_query, [user_id])
|
36
36
|
ensure
|
37
37
|
# Make sure the connection gets closed even if the query explodes.
|
38
38
|
connection.close()
|
data/mailshears.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'mailshears'
|
4
|
-
s.version = '0.0.
|
4
|
+
s.version = '0.0.4'
|
5
5
|
s.platform = Gem::Platform::RUBY
|
6
6
|
s.authors = ['Michael Orlitzky']
|
7
7
|
s.email = ['michael@orlitzky.com']
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.required_rubygems_version = '>= 1.3.6'
|
29
29
|
|
30
30
|
# If you have runtime dependencies, add them here
|
31
|
-
s.add_runtime_dependency 'pg', '~>
|
31
|
+
s.add_runtime_dependency 'pg', '~> 1.2'
|
32
32
|
|
33
33
|
# The list of files to be contained in the gem. We can obtain it
|
34
34
|
# from git as long as we remember that this magic will happen and we
|
data/test/mailshears_test.rb
CHANGED
@@ -208,7 +208,7 @@ class MailshearsTest < MiniTest::Test
|
|
208
208
|
plugin_dbname = cfg.send("#{plugin}_dbname")
|
209
209
|
next if plugin_dbname.nil? # Skip the dovecot plugin
|
210
210
|
query = "CREATE DATABASE #{plugin_dbname};"
|
211
|
-
connection.
|
211
|
+
connection.sync_exec(query)
|
212
212
|
|
213
213
|
plugin_dbhost = cfg.send("#{plugin}_dbhost")
|
214
214
|
plugin_dbport = cfg.send("#{plugin}_dbport")
|
@@ -223,9 +223,9 @@ class MailshearsTest < MiniTest::Test
|
|
223
223
|
plugin_dbpass)
|
224
224
|
|
225
225
|
sql = File.open("test/sql/#{plugin}.sql").read()
|
226
|
-
plugin_conn.
|
226
|
+
plugin_conn.sync_exec(sql)
|
227
227
|
sql = File.open("test/sql/#{plugin}-fixtures.sql").read()
|
228
|
-
plugin_conn.
|
228
|
+
plugin_conn.sync_exec(sql)
|
229
229
|
plugin_conn.close()
|
230
230
|
end
|
231
231
|
|
@@ -246,7 +246,7 @@ class MailshearsTest < MiniTest::Test
|
|
246
246
|
plugin_dbname = cfg.send("#{plugin}_dbname")
|
247
247
|
next if plugin_dbname.nil? # Skip the dovecot plugin
|
248
248
|
query = "DROP DATABASE IF EXISTS #{plugin_dbname};"
|
249
|
-
connection.
|
249
|
+
connection.sync_exec(query)
|
250
250
|
end
|
251
251
|
|
252
252
|
connection.close()
|
data/test/sql/postfixadmin.sql
CHANGED
@@ -89,7 +89,7 @@ ALTER FUNCTION public.merge_quota2() OWNER TO postgres;
|
|
89
89
|
|
90
90
|
SET default_tablespace = '';
|
91
91
|
|
92
|
-
SET default_with_oids =
|
92
|
+
SET default_with_oids = false;
|
93
93
|
|
94
94
|
--
|
95
95
|
-- Name: admin; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -160,7 +160,7 @@ ALTER TABLE public.alias_domain OWNER TO postgres;
|
|
160
160
|
COMMENT ON TABLE alias_domain IS 'Postfix Admin - Domain Aliases';
|
161
161
|
|
162
162
|
|
163
|
-
SET default_with_oids =
|
163
|
+
SET default_with_oids = false;
|
164
164
|
|
165
165
|
--
|
166
166
|
-- Name: config; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -371,7 +371,7 @@ CREATE TABLE quota2 (
|
|
371
371
|
|
372
372
|
ALTER TABLE public.quota2 OWNER TO postgres;
|
373
373
|
|
374
|
-
SET default_with_oids =
|
374
|
+
SET default_with_oids = false;
|
375
375
|
|
376
376
|
--
|
377
377
|
-- Name: vacation; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
data/test/sql/roundcube.sql
CHANGED
@@ -26,7 +26,7 @@ SET search_path = public, pg_catalog;
|
|
26
26
|
|
27
27
|
SET default_tablespace = '';
|
28
28
|
|
29
|
-
SET default_with_oids =
|
29
|
+
SET default_with_oids = false;
|
30
30
|
|
31
31
|
--
|
32
32
|
-- Name: cache; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -145,7 +145,7 @@ CREATE SEQUENCE contactgroups_ids
|
|
145
145
|
|
146
146
|
ALTER TABLE public.contactgroups_ids OWNER TO postgres;
|
147
147
|
|
148
|
-
SET default_with_oids =
|
148
|
+
SET default_with_oids = false;
|
149
149
|
|
150
150
|
--
|
151
151
|
-- Name: contacts; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -182,7 +182,7 @@ CREATE TABLE dictionary (
|
|
182
182
|
|
183
183
|
ALTER TABLE public.dictionary OWNER TO postgres;
|
184
184
|
|
185
|
-
SET default_with_oids =
|
185
|
+
SET default_with_oids = false;
|
186
186
|
|
187
187
|
--
|
188
188
|
-- Name: identities; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -251,7 +251,7 @@ CREATE TABLE searches (
|
|
251
251
|
|
252
252
|
ALTER TABLE public.searches OWNER TO postgres;
|
253
253
|
|
254
|
-
SET default_with_oids =
|
254
|
+
SET default_with_oids = false;
|
255
255
|
|
256
256
|
--
|
257
257
|
-- Name: session; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
@@ -296,7 +296,7 @@ CREATE SEQUENCE user_ids
|
|
296
296
|
|
297
297
|
ALTER TABLE public.user_ids OWNER TO postgres;
|
298
298
|
|
299
|
-
SET default_with_oids =
|
299
|
+
SET default_with_oids = false;
|
300
300
|
|
301
301
|
--
|
302
302
|
-- Name: users; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mailshears
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Orlitzky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.2'
|
27
27
|
description: |2
|
28
28
|
Managing a mail system with virtual users is annoying. The
|
29
29
|
authoritative database of users is stored in one table, but every
|
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
126
|
version: 1.3.6
|
127
127
|
requirements: []
|
128
128
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.
|
129
|
+
rubygems_version: 2.7.10
|
130
130
|
signing_key:
|
131
131
|
specification_version: 4
|
132
132
|
summary: Prune unused mail directories.
|