SylowTech/sylow

View on GitHub
cli/server.js

Summary

Maintainability
D
1 day
Test Coverage
#!/usr/bin/env node
/* eslint-env node */
/* eslint-disable object-shorthand */
/* eslint-disable func-names */
/* eslint-disable prefer-arrow-callback */
/* eslint-disable no-console */

const fs = require('fs');
const mongoose = require('mongoose');
const uuidV4 = require('uuid/v4');
const forge = require('node-forge');

const utils = require('./util');

const forgePki = forge.pki;
const forgeRsa = forge.pki.rsa;

const serverSchema = {
  _id: { type: String, required: true, default: uuidV4 },
  name: { type: String },
  domain: { type: String, required: true },
  description: { type: String },
  contacted: { type: Date, default: Date.now },
  keypair: {
    private: { type: String },
    public: { type: String }
  },
  authoritative: { type: Boolean, default: false },
  created: { type: Date, default: Date.now, required: true },
  updated: { type: Date, default: Date.now }
};

const Server = mongoose.model('Server', serverSchema);

function generateRsa(cb) {
  return forgeRsa.generateKeyPair({ bits: 2048, workers: -1 }, function (err, keypair) {
    if (err) {
      return cb(err);
    }
    return cb(null, {
      private: forgePki.privateKeyToPem(keypair.privateKey),
      public: forgePki.publicKeyToPem(keypair.publicKey)
    });
  });
}

function createServer(datas) {
  return new Promise((resolve, reject) => {
    Server
      .findOne({ authoritative: true })
      .exec()
      .then((server) => {
        if (server) {
          return reject('An authoritative server already exists...');
        }
        return resolve(Server.create(datas));
      });
  });
}

function getAuthoritative() {
  return new Promise((resolve, reject) => {
    Server
      .findOne({ authoritative: true })
      .exec()
      .then((server) => {
        if (server) {
          return resolve(server);
        }
        return reject('No authoritative server was found...');
      })
      .catch(err => reject(err));
  });
}

module.exports = {
  newServer: function (domain, options) {
    utils.mongooseConnect();
    const validOptions = ['name', 'description'];
    if (!domain) {
      console.error('Domain missing');
      process.exit(1);
    }

    const finalDatas = {
      domain,
      keypair: {
        public: null,
        private: null
      }
    };
    validOptions.forEach(function (i) {
      if (options[i] && typeof options[i] !== 'function') {
        finalDatas[i] = options[i];
      }
    });
    finalDatas.authoritative = true;

    if (options.publickeyFile && options.privatekeyFile) {
      finalDatas.keypair = {
        public: fs.readFileSync(options.publickeyFile, 'utf8'),
        private: fs.readFileSync(options.privatekeyFile, 'utf8')
      };
      createServer(finalDatas)
        .then(() => {
          console.log('Success!');
          process.exit(0);
        })
        .catch((e) => {
          console.error(e);
          process.exit(1);
        });
    } else {
      generateRsa(function (err, keypair) {
        if (err) {
          console.error(err);
          process.exit(1);
        }
        finalDatas.keypair = keypair;
        createServer(finalDatas)
          .then(() => {
            console.log('Success!');
            process.exit(0);
          })
          .catch((e) => {
            console.error(e);
            process.exit(1);
          });
      });
    }
  },

  exportServer: function (options) {
    utils.mongooseConnect();
    let targetFile = options.file ? options.file : 'server.json';
    targetFile = targetFile.endsWith('.json') ? targetFile : targetFile.concat('.json');
    getAuthoritative()
      .then((server) => {
        fs.writeFile(targetFile, JSON.stringify(server), (err) => {
          if (err) {
            console.log(err);
            process.exit(1);
          }
          console.log(`Server records saved in ${targetFile}`);
          process.exit(0);
        });
      })
      .catch((err) => {
        console.log(err);
        process.exit(1);
      });
  },

  editServer: function (options) {
    utils.mongooseConnect();
    const validOptions = ['name', 'domain'];

    const finalDatas = {};
    validOptions.forEach(function (i) {
      if (options[i] && typeof options[i] !== 'function') {
        finalDatas[i] = options[i];
      }
    });
    if (options.publickeyFile || options.privatekeyFile) {
      finalDatas.keypair = {};
      if (options.publickeyFile) {
        const pk = fs.readFileSync(options.publickeyFile, 'utf-8');
        Object.assign(finalDatas.keypair, { public: pk });
      }
      if (options.privatekeyFile) {
        const pk = fs.readFileSync(options.privatekeyFile, 'utf-8');
        Object.assign(finalDatas.keypair, { private: pk });
      }
    }

    getAuthoritative()
      .then(server =>
        Server
          .findOneAndUpdate({ _id: server._id }, { $set: finalDatas }, { new: true })
          .then(() => {
            console.log('The server has been updated');
            process.exit(0);
          })
      )
    .catch((err) => {
      console.error(err);
      process.exit(1);
    });
  }
};