<commit_before>import React from 'react';
import { remove, map, clone } from 'lodash';
import { getImageUrlFromProp, getEditedImageUrl, displayCaption } from '../../helpers';

import './post.scss';

import Tags from '../Tags';
import PostTile from '../PostTile';
import Quantity from '../Quantity';
import TextBlock from '../TextBlock';
import ReviewBlock from '../ReviewBlock';
import StatusButton from '../StatusButton';
import MetaInformation from '../MetaInformation';
import UserInformation from '../Users/UserInformation';

class Post extends React.Component {
  getOtherPosts(post) {
    const post_id = post['id'];
    const signup = this.props.signup;

    var posts = signup.posts ? signup.posts : post.siblings.data;

    // get array of posts
    const other_posts = clone(posts);

    // find index that has that post_id and remove
    const big_post = remove(other_posts, function(current_post) {
      return current_post['id'] == post_id;
    });

    // return the rest of the original array
    return other_posts;
  }

  render() {
    const post = this.props.post;
    const caption = displayCaption(post);
    const user = this.props.user ? this.props.user : null;
    const signup = this.props.signup;
    const campaign = this.props.campaign;

    return (

        {/* Post Images */}

              Original Photo

              Edited Photo

          {this.props.showSiblings ?

              {
                map(this.getOtherPosts(post), (post, key) => <PostTile key={key} details={post} />)
              }

          : null}

        {/* User and Post information */}

          <UserInformation user={user}>
            {signup.quantity && this.props.showQuantity ?
              <Quantity quantity={signup.quantity} noun={campaign.reportback_info.noun} verb={campaign.reportback_info.verb} />
            : null}

            {this.props.allowHistory ?

                 this.props.showHistory(post['id'], e)}>Edit | Show History

            : null}

              <TextBlock title="Photo Caption" content={displayCaption(post)} />

              <TextBlock title="Why Statement" content={this.props.signup.why_participated} />

          </UserInformation>

        {/* Review block and meta data */}

            <ReviewBlock post={post} onUpdate={this.props.onUpdate} onTag={this.props.onTag} deletePost={this.props.deletePost} />

            <MetaInformation title="Meta" details={{
              "Post ID": post.id,
              "Submitted": new Date(post.created_at).toDateString(),
              "Source": post.source,
            }} />

    )
  }
}

export default Post;
<commit_msg>Hook up frontend to make api call to rotate image<commit_after>import React from 'react';
import { remove, map, clone } from 'lodash';
import { RestApiClient } from '@dosomething/gateway';
import { getImageUrlFromProp, getEditedImageUrl, displayCaption } from '../../helpers';

import './post.scss';

import Tags from '../Tags';
import PostTile from '../PostTile';
import Quantity from '../Quantity';
import TextBlock from '../TextBlock';
import ReviewBlock from '../ReviewBlock';
import StatusButton from '../StatusButton';
import MetaInformation from '../MetaInformation';
import UserInformation from '../Users/UserInformation';

class Post extends React.Component {
  constructor(props) {
    super(props);

    this.state = this.props.post;

    this.api = new RestApiClient;
  }

  rotate(event) {
    event.preventDefault();

    const post = this.props.post;

    this.api.post(`images/${post.id}?rotate=90`)
    .then((json) => {
      // Update the state of the Post to use the same image url,
      // but add cache-busting string changes and trigger re-render.
      this.setState({
        'media': {
          'url' : `${json.url}?time=${new Date()}`,
        }
      });
    });
  }

  getOtherPosts(post) {
    const post_id = post['id'];
    const signup = this.props.signup;

    var posts = signup.posts ? signup.posts : post.siblings.data;

    // get array of posts
    const other_posts = clone(posts);

    // find index that has that post_id and remove
    const big_post = remove(other_posts, function(current_post) {
      return current_post['id'] == post_id;
    });

    // return the rest of the original array
    return other_posts;
  }

  render() {
    const post = this.state;
    const caption = displayCaption(post);
    const user = this.props.user ? this.props.user : null;
    const signup = this.props.signup;
    const campaign = this.props.campaign;

    return (

        {/* Post Images */}

              Original Photo

              Edited Photo

               this.rotate(event) }>

          {this.props.showSiblings ?

              {
                map(this.getOtherPosts(post), (post, key) => <PostTile key={key} details={post} />)
              }

          : null}

        {/* User and Post information */}

          <UserInformation user={user}>
            {signup.quantity && this.props.showQuantity ?
              <Quantity quantity={signup.quantity} noun={campaign.reportback_info.noun} verb={campaign.reportback_info.verb} />
            : null}

            {this.props.allowHistory ?

                 this.props.showHistory(post['id'], e)}>Edit | Show History

            : null}

              <TextBlock title="Photo Caption" content={displayCaption(post)} />

              <TextBlock title="Why Statement" content={this.props.signup.why_participated} />

          </UserInformation>

        {/* Review block and meta data */}

            <ReviewBlock post={post} onUpdate={this.props.onUpdate} onTag={this.props.onTag} deletePost={this.props.deletePost} />

            <MetaInformation title="Meta" details={{
              "Post ID": post.id,
              "Submitted": new Date(post.created_at).toDateString(),
              "Source": post.source,
            }} />

    )
  }
}

export default Post;
<|endoftext|>


<commit_before>"use strict";

var __get__ = require("rewire/lib/__get__.js").toString(),
    __set__ = require("rewire/lib/__set__.js").toString(),
    __with__ = require("rewire/lib/__with__.js").toString(),
    detectStrictMode = require("rewire/lib/detectStrictMode.js"),
    path = require("path"),
    pathToGetImportGlobalsSrc = require.resolve("rewire/lib/getImportGlobalsSrc.js").split(path.sep).join("/");

function rewireLoader(src) {
    src =
            // Trying to hide the injected line in the debug view with extra whitespaces.
            '                                                                                ' +
            '/* this line was injected by rewire() */ ' + // Comment for the curious developer

            // Now all global variables are declared with a var statement so they can be changed via __set__()
            // without influencing global objects.
            'var global = window; ' + // window is our new global object
            'eval(require("' + pathToGetImportGlobalsSrc + '")()); ' +

            // The module src is wrapped inside a self-executing function.
            // This is necessary to separate the module src from the preceding eval(importGlobalsSrc),
            // because the module src can be in strict mode.
            // In strict mode eval() can only declare vars in the current scope. In this case our setters
            // and getters won't work.
            // @see https://developer.mozilla.org/en/JavaScript/Strict_mode#Making_eval_and_arguments_simpler
            "(function () { " +

            // If the module uses strict mode we must ensure that "use strict" stays at the beginning of the function.
            (detectStrictMode(src) ? ' "use strict"; ' : ' ') +

            src +

            // append at least a newline, the source may end with a line comment
            "\n" +
            "module.exports.__set__ = " + __set__ + "; " +
            "module.exports.__get__ = " + __get__ + "; " +
            "module.exports.__with__ = " + __with__ + "; " +
            " })();";

    return src;
}

module.exports = rewireLoader;<commit_msg>Use `getDefinePropertySrc()` introduced with https://github.com/jhnns/rewire/commit/8b8fde8dc999051df0c5f70a4c4407859e3ddae0<commit_after>"use strict";

var detectStrictMode = require("rewire/lib/detectStrictMode.js"),
    getDefinePropertySrc = require("rewire/lib/getDefinePropertySrc.js"),
    path = require("path"),
    pathToGetImportGlobalsSrc = require.resolve("rewire/lib/getImportGlobalsSrc.js").split(path.sep).join("/");

function rewireLoader(src) {
    src =
            // Trying to hide the injected line in the debug view with extra whitespaces.
            '                                                                                ' +
            '/* this line was injected by rewire() */ ' + // Comment for the curious developer

            // Now all global variables are declared with a var statement so they can be changed via __set__()
            // without influencing global objects.
            'var global = window; ' + // window is our new global object
            'eval(require("' + pathToGetImportGlobalsSrc + '")()); ' +

            // The module src is wrapped inside a self-executing function.
            // This is necessary to separate the module src from the preceding eval(importGlobalsSrc),
            // because the module src can be in strict mode.
            // In strict mode eval() can only declare vars in the current scope. In this case our setters
            // and getters won't work.
            // @see https://developer.mozilla.org/en/JavaScript/Strict_mode#Making_eval_and_arguments_simpler
            "(function () { " +

            // If the module uses strict mode we must ensure that "use strict" stays at the beginning of the function.
            (detectStrictMode(src) ? ' "use strict"; ' : ' ') +

            src +

            // append at least a newline, the source may end with a line comment
            "\n" + getDefinePropertySrc() + " })();";

    return src;
}

