<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var alertMessageDisplayed = false;

function displayMonoxideDanger() {
  if (!alertMessageDisplayed) {
    var m2x = new M2X("b508161c43e6b6dae291d655145999a4");
    m2x.feeds.streamValues(
      //"314b8fd2a5639cd6ed9597b6eb37ad78",
      "c6eabf437b8c69efbb4e4a8d5c60c04d",
      "danger",
      {},
      function(a) {
        console.log(a);
        var co_danger = parseInt(a['values'][0]['value']);
        if (co_danger == 0) {
          alertMsg();
        }
        if (co_danger == 1) {
          clearDanger();
        }
      });
  }
}

function alertDismissed() {
  alertMessageDisplayed = false;
}

function clearDanger() {
  var el = document.getElementById("monoxide");
  el.className = "safe";
  el.innerHTML = "Carbon monoxide levels safe."
}

function alertMsg(){
    alertMessageDisplayed = true;
    var el = document.getElementById("monoxide");
    el.className = "danger";
    el.innerHTML = "Carbon monoxide levels are unsafe."

    navigator.notification.alert(
        'Carbon monoxide levels are unsafe!',  // message
        alertDismissed,         // callback
        'Warning',            // title
        'Done'                  // buttonName
    );
}

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
      app.receivedEvent('deviceready');
      displayMonoxideDanger();
      setInterval(displayMonoxideDanger, 5000);
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};
<commit_msg>flip meaning of safe<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var alertMessageDisplayed = false;

function displayMonoxideDanger() {
  if (!alertMessageDisplayed) {
    var m2x = new M2X("b508161c43e6b6dae291d655145999a4");
    m2x.feeds.streamValues(
      //"314b8fd2a5639cd6ed9597b6eb37ad78",
      "c6eabf437b8c69efbb4e4a8d5c60c04d",
      "danger",
      {},
      function(a) {
        console.log(a);
        var co_danger = parseInt(a['values'][0]['value']);
        if (co_danger == 1) {
          alertMsg();
        }
        if (co_danger == 0) {
          clearDanger();
        }
      });
  }
}

function alertDismissed() {
  alertMessageDisplayed = false;
}

function clearDanger() {
  var el = document.getElementById("monoxide");
  el.className = "safe";
  el.innerHTML = "Carbon monoxide levels safe."
}

function alertMsg(){
    alertMessageDisplayed = true;
    var el = document.getElementById("monoxide");
    el.className = "danger";
    el.innerHTML = "Carbon monoxide levels are unsafe."

    navigator.notification.alert(
        'Carbon monoxide levels are unsafe!',  // message
        alertDismissed,         // callback
        'Warning',            // title
        'Done'                  // buttonName
    );
}

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
      app.receivedEvent('deviceready');
      displayMonoxideDanger();
      setInterval(displayMonoxideDanger, 5000);
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};
<|endoftext|>


<commit_before>import React, {PropTypes, Component} from 'react'
import OnClickOutside from 'react-onclickoutside'

import Dropdown from 'shared/components/Dropdown'
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'
import TemplateQueryBuilder
  from 'src/dashboards/components/TemplateQueryBuilder'

import {
  runTemplateVariableQuery as runTemplateVariableQueryAJAX,
} from 'src/dashboards/apis'

import parsers from 'shared/parsing'

import {TEMPLATE_TYPES} from 'src/dashboards/constants'
import q
  from 'src/dashboards/utils/onlyTheBigliestBigLeagueTemplateVariableQueryGenerator'

const TemplateVariableRow = ({
  template: {id, label, tempVar, values},
  isEditing,
  selectedType,
  selectedDatabase,
  selectedMeasurement,
  onSelectType,
  onSelectDatabase,
  onSelectMeasurement,
  selectedTagKey,
  onSelectTagKey,
  onStartEdit,
  onCancelEdit,
  autoFocusTarget,
  onSubmit,
  onDelete,
}) => (
  <form
    className="tr"
    onSubmit={onSubmit({
      selectedType,
      selectedDatabase,
      selectedMeasurement,
      selectedTagKey,
    })}
  >
    <TableInput
      name="label"
      defaultValue={label}
      isEditing={isEditing}
      onStartEdit={onStartEdit}
      autoFocusTarget={autoFocusTarget}
    />
    <TableInput
      name="tempVar"
      defaultValue={tempVar}
      isEditing={isEditing}
      onStartEdit={onStartEdit}
      autoFocusTarget={autoFocusTarget}
    />

      <Dropdown
        items={TEMPLATE_TYPES}
        onChoose={onSelectType}
        onClick={() => onStartEdit(null)}
        selected={TEMPLATE_TYPES.find(t => t.type === selectedType).text}
        className={'template-variable--dropdown'}
      />

      <TemplateQueryBuilder
        onSelectDatabase={onSelectDatabase}
        selectedType={selectedType}
        selectedDatabase={selectedDatabase}
        onSelectMeasurement={onSelectMeasurement}
        selectedMeasurement={selectedMeasurement}
        selectedTagKey={selectedTagKey}
        onSelectTagKey={onSelectTagKey}
        onStartEdit={onStartEdit}
      />

      {values.length
        ? values.map(({value}) => value).join(', ')
        : '(Query returned no values)'}

      {isEditing
        ?

            <button className="btn btn-sm btn-success" type="submit">
              Run Query
            </button>
            <button
              className="btn btn-sm btn-primary"
              type="button"
              onClick={onCancelEdit}
            >
              Cancel
            </button>

        : <DeleteConfirmButtons onDelete={() => onDelete(id)} />}

  </form>
)

const TableInput = ({
  name,
  defaultValue,
  isEditing,
  onStartEdit,
  autoFocusTarget,
}) => {
  return isEditing
    ?

        <input
          required={true}
          name={name}
          autoFocus={name === autoFocusTarget}
          className="input"
          type="text"
          defaultValue={defaultValue}
        />

    :
 onStartEdit(name)}>{defaultValue}

}

class RowWrapper extends Component {
  constructor(props) {
    super(props)
    const {template: {query, type}} = this.props

    this.state = {
      isEditing: false,
      selectedType: type,
      selectedDatabase: query && query.db,
      selectedMeasurement: query && query.measurement,
      selectedTagKey: query && query.tagKey,
      autoFocusTarget: null,
    }

    this.handleRunQueryRequested = ::this.handleRunQueryRequested
    this.handleSelectType = ::this.handleSelectType
    this.handleSelectDatabase = ::this.handleSelectDatabase
    this.handleSelectMeasurement = ::this.handleSelectMeasurement
    this.handleSelectTagKey = ::this.handleSelectTagKey
    this.handleStartEdit = ::this.handleStartEdit
    this.handleCancelEdit = ::this.handleCancelEdit
    this.runTemplateVariableQuery = ::this.runTemplateVariableQuery
  }

  handleRunQueryRequested({
    selectedDatabase: database,
    selectedMeasurement: measurement,
    selectedTagKey: tagKey,
    selectedType: type,
  }) {
    return async e => {
      e.preventDefault()

      this.setState({isEditing: false})

      const label = e.target.label.value
      const tempVar = e.target.tempVar.value

      const {
        source,
        template,
        onRunQuerySuccess,
        onRunQueryFailure,
      } = this.props

      const {query, tempVars} = q({
        type,
        label,
        tempVar,
        query: {
          database,
          // rp, TODO
          measurement,
          tagKey,
        },
      })

      const queryConfig = {
        query,
        database,
        // rp: TODO
        tempVars,
        type,
        measurement,
        tagKey,
      }

      try {
        const parsedData = await this.runTemplateVariableQuery(
          source,
          queryConfig
        )
        onRunQuerySuccess(template, queryConfig, parsedData, {tempVar, label})
      } catch (error) {
        onRunQueryFailure(error)
      }
    }
  }

  handleClickOutside() {
    this.setState({isEditing: false})
  }

  handleStartEdit(name) {
    this.setState({isEditing: true, autoFocusTarget: name})
  }

  handleCancelEdit() {
    const {template: {type, query: {db, measurement, tagKey}}} = this.props
    this.setState({
      selectedType: type,
      selectedDatabase: db,
      selectedMeasurement: measurement,
      selectedKey: tagKey,
      isEditing: false,
    })
  }

  handleSelectType(item) {
    this.setState({
      selectedType: item.type,
      selectedDatabase: null,
      selectedMeasurement: null,
      selectedKey: null,
    })
  }

  handleSelectDatabase(item) {
    this.setState({selectedDatabase: item.text})
  }

  handleSelectMeasurement(item) {
    this.setState({selectedMeasurement: item.text})
  }

  handleSelectTagKey(item) {
    this.setState({selectedTagKey: item.text})
  }

  async runTemplateVariableQuery(
    source,
    {query, database, rp, tempVars, type, measurement, tagKey}
  ) {
    try {
      const {data} = await runTemplateVariableQueryAJAX(source, {
        query,
        db: database,
        rp,
        tempVars,
      })
      const parsedData = parsers[type](data, tagKey || measurement) // tagKey covers tagKey and fieldKey
      if (parsedData.errors.length) {
        throw parsedData.errors
      }

      return parsedData[type]
    } catch (error) {
      console.error(error)
      throw error
    }
  }

