<commit_before>import { details, mergeInEmptyDraft } from "../detail-definitions.js";
import { findLatestIntervallEndInJsonLdOrNowAndAddMillis } from "../../app/won-utils.js";
import won from "../../app/won-es6.js";
import { getIn } from "../../app/utils.js";
import {
  filterInVicinity,
  concatenateFilters,
  sparqlQuery,
} from "../../app/sparql-builder-utils.js";

export const goodsTransportOffer = {
  identifier: "goodsTransportOffer",
  label: "Offer goods transport",
  icon: "#ico36_uc_transport_offer",
  doNotMatchAfter: findLatestIntervallEndInJsonLdOrNowAndAddMillis,
  draft: {
    ...mergeInEmptyDraft({
      content: {
        title: "Transportation offer",
        type: "http://dbpedia.org/resource/Transport",
      },
    }),
  },
  details: {
    title: { ...details.title },
    location: { ...details.location },
  },
  seeksDetails: {
    tags: { ...details.tags },
    description: { ...details.description },
  },
  generateQuery: (draft, resultName) => {
    const location = getIn(draft, ["content", "location"]);
    const filters = [
      {
        // to select seeks-branch
        prefixes: {
          won: won.defaultContext["won"],
        },
        operations: [
          `${resultName} a won:Need.`,
          `${resultName} won:seeks ?seeks.`,
          `${resultName} a <http://dbpedia.org/resource/Cargo>.`,
          location && "?seeks won:travelAction/s:fromLocation ?location.",
        ],
      },

      filterInVicinity("?location", location, /*radius=*/ 100),
    ];

    const concatenatedFilter = concatenateFilters(filters);

    return sparqlQuery({
      prefixes: concatenatedFilter.prefixes,
      distinct: true,
      variables: [resultName],
      where: concatenatedFilter.operations,
      orderBy: [
        {
          order: "ASC",
          variable: "?location_geoDistance",
        },
      ],
    });
  },
};
<commit_msg>Adapt query for uc-goods-transport-offer<commit_after>import { details, mergeInEmptyDraft } from "../detail-definitions.js";
import { findLatestIntervallEndInJsonLdOrNowAndAddMillis } from "../../app/won-utils.js";
import won from "../../app/won-es6.js";
import { getIn } from "../../app/utils.js";
import { sparqlQuery } from "../../app/sparql-builder-utils.js";

export const goodsTransportOffer = {
  identifier: "goodsTransportOffer",
  label: "Offer goods transport",
  icon: "#ico36_uc_transport_offer",
  doNotMatchAfter: findLatestIntervallEndInJsonLdOrNowAndAddMillis,
  draft: {
    ...mergeInEmptyDraft({
      content: {
        title: "Transportation offer",
        type: "http://dbpedia.org/resource/Transport",
      },
    }),
  },
  details: {
    title: { ...details.title },
    location: { ...details.location },
  },
  seeksDetails: {
    tags: { ...details.tags },
    description: { ...details.description },
  },
  generateQuery: (draft, resultName) => {
    const location = getIn(draft, ["content", "location"]);
    let filter;

    if (location && location.lat && location.lng) {
      filter = {
        // to select seeks-branch
        prefixes: {
          won: won.defaultContext["won"],
          s: won.defaultContext["s"],
          geo: "http://www.bigdata.com/rdf/geospatial#",
          xsd: "http://www.w3.org/2001/XMLSchema#",
        },
        operations: [
          `${resultName} a won:Need.`,
          `${resultName} won:seeks ?seeks.`,
          `${resultName} a <http://dbpedia.org/resource/Cargo>.`,
          "?seeks won:travelAction/s:fromLocation ?fromLocation.",
          "?seeks won:travelAction/s:toLocation ?toLocation.",
          "?fromLocation s:geo ?fromLocation_geo.",
          "?fromLocation_geo s:latitude ?fromLocation_lat;",
          "s:longitude ?fromLocation_lon;",
          `bind (abs(xsd:decimal(?fromLocation_lat) - ${
            location.lat
          }) as ?fromLatDiffRaw)`,
          `bind (abs(xsd:decimal(?fromLocation_lon) - ${
            location.lng
          }) as ?fromLonDiff)`,
          "bind (if ( ?fromLatDiffRaw > 180, 360 - ?fromLatDiffRaw, ?fromLatDiffRaw ) as ?fromLatDiff)",
          "bind ( ?fromLatDiff * ?fromLatDiff + ?fromLonDiff * ?fromLonDiff as ?fromLocation_geoDistanceScore)",
          "?toLocation s:geo ?toLocation_geo.",
          "?toLocation_geo s:latitude ?toLocation_lat;",
          "s:longitude ?toLocation_lon;",
          `bind (abs(xsd:decimal(?toLocation_lat) - ${
            location.lat
          }) as ?toLatDiffRaw)`,
          `bind (abs(xsd:decimal(?toLocation_lon) - ${
            location.lng
          }) as ?toLonDiff)`,
          "bind (if ( ?toLatDiffRaw > 180, 360 - ?toLatDiffRaw, ?toLatDiffRaw ) as ?toLatDiff)",
          "bind ( ?toLatDiff * ?toLatDiff + ?toLonDiff * ?toLonDiff as ?toLocation_geoDistanceScore)",
          "bind (?toLocation_geoDistanceScore + ?fromLocation_geoDistanceScore as ?distScore)",
        ],
      };
    } else {
      filter = {
        // to select seeks-branch
        prefixes: {
          won: won.defaultContext["won"],
        },
        operations: [
          `${resultName} a won:Need.`,
          `${resultName} won:seeks ?seeks.`,
          `${resultName} a <http://dbpedia.org/resource/Cargo>.`,
        ],
      };
    }

    const generatedQuery = sparqlQuery({
      prefixes: filter.prefixes,
      distinct: true,
      variables: [resultName],
      where: filter.operations,
      orderBy: [
        {
          order: "ASC",
          variable: "?distScore",
        },
      ],
    });

    return generatedQuery;
  },
};
<|endoftext|>


<commit_before>/**
 * @file WScript specific File System implementation
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_FS_OPENFOR*/ // File system stream opening mode
/*global _GPF_FS_TYPES*/ // File system types constants
/*global _GPF_HOST*/ // Host types
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfHost*/ // Host type
/*global _gpfFsExploreEnumerator*/ // IFileStorage.explore helper
/*global _gpfPathNormalize*/ // Normalize path
/*global _gpfSetHostFileStorage*/ // Set the result of gpf.fs.getFileStorage
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfHost*/ // Host type
/*global _gpfMsFSO:true*/ // Scripting.FileSystemObject activeX
/*global _gpfPathDecompose*/ // Normalize path and returns an array of parts
/*global _gpfPathNormalize*/ // Normalize path
/*global _GpfWscriptBaseStream*/ // gpf.wscript.BaseStream
/*global _GpfWscriptReadableStream*/ // gpf.wscript.ReadableStream
/*global _GpfWscriptWritableStream*/ // gpf.wscript.WritableStream
// /*#endif*/

/*jshint wsh:true*/
/*eslint-env wsh*/
/*eslint-disable new-cap*/ // FileSystem object APIs are uppercased
/*global Enumerator*/ // Enumerator helper

/**
 * Translate WScript file object into a {@link gpf.typedef.fileStorageInfo}
 *
 * @param {Object} obj WScript file object
 * @param {gpf.fs.types} type Object type
 * @return {gpf.typedef.fileStorageInfo} Information about the object
 */
function _gpfFsWScriptObjToFileStorageInfo (obj, type) {
    return {
        type: type,
        fileName: obj.Name.toLowerCase(),
        filePath: _gpfPathNormalize(obj.Path),
        size: obj.Size,
        createdDateTime: new Date(obj.DateCreated),
        modifiedDateTime: new Date(obj.DateLastModified)
    };
}

function _gpfFsWscriptFSOCallWithArg (name, path) {
    return new Promise(function (resolve) {
        _gpfMsFSO[name](_gpfPathDecompose(path).join("\\"));
        resolve();
    });
}

function _gpfFsWscriptFSOCallWithArgAndTrue (name, path) {
    return new Promise(function (resolve) {
        _gpfMsFSO[name](_gpfPathDecompose(path).join("\\"), true);
        resolve();
    });
}

function _gpfFsWscriptGetFileInfo (path) {
    if (_gpfMsFSO.FileExists(path)) {
        return _gpfFsWScriptObjToFileStorageInfo(_gpfMsFSO.GetFile(path), _GPF_FS_TYPES.FILE);
    }
    return {
        type: _GPF_FS_TYPES.NOT_FOUND
    };
}

function _gpfFsWscriptGetInfo (path) {
    if (_gpfMsFSO.FolderExists(path)) {
        return _gpfFsWScriptObjToFileStorageInfo(_gpfMsFSO.GetFolder(path), _GPF_FS_TYPES.DIRECTORY);
    }
    return _gpfFsWscriptGetFileInfo(path);
}

function _gpfFsWScriptExploreList (collection) {
    var fsoEnum = new Enumerator(collection),
        results = [];
    for (; !fsoEnum.atEnd(); fsoEnum.moveNext()) {
        results.push(fsoEnum.item().Path);
    }
    return results;
}

function _gpfFsWScriptExplore (path) {
    var folder;
    if (_gpfMsFSO.FolderExists(path)) {
        folder = _gpfMsFSO.GetFolder(path);
        return _gpfFsWScriptExploreList(folder.SubFolders)
            .concat(_gpfFsWScriptExploreList(folder.Files));
    }
    return [];
}