module.exports = rewireLoader;<|endoftext|>


<commit_before>
export default {
    uri: 'https://paleobiodb.org/data1.1/colls/summary.json?level=2&interval=',
    getInterval(interval){
        return fetch(this.uri + interval)
            .then((response) => {
                if(!response.ok){
                    throw 'bad response'
                }
                return response.json()
            })
    }
}<commit_msg>safe encode urls<commit_after>
export default {
    uri: 'https://paleobiodb.org/data1.2/colls/summary.json?level=2&interval=',
    getInterval(interval){
        return fetch(this.uri + encodeURIComponent(interval))
            .then((response) => {
                if(!response.ok){
                    throw 'bad response'
                }
                return response.json()
            })
    }
}
<|endoftext|>


<commit_before>var userData = require("../userData.json");
var status = require("../status.json");
var courses = require("../courses.json");

exports.view = function(req, res)
{
	var username = status["loginStatus"]["username"];
	var otherCourses=courses;

	var arr = userData["loginData"];
	var currentCourses;

	for(var i=0;i<arr.length;i++)
	{
		var obj = arr[i];
		var uname;
		for(var key in obj)
		{
			var attrName = key;
			var attrValue = obj[key];

			if(attrName == "username")
			{
				uname=attrValue;
			}

			if(attrName == "courses" && uname==username)
			{
				currentCourses=attrValue;
			}
		}
	}

	if(currentCourses != undefined)
	{
		var splice=false;

		for(var i=0; i<currentCourses.length; i++)
		{
			var obj=currentCourses[i];
			var cID;
			for(var key in obj)
			{
				var attrName=key;
				var attrValue=obj[key];

				if(attrName == "courseID")
				{
					cID = attrValue;

					for(var j=otherCourses.length-1; j>=0; j--)
					{
						splice=false;
						var obj2=otherCourses[j];
						for(var key2 in obj2)
						{
							var attrName2=key2;
							var attrValue2 = obj2[key2];

							if(attrName2 == "courseID" && attrValue2 == cID)
							{

								splice=true;
							}
						}

						if(splice)
						{
							otherCourses.splice(j, 1);
						}
					}
				}
			}
		}
		console.log(otherCourses);
	}
	res.render('addCourse', {"status":status, "courses":otherCourses});

};<commit_msg>Fixed missing courses from select menu bug with copy array<commit_after>var userData = require("../userData.json");
var status = require("../status.json");
var courses = require("../courses.json");

exports.view = function(req, res)
{
	var username = status["loginStatus"]["username"];
	var otherCourses=courses.slice();

	var arr = userData["loginData"];
	var currentCourses;

	for(var i=0;i<arr.length;i++)
	{
		var obj = arr[i];
		var uname;
		for(var key in obj)
		{
			var attrName = key;
			var attrValue = obj[key];

			if(attrName == "username")
			{
				uname=attrValue;
			}

			if(attrName == "courses" && uname==username)
			{
				currentCourses=attrValue;
			}
		}
	}

	if(currentCourses != undefined)
	{
		var splice=false;

		for(var i=0; i<currentCourses.length; i++)
		{
			var obj=currentCourses[i];
			var cID;
			for(var key in obj)
			{
				var attrName=key;
				var attrValue=obj[key];

				if(attrName == "courseID")
				{
					cID = attrValue;

					for(var j=otherCourses.length-1; j>=0; j--)
					{
						splice=false;
						var obj2=otherCourses[j];
						for(var key2 in obj2)
						{
							var attrName2=key2;
							var attrValue2 = obj2[key2];

							if(attrName2 == "courseID" && attrValue2 == cID)
							{

								splice=true;
							}
						}

						if(splice)
						{
							otherCourses.splice(j, 1);
						}
					}
				}
			}
		}
		console.log(otherCourses);
	}
	res.render('addCourse', {"status":status, "courses":otherCourses});

};<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * analyze-css entry point
 *
 * @see https://github.com/macbre/analyze-css
 */
var analyzer = require('./../lib/index'),
	runner = require('./../lib/runner'),
	program = require('optimist'),
	cssString = '',
	argv = {},
	url = '';

// parse options
program
	.usage('analyze-css --url <url> [options]')

	// mandatory
	.describe('url', 'Set URL of CSS to analyze').string('url')
	.describe('file', 'Set local CSS file to analyze').string('file')

	// version / help
	.describe('version', 'Show version number and quit').boolean('version').alias('version', 'V')
	.describe('help', 'This help text').boolean('help').alias('help', 'h');

// parse it
argv = program.parse(process.argv);

// show version number
if (argv.version === true) {
	console.log('analyze-css v%s', analyzer.version);
	process.exit(0);
}

// show help
if (argv.help === true) {
	program.showHelp();
	process.exit(0);
}

// either --url of --file needs to be provided
if (typeof argv.url !== 'string' && typeof argv.file !== 'string') {
	program.showHelp();
	process.exit(255);
}

// run the analyzer
url = argv.url || argv.file;

runner(url, function(err, res) {
	if (err) {
		console.error(err);
		process.exit(255);
	}

	console.log(JSON.stringify(res));
	process.exit(0);
});

<commit_msg>Add pretty print option<commit_after>#!/usr/bin/env node
/**
 * analyze-css entry point
 *
 * @see https://github.com/macbre/analyze-css
 */
var analyzer = require('./../lib/index'),
	runner = require('./../lib/runner'),
	program = require('optimist'),
	cssString = '',
	argv = {},
	url = '';

// parse options
program
	.usage('analyze-css --url <url> [options]')

	// mandatory
	.describe('url', 'Set URL of CSS to analyze').string('url')
	.describe('file', 'Set local CSS file to analyze').string('file')

	.describe('pretty', 'Causes JSON with the results to be pretty-printed').boolean('pretty').alias('pretty', 'p')

	// version / help
	.describe('version', 'Show version number and quit').boolean('version').alias('version', 'V')
	.describe('help', 'This help text').boolean('help').alias('help', 'h');

// parse it
argv = program.parse(process.argv);

// show version number
if (argv.version === true) {
	console.log('analyze-css v%s', analyzer.version);
	process.exit(0);
}

// show help
if (argv.help === true) {
	program.showHelp();
	process.exit(0);
}

// either --url of --file needs to be provided
if (typeof argv.url !== 'string' && typeof argv.file !== 'string') {
	program.showHelp();
	process.exit(255);
}

// run the analyzer
url = argv.url || argv.file;

runner(url, function(err, res) {
	var output;

	// emit an error and die
	if (err) {
		console.error(err);
		process.exit(255);
	}

	// format the results
	if (argv.pretty === true) {
		output = JSON.stringify(res, null, '  ');
	}
	else {
		output = JSON.stringify(res);
	}

	console.log(output);

	// done
	process.exit(0);
});

<|endoftext|>


<commit_before>Template.attachmentsGalery.events({
  'click .js-add-attachment': Popup.open('cardAttachments'),
  // If we let this event bubble, FlowRouter will handle it and empty the page
  // content, see #101.
  'click .js-download'(event) {
    event.stopPropagation();
  },
  'click .js-open-attachment-menu': Popup.open('attachmentActions'),
});

Template.attachmentsGalery.helpers({
  isBoardAdmin() {
    return Meteor.user().isBoardAdmin();
  },
  fileSize(size) {
    return Math.round(size / 1024);
  },
});

Template.cardAttachmentsPopup.events({
  'change .js-attach-file'(event) {
    const card = this;
    if (event.currentTarget.files && event.currentTarget.files[0]) {
      const fileId = Random.id();
      const config = {
        file: event.currentTarget.files[0],
        fileId: fileId,
        meta: Utils.getCommonAttachmentMetaFrom(card),
        chunkSize: 'dynamic',
      };
      config.meta.fileId = fileId;
      const uploader = Attachments.insert(
        config,
        false,
      );
      uploader.on('uploaded', (error, fileRef) => {
        if (!error) {
          if (fileRef.isImage) {
            card.setCover(fileRef._id);
          }
        }
      });
      uploader.on('end', (error, fileRef) => {
        Popup.back();
      });
      uploader.start();
    }
  },
  'click .js-computer-upload'(event, templateInstance) {
    templateInstance.find('.js-attach-file').click();
    event.preventDefault();
  },
  'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'),
});

