@ -5,7 +5,11 @@ import { NumberValidator } from '../../../validators/number.validator';
import { Server } from '../../../interfaces/server' ;
import { Server } from '../../../interfaces/server' ;
import { ServerService } from '../../../services/server.service' ;
import { ServerService } from '../../../services/server.service' ;
import { DataService } from '../../../services/data.service' ;
import { DataService } from '../../../services/data.service' ;
import Parser , { Property , Section , Sections } from "@jedmao/ini-parser" ;
import { Peer } from "../../../interfaces/peer" ;
import { forkJoin , from , Observable , of } from "rxjs" ;
import { concatAll , concatMap , filter , map , mergeAll , mergeMap , switchMap } from "rxjs/operators" ;
import { NotifierService } from "angular-notifier" ;
@Component ( {
@Component ( {
selector : 'app-add-server' ,
selector : 'app-add-server' ,
templateUrl : './add-server.component.html' ,
templateUrl : './add-server.component.html' ,
@ -15,28 +19,50 @@ export class AddServerComponent implements OnInit {
@Input ( ) servers : Server [ ] ;
@Input ( ) servers : Server [ ] ;
serverForm = new FormGroup ( {
// Translates from wg configuration keywords to form and backend keywords
address : new FormControl ( '' , [ IPValidator . isIPAddress ] ) ,
wgConfTranslation = {
interface : new FormControl ( '' , [ Validators . required , Validators . minLength ( 3 ) ] ) ,
"Address" : "address" ,
listen_port : new FormControl ( '' , [ Validators . required , NumberValidator . stringIsNumber ] ) ,
"PrivateKey" : "private_key" ,
endpoint : new FormControl ( '' , Validators . required ) ,
"ListenPort" : "listen_port" ,
private_key : new FormControl ( '' ) ,
"PostUp" : "post_up" ,
public_key : new FormControl ( '' ) ,
"PostDown" : "post_down" ,
shared_key : new FormControl ( '' ) ,
"PublicKey" : "public_key" ,
post_up : new FormControl ( '' ) ,
post_down : new FormControl ( '' ) ,
// Peer
"Endpoint" : "endpoint" ,
// Unused on backend
"AllowedIPs" : "allowed_ips" ,
configuration : new FormControl ( '' ) ,
"DNS" : "dns"
is_running : new FormControl ( false ) ,
}
peers : new FormControl ( [ ] ) ,
} ) ;
serverForm : FormGroup = null ;
isEdit = false ;
isEdit = false ;
editServer : Server = null ;
editServer : Server = null ;
constructor ( private serverAPI : ServerService , private comm : DataService ) { }
initForm ( ) {
this . serverForm = new FormGroup ( {
address : new FormControl ( '' , [ IPValidator . isIPAddress ] ) ,
interface : new FormControl ( '' , [ Validators . required , Validators . minLength ( 3 ) ] ) ,
listen_port : new FormControl ( '' , [ Validators . required , NumberValidator . stringIsNumber ] ) ,
endpoint : new FormControl ( '' , Validators . required ) ,
private_key : new FormControl ( '' ) ,
public_key : new FormControl ( '' ) ,
shared_key : new FormControl ( '' ) ,
post_up : new FormControl ( '' ) ,
post_down : new FormControl ( '' ) ,
// Unused on backend
configuration : new FormControl ( '' ) ,
is_running : new FormControl ( false ) ,
peers : new FormControl ( [ ] ) ,
} ) ;
}
constructor ( private serverAPI : ServerService , private comm : DataService , private notify : NotifierService ) {
}
ngOnInit ( ) : void {
ngOnInit ( ) : void {
this . initForm ( ) ;
this . comm . on ( 'server-edit' ) . subscribe ( ( data : Server ) = > {
this . comm . on ( 'server-edit' ) . subscribe ( ( data : Server ) = > {
this . isEdit = true ;
this . isEdit = true ;
@ -47,6 +73,118 @@ export class AddServerComponent implements OnInit {
}
}
parseFiles ( $event ) {
const files : File [ ] = $event . target . files ;
let observables = [ ]
Array . from ( files ) . forEach ( ( file : File ) = > {
let obs = from ( [ file ] )
. pipe ( map ( x = > from ( x . text ( ) ) ) )
. pipe ( mergeMap ( x = > x ) )
. pipe ( map ( ( x ) = > new Parser ( ) . parse ( x ) . items ) )
. pipe ( map ( ( x : Section [ ] ) = > x . filter ( y = > y . name !== "" && y . name != null ) ) )
. pipe ( map ( ( x : Section [ ] ) = > {
let data : any = { }
// Store filename
data . fileName = file . name ;
// Convert nodes to key-value dict
x . forEach ( ( y : any ) = > {
y . nodes = y . nodes . reduce ( ( result , filter ) = > {
result [ this . wgConfTranslation [ filter [ "key" ] ] ] = filter [ "value" ] ;
return result ;
} , { } ) ;
} )
data . sections = x ;
// Look for endpoint in peer configuration. TODO - Better way?
data . isClient = data . sections
. filter ( section = > Object . keys ( section . nodes ) . find ( nk = > nk === "endpoint" ) )
. length > 0 ;
// 'Detect' if its a client
return data
} ) ) ;
observables . push ( obs ) ;
} ) ;
forkJoin ( observables ) . subscribe ( data = > {
let server : any = data . filter ( ( x : any ) = > ! x . isClient ) ;
if ( server . length !== 1 ) {
// TODO output error - should only be one server
this . notify . notify ( "error" , "Detected multiple server files!" )
return false ;
}
server = server [ 0 ] ;
const peers = data . filter ( ( x : any ) = > x . isClient ) ;
//console.log(peers)
this . importProcessServer ( server ) ;
peers . forEach ( peer = > {
this . importProcessPeer ( peer ) ;
} )
} )
}
importProcessServer ( server ) {
let iFace : any = server . sections . find ( x = > x . name == "Interface" )
const sPeers = server . sections . filter ( x = > x . name == "Peer" ) ;
if ( iFace === null ) {
// TODO error out - should have [interface] on server
this . notify . notify ( "error" , "Could not find [Interface] section" )
return false ;
}
iFace . nodes [ "peers" ] = sPeers
. map ( x = > x . nodes )
. map ( x = > {
x . server_id = - 1 ;
x . address = x . allowed_ips ; // Allowed_ips in server is the address of the peer (Seen from server perspective)
x . allowed_ips = null ; // This should be retrieved from peer data config
return x ;
} )
this . serverForm . patchValue ( {
interface : server . fileName . replace ( ".conf" , "" )
} )
this . serverForm . patchValue ( iFace . nodes )
}
importProcessPeer ( peer ) {
let formPeers = this . serverForm . controls . peers . value ;
let iFace : any = peer . sections . find ( x = > x . name == "Interface" )
const sPeers = peer . sections . filter ( x = > x . name == "Peer" ) ;
if ( sPeers . length > 1 ) {
// TODO not supported for multi-server peers
this . notify . notify ( "error" , "Multi-server peers are not supported! Peer " + peer . fileName +
" will be imported partially." )
return false ;
}
let sPeer = sPeers [ 0 ] ;
let formPeer = formPeers
. find ( x = > x . address . split ( "/" ) [ 0 ] === iFace . nodes . address . split ( "/" ) [ 0 ] )
formPeer . name = peer . fileName ;
formPeer . private_key = iFace . nodes . private_key ;
formPeer . allowed_ips = sPeer . nodes . allowed_ips ;
formPeer . dns = iFace . nodes . dns ;
this . serverForm . patchValue ( {
endpoint : sPeer.nodes.endpoint.split ( ":" ) [ 0 ] ,
public_key : sPeer.nodes.public_key
} )
}
add ( form : Server ) {
add ( form : Server ) {
if ( this . isEdit ) {
if ( this . isEdit ) {
@ -84,4 +222,11 @@ export class AddServerComponent implements OnInit {
} ) ;
} ) ;
} ) ;
} ) ;
}
}
resetForm() {
this . isEdit = false ;
this . editServer = null ;
this . initForm ( )
}
}
}