  render() {
    const {
      isEditing,
      selectedType,
      selectedDatabase,
      selectedMeasurement,
      selectedTagKey,
      autoFocusTarget,
    } = this.state

    return (
      <TemplateVariableRow
        {...this.props}
        isEditing={isEditing}
        selectedType={selectedType}
        selectedDatabase={selectedDatabase}
        selectedMeasurement={selectedMeasurement}
        selectedTagKey={selectedTagKey}
        onSelectType={this.handleSelectType}
        onSelectDatabase={this.handleSelectDatabase}
        onSelectMeasurement={this.handleSelectMeasurement}
        onSelectTagKey={this.handleSelectTagKey}
        onStartEdit={this.handleStartEdit}
        onCancelEdit={this.handleCancelEdit}
        autoFocusTarget={autoFocusTarget}
        onSubmit={this.handleRunQueryRequested}
      />
    )
  }
}

const {arrayOf, bool, func, shape, string} = PropTypes

RowWrapper.propTypes = {
  source: shape({
    links: shape({
      proxy: string,
    }),
  }).isRequired,
  template: shape({
    type: string.isRequired,
    label: string.isRequired,
    tempVar: string.isRequired,
    query: shape({
      db: string,
      influxql: string,
      measurement: string,
      tagKey: string,
    }),
    values: arrayOf(
      shape({
        value: string.isRequired,
        type: string.isRequired,
        selected: bool.isRequired,
      })
    ).isRequired,
    links: shape({
      self: string.isRequired,
    }),
  }),
  onRunQuerySuccess: func.isRequired,
  onRunQueryFailure: func.isRequired,
  onDelete: func.isRequired,
}

TemplateVariableRow.propTypes = {
  ...RowWrapper.propTypes,
  selectedType: string.isRequired,
  selectedDatabase: string,
  selectedTagKey: string,
  onSelectType: func.isRequired,
  onSelectDatabase: func.isRequired,
  onSelectTagKey: func.isRequired,
  onStartEdit: func.isRequired,
  onCancelEdit: func.isRequired,
  onSubmit: func.isRequired,
}

TableInput.propTypes = {
  defaultValue: string,
  isEditing: bool.isRequired,
  onStartEdit: func.isRequired,
  name: string.isRequired,
  autoFocusTarget: string,
}

export default OnClickOutside(RowWrapper)
<commit_msg>Change copy when no values<commit_after>import React, {PropTypes, Component} from 'react'
import OnClickOutside from 'react-onclickoutside'

import Dropdown from 'shared/components/Dropdown'
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'
import TemplateQueryBuilder
  from 'src/dashboards/components/TemplateQueryBuilder'

import {
  runTemplateVariableQuery as runTemplateVariableQueryAJAX,
} from 'src/dashboards/apis'

import parsers from 'shared/parsing'

import {TEMPLATE_TYPES} from 'src/dashboards/constants'
import q
  from 'src/dashboards/utils/onlyTheBigliestBigLeagueTemplateVariableQueryGenerator'

const TemplateVariableRow = ({
  template: {id, label, tempVar, values},
  isEditing,
  selectedType,
  selectedDatabase,
  selectedMeasurement,
  onSelectType,
  onSelectDatabase,
  onSelectMeasurement,
  selectedTagKey,
  onSelectTagKey,
  onStartEdit,
  onCancelEdit,
  autoFocusTarget,
  onSubmit,
  onDelete,
}) => (
  <form
    className="tr"
    onSubmit={onSubmit({
      selectedType,
      selectedDatabase,
      selectedMeasurement,
      selectedTagKey,
    })}
  >
    <TableInput
      name="label"
      defaultValue={label}
      isEditing={isEditing}
      onStartEdit={onStartEdit}
      autoFocusTarget={autoFocusTarget}
    />
    <TableInput
      name="tempVar"
      defaultValue={tempVar}
      isEditing={isEditing}
      onStartEdit={onStartEdit}
      autoFocusTarget={autoFocusTarget}
    />

      <Dropdown
        items={TEMPLATE_TYPES}
        onChoose={onSelectType}
        onClick={() => onStartEdit(null)}
        selected={TEMPLATE_TYPES.find(t => t.type === selectedType).text}
        className={'template-variable--dropdown'}
      />

      <TemplateQueryBuilder
        onSelectDatabase={onSelectDatabase}
        selectedType={selectedType}
        selectedDatabase={selectedDatabase}
        onSelectMeasurement={onSelectMeasurement}
        selectedMeasurement={selectedMeasurement}
        selectedTagKey={selectedTagKey}
        onSelectTagKey={onSelectTagKey}
        onStartEdit={onStartEdit}
      />

      {values.length
        ? values.map(({value}) => value).join(', ')
        : '(No values to display)'}

      {isEditing
        ?

            <button className="btn btn-sm btn-success" type="submit">
              Run Query
            </button>
            <button
              className="btn btn-sm btn-primary"
              type="button"
              onClick={onCancelEdit}
            >
              Cancel
            </button>

        : <DeleteConfirmButtons onDelete={() => onDelete(id)} />}

  </form>
)

const TableInput = ({
  name,
  defaultValue,
  isEditing,
  onStartEdit,
  autoFocusTarget,
}) => {
  return isEditing
    ?

        <input
          required={true}
          name={name}
          autoFocus={name === autoFocusTarget}
          className="input"
          type="text"
          defaultValue={defaultValue}
        />

    :
 onStartEdit(name)}>{defaultValue}

}

class RowWrapper extends Component {
  constructor(props) {
    super(props)
    const {template: {query, type}} = this.props

    this.state = {
      isEditing: false,
      selectedType: type,
      selectedDatabase: query && query.db,
      selectedMeasurement: query && query.measurement,
      selectedTagKey: query && query.tagKey,
      autoFocusTarget: null,
    }

    this.handleRunQueryRequested = ::this.handleRunQueryRequested
    this.handleSelectType = ::this.handleSelectType
    this.handleSelectDatabase = ::this.handleSelectDatabase
    this.handleSelectMeasurement = ::this.handleSelectMeasurement
    this.handleSelectTagKey = ::this.handleSelectTagKey
    this.handleStartEdit = ::this.handleStartEdit
    this.handleCancelEdit = ::this.handleCancelEdit
    this.runTemplateVariableQuery = ::this.runTemplateVariableQuery
  }

  handleRunQueryRequested({
    selectedDatabase: database,
    selectedMeasurement: measurement,
    selectedTagKey: tagKey,
    selectedType: type,
  }) {
    return async e => {
      e.preventDefault()

      this.setState({isEditing: false})

      const label = e.target.label.value
      const tempVar = e.target.tempVar.value

      const {
        source,
        template,
        onRunQuerySuccess,
        onRunQueryFailure,
      } = this.props

      const {query, tempVars} = q({
        type,
        label,
        tempVar,
        query: {
          database,
          // rp, TODO
          measurement,
          tagKey,
        },
      })

      const queryConfig = {
        query,
        database,
        // rp: TODO
        tempVars,
        type,
        measurement,
        tagKey,
      }

      try {
        const parsedData = await this.runTemplateVariableQuery(
          source,
          queryConfig
        )
        onRunQuerySuccess(template, queryConfig, parsedData, {tempVar, label})
      } catch (error) {
        onRunQueryFailure(error)
      }
    }
  }

  handleClickOutside() {
    this.setState({isEditing: false})
  }

  handleStartEdit(name) {
    this.setState({isEditing: true, autoFocusTarget: name})
  }

  handleCancelEdit() {
    const {template: {type, query: {db, measurement, tagKey}}} = this.props
    this.setState({
      selectedType: type,
      selectedDatabase: db,
      selectedMeasurement: measurement,
      selectedKey: tagKey,
      isEditing: false,
    })
  }

  handleSelectType(item) {
    this.setState({
      selectedType: item.type,
      selectedDatabase: null,
      selectedMeasurement: null,
      selectedKey: null,
    })
  }

  handleSelectDatabase(item) {
    this.setState({selectedDatabase: item.text})
  }

  handleSelectMeasurement(item) {
    this.setState({selectedMeasurement: item.text})
  }

  handleSelectTagKey(item) {
    this.setState({selectedTagKey: item.text})
  }

  async runTemplateVariableQuery(
    source,
    {query, database, rp, tempVars, type, measurement, tagKey}
  ) {
    try {
      const {data} = await runTemplateVariableQueryAJAX(source, {
        query,
        db: database,
        rp,
        tempVars,
      })
      const parsedData = parsers[type](data, tagKey || measurement) // tagKey covers tagKey and fieldKey
      if (parsedData.errors.length) {
        throw parsedData.errors
      }

      return parsedData[type]
    } catch (error) {
      console.error(error)
      throw error
    }
  }

  render() {
    const {
      isEditing,
      selectedType,
      selectedDatabase,
      selectedMeasurement,
      selectedTagKey,
      autoFocusTarget,
    } = this.state

    return (
      <TemplateVariableRow
        {...this.props}
        isEditing={isEditing}
        selectedType={selectedType}
        selectedDatabase={selectedDatabase}
        selectedMeasurement={selectedMeasurement}
        selectedTagKey={selectedTagKey}
        onSelectType={this.handleSelectType}
        onSelectDatabase={this.handleSelectDatabase}
        onSelectMeasurement={this.handleSelectMeasurement}
        onSelectTagKey={this.handleSelectTagKey}
        onStartEdit={this.handleStartEdit}
        onCancelEdit={this.handleCancelEdit}
        autoFocusTarget={autoFocusTarget}
        onSubmit={this.handleRunQueryRequested}
      />
    )
  }
}

const {arrayOf, bool, func, shape, string} = PropTypes