const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
let pastedResults = null;

Template.previewClipboardImagePopup.onRendered(() => {
  // we can paste image from clipboard
  const handle = results => {
    if (results.dataURL.startsWith('data:image/')) {
      const direct = results => {
        $('img.preview-clipboard-image').attr('src', results.dataURL);
        pastedResults = results;
      };
      if (MAX_IMAGE_PIXEL) {
        // if has size limitation on image we shrink it before uploading
        Utils.shrinkImage({
          dataurl: results.dataURL,
          maxSize: MAX_IMAGE_PIXEL,
          ratio: COMPRESS_RATIO,
          callback(changed) {
            if (changed !== false && !!changed) {
              results.dataURL = changed;
            }
            direct(results);
          },
        });
      } else {
        direct(results);
      }
    }
  };

  $(document.body).pasteImageReader(handle);

  // we can also drag & drop image file to it
  $(document.body).dropImageReader(handle);
});

Template.previewClipboardImagePopup.events({
  'click .js-upload-pasted-image'() {
    const card = this;
    if (pastedResults && pastedResults.file) {
      const file = pastedResults.file;
      window.oPasted = pastedResults;
      const fileId = Random.id();
      const config = {
        file,
        fileId: fileId,
        meta: Utils.getCommonAttachmentMetaFrom(card),
        fileName: file.name || file.type.replace('image/', 'clipboard.'),
        chunkSize: 'dynamic',
      };
      config.meta.fileId = fileId;
      const uploader = Attachments.insert(
        config,
        false,
      );
      uploader.on('uploaded', (error, fileRef) => {
        if (!error) {
          if (fileRef.isImage) {
            card.setCover(fileRef._id);
          }
        }
      });
      uploader.on('end', (error, fileRef) => {
        pastedResults = null;
        $(document.body).pasteImageReader(() => {});
        Popup.back();
      });
      uploader.start();
    }
  },
});

BlazeComponent.extendComponent({
  isCover() {
    const ret = Cards.findOne(this.data().meta.cardId).coverId == this.data()._id;
    return ret;
  },
  events() {
    return [
      {
        'click .js-rename': Popup.open('attachmentRename'),
        'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
          Attachments.remove(this._id);
          Popup.back(2);
        }),
        'click .js-add-cover'() {
          Cards.findOne(this.data().meta.cardId).setCover(this.data()._id);
          Popup.back();
        },
        'click .js-remove-cover'() {
          Cards.findOne(this.data().meta.cardId).unsetCover();
          Popup.back();
        },
        'click .js-move-storage-fs'() {
          Meteor.call('moveAttachmentToStorage', this.data()._id, "fs");
          Popup.back();
        },
        'click .js-move-storage-gridfs'() {
          Meteor.call('moveAttachmentToStorage', this.data()._id, "gridfs");
          Popup.back();
        },
      }
    ]
  }
}).register('attachmentActionsPopup');

BlazeComponent.extendComponent({
  getNameWithoutExtension() {
    const ret = this.data().name.replace(new RegExp("\." + this.data().extension + "$"), "");
    return ret;
  },
  events() {
    return [
      {
        'keydown input.js-edit-attachment-name'(evt) {
          // enter = save
          if (evt.keyCode === 13) {
            this.find('button[type=submit]').click();
          }
        },
        'click button.js-submit-edit-attachment-name'(event) {
          // save button pressed
          event.preventDefault();
          const name = this.$('.js-edit-attachment-name')[0]
            .value
            .trim() + this.data().extensionWithDot;
          Meteor.call('renameAttachment', this.data()._id, name);
          Popup.back(2);
        },
      }
    ]
  }
}).register('attachmentRenamePopup');
<commit_msg>Attachment, upload all selected files<commit_after>Template.attachmentsGalery.events({
  'click .js-add-attachment': Popup.open('cardAttachments'),
  // If we let this event bubble, FlowRouter will handle it and empty the page
  // content, see #101.
  'click .js-download'(event) {
    event.stopPropagation();
  },
  'click .js-open-attachment-menu': Popup.open('attachmentActions'),
});

Template.attachmentsGalery.helpers({
  isBoardAdmin() {
    return Meteor.user().isBoardAdmin();
  },
  fileSize(size) {
    return Math.round(size / 1024);
  },
});

Template.cardAttachmentsPopup.events({
  'change .js-attach-file'(event) {
    const card = this;
    const files = event.currentTarget.files;
    if (files) {
      let finished = [];
      for (const file of files) {
        const fileId = Random.id();
        const config = {
          file: file,
          fileId: fileId,
          meta: Utils.getCommonAttachmentMetaFrom(card),
          chunkSize: 'dynamic',
        };
        config.meta.fileId = fileId;
        const uploader = Attachments.insert(
          config,
          false,
        );
        uploader.on('uploaded', (error, fileRef) => {
          if (!error) {
            if (fileRef.isImage) {
              card.setCover(fileRef._id);
            }
          }
        });
        uploader.on('end', (error, fileRef) => {
          Popup.back();
        });
        uploader.start();
      }
    }
  },
  'click .js-computer-upload'(event, templateInstance) {
    templateInstance.find('.js-attach-file').click();
    event.preventDefault();
  },
  'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'),
});

const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
let pastedResults = null;

Template.previewClipboardImagePopup.onRendered(() => {
  // we can paste image from clipboard
  const handle = results => {
    if (results.dataURL.startsWith('data:image/')) {
      const direct = results => {
        $('img.preview-clipboard-image').attr('src', results.dataURL);
        pastedResults = results;
      };
      if (MAX_IMAGE_PIXEL) {
        // if has size limitation on image we shrink it before uploading
        Utils.shrinkImage({
          dataurl: results.dataURL,
          maxSize: MAX_IMAGE_PIXEL,
          ratio: COMPRESS_RATIO,
          callback(changed) {
            if (changed !== false && !!changed) {
              results.dataURL = changed;
            }
            direct(results);
          },
        });
      } else {
        direct(results);
      }
    }
  };

  $(document.body).pasteImageReader(handle);

  // we can also drag & drop image file to it
  $(document.body).dropImageReader(handle);
});

Template.previewClipboardImagePopup.events({
  'click .js-upload-pasted-image'() {
    const card = this;
    if (pastedResults && pastedResults.file) {
      const file = pastedResults.file;
      window.oPasted = pastedResults;
      const fileId = Random.id();
      const config = {
        file,
        fileId: fileId,
        meta: Utils.getCommonAttachmentMetaFrom(card),
        fileName: file.name || file.type.replace('image/', 'clipboard.'),
        chunkSize: 'dynamic',
      };
      config.meta.fileId = fileId;
      const uploader = Attachments.insert(
        config,
        false,
      );
      uploader.on('uploaded', (error, fileRef) => {
        if (!error) {
          if (fileRef.isImage) {
            card.setCover(fileRef._id);
          }
        }
      });
      uploader.on('end', (error, fileRef) => {
        pastedResults = null;
        $(document.body).pasteImageReader(() => {});
        Popup.back();
      });
      uploader.start();
    }
  },
});

BlazeComponent.extendComponent({
  isCover() {
    const ret = Cards.findOne(this.data().meta.cardId).coverId == this.data()._id;
    return ret;
  },
  events() {
    return [
      {
        'click .js-rename': Popup.open('attachmentRename'),
        'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
          Attachments.remove(this._id);
          Popup.back(2);
        }),
        'click .js-add-cover'() {
          Cards.findOne(this.data().meta.cardId).setCover(this.data()._id);
          Popup.back();
        },
        'click .js-remove-cover'() {
          Cards.findOne(this.data().meta.cardId).unsetCover();
          Popup.back();
        },
        'click .js-move-storage-fs'() {
          Meteor.call('moveAttachmentToStorage', this.data()._id, "fs");
          Popup.back();
        },
        'click .js-move-storage-gridfs'() {
          Meteor.call('moveAttachmentToStorage', this.data()._id, "gridfs");
          Popup.back();
        },
      }
    ]
  }
}).register('attachmentActionsPopup');

BlazeComponent.extendComponent({
  getNameWithoutExtension() {
    const ret = this.data().name.replace(new RegExp("\." + this.data().extension + "$"), "");
    return ret;
  },
  events() {
    return [
      {
        'keydown input.js-edit-attachment-name'(evt) {
          // enter = save
          if (evt.keyCode === 13) {
            this.find('button[type=submit]').click();
          }
        },
        'click button.js-submit-edit-attachment-name'(event) {
          // save button pressed
          event.preventDefault();
          const name = this.$('.js-edit-attachment-name')[0]
            .value
            .trim() + this.data().extensionWithDot;
          Meteor.call('renameAttachment', this.data()._id, name);
          Popup.back(2);
        },
      }
    ]
  }
}).register('attachmentRenamePopup');
<|endoftext|>


