X-Git-Url: http://gitweb.michael.orlitzky.com/?p=mailshears.git;a=blobdiff_plain;f=lib%2Frm%2Fplugins%2Fpostfixadmin.rb;h=b950b7a76d6c27e9d80c1d9d0b0972427681baf3;hp=103912b648e71ce8edf02a6be0745d76cded190b;hb=df4e02ebf6a4e28a58abcb298a4442a245ad0b15;hpb=d0bfa37fb4be739b31dd97c493764ca19a160182 diff --git a/lib/rm/plugins/postfixadmin.rb b/lib/rm/plugins/postfixadmin.rb index 103912b..b950b7a 100644 --- a/lib/rm/plugins/postfixadmin.rb +++ b/lib/rm/plugins/postfixadmin.rb @@ -3,18 +3,39 @@ require 'pg' require 'common/postfixadmin_plugin' require 'rm/rm_plugin' + +# Handle the removal of users and domains from the Postfixadmin database. +# class PostfixadminRm include PostfixadminPlugin include RmPlugin - def delete_user(user) + # Remove *user* from the Postfixadmin database. This should remove + # him from _every_ table in which he is referenced. Unfortunately, + # Postfixadmin does not use foreign keys or ON DELETE CASCADE + # triggers so we need to delete the associated child table records + # ourselves. + # + # @param user [User] the user to remove. + # + def remove_user(user) raise NonexistentUserError.new(user.to_s()) if not user_exists(user) + # Remove aliases FROM our user to some other address. sql_queries = ['DELETE FROM alias WHERE address = $1;'] - # Wipe out any aliases pointed at our user. + + # Also delete aliases that point SOLELY TO our user. + sql_queries << "DELETE FROM alias WHERE goto = $1;" + + # But aliases don't need to point to a single user! If our user + # was part of a multi-recipient alias, we want to remove our user + # from the alias and leave the other recipients. If you're + # wondering about the leftover double-commas, look towards the end + # of the function. sql_queries << "UPDATE alias SET goto=REPLACE(goto, $1, '');" + sql_queries << 'DELETE FROM mailbox WHERE username = $1;' sql_queries << 'DELETE FROM quota WHERE username = $1;' sql_queries << 'DELETE FROM quota2 WHERE username = $1;' @@ -41,14 +62,37 @@ class PostfixadminRm end - def delete_domain(domain) + # Remove *domain* from the Postfixadmin database. This should remove + # the domain from _every_ table in which it is referenced. It should + # also remove every user that belongs to the doomed domain + # Postfixadmin has some experimental support for triggers, but they + # don't do a very good job of cleaning up. Therefore we remove all + # users in the domain manually before removing the domain itself. + # + # Log entries (from the "log" table) are not removed since they may + # still contain valuable information (although they won't mention + # this removal). + # + # @param domain [Domain] the domain to remove. + # + def remove_domain(domain) raise NonexistentDomainError.new(domain.to_s()) if not domain_exists(domain) + # First remove all users belonging to the domain. This will handle + # alias updates and all the sensitive crap we need to do when + # removing a user. + users = list_domains_users([domain]) + users.each { |u| remove_user(u) } + + # The domain_admins table contains one record per domain + # (repeating the user as necessary), so this really is sufficient. sql_queries = ['DELETE FROM domain_admins WHERE domain = $1;'] + + # Some of the following queries should be redundant now that we've + # removed all users in the domain. sql_queries << 'DELETE FROM alias WHERE domain = $1;' sql_queries << 'DELETE FROM mailbox WHERE domain = $1;' sql_queries << 'DELETE FROM alias_domain WHERE alias_domain = $1;' - sql_queries << 'DELETE FROM log WHERE domain = $1;' sql_queries << 'DELETE FROM vacation WHERE domain = $1;' sql_queries << 'DELETE FROM domain WHERE domain = $1;' @@ -62,29 +106,4 @@ class PostfixadminRm connection.close() end - - protected; - - def domain_exists(domain) - count = 0 - - connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty, - @db_name, @db_user, @db_pass) - - sql_query = 'SELECT COUNT(domain) as count FROM domain WHERE domain = $1;' - connection.query(sql_query, [domain.to_s()]) do |result| - return false if result.ntuples() < 1 - begin - count = result.getvalue(0,0).to_i() - return false if count.nil? - rescue StandardError - return false - end - end - - connection.close() - - return (count > 0) - end - end