RowWrapper.propTypes = {
  source: shape({
    links: shape({
      proxy: string,
    }),
  }).isRequired,
  template: shape({
    type: string.isRequired,
    label: string.isRequired,
    tempVar: string.isRequired,
    query: shape({
      db: string,
      influxql: string,
      measurement: string,
      tagKey: string,
    }),
    values: arrayOf(
      shape({
        value: string.isRequired,
        type: string.isRequired,
        selected: bool.isRequired,
      })
    ).isRequired,
    links: shape({
      self: string.isRequired,
    }),
  }),
  onRunQuerySuccess: func.isRequired,
  onRunQueryFailure: func.isRequired,
  onDelete: func.isRequired,
}

TemplateVariableRow.propTypes = {
  ...RowWrapper.propTypes,
  selectedType: string.isRequired,
  selectedDatabase: string,
  selectedTagKey: string,
  onSelectType: func.isRequired,
  onSelectDatabase: func.isRequired,
  onSelectTagKey: func.isRequired,
  onStartEdit: func.isRequired,
  onCancelEdit: func.isRequired,
  onSubmit: func.isRequired,
}

TableInput.propTypes = {
  defaultValue: string,
  isEditing: bool.isRequired,
  onStartEdit: func.isRequired,
  name: string.isRequired,
  autoFocusTarget: string,
}

export default OnClickOutside(RowWrapper)
<|endoftext|>


<commit_before>import { Text, View } from 'react-native';
import { configure, addDecorator } from "@storybook/react";
import { withInfo, setDefaults } from '@storybook/addon-info';
import { setOptions } from '@storybook/addon-options';
import { withKnobs } from '@storybook/addon-knobs/react';

const req = require.context(
  "../packages",
  true,
  /^((?!node_modules).)*\.(stories|stories.web)\.js$/
);

setDefaults({
  propTablesExclude: [Text, View]
})

setOptions({
  name: 'Times Components',
  hierarchySeparator: /\//
});

addDecorator(withKnobs);
addDecorator((story, context) => withInfo('')(story)(context));

const loadStories = () => req.keys().forEach(filename => req(filename));

configure(loadStories, module);
<commit_msg>fix: swap order of storybook decorators (#866)<commit_after>import { Text, View } from 'react-native';
import { configure, addDecorator } from "@storybook/react";
import { withInfo, setDefaults } from '@storybook/addon-info';
import { setOptions } from '@storybook/addon-options';
import { withKnobs } from '@storybook/addon-knobs/react';

const req = require.context(
  "../packages",
  true,
  /^((?!node_modules).)*\.(stories|stories.web)\.js$/
);

setDefaults({
  propTablesExclude: [Text, View]
})

setOptions({
  name: 'Times Components',
  hierarchySeparator: /\//
});

addDecorator((story, context) => withInfo('')(story)(context));
addDecorator(withKnobs);

const loadStories = () => req.keys().forEach(filename => req(filename));

configure(loadStories, module);
<|endoftext|>


<commit_before>var http = require('http');
var agent = new (http.Agent)({maxSockets: 8});
var IncomingMessage = http.IncomingMessage;
var tls = require('tls');
var CRLF = '\r\n';
var CRLF_BUF = new Buffer(CRLF);
var MAX_BYTES = 1024 * 128;

function isCRLF(buffer, start) {
	   return buffer[start] ==  CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1];
}

function getStringHeaders(req) {
	var headers = [req.method + ' ' + req.url + ' HTTP/' + req.httpVersion];
	if (req.headers && !req.headers.Host) {
		req.headers.Host = req.headers.host;
	}
	for (var key in req.headers) {
		var line = req.headers[key];
		if (Array.isArray(line)) {
			line.forEach(function(value) {
				headers.push(key + ': ' + value);
			});
		} else {
			headers.push(key + ': ' + line);
		}
	}
	headers.push(CRLF);

	return headers.join(CRLF);
}

function resolveResponse(proxyReq, callback) {
	var proxyRes = new IncomingMessage(proxyReq);
	var index = 0;
	var buffer, ended, done, over;

	function execCallback(err) {
		if (!done) {
			callback(err, proxyRes);
			done = true;
		}
	}

	function setHeaders(proxyRes, buffer) {
		var headers = {};
		buffer = buffer.toString().split(/\r\n/g);
		var firstLine = getEntry(buffer[0]);
		if (firstLine) {
			proxyRes.httpVersion = firstLine.key.split('/')[1];
			proxyRes.statusCode = firstLine.value;
		}

		for (var i = 1, len = buffer.length; i < len; i++) {
			var entry = getEntry(buffer[i]);
			if (entry) {
				var value = headers[entry.key];
				if (value) {
					if (!Array.isArray(value)) {
						value = [value];
					}
					value.push(entry.value);
				} else {
					headers[entry.key] = entry.value;
				}
			}
		}
		proxyRes.headers = headers;
		return proxyRes;
	}

	function getEntry(line) {
		if (line) {
			line = line.trim().split(/\s+/g);
			if (line[0] && line[1]) {
				line = {
						key: line[0].toLowerCase(),
						value: line[1]
				}
			} else {
				line = null;
			}
		}

		return line;
	}

   proxyReq.on('data', function(data) {
	   if (ended) {
		   proxyRes.push(data);
		   return;
	   }

	   buffer = buffer ? Buffer.concat([buffer, data]) : data;
	   while(buffer[index]) {
		   if (isCRLF(buffer, index)) {
			   ended = isCRLF(buffer, index + 2);
			   if (!over) {
				   over = buffer.length >= MAX_BYTES;
				   if (ended) {
					   index += 4;
					   setHeaders(proxyRes, buffer.slice(0, index));
					   execCallback();
					   buffer = buffer.slice(index);
					   index = 0;
				   }
			   } else if (ended) {
				   proxyRes.push(buffer.slice(index + 4));
			   }
		   }
		   index++;
	   }

   });

   proxyReq.on('end', function() {
	   execCallback(new Error('Bad response'));
	   proxyRes.push(null);
   });
}

module.exports = function proxy(req, callback) {
	var headers = req.headers;
	var options = req.options;
	var done;

	function execCallback(err, proxyRes) {
		if (!done) {
			callback && callback(err, proxyRes);
			done = true;
		}
	}

	options.method = 'CONNECT';
	options.path = headers.host;
	if (options.agent == null) {
		options.agent = agent;
	}
	options.headers = {
			host : headers.host,
			'proxy-connection': 'keep-alive',
			'user-agent': headers['user-agent']
		};

	http.request(options).on('error', execCallback)
	.on('connect', function (res, socket, head) {
		socket.on('error', execCallback);
	    var proxyReq = tls.connect({
	        rejectUnauthorized: false,
	        socket: socket
	    }, function () {
	        proxyReq.write(getStringHeaders(req));
	        req.pipe(proxyReq);
	    }).on('error', execCallback);

	 resolveResponse(proxyReq, execCallback);
	}).end();
};

<commit_msg>https proxy<commit_after>var http = require('http');
var agent = new (http.Agent)({maxSockets: 8});
var IncomingMessage = http.IncomingMessage;
var tls = require('tls');
var CRLF = '\r\n';
var CRLF_BUF = new Buffer(CRLF);
var MAX_BYTES = 1024 * 128;

function isCRLF(buffer, start) {
	   return buffer[start] ==  CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1];
}

function getStringHeaders(req) {
	var headers = [req.method + ' ' + req.url + ' HTTP/' + req.httpVersion];
	if (req.headers && !req.headers.Host) {
		req.headers.Host = req.headers.host;
	}
	for (var key in req.headers) {
		var line = req.headers[key];
		if (Array.isArray(line)) {
			line.forEach(function(value) {
				headers.push(key + ': ' + value);
			});
		} else {
			headers.push(key + ': ' + line);
		}
	}
	headers.push(CRLF);

	return headers.join(CRLF);
}

function resolveResponse(proxyReq, callback) {
	var proxyRes = new IncomingMessage(proxyReq);
	var index = 0;
	var buffer, ended, done, over;

	function execCallback(err) {
		if (!done) {
			callback(err, proxyRes);
			done = true;
		}
	}

	function setHeaders(proxyRes, buffer) {
		var headers = {};
		buffer = buffer.toString().split(/\r\n/g);
		var firstLine = getEntry(buffer[0]);
		if (firstLine) {
			proxyRes.httpVersion = firstLine.key.split('/')[1];
			proxyRes.statusCode = firstLine.value;
		}

		for (var i = 1, len = buffer.length; i < len; i++) {
			var entry = getEntry(buffer[i]);
			if (entry) {
				var value = headers[entry.key];
				if (value) {
					if (!Array.isArray(value)) {
						value = [value];
					}
					value.push(entry.value);
				} else {
					headers[entry.key] = entry.value;
				}
			}
		}
		proxyRes.headers = headers;
		return proxyRes;
	}

	function getEntry(line) {
		if (line) {
			line = line.trim().split(/\s+/g);
			if (line[0] && line[1]) {
				line = {
						key: line[0].toLowerCase(),
						value: line[1]
				}
			} else {
				line = null;
			}
		}

		return line;
	}

   proxyReq.on('data', function(data) {
	   if (ended) {
		   proxyRes.push(data);
		   return;
	   }

	   buffer = buffer ? Buffer.concat([buffer, data]) : data;
	   while(buffer[index]) {
		   if (isCRLF(buffer, index)) {
			   ended = isCRLF(buffer, index + 2);
			   if (!over) {
				   over = buffer.length >= MAX_BYTES;
				   if (ended) {
					   index += 4;
					   setHeaders(proxyRes, buffer.slice(0, index));
					   execCallback();
					   buffer = buffer.slice(index);
					   index = 0;
				   }
			   } else if (ended) {
				   proxyRes.push(buffer.slice(index + 4));
			   }
		   }
		   index++;
	   }

   });

   proxyReq.on('end', function() {
	   execCallback(new Error('Bad response'));
	   proxyRes.push(null);
   });
}