<commit_before>'use strict';

var Promise = require('bluebird');
var byline = require('byline');

var HOST_REGEXP = /^\s*?(?:[a-f0-9\.:]+)\s+?([a-z0-9\._\-]+)\s*.*?$/i;

function matchHost(line) {
  var matches = HOST_REGEXP.exec(line);
  if (matches && matches.length === 2) {
    return matches[1];
  }
}

module.exports = function (readStream) {
  return Promise.resolve(readStream)
    .then(function (stream) {
      return new Promise(function (resolve, reject) {
        //if (!stream) {
        //  return resolve([]);
        //}
        var hosts = [];

        byline(stream)
          .on('data', function (line) {
            var match = matchHost(line);
            if (match) {
              hosts.push(match);
            }
          })
          .on('error', reject)
          .on('finish', function () {
            resolve(hosts);
          });
      });
    });
};
<commit_msg>cosmetics<commit_after>'use strict';

var Promise = require('bluebird');
var byline = require('byline');

var HOST_REGEXP = /^\s*?(?:[a-f0-9\.:]+)\s+?([a-z0-9\._\-]+)\s*.*?$/i;

function matchHost(line) {
  var matches = HOST_REGEXP.exec(line);
  if (matches && matches.length === 2) {
    return matches[1];
  }
}

module.exports = function (readStream) {
  return Promise.resolve(readStream)
    .then(function (stream) {
      return new Promise(function (resolve, reject) {
        var hosts = [];

        byline(stream)
          .on('data', function (line) {
            var match = matchHost(line);
            if (match) {
              hosts.push(match);
            }
          })
          .on('error', reject)
          .on('finish', function () {
            resolve(hosts);
          });
      });
    });
};
<|endoftext|>


<commit_before>/*

Metaball rendering demo. Many ideas and code taken from here

 */

const regl = require('../regl')()
const surfaceNets = require('surface-nets')
const ndarray = require('ndarray')
const fill = require('ndarray-fill')
const normals = require('angle-normals')
const mat3 = require('gl-mat3')
const camera = require('./util/camera')(regl, {
  distance: 1,
  maxDistance: 3,
  minDistance: 0.5,
  center: [0.5, 0.5, 0.5]
})

const drawMetaballs = regl({
  vert: `
    precision mediump float;
    uniform mat4 projection, view;
    uniform mat3 normalMatrix;
    attribute vec3 position, normal;
    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;
    void main () {
      vNormal = normalMatrix * normal;
      vONormal = normal;
      vPosition = vec4( position, 1.0 );
      vOPosition = view * vPosition;
      vU = normalize( vec3( vOPosition ) );
      gl_Position = projection * vOPosition;
    }`,
  frag: `
    precision mediump float;
    uniform sampler2D textureMap, normalMap;
    uniform vec3 color, eye;
    uniform float normalScale, texScale, useSSS, useScreen;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    float random(vec3 scale,float seed) {
      return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);
    }

    void main() {
      vec3 n = normalize( vONormal.xyz );
      vec3 blend_weights = abs( n );
      blend_weights = ( blend_weights - 0.2 ) * 7.;
      blend_weights = max( blend_weights, 0. );
      blend_weights /= ( blend_weights.x + blend_weights.y + blend_weights.z );

      vec2 coord1 = vPosition.yz * texScale;
      vec2 coord2 = vPosition.zx * texScale;
      vec2 coord3 = vPosition.xy * texScale;

      vec3 bump1 = texture2D( normalMap, coord1 ).rgb;
      vec3 bump2 = texture2D( normalMap, coord2 ).rgb;
      vec3 bump3 = texture2D( normalMap, coord3 ).rgb;

      vec3 blended_bump = bump1 * blend_weights.xxx +
                          bump2 * blend_weights.yyy +
                          bump3 * blend_weights.zzz;

      vec3 tanX = vec3( vNormal.x, -vNormal.z, vNormal.y);
      vec3 tanY = vec3( vNormal.z, vNormal.y, -vNormal.x);
      vec3 tanZ = vec3(-vNormal.y, vNormal.x, vNormal.z);
      vec3 blended_tangent = tanX * blend_weights.xxx +
                             tanY * blend_weights.yyy +
                             tanZ * blend_weights.zzz;

      vec3 normalTex = blended_bump * 2.0 - 1.0;
      normalTex.xy *= normalScale;
      normalTex.y *= -1.;
      normalTex = normalize( normalTex );
      mat3 tsb = mat3( normalize( blended_tangent ), normalize( cross( vNormal, blended_tangent ) ), normalize( vNormal ) );
      vec3 finalNormal = tsb * normalTex;

      vec3 r = reflect( normalize( vU ), normalize( finalNormal ) );
      float m = 2.0 * sqrt( r.x * r.x + r.y * r.y + ( r.z + 1.0 ) * ( r.z + 1.0 ) );
      vec2 calculatedNormal = vec2( r.x / m + 0.5,  r.y / m + 0.5 );

      vec3 base = texture2D( textureMap, calculatedNormal ).rgb;

      float rim = 1.75 * max( 0., abs( dot( normalize( vNormal ), normalize( -vOPosition.xyz ) ) ) );
      base += useSSS * color * ( 1. - .75 * rim );
      base += ( 1. - useSSS ) * 10. * base * color * clamp( 1. - rim, 0., .15 );

      if( useScreen == 1. ) {
        base = vec3( 1. ) - ( vec3( 1. ) - base ) * ( vec3( 1. ) - base );
      }

      float nn = .05 * random( vec3( 1. ), length( gl_FragCoord ) );
      base += vec3( nn );

      gl_FragColor = vec4( base.rgb, 1. );
    }`,
  attributes: {
    position: regl.prop('positions'),
    normal: (context, props) => normals(props.cells, props.positions)
  },
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    sphereColor: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    normalScale: 1,
    texScale: 10,
    useSSS: 0,
    noise: 0.4,
    useScreen: 1,
    normalMatrix: (context) => {
      let a = mat3.create()
      mat3.normalFromMat4(a, context.view)
      return a
    },
    width: regl.context('viewportWidth'),
    height: regl.context('viewportHeight'),
    textureMap: regl.prop('textureMap'),
    normalMap: regl.prop('normalMap')
  },
  elements: regl.prop('cells')
})

const numblobs = 20
const strength = 1.2 / ((Math.sqrt(numblobs) - 1) / 4 + 1)
const subtract = 12
const size = 50
const bounds = [[0, 0, 0], [1.5, 1.5, 1.5]]
const position = (time, i) => {
  return [
    Math.sin(i + 1.26 * time * (1.03 + 0.5 * Math.cos(0.21 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.12 * time * 0.21 * Math.sin((0.72 + 0.83 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.32 * time * 0.1 * Math.sin((0.92 + 0.53 * i))) * 0.27 + 0.5
  ]
}
let start_bounds, end_bounds
[start_bounds, end_bounds] = bounds
const step_sizes = [0, 1, 2].map((i) => (end_bounds[i] - start_bounds[i]) / size)
const r = size * Math.sqrt(strength / subtract)

const render = (tick) => {
  let time = 0.05 * tick
  let fieldArray = new Float32Array(size * size * size)

  for (let n = 0; n < numblobs; n++) {
    let ballx, bally, ballz
    [ballx, bally, ballz] = position(time, n)
    let zs = ballz * size
    let ys = bally * size
    let xs = ballx * size

    let min_z = Math.floor(zs - r)
    if (min_z < 1) min_z = 1
    let max_z = Math.floor(zs + r)
    if (max_z > size - 1) max_z = size - 1
    let min_y = Math.floor(ys - r)
    if (min_y < 1) min_y = 1
    let max_y = Math.floor(ys + r)
    if (max_y > size - 1) max_y = size - 1
    let min_x = Math.floor(xs - r)
    if (min_x < 1) min_x = 1
    let max_x = Math.floor(xs + r)
    if (max_x > size - 1) max_x = size - 1

    for (let z = min_z; z < max_z; z++) {
      let z_offset = size * size * z

      for (let y = min_y; y < max_y; y++) {
        let y_offset = size * y

        for (let x = min_x; x < max_x; x++) {
          let fx = x / size - ballx
          let fy = y / size - bally
          let fz = z / size - ballz
          let val = strength / (0.000001 + (fx * fx) + (fy * fy) + (fz * fz)) - subtract
          if (val > 0.0) fieldArray[z_offset + y_offset + x] += val
        }
      }
    }
  }

  let mesh = surfaceNets(ndarray(fieldArray, [size, size, size]), 80.0)
  let coordinate_positions = mesh.positions.map((p) => {
    return p.map((index, i) => start_bounds[i] + (index * step_sizes[i]))
  })
  return {positions: coordinate_positions, cells: mesh.cells}
}

require('resl')({
  manifest: {
    sphereTexture: {
      type: 'image',
      src: 'spheretexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'clamp',
        wrapS: 'clamp'
      })
    },
    normalTexture: {
      type: 'image',
      src: 'normaltexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'repeat',
        wrapS: 'repeat'
      })
    }
  },
  onDone: ({sphereTexture, normalTexture}) => {
    regl.frame(({tick}) => {
      let mesh = render(tick)
      camera(() => {
        drawMetaballs({
          positions: mesh.positions,
          cells: mesh.cells,
          textureMap: sphereTexture,
          normalMap: normalTexture
        })
      })
    })
  }
})
<commit_msg>Add background.<commit_after>/*

Metaball rendering demo. Many ideas and code taken from here

 */

