text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  let authenticateSocketConnection = (() => {
    var _ref3 = _asyncToGenerator(function* (config, socket) {
      // Verify user session
      let cookies = socket.handshake.headers.cookie;
      if (cookies) {
        cookies = cookies.split('; ');
        if (cookies.length > 1) {
          const pSessionCookies = cookies.filter(function (cookie) {
            return cookie.startsWith('P_SESSION');
          });
          const jwtToken = pSessionCookies[0].split('=')[1];
          const principal = yield (0, _auth.validateUserSessionCookies)({ jwtToken });
          if (principal && principal.credentials) {
            return {
              type: 'principal',
              principal: principal.credentials
            };
          }
        }
      }
  
      // Verify bearer token
      const token = socket.handshake.query.token;
      if (token) {
        return {
          type: 'bearer',
          token
        };
      }
      throw (0, _errors.errorWithKey)('not-authorized', { tags: ['warn', 'porg', 'socket-io'], cause: `Error validating socket configuration` });
    });
  
    return function authenticateSocketConnection(_x3, _x4) {
      return _ref3.apply(this, arguments);
    };
  })();
  
  var _path = require('path');
  
  var _path2 = _interopRequireDefault(_path);
  
  var _fs = require('fs');
  
  var _fs2 = _interopRequireDefault(_fs);
  
  var _underscore = require('underscore');
  
  var _underscore2 = _interopRequireDefault(_underscore);
  
  var _papagaio = require('papagaio');
  
  var _socket = require('socket.io');
  
  var _socket2 = _interopRequireDefault(_socket);
  
  var _auth = require('../plugins/auth');
  
  var _joi = require('joi');
  
  var _joi2 = _interopRequireDefault(_joi);
  
  var _errors = require('../plugins/errors');
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
  
  const SOCKETS_FOLDER = 'sockets/on';
  let socketIO;
  
  const setSocketIO = (() => {
    var _ref = _asyncToGenerator(function* ({ config, listener }) {
      // Configuration schema
      const socketConfigsSchema = {
        config: {
          description: _joi2.default.string(),
          event: _joi2.default.string().required(),
          auth: _joi2.default.object().keys({
            'user-session': _joi2.default.array().items(_joi2.default.string()),
            bearers: _joi2.default.array().items(_joi2.default.string().valid(Object.keys(config.auth.staticBearer)))
          })
        },
        handler: _joi2.default.func()
  
        // Read socket configurarion files
      };let dirMainFile = _path2.default.dirname(require.main.filename);
      if (config.nodeStartPath) {
        dirMainFile = _path2.default.resolve(dirMainFile, config.nodeStartPath);
      }
      let normalizePath = _path2.default.join(dirMainFile, SOCKETS_FOLDER);
      const socketsConfigs = [];
      if (!_fs2.default.existsSync(normalizePath)) {
        (0, _papagaio.logger)(['info', 'porg', 'sockets'], 'Porg could not find any sockets folder');
      }
      _fs2.default.readdirSync(normalizePath).forEach(function (file) {
        const module = require(_path2.default.join(normalizePath, file));
        if (module.handler && module.config) {
          socketsConfigs.push(module);
        } else {
          (0, _papagaio.logger)(['info', 'porg', 'sockets'], 'Porg could not find any sockets folder');
        }
      });
  
      // Validate socket configuration files
      if (socketsConfigs.length <= 0) {
        (0, _papagaio.logger)(['info', 'porg', 'sockets'], 'Porg could not find any socket handler files in sockets folder');
        return;
      }
      (0, _papagaio.logger)(['info', 'porg', 'socket-io'], `Porg found ${socketsConfigs.length} on event handlers`);
      yield socketsConfigs.forEach(function (socketConfig) {
        const validation = _joi2.default.validate(socketConfig, socketConfigsSchema);
        if (validation.error) {
          throw (0, _errors.errorWithKey)('validation-error', { tags: ['emerg', 'porg', 'socket-io'], cause: `Error validating socket configuration \n ${validation.error}` });
        }
      });
  
      // Start socket server
      socketIO = (0, _socket2.default)(listener);
  
      // Setup on connection event
      socketIO.on('connection', (() => {
        var _ref2 = _asyncToGenerator(function* (socket) {
          (0, _papagaio.logger)(['info', 'porg', 'socket-io'], 'Client starting connection...');
          try {
            const auth = yield authenticateSocketConnection(config, socket);
            socketsConfigs.forEach(function (socketConfig) {
              // If user is in a session and the event supports user-session
              if (auth.type === 'principal' && Object.keys(socketConfig.config.auth).includes('user-session')) {
                const principal = auth.principal;
                const missingRoles = _underscore2.default.difference(socketConfig.config.auth['user-session'], principal.roles);
                if (missingRoles.length <= 0) {
                  socket.on(socketConfig.config.event, function (params) {
                    return socketConfig.handler({ socket, auth, params });
                  });
                  (0, _papagaio.logger)(['info', 'porg', 'socket-io'], `Socket IO handler configured for event ${socketConfig.config.event} with roles ${socketConfig.config.auth['user-session']}`);
                  return;
                }
                (0, _papagaio.logger)(['warn', 'porg', 'socket-io'], `Client with username ${principal.sub} tried to send an event ${socketConfig.config.event} with roles ${principal.roles}`);
              } else if (auth.type === 'bearer' && socketConfig.config.auth.bearers) {
                const bearers = socketConfig.config.auth.bearers;
                const token = auth.token;
                bearers.forEach(function (bearer) {
                  if (token === config.auth.staticBearer[bearer]) {
                    socket.on(socketConfig.config.event, function (params) {
                      return socketConfig.handler({ socket, auth, params });
                    });
                    (0, _papagaio.logger)(['info', 'porg', 'socket-io'], `Socket IO handler configured for event ${socketConfig.config.event} with bearer ${token}`);
                  }
                });
              }
            });
            (0, _papagaio.logger)(['info', 'porg', 'socket-io'], `Connection established`);
          } catch (err) {
            (0, _papagaio.logger)(['info', 'porg', 'socket-io'], `Unknown user tried to connect to Socket IO\n${err}`);
            socket.disconnect();
          }
        });
  
        return function (_x2) {
          return _ref2.apply(this, arguments);
        };
      })());
    });
  
    return function setSocketIO(_x) {
      return _ref.apply(this, arguments);
    };
  })();
  
  const getSocketIO = () => {
    return socketIO;
  };
  
  exports.default = {
    getSocketIO,
    setSocketIO
  };
  module.exports = exports['default'];