module.exports = function proxy(req, callback) {
	var headers = req.headers;
	var options = req.options;
	var done;

	function execCallback(err, proxyRes) {
		if (!done) {
			callback && callback(err, proxyRes);
			done = true;
		}
	}

	options.method = 'CONNECT';
	options.path = headers.host;
	if (options.agent == null) {
		options.agent = agent;
	}
	options.headers = {
			host : headers.host,
			'proxy-connection': 'keep-alive',
			'user-agent': headers['user-agent']
		};

	http.request(options).on('error', execCallback)
	.on('connect', function (res, socket, head) {
		socket.on('error', execCallback);
	    var proxyReq = tls.connect({
	        rejectUnauthorized: false,
	        socket: socket
	    }, function () {
	        proxyReq.write(getStringHeaders(req));
	        req.on('data', function(data) {
	        	proxyReq.write(data);
	        });
	        req.on('end', function() {
	        	proxyReq.end();
	        });
	    }).on('error', execCallback);

	 resolveResponse(proxyReq, execCallback);
	}).end();
};

<|endoftext|>


<commit_before>"use strict";
if (process.env.NODE_ENV === "test") {
  exports.osmbc_version = "1.8.4";
} else {
  exports.osmbc_version = "3.7.2d";
}
<commit_msg>no message<commit_after>"use strict";
if (process.env.NODE_ENV === "test") {
  exports.osmbc_version = "1.8.4";
} else {
  exports.osmbc_version = "3.8.0";
}
<|endoftext|>


<commit_before>angular.module('Directory.user', ['Directory.loader', 'Directory.users.models'])
.factory('Me', ['$q', '$timeout', 'Loader', 'User', function ($q, $timeout, Loader, User) {
  var currentUser;

  var Me = Loader(User.get('me')).then(function(user) {
    currentUser = user;
    Me.authenticated.apply(Me, Me.authenticatedParams);
    return currentUser;
  });

  Me.authenticated = function () {
    var argsArray = Array.prototype.slice.call(arguments);
    if (currentUser) {
      currentUser.authenticated.apply(currentUser, argsArray);
    } else {
      this.authenticatedParams = argsArray;
    }
  }

  return Me;
}]);
<commit_msg>rootScoped<commit_after>angular.module('Directory.user', ['Directory.loader', 'Directory.users.models'])
.factory('Me', ['$q', '$timeout', 'Loader', 'User', '$rootScope', function ($q, $timeout, Loader, User, $rootScope) {
  var currentUser;

  var Me = Loader(User.get('me')).then(function(user) {
    currentUser = user;
    $rootScope.currentUser = user;
    Me.authenticated.apply(Me, Me.authenticatedParams);
    return currentUser;
  });

  Me.authenticated = function () {
    var argsArray = Array.prototype.slice.call(arguments);
    if (currentUser) {
      currentUser.authenticated.apply(currentUser, argsArray);
    } else {
      this.authenticatedParams = argsArray;
    }
  }

  return Me;
}]);
<|endoftext|>


<commit_before>import {SaveRevision, SaveCopy} from "../../exporter/native"
import {ExportFidusFile} from "../../exporter/native/file"
import {LatexExporter} from "../../exporter/latex"
import {HTMLExporter} from "../../exporter/html"
import {EpubExporter} from "../../exporter/epub"
import {DocxExporter} from "../../exporter/docx"
import {OdtExporter} from "../../exporter/odt"
import {reviewSubmit} from "../../ojs"
import {RevisionDialog} from "./dialogs"
import {BibliographyDB} from "../../bibliography/database"
import {ImageDB} from "../../images/database"

export class ModMenusActions {
    constructor(mod) {
        mod.actions = this
        this.mod = mod
    }

    saveRevision() {
        this.mod.editor.save().then(
            () => {
                let dialog = new RevisionDialog()
                return dialog.init()
            }
        ).then(
            note => {
                let saver = new SaveRevision(
                    this.mod.editor.doc,
                    this.mod.editor.imageDB,
                    this.mod.editor.bibDB,
                    note
                )
                return saver.init()
            }
        )
    }

    saveCopy() {
        this.mod.editor.save().then(
            () => {
                let newBibDB, newImageDB
                if (this.mod.editor.doc.owner.id === this.mod.editor.user.id) {
                    // We are copying from and to the same user.
                    // We don't need different databases for this.
                    newBibDB = this.mod.editor.bibDB
                    newImageDB = this.mod.editor.imageDB
                    return Promise.resolve({newBibDB, newImageDB})
                } else {
                    newBibDB = new BibliographyDB(this.mod.editor.user.id)
                    newImageDB = new ImageDB(this.mod.editor.user.id)
                    return newBibDB.getDB().then(
                        () => newImageDB.getDB()
                    ).then(
                        () => Promise.resolve({newBibDB, newImageDB})
                    )
                }
            }
        ).then(({newBibDB, newImageDB}) => {
            let copier = new SaveCopy(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB,
                newBibDB,
                newImageDB,
                this.mod.editor.user
            )
            return copier.init()
        }).then(({doc, docInfo}) => {
                window.location.href = `/document/${doc.id}/`
            }
        )
    }

    download() {
        this.mod.editor.save().then(() => {
            new ExportFidusFile(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB
            )
        })
    }

    downloadTemplateExport(templateUrl, templateType) {
        this.mod.editor.save().then(() => {
            if (templateType === 'docx') {
                new DocxExporter(
                    this.mod.editor.doc,
                    templateUrl,
                    this.mod.editor.bibDB,
                    this.mod.editor.imageDB
                )
            } else {
                new OdtExporter(
                    this.mod.editor.doc,
                    templateUrl,
                    this.mod.editor.bibDB,
                    this.mod.editor.imageDB
                )
            }

        })
    }

    downloadLatex() {
        this.mod.editor.save().then(() => {
            new LatexExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB
            )
        })
    }

    downloadEpub() {
        this.mod.editor.save().then(() => {
            new EpubExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB
            )
        })
    }

    downloadHtml() {
        this.mod.editor.save().then(() => {
            new HTMLExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB
            )
        })
    }

    close() {
        this.mod.editor.save().then(() => {
            window.location.href = '/'
        })
    }

    submitReview() {
        this.mod.editor.save().then(() => reviewSubmit(this.mod.editor))
    }

    returnToOJS() {
        this.mod.editor.save().then(() => {
            window.location.href = window.ojsUrl
        })
    }

    showKeyBindings() {
        this.mod.editor.mod.tools.showKeyBindings.show()
    }

    print() {
        this.mod.editor.mod.tools.print.print()
    }

    wordCounter() {
        this.mod.editor.mod.tools.wordCount.wordCountDialog()
    }
}
<commit_msg>remove last OJS calls<commit_after>import {SaveRevision, SaveCopy} from "../../exporter/native"
import {ExportFidusFile} from "../../exporter/native/file"
import {LatexExporter} from "../../exporter/latex"
import {HTMLExporter} from "../../exporter/html"
import {EpubExporter} from "../../exporter/epub"
import {DocxExporter} from "../../exporter/docx"
import {OdtExporter} from "../../exporter/odt"
import {RevisionDialog} from "./dialogs"
import {BibliographyDB} from "../../bibliography/database"
import {ImageDB} from "../../images/database"

export class ModMenusActions {
    constructor(mod) {
        mod.actions = this
        this.mod = mod
    }

    saveRevision() {
        this.mod.editor.save().then(
            () => {
                let dialog = new RevisionDialog()
                return dialog.init()
            }
        ).then(
            note => {
                let saver = new SaveRevision(
                    this.mod.editor.doc,
                    this.mod.editor.imageDB,
                    this.mod.editor.bibDB,
                    note
                )
                return saver.init()
            }
        )
    }

    saveCopy() {
        this.mod.editor.save().then(
            () => {
                let newBibDB, newImageDB
                if (this.mod.editor.doc.owner.id === this.mod.editor.user.id) {
                    // We are copying from and to the same user.
                    // We don't need different databases for this.
                    newBibDB = this.mod.editor.bibDB
                    newImageDB = this.mod.editor.imageDB
                    return Promise.resolve({newBibDB, newImageDB})
                } else {
                    newBibDB = new BibliographyDB(this.mod.editor.user.id)
                    newImageDB = new ImageDB(this.mod.editor.user.id)
                    return newBibDB.getDB().then(
                        () => newImageDB.getDB()
                    ).then(
                        () => Promise.resolve({newBibDB, newImageDB})
                    )
                }
            }
        ).then(({newBibDB, newImageDB}) => {
            let copier = new SaveCopy(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB,
                newBibDB,
                newImageDB,
                this.mod.editor.user
            )
            return copier.init()
        }).then(({doc, docInfo}) => {
                window.location.href = `/document/${doc.id}/`
            }
        )
    }

    download() {
        this.mod.editor.save().then(() => {
            new ExportFidusFile(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB
            )
        })
    }