const regl = require('../regl')()
const surfaceNets = require('surface-nets')
const ndarray = require('ndarray')
const normals = require('angle-normals')
const mat3 = require('gl-mat3')
const camera = require('./util/camera')(regl, {
  distance: 1.5,
  maxDistance: 3,
  minDistance: 0.5,
  center: [1, 1, 1],
  theta: 1.0
})

const drawBackground = regl({
  vert: `
    precision mediump float;
    attribute vec2 position;
    void main() {
      gl_Position = vec4(position, 0., 1.);
    }`,
  frag: `
    precision mediump float;
    uniform vec3 color;
    uniform float noise, width, height;

    #define VIG_REDUCTION_POWER 1.
    #define VIG_BOOST 1.

    float random(vec3 scale,float seed) {
      return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);
    }

    void main () {
      vec2 resolution = vec2(width, height);
      vec2 center = resolution * 0.5;
      float vignette = distance( center, gl_FragCoord.xy ) / resolution.x;
      vignette = VIG_BOOST - vignette * VIG_REDUCTION_POWER;

      float n = noise * (.5 - random(vec3(1.), length(gl_FragCoord)));

      float v = .5 * length(vec2(gl_FragCoord.y / resolution.y, (1. - abs(.5 - gl_FragCoord.x / resolution.x))));
      vec3 base = color;
      base += vec3(pow(v, 2.));

      gl_FragColor = vec4(base * vec3(vignette) + vec3(n), 1.);
    }`,
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    width: regl.context('viewportWidth'),
    height: regl.context('viewportHeight'),
    noise: 0.05
  },
  attributes: {
    position: [-4, -4, 4, -4, 0, 4]
  },
  count: 3
})

const drawMetaballs = regl({
  vert: `
    precision mediump float;
    uniform mat4 projection, view;
    uniform mat3 normalMatrix;

    attribute vec3 position, normal;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    void main () {
      vNormal = normalMatrix * normal;
      vONormal = normal;
      vPosition = vec4(position, 1.0);
      vOPosition = view * vPosition;
      vU = normalize(vec3(vOPosition));
      gl_Position = projection * vOPosition;
    }`,
  frag: `
    precision mediump float;
    uniform sampler2D textureMap, normalMap;
    uniform float normalScale, texScale;
    uniform vec3 color, eye;

    varying vec3 vNormal, vONormal, vU;
    varying vec4 vPosition, vOPosition;

    float random(vec3 scale, float seed) {
      return fract(sin(dot(gl_FragCoord.xyz + seed,scale)) * 43758.5453 + seed);
    }

    void main() {
      vec3 n = normalize(vONormal.xyz);
      vec3 blend_weights = abs(n);
      blend_weights = (blend_weights - 0.2) * 7.;
      blend_weights = max(blend_weights, 0.);
      blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z);

      vec2 coord1 = vPosition.yz * texScale;
      vec2 coord2 = vPosition.zx * texScale;
      vec2 coord3 = vPosition.xy * texScale;

      vec3 bump1 = texture2D(normalMap, coord1).rgb;
      vec3 bump2 = texture2D(normalMap, coord2).rgb;
      vec3 bump3 = texture2D(normalMap, coord3).rgb;

      vec3 blended_bump = bump1 * blend_weights.xxx +
                          bump2 * blend_weights.yyy +
                          bump3 * blend_weights.zzz;

      vec3 tanX = vec3(vNormal.x, -vNormal.z, vNormal.y);
      vec3 tanY = vec3(vNormal.z, vNormal.y, -vNormal.x);
      vec3 tanZ = vec3(-vNormal.y, vNormal.x, vNormal.z);
      vec3 blended_tangent = tanX * blend_weights.xxx +
                             tanY * blend_weights.yyy +
                             tanZ * blend_weights.zzz;

      vec3 normalTex = blended_bump * 2.0 - 1.0;
      normalTex.xy *= normalScale;
      normalTex.y *= -1.;
      normalTex = normalize(normalTex);
      mat3 tsb = mat3(normalize(blended_tangent), normalize(cross(vNormal, blended_tangent)), normalize(vNormal));
      vec3 finalNormal = tsb * normalTex;

      vec3 r = reflect(normalize(vU), normalize(finalNormal));
      float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
      vec2 calculatedNormal = vec2(r.x / m + 0.5, r.y / m + 0.5);

      vec3 base = texture2D(textureMap, calculatedNormal).rgb;

      float rim = 1.75 * max(0., abs(dot(normalize(vNormal), normalize(-vOPosition.xyz))));
      base += 10. * base * color * clamp(1. - rim, 0., .15);

      base = vec3(1.) - (vec3(1.) - base) * (vec3(1.) - base);

      float nn = .05 * random(vec3(1.), length(gl_FragCoord));
      base += vec3(nn);

      gl_FragColor = vec4(base.rgb, 1.);
    }`,
  attributes: {
    position: regl.prop('positions'),
    normal: (context, props) => normals(props.cells, props.positions)
  },
  uniforms: {
    color: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    sphereColor: [36 / 255.0, 70 / 255.0, 106 / 255.0],
    normalScale: 1,
    texScale: 10,
    normalMatrix: (context) => {
      let a = mat3.create()
      mat3.normalFromMat4(a, context.view)
      return a
    },
    textureMap: regl.prop('textureMap'),
    normalMap: regl.prop('normalMap')
  },
  elements: regl.prop('cells')
})

const numblobs = 20
const strength = 1.2 / ((Math.sqrt(numblobs) - 1) / 4 + 1)
const subtract = 12
const size = 50
const bounds = [[0.5, 0.5, 0.5], [1.5, 1.5, 1.5]]
const position = (time, i) => {
  return [
    Math.sin(i + 1.26 * time * (1.03 + 0.5 * Math.cos(0.21 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.12 * time * 0.21 * Math.sin((0.72 + 0.83 * i))) * 0.27 + 0.5,
    Math.cos(i + 1.32 * time * 0.1 * Math.sin((0.92 + 0.53 * i))) * 0.27 + 0.5
  ]
}
let start_bounds, end_bounds
[start_bounds, end_bounds] = bounds
const step_sizes = [0, 1, 2].map((i) => (end_bounds[i] - start_bounds[i]) / size)
const r = size * Math.sqrt(strength / subtract)

const render = (tick) => {
  let time = 0.5 * tick
  let fieldArray = new Float32Array(size * size * size)

  for (let n = 0; n < numblobs; n++) {
    let ballx, bally, ballz
    [ballx, bally, ballz] = position(time, n)
    let zs = ballz * size
    let ys = bally * size
    let xs = ballx * size

    let min_z = Math.floor(zs - r)
    if (min_z < 1) min_z = 1
    let max_z = Math.floor(zs + r)
    if (max_z > size - 1) max_z = size - 1
    let min_y = Math.floor(ys - r)
    if (min_y < 1) min_y = 1
    let max_y = Math.floor(ys + r)
    if (max_y > size - 1) max_y = size - 1
    let min_x = Math.floor(xs - r)
    if (min_x < 1) min_x = 1
    let max_x = Math.floor(xs + r)
    if (max_x > size - 1) max_x = size - 1

    for (let z = min_z; z < max_z; z++) {
      let z_offset = size * size * z

      for (let y = min_y; y < max_y; y++) {
        let y_offset = size * y

        for (let x = min_x; x < max_x; x++) {
          let fx = x / size - ballx
          let fy = y / size - bally
          let fz = z / size - ballz
          let val = strength / (0.000001 + (fx * fx) + (fy * fy) + (fz * fz)) - subtract
          if (val > 0.0) fieldArray[z_offset + y_offset + x] += val
        }
      }
    }
  }

  let mesh = surfaceNets(ndarray(fieldArray, [size, size, size]), 80.0)
  let coordinate_positions = mesh.positions.map((p) => {
    return p.map((index, i) => start_bounds[i] + (index * step_sizes[i]))
  })
  return {positions: coordinate_positions, cells: mesh.cells}
}

require('resl')({
  manifest: {
    sphereTexture: {
      type: 'image',
      src: 'spheretexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'clamp',
        wrapS: 'clamp'
      })
    },
    normalTexture: {
      type: 'image',
      src: 'normaltexture.jpg',
      parser: (data) => regl.texture({
        data: data,
        wrapT: 'repeat',
        wrapS: 'repeat'
      })
    }
  },
  onDone: ({sphereTexture, normalTexture}) => {
    regl.frame(({time}) => {
      let mesh = render(time)
      camera(() => {
        drawBackground({depth: {enable: false, mask: false}})
        regl.clear({depth: 1})
        drawMetaballs({
          positions: mesh.positions,
          cells: mesh.cells,
          textureMap: sphereTexture,
          normalMap: normalTexture
        })
      })
    })
  }
})
<|endoftext|>


