UNPKG

postelf

Version:

a web based solution for email server/client based on postfix

884 lines (824 loc) 31.1 kB
/* eslint-disable no-unused-vars */ class Service { constructor (options) { this.options = options || {}; this.coreServiceStarted=false; const path = require('path'); this.scriptName = "["+path.basename(__filename)+"] "; } setup(app) { console.log(this.scriptName+"service wizard started") this.app = app; this.CORE_API_URL = 'http://localhost:'+app.get("coreport"); } async update (id, data, params) { //try connect console.log(this.scriptName+JSON.stringify(data)); if(data.cmd=="testDatabase"){ return this.testDatabase(data.data); } else if(data.cmd=="testDependency"){ return this.testDependency(data.data); } else if(data.cmd=="finishWizard"){ return this.finishWizard(data.data); } else if(data.cmd=="getConfig"){ return this.getConfig(); } else if(data.cmd=="startCoreService"){ return this.startCoreService(data.data); } } async testDatabase(data){ const pg = require('pg'); var con = new pg.Client({ host: data.dbAddress, port: '5432', user: data.dbUSer, password: data.dbPassword, database: data.dbName }) let success=false; let error=null; const pConnect=con.connect() .then(() => {success=true;}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'connection error', err.stack);}); await pConnect; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } //try create table success=false; let pQuery = con.query('drop table if exists test') .then(() => {success=true;}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query('create table test(col1 varchar(10))') .then(() => {success=true;}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } //try drop table success=false; pQuery = con.query('drop table test') .then(() => {success=true;}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } con.end(); return {code:200}; } async testDependency(data){ //start core service if not started if(!this.coreServiceStarted) this.startCoreService(data); else console.log(this.scriptName+"core service already started, skip"); //check if package is installed let pkgDependency=["postgresql","postfix","dovecot","cyrus-sasl","cyrus-sasl-sql"]; let error=null; const util = require('util'); const exec = util.promisify(require('child_process').exec); let i=0; let ret=new Array(); for (i=0;i<pkgDependency.length;i++) { console.log(this.scriptName+"test package "+pkgDependency[i]); await exec("rpm -qi "+pkgDependency[i]) .then((result) => { let idx=result.stdout.indexOf("Version :"); if(idx==-1) ret.push({name:"Package "+pkgDependency[i], error:"not installed"}); else ret.push({name:"Package "+pkgDependency[i]}); console.log(this.scriptName+"result added:"+ret); },(err)=>{ ret.push({name:"Package "+pkgDependency[i], error:err.toString()}); error=err; console.error(this.scriptName+'testDependency error:'+err.toString()); }) .catch((err) => { ret.push({name:"Package "+pkgDependency[i], error:err.toString()}); error=err; console.error(this.scriptName+'testDependency error:'+err.toString(), err.stack); }); } console.log(this.scriptName+"package test done"); //check file path access let paths=[data.baseMailFolder]; let pathResult=await this.testAccess(paths); for(i=0;i<pathResult.length;i++){ if(pathResult[i].result==0){ ret.push({name:"Path "+pathResult[i].path}); } else{ ret.push({name:"Path "+pathResult[i].path,error:"access denied"}); } } console.log(this.scriptName+"access test done"); //check if service is enabled pkgDependency=["postgresql","postfix","dovecot","saslauthd"]; const systemctl = require('systemctl') for(i=0;i<pkgDependency.length;i++) { let serviceEnabled=false; let jobService=systemctl.isEnabled('postfix').then(enabled => { serviceEnabled=enabled; }) await jobService; if(serviceEnabled) ret.push({name:"Service "+pkgDependency[i]}); else ret.push({name:"Service "+pkgDependency[i],error:"no enabled"}); } console.log(this.scriptName+"access service done"); console.log(this.scriptName+"result returned:"+ret); return ret; } async testAccess(paths){ console.log(this.scriptName+paths); const fs = require('fs'); let ret=[]; let i=0; for (i=0;i<paths.length;i++) { let path=paths[i]; try { fs.accessSync(path, fs.constants.R_OK | fs.constants.W_OK); ret.push({path:path,result:0}); } catch (err) { ret.push({path:path,result:-1}); } } return ret; } async finishWizard(data){ if(!this.coreServiceStarted){ return {code:500,error:"core service is not started"}; } //database tables let ret = await this.initDB(data); if(ret.error) return ret; if(!data.selfsign){ data.selfsign={ countryName:"AU", stateOrProvinceName:"VIC", localityName:"MEL", organizationName:"BYTESTUDIO", commonName:"POSTELF.COM", emailAddress:"ADMIN@BYTESTUDIO.COM.AU" }; } //generate ssl cert files ret = await this.generateKeyCert(data); if(ret.error) return ret; ret= await this.generateConfigFile(data); if(ret.error) return ret; ret= await this.restartService(data); let i=0; let restartErr=''; for(i=0;i<ret.length;i++) { let r=ret[i]; if(r.error) restartErr+=r.error+"."; } if(restartErr.length>0) return {code:500,error:restartErr}; const fs = require('fs'); let pjson = require(__dirname+'/../../../package.json'); let path=__dirname+"/../../../config/installed.json"; console.log(this.scriptName+"write install record:"+pjson.version+","+path); let installed={version:pjson.version, dbAddress:data.dbAddress, dbUSer:data.dbUSer, dbPassword:data.dbPassword, dbName:data.dbName }; fs.writeFileSync(path,JSON.stringify(installed, null, 2),{mode:0o744}); return {code:200}; //postfix config file //sasl2 config //dovecot configureation } async initDB(config){ const pg = require('pg'); var con = new pg.Client({ host: config.dbAddress, port: '5432', user: config.dbUSer, password: config.dbPassword, database: config.dbName }) try{ //connect to db let success=false; let error=null; const pConnect=con.connect() .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'connection error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'connection error', err.stack);}); await pConnect; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"connected to db"); //try create table admin success=false; let pQuery = con.query("DROP TABLE IF EXISTS admin") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query('CREATE TABLE IF NOT EXISTS admin(\r\n'+ "id serial NOT NULL PRIMARY KEY,\r\n"+ "username varchar(255) NOT NULL default '' UNIQUE,\r\n"+ "password varchar(255) NOT NULL default '' ,\r\n"+ "created timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "modified timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "active smallint NOT NULL default '1')") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"admin table created"); //try create table domain success=false; pQuery = con.query("DROP TABLE IF EXISTS domain") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } //try create table domain success=false; pQuery = con.query('CREATE TABLE IF NOT EXISTS domain(\r\n'+ "domain varchar(255) NOT NULL default '' PRIMARY KEY,\r\n"+ "description varchar(255) NOT NULL default '',\r\n"+ "mailboxes integer NOT NULL default '0',\r\n"+ "maxquota integer NOT NULL default '0',\r\n"+ "created timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "modified timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "active smallint NOT NULL default '1')") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"domain table created"); //try create table mailbox success=false; pQuery = con.query("DROP TABLE IF EXISTS mailbox") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query('CREATE TABLE IF NOT EXISTS mailbox(\r\n'+ "username varchar(255) NOT NULL default '' PRIMARY KEY,\r\n"+ "password varchar(255) NOT NULL default '',\r\n"+ "name varchar(255) NOT NULL default '',\r\n"+ "quota integer NOT NULL default '0',\r\n"+ "domain varchar(255) NOT NULL default '',\r\n"+ "created timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "modified timestamp NOT NULL default '1970-01-01 00:00:00',\r\n"+ "active smallint NOT NULL default '1')") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"mailbox table created"); //create record for admin login success=false; pQuery = con.query("INSERT INTO admin (username,password,created,modified,active) VALUES ($1,$2,$3,$4,$5)" ,[config.loginName,config.password,"now()","now()",1]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"admin record created"); //create record for domain success=false; pQuery = con.query("INSERT INTO domain (domain,created,modified,active) VALUES ($1,$2,$3,$4)" ,[config.emailDomain,"now()","now()",1]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"domain record created"); //create record for mailbox success=false; pQuery = con.query("INSERT INTO mailbox (\"username\",password,domain,created,modified,active) VALUES ($1,$2,$3,$4,$5,$6)" ,[config.emailUser,config.emailPassword,config.emailDomain,"now()","now()",1]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"mailbox record created"); //try create table config success=false; pQuery = con.query("DROP TABLE IF EXISTS config") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query('CREATE TABLE IF NOT EXISTS config(\r\n'+ "conf_key varchar(255) NOT NULL PRIMARY KEY,\r\n"+ "conf_value varchar(1024) NOT NULL default '' )") .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"config table created"); success=false; pQuery = con.query("INSERT INTO config (conf_key,conf_value) VALUES ($1,$2)" ,["baseMailFolder",config.baseMailFolder]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query("INSERT INTO config (conf_key,conf_value) VALUES ($1,$2)" ,["runasuser",config.runasuser]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } success=false; pQuery = con.query("INSERT INTO config (conf_key,conf_value) VALUES ($1,$2)" ,["sudoPassword",config.sudoPassword]) .then(() => {success=true;},(err)=>{success=false; error=err; console.error(this.scriptName+'query error', err.stack);}) .catch((err) => {success=false; error=err; console.error(this.scriptName+'query error', err.stack);}); await pQuery; if(!success){ con.end(); return {code:500, error:error.toString(), stack:error}; } console.log(this.scriptName+"config records created"); //return OK con.end(); return {code:200}; } catch(err){ con.end(); return {code:500,error:err.toString()}; } finally{ con.end(); } } async createFolderAsRoot(path,mode){ const rp = require('request-promise'); const options = { method: 'PUT', uri: this.CORE_API_URL+"/postelf-core", body: { cmd:"createFolder", data:{path:path,mode:mode} }, json: true }; return rp(options) .then( (res) => { if(res.error){ console.error(this.scriptName+"createFolderAsRoot:"+path+" error:"+res.error); this.error=err.toString(); } },(err)=>{ console.error(this.scriptName+"createFolderAsRoot:"+path+" error:"+err.toString()); this.error=err.toString(); }) .catch( (err) =>{ console.error(this.scriptName+"createFolderAsRoot:"+path+"error:"+err.toString()); this.error=err.toString(); }); } async writeFileAsRoot(path,content,mode){ const rp = require('request-promise'); const options = { method: 'PUT', uri: this.CORE_API_URL+"/postelf-core", body: { cmd:"writeFile", data:{path:path,content:content,mode:mode} }, json: true }; return rp(options) .then( (res) => { if(res.error){ console.error(this.scriptName+"writeFileAsRoot:"+path+" error:"+res.error); this.error=res.error.toString(); } },(err)=>{ console.error(this.scriptName+"writeFileAsRoot:"+path+" error:"+err.toString()); this.error=err.toString(); }) .catch( (err) =>{ console.error(this.scriptName+"writeFileAsRoot:"+path+"error:"+err.toString()); this.error=err.toString(); }); } async restartServiceAsRoot(service){ const rp = require('request-promise'); const options = { method: 'PUT', uri: this.CORE_API_URL+"/postelf-core", body: { cmd:"restartService", data:{service:service} }, json: true }; return rp(options) .then( (res) => { if(res.error){ console.error(this.scriptName+"restartServiceAsRoot:"+path+" error:"+res.error); this.error=res.error.toString(); } },(err)=>{ console.error(this.scriptName+"restartServiceAsRoot:"+path+" error:"+err.toString()); this.error=err.toString(); }) .catch( (err) =>{ console.error(this.scriptName+"restartServiceAsRoot:"+path+"error:"+err.toString()); this.error=err.toString(); }); } async generateKeyCert(config){ const fs = require('fs'); const node_openssl = require('node-openssl-cert'); const openssl = new node_openssl(); let pKey=''; let pCsr=''; let pCrt=''; let error = undefined; try{ //check if cert folder exists if(!fs.existsSync("/etc/postfix/certs")){ console.log(this.scriptName+"cert folder not exist, create new one"); let jobMK=this.createFolderAsRoot("/etc/postfix/certs",0o755); await jobMK; if(jobMK.error){ return {code:500,error:jobMK.error}; } } //create ssl key let jobKey = new Promise((resolve, reject) => { openssl.generateRSAPrivateKey({}, function(err, key, cmd) { if (err) { error=err; reject(err); } pKey=key; return resolve([cmd,key]) }); }).then( async ([cmd,key])=>{},err=>{error=err;}); await jobKey; if(error){ return {code:500,error:error.toString()}; } //write ssl key to file let jobWK=this.writeFileAsRoot("/etc/postfix/certs/server.key",pKey,0o744); await jobWK; if(jobWK.error){ return {code:500,error:jobWK.error}; } console.log(this.scriptName+"key created"); //create csr let csroptions = { hash: 'sha256', subject: { countryName: config.selfsign.countryName, stateOrProvinceName: config.selfsign.stateOrProvinceName, localityName: config.selfsign.localityName, postalCode: 'N/A', streetAddress: 'N/A', organizationName: config.selfsign.organizationName, organizationalUnitName: 'N/A', commonName: [ config.selfsign.commonName ], emailAddress: config.selfsign.emailAddress } } let jobCsr = new Promise((resolve, reject) => { openssl.generateCSR(csroptions, pKey, '', function(err, csr, cmd) { if(err) { error=err; return reject(err) } else { pCsr=csr; return resolve([cmd.command,csr,cmd.files.config]) } }); }); await jobCsr; if(error){ return {code:500,error:error.toString()}; } //write csr to file let jobWCSR=this.writeFileAsRoot("/etc/postfix/certs/server.csr",pCsr,0o744); await jobWCSR; if(jobWCSR.error){ return {code:500,error:jobWCSR.error}; } console.log(this.scriptName+"csr created"); //create crt var cacsroptions = { hash: 'sha256', days: 240, subject: { countryName: config.selfsign.countryName, stateOrProvinceName: config.selfsign.stateOrProvinceName, localityName: config.selfsign.localityName, postalCode: 'N/A', streetAddress: 'N/A', organizationName: config.selfsign.organizationName, organizationalUnitName: 'N/A', commonName: [ config.selfsign.commonName ] }, } let jobSign = new Promise((resolve, reject) => { openssl.selfSignCSR(pCsr, cacsroptions, pKey, '', function(err, cacrt, cmd) { if(err) { error=err; return reject(err) } else { pCrt=cacrt; return resolve([cmd,cacrt]) } }); }); await jobSign; if(error){ return {code:500,error:error.toString()}; } //write crt to file let jobWCRT=this.writeFileAsRoot("/etc/postfix/certs/server.crt",pCrt,0o744); await jobWCRT; if(jobWCRT.error){ return {code:500,error:jobWCRT.error}; } console.log(this.scriptName+"crt created"); } catch(err){ console.log("catch"); error=err; return {code:500,error:error}; } return {code:200}; } async generateConfigFile(config){ const fs = require('fs'); try{ const { exec } = require('child_process'); let uid=''; let gid=''; let error=''; let jobID = new Promise((resolve, reject) => { exec('id -u '+config.runasuser, (err, stdout, stderr) => { if (err) { error=err; reject(err); return; } if(stderr.length>0){ error=stderr; reject(stderr); return; } uid=stdout.replace("\n",""); resolve(stdout); }); }).then((stdout)=>{},(err)=>{}).catch((err)=>{});; await jobID; console.log(this.scriptName+"uid is:"+uid); jobID = new Promise((resolve, reject) => { exec('id -g '+config.runasuser, (err, stdout, stderr) => { if (err) { error=err; reject(err); return; } if(stderr.length>0){ error=stderr; reject(stderr); return; } gid=stdout.replace("\n",""); resolve(stdout); }); }).then((stdout)=>{},(err)=>{}).catch((err)=>{});; await jobID; console.log(this.scriptName+"gid is:"+gid); if(error.length>0) return {code:500,error:error}; //create sasl2 config let temp=this.app.get('sasl_template').join("\n"); temp=temp.replace("[[@dbAddress@]]",config.dbAddress); temp=temp.replace("[[@dbUSer@]]",config.dbUSer); temp=temp.replace("[[@dbPassword@]]",config.dbPassword); temp=temp.replace("[[@dbName@]]",config.dbName); //write crt to file let jobWsasl2=this.writeFileAsRoot("/etc/sasl2/smtpd.conf",temp,0o744); await jobWsasl2; if(jobWsasl2.error){ return {code:500,error:jobWsasl2.error}; } console.log(this.scriptName+"sasl2 config created"); //create dovecot config temp=this.app.get('dovecot_template').join("\n"); temp=temp.replace("[[@baseMailFolder@]]",config.baseMailFolder); let jobWdovecot=this.writeFileAsRoot("/etc/dovecot/dovecot.conf",temp,0o744); await jobWdovecot; if(jobWdovecot.error){ return {code:500,error:jobWdovecot.error}; } console.log(this.scriptName+"dovecot config created"); temp=this.app.get('dovecot_auth_template').join("\n"); temp=temp.replace("[[@baseMailFolder@]]",config.baseMailFolder); temp=temp.replace("[[@baseMailFolder@]]",config.baseMailFolder); //need to do it twice becasue there are 2 instances need to be replaced temp=temp.replace("[[@dbAddress@]]",config.dbAddress); temp=temp.replace("[[@dbUSer@]]",config.dbUSer); temp=temp.replace("[[@dbPassword@]]",config.dbPassword); temp=temp.replace("[[@dbName@]]",config.dbName); temp=temp.replace("[[@uid@]]",uid); temp=temp.replace("[[@gid@]]",gid); let jobWdovecot2=this.writeFileAsRoot("/etc/dovecot/dovecot-sql.conf",temp,0o744); await jobWdovecot2; if(jobWdovecot2.error){ return {code:500,error:jobWdovecot2.error}; } console.log(this.scriptName+"dovecot auth config created"); temp=this.app.get('pfx_virtual_template').join("\n"); temp=temp.replace("[[@dbAddress@]]",config.dbAddress); temp=temp.replace("[[@dbUSer@]]",config.dbUSer); temp=temp.replace("[[@dbPassword@]]",config.dbPassword); temp=temp.replace("[[@dbName@]]",config.dbName); let jobWpfx1=this.writeFileAsRoot("/etc/postfix/virtual.cf",temp,0o744); await jobWpfx1; if(jobWpfx1.error){ return {code:500,error:jobWpfx1.error}; } console.log(this.scriptName+"postfix virtual config created"); temp=this.app.get('pfx_vmailbox_template').join("\n"); temp=temp.replace("[[@dbAddress@]]",config.dbAddress); temp=temp.replace("[[@dbUSer@]]",config.dbUSer); temp=temp.replace("[[@dbPassword@]]",config.dbPassword); temp=temp.replace("[[@dbName@]]",config.dbName); let jobWpfx2=this.writeFileAsRoot("/etc/postfix/vmailbox.cf",temp,0o744); await jobWpfx2; if(jobWpfx2.error){ return {code:500,error:jobWpfx2.error}; } console.log(this.scriptName+"postfix vmailbox config created"); temp=this.app.get('pfx_main').join("\n"); temp=temp.replace("[[@uid@]]",uid); temp=temp.replace("[[@gid@]]",gid); temp=temp.replace("[[@baseMailFolder@]]",config.baseMailFolder); let jobWpfx3=this.writeFileAsRoot("/etc/postfix/main.cf",temp,0o744); await jobWpfx3; if(jobWpfx3.error){ return {code:500,error:jobWpfx3.error}; } console.log(this.scriptName+"postfix main config created"); temp=this.app.get('pfx_master').join("\n"); let jobWpfx4=this.writeFileAsRoot("/etc/postfix/master.cf",temp,0o744); await jobWpfx4; if(jobWpfx4.error){ return {code:500,error:jobWpfx4.error}; } console.log(this.scriptName+"postfix master config created"); } catch(err) { return {code:500,error:err.toString()}; } return {code:200}; } async restartService(config){ let arrServices=["saslauthd","dovecot","postfix",]; const { exec } = require('child_process'); let arrRet=[]; let i=0; for(i=0;i<arrServices.length;i++){ let service=arrServices[i]; let jobRestart=this.restartServiceAsRoot(service); await jobRestart; if(jobRestart.error){ arrRet.push({cmd:'service restart '+service, error:jobRestart.toString()}); } else{ arrRet.push({cmd:'service restart '+service}); } console.log(this.scriptName+service+" restarted"); } return arrRet; } async getConfig() { return new Promise((resolve, reject) => { const fs = require('fs'); let path=__dirname+"/../../../config/installed.json"; if(fs.existsSync(path)) resolve({code:200,installed:"yes"}); else resolve({code:200,installed:"no"}); }).then((ret)=>{ console.log(this.scriptName+ret); return ret;}); } async startCoreService(config) { return new Promise((resolve, reject) => { try{ var sudo = require('./../../sudojs'); sudo.setPassword(config.sudoPassword); sudo.check((result)=>{ if(!result) reject({code:500,error:"wrong sudo password"}); }); var options = {check: true, withResult: true}; console.log(this.scriptName+__dirname +'/../coreservice.js'); var command = ['node', __dirname +'/../coreservice.js']; sudo.exec(command, options, function(err, pid, result) { console.log("err:"+err+",pid:"+pid+",result:"+result); }); resolve({code:200}); console.log(this.scriptName+"core service started"); this.coreServiceStarted=true; } catch(err) { console.log(this.scriptName+"failed to start core service"); console.log(this.scriptName+err.toString()); reject({code:500,error:err.toString()}); } }).then((ret)=>{ console.log(this.scriptName+ret); return ret;}, (err)=>{ console.log(this.scriptName+err); return err;}); } } module.exports = function (options) { return new Service(options); }; module.exports.Service = Service;