    downloadTemplateExport(templateUrl, templateType) {
        this.mod.editor.save().then(() => {
            if (templateType === 'docx') {
                new DocxExporter(
                    this.mod.editor.doc,
                    templateUrl,
                    this.mod.editor.bibDB,
                    this.mod.editor.imageDB
                )
            } else {
                new OdtExporter(
                    this.mod.editor.doc,
                    templateUrl,
                    this.mod.editor.bibDB,
                    this.mod.editor.imageDB
                )
            }

        })
    }

    downloadLatex() {
        this.mod.editor.save().then(() => {
            new LatexExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB,
                this.mod.editor.imageDB
            )
        })
    }

    downloadEpub() {
        this.mod.editor.save().then(() => {
            new EpubExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB
            )
        })
    }

    downloadHtml() {
        this.mod.editor.save().then(() => {
            new HTMLExporter(
                this.mod.editor.doc,
                this.mod.editor.bibDB
            )
        })
    }

    close() {
        this.mod.editor.save().then(() => {
            window.location.href = '/'
        })
    }

    showKeyBindings() {
        this.mod.editor.mod.tools.showKeyBindings.show()
    }

    print() {
        this.mod.editor.mod.tools.print.print()
    }

    wordCounter() {
        this.mod.editor.mod.tools.wordCount.wordCountDialog()
    }
}
<|endoftext|>


<commit_before>
$(document).ready(function() {

  // Make the main nav open the subnav
  $('#station > ul > li > a').each(function(i, a) {
    var href = $(a).attr('href');
    $(a).click(function(event) {
      event.preventDefault();
      id = $(this).parent().attr('id').replace('nav_item_', '');
      caboose_subnav(id, href);
    })
  });

  // Make the subnav links take over the entire page instead of just the iframe
  //$('#station ul li ul li a').each(function(i, a) {
  //  var href = $(a).attr('href');
  //  $(a).click(function(event) {
  //    event.preventDefault();
  //    parent.window.location = href;
  //  })
  //});

});

function caboose_subnav(id, href)
{
  parent.$.fn.colorbox.resize({ innerHeight: plugin_count * 50, innerWidth: '400px' });

  $('#station > ul > li').each(function(i, li) {
    id2 = $(li).attr('id').replace('nav_item_', '');
    if (id == id2)
      $(li).addClass('selected');
    else
      $(li).removeClass('selected');
  });

  $('#station ul li ul').hide();
  $('#station ul li#nav_item_' + id + ' ul').show();

  var height = $('#station > ul').height();
  $('#station ul li#nav_item_' + id + ' ul').height(height);
}
<commit_msg>More changes<commit_after>
$(document).ready(function() {

  // Make the main nav open the subnav
  $('#station > ul > li > a').each(function(i, a) {
    var href = $(a).attr('href');
    $(a).click(function(event) {
      event.preventDefault();
      id = $(this).parent().attr('id').replace('nav_item_', '');
      caboose_subnav(id, href);
    })
  });

  // Make the subnav links take over the entire page instead of just the iframe
  $('#station ul li ul li a').each(function(i, a) {
    var href = $(a).attr('href');
    $(a).click(function(event) {
      event.preventDefault();
      parent.window.location = href;
    })
  });

});