<commit_before>"use strict";
var fs = require("fs");
var Docker = require('dockerode');
var utils = require("soajs/lib/utils");
var Grid = require('gridfs-stream');
var fs = require('fs');
var rimraf = require('rimraf');

function checkError(error, cb, fCb) {
	if (error) {
		return cb(error, null);
	}
	return fCb();
}

function getDockerCerts(dockerConfig, certs, gfs, db, counter, cb) {
	var gs = new gfs.mongo.GridStore(db, certs[counter]._id, 'r', {
		root: 'fs',
		w: 1,
		fsync: true
	});

	gs.open(function (error, gstore) {
		checkError(error, cb, function () {
			gstore.read(function (error, filedata) {
				checkError(error, cb, function () {
					gstore.close();
					var certKey = certs[counter].filename.split(".")[0];
					dockerConfig[certKey] = filedata;

					counter++;
					if (counter === certs.length) {
						return cb(null, dockerConfig);
					}
					else {
						return getDockerCerts(dockerConfig, certs, gfs, db, counter, cb);
					}
				});
			});
		});
	});
}

var lib = {
	"getDeployer": function (deployerConfig, mongo, cb) {
		/**
			Three options:
				- local: use socket port
				- remote: get manager node record, extract ip/port and certificates
				- remote and adding a new node: in case of adding a new node, use ip/port of new node and certificates
		*/
		var config = utils.cloneObj(deployerConfig);
		var docker;
		if (config.socketPath) {
			docker = new Docker({socketPath: config.socketPath});
			return cb(null, docker);
		}
		else {
			var dockerConfig = {};
			getTargetNode(config, function (error, target) {
				checkError(error, cb, function () {
					dockerConfig.host = target.host;
					dockerConfig.port = target.port;

					getNodeCertificates(config, dockerConfig, function (error, dockerConfig) {
						checkError(error, cb, function () {
							docker = new Docker(dockerConfig);
							return cb(null, docker);
						});
					});
				});
			});
		}

		function getTargetNode(config, callback) {
			if (config.flags && config.flags.newNode) {
				if (!config.host || !config.port) {
					return callback({message: 'Missing host/port info'});
				}
				return callback(null, {host: config.host, port: config.port});
			}
			else {
				if (!config.nodes || (config.nodes && config.nodes.length === 0)) {
					return callback({message: 'No manager nodes found in this environment\'s deployer'});
				}
				var oneManagerNode = config.nodes[0]; //any manager node can be selected
				mongo.findOne('docker', {recordType: 'node', name: oneManagerNode}, function (error, nodeRecord) {
					checkError(error || !nodeRecord, callback, function () {
						return callback(null, {host: nodeRecord.ip, port: nodeRecord.dockerPort});
					});
				});
			}
		}

		function getNodeCertificates(config, dockerConfig, callback) {
			if (!config.envCode) {
				return callback({message: 'Missing environment code'});
			}

			var criteria = {};
			criteria['metadata.env.' + config.envCode.toUpperCase()] = config.selectedDriver;
			mongo.find('fs.files', criteria, function (error, certs) {
				checkError(error, callback, function () {
					if (!certs || (certs && certs.length === 0)) {
						return callback({message: 'No certificates for ' + config.envCode + ' environment found'});
					}

					mongo.getMongoSkinDB(function (error, db) {
						checkError(error, callback, function () {
							var gfs = Grid(db, mongo.mongoSkin);
							var counter = 0;
							getDockerCerts(dockerConfig, certs, gfs, db, counter, function (error, dockerConfig) {
								checkError(error, callback, function () {
									return callback(null, dockerConfig);
								});
							});
						});
					});
				});
			});
		}
	},

	"container": function (dockerInfo, action, cid, mongo, opts, cb) {
		lib.getDeployer(dockerInfo, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				var container = deployer.getContainer(cid);
				container[action](opts || null, function (error, response) {

					checkError(error, cb, function () {
						if (action === 'start' || action === 'restart') {
							container.inspect(cb);
						}
						else return cb(null, response);
					});
				});
			});
		});
	}
};
var deployer = {
	"createContainer": function (deployerConfig, params, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}
			deployer.createContainer(params, function (err, container) {
				checkError(err, cb, function () {
					container.inspect(cb);
				});
			});
		});
	},

	"start": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "start", cid, mongo, null, cb);
	},

	"exec": function (deployerConfig, cid, mongo, opts, cb) {
		lib.container(deployerConfig, "exec", cid, mongo, opts, cb);
	},

	"restart": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "restart", cid, mongo, null, cb);
	},

	"remove": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "remove", cid, mongo, {"force": true}, cb);
	},

	"info": function (deployerConfig, cid, soajs, res, mongo) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			deployer.getContainer(cid).logs({
					stderr: true,
					stdout: true,
					timestamps: false,
					tail: 200
				},
				function (error, stream) {
					if (error) {
						soajs.log.error('logStreamContainer error: ', error);
						return res.json(soajs.buildResponse({"code": 601, "msg": error.message}));
					}
					else {
						var data = '';
						var chunk;
						stream.setEncoding('utf8');
						stream.on('readable', function () {
							var handle = this;
							while ((chunk = handle.read()) != null) {
								data += chunk.toString("utf8");
							}
						});

						stream.on('end', function () {
							stream.destroy();
							var out = soajs.buildResponse(null, {'data': data});
							return res.json(out);
						});
					}
				});
		});
	},

	"addNode": function (deployerConfig, options, mongo, cb) {
		deployerConfig.flags = {
			newNode: true
		};

		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				deployer.info(function (error, nodeInfo) {
					checkError(error, cb, function () {
						deployer.swarmJoin(options, function (error) {
							checkError(error, cb, function () {
								if (options.role === 'manager') {
									var node = deployer.getNode(nodeInfo.Name);
									node.inspect(cb);
								}
								else {
									//get manager node from swarm and inspect newly added node
									delete deployerConfig.flags;
									delete deployerConfig.host;
									delete deployerConfig.port;

									lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
										checkError(error, cb, function () {
											deployer.listNodes(function (error, nodes) {
												checkError(error, cb, function () {
													for (var i = 0; i < nodes.length; i++) {
														if (nodes[i].Description.Hostname === nodeInfo.Name) {
															return cb(null, nodes[i]);
														}
													}
													return cb();
												});
											});
										});
									});
								}
							});
						});
					});
				});
			});
		});
	},

	"removeNode": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}

			//TODO: check this
			var node = deployer.getNode(options.name);
			node.remove(function (error, result) {
				checkError(error, cb, function () {

					return cb(error, result);
				});
			});
		});
	},

	"updateNode": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				//update node is not yet implemented in dockerode
				var node = deployer.getNode(options.nodeId);

				//need to inspect node in order to get its current version and pass it to update call
				node.inspect(function (error, nodeRecord) {
					checkError(error, cb, function () {
						options.version = nodeRecord.Version.Index;
						node.update(options, function (error, result) {
							checkError(error, cb, function () {
								return cb(null, true);
							});
						});
					});
				});
			});
		});
	},

	"deployHAService": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}

			deployer.createService(options, cb);
		});
	},

	"scaleHAService": function (deployerConfig, options, mongo, cb) {

	},

	"deleteHAService": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}

			var serviceId = '';
			var service = deployer.getService(serviceId);
			service.remove(cb);
		});
	}
};
module.exports = deployer;
<commit_msg>SOAJ-364: implemented removeNode() in docker driver<commit_after>"use strict";
var fs = require("fs");
var Docker = require('dockerode');
var utils = require("soajs/lib/utils");
var Grid = require('gridfs-stream');
var fs = require('fs');
var rimraf = require('rimraf');

