]> Frank Brehm's Git Trees - my-stuff/postfix-maps.git/commitdiff
Weitergekommen
authorFrank Brehm <frank@brehm-online.com>
Thu, 5 Aug 2010 13:35:02 +0000 (13:35 +0000)
committerFrank Brehm <frank@brehm-online.com>
Thu, 5 Aug 2010 13:35:02 +0000 (13:35 +0000)
git-svn-id: http://svn.brehm-online.com/svn/my-stuff/postfix-maps/trunk@106 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa

etc/config.yml
lib/FrBr/Postfix/App.pm

index c3a749377e423cb9e48f3220d49a1f35e6b1f8f5..67bd65d065300c1b1bdf932942b6c7f85a4c4fa1 100644 (file)
@@ -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':
 #
 # 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
index 64b0f23de5d59053641009630d353338f4a43bb9..a9afce4e73479d2bf7c2d95fefa0a90780a419e2 100644 (file)
@@ -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." );
 
 }