function caboose_subnav(id, href)
{
  parent.$.fn.colorbox.resize({ innerHeight: plugin_count * 50, innerWidth: '400px' });

  $('#station > ul > li').each(function(i, li) {
    id2 = $(li).attr('id').replace('nav_item_', '');
    if (id == id2)
      $(li).addClass('selected');
    else
      $(li).removeClass('selected');
  });

  $('#station ul li ul').hide();
  $('#station ul li#nav_item_' + id + ' ul').show();

  var height = $('#station > ul').height();
  $('#station ul li#nav_item_' + id + ' ul').height(height);
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var bufrw = require('bufrw');
var Checksum = require('./checksum');
var ArgsRW = require('./args');
var argsrw = ArgsRW(bufrw.buf2);

// flags:1 csumtype:1 (csum:4){0,1} (arg~2)+
function CallRequestCont(flags, csum, args) {
    var self = this;
    self.type = CallRequestCont.TypeCode;
    self.flags = flags || 0;
    self.csum = Checksum.objOrType(csum);
    self.args = args || [];
    self.cont = null;
    self._flagsOffset = 0;
}

var flagsReadLen = {
    byteLength: flagsLength,
    writeInto: saveFlagsOffset,
    readFrom: readFlagsFrom
};

var flagsRetWrite = {
    writeInto: writeFlagsInto,
};

function saveFlagsOffset(body, buffer, offset) {
    body._flagsOffset = offset;
    return bufrw.WriteResult.just(offset + bufrw.UInt8.width);
}

function flagsLength() {
    return bufrw.LengthResult.just(bufrw.UInt8.width);
}

function writeFlagsInto(body, buffer, offset) {
    var res = bufrw.UInt8.writeInto(body.flags, buffer, body._flagsOffset);
    if (!res.err) res.offset = offset;
    return res;
}

function readFlagsFrom(body, buffer, offset) {
    return bufrw.UInt8.readFrom(buffer, offset);
}

CallRequestCont.TypeCode = 0x13;
CallRequestCont.Cont = CallRequestCont;
CallRequestCont.RW = bufrw.Struct(CallRequestCont, [
    {name: 'flags', call: flagsReadLen}, // flags:1 -- skipped at first
    {call: argsrw},                      // (arg~2)+
    {call: flagsRetWrite}                // -- rw flags last
]);

CallRequestCont.prototype.verifyChecksum = function verifyChecksum(prior) {
    var self = this;
    return self.csum.verify(self.args, prior);
};

// flags:1 csumtype:1 (csum:4){0,1} (arg~2)+
function CallResponseCont(flags, csum, args) {
    var self = this;
    self.type = CallResponseCont.TypeCode;
    self.flags = flags || 0;
    self.csum = Checksum.objOrType(csum);
    self.args = args || [];
    self.cont = null;
    self._flagsOffset = 0;
}

CallResponseCont.TypeCode = 0x14;
CallResponseCont.Cont = CallResponseCont;
CallResponseCont.RW = bufrw.Struct(CallResponseCont, [
    {name: 'flags', call: flagsReadLen}, // flags:1 -- skipped at first
    {call: argsrw},                      // (arg~2)+
    {call: flagsRetWrite}                // -- rw flags last
]);

CallResponseCont.prototype.verifyChecksum = function verifyChecksum(prior) {
    var self = this;
    return self.csum.verify(self.args, prior);
};

module.exports.RequestCont = CallRequestCont;
module.exports.ResponseCont = CallResponseCont;
<commit_msg>v2/cont: switch to a custom RW<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var bufrw = require('bufrw');
var Checksum = require('./checksum');
var ArgsRW = require('./args');
var argsrw = ArgsRW(bufrw.buf2);

// flags:1 csumtype:1 (csum:4){0,1} (arg~2)+
function CallRequestCont(flags, csum, args) {
    var self = this;
    self.type = CallRequestCont.TypeCode;
    self.flags = flags || 0;
    self.csum = Checksum.objOrType(csum);
    self.args = args || [];
    self.cont = null;
    self._flagsOffset = 0;
}

CallRequestCont.TypeCode = 0x13;
CallRequestCont.Cont = CallRequestCont;
CallRequestCont.RW = bufrw.Base(callReqContLength, readCallReqContFrom, writeCallReqContInto);

function callReqContLength(body) {
    var res;
    var length = 0;

    // flags:1
    length += bufrw.UInt8.width;

    // csumtype:1 (csum:4){0,1} (arg~2)*
    res = argsrw.byteLength(body);
    if (!res.err) res.length += length;

    return res;
}

function readCallReqContFrom(buffer, offset) {
    var res;
    var body = new CallRequestCont();

    // flags:1
    res = bufrw.UInt8.readFrom(buffer, offset);
    if (res.err) return res;
    offset = res.offset;
    body.flags = res.value;

    // csumtype:1 (csum:4){0,1} (arg~2)*
    res = argsrw.readFrom(body, buffer, offset);
    if (!res.err) res.value = body;

    return res;
}

function writeCallReqContInto(body, buffer, offset) {
    var start = offset;
    var res;

    // flags:1 -- skip for now, write args frist
    offset += bufrw.UInt8.width;

    // csumtype:1 (csum:4){0,1} (arg~2)* -- (may mutate body.flags)
    res = argsrw.writeInto(body, buffer, offset);
    if (res.err) return res;
    offset = res.offset;

    // now we know the final flags, write them
    res = bufrw.UInt8.writeInto(body.flags, buffer, start);
    if (!res.err) res.offset = offset;

    return res;
}

CallRequestCont.prototype.verifyChecksum = function verifyChecksum(prior) {
    var self = this;
    return self.csum.verify(self.args, prior);
};

// flags:1 csumtype:1 (csum:4){0,1} (arg~2)+
function CallResponseCont(flags, csum, args) {
    var self = this;
    self.type = CallResponseCont.TypeCode;
    self.flags = flags || 0;
    self.csum = Checksum.objOrType(csum);
    self.args = args || [];
    self.cont = null;
    self._flagsOffset = 0;
}

CallResponseCont.TypeCode = 0x14;
CallResponseCont.Cont = CallResponseCont;
CallResponseCont.RW = bufrw.Base(callResContLength, readCallResContFrom, writeCallResContInto);

function callResContLength(body) {
    var res;
    var length = 0;

    // flags:1
    length += bufrw.UInt8.width;

    // csumtype:1 (csum:4){0,1} (arg~2)*
    res = argsrw.byteLength(body);
    if (!res.err) res.length += length;

    return res;
}

function readCallResContFrom(buffer, offset) {
    var res;
    var body = new CallResponseCont();

    // flags:1
    res = bufrw.UInt8.readFrom(buffer, offset);
    if (res.err) return res;
    offset = res.offset;
    body.flags = res.value;

    // csumtype:1 (csum:4){0,1} (arg~2)*
    res = argsrw.readFrom(body, buffer, offset);
    if (!res.err) res.value = body;

    return res;
}

function writeCallResContInto(body, buffer, offset) {
    var start = offset;
    var res;

    // flags:1 -- skip for now, write args frist
    offset += bufrw.UInt8.width;

    // csumtype:1 (csum:4){0,1} (arg~2)* -- (may mutate body.flags)
    res = argsrw.writeInto(body, buffer, offset);
    if (res.err) return res;
    offset = res.offset;

    // now we know the final flags, write them
    res = bufrw.UInt8.writeInto(body.flags, buffer, start);
    if (!res.err) res.offset = offset;

    return res;
}

CallResponseCont.prototype.verifyChecksum = function verifyChecksum(prior) {
    var self = this;
    return self.csum.verify(self.args, prior);
};

module.exports.RequestCont = CallRequestCont;
module.exports.ResponseCont = CallResponseCont;
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('../common/errors');
const logger = require('../common/logger');
const utils = require('../common/utils');
const catalog = require('../common/models/catalog');
const FabrikBaseController = require('./FabrikBaseController');
const lockManager = require('../data-access-layer/eventmesh').lockManager;
const AssertionError = assert.AssertionError;
const BadRequest = errors.BadRequest;
const PreconditionFailed = errors.PreconditionFailed;
const NotFound = errors.NotFound;
const ServiceInstanceNotFound = errors.ServiceInstanceNotFound;
const ServiceBindingAlreadyExists = errors.ServiceBindingAlreadyExists;
const ContinueWithNext = errors.ContinueWithNext;
const CONST = require('../common/constants');
const eventmesh = require('../data-access-layer/eventmesh');
const config = require('../common/config');
const formatUrl = require('url').format;

class ServiceBrokerApiController extends FabrikBaseController {
  constructor() {
    super();
  }

  apiVersion(req, res) {
    /* jshint unused:false */
    const minVersion = CONST.SF_BROKER_API_VERSION_MIN;
    const version = _.get(req.headers, 'x-broker-api-version', '1.0');
    return Promise
      .try(() => {
        if (utils.compareVersions(version, minVersion) >= 0) {
          return;
        } else {
          throw new PreconditionFailed(`At least Broker API version ${minVersion} is required.`);
        }
      })
      .throw(new ContinueWithNext());
  }

  getCatalog(req, res) {
    /* jshint unused:false */
    res.status(CONST.HTTP_STATUS_CODE.OK).json(this.fabrik.getPlatformManager(req.params.platform).getCatalog(catalog));
  }

  putInstance(req, res) {
    const params = req.body;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function getDashboardUrl(serviceId, planId, instanceGuid) {
      return formatUrl(_
        .chain(config.external)
        .pick('protocol', 'host')
        .set('slashes', true)
        .set('pathname', `/manage/instances/${serviceId}/${planId}/${instanceGuid}`)
        .value()
      );
    }

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.CREATED;
      const body = {
        dashboard_url: getDashboardUrl(params.service_id, params.plan_id, req.params.instance_id)
      };
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    req.operation_type = CONST.OPERATION_TYPE.CREATE;
    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            started_at: new Date()
          });
        }
      })
      .then(done);
  }

  patchInstance(req, res) {
    const params = _
      .chain(req.body)
      // .omit('plan_id', 'service_id') //Not omiting even for restore. will that be a problem?
      .cloneDeep()
      .value();
    //cloning here so that the DirectorInstance.update does not unset the 'service-fabrik-operation' from original req.body object
    const isRestoreOperation = _.get(params.parameters, 'service-fabrik-operation', null) ? true : false;
    req.operation_type = CONST.OPERATION_TYPE.UPDATE;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done(result) {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
        if (isRestoreOperation) {
          body.operation = utils.encodeBase64(result);
        }
      }
      res.status(statusCode).send(body);
    }

    function isUpdatePossible(previousPlanId) {
      const planId = params.plan_id;
      const plan = catalog.getPlan(planId);
      const previousPlan = _.find(plan.service.plans, ['id', previousPlanId]);
      return plan === previousPlan || _.includes(plan.manager.settings.update_predecessors, previousPlan.id);
    }

    if (isRestoreOperation) {
      return Promise
        .try(() => {
          if (!req.manager.isUpdatePossible(params.previous_values.plan_id)) { //ideally this can also use the local function but not changing as this piece of code anyways go away once restore manager in place.
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
          return req.instance.update(params);
        })
        .then(done);
    } else {
      return Promise
        .try(() => {
          if (!isUpdatePossible(params.previous_values.plan_id)) {
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
        })
        //TODO : handle existing cases
        .then(() => {
          return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .catch(NotFound, () => {
          logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
            `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
          return eventmesh.apiServerClient.createResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .then(done);
    }
  }

  deleteInstance(req, res) {
    const params = req.query;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    req.operation_type = CONST.OPERATION_TYPE.DELETE;

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .catch(NotFound, () => {
        logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
          `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(done)
      .catch(ServiceInstanceNotFound, gone);
  }
  getLastInstanceOperation(req, res) {
    const encodedOp = _.get(req, 'query.operation', undefined);
    const operation = encodedOp === undefined ? null : utils.decodeBase64(encodedOp);
    const guid = req.params.instance_id;
    let action, instanceType;
    if (operation) {
      action = _.capitalize(operation.type);
      instanceType = req.instance.constructor.typeDescription;
    }

    function done(result) {
      const body = _.pick(result, 'state', 'description');
      // Unlock resource if state is succeeded or failed
      if (result.state === CONST.OPERATION.SUCCEEDED || result.state === CONST.OPERATION.FAILED) {
        return lockManager.unlock(req.params.instance_id)
          .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send(body));
      }
      res.status(CONST.HTTP_STATUS_CODE.OK).send(body);
    }

    function failed(err) {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send({
          state: CONST.OPERATION.FAILED,
          description: `${action} ${instanceType} '${guid}' failed because "${err.message}"`
        }));
    }

    function gone() {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.GONE).send({}));
    }

    function notFound(err) {
      if (operation && operation.type === 'delete') {
        return gone();
      } else if (!operation) { //TODO : for non delete case, check when notfound is thrown and handle. similarly for AssertionError
        //      failed(err);
        return gone();
      }
      failed(err);
    }

    if (operation) { // keeping it to support last operation for the restore and for any ongoing update, delete?
      return req.instance.lastOperation(operation)
        .then(done)
        .catch(AssertionError, failed)
        .catch(ServiceInstanceNotFound, notFound);
    } else {
      const planId = req.query.plan_id;
      const plan = catalog.getPlan(planId);
      return eventmesh.apiServerClient.getLastOperation({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id
        })
        .then(done)
        .catch(AssertionError, failed)
        .catch(NotFound, notFound);
    }
  }

  putBinding(req, res) {
    const params = _(req.body)
      .set('binding_id', req.params.binding_id)
      .value();

    function done(credentials) {
      // omit credentials from resource response

      res.status(CONST.HTTP_STATUS_CODE.CREATED).send({
        credentials: credentials
      });
    }

    function conflict(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.CONFLICT).send({});
    }

    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          parentResourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
        started_at: new Date()
      }))
      .then(operationStatus => done(operationStatus.response))
      .catch(ServiceBindingAlreadyExists, conflict);
  }

  deleteBinding(req, res) {
    const params = _(req.query)
      .set('binding_id', req.params.binding_id)
      .value();

    function done() {
      res.status(CONST.HTTP_STATUS_CODE.OK).send({});
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
        started_at: new Date()
      }))
      .then(() => eventmesh.apiServerClient.deleteResource({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id
      }))
      .then(done)
      .catch(NotFound, gone);
  }

}

module.exports = ServiceBrokerApiController;<commit_msg>Omit credentials from bind resource<commit_after>'use strict';

const assert = require('assert');
const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('../common/errors');
const logger = require('../common/logger');
const utils = require('../common/utils');
const catalog = require('../common/models/catalog');
const FabrikBaseController = require('./FabrikBaseController');
const lockManager = require('../data-access-layer/eventmesh').lockManager;
const AssertionError = assert.AssertionError;
const BadRequest = errors.BadRequest;
const PreconditionFailed = errors.PreconditionFailed;
const NotFound = errors.NotFound;
const ServiceInstanceNotFound = errors.ServiceInstanceNotFound;
const ServiceBindingAlreadyExists = errors.ServiceBindingAlreadyExists;
const ContinueWithNext = errors.ContinueWithNext;
const CONST = require('../common/constants');
const eventmesh = require('../data-access-layer/eventmesh');
const config = require('../common/config');
const formatUrl = require('url').format;

class ServiceBrokerApiController extends FabrikBaseController {
  constructor() {
    super();
  }

  apiVersion(req, res) {
    /* jshint unused:false */
    const minVersion = CONST.SF_BROKER_API_VERSION_MIN;
    const version = _.get(req.headers, 'x-broker-api-version', '1.0');
    return Promise
      .try(() => {
        if (utils.compareVersions(version, minVersion) >= 0) {
          return;
        } else {
          throw new PreconditionFailed(`At least Broker API version ${minVersion} is required.`);
        }
      })
      .throw(new ContinueWithNext());
  }

