b950b7a76d6c27e9d80c1d9d0b0972427681baf3
[mailshears.git] / lib / rm / plugins / postfixadmin.rb
1 require 'pg'
2
3 require 'common/postfixadmin_plugin'
4 require 'rm/rm_plugin'
5
6
7 # Handle the removal of users and domains from the Postfixadmin database.
8 #
9 class PostfixadminRm
10
11 include PostfixadminPlugin
12 include RmPlugin
13
14
15 # Remove *user* from the Postfixadmin database. This should remove
16 # him from _every_ table in which he is referenced. Unfortunately,
17 # Postfixadmin does not use foreign keys or ON DELETE CASCADE
18 # triggers so we need to delete the associated child table records
19 # ourselves.
20 #
21 # @param user [User] the user to remove.
22 #
23 def remove_user(user)
24 raise NonexistentUserError.new(user.to_s()) if not user_exists(user)
25
26 # Remove aliases FROM our user to some other address.
27 sql_queries = ['DELETE FROM alias WHERE address = $1;']
28
29 # Also delete aliases that point SOLELY TO our user.
30 sql_queries << "DELETE FROM alias WHERE goto = $1;"
31
32 # But aliases don't need to point to a single user! If our user
33 # was part of a multi-recipient alias, we want to remove our user
34 # from the alias and leave the other recipients. If you're
35 # wondering about the leftover double-commas, look towards the end
36 # of the function.
37 sql_queries << "UPDATE alias SET goto=REPLACE(goto, $1, '');"
38
39 sql_queries << 'DELETE FROM mailbox WHERE username = $1;'
40 sql_queries << 'DELETE FROM quota WHERE username = $1;'
41 sql_queries << 'DELETE FROM quota2 WHERE username = $1;'
42 sql_queries << 'DELETE FROM vacation WHERE email = $1;'
43
44 # Should be handled by a trigger, according to PostfixAdmin code.
45 sql_queries << 'DELETE FROM vacation_notification WHERE on_vacation = $1;'
46
47 connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty,
48 @db_name, @db_user, @db_pass)
49
50 sql_queries.each do |sql_query|
51 connection.query(sql_query, [user.to_s()])
52 end
53
54 # The earlier alias update query will leave things like
55 # "foo@example.com,,bar@example.com" in the "goto" column. Now
56 # we fix it. We don't do it in the loop because query() craps
57 # out on the superfluous parameter.
58 sql_query = "UPDATE alias SET goto=REPLACE(goto, ',,', ',');"
59 connection.query(sql_query)
60
61 connection.close()
62 end
63
64
65 # Remove *domain* from the Postfixadmin database. This should remove
66 # the domain from _every_ table in which it is referenced. It should
67 # also remove every user that belongs to the doomed domain
68 # Postfixadmin has some experimental support for triggers, but they
69 # don't do a very good job of cleaning up. Therefore we remove all
70 # users in the domain manually before removing the domain itself.
71 #
72 # Log entries (from the "log" table) are not removed since they may
73 # still contain valuable information (although they won't mention
74 # this removal).
75 #
76 # @param domain [Domain] the domain to remove.
77 #
78 def remove_domain(domain)
79 raise NonexistentDomainError.new(domain.to_s()) if not domain_exists(domain)
80
81 # First remove all users belonging to the domain. This will handle
82 # alias updates and all the sensitive crap we need to do when
83 # removing a user.
84 users = list_domains_users([domain])
85 users.each { |u| remove_user(u) }
86
87 # The domain_admins table contains one record per domain
88 # (repeating the user as necessary), so this really is sufficient.
89 sql_queries = ['DELETE FROM domain_admins WHERE domain = $1;']
90
91 # Some of the following queries should be redundant now that we've
92 # removed all users in the domain.
93 sql_queries << 'DELETE FROM alias WHERE domain = $1;'
94 sql_queries << 'DELETE FROM mailbox WHERE domain = $1;'
95 sql_queries << 'DELETE FROM alias_domain WHERE alias_domain = $1;'
96 sql_queries << 'DELETE FROM vacation WHERE domain = $1;'
97 sql_queries << 'DELETE FROM domain WHERE domain = $1;'
98
99 connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty,
100 @db_name, @db_user, @db_pass)
101
102 sql_queries.each do |sql_query|
103 connection.query(sql_query, [domain.to_s()])
104 end
105
106 connection.close()
107 end
108
109 end