function checkError(error, cb, fCb) {
	if (error) {
		return cb(error, null);
	}
	return fCb();
}

function getDockerCerts(dockerConfig, certs, gfs, db, counter, cb) {
	var gs = new gfs.mongo.GridStore(db, certs[counter]._id, 'r', {
		root: 'fs',
		w: 1,
		fsync: true
	});

	gs.open(function (error, gstore) {
		checkError(error, cb, function () {
			gstore.read(function (error, filedata) {
				checkError(error, cb, function () {
					gstore.close();
					var certKey = certs[counter].filename.split(".")[0];
					dockerConfig[certKey] = filedata;

					counter++;
					if (counter === certs.length) {
						return cb(null, dockerConfig);
					}
					else {
						return getDockerCerts(dockerConfig, certs, gfs, db, counter, cb);
					}
				});
			});
		});
	});
}

var lib = {
	"getDeployer": function (deployerConfig, mongo, cb) {
		/**
			Three options:
				- local: use socket port
				- remote: get manager node record, extract ip/port and certificates
				- remote and adding a new node: in case of adding a new node, use ip/port of new node and certificates
		*/
		var config = utils.cloneObj(deployerConfig);
		var docker;
		if (config.socketPath) {
			docker = new Docker({socketPath: config.socketPath});
			return cb(null, docker);
		}
		else {
			var dockerConfig = {};
			getTargetNode(config, function (error, target) {
				checkError(error, cb, function () {
					dockerConfig.host = target.host;
					dockerConfig.port = target.port;

					getNodeCertificates(config, dockerConfig, function (error, dockerConfig) {
						checkError(error, cb, function () {
							docker = new Docker(dockerConfig);
							return cb(null, docker);
						});
					});
				});
			});
		}

		function getTargetNode(config, callback) {
			if (config.flags && (config.flags.newNode || config.flags.targetNode)) {
				if (!config.host || !config.port) {
					return callback({message: 'Missing host/port info'});
				}
				return callback(null, {host: config.host, port: config.port});
			}
			else {
				if (!config.nodes || (config.nodes && config.nodes.length === 0)) {
					return callback({message: 'No manager nodes found in this environment\'s deployer'});
				}
				var oneManagerNode = config.nodes[0]; //any manager node can be selected
				mongo.findOne('docker', {recordType: 'node', name: oneManagerNode}, function (error, nodeRecord) {
					checkError(error || !nodeRecord, callback, function () {
						return callback(null, {host: nodeRecord.ip, port: nodeRecord.dockerPort});
					});
				});
			}
		}

		function getNodeCertificates(config, dockerConfig, callback) {
			if (!config.envCode) {
				return callback({message: 'Missing environment code'});
			}

			var criteria = {};
			criteria['metadata.env.' + config.envCode.toUpperCase()] = config.selectedDriver;
			mongo.find('fs.files', criteria, function (error, certs) {
				checkError(error, callback, function () {
					if (!certs || (certs && certs.length === 0)) {
						return callback({message: 'No certificates for ' + config.envCode + ' environment found'});
					}

					mongo.getMongoSkinDB(function (error, db) {
						checkError(error, callback, function () {
							var gfs = Grid(db, mongo.mongoSkin);
							var counter = 0;
							getDockerCerts(dockerConfig, certs, gfs, db, counter, function (error, dockerConfig) {
								checkError(error, callback, function () {
									return callback(null, dockerConfig);
								});
							});
						});
					});
				});
			});
		}
	},

	"container": function (dockerInfo, action, cid, mongo, opts, cb) {
		lib.getDeployer(dockerInfo, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				var container = deployer.getContainer(cid);
				container[action](opts || null, function (error, response) {

					checkError(error, cb, function () {
						if (action === 'start' || action === 'restart') {
							container.inspect(cb);
						}
						else return cb(null, response);
					});
				});
			});
		});
	}
};
var deployer = {
	"createContainer": function (deployerConfig, params, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}
			deployer.createContainer(params, function (err, container) {
				checkError(err, cb, function () {
					container.inspect(cb);
				});
			});
		});
	},

	"start": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "start", cid, mongo, null, cb);
	},

	"exec": function (deployerConfig, cid, mongo, opts, cb) {
		lib.container(deployerConfig, "exec", cid, mongo, opts, cb);
	},

	"restart": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "restart", cid, mongo, null, cb);
	},

	"remove": function (deployerConfig, cid, mongo, cb) {
		lib.container(deployerConfig, "remove", cid, mongo, {"force": true}, cb);
	},

	"info": function (deployerConfig, cid, soajs, res, mongo) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			deployer.getContainer(cid).logs({
					stderr: true,
					stdout: true,
					timestamps: false,
					tail: 200
				},
				function (error, stream) {
					if (error) {
						soajs.log.error('logStreamContainer error: ', error);
						return res.json(soajs.buildResponse({"code": 601, "msg": error.message}));
					}
					else {
						var data = '';
						var chunk;
						stream.setEncoding('utf8');
						stream.on('readable', function () {
							var handle = this;
							while ((chunk = handle.read()) != null) {
								data += chunk.toString("utf8");
							}
						});

						stream.on('end', function () {
							stream.destroy();
							var out = soajs.buildResponse(null, {'data': data});
							return res.json(out);
						});
					}
				});
		});
	},

	"addNode": function (deployerConfig, options, mongo, cb) {
		deployerConfig.flags = {
			newNode: true
		};

		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				deployer.info(function (error, nodeInfo) {
					checkError(error, cb, function () {
						deployer.swarmJoin(options, function (error) {
							checkError(error, cb, function () {
								if (options.role === 'manager') {
									var node = deployer.getNode(nodeInfo.Name);
									node.inspect(cb);
								}
								else {
									//get manager node from swarm and inspect newly added node
									delete deployerConfig.flags;
									delete deployerConfig.host;
									delete deployerConfig.port;

									lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
										checkError(error, cb, function () {
											deployer.listNodes(function (error, nodes) {
												checkError(error, cb, function () {
													for (var i = 0; i < nodes.length; i++) {
														if (nodes[i].Description.Hostname === nodeInfo.Name) {
															return cb(null, nodes[i]);
														}
													}
													return cb();
												});
											});
										});
									});
								}
							});
						});
					});
				});
			});
		});
	},

	"removeNode": function (deployerConfig, options, mongo, cb) {
		/*
			- get deployer for target node
			- leave swarm
			- return success response
			- get deployer of a manager node in the swarm
			- remove node
		*/

		var targetDeployerConfig = JSON.parse(JSON.stringify(deployerConfig));
		targetDeployerConfig.host = options.ip;
		targetDeployerConfig.port = options.dockerPort;
		targetDeployerConfig.flags = { targetNode: true };
		lib.getDeployer(targetDeployerConfig, mongo, function (error, targetDeployer) {
			checkError(error, cb, function () {
				targetDeployer.swarmLeave(function (error) {
					checkError(error, cb, function () {

						//return response and remove node entry from swarm in the background
						cb(null, true);

						lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
							var node = deployer.getNode(options.id);
							setTimeout(function () {
								node.remove(); //TODO: handle callback
							}, 20000);
						});
					});
				});
			});
		});
	},

	"updateNode": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			checkError(error, cb, function () {
				//update node is not yet implemented in dockerode
				var node = deployer.getNode(options.nodeId);

				//need to inspect node in order to get its current version and pass it to update call
				node.inspect(function (error, nodeRecord) {
					checkError(error, cb, function () {
						options.version = nodeRecord.Version.Index;
						node.update(options, function (error, result) {
							checkError(error, cb, function () {
								return cb(null, true);
							});
						});
					});
				});
			});
		});
	},

	"deployHAService": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}

			deployer.createService(options, cb);
		});
	},

	"scaleHAService": function (deployerConfig, options, mongo, cb) {

	},

	"deleteHAService": function (deployerConfig, options, mongo, cb) {
		lib.getDeployer(deployerConfig, mongo, function (error, deployer) {
			if (error) {
				return cb(error);
			}

			var serviceId = '';
			var service = deployer.getService(serviceId);
			service.remove(cb);
		});
	}
};
module.exports = deployer;
<|endoftext|>