  getCatalog(req, res) {
    /* jshint unused:false */
    res.status(CONST.HTTP_STATUS_CODE.OK).json(this.fabrik.getPlatformManager(req.params.platform).getCatalog(catalog));
  }

  putInstance(req, res) {
    const params = req.body;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function getDashboardUrl(serviceId, planId, instanceGuid) {
      return formatUrl(_
        .chain(config.external)
        .pick('protocol', 'host')
        .set('slashes', true)
        .set('pathname', `/manage/instances/${serviceId}/${planId}/${instanceGuid}`)
        .value()
      );
    }

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.CREATED;
      const body = {
        dashboard_url: getDashboardUrl(params.service_id, params.plan_id, req.params.instance_id)
      };
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    req.operation_type = CONST.OPERATION_TYPE.CREATE;
    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(() => {
        if (!plan.manager.async) {
          return eventmesh.apiServerClient.getResourceOperationStatus({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
            started_at: new Date()
          });
        }
      })
      .then(done);
  }

  patchInstance(req, res) {
    const params = _
      .chain(req.body)
      // .omit('plan_id', 'service_id') //Not omiting even for restore. will that be a problem?
      .cloneDeep()
      .value();
    //cloning here so that the DirectorInstance.update does not unset the 'service-fabrik-operation' from original req.body object
    const isRestoreOperation = _.get(params.parameters, 'service-fabrik-operation', null) ? true : false;
    req.operation_type = CONST.OPERATION_TYPE.UPDATE;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done(result) {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
        if (isRestoreOperation) {
          body.operation = utils.encodeBase64(result);
        }
      }
      res.status(statusCode).send(body);
    }

    function isUpdatePossible(previousPlanId) {
      const planId = params.plan_id;
      const plan = catalog.getPlan(planId);
      const previousPlan = _.find(plan.service.plans, ['id', previousPlanId]);
      return plan === previousPlan || _.includes(plan.manager.settings.update_predecessors, previousPlan.id);
    }

