require 'common/domain' require 'common/plugin' require 'common/user' require 'pg' # Code that all Postfixadmin plugins ({PostfixadminPrune}, # {PostfixadminRm}, {PostfixadminMv}) share. # module PostfixadminPlugin # We implement the Plugin "interface." include Plugin # Initialize this Postfixadmin {Plugin} with values in *cfg*. # # @param cfg [Configuration] the configuration for this plugin. # def initialize(cfg) @db_host = cfg.postfixadmin_dbhost @db_port = cfg.postfixadmin_dbport @db_opts = cfg.postfixadmin_dbopts @db_tty = cfg.postfixadmin_dbtty @db_name = cfg.postfixadmin_dbname @db_user = cfg.postfixadmin_dbuser @db_pass = cfg.postfixadmin_dbpass end # Obtain a list of domains from Postfixadmin. This is more efficient # than the {Plugin} default implementation because domains have # their own table in the database and we can easily select them # rather than filtering the list of users. # # @return [Array] a list of the domains in Postfixadmin. # def list_domains() domains = [] connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty, @db_name, @db_user, @db_pass) # 'ALL' is a magic domain, and we don't want it. sql_query = "SELECT domain FROM domain WHERE domain <> 'ALL';" connection.query(sql_query) do |result| domains = result.field_values('domain') end connection.close() return domains.map{ |d| Domain.new(d) } end # Return a list of Postfixadmin users. # # @return [Array] a list of users contained in the # Postfixadmin database. # def list_users() users = [] connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty, @db_name, @db_user, @db_pass) sql_query = 'SELECT username FROM mailbox;' connection.query(sql_query) do |result| users = result.field_values('username') end connection.close() return users.map{ |u| User.new(u) } end # Efficiently list all Postfixadmin users belonging to the given # Postfixadmin *domains*. # # @param domains [Array] the domains whose users we want. # # @return [Array] a list of {User} objects belonging to # *domains* for this plugin. # def list_domains_users(domains) usernames = [] return usernames if domains.length() == 0 connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty, @db_name, @db_user, @db_pass) # The number of parameters that we'll pass into our prepared query # is the number of domains that we're given. It's important that # we have at least one domain here. params = 1.upto(domains.length()).map{ |i| '$' + i.to_s() }.join(',') sql_query = "SELECT username FROM mailbox WHERE domain IN (#{params});" # Now replace each Domain with its string representation and pass # those in as our individual parameters. connection.query(sql_query, domains.map{ |d| d.to_s() }) do |result| usernames = result.field_values('username') end connection.close() return usernames.map{ |u| User.new(u) } end # Get a list of all Postfixadmin aliases as a from => to # hash. This is useful for testing, since aliases should be removed # when either the "from user" or "to user" are removed. # # @return [Hash] all aliases known to Postfixadmin in the form of a # from => to hash. # def list_aliases() aliases = [] connection = PGconn.connect(@db_host, @db_port, @db_opts, @db_tty, @db_name, @db_user, @db_pass) sql_query = 'SELECT address,goto FROM alias;' results = connection.query(sql_query) results.each do |row| # row should be a hash aliases << row end connection.close() return aliases end # A fast implementation of the "does this domain exist?" # operation. It only queries the database for the existence of # *domain* rather than a list of all domains (which is the default # implementation). # # @param domain [Domain] the domain whose existence is in question. # # @return [Boolean] true if *domain* exists in the Postfixadmin # database and false otherwise. # 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 count = result.getvalue(0,0).to_i() return false if count.nil? end connection.close() return (count > 0) end end