<commit_before>/**
 * Created by daniel.irwin on 5/24/17.
 */

const parseQuery = require('querystring').parse;
const parseUrl = require('url').parse;
const logger = require('./logger');
const LOG = new logger('Arupex-RouteAnalyzer');
class RouteAnalyzer {

    decompileRoute(route) {
        let parse = parseUrl(route);
        let routeUrl = parse.pathname;
        let method = 'GET';
        let methodRegex = /GET|POST|PUT|PATCH|DELETE|HEAD/i;

        if(route.indexOf(methodRegex) === 0){
            method = route.match(method)[0].toUpperCase();
            route = route.replace(methodRegex, '').trim();
        }

        const routeVariable = /{{\w+}}/g;

        return {
            method : method,
            route : route,
            path : decodeURIComponent(routeUrl),//because url.parse encodes it :(
            regex : new RegExp(routeUrl.split(routeVariable).join('([\\w+|-]+)').replace(/\//g,'\\/')),
            pathParams : (routeUrl.match(routeVariable) || []).map(s => s.replace(/{{|}}/g, '')) || [],
            routePieces : (routeUrl.includes('?')?routeUrl.substr(0, routeUrl.indexOf('?')):routeUrl).split(/{{\w+}}|\//g).filter(e=>e),
            query : parseQuery(parse.query) || {}
        };
    }

    conductor(routeMap) {

        let routes = Object.keys(routeMap)
            .map( (route) => this.decompileRoute(route));

        //conductor acts upon a requested route
        return (requestedRoute) => {

            let routesFound = routes.filter( route => route.regex.test(requestedRoute));
            let routeFind = this.findLongestRoute(routesFound);

            if(routeFind){
                let parsed = parseUrl(requestedRoute);
                let query = parseQuery(parsed.query);
                let matches = routeFind.regex.exec(requestedRoute);

                let routeQueryKeys = Object.keys(routeFind.query);

                let missingParams = [];
                let resolvedQueryParams = routeQueryKeys.reduce((acc, v) => {
                    if(query[v]) {
                        acc[routeFind.query[v] ? routeFind.query[v].replace(/{{|}}|{|}/g, '') : ''] = query[v];
                    }
                    else if(/{{.*}}/g.test(routeFind.query[v])){
                        missingParams.push(v);
                    }
                    return acc;
                }, {});

                if(missingParams.length > 0){
                    throw new Error('missing parameter(s) ' + missingParams);
                }

                let pathParams = routeFind.pathParams.reduce((acc, key, i) => {
                    acc[key] = matches[i+1];
                    return acc;
                }, {});

                return Object.assign({}, routeFind, {
                    rail : routeMap[routeFind.route],
                    requestedRoute: requestedRoute,
                    queryParams : resolvedQueryParams,
                    pathParams : pathParams,

                    //What AWS Calls Them
                    queryStringParameters : resolvedQueryParams,
                    pathParameters : pathParams,
                    resource : requestedRoute
                });
            }
        };
    }

    findLongestRoute(routesFound) {
        let routeFind = null;
        if (routesFound.length > 1) {
            LOG.warn(`multiple routes matched looking for the one with the largest length`);
            let routeLengths = routesFound.reduce((acc, v) => {
                if (v.length > acc.length) {
                    acc = {
                        length: v.length,
                        last: v,
                        count: 1
                    };
                }
                if (v.length = acc.length) {
                    acc.count++;
                    acc.last = v;
                }
                return acc;
            }, {
                length: routesFound[0].length,
                last: routesFound[0],
                count: 1
            });

            if (routeLengths.count > 1) {
                LOG.warn(`multiple routes were considered the 'longest', selecting the last one`);
            }
            routeFind = routeLengths.last;
        }
        else if (routesFound.length === 1) {
            routeFind = routesFound[0];
        }
        return routeFind;
    }
}

module.exports = new RouteAnalyzer();<commit_msg>Fix logic to find longest route and include logs<commit_after>/**
 * Created by daniel.irwin on 5/24/17.
 */

const parseQuery = require('querystring').parse;
const parseUrl = require('url').parse;
const logger = require('./logger');
const LOG = new logger('Arupex-RouteAnalyzer');
class RouteAnalyzer {

    decompileRoute(route) {
        let parse = parseUrl(route);
        let routeUrl = parse.pathname;
        const path = decodeURIComponent(routeUrl);//because url.parse encodes it :(
        let method = 'GET';
        let methodRegex = /GET|POST|PUT|PATCH|DELETE|HEAD/i;

        if(route.indexOf(methodRegex) === 0){
            method = route.match(method)[0].toUpperCase();
            route = route.replace(methodRegex, '').trim();
        }

        const routeVariable = /{{\w+}}/g;

        return {
            method : method,
            route : route,
            path : path,
            length : path.length,
            regex : new RegExp(routeUrl.split(routeVariable).join('([\\w+|-]+)').replace(/\//g,'\\/')),
            pathParams : (routeUrl.match(routeVariable) || []).map(s => s.replace(/{{|}}/g, '')) || [],
            routePieces : (routeUrl.includes('?')?routeUrl.substr(0, routeUrl.indexOf('?')):routeUrl).split(/{{\w+}}|\//g).filter(e=>e),
            query : parseQuery(parse.query) || {}
        };
    }

    conductor(routeMap) {

        let routes = Object.keys(routeMap)
            .map( (route) => this.decompileRoute(route));

        //conductor acts upon a requested route
        return (requestedRoute) => {

            let routesFound = routes.filter( route => {
                if (route.regex.test(requestedRoute)) {
                    LOG.info(`matched path: ${route.path}`);
                    return true;
                }
            });
            let routeFind = this.findLongestRoute(routesFound);

            if(routeFind){
                let parsed = parseUrl(requestedRoute);
                let query = parseQuery(parsed.query);
                let matches = routeFind.regex.exec(requestedRoute);

                let routeQueryKeys = Object.keys(routeFind.query);

                let missingParams = [];
                let resolvedQueryParams = routeQueryKeys.reduce((acc, v) => {
                    if(query[v]) {
                        acc[routeFind.query[v] ? routeFind.query[v].replace(/{{|}}|{|}/g, '') : ''] = query[v];
                    }
                    else if(/{{.*}}/g.test(routeFind.query[v])){
                        missingParams.push(v);
                    }
                    return acc;
                }, {});

                if(missingParams.length > 0){
                    throw new Error('missing parameter(s) ' + missingParams);
                }

                let pathParams = routeFind.pathParams.reduce((acc, key, i) => {
                    acc[key] = matches[i+1];
                    return acc;
                }, {});

                return Object.assign({}, routeFind, {
                    rail : routeMap[routeFind.route],
                    requestedRoute: requestedRoute,
                    queryParams : resolvedQueryParams,
                    pathParams : pathParams,

                    //What AWS Calls Them
                    queryStringParameters : resolvedQueryParams,
                    pathParameters : pathParams,
                    resource : requestedRoute
                });
            }
        };
    }

    findLongestRoute(routesFound) {
        let routeFind = null;
        if (routesFound.length > 1) {
            LOG.warn(`multiple paths matched looking for the one with the largest length`);
            let routeLengths = routesFound.reduce((acc, v) => {
                if (v.length > acc.length) {
                    acc = {
                        length: v.length,
                        last: v,
                        count: 1
                    };
                }
                if (v.length === acc.length) {
                    acc.count++;
                    acc.last = v;
                }
                return acc;
            }, {
                length: routesFound[0].length,
                last: routesFound[0],
                count: 1
            });

            if (routeLengths.count > 1) {
                LOG.warn(`multiple paths were considered the 'longest', selecting the last one`);
            }
            routeFind = routeLengths.last;
            LOG.warn(`selected path: ${routeFind.path}`);
        }
        else if (routesFound.length === 1) {
            routeFind = routesFound[0];
        }
        return routeFind;
    }
}

module.exports = new RouteAnalyzer();<|endoftext|>