    if (isRestoreOperation) {
      return Promise
        .try(() => {
          if (!req.manager.isUpdatePossible(params.previous_values.plan_id)) { //ideally this can also use the local function but not changing as this piece of code anyways go away once restore manager in place.
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
          return req.instance.update(params);
        })
        .then(done);
    } else {
      return Promise
        .try(() => {
          if (!isUpdatePossible(params.previous_values.plan_id)) {
            throw new BadRequest(`Update to plan '${req.manager.plan.name}' is not possible`);
          }
        })
        //TODO : handle existing cases
        .then(() => {
          return eventmesh.apiServerClient.updateResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .catch(NotFound, () => {
          logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
            `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
          return eventmesh.apiServerClient.createResource({
            resourceGroup: plan.manager.resource_mappings.resource_group,
            resourceType: plan.manager.resource_mappings.resource_type,
            resourceId: req.params.instance_id,
            options: params,
            status: {
              state: CONST.APISERVER.RESOURCE_STATE.UPDATE,
              lastOperation: {},
              response: {}
            }
          });
        })
        .then(done);
    }
  }

  deleteInstance(req, res) {
    const params = req.query;
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    function done() {
      let statusCode = CONST.HTTP_STATUS_CODE.OK;
      const body = {};
      if (plan.manager.async) {
        statusCode = CONST.HTTP_STATUS_CODE.ACCEPTED;
      }
      res.status(statusCode).send(body);
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    req.operation_type = CONST.OPERATION_TYPE.DELETE;

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .catch(NotFound, () => {
        logger.info(`Resource resourceGroup: ${plan.manager.resource_mappings.resource_group},` +
          `resourceType: ${plan.manager.resource_mappings.resource_type}, resourceId: ${req.params.instance_id} not found, Creating now...`);
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE,
            lastOperation: {},
            response: {}
          }
        });
      })
      .then(done)
      .catch(ServiceInstanceNotFound, gone);
  }
  getLastInstanceOperation(req, res) {
    const encodedOp = _.get(req, 'query.operation', undefined);
    const operation = encodedOp === undefined ? null : utils.decodeBase64(encodedOp);
    const guid = req.params.instance_id;
    let action, instanceType;
    if (operation) {
      action = _.capitalize(operation.type);
      instanceType = req.instance.constructor.typeDescription;
    }

    function done(result) {
      const body = _.pick(result, 'state', 'description');
      // Unlock resource if state is succeeded or failed
      if (result.state === CONST.OPERATION.SUCCEEDED || result.state === CONST.OPERATION.FAILED) {
        return lockManager.unlock(req.params.instance_id)
          .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send(body));
      }
      res.status(CONST.HTTP_STATUS_CODE.OK).send(body);
    }

    function failed(err) {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.OK).send({
          state: CONST.OPERATION.FAILED,
          description: `${action} ${instanceType} '${guid}' failed because "${err.message}"`
        }));
    }

    function gone() {
      return lockManager.unlock(req.params.instance_id)
        .then(() => res.status(CONST.HTTP_STATUS_CODE.GONE).send({}));
    }

    function notFound(err) {
      if (operation && operation.type === 'delete') {
        return gone();
      } else if (!operation) { //TODO : for non delete case, check when notfound is thrown and handle. similarly for AssertionError
        //      failed(err);
        return gone();
      }
      failed(err);
    }

    if (operation) { // keeping it to support last operation for the restore and for any ongoing update, delete?
      return req.instance.lastOperation(operation)
        .then(done)
        .catch(AssertionError, failed)
        .catch(ServiceInstanceNotFound, notFound);
    } else {
      const planId = req.query.plan_id;
      const plan = catalog.getPlan(planId);
      return eventmesh.apiServerClient.getLastOperation({
          resourceGroup: plan.manager.resource_mappings.resource_group,
          resourceType: plan.manager.resource_mappings.resource_type,
          resourceId: req.params.instance_id
        })
        .then(done)
        .catch(AssertionError, failed)
        .catch(NotFound, notFound);
    }
  }

  putBinding(req, res) {
    const params = _(req.body)
      .set('binding_id', req.params.binding_id)
      .value();

    function done(credentials) {
      // omit credentials from resource response
      return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          status: {
            response: {}
          }
        })
        .then(() => res.status(CONST.HTTP_STATUS_CODE.CREATED).send({
          credentials: credentials
        }));
    }

    function conflict(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.CONFLICT).send({});
    }

    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.createResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          parentResourceId: req.params.instance_id,
          options: params,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.IN_QUEUE,
        started_at: new Date()
      }))
      .then(operationStatus => done(operationStatus.response))
      .catch(ServiceBindingAlreadyExists, conflict);
  }

  deleteBinding(req, res) {
    const params = _(req.query)
      .set('binding_id', req.params.binding_id)
      .value();

    function done() {
      res.status(CONST.HTTP_STATUS_CODE.OK).send({});
    }

    function gone(err) {
      /* jshint unused:false */
      res.status(CONST.HTTP_STATUS_CODE.GONE).send({});
    }
    const planId = params.plan_id;
    const plan = catalog.getPlan(planId);

    return Promise
      .try(() => {
        return eventmesh.apiServerClient.updateResource({
          resourceGroup: plan.manager.resource_mappings.bind.resource_group,
          resourceType: plan.manager.resource_mappings.bind.resource_type,
          resourceId: params.binding_id,
          status: {
            state: CONST.APISERVER.RESOURCE_STATE.DELETE
          }
        });
      })
      .then(() => eventmesh.apiServerClient.getResourceOperationStatus({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id,
        start_state: CONST.APISERVER.RESOURCE_STATE.DELETE,
        started_at: new Date()
      }))
      .then(() => eventmesh.apiServerClient.deleteResource({
        resourceGroup: plan.manager.resource_mappings.bind.resource_group,
        resourceType: plan.manager.resource_mappings.bind.resource_type,
        resourceId: params.binding_id
      }))
      .then(done)
      .catch(NotFound, gone);
  }

}

module.exports = ServiceBrokerApiController;<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var utils = require('./utils');

module.exports = function(options) {
  return function(app) {
    if (!utils.isValid(app, 'update-support-helpers')) return;
    app.helpers(utils.helpers());
    app.helper('hasValue', function(val, str) {
      return utils.hasValue(val) ? str : '';
    });

    app.helper('hasAny', function(arr, str) {
      arr = utils.arrayify(arr);
      var len = arr.length;
      var idx = -1;
      while (++idx < len) {
        var ele = arr[idx] || [];
        if (ele.length) {
          return str;
        }
      }
      return '';
    });

    app.helper('relatedLinks', function(related) {
      if (!related || typeof related !== 'object') {
        return '';
      }
      var links = app.getHelper('links').bind(this);
      return relatedLinks(related, links);
    });

    app.helper('links', function(related, prop) {
      var arr = related[prop] || (related[prop] = []);
      arr = utils.arrayify(arr);
      if (arr.length === 0) {
        return '';
      }

      var fp = this.view.stem;
      var dir = 'docs';
      var segs = fp.split('.');
      if (segs.length > 1) {
        dir = segs[0];
      }
      var links = arr.map(function(link) {
        return createLink(dir, prop, link);
      });
      return links.join('\n');
    });
  };
};

function relatedLinks(related, links) {
  var keys = Object.keys(related);
  if (keys.length === 0) {
    return '';
  }

  var hasLinks = false;
  function reduce(acc, key) {
    if (related[key].length === 0) {
      return acc;
    }

    hasLinks = true;
    acc += `**${heading(key)}**\n${links(related, key)}\n`;
    return acc;
  }

  var list = `${keys.reduce(reduce, '')}`;

  if (!hasLinks) {
    return '';
  }

  return `## Related\n${list}`;
}

function createLink(dir, prop, link) {
  var key = (prop === 'doc') ? 'docs' : prop;

  var filename = link;
  var name = link;
  var anchor = '';
  var segs = link.split('#');
  if (segs.length === 2) {
    name = segs[segs.length - 1];
    anchor = '#' + name;
    filename = segs[0];
  }

  if (!/\.md$/.test(filename) && !/#/.test(filename)) {
    filename += '.md';
  }
  if (dir !== key) {
    if (key === 'docs') {
      key = '';
    }
    filename = path.join('..', key, filename);
  } else if (key !== 'docs' && dir !== key) {
    filename = path.join(key, filename);
  }
  return `- [${name}](${filename}${anchor})`;
}

function heading(title) {
  switch (title.toLowerCase()) {
    case 'doc':
      title = 'docs';
      break;
    case 'url':
      title = 'links';
      break;
    default:
      if (/(i|s)$/.test(title.toLowerCase()) === false) {
        title += 's';
      }
      break;
  }

  if (/s$/.test(title)) {
    return utils.pascalcase(title);
  }
  return title.toUpperCase();
}
<commit_msg>normalize related links into objects for customizing related links<commit_after>'use strict';

var path = require('path');
var utils = require('./utils');

module.exports = function(options) {
  return function(app) {
    if (!utils.isValid(app, 'update-support-helpers')) return;
    app.helpers(utils.helpers());
    app.helper('hasValue', function(val, str) {
      return utils.hasValue(val) ? str : '';
    });

    app.helper('hasAny', function(arr, str) {
      arr = utils.arrayify(arr);
      var len = arr.length;
      var idx = -1;
      while (++idx < len) {
        var ele = arr[idx] || [];
        if (ele.length) {
          return str;
        }
      }
      return '';
    });

    app.helper('relatedLinks', function(related) {
      if (!related || typeof related !== 'object') {
        return '';
      }
      var links = app.getHelper('links').bind(this);
      return relatedLinks(related, links);
    });

    app.helper('links', function(related, prop) {
      var arr = related[prop] || (related[prop] = []);
      arr = utils.arrayify(arr);
      if (arr.length === 0) {
        return '';
      }

      var fp = this.view.stem;
      var dir = 'docs';
      var segs = fp.split('.');
      if (segs.length > 1) {
        dir = segs[0];
      }
      var links = arr.map(function(link) {
        return createLink(dir, prop, link);
      });
      return links.join('\n');
    });
  };
};

function relatedLinks(related, links) {
  var keys = Object.keys(related);
  if (keys.length === 0) {
    return '';
  }

  var hasLinks = false;
  function reduce(acc, key) {
    if (related[key].length === 0) {
      return acc;
    }

    hasLinks = true;
    acc += `**${heading(key)}**\n${links(related, key)}\n`;
    return acc;
  }

  var list = `${keys.reduce(reduce, '')}`;

  if (!hasLinks) {
    return '';
  }

  return `## Related\n${list}`;
}

function createLink(dir, prop, link) {
  var key = (prop === 'doc') ? 'docs' : prop;
  link = normalizeLink(link);

  if (dir !== key) {
    if (key === 'docs') {
      key = '';
    }
    link.filename = path.join('..', key, link.filename);
  } else if (key !== 'docs' && dir !== key) {
    link.filename = path.join(key, link.filename);
  }
  return `- [${link.title}](${link.filename}${link.anchor})`;
}

function heading(title) {
  switch (title.toLowerCase()) {
    case 'doc':
      title = 'docs';
      break;
    case 'url':
      title = 'links';
      break;
    default:
      if (/(i|s)$/.test(title.toLowerCase()) === false) {
        title += 's';
      }
      break;
  }

  if (/s$/.test(title)) {
    return utils.pascalcase(title);
  }
  return title.toUpperCase();
}

function normalizeLink(obj) {
  if (typeof obj === 'string') {
    obj = {link: obj};
  }
  var link = obj.link;
  var filename = link;
  var name = link;
  var anchor = '';
  var segs = link.split('#');
  if (segs.length === 2) {
    name = segs[segs.length - 1];
    anchor = '#' + name;
    filename = segs[0];
  }

  if (!/\.md$/.test(filename) && !/#/.test(filename)) {
    filename += '.md';
  }

  obj.title = obj.title || name;
  obj.filename = obj.filename || filename;
  obj.anchor = obj.anchor || anchor;
  return obj;
}
<|endoftext|>


<commit_before>// Copyright 2017 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Service to operate the playback of autogenerated audio
 * using the SpeechSynthesis API.
 */

oppia.factory('AutogeneratedAudioPlayerService', [
  'SpeechSynthesisChunkerService',
  function(SpeechSynthesisChunkerService) {
    var DEFAULT_PLAYBACK_RATE = 0.92;

    var _speechSynthesis = window.speechSynthesis;
    var utterance = new SpeechSynthesisUtterance();
    // The paused property of speech synthesis seems to return false
    // no matter what, so we manually define our own property to track.
    var _isPlaying = false;

    var _play = function(html, language, audioFinishedCallback) {
      message = SpeechSynthesisChunkerService.convertToSpeakableText(html);
      utterance.text = message;
      utterance.lang = language;
      utterance.rate = DEFAULT_PLAYBACK_RATE;
      _isPlaying = true;
      SpeechSynthesisChunkerService.speak(
        utterance,
        function() {
          _isPlaying = false;
          audioFinishedCallback();
        }
      );
    };

    return {
      play: function(html, language, audioFinishedCallback) {
        return _play(html, language, audioFinishedCallback);
      },
      pause: function() {
        // Pause and resume don't seem to work well. When an utterance is
        // paused and an attempt to resume is made more than approximately 15
        // seconds later, nothing happens. Avoid using for now.
        _speechSynthesis.pause();
        _isPlaying = false;
      },
      resume: function() {
        _speechSynthesis.resume();
        _isPlaying = true;
      },
      cancel: function() {
        SpeechSynthesisChunkerService.cancel();
        _isPlaying = false;
      },
      isPlaying: function() {
        return _isPlaying;
      }
    }
  }
]);
<commit_msg>Add fallback for browsers which do not support speech synthesis. (#4028)<commit_after>// Copyright 2017 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Service to operate the playback of autogenerated audio
 * using the SpeechSynthesis API.
 */

oppia.factory('AutogeneratedAudioPlayerService', [
  'SpeechSynthesisChunkerService',
  function(SpeechSynthesisChunkerService) {
    var DEFAULT_PLAYBACK_RATE = 0.92;

    var _speechSynthesis = window.speechSynthesis;
    // Not all browsers support SpeechSynthesisUtterance, so we need the
    // fallback to prevent a "SpeechSynthesisUtterance is not defined" error.
    var utterance = (
      SpeechSynthesisUtterance ? new SpeechSynthesisUtterance() : null);
    // The paused property of speech synthesis seems to return false
    // no matter what, so we manually define our own property to track.
    var _isPlaying = false;

    var _play = function(html, language, audioFinishedCallback) {
      message = SpeechSynthesisChunkerService.convertToSpeakableText(html);
      utterance.text = message;
      utterance.lang = language;
      utterance.rate = DEFAULT_PLAYBACK_RATE;
      _isPlaying = true;
      SpeechSynthesisChunkerService.speak(
        utterance,
        function() {
          _isPlaying = false;
          audioFinishedCallback();
        }
      );
    };

    return {
      play: function(html, language, audioFinishedCallback) {
        return _play(html, language, audioFinishedCallback);
      },
      pause: function() {
        // Pause and resume don't seem to work well. When an utterance is
        // paused and an attempt to resume is made more than approximately 15
        // seconds later, nothing happens. Avoid using for now.
        _speechSynthesis.pause();
        _isPlaying = false;
      },
      resume: function() {
        _speechSynthesis.resume();
        _isPlaying = true;
      },
      cancel: function() {
        SpeechSynthesisChunkerService.cancel();
        _isPlaying = false;
      },
      isPlaying: function() {
        return _isPlaying;
      }
    }
  }
]);
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent( 'sl-modal-footer', 'Unit | Component | sl modal footer', {
    unit: true
});

test( 'Default property values', function( assert ) {
    const component = this.subject();

    assert.strictEqual(
        component.get( 'buttonText' ),
        'Close',
        'Default buttonText is "Close"'
    );
});
<commit_msg>Added sl-modal-footer dual instance test<commit_after>import { moduleForComponent, test } from 'ember-qunit';
import globalLibraries from '../../helpers/sl/synchronous/global-libraries';

moduleForComponent( 'sl-modal-footer', 'Unit | Component | sl modal footer', {
    unit: true
});

test( 'Default property values', function( assert ) {
    const component = this.subject();

    assert.strictEqual(
        component.get( 'buttonText' ),
        'Close',
        'Default buttonText is "Close"'
    );
});

test( 'There are no references to Ember.$, $ or jQuery', function( assert ) {
    globalLibraries.setupSpies();

    const component = this.subject();

    this.render();

    globalLibraries.triggerEvents( component );

    assert.notOk(
        globalLibraries.called()
    );

    globalLibraries.restoreSpies();
});
<|endoftext|>