var _GpfWScriptFileStorage = _gpfDefine(/** @lends gpf.wscript.FileStorage */ {
    $class: "gpf.wscript.FileStorage",

    /**
     * WScript specific IFileStorage implementation
     *
     * @constructor gpf.wscript.FileStorage
     * @implements {gpf.interfaces.IFileStorage}
     */
    constructor: function () {
        if (!_gpfMsFSO) {
            _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");
        }
    },

    //region gpf.interfaces.IFileStorage

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#getInfo
     * @since 0.1.9
     */
    getInfo: function (path) {
        return Promise.resolve(_gpfFsWscriptGetInfo(_gpfPathDecompose(path).join("\\")));
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#openTextStream
     * @since 0.1.9
     */
    openTextStream: function (path, mode) {
        path = _gpfPathDecompose(path).join("\\");
        return new Promise(function (resolve) {
            var stream;
            if (_GPF_FS_OPENFOR.READING === mode) {
                stream = new _GpfWscriptReadableStream(_gpfMsFSO.OpenTextFile(path, 1, false));
            } else {
                stream = new _GpfWscriptWritableStream(_gpfMsFSO.OpenTextFile(path, 8, true));
            }
            resolve(stream);
        });
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#close
     * @since 0.1.9
     */
    close: function (stream) {
        if (stream instanceof _GpfWscriptBaseStream) {
            return stream.close();
        }
        return Promise.reject(new gpf.Error.IncompatibleStream());
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#explore
     * @since 0.1.9
     */
    explore: function (path) {
        return Promise.resolve(_gpfFsExploreEnumerator(this, _gpfFsWScriptExplore(_gpfPathDecompose(path).join("\\"))));
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#createDirectory
     * @since 0.1.9
     */
    createDirectory: _gpfFsWscriptFSOCallWithArg.bind(null, "CreateFolder"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteFile
     * @since 0.1.9
     */
    deleteFile: _gpfFsWscriptFSOCallWithArgAndTrue.bind(null, "DeleteFile"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteDirectory
     * @since 0.1.9
     */
    deleteDirectory: _gpfFsWscriptFSOCallWithArgAndTrue.bind(null, "DeleteFolder")

    //endregion

});

/* istanbul ignore */ // Because tested with NodeJS
if (_GPF_HOST.WSCRIPT === _gpfHost) {

    _gpfSetHostFileStorage(new _GpfWScriptFileStorage());

}
<commit_msg>Documentation<commit_after>/**
 * @file WScript specific File System implementation
 * @since 0.1.9
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_FS_OPENFOR*/ // File system stream opening mode
/*global _GPF_FS_TYPES*/ // File system types constants
/*global _GPF_HOST*/ // Host types
/*global _GpfWscriptBaseStream*/ // gpf.wscript.BaseStream
/*global _GpfWscriptReadableStream*/ // gpf.wscript.ReadableStream
/*global _GpfWscriptWritableStream*/ // gpf.wscript.WritableStream
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfFsExploreEnumerator*/ // IFileStorage.explore helper
/*global _gpfHost*/ // Host type
/*global _gpfHost*/ // Host type
/*global _gpfMsFSO:true*/ // Scripting.FileSystemObject activeX
/*global _gpfPathDecompose*/ // Normalize path and returns an array of parts
/*global _gpfPathNormalize*/ // Normalize path
/*global _gpfPathNormalize*/ // Normalize path
/*global _gpfSetHostFileStorage*/ // Set the result of gpf.fs.getFileStorage
/*#endif*/

/*jshint wsh:true*/
/*eslint-env wsh*/
/*eslint-disable new-cap*/ // FileSystem object APIs are uppercased
/*global Enumerator*/ // Enumerator helper

/**
 * Translate WScript file object into a {@link gpf.typedef.fileStorageInfo}
 *
 * @param {Object} obj WScript file object
 * @param {gpf.fs.types} type Object type
 * @return {gpf.typedef.fileStorageInfo} Information about the object
 * @since 0.1.9
 */
function _gpfFsWScriptObjToFileStorageInfo (obj, type) {
    return {
        type: type,
        fileName: obj.Name.toLowerCase(),
        filePath: _gpfPathNormalize(obj.Path),
        size: obj.Size,
        createdDateTime: new Date(obj.DateCreated),
        modifiedDateTime: new Date(obj.DateLastModified)
    };
}

function _gpfFsWscriptFSOCallWithArg (name, path) {
    return new Promise(function (resolve) {
        _gpfMsFSO[name](_gpfPathDecompose(path).join("\\"));
        resolve();
    });
}

function _gpfFsWscriptFSOCallWithArgAndTrue (name, path) {
    return new Promise(function (resolve) {
        _gpfMsFSO[name](_gpfPathDecompose(path).join("\\"), true);
        resolve();
    });
}

function _gpfFsWscriptGetFileInfo (path) {
    if (_gpfMsFSO.FileExists(path)) {
        return _gpfFsWScriptObjToFileStorageInfo(_gpfMsFSO.GetFile(path), _GPF_FS_TYPES.FILE);
    }
    return {
        type: _GPF_FS_TYPES.NOT_FOUND
    };
}

function _gpfFsWscriptGetInfo (path) {
    if (_gpfMsFSO.FolderExists(path)) {
        return _gpfFsWScriptObjToFileStorageInfo(_gpfMsFSO.GetFolder(path), _GPF_FS_TYPES.DIRECTORY);
    }
    return _gpfFsWscriptGetFileInfo(path);
}

function _gpfFsWScriptExploreList (collection) {
    var fsoEnum = new Enumerator(collection),
        results = [];
    for (; !fsoEnum.atEnd(); fsoEnum.moveNext()) {
        results.push(fsoEnum.item().Path);
    }
    return results;
}

function _gpfFsWScriptExplore (path) {
    var folder;
    if (_gpfMsFSO.FolderExists(path)) {
        folder = _gpfMsFSO.GetFolder(path);
        return _gpfFsWScriptExploreList(folder.SubFolders)
            .concat(_gpfFsWScriptExploreList(folder.Files));
    }
    return [];
}

var _GpfWScriptFileStorage = _gpfDefine(/** @lends gpf.wscript.FileStorage */ {
    $class: "gpf.wscript.FileStorage",

    /**
     * WScript specific IFileStorage implementation
     *
     * @constructor gpf.wscript.FileStorage
     * @implements {gpf.interfaces.IFileStorage}
     * @since 0.1.9
     */
    constructor: function () {
        if (!_gpfMsFSO) {
            _gpfMsFSO = new ActiveXObject("Scripting.FileSystemObject");
        }
    },

    //region gpf.interfaces.IFileStorage

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#getInfo
     * @since 0.1.9
     */
    getInfo: function (path) {
        return Promise.resolve(_gpfFsWscriptGetInfo(_gpfPathDecompose(path).join("\\")));
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#openTextStream
     * @since 0.1.9
     */
    openTextStream: function (path, mode) {
        path = _gpfPathDecompose(path).join("\\");
        return new Promise(function (resolve) {
            var stream;
            if (_GPF_FS_OPENFOR.READING === mode) {
                stream = new _GpfWscriptReadableStream(_gpfMsFSO.OpenTextFile(path, 1, false));
            } else {
                stream = new _GpfWscriptWritableStream(_gpfMsFSO.OpenTextFile(path, 8, true));
            }
            resolve(stream);
        });
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#close
     * @since 0.1.9
     */
    close: function (stream) {
        if (stream instanceof _GpfWscriptBaseStream) {
            return stream.close();
        }
        return Promise.reject(new gpf.Error.IncompatibleStream());
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#explore
     * @since 0.1.9
     */
    explore: function (path) {
        return Promise.resolve(_gpfFsExploreEnumerator(this, _gpfFsWScriptExplore(_gpfPathDecompose(path).join("\\"))));
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#createDirectory
     * @since 0.1.9
     */
    createDirectory: _gpfFsWscriptFSOCallWithArg.bind(null, "CreateFolder"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteFile
     * @since 0.1.9
     */
    deleteFile: _gpfFsWscriptFSOCallWithArgAndTrue.bind(null, "DeleteFile"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteDirectory
     * @since 0.1.9
     */
    deleteDirectory: _gpfFsWscriptFSOCallWithArgAndTrue.bind(null, "DeleteFolder")

    //endregion

});

if (_GPF_HOST.WSCRIPT === _gpfHost) {

    _gpfSetHostFileStorage(new _GpfWScriptFileStorage());

}
<|endoftext|>


<commit_before>import THREE from "THREE";

export default class Shader {
  constructor (vertexShader, fragmentShader, uniforms = {}, attributes = {}) {
    this.vertexShader = vertexShader;
    this.fragmentShader = fragmentShader;
    this.uniforms = uniforms;
    this.attributes = attributes;

    this.parseQualifiers();
  }

  /**
   * Parse shader strings to extract uniforms and attributes
   */
  parseQualifiers () {
    let str = `${this.vertexShader}\n${this.fragmentShader}`;
    let regExp = /(uniform|attribute) (.[^ ]+) (.[^ ;\[\]]+)\[? *(\d+)? *\]?/g;

    let match;

    while((match = regExp.exec(str))) {
      let [ , glslQualifier, glslType, variableName, lengthStr] = match;
      let length = parseInt(lengthStr);

      if (this[`${glslQualifier}s`][variableName]) {
        continue;
      }

      let type;
      let value;
      let typeMatch;

      if(/float|double/.test(glslType)) {
        if(isNaN(length)) {
          type = "f";
          value = "0";
        }
        else {
          type = "fv1";
          value = new Array(length).fill(0);
        }
      }
      else if(/int|uint/.test(glslType)) {
        if(isNaN(length)) {
          type = "i";
          value = "0";
        }
        else {
          type = "iv1";
          value = new Array(length).fill(0);
        }
      }
      else if(/sampler2D/.test(glslType)) {
        if(isNaN(length)) {
          type = "t";
          value = new THREE.Texture();
        }
        else {
          type = "tv";
          value = new Array(length).fill().map(v => new THREE.Texture());
        }
      }
      else if(/samplerCube/.test(glslType)) {
        if(isNaN(length)) {
          type = "t";
          value = new THREE.CubeTexture();
        }
        else {
          type = "tv";
          value = new Array(length).fill().map(v => new THREE.CubeTexture());
        }
      }
      else if((typeMatch = /(.?)vec(\d)/.exec(glslType))) {
        let vectorLength = typeMatch[2];
        if(isNaN(length)) {
          type = `v${vectorLength}`;
          value = new THREE[`Vector${vectorLength}`]();
        }
        else {
          type = `v${vectorLength}v`;
          value = new Array(length).fill().map(v => new THREE[`Vector${vectorLength}`]());
        }
      }
      else if((typeMatch = /mat(\d)/.exec(glslType))) {
        let matrixLength = typeMatch[1];
        if(isNaN(length)) {
          type = `m${matrixLength}`;
          value = new THREE[`Matrix${matrixLength}`]();
        }
        else {
          type = `m${matrixLength}v`;
          value = new Array(length).fill().map(v => new THREE[`Matrix${matrixLength}`]());
        }
      }
      else {
        type = glslType;
        value = null;
      }

      this[`${glslQualifier}s`][variableName] = {type, value};
    }
  }
}
<commit_msg>clean threejs shader<commit_after>import THREE from "THREE";

export default class Shader {
  constructor (vertexShader, fragmentShader, uniforms, attributes) {
    this.vertexShader = vertexShader;
    this.fragmentShader = fragmentShader;
    this.uniforms = uniforms;
    this.attributes = attributes;

    this.parseQualifiers();
  }

  /**
   * Parse shader strings to extract uniforms and attributes
   */
  parseQualifiers () {
    let str = `${this.vertexShader}\n${this.fragmentShader}`;
    let regExp = /(uniform|attribute) (.[^ ]+) (.[^ ;\[\]]+)\[? *(\d+)? *\]?/g;

    let match;

    while((match = regExp.exec(str))) {
      let [ , glslQualifier, glslType, variableName, lengthStr] = match;
      let length = parseInt(lengthStr);

      let glslQualifiers = this[`${glslQualifier}s`];
      if(!glslQualifiers) {
        glslQualifiers = this[`${glslQualifier}s`] = {};
      }
      if (glslQualifiers[variableName]) {
        continue;
      }

      let type;
      let value;
      let typeMatch;

      if(/float|double/.test(glslType)) {
        if(isNaN(length)) {
          type = "f";
          value = "0";
        }
        else {
          type = "fv1";
          value = new Array(length).fill(0);
        }
      }
      else if(/int|uint/.test(glslType)) {
        if(isNaN(length)) {
          type = "i";
          value = "0";
        }
        else {
          type = "iv1";
          value = new Array(length).fill(0);
        }
      }
      else if(/sampler2D/.test(glslType)) {
        if(isNaN(length)) {
          type = "t";
          value = new THREE.Texture();
        }
        else {
          type = "tv";
          value = new Array(length).fill().map(v => new THREE.Texture());
        }
      }
      else if(/samplerCube/.test(glslType)) {
        if(isNaN(length)) {
          type = "t";
          value = new THREE.CubeTexture();
        }
        else {
          type = "tv";
          value = new Array(length).fill().map(v => new THREE.CubeTexture());
        }
      }
      else if((typeMatch = /(.?)vec(\d)/.exec(glslType))) {
        let vectorLength = typeMatch[2];
        if(isNaN(length)) {
          type = `v${vectorLength}`;
          value = new THREE[`Vector${vectorLength}`]();
        }
        else {
          type = `v${vectorLength}v`;
          value = new Array(length).fill().map(v => new THREE[`Vector${vectorLength}`]());
        }
      }
      else if((typeMatch = /mat(\d)/.exec(glslType))) {
        let matrixLength = typeMatch[1];
        if(isNaN(length)) {
          type = `m${matrixLength}`;
          value = new THREE[`Matrix${matrixLength}`]();
        }
        else {
          type = `m${matrixLength}v`;
          value = new Array(length).fill().map(v => new THREE[`Matrix${matrixLength}`]());
        }
      }
      else {
        type = glslType;
        value = null;
      }

      glslQualifiers[variableName] = {type, value};
    }
  }
}
<|endoftext|>


<commit_before>/*
  backgrid-text-cell
  http://github.com/wyuenho/backgrid

  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
  Licensed under the MIT @license.
*/

(function (window, $, _, Backbone, Backgrid)  {

  /**
     Renders a form with a text area and a save button in a modal dialog.

     @class Backgrid.Extension.TextareaEditor
     @extends Backgrid.CellEditor
   */
  var TextareaEditor = Backgrid.Extension.TextareaEditor = Backgrid.CellEditor.extend({

    /** @property */
    tagName: "div",

    /** @property */
    className: "modal hide fade",

    /** @property {function(Object, ?Object=): string} template */
    template: _.template('<form>
<button type="button" class="close" data-dismiss="modal">×</button>
<%- column.get("label") %>

<textarea cols="<%= cols %>" rows="<%= rows %>"><%- content %></textarea>

<input class="btn" type="submit" value="Save"/>
</form>'),

    /** @property */
    cols: 80,

    /** @property */
    rows: 10,

    /** @property */
    events: {
      "submit": "save",
      "hide": "cancel",
      "hidden": "close"
    },

    /**
       @property {Object} modalOptions The options passed to Bootstrap's modal
       plugin.
    */
    modalOptions: {
      backdrop: false
    },

    /**
       Renders a modal form dialog with a textarea, submit button and a close button.
    */
    render: function () {
      this.$el.html($(this.template({
        column: this.column,
        cols: this.cols,
        rows: this.rows,
        content: this.formatter.fromRaw(this.model.get(this.column.get("name")))
      })));

      this.delegateEvents();

      this.$el.modal(this.modalOptions);

      return this;
    },

    /**
       Event handler. Saves the text in the text area to the model.

       Triggers a Backbone `backgrid:error` event along with the editor as the
       parameter if the value cannot be converted. Classes listening to the
       `backgrid:error` event, usually the Cell classes, should respond
       appropriately, usually by rendering some kind of error feedback.

       @param {Event} e
    */
    save: function (e) {
      if (e) e.preventDefault();

      var content = this.formatter.toRaw(this.$el.find("textarea").val());

      if (_.isUndefined(content) ||
          !this.model.set(this.column.get("name"), content, {validate: true})) {
        this.trigger("backgrid:error", this);
      }
      else {
        this.$el.modal("hide");
      }
    },

    /**
       Event handler. Revert the text in the model after asking for confirmation
       if dirty, otherwise just close the editor.

       @param {Event} e
    */
    cancel: function (e) {

      var content = this.formatter.toRaw(this.$el.find("textarea").val());

      // Dirty
      if (content !== this.model.get(this.column.get("name")).replace(/\r/g, '') &&
          window.confirm("Would you like to save your changes?")) {
        e.preventDefault();
        e.stopPropagation();
        return this.save();
      }
    },

    /**
       Triggers a `backgrid:done` event along with the cell editor as the
       parameter after the modal is hidden.
     */
    close: function () {
      this.trigger("backgrid:done", this);
    }

  });

  /**
     TextCell is a string cell type that renders a form with a text area in a
     modal dialog instead of an input box editor. It is best suited for entering
     a large body of text.

     @class Backgrid.Extension.TextCell
     @extends Backgrid.StringCell
  */
  var TextCell = Backgrid.Extension.TextCell = Backgrid.StringCell.extend({

    /** @property */
    className: "text-cell",

    /** @property  */
    editor: TextareaEditor

  });

}(window, jQuery, _, Backbone, Backgrid));
<commit_msg>Fix text cell keybaord nav bindings and focuses the text area when modal is shown<commit_after>/*
  backgrid-text-cell
  http://github.com/wyuenho/backgrid

  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
  Licensed under the MIT @license.
*/

(function (window, $, _, Backbone, Backgrid)  {

  /**
     Renders a form with a text area and a save button in a modal dialog.

     @class Backgrid.Extension.TextareaEditor
     @extends Backgrid.CellEditor
  */
  var TextareaEditor = Backgrid.Extension.TextareaEditor = Backgrid.CellEditor.extend({

    /** @property */
    tagName: "div",

    /** @property */
    className: "modal hide fade",

    /** @property {function(Object, ?Object=): string} template */
    template: _.template('<form>
<button type="button" class="close" data-dismiss="modal">×</button>
<%- column.get("label") %>

<textarea cols="<%= cols %>" rows="<%= rows %>"><%- content %></textarea>

<input class="btn" type="submit" value="Save"/>
</form>'),

    /** @property */
    cols: 80,

    /** @property */
    rows: 10,

    /** @property */
    events: {
      "submit": "save",
      "hide": "cancel",
      "hidden": "close",
      "shown": "focus"
    },

    /**
       @property {Object} modalOptions The options passed to Bootstrap's modal
       plugin.
    */
    modalOptions: {
      backdrop: false
    },

    /**
       Renders a modal form dialog with a textarea, submit button and a close button.
    */
    render: function () {
      this.$el.html($(this.template({
        column: this.column,
        cols: this.cols,
        rows: this.rows,
        content: this.formatter.fromRaw(this.model.get(this.column.get("name")))
      })));

      this.delegateEvents();

      this.$el.modal(this.modalOptions);

      return this;
    },

    /**
       Event handler. Saves the text in the text area to the model.

       Triggers a Backbone `backgrid:error` event along with the editor as the
       parameter if the value cannot be converted. Classes listening to the
       `backgrid:error` event, usually the Cell classes, should respond
       appropriately, usually by rendering some kind of error feedback.

       @param {Event} e
    */
    save: function (e) {
      if (e) e.preventDefault();

      var content = this.formatter.toRaw(this.$el.find("textarea").val());

      if (_.isUndefined(content) ||
          !this.model.set(this.column.get("name"), content, {validate: true})) {
        this.trigger("backgrid:error", this);
      }
      else {
        this.$el.modal("hide");
      }
    },

    /**
       Event handler. Revert the text in the model after asking for confirmation
       if dirty, otherwise just close the editor.

       @param {Event} e
    */
    cancel: function (e) {

      var content = this.formatter.toRaw(this.$el.find("textarea").val());

      // Dirty
      if (content !== this.model.get(this.column.get("name")).replace(/\r/g, '') &&
          window.confirm("Would you like to save your changes?")) {
        e.preventDefault();
        e.stopPropagation();
        return this.save();
      }
    },

    /**
       Triggers a `backgrid:done` event along with the cell editor as the
       parameter after the modal is hidden.

       @param {Event} e
    */
    close: function (e) {
      this.trigger("backgrid:done", this, Backgrid.Cell.buildKeyMods(e));
    },

    /**
       Focuses the textarea when the modal is shown.
    */
    focus: function () {
      this.$el.find("textarea").focus();
    }

  });

  /**
     TextCell is a string cell type that renders a form with a text area in a
     modal dialog instead of an input box editor. It is best suited for entering
     a large body of text.

     @class Backgrid.Extension.TextCell
     @extends Backgrid.StringCell
  */
  var TextCell = Backgrid.Extension.TextCell = Backgrid.StringCell.extend({

    /** @property */
    className: "text-cell",

    /** @property  */
    editor: TextareaEditor

  });

}(window, jQuery, _, Backbone, Backgrid));
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 The FOAM 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.
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'UserAndGroupAuthService',
  flags: ['java'],

  implements: [
    'foam.nanos.auth.AuthService',
    'foam.nanos.NanoService'
  ],

  imports: [
    'DAO localGroupDAO',
    'DAO localSessionDAO',
    'DAO localUserDAO'
  ],

  javaImports: [
    'foam.core.X',
    'foam.dao.DAO',
    'foam.nanos.auth.LifecycleState',
    'foam.nanos.auth.Subject',
    'foam.nanos.auth.User',
    'foam.nanos.logger.Logger',
    'foam.nanos.notification.Notification',
    'foam.nanos.session.Session',
    'foam.util.Email',
    'foam.util.Password',
    'foam.util.SafetyUtil',

    'java.security.Permission',
    'java.util.Calendar',
    'javax.security.auth.AuthPermission',

    'static foam.mlang.MLang.AND',
    'static foam.mlang.MLang.CLASS_OF',
    'static foam.mlang.MLang.EQ',
    'static foam.mlang.MLang.OR'
  ],

  constants: [
    {
      name: 'CHECK_USER_PERMISSION',
      type: 'String',
      value: 'service.auth.checkUser'
    }
  ],

  methods: [
    {
      name: 'start',
      javaCode: '// nothing here'
    },
    {
      name: 'getCurrentSubject',
      javaCode: `
        Session session = x.get(Session.class);
        // fetch context and check if not null or user id is 0
        if ( session == null || session.getUserId() == 0 ) {
          throw new AuthenticationException("Not logged in");
        }
        // get user from session id
        User user = (User) ((DAO) getLocalUserDAO()).find(session.getUserId());
        user.validateAuth(x);
        // check if group enabled
        Group group = getCurrentGroup(x);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }
        Subject subject = (Subject) x.get("subject");
        return subject;
      `
    },
    {
      name: 'loginHelper',
      documentation: `Helper function to reduce duplicated code.`,
      type: 'User',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'user',
          type: 'User'
        },
        {
          name: 'password',
          type: 'String'
        }
      ],
      javaThrows: ['foam.nanos.auth.AuthenticationException'],
      javaCode: `
      try {
        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }

        // check that the user is active
        assertUserIsActive(user);

        // check if user enabled
        if ( ! user.getEnabled() ) {
          throw new AuthenticationException("User disabled");
        }

        // check if user login enabled
        if ( ! user.getLoginEnabled() ) {
          throw new AuthenticationException("Login disabled");
        }

        // check if group enabled
        X userX = x.put("subject", new Subject.Builder(x).setUser(user).build());
        Group group = user.findGroup(userX);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }

        if ( ! Password.verify(password, user.getPassword()) ) {
          throw new AuthenticationException("Invalid Password");
        }

        // Freeze user
        user = (User) user.fclone();
        user.freeze();

        Session session = x.get(Session.class);
        session.setUserId(user.getId());

        if ( Group.ADMIN_GROUP.equalsIgnoreCase(user.getGroup()) ||
             check(x.put("user", user), "*") ) {
          session.setClusterable(false);
          String msg = "Admin login for " + user.getId() + " succeeded on " + System.getProperty("hostname", "localhost");
          ((foam.nanos.logger.Logger) x.get("logger")).warning(msg);
          Notification notification = new Notification.Builder(x)
            .setTemplate("NOC")
            .setToastMessage(msg);
            .setBody(msg)
            .build();
          ((DAO) x.get("localNotificationDAO")).put(notification);
        }

        ((DAO) getLocalSessionDAO()).inX(x).put(session);
        session.setContext(session.applyTo(session.getContext()));
        return user;
      } catch ( AuthenticationException e ) {
        if ( user != null &&
             ( Group.ADMIN_GROUP.equalsIgnoreCase(user.getGroup()) ||
               check(x.put("user", user), "*") ) ) {
          String msg = "Admin login for " + user.getId() + " failed on " + System.getProperty("hostname", "localhost");
          ((foam.nanos.logger.Logger) x.get("logger")).warning(msg);
          Notification notification = new Notification.Builder(x)
            .setTemplate("NOC")
            .setToastMessage(msg);
            .setBody(msg)
            .build();
          ((DAO) x.get("localNotificationDAO")).put(notification);
        }
        throw e;
      }
      `
    },
    {
      name: 'login',
      documentation: `Login a user by their identifier (email or username) provided, validate the password and
        return the user in the context`,
      javaCode: `
        User user = (User) ((DAO) getLocalUserDAO())
          .inX(x)
          .find(
            AND(
              OR(
                EQ(User.EMAIL, identifier.toLowerCase()),
                EQ(User.USER_NAME, identifier)
              ),
              CLASS_OF(User.class)
            )
          );

        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }
        return loginHelper(x, user, password);
      `
    },
    {
      name: 'checkUser',
      documentation: `Checks if the user passed into the method has the passed
        in permission attributed to it by checking their group. No check on User
        and group enabled flags.`,
      javaCode: `
        // check whether user has permission to check user permissions
        if ( ! check(x, CHECK_USER_PERMISSION) ) throw new AuthorizationException();

        if ( user == null || permission == null ) return false;

        try {
          String groupId = (String) user.getGroup();

          while ( ! SafetyUtil.isEmpty(groupId) ) {
            Group group = (Group) ((DAO) getLocalGroupDAO()).find(groupId);

            // if group is null break
            if ( group == null ) break;

            // check permission
            if ( group.implies(x, new AuthPermission(permission)) ) return true;

            // check parent group
            groupId = group.getParent();
          }
        } catch (Throwable t) {
        }

        return false;
      `
    },
    {
      name: 'check',
      documentation: `Check if the user in the context supplied has the right
        permission.`,
      javaCode: `
        if ( x == null || permission == null ) return false;

        Permission p = new AuthPermission(permission);

        try {
          Group group = getCurrentGroup(x);

          while ( group != null ) {

            // check permission
            if ( group.implies(x, p) ) return true;

            // check parent group
            group = (Group) ((DAO) getLocalGroupDAO()).find(group.getParent());
          }
        } catch (IllegalArgumentException e) {
          Logger logger = (Logger) x.get("logger");
          logger.error("check", p, e);
        } catch (Throwable t) {
        }

        return false;
      `
    },
    {
      name: 'validatePassword',
      javaCode: `
        // Password policy to validate against
        PasswordPolicy passwordPolicy = null;

        // Retrieve the logger
        Logger logger = (Logger) x.get("logger");

        // Retrieve the password policy from the user and group when available
        if ( user != null ) {
          Group ancestor = (Group) x.get("group");
          if ( ancestor != null ) {
            // Check password policy
            passwordPolicy = ancestor.getPasswordPolicy();
            while ( passwordPolicy == null || ! passwordPolicy.getEnabled() ) {
              ancestor = ancestor.getAncestor(x, ancestor);
              if ( ancestor == null ) break;
              passwordPolicy = ancestor.getPasswordPolicy();
            }
          }
        }

        // Use the default password policy if nothing is found
        if ( passwordPolicy == null || ! passwordPolicy.getEnabled() ) {
          passwordPolicy = new PasswordPolicy();
          passwordPolicy.setEnabled(true);
        }

        // Validate the password against the password policy
        passwordPolicy.validate(user, potentialPassword);
      `
    },
    {
      name: 'assertUserIsActive',
      documentation: `Given a user, we check whether the user is ACTIVE.`,
      args: [
        {
          name: 'user',
          type: 'foam.nanos.auth.User'
        }
      ],
      javaCode: `
      // check that the user is active
      if ( user instanceof LifecycleAware && ((LifecycleAware)user).getLifecycleState() != LifecycleState.ACTIVE ) {
        throw new AuthenticationException("User is not active");
      }
      `
    },
    {
      name: 'updatePassword',
      documentation: `Given a context with a user, validate the password to be
        updated and return a context with the updated user information.`,
      javaCode: `
        if ( x == null || SafetyUtil.isEmpty(oldPassword) || SafetyUtil.isEmpty(newPassword) ) {
          throw new RuntimeException("Password fields cannot be blank");
        }

        Session session = x.get(Session.class);
        if ( session == null || session.getUserId() == 0 ) {
          throw new AuthenticationException("User not found");
        }

        User user = (User) ((DAO) getLocalUserDAO()).find(session.getUserId());
        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }

        // check that the user is active
        assertUserIsActive(user);

        // check if user enabled
        if ( ! user.getEnabled() ) {
          throw new AuthenticationException("User disabled");
        }

        // check if user login enabled
        if ( ! user.getLoginEnabled() ) {
          throw new AuthenticationException("Login disabled");
        }

        // check if group enabled
        Group group = user.findGroup(x);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }

        // check if password is valid per validatePassword method
        validatePassword(x, user, newPassword);

        // old password does not match
        if ( ! Password.verify(oldPassword, user.getPassword()) ) {
          throw new RuntimeException("Old password is incorrect");
        }

        // new password is the same
        if ( Password.verify(newPassword, user.getPassword()) ) {
          throw new RuntimeException("New password must be different");
        }

        // store new password in DAO and put in context
        user = (User) user.fclone();
        user.setPasswordLastModified(Calendar.getInstance().getTime());
        user.setPreviousPassword(user.getPassword());
        user.setPassword(Password.hash(newPassword));
        // TODO: modify line to allow actual setting of password expiry in cases where users are required to periodically update their passwords
        user.setPasswordExpiry(null);
        user = (User) ((DAO) getLocalUserDAO()).put(user);
        Subject subject = new Subject.Builder(x).setUser(user).build();
        session.setContext(session.getContext().put("subject", subject).put("group", group));
        return user;
      `
    },
    {
      name: 'validateUser',
      documentation: `Used to validate properties of a user. This will be called
        on registration of users. Will mainly be used as a veto method. Users
        should have id, email, first name, last name, password for registration`,
      javaCode: `
        if ( user == null ) {
          throw new AuthenticationException("Invalid User");
        }

        if ( SafetyUtil.isEmpty(user.getEmail()) ) {
          throw new AuthenticationException("Email is required for creating a user");
        }

        if ( ! Email.isValid(user.getEmail()) ) {
          throw new AuthenticationException("Email format is invalid");
        }

        if ( SafetyUtil.isEmpty(user.getFirstName()) ) {
          throw new AuthenticationException("First Name is required for creating a user");
        }

        if ( SafetyUtil.isEmpty(user.getLastName()) ) {
          throw new AuthenticationException("Last Name is required for creating a user");
        }

        if ( SafetyUtil.isEmpty(user.getPassword()) ) {
          throw new AuthenticationException("Password is required for creating a user");
        }

        validatePassword(x, user, user.getPassword());
      `
    },
    {
      name: 'logout',
      documentation: `Just return a null user for now. Not sure how to handle
        the cleanup of the current context.`,
      javaCode: `
        Session session = x.get(Session.class);
        if ( session != null && session.getUserId() != 0 ) {
          ((DAO) getLocalSessionDAO()).remove(session);
        }
      `
    },
    {
      name: 'getCurrentGroup',
      documentation: `Gets the effective group from a context.`,
      javaCode: `
        // Highest precedence: Just return the group from the context if it's already
        // been set.
        Group group = (Group) x.get("group");

        if ( group != null ) return group;

        Subject subject = (Subject) x.get("subject");
        User user = subject.getUser();
        User agent = subject.getRealUser();

        // Second highest precedence: If one user is acting as another, return the
        // group on the junction between them.
        if ( user != null ) {
          if ( agent != null && agent != user ) {
            DAO agentJunctionDAO = (DAO) x.get("agentJunctionDAO");
            UserUserJunction junction = (UserUserJunction) agentJunctionDAO.find(
              AND(
                EQ(UserUserJunction.SOURCE_ID, agent.getId()),
                EQ(UserUserJunction.TARGET_ID, user.getId())
              )
            );

            if ( junction == null ) {
              ((foam.nanos.logger.Logger) x.get("logger")).warning("There was a user and an agent in the context, but a junction between them was not found.", "user", user.getId(), "agent", agent.getId());
              throw new RuntimeException("There was a user and an agent in the context, but a junction between them was not found.");
            }

            return (Group) ((DAO) getLocalGroupDAO()).inX(x).find(junction.getGroup());
          }

          // Third highest precedence: If a user is logged in but not acting as
          // another user, return their group.
          return (Group) ((DAO) getLocalGroupDAO()).inX(x).find(user.getGroup());
        }

        // If none of the cases above match, return null.
        // TODO: Should this throw an error instead?
        return null;
      `
    }
  ]
});

<commit_msg>syntax error<commit_after>/**
 * @license
 * Copyright 2019 The FOAM 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.
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'UserAndGroupAuthService',
  flags: ['java'],

  implements: [
    'foam.nanos.auth.AuthService',
    'foam.nanos.NanoService'
  ],

  imports: [
    'DAO localGroupDAO',
    'DAO localSessionDAO',
    'DAO localUserDAO'
  ],

  javaImports: [
    'foam.core.X',
    'foam.dao.DAO',
    'foam.nanos.auth.LifecycleState',
    'foam.nanos.auth.Subject',
    'foam.nanos.auth.User',
    'foam.nanos.logger.Logger',
    'foam.nanos.notification.Notification',
    'foam.nanos.session.Session',
    'foam.util.Email',
    'foam.util.Password',
    'foam.util.SafetyUtil',

    'java.security.Permission',
    'java.util.Calendar',
    'javax.security.auth.AuthPermission',

    'static foam.mlang.MLang.AND',
    'static foam.mlang.MLang.CLASS_OF',
    'static foam.mlang.MLang.EQ',
    'static foam.mlang.MLang.OR'
  ],

  constants: [
    {
      name: 'CHECK_USER_PERMISSION',
      type: 'String',
      value: 'service.auth.checkUser'
    }
  ],

  methods: [
    {
      name: 'start',
      javaCode: '// nothing here'
    },
    {
      name: 'getCurrentSubject',
      javaCode: `
        Session session = x.get(Session.class);
        // fetch context and check if not null or user id is 0
        if ( session == null || session.getUserId() == 0 ) {
          throw new AuthenticationException("Not logged in");
        }
        // get user from session id
        User user = (User) ((DAO) getLocalUserDAO()).find(session.getUserId());
        user.validateAuth(x);
        // check if group enabled
        Group group = getCurrentGroup(x);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }
        Subject subject = (Subject) x.get("subject");
        return subject;
      `
    },
    {
      name: 'loginHelper',
      documentation: `Helper function to reduce duplicated code.`,
      type: 'User',
      args: [
        {
          name: 'x',
          type: 'Context'
        },
        {
          name: 'user',
          type: 'User'
        },
        {
          name: 'password',
          type: 'String'
        }
      ],
      javaThrows: ['foam.nanos.auth.AuthenticationException'],
      javaCode: `
      try {
        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }

        // check that the user is active
        assertUserIsActive(user);

        // check if user enabled
        if ( ! user.getEnabled() ) {
          throw new AuthenticationException("User disabled");
        }

        // check if user login enabled
        if ( ! user.getLoginEnabled() ) {
          throw new AuthenticationException("Login disabled");
        }

        // check if group enabled
        X userX = x.put("subject", new Subject.Builder(x).setUser(user).build());
        Group group = user.findGroup(userX);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }

        if ( ! Password.verify(password, user.getPassword()) ) {
          throw new AuthenticationException("Invalid Password");
        }

        // Freeze user
        user = (User) user.fclone();
        user.freeze();

        Session session = x.get(Session.class);
        session.setUserId(user.getId());

        if ( Group.ADMIN_GROUP.equalsIgnoreCase(user.getGroup()) ||
             check(x.put("user", user), "*") ) {
          session.setClusterable(false);
          String msg = "Admin login for " + user.getId() + " succeeded on " + System.getProperty("hostname", "localhost");
          ((foam.nanos.logger.Logger) x.get("logger")).warning(msg);
          Notification notification = new Notification.Builder(x)
            .setTemplate("NOC");
            .setToastMessage(msg);
            .setBody(msg)
            .build();
          ((DAO) x.get("localNotificationDAO")).put(notification);
        }

        ((DAO) getLocalSessionDAO()).inX(x).put(session);
        session.setContext(session.applyTo(session.getContext()));
        return user;
      } catch ( AuthenticationException e ) {
        if ( user != null &&
             ( Group.ADMIN_GROUP.equalsIgnoreCase(user.getGroup()) ||
               check(x.put("user", user), "*") ) ) {
          String msg = "Admin login for " + user.getId() + " failed on " + System.getProperty("hostname", "localhost");
          ((foam.nanos.logger.Logger) x.get("logger")).warning(msg);
          Notification notification = new Notification.Builder(x)
            .setTemplate("NOC");
            .setToastMessage(msg);
            .setBody(msg)
            .build();
          ((DAO) x.get("localNotificationDAO")).put(notification);
        }
        throw e;
      }
      `
    },
    {
      name: 'login',
      documentation: `Login a user by their identifier (email or username) provided, validate the password and
        return the user in the context`,
      javaCode: `
        User user = (User) ((DAO) getLocalUserDAO())
          .inX(x)
          .find(
            AND(
              OR(
                EQ(User.EMAIL, identifier.toLowerCase()),
                EQ(User.USER_NAME, identifier)
              ),
              CLASS_OF(User.class)
            )
          );

        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }
        return loginHelper(x, user, password);
      `
    },
    {
      name: 'checkUser',
      documentation: `Checks if the user passed into the method has the passed
        in permission attributed to it by checking their group. No check on User
        and group enabled flags.`,
      javaCode: `
        // check whether user has permission to check user permissions
        if ( ! check(x, CHECK_USER_PERMISSION) ) throw new AuthorizationException();

        if ( user == null || permission == null ) return false;

        try {
          String groupId = (String) user.getGroup();

          while ( ! SafetyUtil.isEmpty(groupId) ) {
            Group group = (Group) ((DAO) getLocalGroupDAO()).find(groupId);

            // if group is null break
            if ( group == null ) break;

            // check permission
            if ( group.implies(x, new AuthPermission(permission)) ) return true;

            // check parent group
            groupId = group.getParent();
          }
        } catch (Throwable t) {
        }

        return false;
      `
    },
    {
      name: 'check',
      documentation: `Check if the user in the context supplied has the right
        permission.`,
      javaCode: `
        if ( x == null || permission == null ) return false;

        Permission p = new AuthPermission(permission);

        try {
          Group group = getCurrentGroup(x);

          while ( group != null ) {

            // check permission
            if ( group.implies(x, p) ) return true;

            // check parent group
            group = (Group) ((DAO) getLocalGroupDAO()).find(group.getParent());
          }
        } catch (IllegalArgumentException e) {
          Logger logger = (Logger) x.get("logger");
          logger.error("check", p, e);
        } catch (Throwable t) {
        }

        return false;
      `
    },
    {
      name: 'validatePassword',
      javaCode: `
        // Password policy to validate against
        PasswordPolicy passwordPolicy = null;

        // Retrieve the logger
        Logger logger = (Logger) x.get("logger");

        // Retrieve the password policy from the user and group when available
        if ( user != null ) {
          Group ancestor = (Group) x.get("group");
          if ( ancestor != null ) {
            // Check password policy
            passwordPolicy = ancestor.getPasswordPolicy();
            while ( passwordPolicy == null || ! passwordPolicy.getEnabled() ) {
              ancestor = ancestor.getAncestor(x, ancestor);
              if ( ancestor == null ) break;
              passwordPolicy = ancestor.getPasswordPolicy();
            }
          }
        }

        // Use the default password policy if nothing is found
        if ( passwordPolicy == null || ! passwordPolicy.getEnabled() ) {
          passwordPolicy = new PasswordPolicy();
          passwordPolicy.setEnabled(true);
        }

        // Validate the password against the password policy
        passwordPolicy.validate(user, potentialPassword);
      `
    },
    {
      name: 'assertUserIsActive',
      documentation: `Given a user, we check whether the user is ACTIVE.`,
      args: [
        {
          name: 'user',
          type: 'foam.nanos.auth.User'
        }
      ],
      javaCode: `
      // check that the user is active
      if ( user instanceof LifecycleAware && ((LifecycleAware)user).getLifecycleState() != LifecycleState.ACTIVE ) {
        throw new AuthenticationException("User is not active");
      }
      `
    },
    {
      name: 'updatePassword',
      documentation: `Given a context with a user, validate the password to be
        updated and return a context with the updated user information.`,
      javaCode: `
        if ( x == null || SafetyUtil.isEmpty(oldPassword) || SafetyUtil.isEmpty(newPassword) ) {
          throw new RuntimeException("Password fields cannot be blank");
        }

        Session session = x.get(Session.class);
        if ( session == null || session.getUserId() == 0 ) {
          throw new AuthenticationException("User not found");
        }

        User user = (User) ((DAO) getLocalUserDAO()).find(session.getUserId());
        if ( user == null ) {
          throw new AuthenticationException("User not found");
        }

        // check that the user is active
        assertUserIsActive(user);

        // check if user enabled
        if ( ! user.getEnabled() ) {
          throw new AuthenticationException("User disabled");
        }

        // check if user login enabled
        if ( ! user.getLoginEnabled() ) {
          throw new AuthenticationException("Login disabled");
        }

        // check if group enabled
        Group group = user.findGroup(x);
        if ( group != null && ! group.getEnabled() ) {
          throw new AuthenticationException("Group disabled");
        }

        // check if password is valid per validatePassword method
        validatePassword(x, user, newPassword);

        // old password does not match
        if ( ! Password.verify(oldPassword, user.getPassword()) ) {
          throw new RuntimeException("Old password is incorrect");
        }

        // new password is the same
        if ( Password.verify(newPassword, user.getPassword()) ) {
          throw new RuntimeException("New password must be different");
        }

        // store new password in DAO and put in context
        user = (User) user.fclone();
        user.setPasswordLastModified(Calendar.getInstance().getTime());
        user.setPreviousPassword(user.getPassword());
        user.setPassword(Password.hash(newPassword));
        // TODO: modify line to allow actual setting of password expiry in cases where users are required to periodically update their passwords
        user.setPasswordExpiry(null);
        user = (User) ((DAO) getLocalUserDAO()).put(user);
        Subject subject = new Subject.Builder(x).setUser(user).build();
        session.setContext(session.getContext().put("subject", subject).put("group", group));
        return user;
      `
    },
    {
      name: 'validateUser',
      documentation: `Used to validate properties of a user. This will be called
        on registration of users. Will mainly be used as a veto method. Users
        should have id, email, first name, last name, password for registration`,
      javaCode: `
        if ( user == null ) {
          throw new AuthenticationException("Invalid User");
        }

        if ( SafetyUtil.isEmpty(user.getEmail()) ) {
          throw new AuthenticationException("Email is required for creating a user");
        }

        if ( ! Email.isValid(user.getEmail()) ) {
          throw new AuthenticationException("Email format is invalid");
        }

        if ( SafetyUtil.isEmpty(user.getFirstName()) ) {
          throw new AuthenticationException("First Name is required for creating a user");
        }

        if ( SafetyUtil.isEmpty(user.getLastName()) ) {
          throw new AuthenticationException("Last Name is required for creating a user");
        }

        if ( SafetyUtil.isEmpty(user.getPassword()) ) {
          throw new AuthenticationException("Password is required for creating a user");
        }

        validatePassword(x, user, user.getPassword());
      `
    },
    {
      name: 'logout',
      documentation: `Just return a null user for now. Not sure how to handle
        the cleanup of the current context.`,
      javaCode: `
        Session session = x.get(Session.class);
        if ( session != null && session.getUserId() != 0 ) {
          ((DAO) getLocalSessionDAO()).remove(session);
        }
      `
    },
    {
      name: 'getCurrentGroup',
      documentation: `Gets the effective group from a context.`,
      javaCode: `
        // Highest precedence: Just return the group from the context if it's already
        // been set.
        Group group = (Group) x.get("group");

        if ( group != null ) return group;

        Subject subject = (Subject) x.get("subject");
        User user = subject.getUser();
        User agent = subject.getRealUser();

        // Second highest precedence: If one user is acting as another, return the
        // group on the junction between them.
        if ( user != null ) {
          if ( agent != null && agent != user ) {
            DAO agentJunctionDAO = (DAO) x.get("agentJunctionDAO");
            UserUserJunction junction = (UserUserJunction) agentJunctionDAO.find(
              AND(
                EQ(UserUserJunction.SOURCE_ID, agent.getId()),
                EQ(UserUserJunction.TARGET_ID, user.getId())
              )
            );

            if ( junction == null ) {
              ((foam.nanos.logger.Logger) x.get("logger")).warning("There was a user and an agent in the context, but a junction between them was not found.", "user", user.getId(), "agent", agent.getId());
              throw new RuntimeException("There was a user and an agent in the context, but a junction between them was not found.");
            }

            return (Group) ((DAO) getLocalGroupDAO()).inX(x).find(junction.getGroup());
          }

          // Third highest precedence: If a user is logged in but not acting as
          // another user, return their group.
          return (Group) ((DAO) getLocalGroupDAO()).inX(x).find(user.getGroup());
        }

        // If none of the cases above match, return null.
        // TODO: Should this throw an error instead?
        return null;
      `
    }
  ]
});

<|endoftext|>


<commit_before>var Score = {
    current: 0,
    donuts: 0,
    veggie: 0,
    isGameOver: false,
    updateLoopTime: 0,
    speedIncrementTime: 0,

    init: function() {
        this.updateUi();
    },

    updateUi: function() {
        $('#score').text(this.getString());

        var $fiveADay = $('#fiveaday');

        for (var i = 1; i <= 5; i++) {
            var $step = $fiveADay.find('.step.s' + i);

            if (this.veggie >= i) {
                $step.addClass('active');
            } else {
                $step.removeClass('active');
            }
        }

        $('#speed').text('Speed x' + (Map.velocity - Map.STARTING_VELOCITY + 1));

        if (Map.velocity <= 0) {
            $('#speed').hide();
        } else {
            $('#speed').show();
        }
    },

    getString: function() {
        var paddedLength = 6;
        var scoreString = Math.round(this.current).toString();
        var toPad = paddedLength - scoreString.length;

        if (toPad > 0) {
            for (var i = 0; i < toPad; i++) {
                scoreString = "0" + scoreString;
            }
        }

        return scoreString;
    },

    addScore: function(amt) {
        this.current += amt;

        if (this.current < 0) {
            this.current = 0;
        }
    },

    addDonut: function() {
        this.donuts++;
        this.addScore(100);
    },

    addVeggie: function() {
        if (this.veggie >= 5) {
            return;
        }

        this.veggie++;
        this.addScore(-250);

        if (this.veggie >= 5 && !this.isGameOver) {
            Map.player.puke();
            this.gameOver("Watch out for your five a day! It keeps the doctor away!
(That's not what we want)");
        }
    },

    update: function() {
        if (this.isGameOver && Keyboard.wasKeyPressed(KeyEvent.DOM_VK_SPACE)) {
            Map.newGame();
        }

        if (this.updateLoopTime > 0) {
            this.updateLoopTime--;
        }

        if (this.updateLoopTime <= 0) {
            if (!this.isGameOver) {
                this.addScore(10 * (Map.velocity - Map.STARTING_VELOCITY));
            }

            this.updateUi();
            this.updateLoopTime = 15; // 250ms, or something like that
        }

        if (this.speedIncrementTime > 0) {
            this.speedIncrementTime--;
        }

        if (this.speedIncrementTime <= 0 && !this.isGameOver) {
            Map.velocity += 0.5;
            this.speedIncrementTime = (60 * 10); // Every ten seconds or so
        }
    },

    gameOver: function(reason) {
        if (this.isGameOver) {
            return;
        }

        Map.player.omnomTimer = -1;

        this.isGameOver = true;

        Map.velocity = 0;

        var $gameOver = $('#gameover');
        $gameOver.find('.reason').html(reason);
        $gameOver.slideDown();
    },

    reset: function() {
        this.isGameOver = false;
        this.current = 0;
        this.donuts = 0;
        this.veggie = 0;
        this.updateLoopTime = 0;
        this.speedIncrementTime = 0;
    }
};<commit_msg>Scoring: Award scores based on movement speed. Higher speed = higher scores. (Apply to pickups)<commit_after>var Score = {
    current: 0,
    donuts: 0,
    veggie: 0,
    isGameOver: false,
    updateLoopTime: 0,
    speedIncrementTime: 0,

    init: function() {
        this.updateUi();
    },

    updateUi: function() {
        $('#score').text(this.getString());

        var $fiveADay = $('#fiveaday');

        for (var i = 1; i <= 5; i++) {
            var $step = $fiveADay.find('.step.s' + i);

            if (this.veggie >= i) {
                $step.addClass('active');
            } else {
                $step.removeClass('active');
            }
        }

        $('#speed').text('Speed x' + (Map.velocity - Map.STARTING_VELOCITY + 1));

        if (Map.velocity <= 0) {
            $('#speed').hide();
        } else {
            $('#speed').show();
        }
    },

    getString: function() {
        var paddedLength = 6;
        var scoreString = Math.round(this.current).toString();
        var toPad = paddedLength - scoreString.length;

        if (toPad > 0) {
            for (var i = 0; i < toPad; i++) {
                scoreString = "0" + scoreString;
            }
        }

        return scoreString;
    },

    addScore: function(amt) {
        this.current += amt;

        if (this.current < 0) {
            this.current = 0;
        }
    },

    addDonut: function() {
        this.donuts++;
        this.addScore(100 * (Map.velocity - Map.STARTING_VELOCITY));
    },

    addVeggie: function() {
        if (this.veggie >= 5) {
            return;
        }

        this.veggie++;
        this.addScore(-250 * (Map.velocity - Map.STARTING_VELOCITY));

        if (this.veggie >= 5 && !this.isGameOver) {
            Map.player.puke();
            this.gameOver("Watch out for your five a day! It keeps the doctor away!
(That's not what we want)");
        }
    },

    update: function() {
        if (this.isGameOver && Keyboard.wasKeyPressed(KeyEvent.DOM_VK_SPACE)) {
            Map.newGame();
        }

        if (this.updateLoopTime > 0) {
            this.updateLoopTime--;
        }

        if (this.updateLoopTime <= 0) {
            if (!this.isGameOver) {
                this.addScore(10 * (Map.velocity - Map.STARTING_VELOCITY));
            }

            this.updateUi();
            this.updateLoopTime = 15; // 250ms, or something like that
        }

        if (this.speedIncrementTime > 0) {
            this.speedIncrementTime--;
        }

        if (this.speedIncrementTime <= 0 && !this.isGameOver) {
            Map.velocity += 0.5;
            this.speedIncrementTime = (60 * 10); // Every ten seconds or so
        }
    },

    gameOver: function(reason) {
        if (this.isGameOver) {
            return;
        }

        Map.player.omnomTimer = -1;

        this.isGameOver = true;

        Map.velocity = 0;

        var $gameOver = $('#gameover');
        $gameOver.find('.reason').html(reason);
        $gameOver.slideDown();
    },

    reset: function() {
        this.isGameOver = false;
        this.current = 0;
        this.donuts = 0;
        this.veggie = 0;
        this.updateLoopTime = 0;
        this.speedIncrementTime = 0;
    }
};<|endoftext|>


<commit_before>import { isString, isObject, includes, every, findIndex } from 'lodash'
import { getTypedAncestor } from './helper'

function isVnode (vnode) {
  return isObject(vnode) && vnode.componentOptions
}

/**
 * 判断是否指定值是否能够传入 getNodes 以获取 DOM nodes 。
 *
 * @param {string|Vue|Node|Array<string>|Array<Vue>|Array<Node>} v 待判断的值
 * @return {boolean}
 */
export function isValidNodesResolver (v) {
  function isValid (item) {
    return (
      isString(item) ||
      item.$vnode ||
      includes([1, 3], item.nodeType) ||
      isVnode(item)
    )
  }

  return isValid(v) || (Array.isArray(v) && every(v, isValid))
}

/**
 * 根据ref拿到指定的DOM节点，主要有一下情况：
 * 1、如果ref是字符串，就需要从context下面找指定ref的组件实例或者DOM元素；
 * 2、如果ref直接就是组件实例，那就取ref.$el；
 * 3、如果ref直接就是文本节点或者元素节点，就返回ref。
 * 4、否则返回空数组
 *
 * @param {string|Vue|Node|Array<string>|Array<Vue>|Array<Node>} ref 目标节点标识
 * @param {VueContext=} context 组件上下文，在ref为字符串的时候必传
 * @return {Node}
 */
export function getNodes (ref, context) {
  let vnodes = getVnodes(ref, context)
  return vnodes.map(item => {
    if (isVnode(item)) {
      return item.elm
    }
    return item
  })
}

export function getVnodes (ref, context) {
  if (!ref) {
    return []
  }
  let vnodes
  if (isString(ref)) {
    vnodes = context.$refs[ref]
    if (!vnodes) {
      vnodes = []
    } else {
      vnodes = Array.isArray(vnodes) ? vnodes : [vnodes]
    }
    vnodes = vnodes.map(item => item.$vnode || item)
  } else {
    ref = Array.isArray(ref) ? ref : [ref]
    vnodes = ref.map(item => {
      if (item.$vnode) {
        return item.$vnode
      } else if (isVnode(item) || item.nodeType === 1 || item.nodeType === 3) {
        // vnode节点、dom元素节点和文本节点
        return item
      }
    })
  }
  return vnodes
}

/**
 * 获取与当前组件最接近的给定类型的祖先组件中，当前组件在其第几个直接子节点的位置
 * @param {Vue} current 查找的组件实例
 * @param {string} parentType 父级类型
 * @returns {number} 该实例所在位置的索引，找不到返回 -1
 */
export function getIndexOfType (current, parentType) {
  let parent = parentType
    ? getTypedAncestor(current, parentType)
    : current.$parent

  if (parentType && !parent) {
    throw new Error(`No ancestor typed as [${parentType}] found.`)
  }

  let parentVnodes = parent.$slots.default

  while (current.$parent !== parent) {
    current = current.$parent
  }

  let currentVnode = getVnodes(current)[0]

  // 只是用于每次渲染时插入到当前位置的顺序
  return findIndex(parentVnodes, vnode => vnode === currentVnode)
}

/**
 * 查找该组件的子孙组件中第一个有某个方法的组件实例，深度优先
 * @param {Vue} context 查找的组件实例，即从 context.$children 开始查找
 * @param {function(Vue): boolean} predicate 判断这个组件是否匹配
 * @returns {?Vue} 找到的组件
 */
export function findComponent (context, predicate) {
  let comp = null
  function walkChildren (children) {
    return children.some(i => {
      let match = predicate(i)
      if (match) {
        comp = i
      } else if (i.$children && i.$children.length) {
        return walkChildren(i.$children)
      }
      return !!match
    })
  }
  walkChildren(context.$children || [])
  return comp
}
<commit_msg>fix: fix item of vnodes is undefined in getVnodes util<commit_after>import { isString, isObject, includes, every, findIndex } from 'lodash'
import { getTypedAncestor } from './helper'

function isVnode (vnode) {
  return isObject(vnode) && vnode.componentOptions
}

/**
 * 判断是否指定值是否能够传入 getNodes 以获取 DOM nodes 。
 *
 * @param {string|Vue|Node|Array<string>|Array<Vue>|Array<Node>} v 待判断的值
 * @return {boolean}
 */
export function isValidNodesResolver (v) {
  function isValid (item) {
    return (
      isString(item) ||
      item.$vnode ||
      includes([1, 3], item.nodeType) ||
      isVnode(item)
    )
  }

  return isValid(v) || (Array.isArray(v) && every(v, isValid))
}

/**
 * 根据ref拿到指定的DOM节点，主要有一下情况：
 * 1、如果ref是字符串，就需要从context下面找指定ref的组件实例或者DOM元素；
 * 2、如果ref直接就是组件实例，那就取ref.$el；
 * 3、如果ref直接就是文本节点或者元素节点，就返回ref。
 * 4、否则返回空数组
 *
 * @param {string|Vue|Node|Array<string>|Array<Vue>|Array<Node>} ref 目标节点标识
 * @param {VueContext=} context 组件上下文，在ref为字符串的时候必传
 * @return {Node}
 */
export function getNodes (ref, context) {
  let vnodes = getVnodes(ref, context)
  return vnodes.map(item => {
    if (isVnode(item)) {
      return item.elm
    }
    return item
  })
}

export function getVnodes (ref, context) {
  if (!ref) {
    return []
  }
  let vnodes
  if (isString(ref)) {
    vnodes = context.$refs[ref]
    if (!vnodes) {
      vnodes = []
    } else {
      vnodes = Array.isArray(vnodes) ? vnodes : [vnodes]
    }
    vnodes = vnodes.filter(Boolean).map(item => item.$vnode || item)
  } else {
    ref = Array.isArray(ref) ? ref : [ref]
    vnodes = ref.map(item => {
      if (item.$vnode) {
        return item.$vnode
      } else if (isVnode(item) || item.nodeType === 1 || item.nodeType === 3) {
        // vnode节点、dom元素节点和文本节点
        return item
      }
    })
  }
  return vnodes
}

/**
 * 获取与当前组件最接近的给定类型的祖先组件中，当前组件在其第几个直接子节点的位置
 * @param {Vue} current 查找的组件实例
 * @param {string} parentType 父级类型
 * @returns {number} 该实例所在位置的索引，找不到返回 -1
 */
export function getIndexOfType (current, parentType) {
  let parent = parentType
    ? getTypedAncestor(current, parentType)
    : current.$parent

  if (parentType && !parent) {
    throw new Error(`No ancestor typed as [${parentType}] found.`)
  }

  let parentVnodes = parent.$slots.default

  while (current.$parent !== parent) {
    current = current.$parent
  }

  let currentVnode = getVnodes(current)[0]

  // 只是用于每次渲染时插入到当前位置的顺序
  return findIndex(parentVnodes, vnode => vnode === currentVnode)
}

/**
 * 查找该组件的子孙组件中第一个有某个方法的组件实例，深度优先
 * @param {Vue} context 查找的组件实例，即从 context.$children 开始查找
 * @param {function(Vue): boolean} predicate 判断这个组件是否匹配
 * @returns {?Vue} 找到的组件
 */
export function findComponent (context, predicate) {
  let comp = null
  function walkChildren (children) {
    return children.some(i => {
      let match = predicate(i)
      if (match) {
        comp = i
      } else if (i.$children && i.$children.length) {
        return walkChildren(i.$children)
      }
      return !!match
    })
  }
  walkChildren(context.$children || [])
  return comp
}
<|endoftext|>


<commit_before>(function($) {

	var baseUrl = '/api';

	function config(callback) {
		var c = {
			baseUrl : function(url) {
				baseUrl = url;
			}
		};

		callback(c);
	}

	function defaultAjax(type, options) {
		var request = $.ajax({
			type : type,
			url : baseUrl + options.url + (options.query ? '?' + $.param(options.query) : ''),
			data : options.data,
			async : options.async,
			contentType : 'application/json;charset=UTF-8',
			dataType : 'json'
		});

		return request;
	}

	function extractId(object) {
		if (object.id) {
			return object.id;
		}
		throw 'use yawp(id) if your endpoint does not have a @Id field called id';
	}

	function query(options) {
		var q = {};

		function where(data) {
			if (arguments.length === 1) {
				q.where = data;
			} else {
				q.where = $.makeArray(arguments);
			}
			return this;
		}

		function order(data) {
			q.order = data;
			return this;
		}

		function sort(data) {
			q.sort = data;
			return this;
		}

		function limit(data) {
			q.limit = data;
			return this;
		}

		function fetch(callback) {
			return defaultAjax('GET', options()).done(callback);
		}

		function setupQuery() {
			if (Object.keys(q).length > 0) {
				options.addQueryParameter('q', JSON.stringify(q));
			}
		}

		function url(decode) {
			setupQuery();
			var url = baseUrl + options().url + (options().query ? '?' + $.param(options().query) : '');
			if (decode) {
				return decodeURIComponent(url);
			}
			return url;
		}

		function list(callback) {
			setupQuery();
			return defaultAjax('GET', options()).done(callback);
		}

		function first(callback) {
			limit(1);

			return list(function(objects) {
				var object = objects.length == 0 ? null : objects[0];
				if (callback) {
					callback(object);
				}
			});
		}

		function only(callback) {
			return list(function(objects) {
				if (objects.length != 1) {
					throw 'called only but got ' + objects.length + ' results';
				}
				if (callback) {
					callback(objects[0]);
				}
			});
		}

		return {
			where : where,
			order : order,
			sort : sort,
			limit : limit,
			fetch : fetch,
			list : list,
			first : first,
			only : only,
			url : url
		};
	}

	function repository(options) {
		function create(object) {
			options().data = JSON.stringify(object);
			return defaultAjax('POST', options());
		}

		function update(object) {
			options().data = JSON.stringify(object);
			return defaultAjax('PUT', options());
		}

		function patch(object) {
			options().data = JSON.stringify(object);
			return defaultAjax('PATCH', options());
		}

		function destroy() {
			return defaultAjax('DELETE', options());
		}

		return {
			create : create,
			update : update,
			patch : patch,
			destroy : destroy
		};
	}

	function actions(options) {
		function actionOptions(action) {
			options().url += '/' + action;
			return options();
		}

		function params(params) {
			options.addQueryParameters(params);
			return this;
		}

		function get(action) {
			return defaultAjax('GET', actionOptions(action));
		}

		function put(action) {
			return defaultAjax('PUT', actionOptions(action));
		}

		function post(action) {
			return defaultAjax('POST', actionOptions(action));
		}

		function _delete(action) {
			return defaultAjax('DELETE', actionOptions(action));
		}

		return {
			params : params,
			get : get,
			put : put,
			post : post,
			_delete : _delete
		};
	}

	function yawp(baseArg) {
		function normalize(arg) {
			if (!arg) {
				return '';
			}
			if (arg instanceof Object) {
				return extractId(arg);
			}
			return arg;
		}

		var ajaxOptions = {
			url : normalize(baseArg)
		}

		function options() {
			return ajaxOptions;
		}

		options.addQueryParameters = function(params) {
			ajaxOptions.query = $.extend(ajaxOptions.query, params);
		};

		options.addQueryParameter = function(key, value) {
			if (!ajaxOptions.query) {
				ajaxOptions.query = {};
			}
			ajaxOptions.query[key] = value;
		};

		function from(parentBaseArg) {
			var parentBase = normalize(parentBaseArg);
			options().url = parentBase + options().url;
			return this;
		}

		function transform(t) {
			options.addQueryParameter('t', t);
			return this;
		}

		function sync() {
			ajaxOptions.async = false;
			return this;
		}

		return $.extend({
			from : from,
			transform : transform,
			sync : sync
		}, query(options), repository(options), actions(options));
	}

	function update(object) {
		var id = extractId(object);
		return yawp(id).update(object);
	}

	function patch(object) {
		var id = extractId(object);
		return yawp(id).patch(object);
	}

	function destroy(object) {
		var id = extractId(object);
		return yawp(id).destroy(object);
	}

	var api = {
		config : config,
		update : update,
		patch : patch,
		destroy : destroy
	};

	window.yawp = $.extend(yawp, api);

})(jQuery);
<commit_msg>console to site<commit_after><|endoftext|>


<commit_before>/**
 * A Gulp task for compiling JavaScript through Browserify.
 *
 * To use this in a gulpfile.js:
 *
 *    import BuildTask from 'carbon-factory/lib/gulp/build';
 *    gulp.task('default', BuildTask());
 *
 * You can also pass a hash of options to customise the task:
 *
 *    import BuildTask from 'carbon-factory/lib/gulp/build';
 *
 *    var opts = {
 *      src: "./src/main.js",
 *      jsDest: "./assets/javascripts",
 *      jsFile: "app.js",
 *      additionalSassTransformDirs: ['./node_modules/my-custom-package']
 *    }
 *
 *    gulp.task('default', BuildTask(opts));
 *
 * If you have setup the task using the task name 'default' then you can run it
 * through the command line like this:
 *
 *    gulp
 *
 * The process can also be ran without watch files for changes (useful for running single builds):
 *
 *    gulp --build
 *
 * The process can also be ran with specific handlers:
 *
 *    gulp --handler uki
 *
 * This will include a module named `carbon-handler-uki` in the build process.
 */

import aliasify from 'aliasify';
import babel from 'babelify';
import browserify from 'browserify';
import gulp from 'gulp';
import gutil from 'gulp-util';
import mkdirp from 'mkdirp';
import notifier from 'node-notifier';
import parcelify from 'parcelify';
import envify from 'envify/custom';
import sassCssStream from 'sass-css-stream';
import source from 'vinyl-source-stream';
import watchify from 'watchify';
import yargs from 'yargs';
import gulpif from 'gulp-if';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import livereactload from 'livereactload';

var argv = yargs.argv;

export default function (opts) {
  var options = opts;

  return function() {
    var opts = options || {},
        // the entrypoint for the JavaScript application
        src = opts.src || './src/main.js',
        // the destination directory for the generated code
        jsDest = opts.jsDest || './assets/javascripts',
        // the destination file for the generated code
        jsFile = opts.jsFile || 'ui.js',
        // the destination for the css file
        cssDest = opts.cssDest || './assets/stylesheets',
        // the filename to write the css to
        cssFile = opts.cssFile || 'ui.css',
        // the destination for any fonts
        fontDest = opts.fontDest || './assets/fonts',
        // the destination for any images
        imageDest = opts.imageDest || './assets/images',
        // define directories in which to apply sass transforms
        additionalSassTransformDirs = ['./node_modules/carbon', './'],
        // a standalone param to expose components globally
        standalone = opts.standalone || null,
        // if single build, or run and watch
        watch = (argv.build === undefined),
        // if in production mode
        production = argv.production || false,
        // if uglify requested
        doUglify = opts.uglify || true;

    if (opts.additionalSassTransformDirs) {
      // define directories in which to apply sass transforms
      additionalSassTransformDirs = additionalSassTransformDirs.concat(opts.additionalSassTransformDirs);
    }

    if (production) {
      process.env.NODE_ENV = 'production';
    }

    // handles any errors and exits the task
    function handleError(err) {
      // placeholder for toast notification message
      var notifierMessage = '';
      var message = err.message;

      // if location in file available
      if (err.loc) {
        var position = "\nLine: "   + err.loc.line
                     + "\nColumn: " + err.loc.column;
        notifierMessage += position;
        message += position;
      }

      // if code context available
      if (err.codeFrame) {
        message += "\n" + err.codeFrame;
      }

      // additional toast notification variables
      var title = 'Error: '

      // format file path
      if (err.filename) {
        var file = err.filename.split('/');
        title += file[file.length-1];
      }

      // output error messages in toast and in console
      notifier.notify({ title: title, message: notifierMessage } );
      gutil.log(gutil.colors.red(err.name), message);

      // exit task
      if (watch) {
        this.emit('end');
      } else {
        process.exit(1);
      }
    }

    // a handler argument if supplied one when running the task
    var handler = argv.handler;

    /**
     * Babel options (for JS/JSX).
     */
    var babelTransform = babel.configure({
      ignore: /node_modules/,
      extends: process.cwd() + '/node_modules/carbon-factory/.babelrc' // manually set babelrc for gulp task

    });

    /**
     * Alias options (to include handler specific JS).
     */
    var aliasTransform = null;

    if (handler) {
      aliasTransform = aliasify.configure({
        aliases: {
          // make it possible to import the original handler if `carbon-handler`
          // is aliased to get something else
          "base-handler": "./src/carbon-handler",
          // if using a handler, alias any imports of `carbon-handler` to use
          // the handler instead
          "carbon-handler": "carbon-handler-" + handler
        }
      });
    }

    /**
     * Envify options (sets env options when compiling code).
     */
    var envifyTransform = envify({
      global: true,
      _: 'purge',
      NODE_ENV: process.env.NODE_ENV
    });

    /**
     * Browserify options (for CommonJS).
     */
    var browserifyOpts = {
      // the entry points for the application
      entries: [ src ],
      // which transforms to apply to the code
      transform: [ babelTransform, aliasTransform, envifyTransform ],
      // lookup paths when importing modules
      paths: [ './src' ],

      // Caching for watchify see:
      // https://github.com/substack/watchify/blob/v3.7.0/readme.markdown#watchifyb-opts
      cache: {},
      packageCache: {}
    };

    if (watch && !argv.cold) {
      browserifyOpts.plugin = [ livereactload ];
    }

    if (standalone) {
      browserifyOpts.standalone = standalone;
    }

    var browserified = browserify(browserifyOpts);

    // create dirs for assets
    mkdirp(fontDest, function (err) {
      if (err) console.error(err);
    });
    mkdirp(imageDest, function (err) {
      if (err) console.error(err);
    });
    mkdirp(cssDest, function (err) {
      if (err) console.error(err);
    });

    /**
     * Parcelify options (for Sass/CSS).
     */
    var parcelified = parcelify(browserified, {
      // watch scss files to update on any changes
      watch: watch,
      // where to bundle the output
      bundles: {
        style: cssDest + '/' + cssFile,
        fonts: null,
        images: null
      },
      appTransforms : [
        // sass transformer
        function sassTransformer( file ) {
          // array of include paths allows for overriding entire files
          return sassCssStream( file, {
            includePaths: [
              process.cwd() + "/src/style-config", // check for overrides in local style-config directory
              process.cwd() + "/node_modules/carbon/lib/style-config", // check for original config files
              process.cwd() + "/node_modules" // generic namespace for any other lookups
            ]
          });
        }
      ],
      // where to apply transforms
      appTransformDirs: additionalSassTransformDirs
    }).on('done', function() {
      // when parcelify is ready
      gutil.log("Assets are compiled!");

      if (watch) {
        gutil.log("Gulp is now watching and will rebuild your code when it detects any file changes...");
      }
    }).on('error', function(err) {
      // handle error
      gutil.log("*** CSS Error ***");
      handleError.call(this, err);
    }).on('bundleWritten', function(path, name, parcel) {
      // copy the fonts to the correct directory
      var fonts = [];
      parcel.parcelAssetsByType.fonts.forEach((font) => {
        fonts.push(font.srcPath);
      });
      gulp.src(fonts)
        .pipe(gulp.dest(fontDest));

      // copy the images to the correct directory
      var images = [];
      parcel.parcelAssetsByType.images.forEach((image) => {
        images.push(image.srcPath);
      });
      gulp.src(images)
        .pipe(gulp.dest(imageDest));

      // write the css file
      return gulp.src(cssFile)
        .on('error', () => gutil.log("*** Error writing the CSS File ***"))
        .on('error', handleError)
        .pipe(gulp.dest(cssDest));
    });

    /**
     * The pack we are going to watch and build
     */
    var bundler = watch ? watchify(browserified) : browserified;

    /**
     * The main build task.
     */
    function build(f) {
      if (f) gutil.log('Recompiling ' + f);
      return bundler
        .bundle()
        .on('error', () => gutil.log("*** Browserify Error ***"))
        .on('error', handleError)
        .pipe(source(jsFile))
        .pipe(gulpif(production && doUglify, streamify(uglify())))
        .pipe(gulp.dest(jsDest));
    };

    // run the build immediately and whenever the bundler updates
    bundler.on('update', build);
    build();
  }
};
<commit_msg>Actually fix default uglify logic<commit_after>/**
 * A Gulp task for compiling JavaScript through Browserify.
 *
 * To use this in a gulpfile.js:
 *
 *    import BuildTask from 'carbon-factory/lib/gulp/build';
 *    gulp.task('default', BuildTask());
 *
 * You can also pass a hash of options to customise the task:
 *
 *    import BuildTask from 'carbon-factory/lib/gulp/build';
 *
 *    var opts = {
 *      src: "./src/main.js",
 *      jsDest: "./assets/javascripts",
 *      jsFile: "app.js",
 *      additionalSassTransformDirs: ['./node_modules/my-custom-package']
 *    }
 *
 *    gulp.task('default', BuildTask(opts));
 *
 * If you have setup the task using the task name 'default' then you can run it
 * through the command line like this:
 *
 *    gulp
 *
 * The process can also be ran without watch files for changes (useful for running single builds):
 *
 *    gulp --build
 *
 * The process can also be ran with specific handlers:
 *
 *    gulp --handler uki
 *
 * This will include a module named `carbon-handler-uki` in the build process.
 */

import aliasify from 'aliasify';
import babel from 'babelify';
import browserify from 'browserify';
import gulp from 'gulp';
import gutil from 'gulp-util';
import mkdirp from 'mkdirp';
import notifier from 'node-notifier';
import parcelify from 'parcelify';
import envify from 'envify/custom';
import sassCssStream from 'sass-css-stream';
import source from 'vinyl-source-stream';
import watchify from 'watchify';
import yargs from 'yargs';
import gulpif from 'gulp-if';
import uglify from 'gulp-uglify';
import streamify from 'gulp-streamify';
import livereactload from 'livereactload';

var argv = yargs.argv;

export default function (opts) {
  var options = opts;

  return function() {
    var opts = options || {},
        // the entrypoint for the JavaScript application
        src = opts.src || './src/main.js',
        // the destination directory for the generated code
        jsDest = opts.jsDest || './assets/javascripts',
        // the destination file for the generated code
        jsFile = opts.jsFile || 'ui.js',
        // the destination for the css file
        cssDest = opts.cssDest || './assets/stylesheets',
        // the filename to write the css to
        cssFile = opts.cssFile || 'ui.css',
        // the destination for any fonts
        fontDest = opts.fontDest || './assets/fonts',
        // the destination for any images
        imageDest = opts.imageDest || './assets/images',
        // define directories in which to apply sass transforms
        additionalSassTransformDirs = ['./node_modules/carbon', './'],
        // a standalone param to expose components globally
        standalone = opts.standalone || null,
        // if single build, or run and watch
        watch = (argv.build === undefined),
        // if in production mode
        production = argv.production || false,
        // if uglify requested
        doUglify = (opts.uglify !== false);

    if (opts.additionalSassTransformDirs) {
      // define directories in which to apply sass transforms
      additionalSassTransformDirs = additionalSassTransformDirs.concat(opts.additionalSassTransformDirs);
    }

    if (production) {
      process.env.NODE_ENV = 'production';
    }

    // handles any errors and exits the task
    function handleError(err) {
      // placeholder for toast notification message
      var notifierMessage = '';
      var message = err.message;

      // if location in file available
      if (err.loc) {
        var position = "\nLine: "   + err.loc.line
                     + "\nColumn: " + err.loc.column;
        notifierMessage += position;
        message += position;
      }

      // if code context available
      if (err.codeFrame) {
        message += "\n" + err.codeFrame;
      }

      // additional toast notification variables
      var title = 'Error: '

      // format file path
      if (err.filename) {
        var file = err.filename.split('/');
        title += file[file.length-1];
      }

      // output error messages in toast and in console
      notifier.notify({ title: title, message: notifierMessage } );
      gutil.log(gutil.colors.red(err.name), message);

      // exit task
      if (watch) {
        this.emit('end');
      } else {
        process.exit(1);
      }
    }

    // a handler argument if supplied one when running the task
    var handler = argv.handler;

    /**
     * Babel options (for JS/JSX).
     */
    var babelTransform = babel.configure({
      ignore: /node_modules/,
      extends: process.cwd() + '/node_modules/carbon-factory/.babelrc' // manually set babelrc for gulp task

    });

    /**
     * Alias options (to include handler specific JS).
     */
    var aliasTransform = null;

    if (handler) {
      aliasTransform = aliasify.configure({
        aliases: {
          // make it possible to import the original handler if `carbon-handler`
          // is aliased to get something else
          "base-handler": "./src/carbon-handler",
          // if using a handler, alias any imports of `carbon-handler` to use
          // the handler instead
          "carbon-handler": "carbon-handler-" + handler
        }
      });
    }

    /**
     * Envify options (sets env options when compiling code).
     */
    var envifyTransform = envify({
      global: true,
      _: 'purge',
      NODE_ENV: process.env.NODE_ENV
    });

    /**
     * Browserify options (for CommonJS).
     */
    var browserifyOpts = {
      // the entry points for the application
      entries: [ src ],
      // which transforms to apply to the code
      transform: [ babelTransform, aliasTransform, envifyTransform ],
      // lookup paths when importing modules
      paths: [ './src' ],

      // Caching for watchify see:
      // https://github.com/substack/watchify/blob/v3.7.0/readme.markdown#watchifyb-opts
      cache: {},
      packageCache: {}
    };

    if (watch && !argv.cold) {
      browserifyOpts.plugin = [ livereactload ];
    }

    if (standalone) {
      browserifyOpts.standalone = standalone;
    }

    var browserified = browserify(browserifyOpts);

    // create dirs for assets
    mkdirp(fontDest, function (err) {
      if (err) console.error(err);
    });
    mkdirp(imageDest, function (err) {
      if (err) console.error(err);
    });
    mkdirp(cssDest, function (err) {
      if (err) console.error(err);
    });

    /**
     * Parcelify options (for Sass/CSS).
     */
    var parcelified = parcelify(browserified, {
      // watch scss files to update on any changes
      watch: watch,
      // where to bundle the output
      bundles: {
        style: cssDest + '/' + cssFile,
        fonts: null,
        images: null
      },
      appTransforms : [
        // sass transformer
        function sassTransformer( file ) {
          // array of include paths allows for overriding entire files
          return sassCssStream( file, {
            includePaths: [
              process.cwd() + "/src/style-config", // check for overrides in local style-config directory
              process.cwd() + "/node_modules/carbon/lib/style-config", // check for original config files
              process.cwd() + "/node_modules" // generic namespace for any other lookups
            ]
          });
        }
      ],
      // where to apply transforms
      appTransformDirs: additionalSassTransformDirs
    }).on('done', function() {
      // when parcelify is ready
      gutil.log("Assets are compiled!");

      if (watch) {
        gutil.log("Gulp is now watching and will rebuild your code when it detects any file changes...");
      }
    }).on('error', function(err) {
      // handle error
      gutil.log("*** CSS Error ***");
      handleError.call(this, err);
    }).on('bundleWritten', function(path, name, parcel) {
      // copy the fonts to the correct directory
      var fonts = [];
      parcel.parcelAssetsByType.fonts.forEach((font) => {
        fonts.push(font.srcPath);
      });
      gulp.src(fonts)
        .pipe(gulp.dest(fontDest));

      // copy the images to the correct directory
      var images = [];
      parcel.parcelAssetsByType.images.forEach((image) => {
        images.push(image.srcPath);
      });
      gulp.src(images)
        .pipe(gulp.dest(imageDest));

      // write the css file
      return gulp.src(cssFile)
        .on('error', () => gutil.log("*** Error writing the CSS File ***"))
        .on('error', handleError)
        .pipe(gulp.dest(cssDest));
    });

    /**
     * The pack we are going to watch and build
     */
    var bundler = watch ? watchify(browserified) : browserified;

    /**
     * The main build task.
     */
    function build(f) {
      if (f) gutil.log('Recompiling ' + f);
      return bundler
        .bundle()
        .on('error', () => gutil.log("*** Browserify Error ***"))
        .on('error', handleError)
        .pipe(source(jsFile))
        .pipe(gulpif(production && doUglify, streamify(uglify())))
        .pipe(gulp.dest(jsDest));
    };

    // run the build immediately and whenever the bundler updates
    bundler.on('update', build);
    build();
  }
};
<|endoftext|>