From: Frank Brehm Date: Thu, 5 Aug 2010 13:35:02 +0000 (+0000) Subject: Weitergekommen X-Git-Url: https://git.uhu-banane.org/?a=commitdiff_plain;h=09302bfc6756cb42b9d3d5cb1a2faa4bb2d3b796;p=my-stuff%2Fpostfix-maps.git Weitergekommen git-svn-id: http://svn.brehm-online.com/svn/my-stuff/postfix-maps/trunk@106 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa --- diff --git a/etc/config.yml b/etc/config.yml index c3a7493..67bd65d 100644 --- a/etc/config.yml +++ b/etc/config.yml @@ -14,6 +14,9 @@ # Das globale Verzeichnis der Postfix-Konfiguration #postfixdir: '/etc/postfix' # +# Das Arbeitsverzeichnis zum zeitweiligen Auschecken, absolut oder relativ zu postfixdir +#workdir: 'work' +# # Datenbank-Konfiguration #schema_class: 'FrBr::Postffix::Db' 'Model::Schema': @@ -24,8 +27,22 @@ # # Die eigentliche Zuordnung von Datenbank-Tabellen zu Postfix-Mapfiles maps: + alias: + file: aliases + description: 'Lokale Alias-Definitionen' + enabled: 1 + db_type: hash + text_type: aliases + resultset: Alias + columns: + - alias + - destination + where: + enabled: y + order_by: alias canonical: file: canonical + description: 'Canonical Mappings' enabled: 1 db_type: hash text_type: map @@ -38,6 +55,7 @@ maps: order_by: email mydomains: file: mydomains + description: 'Alle lokalen (echten) Domänen' enabled: 1 db_type: hash text_type: map @@ -51,6 +69,7 @@ maps: order_by: domain recipient_bcc: file: recipient_bcc + description: 'BCC-Zuordnungen zu lokalen Empfängern' enabled: 1 db_type: hash text_type: map @@ -63,6 +82,7 @@ maps: order_by: email relay_domains: file: relay_domains + description: 'Alle Relay-Domänen' enabled: 1 db_type: hash text_type: map @@ -76,6 +96,7 @@ maps: order_by: domain relocated: file: relocated + description: 'Alle relocatet Mailadressen' enabled: 1 db_type: hash text_type: map @@ -88,6 +109,7 @@ maps: order_by: email sender_bcc: file: sender_bcc + description: 'BCC-Zuordnungen zu lokalen Sendern' enabled: 1 db_type: hash text_type: map @@ -100,6 +122,7 @@ maps: order_by: email virtual_alias_domains: file: virtual_alias_domains + description: 'Virtuelle Alias-Domänen' enabled: 1 db_type: hash text_type: map @@ -113,6 +136,7 @@ maps: order_by: domain virtual_alias_maps: file: virtual_alias_maps + description: 'Virtuelle Alias-Mappings' enabled: 1 db_type: hash text_type: map @@ -125,6 +149,7 @@ maps: order_by: email virtual_mailbox_domains: file: virtual_mailbox_domains + description: 'Virtuelle Mailbox-Domänen' enabled: 1 db_type: hash text_type: map @@ -138,6 +163,7 @@ maps: order_by: domain virtual_mailbox_maps: file: virtual_mailbox_maps + description: 'Virtuelle Mailbox-Mappings' enabled: 1 db_type: hash text_type: map diff --git a/lib/FrBr/Postfix/App.pm b/lib/FrBr/Postfix/App.pm index 64b0f23..a9afce4 100644 --- a/lib/FrBr/Postfix/App.pm +++ b/lib/FrBr/Postfix/App.pm @@ -22,6 +22,7 @@ use utf8; use MooseX::Types::Path::Class; use Path::Class; +use Encode qw( decode_utf8 encode_utf8 is_utf8 ); extends 'FrBr::Common::MooseX::App'; @@ -100,6 +101,69 @@ sub _build_workdir { return dir->new( 'work' ); } +#----------------------------------------- + +=head2 postfix_maps + +ArrayRef für die aus der Konfiguration eigelesenen Mappings + +=cut + +has 'postfix_maps' => ( + is => 'rw', + isa => 'ArrayRef', + traits => [ 'NoGetopt' ], + lazy => 1, + builder => '_build_postfix_maps', + documentation => 'Die aus der Konfiguration eigelesenen Mappings', +); + +#------ + +sub _build_postfix_maps { + return []; +} + +#----------------------------------------- + +=head2 valid_maptypes + +HashRef mit allen gültigen Map-Typen + +=cut + +has 'valid_maptypes' => ( + is => 'ro', + isa => 'HashRef', + traits => [ 'NoGetopt' ], + lazy => 1, + builder => '_build_valid_maptypes', + documentation => 'HashRef mit allen gültigen Postfix-Map-Typen.', +); + +#------ + +sub _build_valid_maptypes { + return { + 'btree' => { restart => 0, do_map => 1, exec_map => 1, }, + 'cdb' => { restart => 0, do_map => 1, exec_map => 1, }, + 'cidr' => { restart => 1, do_map => 1, exec_map => 0, }, + 'dbm' => { restart => 0, do_map => 1, exec_map => 1, }, + 'environ' => { restart => 0, do_map => 0, exec_map => 0, }, + 'hash' => { restart => 0, do_map => 1, exec_map => 1, }, + 'ldap' => { restart => 0, do_map => 0, exec_map => 0, }, + 'mysql' => { restart => 0, do_map => 0, exec_map => 0, }, + 'pcre' => { restart => 1, do_map => 1, exec_map => 0, }, + 'pgsql' => { restart => 0, do_map => 0, exec_map => 0, }, + 'proxy' => { restart => 0, do_map => 0, exec_map => 0, }, + 'regexp' => { restart => 1, do_map => 1, exec_map => 0, }, + 'sdbm' => { restart => 0, do_map => 1, exec_map => 1, }, + 'static' => { restart => 0, do_map => 0, exec_map => 0, }, + 'tcp' => { restart => 0, do_map => 0, exec_map => 0, }, + 'unix' => { restart => 0, do_map => 0, exec_map => 0, }, + }; +} + #--------------------------------------------------------------------------- # Ändern der Eigenschaften einiger geerbter Attribute @@ -138,14 +202,15 @@ sub _build_default_config { }, maps => { 'alias' => { - 'file' => 'aliases', - 'enabled' => 1, - 'db_type' => 'hash', - 'text_type' => 'aliases', - 'resultset' => 'Alias', - 'columns' => [ 'alias', 'destination', ], - 'where' => { 'enabled' => 'y' }, - 'order_by' => 'alias', + 'file' => 'aliases', + 'enabled' => 1, + 'db_type' => 'hash', + 'text_type' => 'aliases', + 'resultset' => 'Alias', + 'columns' => [ 'alias', 'destination', ], + 'where' => { 'enabled' => 'y' }, + 'order_by' => 'alias', + 'description' => 'Lokale Alias-Definitionen', }, }, }; @@ -220,6 +285,12 @@ after 'evaluate_config' => sub { } + if ( $self->verbose >= 2 ) { + for my $key qw( postfix_dir work_dir postfix_maps valid_maptypes ) { + my $tmp = $self->$key; + } + } + unless ( $self->postfix_dir->is_absolute ) { my $d = $self->postfix_dir; $d = dir( $self->basedir, $self->postfix_dir )->absolute; @@ -234,10 +305,143 @@ after 'evaluate_config' => sub { $self->debug( sprintf( "Setze Arbeitsverzeichnis auf '%s' ...", $d ) ) if $self->verbose >= 2; } + $self->_initialise_maps(); + }; #--------------------------------------------------------------------------- +sub _initialise_maps { + + my $self = shift; + + $self->debug( "Übernehme Mappings aus der Konfiguration ..." ) if $self->verbose >= 2; + + my $maps = $self->postfix_maps; + + for my $key ( keys %{ $self->config } ) { + + next unless $key =~ /^maps$/i; + + my $config_maps = $self->config->{$key}; + $self->debug( "Versuche Mappings einzulesen aus: ", $config_maps ) if $self->verbose >= 3; + + for my $mapname ( sort { lc($a) cmp lc($b) } keys %$config_maps ) { + + unless ( $config_maps->{$mapname}{'enabled'} ) { + $self->debug( sprintf( "Mapping '%s' disabled.", $mapname ) ); + next; + } + + my $m = {}; + + # Mapdateien festlegen + unless ( $config_maps->{$mapname}{'file'} ) { + $self->warn( sprintf( "In Mapping '%s' wurde kein Dateiname festgelegt.", $mapname ) ); + next; + } + { + my $file = file( $config_maps->{$mapname}{'file'} ); + $m->{'mapfile'} = $file->is_absolute ? $file : file( $self->postfix_dir, $file ); + $m->{'workfile'} = file( $self->work_dir, $file->basename ); + } + + # Maptyp festlegen + unless ( $config_maps->{$mapname}{'db_type'} ) { + $self->warn( sprintf( "Kein Datenbanktyp für Mapping '%s' festgelegt.", $mapname ) ); + next; + } + { + my $type = lc( $config_maps->{$mapname}{'db_type'} ); + unless ( $self->valid_maptypes->{$type} ) { + $self->error( sprintf( "Ungültiger Datenbanktyp '%s' in Mapping '%s'.", $type, $mapname ) ); + exit 4; + } + unless ( $self->valid_maptypes->{$type}{'do_map'} ) { + $self->debug( sprintf( "Für Datenbanktyp '%s' bei Mapping '%s' wird nichts gemacht.", $mapname ) ); + next; + } + $m->{'db_type'} = $type; + $m->{'exec_map'} = $self->valid_maptypes->{$type}{'exec_map'}; + $m->{'restart_postfix'} = $self->valid_maptypes->{$type}{'restart'}; + } + + # Texttyp festlegen + unless ( $config_maps->{$mapname}{'text_type'} ) { + $self->warn( sprintf( "Kein Texttyp für Mapping '%s' festgelegt.", $mapname ) ); + next; + } + { + my $type = lc( $config_maps->{$mapname}{'text_type'} ); + unless ( $type eq 'map' or $type eq 'aliases' ) { + $self->error( sprintf( "Ungültiger Texttyp '%s' in Mapping '%s'.", $type, $mapname ) ); + exit 4; + } + $m->{'text_type'} = $type; + } + + # Beschreibung setzen + $m->{'description'} = $config_maps->{$mapname}{'description'} || $mapname; + + # Resultset-Zuordnung + unless ( $config_maps->{$mapname}{'resultset'} ) { + $self->warn( sprintf( "Kein Resultset für Mapping '%s' festgelegt.", $mapname ) ); + next; + } + $m->{'resultset'} = $config_maps->{$mapname}{'resultset'}; + + # Tabellenspalten zuordnen + unless ( $config_maps->{$mapname}{'columns'} ) { + $self->warn( sprintf( "Keine Tabellenspalten für Mapping '%s' festgelegt.", $mapname ) ); + next; + } + { + my $cols = $config_maps->{$mapname}{'columns'}; + unless ( ref($cols) and ref($cols) eq 'ARRAY' ) { + $self->error( sprintf( "Ungültige Spaltendefinition in Mapping '%s': ", $mapname ), $cols ); + exit 4; + } + unless ( scalar( @$cols ) >= 2 ) { + $self->error( sprintf( "Zuwenige Spalten für Mapping '%s' angegeben (mindestens 2).", $mapname ) ); + exit 4; + } + $m->{'columns'} = [ $cols->[0], $cols->[1], ]; + } + + # Where-Klausel setzen + if ( $config_maps->{$mapname}{'where'} ) { + my $where = $config_maps->{$mapname}{'where'}; + if ( ref($where) and ref($where) eq 'HASH' ) { + $m->{'where'} = $where; + } + else { + $self->error( sprintf( "Ungültige Where-Angabe für Mapping '%s': ", $mapname ), $where ); + exit 4; + } + } + else { + $m->{'where'} = undef; + } + + # Sortier-Klausel setzen + if ( $config_maps->{$mapname}{'order_by'} ) { + $m->{'order_by'} = $config_maps->{$mapname}{'order_by'}; + } + else { + $m->{'order_by'} = undef; + } + + push @$maps, $m; + + } + + return; + } + +} + +#--------------------------------------------------------------------------- + after 'init_app' => sub { my $self = shift; @@ -284,6 +488,29 @@ sub run { exit 2; } + unless ( -d $self->work_dir ) { + $self->info( sprintf( "Arbeitsverzeichnis '%s' existiert nicht, wird erstellt.", $self->work_dir ) ); + my $err; + $self->work_dir->mkpath( { verbose => $self->verbose, mode => 0700, error => \$err } ); + if (@$err) { + my $out = ''; + for my $errhash ( @$err ) { + for my $file ( keys %$errhash ) { + my $f = is_utf8($file) ? encode_utf8($file) : $file; + my $e = is_utf8($errhash->{$file}) ? encode_utf8($errhash->{$file}) : $errhash->{$file}; + $out .= sprintf( " %s: %s\n", $f, $e ); + } + } + $self->error( sprintf( "Konnte Arbeitsverzeichnis '%s' nicht erstellen:\n%s", $self->work_dir, $out ) ); + exit 2; + } + } + + if ( $self->postfix_dir->resolve->stringify eq $self->work_dir->resolve->stringify ) { + $self->error( sprintf( "Postfix- und Arbeitsverzeichnis dürfen nicht physikalisch übereinstimmen ('%s').", $self->work_dir->resolve->stringify ) ); + exit 2; + } + $self->info( "Ende der Arbeit." ); }