@ -2,31 +2,50 @@ use std::ops::Deref;
use std ::path ::Path ;
use std ::path ::Path ;
use command_runner ::{ CommandRunner , SetuidCommandRunner } ;
use command_runner ::{ CommandRunner , SetuidCommandRunner } ;
use storage ::SimpleStorage ;
use storage ::{ SimpleStorage , Storage } ;
use symbols ::{ Action , Symbol , SymbolRunner } ;
use symbols ::{ Action , Symbol , SymbolRunner } ;
use symbols ::acme ::{ AcmeCert , AcmeCertChain } ;
use symbols ::acme ::{ AcmeCert , AcmeCertChain } ;
use symbols ::file ::File ;
use symbols ::file ::File ;
use symbols ::git ::checkout ::GitCheckout ;
use symbols ::git ::checkout ::GitCheckout ;
use symbols ::hook ::Hook ;
use symbols ::hook ::Hook ;
use symbols ::list ::ListAction ;
use symbols ::list ::ListAction ;
use symbols ::nginx ::server ::NginxServer ;
use symbols ::mariadb ::{ DatabaseDump , MariaDBDatabase , MariaDBUser } ;
use symbols ::nginx ::server ::{ NginxServer , server_config } ;
use symbols ::owner ::Owner ;
use symbols ::owner ::Owner ;
use symbols ::stored_directory ::{ StoredDirectory , StorageDirection } ;
use symbols ::stored_directory ::{ StoredDirectory , StorageDirection } ;
use symbols ::systemd ::reload ::ReloadService ;
use symbols ::systemd ::reload ::ReloadService ;
use symbols ::tls ::SelfSignedTlsCert ;
use symbols ::tls ::SelfSignedTlsCert ;
pub struct SymbolFactory < 'a , C : 'a + CommandRunner , R : 'a + SymbolRunner > {
pub trait Policy {
fn user_name_for_host ( & self , host_name : & 'static str ) -> String ;
}
pub struct DefaultPolicy ;
impl Policy for DefaultPolicy {
fn user_name_for_host ( & self , host_name : & 'static str ) -> String {
host_name . split ( '.' ) . rev ( ) . fold ( String ::new ( ) , | result , part | if result . len ( ) > 0 { result + "_" } else { result } + part )
}
}
pub struct SymbolFactory < 'a , C : 'a + CommandRunner , R : 'a + SymbolRunner , P : 'a + Policy > {
command_runner : & 'a C ,
command_runner : & 'a C ,
acme_command_runner : SetuidCommandRunner < 'a , C > ,
acme_command_runner : SetuidCommandRunner < 'a , C > ,
symbol_runner : & 'a R
symbol_runner : & 'a R ,
policy : & 'a P
}
}
impl < 'b , C : 'b + CommandRunner , R : 'b + SymbolRunner > SymbolFactory < 'b , C , R > {
pub fn new ( command_runner : & 'b C , symbol_runner : & 'b R ) -> Self {
impl < 'b , C : 'b + CommandRunner , R : 'b + SymbolRunner , P : 'b + Policy > SymbolFactory < 'b , C , R , P > {
pub fn new ( command_runner : & 'b C , symbol_runner : & 'b R , policy : & 'b P ) -> Self {
let acme_user = "acme" ; // FIXME: CONFIG
let acme_user = "acme" ; // FIXME: CONFIG
let acme_command_runner = SetuidCommandRunner ::new ( acme_user , command_runner ) ;
let acme_command_runner = SetuidCommandRunner ::new ( acme_user , command_runner ) ;
SymbolFactory { command_runner : command_runner , acme_command_runner : acme_command_runner , symbol_runner : symbol_runner }
SymbolFactory {
command_runner : command_runner ,
acme_command_runner : acme_command_runner ,
symbol_runner : symbol_runner ,
policy : policy
}
}
}
pub fn get_nginx_acme_server < 'a , 'c : 'a , S : 'a + Symbol > ( & 'c self , host : & 'static str , nginx_server_symbol : S ) -> Box < Action + 'a > {
pub fn get_nginx_acme_server < 'a , 'c : 'a , S : 'a + Symbol > ( & 'c self , host : & 'static str , nginx_server_symbol : S ) -> Box < Action + 'a > {
@ -61,11 +80,11 @@ impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
) ) . into_action ( self . symbol_runner )
) ) . into_action ( self . symbol_runner )
}
}
pub fn get_php_fpm_pool_socket_path < 'a > ( & 'a self , user_name : & 'static str ) -> String {
fn get_php_fpm_pool_socket_path < 'a > ( & 'a self , user_name : & str ) -> String {
format ! ( "/run/php/{}.sock" , user_name )
format ! ( "/run/php/{}.sock" , user_name )
}
}
pub fn get_php_fpm_pool < 'a > ( & 'a self , user_name : & 'static str ) -> Box < Action + 'a > {
fn get_php_fpm_pool < 'a > ( & 'a self , user_name : & str ) -> Box < Action + 'a > {
let socket = self . get_php_fpm_pool_socket_path ( user_name ) ;
let socket = self . get_php_fpm_pool_socket_path ( user_name ) ;
Box ::new ( Hook ::new (
Box ::new ( Hook ::new (
File ::new (
File ::new (
@ -84,14 +103,63 @@ pm.max_children = 10"
) ) . into_action ( self . symbol_runner )
) ) . into_action ( self . symbol_runner )
}
}
pub fn get_nginx_php_server < 'a > ( & 'a self , host_name : & 'static str , user_name : & 'static str , root_dir : & 'static str ) -> NginxServer < 'a , C , String > {
let socket = self . get_php_fpm_pool_socket_path ( user_name ) ;
pub fn serve_php < 'a > ( & 'a self , host_name : & 'static str , root_dir : & 'static str ) -> Box < Action + 'a > {
let user_name = self . policy . user_name_for_host ( host_name ) ;
let socket = self . get_php_fpm_pool_socket_path ( & user_name ) ;
Box ::new ( ListAction ::new ( vec ! [
self . get_php_fpm_pool ( & user_name ) ,
self . get_nginx_acme_server ( host_name ,
NginxServer ::new_php (
NginxServer ::new_php (
host_name ,
host_name ,
socket . into ( ) ,
socket . into ( ) ,
root_dir ,
root_dir ,
self . command_runner
self . command_runner
)
)
)
] ) )
}
pub fn serve_dokuwiki < 'a > ( & 'a self , host_name : & 'static str , root_dir : & 'static str ) -> Box < Action + 'a > {
let user_name = self . policy . user_name_for_host ( host_name ) ;
let socket = self . get_php_fpm_pool_socket_path ( & user_name ) ;
Box ::new ( ListAction ::new ( vec ! [
self . get_php_fpm_pool ( & user_name ) ,
self . get_nginx_acme_server ( host_name ,
NginxServer ::new (
host_name ,
server_config ( "hostname" , & format ! ( "
root { } ;
index doku . php ;
location ~ [ ^ / ] \ \ . php ( / | $) { {
fastcgi_pass unix :{ } ;
include \ " snippets / fastcgi - php . conf \ " ;
} }
location ~ / ( data / | conf / | bin / | inc / | install . php ) { { deny all ; } }
location / { { try_files $uri $uri / @ dokuwiki ; } }
location @ dokuwiki { {
# rewrites \ " doku . php / \ " out of the URLs if you set the userewrite setting to . htaccess in dokuwiki config page
rewrite ^ / _media / ( . * ) / lib / exe / fetch . php ? media = $ 1 last ;
rewrite ^ / _detail / ( . * ) / lib / exe / detail . php ? media = $ 1 last ;
rewrite ^ / _export / ( [ ^ / ] + ) / ( . * ) / doku . php ? do = export_ $ 1 & id = $ 2 last ;
rewrite ^ / ( . * ) / doku . php ? id = $ 1 & $args last ;
} }
" ,
root_dir ,
socket ) ) ,
self . command_runner
) )
] ) )
}
pub fn serve_redir < 'a > ( & 'a self , host_name : & 'static str , target : & 'static str ) -> Box < Action + 'a > {
self . get_nginx_acme_server ( host_name , NginxServer ::new_redir ( host_name , target , self . command_runner ) )
}
pub fn serve_static < 'a > ( & 'a self , host_name : & 'static str , dir : & 'a str ) -> Box < Action + 'a > {
self . get_nginx_acme_server ( host_name , NginxServer ::new_static ( host_name , dir , self . command_runner ) )
}
}
pub fn get_stored_directory < 'a , T : Into < String > > ( & 'a self , storage_name : & 'static str , target : T ) -> ( Box < Action + 'a > , Box < Action + 'a > ) {
pub fn get_stored_directory < 'a , T : Into < String > > ( & 'a self , storage_name : & 'static str , target : T ) -> ( Box < Action + 'a > , Box < Action + 'a > ) {
@ -103,6 +171,18 @@ pm.max_children = 10"
)
)
}
}
pub fn get_mariadb_database < 'a > ( & 'a self , name : & 'static str ) -> Box < Action + 'a > {
let db_dump = SimpleStorage ::new ( "/root/data" . to_string ( ) , format ! ( "{}.sql" , name ) ) ;
Box ::new ( ListAction ::new ( vec ! [
Box ::new ( MariaDBDatabase ::new ( name . into ( ) , db_dump . read_filename ( ) . unwrap ( ) . into ( ) , self . command_runner ) ) . into_action ( self . symbol_runner ) ,
Box ::new ( DatabaseDump ::new ( name , db_dump , self . command_runner ) ) . into_action ( self . symbol_runner )
] ) )
}
pub fn get_mariadb_user < 'a > ( & 'a self , user_name : & 'static str ) -> Box < Action + 'a > {
Box ::new ( MariaDBUser ::new ( user_name . into ( ) , self . command_runner ) ) . into_action ( self . symbol_runner )
}
pub fn get_git_checkout < 'a , T : 'a + AsRef < str > > ( & 'a self , target : T , source : & 'a str , branch : & 'a str ) -> Box < Action + 'a > {
pub fn get_git_checkout < 'a , T : 'a + AsRef < str > > ( & 'a self , target : T , source : & 'a str , branch : & 'a str ) -> Box < Action + 'a > {
Box ::new ( GitCheckout ::new ( target , source , branch , self . command_runner ) ) . into_action ( self . symbol_runner )
Box ::new ( GitCheckout ::new ( target , source , branch , self . command_runner ) ) . into_action ( self . symbol_runner )
}
}
@ -111,7 +191,7 @@ pm.max_children = 10"
Box ::new ( Owner ::new ( file , user . into ( ) , self . command_runner ) ) . into_action ( self . symbol_runner )
Box ::new ( Owner ::new ( file , user . into ( ) , self . command_runner ) ) . into_action ( self . symbol_runner )
}
}
pub fn get_file < 'a , F : 'a + Deref < Target = str > , P : 'a + AsRef < Path > > ( & 'a self , path : P , content : F ) -> Box < Action + 'a > {
pub fn get_file < 'a , F : 'a + Deref < Target = str > , Q : 'a + AsRef < Path > > ( & 'a self , path : Q , content : F ) -> Box < Action + 'a > {
Box ::new ( File ::new ( path , content ) ) . into_action ( self . symbol_runner )
Box ::new ( File ::new ( path , content ) ) . into_action ( self . symbol_runner )
}
}
}
}