<commit_before>import _reduce from 'lodash/reduce'
import _isObject from 'lodash/isObject'
import {call} from 'redux-saga/effects'
import {cache} from 'tocco-util'
import _get from 'lodash/get'

import {requestSaga} from './rest'

/**
 * Helper to fetch a single entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntity(entityName, key, query, transformer = json => json) {
  const requestQuery = yield call(buildRequestQuery, query)
  const options = {
    method: 'GET',
    queryParams: {
      ...requestQueryToUrlParams(requestQuery),
      _permissions: true,
      _omitLinks: true
    }
  }

  const resp = yield call(requestSaga, `entities/2.0/${entityName}/${key}`, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch the default-display of an entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param type {String} type of the display, default display if none passed
 */
export function* fetchDisplay(entityName, key, type) {
  return _get(yield fetchDisplays({[entityName]: [key]}, type), `${entityName}.${key}`, null)
}

/**
 * Helper to fetch display-expressions of a form for a list of entities
 *
 * @param formName {String} Name of the form
 * @param scope {String} Requested form scope e.g. update or list
 * @param entityKeys {Array} List of entity keys
 * @param displayExpressionFields {Array} List of desired display-expression fields
 */
export function* fetchDisplayExpressions(formName, scope, entityKeys, displayExpressionFields) {
  const options = {
    method: 'GET',
    queryParams: {
      _keys: entityKeys.join(','),
      _paths: displayExpressionFields.join(',')
    }
  }

  const response = yield call(requestSaga, `forms/${formName}_${scope}/display-expressions`, options)

  return response.body.displayExpressions.reduce((acc, val) => ({...acc, [val.key]: val.displayExpressions}), {})
}

/**
 * Helper to fetch the default-display of an entities.
 *
 * @param request {Object} Object containing model and keys of desired entities e.g. {User: ["123"], Gender: ["1", "2"]}
 * @param type {String} type of the display, default display if none passed
 */
export function* fetchDisplays(request, type) {
  const currentDisplays = Object.entries(request).map(([model, keys]) => ({
    model,
    keys: keys.filter(key => cache.get('display', `${model}.${key}${type ? `.${type}` : ''}`) === undefined),
    displays: keys.map(key => ({key, display: cache.get('display', `${model}.${key}${type ? `.${type}` : ''}`)}))
      .filter(value => value.display !== undefined)
  }))

  const loadedDisplays = yield loadDisplays(currentDisplays, type)

  return currentDisplays.reduce((acc, {model, displays}) => ({
    ...acc,
    [model]: {
      ...acc[model],
      ...(displays.reduce((acc, {key, display}) => ({
        ...acc,
        [key]: display
      }), {}))
    }
  }), loadedDisplays)
}

function* loadDisplays(currentDisplays, type) {
  const keysToLoad = currentDisplays.filter(({keys}) => keys.length > 0).map(({model, keys}) => ({model, keys}))
  if (keysToLoad.length > 0) {
    const options = {
      method: 'POST',
      body: {data: keysToLoad}
    }
    const response = yield call(requestSaga, `entities/2.0/displays${type ? `/${type}` : ''}`, options)

    const loadedDisplays = response.body.data.reduce((acc, value) => (
      {
        ...acc,
        [value.model]: value.values.reduce((acc, value) => ({...acc, [value.key]: value.display}), {})
      }
    ), {})
    Object.entries(loadedDisplays).forEach(([entityName, values]) => {
      Object.entries(values).forEach(([key, display]) => {
        cache.add('display', `${entityName}.${key}${type ? `.${type}` : ''}}`, display)
      })
    })
    return loadedDisplays
  } else {
    return {}
  }
}

/**
 * Fetch amount of entities
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/count
 */
export function* fetchEntityCount(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {}
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = (endpoint || `entities/2.0/${entityName}`) + '/count'

  const options = {
    method,
    ...(method === 'GET' ? {queryParams: requestQueryToUrlParams(requestQuery)} : {body: requestQuery})
  }

  const response = yield call(requestSaga, resource, options)
  return response.body.count
}

/**
 * Helper to fetch entities.
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/search
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntities(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {},
  transformer = defaultEntityTransformer
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = endpoint || `entities/2.0/${entityName}${method === 'POST' ? '/search' : ''}`

  const options = {
    method,
    queryParams: {
      _omitLinks: true,
      ...(method === 'GET' && requestQueryToUrlParams(requestQuery))
    },
    ...(method === 'POST' && {body: requestQuery})
  }

  const resp = yield call(requestSaga, resource, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch forms.
 * @param formName {String} Name of the requested form
 * @param scope {String} Requested form scope e.g. update or list
 * @param allowNotFound {Boolean} If true and the form does not exist null is returned.
 *                                Otherwise an exception will be thrown.
 */
export function* fetchForm(formName, scope, allowNotFound = false) {
  const request = `${formName}/${scope}`
  const cachedForm = cache.get('form', request)
  if (cachedForm !== undefined) {
    return cachedForm
  }

  const options = {
    ...(allowNotFound && {acceptedStatusCodes: [404]})
  }

  const response = yield call(requestSaga, `forms/${request}`, options)

  if (allowNotFound && response.status === 404) {
    cache.add('form', request, null)
    return null
  }

  const form = yield call(defaultFormTransformer, response.body)
  cache.add('form', request, form)
  return form
}

/**
 * Helper to fetch filters of an entity
 * @param entityName {String} Name of the  entity
 */
export function* fetchSearchFilters(entityName) {
  const response = yield call(requestSaga, `client/searchfilters/${entityName}`)
  return response.body.filters
}

/**
 * Helper to fetch models.
 * @param entityName {String} Name of the entity you like to fetch the model
 */
export function* fetchModel(entityName, transformer = defaultModelTransformer) {
  const cachedModel = cache.get('model', entityName)
  if (cachedModel) {
    return cachedModel
  }

  const resp = yield call(requestSaga, `entities/${entityName}/model`)
  const model = yield call(transformer, resp.body)
  cache.add('model', entityName, model)
  return model
}

export const defaultModelTransformer = json => {
  const model = {
    name: json.name,
    label: json.label,
    paths: {}
  }
  json.fields.forEach(field => {
    model.paths[field.fieldName] = {
      ...field
    }
  })

  json.relations.forEach(relation => {
    model.paths[relation.relationName] = {
      type: 'relation',
      ...relation
    }
  })
  return model
}

export const defaultFormTransformer = json => (json.form)

export const defaultEntityTransformer = json => (json.data)

/**
 * Function that converts a query object into request query object that can be attached to a request.
 * Some options get converted or calculated and other removed if there are undefined.
 *
 * @param options {Object} An object which can contain the following options:
 * - conditions {Object} Object that can contain search fields. Each field
 * - fields {Array} Fields that should be returned
 * - form {String} Name of the form, needed to resolve display expressions and such
 * - limit {Object} Maximum amount of entities to be retrieved
 * - search {Object} Fulltext search on entity
 * - sorting {Array} Array of objects containing a field and order String. e.g. [{field: 'firstname', order: 'asc'}]
 * - page {Number} Current page, needed to calculate offset. Default is undefined which means no offset.
 * - paths {Array} Paths that should be returned
 * - where {String} TQL query
 * - relations {String} Relations that should be returned
 * - filters {Array} List of filter names to be applied
 * - constriction {String} Id of the constriction that should be applied
 */
export const buildRequestQuery = ({
  conditions,
  fields,
  form,
  limit,
  search,
  sorting,
  page,
  paths,
  where,
  relations,
  filter,
  keys,
  constriction
} = {}) => (
  {
    ...(conditions ? {conditions} : {}),
    ...(Array.isArray(fields) ? {fields: fields.length === 0 ? '!' : fields} : {}),
    ...(form ? {form} : {}),
    ...(limit ? {limit} : {}),
    ...(search ? {search} : {}),
    ...(sorting ? {sort: sorting.map(s => `${s.field} ${s.order}`).join(', ')} : {}),
    ...(page && limit ? {offset: (page - 1) * limit} : {}),
    ...(paths ? {paths} : {}),
    ...(where ? {where} : {}),
    ...(Array.isArray(relations) ? {relations: relations.length === 0 ? '!' : relations} : {}),
    ...(filter ? {filter} : {}),
    ...(keys ? {keys} : {}),
    ...(constriction ? {constriction} : {})
  }
)

export const requestQueryToUrlParams = queryObject =>
  _reduce(queryObject, (result, value, key) => {
    let add = {}
    if (key === 'conditions') {
      add = flattenObjectValues(value)
    } else {
      add['_' + key] = Array.isArray(value) ? value.join(',') : value
    }

    return {
      ...result,
      ...add
    }
  }, {})

export const flattenObjectValues = value =>
  _reduce(value, (result, value, key) => ({
    ...result,
    [key]: _isObject(value) && value.value ? value.value : value
  }), {})

/**
 * Helper to fetch information about the currently logged in user including username and active business unit.
 */
export function* fetchPrincipal() {
  const cachedPrincipal = cache.get('session', 'principal')
  if (cachedPrincipal !== undefined) {
    return cachedPrincipal
  }

  const principalResponse = yield call(requestSaga, 'principals')
  const {username, businessUnit: currentBusinessUnit} = principalResponse.body

  const principal = {
    username,
    currentBusinessUnit
  }

  yield cache.add('session', 'principal', principal)

  return principal
}
<commit_msg>fix(app-extension): remove brackets from cache id<commit_after>import _reduce from 'lodash/reduce'
import _isObject from 'lodash/isObject'
import {call} from 'redux-saga/effects'
import {cache} from 'tocco-util'
import _get from 'lodash/get'

import {requestSaga} from './rest'

/**
 * Helper to fetch a single entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntity(entityName, key, query, transformer = json => json) {
  const requestQuery = yield call(buildRequestQuery, query)
  const options = {
    method: 'GET',
    queryParams: {
      ...requestQueryToUrlParams(requestQuery),
      _permissions: true,
      _omitLinks: true
    }
  }

  const resp = yield call(requestSaga, `entities/2.0/${entityName}/${key}`, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch the default-display of an entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param type {String} type of the display, default display if none passed
 */
export function* fetchDisplay(entityName, key, type) {
  return _get(yield fetchDisplays({[entityName]: [key]}, type), `${entityName}.${key}`, null)
}

/**
 * Helper to fetch display-expressions of a form for a list of entities
 *
 * @param formName {String} Name of the form
 * @param scope {String} Requested form scope e.g. update or list
 * @param entityKeys {Array} List of entity keys
 * @param displayExpressionFields {Array} List of desired display-expression fields
 */
export function* fetchDisplayExpressions(formName, scope, entityKeys, displayExpressionFields) {
  const options = {
    method: 'GET',
    queryParams: {
      _keys: entityKeys.join(','),
      _paths: displayExpressionFields.join(',')
    }
  }

  const response = yield call(requestSaga, `forms/${formName}_${scope}/display-expressions`, options)

  return response.body.displayExpressions.reduce((acc, val) => ({...acc, [val.key]: val.displayExpressions}), {})
}

/**
 * Helper to fetch the default-display of an entities.
 *
 * @param request {Object} Object containing model and keys of desired entities e.g. {User: ["123"], Gender: ["1", "2"]}
 * @param type {String} type of the display, default display if none passed
 */
export function* fetchDisplays(request, type) {
  const currentDisplays = Object.entries(request).map(([model, keys]) => ({
    model,
    keys: keys.filter(key => cache.get('display', `${model}.${key}${type ? `.${type}` : ''}`) === undefined),
    displays: keys.map(key => ({key, display: cache.get('display', `${model}.${key}${type ? `.${type}` : ''}`)}))
      .filter(value => value.display !== undefined)
  }))

  const loadedDisplays = yield loadDisplays(currentDisplays, type)

  return currentDisplays.reduce((acc, {model, displays}) => ({
    ...acc,
    [model]: {
      ...acc[model],
      ...(displays.reduce((acc, {key, display}) => ({
        ...acc,
        [key]: display
      }), {}))
    }
  }), loadedDisplays)
}

function* loadDisplays(currentDisplays, type) {
  const keysToLoad = currentDisplays.filter(({keys}) => keys.length > 0).map(({model, keys}) => ({model, keys}))
  if (keysToLoad.length > 0) {
    const options = {
      method: 'POST',
      body: {data: keysToLoad}
    }
    const response = yield call(requestSaga, `entities/2.0/displays${type ? `/${type}` : ''}`, options)

    const loadedDisplays = response.body.data.reduce((acc, value) => (
      {
        ...acc,
        [value.model]: value.values.reduce((acc, value) => ({...acc, [value.key]: value.display}), {})
      }
    ), {})
    Object.entries(loadedDisplays).forEach(([entityName, values]) => {
      Object.entries(values).forEach(([key, display]) => {
        cache.add('display', `${entityName}.${key}${type ? `.${type}` : ''}`, display)
      })
    })
    return loadedDisplays
  } else {
    return {}
  }
}

/**
 * Fetch amount of entities
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/count
 */
export function* fetchEntityCount(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {}
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = (endpoint || `entities/2.0/${entityName}`) + '/count'

  const options = {
    method,
    ...(method === 'GET' ? {queryParams: requestQueryToUrlParams(requestQuery)} : {body: requestQuery})
  }

  const response = yield call(requestSaga, resource, options)
  return response.body.count
}

/**
 * Helper to fetch entities.
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/search
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntities(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {},
  transformer = defaultEntityTransformer
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = endpoint || `entities/2.0/${entityName}${method === 'POST' ? '/search' : ''}`

  const options = {
    method,
    queryParams: {
      _omitLinks: true,
      ...(method === 'GET' && requestQueryToUrlParams(requestQuery))
    },
    ...(method === 'POST' && {body: requestQuery})
  }

  const resp = yield call(requestSaga, resource, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch forms.
 * @param formName {String} Name of the requested form
 * @param scope {String} Requested form scope e.g. update or list
 * @param allowNotFound {Boolean} If true and the form does not exist null is returned.
 *                                Otherwise an exception will be thrown.
 */
export function* fetchForm(formName, scope, allowNotFound = false) {
  const request = `${formName}/${scope}`
  const cachedForm = cache.get('form', request)
  if (cachedForm !== undefined) {
    return cachedForm
  }

  const options = {
    ...(allowNotFound && {acceptedStatusCodes: [404]})
  }

  const response = yield call(requestSaga, `forms/${request}`, options)

  if (allowNotFound && response.status === 404) {
    cache.add('form', request, null)
    return null
  }

  const form = yield call(defaultFormTransformer, response.body)
  cache.add('form', request, form)
  return form
}

/**
 * Helper to fetch filters of an entity
 * @param entityName {String} Name of the  entity
 */
export function* fetchSearchFilters(entityName) {
  const response = yield call(requestSaga, `client/searchfilters/${entityName}`)
  return response.body.filters
}

/**
 * Helper to fetch models.
 * @param entityName {String} Name of the entity you like to fetch the model
 */
export function* fetchModel(entityName, transformer = defaultModelTransformer) {
  const cachedModel = cache.get('model', entityName)
  if (cachedModel) {
    return cachedModel
  }

  const resp = yield call(requestSaga, `entities/${entityName}/model`)
  const model = yield call(transformer, resp.body)
  cache.add('model', entityName, model)
  return model
}

export const defaultModelTransformer = json => {
  const model = {
    name: json.name,
    label: json.label,
    paths: {}
  }
  json.fields.forEach(field => {
    model.paths[field.fieldName] = {
      ...field
    }
  })

  json.relations.forEach(relation => {
    model.paths[relation.relationName] = {
      type: 'relation',
      ...relation
    }
  })
  return model
}

export const defaultFormTransformer = json => (json.form)

export const defaultEntityTransformer = json => (json.data)

/**
 * Function that converts a query object into request query object that can be attached to a request.
 * Some options get converted or calculated and other removed if there are undefined.
 *
 * @param options {Object} An object which can contain the following options:
 * - conditions {Object} Object that can contain search fields. Each field
 * - fields {Array} Fields that should be returned
 * - form {String} Name of the form, needed to resolve display expressions and such
 * - limit {Object} Maximum amount of entities to be retrieved
 * - search {Object} Fulltext search on entity
 * - sorting {Array} Array of objects containing a field and order String. e.g. [{field: 'firstname', order: 'asc'}]
 * - page {Number} Current page, needed to calculate offset. Default is undefined which means no offset.
 * - paths {Array} Paths that should be returned
 * - where {String} TQL query
 * - relations {String} Relations that should be returned
 * - filters {Array} List of filter names to be applied
 * - constriction {String} Id of the constriction that should be applied
 */
export const buildRequestQuery = ({
  conditions,
  fields,
  form,
  limit,
  search,
  sorting,
  page,
  paths,
  where,
  relations,
  filter,
  keys,
  constriction
} = {}) => (
  {
    ...(conditions ? {conditions} : {}),
    ...(Array.isArray(fields) ? {fields: fields.length === 0 ? '!' : fields} : {}),
    ...(form ? {form} : {}),
    ...(limit ? {limit} : {}),
    ...(search ? {search} : {}),
    ...(sorting ? {sort: sorting.map(s => `${s.field} ${s.order}`).join(', ')} : {}),
    ...(page && limit ? {offset: (page - 1) * limit} : {}),
    ...(paths ? {paths} : {}),
    ...(where ? {where} : {}),
    ...(Array.isArray(relations) ? {relations: relations.length === 0 ? '!' : relations} : {}),
    ...(filter ? {filter} : {}),
    ...(keys ? {keys} : {}),
    ...(constriction ? {constriction} : {})
  }
)

export const requestQueryToUrlParams = queryObject =>
  _reduce(queryObject, (result, value, key) => {
    let add = {}
    if (key === 'conditions') {
      add = flattenObjectValues(value)
    } else {
      add['_' + key] = Array.isArray(value) ? value.join(',') : value
    }

    return {
      ...result,
      ...add
    }
  }, {})

export const flattenObjectValues = value =>
  _reduce(value, (result, value, key) => ({
    ...result,
    [key]: _isObject(value) && value.value ? value.value : value
  }), {})

/**
 * Helper to fetch information about the currently logged in user including username and active business unit.
 */
export function* fetchPrincipal() {
  const cachedPrincipal = cache.get('session', 'principal')
  if (cachedPrincipal !== undefined) {
    return cachedPrincipal
  }

  const principalResponse = yield call(requestSaga, 'principals')
  const {username, businessUnit: currentBusinessUnit} = principalResponse.body

  const principal = {
    username,
    currentBusinessUnit
  }

  yield cache.add('session', 'principal', principal)

  return principal
}
<|endoftext|>


<commit_before>
/*
#     CloudBoost - Core Engine that powers Bakend as a Service
#     (c) 2014 HackerBay, Inc.
#     CloudBoost may be freely distributed under the Apache 2 License
*/

module.exports = function (){

    //Add Items to the cache.
    global.app.put('/cache/:appId/:name/:key', function(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var key =        req.params.key;
        var item =       req.body.item;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
          if(isMasterKey){
            global.cacheService.put(appId, cacheName, key, item).then(function(item){
                console.log('+++ PUT Success +++');
                console.log(item);

                //convert number to string because express res.send() considers sending numbber as HTTP Status Code
                if(typeof item === "number"){
                    item = item.toString();
                }

                res.status(200).send(item);
            }).catch(function(err){
                console.log('++++++ PUT Error +++++++');
                console.log(err);
                res.status(400).send(err);
            });
        }else{
             res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
     });

     global.apiTracker.log(appId,"Cache / Item / Save", req.url,sdk);

    });

    //Delete Cache
    global.app.delete('/cache/:appId/:name', _deleteCache);
    global.app.put('/cache/:appId/:name', _deleteCache);

    function _deleteCache(req, res){
        var appId =       req.params.appId;
        var cacheName =   req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteCache(appId, cacheName).then(function(cache){
                    console.log('+++ CACHE DELETE Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function(err){
                    console.log('++++++ CACHE DELETE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Delete", req.url,sdk);
    }

    //delete item.
    global.app.delete('/cache/:appId/:name/item/:key', _deleteItem);
    global.app.put('/cache/:appId/:name/item/:key', _deleteItem);

    function _deleteItem(req, res){
        var appId =       req.params.appId;
        var cacheName =   req.params.name;
        var key = req.params.key;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteItem(appId, cacheName,key).then(function(item){
                    console.log('+++ ITEM DELETE Success +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function(err){
                    console.log('++++++ ITEM DELETE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Item  / Delete", req.url,sdk);
    }

    //Create a Cache
    global.app.post('/cache/:appId/:name/create', function (req, res) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.create(appId, cacheName).then(function (cache) {
                    console.log('+++ CACHE Create Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function (err) {
                    console.log('++++++ CACHE Create Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Create", req.url,sdk);
    });

    //Clear Cache
    global.app.delete('/cache/:appId/:name/clear', _clearCache);
    global.app.put('/cache/:appId/:name/clear/items', _clearCache);

    function _clearCache(req, res) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.clearCache(appId, cacheName).then(function (cache) {
                    console.log('+++ CACHE Clear Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function (err) {
                    console.log('++++++ CACHE Clear Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Clear", req.url,sdk);
    }

    //get single item from a cache.
    global.app.post('/cache/:appId/:name/:key/item', _getItem);
    global.app.get('/cache/:appId/:name/:key/item', _getItem);

    //getb all items from a cache.
    global.app.post('/cache/:appId/:name/items', _getAllItems);
    global.app.get('/cache/:appId/:name/items', _getAllItems);

    //get cache info.
    global.app.post('/cache/:appId/:name', _getInfo);
    global.app.get('/cache/:appId/:name', _getInfo);

    //get all app cache info.
    global.app.post('/cache/:appId', _getAllAppCache);
    global.app.get('/cache/:appId', _getAllAppCache);

    //get items count.
    global.app.post('/cache/:appId/:name/items/count', _getItemsCount);
    global.app.get('/cache/:appId/:name/items/count', _getItemsCount);

    //Delete All Caches
    global.app.delete('/cache/:appId', _deleteAllCache);
    global.app.put('/cache/:appId', _deleteAllCache);

    function _deleteAllCache(req, res){
        var appId = req.params.appId;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteAllAppCache(appId).then(function(cache){
                    console.log('+++ DELETE ALL APP CACHE Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function(err){
                    console.log('++++++ DELETE ALL APP CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
           res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / DeleteAll", req.url,sdk);
    }

    function _getItem(req, res, next){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var key =        req.params.key;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getItem(appId, cacheName, key).then(function(item){
                    console.log('+++ GET CACHE ITEM Success +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function(err){
                    console.log('++++++ GET CACHE ITEM  Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
            res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / Item / Get", req.url,sdk);
    };

    function _getItemsCount(req, res, next) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var key = req.params.key;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.getItemsCount(appId, cacheName, key).then(function (item) {
                    console.log('+++ Get Items count +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function (err) {
                    console.log('+++ Get Items count +++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / Item / Count", req.url,sdk);
    };

    function _getCache(req, res, next){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getCache(appId, cacheName).then(function(cache){
                    console.log('+++ GET CACHE Success +++');
                    console.log(cache);
                    res.status(200).send(cache);
                }).catch(function(err){
                    console.log('++++++ GET CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
            res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / Get", req.url,sdk);
    };

    function _getAllAppCache(req, res, next){
        var appId =     req.params.appId;
        var appKey =    req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getAllAppCache(appId).then(function(caches){
                    console.log('+++ GET ALL APP CACHE Success +++');
                    console.log(caches);
                    res.status(200).send(caches);
                }).catch(function(err){
                    console.log('++++++ GET ALL CACHE APP Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / GetAll", req.url,sdk);
    };

    function _getAllItems(req, res, next){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey    =  req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getAllItems(appId, cacheName).then(function(items){
                    console.log('+++ GET ALL CACHE Success +++');
                    console.log(items);
                    res.status(200).json(items);
                }).catch(function(err){
                    console.log('++++++ GET ALL CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / Item/ GetAll", req.url,sdk);
    };

    function _getInfo(req, res, next){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getInfo(appId, cacheName).then(function(info){
                    console.log('+++ GET CACHE INFO Success +++');
                    console.log(info);
                    res.status(200).json(info);
                }).catch(function(err){
                    console.log('++++++ GET CACHE INFO  Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / GetInfo", req.url,sdk);
    };

};<commit_msg>api/cache/CloudCache.js<commit_after>
/*
#     CloudBoost - Core Engine that powers Bakend as a Service
#     (c) 2014 HackerBay, Inc.
#     CloudBoost may be freely distributed under the Apache 2 License
*/

module.exports = function (){

    //Add Items to the cache.
    global.app.put('/cache/:appId/:name/:key', function(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var key =        req.params.key;
        var item =       req.body.item;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
          if(isMasterKey){
            global.cacheService.put(appId, cacheName, key, item).then(function(item){
                console.log('+++ PUT Success +++');
                console.log(item);

                //convert number to string because express res.send() considers sending numbber as HTTP Status Code
                if(typeof item === "number"){
                    item = item.toString();
                }

                res.status(200).send(item);
            }).catch(function(err){
                console.log('++++++ PUT Error +++++++');
                console.log(err);
                res.status(400).send(err);
            });
        }else{
             res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
     });

     global.apiTracker.log(appId,"Cache / Item / Save", req.url,sdk);

    });

    //Delete Cache
    global.app.delete('/cache/:appId/:name', _deleteCache);
    global.app.put('/cache/:appId/:name', _deleteCache);

    function _deleteCache(req, res){
        var appId =       req.params.appId;
        var cacheName =   req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteCache(appId, cacheName).then(function(cache){
                    console.log('+++ CACHE DELETE Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function(err){
                    console.log('++++++ CACHE DELETE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Delete", req.url,sdk);
    }

    //delete item.
    global.app.delete('/cache/:appId/:name/item/:key', _deleteItem);
    global.app.put('/cache/:appId/:name/item/:key', _deleteItem);

    function _deleteItem(req, res){
        var appId =       req.params.appId;
        var cacheName =   req.params.name;
        var key = req.params.key;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteItem(appId, cacheName,key).then(function(item){
                    console.log('+++ ITEM DELETE Success +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function(err){
                    console.log('++++++ ITEM DELETE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Item  / Delete", req.url,sdk);
    }

    //Create a Cache
    global.app.post('/cache/:appId/:name/create', function (req, res) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.create(appId, cacheName).then(function (cache) {
                    console.log('+++ CACHE Create Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function (err) {
                    console.log('++++++ CACHE Create Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Create", req.url,sdk);
    });

    //Clear Cache
    global.app.delete('/cache/:appId/:name/clear', _clearCache);
    global.app.put('/cache/:appId/:name/clear/items', _clearCache);

    function _clearCache(req, res) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.clearCache(appId, cacheName).then(function (cache) {
                    console.log('+++ CACHE Clear Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function (err) {
                    console.log('++++++ CACHE Clear Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key.");
            }
        });

        global.apiTracker.log(appId,"Cache / Clear", req.url,sdk);
    }

    //get single item from a cache.
    global.app.post('/cache/:appId/:name/:key/item', _getItem);
    global.app.get('/cache/:appId/:name/:key/item', _getItem);

    //getb all items from a cache.
    global.app.post('/cache/:appId/:name/items', _getAllItems);
    global.app.get('/cache/:appId/:name/items', _getAllItems);

    //get cache info.
    global.app.post('/cache/:appId/:name', _getInfo);
    global.app.get('/cache/:appId/:name', _getInfo);

    //get all app cache info.
    global.app.post('/cache/:appId', _getAllAppCache);
    global.app.get('/cache/:appId', _getAllAppCache);

    //get items count.
    global.app.post('/cache/:appId/:name/items/count', _getItemsCount);
    global.app.get('/cache/:appId/:name/items/count', _getItemsCount);

    //Delete All Caches
    global.app.delete('/cache/:appId', _deleteAllCache);
    global.app.put('/cache/:appId', _deleteAllCache);

    function _deleteAllCache(req, res){
        var appId = req.params.appId;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.deleteAllAppCache(appId).then(function(cache){
                    console.log('+++ DELETE ALL APP CACHE Success +++');
                    console.log(cache);
                    res.status(200).json(cache);
                }).catch(function(err){
                    console.log('++++++ DELETE ALL APP CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
           res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / DeleteAll", req.url,sdk);
    }

    function _getItem(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var key =        req.params.key;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getItem(appId, cacheName, key).then(function(item){
                    console.log('+++ GET CACHE ITEM Success +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function(err){
                    console.log('++++++ GET CACHE ITEM  Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
            res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / Item / Get", req.url,sdk);
    };

    function _getItemsCount(req, res) {
        var appId = req.params.appId;
        var cacheName = req.params.name;
        var key = req.params.key;
        var appKey = req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
            if (isMasterKey) {
                global.cacheService.getItemsCount(appId, cacheName, key).then(function (item) {
                    console.log('+++ Get Items count +++');
                    console.log(item);
                    res.status(200).json(item);
                }).catch(function (err) {
                    console.log('+++ Get Items count +++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else {
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / Item / Count", req.url,sdk);
    };

    function _getCache(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getCache(appId, cacheName).then(function(cache){
                    console.log('+++ GET CACHE Success +++');
                    console.log(cache);
                    res.status(200).send(cache);
                }).catch(function(err){
                    console.log('++++++ GET CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
        }else{
            res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
        }
        });

        global.apiTracker.log(appId,"Cache / Get", req.url,sdk);
    };

    function _getAllAppCache(req, res){
        var appId =     req.params.appId;
        var appKey =    req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getAllAppCache(appId).then(function(caches){
                    console.log('+++ GET ALL APP CACHE Success +++');
                    console.log(caches);
                    res.status(200).send(caches);
                }).catch(function(err){
                    console.log('++++++ GET ALL CACHE APP Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            } else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / GetAll", req.url,sdk);
    };

    function _getAllItems(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey    =  req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getAllItems(appId, cacheName).then(function(items){
                    console.log('+++ GET ALL CACHE Success +++');
                    console.log(items);
                    res.status(200).json(items);
                }).catch(function(err){
                    console.log('++++++ GET ALL CACHE Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / Item/ GetAll", req.url,sdk);
    };

    function _getInfo(req, res){
        var appId =      req.params.appId;
        var cacheName =  req.params.name;
        var appKey =     req.body.key;
        var sdk = req.body.sdk || "REST";
        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey){
            if(isMasterKey){
                global.cacheService.getInfo(appId, cacheName).then(function(info){
                    console.log('+++ GET CACHE INFO Success +++');
                    console.log(info);
                    res.status(200).json(info);
                }).catch(function(err){
                    console.log('++++++ GET CACHE INFO  Error +++++++');
                    console.log(err);
                    res.status(400).send(err);
                });
            }else{
                res.status(401).send("Unauthorized access. Cache API's can be used only by using master key. ");
            }
        });

        global.apiTracker.log(appId,"Cache / GetInfo", req.url,sdk);
    };

};<|endoftext|>


<commit_before>import React from 'react';
import { createComponent, border } from 'olymp-fela';
import { Image } from 'olymp-cloudinary';

const Avatar = createComponent(
  ({ theme }) => ({
    float: 'right',
    margin: theme.space2,
    marginRight: 0,
  }),
  ({ className, value }) =>
    <Image className={className} value={value} width={100} ratio={1} avatar />,
  p => Object.keys(p)
);

const H3 = createComponent(
  ({ theme, farbe }) => ({
    borderBottom: border(theme, farbe),
    display: 'inline',
    paddingRight: theme.space1,
  }),
  'h3',
  ({ farbe, ...p }) => Object.keys(p)
);

export default createComponent(
  ({ theme }) => ({
    marginY: theme.space3,
    display: 'block',
    clear: 'both',
  }),
  ({ className, name, bild, beschreibung, farbe }) =>
    (

      <Avatar value={bild} />

{name}

{beschreibung}

),
  p => Object.keys(p)
);
<commit_msg>gz personen lightbox<commit_after>import React from 'react';
import { createComponent, border } from 'olymp-fela';
import { LightboxImage } from 'olymp-cloudinary';

const Avatar = createComponent(
  ({ theme }) => ({
    float: 'right',
    margin: theme.space2,
    marginRight: 0,
  }),
  ({ className, value }) =>
    (<LightboxImage
      className={className}
      value={value}
      width={100}
      ratio={1}
      avatar
    />),
  p => Object.keys(p)
);

const H3 = createComponent(
  ({ theme, farbe }) => ({
    borderBottom: border(theme, farbe),
    display: 'inline',
    paddingRight: theme.space1,
  }),
  'h3',
  ({ farbe, ...p }) => Object.keys(p)
);

export default createComponent(
  ({ theme }) => ({
    marginY: theme.space3,
    display: 'block',
    clear: 'both',
  }),
  ({ className, name, bild, beschreibung, farbe }) =>
    (

      <Avatar value={bild} />

        {name}

        {beschreibung}

),
  p => Object.keys(p)
);
<|endoftext|>


<commit_before>const
  Promise = require( 'promise' ),
  path = require( 'path' ),
  bcrypt = require( 'bcrypt' ),
  debug = require( 'debug' )( 'authController' );

module.exports = function( app ) {
  const
    Model = app.models.user,
    user = require( '../lib/mongoose' )( Model ),
    ROOT_PATH = process.env.PWD;

  function renderLogin( req, res ) {
    res.sendFile( path.join( ROOT_PATH, 'app/src/views/login.html' ) );
  }

  function signin( req, res ) {
    const authData = req.body;

    Promise.resolve( authData )
      .then( validateEmail )
      .then( validatePassword )
      .then( findUser )
      .then( authUser )
      .then( createSession.bind( null, req ) )
      .then( _user => res.status( 200 ).json( _user ) )
      .catch( error => res.status( 500 ).send( { message: error.message, stack: error.stack } ) );

    function validateEmail( _authData ) {
      if ( !( _authData && _authData.email ) ) {
        throw new Error( 'A propriedade email é obrigatória' );
      }

      return _authData;
    }

    function validatePassword( _authData ) {
      if ( !authData.password ) {
        throw new Error( 'A propriedade password é obrigatória' );
      }

      return _authData;
    }

    function findUser( _authData ) {
      return new Promise(( resolve, reject ) => {
        user.get( { email: _authData.email, active: true } )
          .then( _user => {
            if ( !_user ) throw new Error( 'Usuário não existe' );

            resolve( _user );
          })
          .catch( reject );
      });
    }
    /**
     *
     * @param {Object} _user
     */
    function authUser( _user ) {
      return new Promise(( resolve, reject ) => {
        bcrypt.compare( authData.password, _user.password )
          .then( isAuthenticated => {
            if ( !isAuthenticated ) throw new Error( 'Senha do usuário está incorreta.' );
            _user.isAuthenticated = isAuthenticated;
            resolve( _user )
          })
          .catch( reject );
      });
    }

    function createSession( req, _user ) {
      delete _user.password;
      req.session.user = _user;

      return  _user;
    }
  }

  return {
    renderLogin,
    signin
  }
}
<commit_msg>[UPDATE]: Adicionado método signout.<commit_after>const
  Promise = require( 'promise' ),
  path = require( 'path' ),
  bcrypt = require( 'bcrypt' ),
  debug = require( 'debug' )( 'authController' );

module.exports = function( app ) {
  const
    Model = app.models.user,
    user = require( '../lib/mongoose' )( Model ),
    ROOT_PATH = process.env.PWD;

  function renderLogin( req, res ) {
    res.sendFile( path.join( ROOT_PATH, 'app/src/views/login.html' ) );
  }

  function signin( req, res ) {
    const authData = req.body;

    Promise.resolve( authData )
      .then( validateEmail )
      .then( validatePassword )
      .then( findUser )
      .then( authUser )
      .then( createSession.bind( null, req ) )
      .then( _user => res.status( 200 ).json( _user ) )
      .catch( error => res.status( 500 ).send( { message: error.message, stack: error.stack } ) );

    function validateEmail( _authData ) {
      if ( !( _authData && _authData.email ) ) {
        throw new Error( 'A propriedade email é obrigatória' );
      }

      return _authData;
    }

    function validatePassword( _authData ) {
      if ( !authData.password ) {
        throw new Error( 'A propriedade password é obrigatória' );
      }

      return _authData;
    }

    function findUser( _authData ) {
      return new Promise(( resolve, reject ) => {
        user.get( { email: _authData.email, active: true } )
          .then( _user => {
            if ( !_user ) throw new Error( 'Usuário não existe' );

            resolve( _user );
          })
          .catch( reject );
      });
    }
    /**
     *
     * @param {Object} _user
     */
    function authUser( _user ) {
      return new Promise( ( resolve, reject ) => {
        bcrypt.compare( authData.password, _user.password )
          .then( isAuthenticated => {
            if ( !isAuthenticated ) throw new Error( 'Senha do usuário está incorreta.' );
            _user.isAuthenticated = isAuthenticated;
            resolve( _user )
          })
          .catch( reject );
      });
    }

    function createSession( req, _user ) {
      delete _user.password;
      req.session.user = _user;

      return  _user;
    }
  }

  function signout( req, res, next ) {
    if ( req.session.user ) {
      req.session.destroy( error => {
        if ( error ) return res.status( 500 ).send( { error } );
        res.redirect( '/auth/signin' );
      });
    }
  }

  return {
    renderLogin,
    signin,
    signout
  }
}
<|endoftext|>


<commit_before>var secrets = require('./config/secrets');
var getDropletStats = require('./droplet_stats');
var User = require('./models/User');

var mongoose = require('mongoose');
mongoose.connect(secrets.db);

var DigitalOceanAPI = require('digitalocean-api');
var api = new DigitalOceanAPI(secrets.digitalocean.client_id, secrets.digitalocean.api_key);

var _ = require('underscore');

var checkServers = function () {
  console.log( '| Doing Server Check' );
  User.find( '', function(err,users) {
    if (err) return err;
    var starbound_servers = [];
    _.each(users, function(user,i) {
      // console.log(user);
      if( user.servers[0] != undefined ) {
        starbound_servers.push( user.servers[0] );
      }
      return false;
    });
    console.log( '| Servers' );

    api.dropletGetAll(function(err,droplets){
      if (err) return err;
      _.each(droplets, function(droplet,i) {
        if( _.contains( starbound_servers, droplet.id ) ) {
          console.log( droplet.name, droplet.id );
          // starbound.today Droplets
          getDropletStats( droplet );
        }
      });
    });

  });
}

setInterval( checkServers(), 15 * 60 * 1000 );
<commit_msg>monitor logging<commit_after>var secrets = require('./config/secrets');
var getDropletStats = require('./droplet_stats');
var User = require('./models/User');

var mongoose = require('mongoose');
mongoose.connect(secrets.db);

var DigitalOceanAPI = require('digitalocean-api');
var api = new DigitalOceanAPI(secrets.digitalocean.client_id, secrets.digitalocean.api_key);

var fs = require('fs');
var _ = require('underscore');

var checkServers = function () {
  console.log( '| Doing Server Check' );
  User.find( '', function(err,users) {
    if (err) return err;
    var starbound_servers = [];
    _.each(users, function(user,i) {
      // console.log(user);
      if( user.servers[0] != undefined ) {
        starbound_servers.push( user.servers[0] );
      }
      return false;
    });
    console.log( '| Servers' );

    api.dropletGetAll(function(err,droplets){
      if (err) return err;
      _.each(droplets, function(droplet,i) {
        if( _.contains( starbound_servers, droplet.id ) ) {
          console.log( droplet.name, droplet.id );
          // starbound.today Droplets
          var data = getDropletStats( droplet );
          data.name = droplet.name;
          data.id = droplet.id;
          data.time = new Date();
          fs.appendFile('./server-monitor.log', data, function (err) {
            console.log( 'Ran 15 min check' );
          });
        }
      });
    });

  });
}

setInterval( checkServers(), 15 * 60 * 1000 );
<|endoftext|>


<commit_before>const ip = require('ip');
const webpack = require('webpack');
const getPort = require('get-port');
const { resolve } = require('path');
const clear = require('console-clear');
const { writeFile } = require('../../fs');
const { bold, red, green, magenta } = require('kleur');
const DevServer = require('webpack-dev-server');
const clientConfig = require('./webpack-client-config');
const serverConfig = require('./webpack-server-config');
const transformConfig = require('./transform-config');
const { error, isDir, warn } = require('../../util');

async function devBuild(env) {
	let config = await clientConfig(env);

	await transformConfig(env, config);

	let userPort =
		parseInt(process.env.PORT || config.devServer.port, 10) || 8080;
	let port = await getPort({ port: userPort });

	let compiler = webpack(config);
	return new Promise((res, rej) => {
		compiler.hooks.emit.tapAsync('CliDevPlugin', (compilation, callback) => {
			let missingDeps = compilation.missingDependencies;
			let nodeModulesPath = resolve(__dirname, '../../../node_modules');

			// ...tell webpack to watch node_modules recursively until they appear.
			if (
				Array.from(missingDeps).some(
					file => file.indexOf(nodeModulesPath) !== -1
				)
			) {
				compilation.contextDependencies.push(nodeModulesPath);
			}

			callback();
		});

		compiler.hooks.done.tap('CliDevPlugin', stats => {
			let devServer = config.devServer;
			let protocol = process.env.HTTPS || devServer.https ? 'https' : 'http';
			let host = process.env.HOST || devServer.host || 'localhost';

			let serverAddr = `${protocol}://${host}:${bold(port)}`;
			let localIpAddr = `${protocol}://${ip.address()}:${bold(port)}`;

			if (env['clear']) clear(true);

			if (stats.hasErrors()) {
				process.stdout.write(red('Build failed!\n\n'));
			} else {
				process.stdout.write(green('Compiled successfully!\n\n'));

				if (userPort !== port) {
					process.stdout.write(
						`Port ${bold(userPort)} is in use, using ${bold(port)} instead\n\n`
					);
				}
				process.stdout.write('You can view the application in browser.\n\n');
				process.stdout.write(`${bold('Local:')}            ${serverAddr}\n`);
				process.stdout.write(`${bold('On Your Network:')}  ${localIpAddr}\n`);
			}

			showStats(stats);
		});

		compiler.hooks.failed.tap('CliDevPlugin', rej);

		let c = Object.assign({}, config.devServer, {
			stats: { colors: true },
		});

		let server = new DevServer(compiler, c);
		server.listen(port);
		res(server);
	});
}

async function prodBuild(env) {
	let config = await clientConfig(env);
	await transformConfig(env, config);

	if (env.prerender) {
		let ssrConfig = serverConfig(env);
		await transformConfig(env, ssrConfig, true);
		let serverCompiler = webpack(ssrConfig);
		await runCompiler(serverCompiler);
	}

	let clientCompiler = webpack(config);
	let stats = await runCompiler(clientCompiler);

	// Timeout for plugins that work on `after-emit` event of webpack
	await new Promise(r => setTimeout(r, 20));

	return showStats(stats);
}

function runCompiler(compiler) {
	return new Promise((res, rej) => {
		compiler.run((err, stats) => {
			showStats(stats);

			if (err || (stats && stats.hasErrors())) {
				rej(red('Build failed! ' + (err || '')));
			}

			res(stats);
		});
	});
}

function showStats(stats) {
	if (stats) {
		if (stats.hasErrors()) {
			allFields(stats, 'errors')
				.map(stripLoaderPrefix)
				.forEach(msg => error(msg));
		}

		if (stats.hasWarnings()) {
			allFields(stats, 'warnings')
				.map(stripLoaderPrefix)
				.forEach(msg => warn(msg));
		}
	}

	return stats;
}

function writeJsonStats(stats) {
	let outputPath = resolve(process.cwd(), 'stats.json');
	let jsonStats = stats.toJson({
		json: true,
		chunkModules: true,
		source: false,
	});

	function strip(stats) {
		stats.modules.forEach(stripLoaderFromModuleNames);
		stats.chunks.forEach(c => {
			(
				c.modules ||
				(c.mapModules != null ? c.mapModules(Object) : c.getModules())
			).forEach(stripLoaderFromModuleNames);
		});
		if (stats.children) stats.children.forEach(strip);
	}

	strip(jsonStats);

	return writeFile(outputPath, JSON.stringify(jsonStats)).then(() => {
		process.stdout.write('\nWebpack output stats generated.\n\n');
		process.stdout.write('You can upload your stats.json to:\n');
		process.stdout.write(
			'- https://chrisbateman.github.io/webpack-visualizer/\n'
		);
		process.stdout.write('- https://webpack.github.io/analyse/\n');
	});
}

function allFields(stats, field, fields = [], name = null) {
	const info = stats.toJson({
		errors: true,
		warnings: false,
		errorDetails: false,
	});
	const addCompilerPrefix = msg =>
		name ? bold(magenta(name + ': ')) + msg : msg;
	if (field === 'errors' && stats.hasErrors()) {
		fields = fields.concat(info.errors.map(addCompilerPrefix));
	}
	if (field === 'warnings' && stats.hasWarnings()) {
		fields = fields.concat(info.warnings.map(addCompilerPrefix));
	}
	if (stats.compilation.children) {
		stats.compilation.children.forEach((child, index) => {
			const name = child.name || `Child Compiler ${index + 1}`;
			const stats = child.getStats();
			fields = allFields(stats, field, fields, name);
		});
	}
	return fields;
}

const keysToNormalize = [
	'issuer',
	'issuerName',
	'identifier',
	'name',
	'module',
	'moduleName',
	'moduleIdentifier',
];

/** Removes all loaders from any resource identifiers found in a string */
function stripLoaderPrefix(str) {
	if (typeof str === 'string') {
		str = str.replace(
			/(?:(\()|(^|\b|@))(\.\/~|\.{0,2}\/(?:[^\s]+\/)?node_modules)\/\w+-loader(\/[^?!]+)?(\?\?[\w_.-]+|\?({[\s\S]*?})?)?!/g,
			'$1'
		);
		str = str.replace(/(\.?\.?(?:\/[^/ ]+)+)\s+\(\1\)/g, '$1');
		str = replaceAll(str, process.cwd(), '.');
		return str;
	}
	return str;
}

// https://gist.github.com/developit/1a40a6fee65361d1182aaa22ab8c334c
function replaceAll(str, find, replace) {
	let s = '',
		index,
		next;
	while (~(next = str.indexOf(find, index))) {
		s += str.substring(index, next) + replace;
		index = next + find.length;
	}
	return s + str.substring(index);
}

function stripLoaderFromModuleNames(m) {
	for (let key in m) {
		if (
			Object.prototype.hasOwnProperty.call(m, key) &&
			m[key] != null &&
			~keysToNormalize.indexOf(key)
		) {
			m[key] = stripLoaderPrefix(m[key]);
		}
	}

	if (m.reasons) {
		m.reasons.forEach(stripLoaderFromModuleNames);
	}

	return m;
}

module.exports = function(env, watch = false) {
	env.isProd = env.production; // shorthand
	env.isWatch = !!watch; // use HMR?
	env.cwd = resolve(env.cwd || process.cwd());

	// env.src='src' via `build` default
	let src = resolve(env.cwd, env.src);
	env.src = isDir(src) ? src : env.cwd;

	// attach sourcing helper
	env.source = dir => resolve(env.src, dir);

	// determine build-type to run
	return (watch ? devBuild : prodBuild)(env);
};

module.exports.writeJsonStats = writeJsonStats;
<commit_msg>fix for 939<commit_after>const ip = require('ip');
const webpack = require('webpack');
const getPort = require('get-port');
const { resolve } = require('path');
const clear = require('console-clear');
const { writeFile } = require('../../fs');
const { bold, red, green, magenta } = require('kleur');
const DevServer = require('webpack-dev-server');
const clientConfig = require('./webpack-client-config');
const serverConfig = require('./webpack-server-config');
const transformConfig = require('./transform-config');
const { error, isDir, warn } = require('../../util');

async function devBuild(env) {
	let config = await clientConfig(env);

	await transformConfig(env, config);

	let userPort =
		parseInt(process.env.PORT || config.devServer.port, 10) || 8080;
	let port = await getPort({ port: userPort });

	let compiler = webpack(config);
	return new Promise((res, rej) => {
		compiler.hooks.emit.tapAsync('CliDevPlugin', (compilation, callback) => {
			let missingDeps = compilation.missingDependencies;
			let nodeModulesPath = resolve(__dirname, '../../../node_modules');

			// ...tell webpack to watch node_modules recursively until they appear.
			if (
				Array.from(missingDeps).some(
					file => file.indexOf(nodeModulesPath) !== -1
				)
			) {
				compilation.contextDependencies.push(nodeModulesPath);
			}

			callback();
		});

		compiler.hooks.done.tap('CliDevPlugin', stats => {
			let devServer = config.devServer;
			let protocol = process.env.HTTPS || devServer.https ? 'https' : 'http';
			let host = process.env.HOST || devServer.host || 'localhost';

			let serverAddr = `${protocol}://${host}:${bold(port)}`;
			let localIpAddr = `${protocol}://${ip.address()}:${bold(port)}`;

			if (env['clear']) clear(true);

			if (stats.hasErrors()) {
				process.stdout.write(red('Build failed!\n\n'));
			} else {
				process.stdout.write(green('Compiled successfully!\n\n'));

				if (userPort !== port) {
					process.stdout.write(
						`Port ${bold(userPort)} is in use, using ${bold(port)} instead\n\n`
					);
				}
				process.stdout.write('You can view the application in browser.\n\n');
				process.stdout.write(`${bold('Local:')}            ${serverAddr}\n`);
				process.stdout.write(`${bold('On Your Network:')}  ${localIpAddr}\n`);
			}

			showStats(stats, false);
		});

		compiler.hooks.failed.tap('CliDevPlugin', rej);

		let c = Object.assign({}, config.devServer, {
			stats: { colors: true },
		});

		let server = new DevServer(compiler, c);
		server.listen(port);
		res(server);
	});
}

async function prodBuild(env) {
	let config = await clientConfig(env);
	await transformConfig(env, config);

	if (env.prerender) {
		let ssrConfig = serverConfig(env);
		await transformConfig(env, ssrConfig, true);
		let serverCompiler = webpack(ssrConfig);
		await runCompiler(serverCompiler);
	}

	let clientCompiler = webpack(config);
	let stats = await runCompiler(clientCompiler);

	// Timeout for plugins that work on `after-emit` event of webpack
	await new Promise(r => setTimeout(r, 20));

	return showStats(stats, true);
}

function runCompiler(compiler) {
	return new Promise((res, rej) => {
		compiler.run((err, stats) => {
			showStats(stats, true);

			if (err || (stats && stats.hasErrors())) {
				rej(red('Build failed! ' + (err || '')));
			}

			res(stats);
		});
	});
}

function showStats(stats, isProd) {
	if (stats) {
		if (stats.hasErrors()) {
			allFields(stats, 'errors')
				.map(stripLoaderPrefix)
				.forEach(msg => error(msg, isProd ? 1 : 0));
		}

		if (stats.hasWarnings()) {
			allFields(stats, 'warnings')
				.map(stripLoaderPrefix)
				.forEach(msg => warn(msg));
		}
	}

	return stats;
}

function writeJsonStats(stats) {
	let outputPath = resolve(process.cwd(), 'stats.json');
	let jsonStats = stats.toJson({
		json: true,
		chunkModules: true,
		source: false,
	});

	function strip(stats) {
		stats.modules.forEach(stripLoaderFromModuleNames);
		stats.chunks.forEach(c => {
			(
				c.modules ||
				(c.mapModules != null ? c.mapModules(Object) : c.getModules())
			).forEach(stripLoaderFromModuleNames);
		});
		if (stats.children) stats.children.forEach(strip);
	}

	strip(jsonStats);

	return writeFile(outputPath, JSON.stringify(jsonStats)).then(() => {
		process.stdout.write('\nWebpack output stats generated.\n\n');
		process.stdout.write('You can upload your stats.json to:\n');
		process.stdout.write(
			'- https://chrisbateman.github.io/webpack-visualizer/\n'
		);
		process.stdout.write('- https://webpack.github.io/analyse/\n');
	});
}

function allFields(stats, field, fields = [], name = null) {
	const info = stats.toJson({
		errors: true,
		warnings: false,
		errorDetails: false,
	});
	const addCompilerPrefix = msg =>
		name ? bold(magenta(name + ': ')) + msg : msg;
	if (field === 'errors' && stats.hasErrors()) {
		fields = fields.concat(info.errors.map(addCompilerPrefix));
	}
	if (field === 'warnings' && stats.hasWarnings()) {
		fields = fields.concat(info.warnings.map(addCompilerPrefix));
	}
	if (stats.compilation.children) {
		stats.compilation.children.forEach((child, index) => {
			const name = child.name || `Child Compiler ${index + 1}`;
			const stats = child.getStats();
			fields = allFields(stats, field, fields, name);
		});
	}
	return fields;
}

const keysToNormalize = [
	'issuer',
	'issuerName',
	'identifier',
	'name',
	'module',
	'moduleName',
	'moduleIdentifier',
];

/** Removes all loaders from any resource identifiers found in a string */
function stripLoaderPrefix(str) {
	if (typeof str === 'string') {
		str = str.replace(
			/(?:(\()|(^|\b|@))(\.\/~|\.{0,2}\/(?:[^\s]+\/)?node_modules)\/\w+-loader(\/[^?!]+)?(\?\?[\w_.-]+|\?({[\s\S]*?})?)?!/g,
			'$1'
		);
		str = str.replace(/(\.?\.?(?:\/[^/ ]+)+)\s+\(\1\)/g, '$1');
		str = replaceAll(str, process.cwd(), '.');
		return str;
	}
	return str;
}

// https://gist.github.com/developit/1a40a6fee65361d1182aaa22ab8c334c
function replaceAll(str, find, replace) {
	let s = '',
		index,
		next;
	while (~(next = str.indexOf(find, index))) {
		s += str.substring(index, next) + replace;
		index = next + find.length;
	}
	return s + str.substring(index);
}

function stripLoaderFromModuleNames(m) {
	for (let key in m) {
		if (
			Object.prototype.hasOwnProperty.call(m, key) &&
			m[key] != null &&
			~keysToNormalize.indexOf(key)
		) {
			m[key] = stripLoaderPrefix(m[key]);
		}
	}

	if (m.reasons) {
		m.reasons.forEach(stripLoaderFromModuleNames);
	}

	return m;
}

module.exports = function(env, watch = false) {
	env.isProd = env.production; // shorthand
	env.isWatch = !!watch; // use HMR?
	env.cwd = resolve(env.cwd || process.cwd());

	// env.src='src' via `build` default
	let src = resolve(env.cwd, env.src);
	env.src = isDir(src) ? src : env.cwd;

	// attach sourcing helper
	env.source = dir => resolve(env.src, dir);

	// determine build-type to run
	return (watch ? devBuild : prodBuild)(env);
};

module.exports.writeJsonStats = writeJsonStats;
<|endoftext|>


<commit_before>import _ from 'underscore';

import PaginateWidget from 'girder/views/widgets/PaginateWidget';
import View from 'girder/views/View';
import { defineFlags, formatDate, DATE_SECOND } from 'girder/misc';
import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import { SORT_DESC } from 'girder/constants';

import JobCollection from '../collections/JobCollection';
import JobListWidgetTemplate from '../templates/jobListWidget.pug';
import JobStatus from '../JobStatus';

import '../stylesheets/jobListWidget.styl';

var JobListWidget = View.extend({
    events: {
        'click .g-job-checkbox-menu input': function (e) {
            var cid = $(e.target).attr('cid');
            this.trigger('g:jobClicked', this.collection.get(cid));
        }
    },

    initialize: function (settings) {
        var currentUser = getCurrentUser();
        this.columns = settings.columns || this.columnEnum.COLUMN_ALL;
        this.filter = settings.filter || {
            userId: currentUser.id
        };
        this.typeFilter = {};
        this.statusFilter = {};

        this.collection = new JobCollection();
        this.collection.sortField = settings.sortField || 'created';
        this.collection.sortDir = settings.sortDir || SORT_DESC;
        this.collection.pageLimit = settings.pageLimit || this.collection.pageLimit;

        this.collection.on('g:changed', function () {
            this.render();
        }, this).fetch(this.filter);

        this.showHeader = _.has(settings, 'showHeader') ? settings.showHeader : true;
        this.showPaging = _.has(settings, 'showPaging') ? settings.showPaging : true;
        this.linkToJob = _.has(settings, 'linkToJob') ? settings.linkToJob : true;
        this.triggerJobClick = _.has(settings, 'triggerJobClick') ? settings.triggerJobClick : false;

        this.paginateWidget = new PaginateWidget({
            collection: this.collection,
            parentView: this
        });

        eventStream.on('g:event.job_status', this._statusChange, this);

        this.filterTypeMenuWidget = new girder.views.jobs.CheckBoxMenuWidget({
            title: 'Type',
            values: [],
            parentView: this
        });

        this.filterTypeMenuWidget.on('g:triggerCheckBoxMenuChanged', function (e) {
            this.typeFilter = _.clone(e);
            this.render();
        }, this);

        this.filterStatusMenuWidget = new girder.views.jobs.CheckBoxMenuWidget({
            title: 'Status',
            values: [],
            parentView: this
        });

        this.filterStatusMenuWidget.on('g:triggerCheckBoxMenuChanged', function (e) {
            this.statusFilter = _.clone(e);
            this.render();
        }, this);
    },

    columnEnum: defineFlags([
        'COLUMN_STATUS_ICON',
        'COLUMN_TITLE',
        'COLUMN_UPDATED',
        'COLUMN_OWNER',
        'COLUMN_TYPE',
        'COLUMN_STATUS'
    ], 'COLUMN_ALL'),

    render: function () {
        var jobs = this._filterJobs(this.collection.toArray()), types, states;

        this.$el.html(JobListWidgetTemplate({
            jobs: this.collection.toArray(),
            showHeader: this.showHeader,
            columns: this.columns,
            columnEnum: this.columnEnum,
            linkToJob: this.linkToJob,
            triggerJobClick: this.triggerJobClick,
            JobStatus: JobStatus,
            formatDate: formatDate,
            DATE_SECOND: DATE_SECOND
        }));

        types = _.uniq(this.collection.toArray().map(function (job) {
            return job.attributes.type;
        }));

        this._updateFilter(this.typeFilter, types);
        this.filterTypeMenuWidget.setValues(this.typeFilter);

        states = _.uniq(this.collection.toArray().map(function (job) {
            return girder.jobs_JobStatus.text(job.attributes.status);
        }));
        this._updateFilter(this.statusFilter, states);
        this.filterStatusMenuWidget.setValues(this.statusFilter);

        this.filterTypeMenuWidget.setElement(this.$('.g-job-type-header')).render();
        this.filterStatusMenuWidget.setElement(this.$('.g-job-status-header')).render();

        if (this.showPaging) {
            this.paginateWidget.setElement(this.$('.g-job-pagination')).render();
        }

        return this;
    },

    _statusChange: function (event) {
        var job = event.data,
            tr = this.$('tr[g-job-id=' + job._id + ']');

        if (!tr.length) {
            return;
        }

        if (this.columns & this.columnEnum.COLUMN_STATUS_ICON) {
            tr.find('td.g-status-icon-container').attr('status', job.status)
              .find('i').removeClass().addClass(JobStatus.icon(job.status));
        }
        if (this.columns & this.columnEnum.COLUMN_STATUS) {
            tr.find('td.g-job-status-cell').text(JobStatus.text(job.status));
        }
        if (this.columns & this.columnEnum.COLUMN_UPDATED) {
            tr.find('td.g-job-updated-cell').text(
                formatDate(job.updated, DATE_SECOND));
        }

        tr.addClass('g-highlight');

        window.setTimeout(function () {
            tr.removeClass('g-highlight');
        }, 1000);
    },
    _filterJobs: function (jobs) {
        var filterJobs = [];

        // Include all jobs that have matching state or type field.
        filterJobs = this.collection.filter(_.bind(function (job) {
            return ((_.isEmpty(this.typeFilter) || _.isUndefined(job.attributes.type) ||
                        this.typeFilter[job.attributes.type]) &&
                    (_.isEmpty(this.statusFilter) || _.isUndefined(job.attributes.status) ||
                        this.statusFilter[girder.jobs_JobStatus.text(job.attributes.status)]));
        }, this));

        return filterJobs;
    },
    _updateFilter: function (filter, newValues) {
        // We need to work out what keys have been removed or added
        // so we can update the filter. We do this rather than created
        // a new filter inorder to preserve the existing user selections.
        var currentValues = _.keys(filter), added, removed;
        added = _.difference(newValues, currentValues);
        removed = _.difference(currentValues, newValues);

        _.each(added, function (value) {
            filter[value] = true;
        });
        _.each(removed, function (value) {
            delete filter[value];
        });
    }
});

export default JobListWidget;
<commit_msg>Handle jobs without a type defined<commit_after>import _ from 'underscore';

import PaginateWidget from 'girder/views/widgets/PaginateWidget';
import View from 'girder/views/View';
import { defineFlags, formatDate, DATE_SECOND } from 'girder/misc';
import eventStream from 'girder/utilities/EventStream';
import { getCurrentUser } from 'girder/auth';
import { SORT_DESC } from 'girder/constants';

import JobCollection from '../collections/JobCollection';
import JobListWidgetTemplate from '../templates/jobListWidget.pug';
import JobStatus from '../JobStatus';

import '../stylesheets/jobListWidget.styl';

var JobListWidget = View.extend({
    events: {
        'click .g-job-checkbox-menu input': function (e) {
            var cid = $(e.target).attr('cid');
            this.trigger('g:jobClicked', this.collection.get(cid));
        }
    },

    initialize: function (settings) {
        var currentUser = getCurrentUser();
        this.columns = settings.columns || this.columnEnum.COLUMN_ALL;
        this.filter = settings.filter || {
            userId: currentUser.id
        };
        this.typeFilter = {};
        this.statusFilter = {};

        this.collection = new JobCollection();
        this.collection.sortField = settings.sortField || 'created';
        this.collection.sortDir = settings.sortDir || SORT_DESC;
        this.collection.pageLimit = settings.pageLimit || this.collection.pageLimit;

        this.collection.on('g:changed', function () {
            this.render();
        }, this).fetch(this.filter);

        this.showHeader = _.has(settings, 'showHeader') ? settings.showHeader : true;
        this.showPaging = _.has(settings, 'showPaging') ? settings.showPaging : true;
        this.linkToJob = _.has(settings, 'linkToJob') ? settings.linkToJob : true;
        this.triggerJobClick = _.has(settings, 'triggerJobClick') ? settings.triggerJobClick : false;

        this.paginateWidget = new PaginateWidget({
            collection: this.collection,
            parentView: this
        });

        eventStream.on('g:event.job_status', this._statusChange, this);

        this.filterTypeMenuWidget = new girder.views.jobs.CheckBoxMenuWidget({
            title: 'Type',
            values: [],
            parentView: this
        });

        this.filterTypeMenuWidget.on('g:triggerCheckBoxMenuChanged', function (e) {
            this.typeFilter = _.clone(e);
            this.render();
        }, this);

        this.filterStatusMenuWidget = new girder.views.jobs.CheckBoxMenuWidget({
            title: 'Status',
            values: [],
            parentView: this
        });

        this.filterStatusMenuWidget.on('g:triggerCheckBoxMenuChanged', function (e) {
            this.statusFilter = _.clone(e);
            this.render();
        }, this);
    },

    columnEnum: defineFlags([
        'COLUMN_STATUS_ICON',
        'COLUMN_TITLE',
        'COLUMN_UPDATED',
        'COLUMN_OWNER',
        'COLUMN_TYPE',
        'COLUMN_STATUS'
    ], 'COLUMN_ALL'),

    render: function () {
        var jobs = this._filterJobs(this.collection.toArray()), types, states;

        this.$el.html(JobListWidgetTemplate({
            jobs: this.collection.toArray(),
            showHeader: this.showHeader,
            columns: this.columns,
            columnEnum: this.columnEnum,
            linkToJob: this.linkToJob,
            triggerJobClick: this.triggerJobClick,
            JobStatus: JobStatus,
            formatDate: formatDate,
            DATE_SECOND: DATE_SECOND
        }));

        types = _.uniq(this.collection.toArray().map(function (job) {
            return job.attributes.type ? job.attributes.type : '';
        }));

        this._updateFilter(this.typeFilter, types);
        this.filterTypeMenuWidget.setValues(this.typeFilter);

        states = _.uniq(this.collection.toArray().map(function (job) {
            return girder.jobs_JobStatus.text(job.attributes.status);
        }));
        this._updateFilter(this.statusFilter, states);
        this.filterStatusMenuWidget.setValues(this.statusFilter);

        this.filterTypeMenuWidget.setElement(this.$('.g-job-type-header')).render();
        this.filterStatusMenuWidget.setElement(this.$('.g-job-status-header')).render();

        if (this.showPaging) {
            this.paginateWidget.setElement(this.$('.g-job-pagination')).render();
        }

        return this;
    },

    _statusChange: function (event) {
        var job = event.data,
            tr = this.$('tr[g-job-id=' + job._id + ']');

        if (!tr.length) {
            return;
        }

        if (this.columns & this.columnEnum.COLUMN_STATUS_ICON) {
            tr.find('td.g-status-icon-container').attr('status', job.status)
              .find('i').removeClass().addClass(JobStatus.icon(job.status));
        }
        if (this.columns & this.columnEnum.COLUMN_STATUS) {
            tr.find('td.g-job-status-cell').text(JobStatus.text(job.status));
        }
        if (this.columns & this.columnEnum.COLUMN_UPDATED) {
            tr.find('td.g-job-updated-cell').text(
                formatDate(job.updated, DATE_SECOND));
        }

        tr.addClass('g-highlight');

        window.setTimeout(function () {
            tr.removeClass('g-highlight');
        }, 1000);
    },
    _filterJobs: function (jobs) {
        var filterJobs = [];
        // Include all jobs that match the type and status filters. Jobs that
        // have an undefined type are mapped to '', this is added as a filter
        // option for the user to select.
        filterJobs = this.collection.filter(_.bind(function (job) {
            return ((_.isEmpty(this.typeFilter) ||
                        this.typeFilter[job.attributes.type ? job.attributes.type : '']) &&
                    (_.isEmpty(this.statusFilter) ||
                        this.statusFilter[girder.jobs_JobStatus.text(job.attributes.status)]));
        }, this));

        return filterJobs;
    },
    _updateFilter: function (filter, newValues) {
        // We need to work out what keys have been removed or added
        // so we can update the filter. We do this rather than created
        // a new filter inorder to preserve the existing user selections.
        var currentValues = _.keys(filter), added, removed;
        added = _.difference(newValues, currentValues);
        removed = _.difference(currentValues, newValues);

        _.each(added, function (value) {
            filter[value] = true;
        });
        _.each(removed, function (value) {
            delete filter[value];
        });
    }
});

export default JobListWidget;
<|endoftext|>


<commit_before>module.exports = function(Meteor) {
	var _ = Meteor.underscore;
	var Tracker = Meteor.Tracker;
	var ReactiveObjectMap;

	ReactiveObjectMap = function() {
		if (!(this instanceof ReactiveObjectMap))
		// called without `new`
			return new ReactiveObjectMap();

		this._map = {};
		this._dep = new Tracker.Dependency;
	};

	ReactiveObjectMap.prototype.assign = function(collection, iteratee) {
		this._map = _.indexBy(collection, iteratee);
		this._dep.changed();
	};

	ReactiveObjectMap.prototype.get = function(key) {
		if (Tracker.active)
			this._dep.depend();
		return this._map[key];
	};

	ReactiveObjectMap.prototype.set = function(key, value) {
		var old = this._map[key];
		this._map[key] = value;
		if (old !== value)
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.has = function(key) {
		if (Tracker.active)
			this._dep.depend();
		return this._map.hasOwnProperty(key);
	};

	ReactiveObjectMap.prototype.clear = function(key, value) {
		this._map = {};
		this._dep.changed();
	};

	ReactiveObjectMap.prototype.delete = function(key, value) {
		if (delete this._map[key])
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.setAttribute = function(key, attr, value) {
		var old = this._map[key][attr];
		this._map[key][attr] = value;
		if (old !== value)
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.getAttribute = function(key, attr) {
		if (Tracker.active)
			this._dep.depend();
		return this._map[key][attr];
	};

	ReactiveObjectMap.prototype.keys = function() {
		if (Tracker.active)
			this._dep.depend();
		return Object.keys(this._map);
	};

	ReactiveObjectMap.prototype.values = function() {
		if (Tracker.active)
			this._dep.depend();
		return _.values(this._map);
	};

	ReactiveObjectMap.prototype.filter = function(predicate) {
		if (Tracker.active)
			this._dep.depend();
		return _.filter(this._map,predicate);
	};

	ReactiveObjectMap.prototype.sortBy = function(iteratee) {
		if (Tracker.active)
			this._dep.depend();
		return _.sortBy(this._map,iteratee);
	};

	ReactiveObjectMap.prototype.map = function(iteratee) {
		if (Tracker.active)
			this._dep.depend();
		return _.map(this._map,iteratee);
	};

	ReactiveObjectMap.prototype.size = function() {
		if (Tracker.active)
			this._dep.depend();
		return Object.keys(this._map).length;
	};

	ReactiveObjectMap.prototype.toString = function() {
		return 'ReactiveObjectMap{' + this.get() + '}';
	};

	ReactiveObjectMap.prototype._numListeners = function() {
		// Tests want to know.
		// Accesses a private field of Tracker.Dependency.
		var count = 0;
		for (var id in this._dep._dependentsById)
			count++;
		return count;
	};

	Meteor.ReactiveObjectMap = ReactiveObjectMap;

	module.exports = ReactiveObjectMap;
};
<commit_msg>get() returns object map<commit_after>module.exports = function(Meteor) {
	var _ = Meteor.underscore;
	var Tracker = Meteor.Tracker;
	var ReactiveObjectMap;

	ReactiveObjectMap = function() {
		if (!(this instanceof ReactiveObjectMap))
		// called without `new`
			return new ReactiveObjectMap();

		this._map = {};
		this._dep = new Tracker.Dependency;
	};

	ReactiveObjectMap.prototype.assign = function(collection, iteratee) {
		this._map = _.indexBy(collection, iteratee);
		this._dep.changed();
	};

	ReactiveObjectMap.prototype.get = function(key) {
		if (Tracker.active)
			this._dep.depend();
		if (key)
			return this._map[key];
		else
			return this._map;
	};

	ReactiveObjectMap.prototype.set = function(key, value) {
		var old = this._map[key];
		this._map[key] = value;
		if (old !== value)
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.has = function(key) {
		if (Tracker.active)
			this._dep.depend();
		return this._map.hasOwnProperty(key);
	};

	ReactiveObjectMap.prototype.clear = function(key, value) {
		this._map = {};
		this._dep.changed();
	};

	ReactiveObjectMap.prototype.delete = function(key, value) {
		if (delete this._map[key])
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.setAttribute = function(key, attr, value) {
		var old = this._map[key][attr];
		this._map[key][attr] = value;
		if (old !== value)
			this._dep.changed();
	};

	ReactiveObjectMap.prototype.getAttribute = function(key, attr) {
		if (Tracker.active)
			this._dep.depend();
		return this._map[key][attr];
	};

	ReactiveObjectMap.prototype.keys = function() {
		if (Tracker.active)
			this._dep.depend();
		return Object.keys(this._map);
	};

	ReactiveObjectMap.prototype.values = function() {
		if (Tracker.active)
			this._dep.depend();
		return _.values(this._map);
	};

	ReactiveObjectMap.prototype.filter = function(predicate) {
		if (Tracker.active)
			this._dep.depend();
		return _.filter(this._map,predicate);
	};

	ReactiveObjectMap.prototype.sortBy = function(iteratee) {
		if (Tracker.active)
			this._dep.depend();
		return _.sortBy(this._map,iteratee);
	};

	ReactiveObjectMap.prototype.map = function(iteratee) {
		if (Tracker.active)
			this._dep.depend();
		return _.map(this._map,iteratee);
	};

	ReactiveObjectMap.prototype.size = function() {
		if (Tracker.active)
			this._dep.depend();
		return Object.keys(this._map).length;
	};

	ReactiveObjectMap.prototype.toString = function() {
		return 'ReactiveObjectMap{' + this.get() + '}';
	};

	ReactiveObjectMap.prototype._numListeners = function() {
		// Tests want to know.
		// Accesses a private field of Tracker.Dependency.
		var count = 0;
		for (var id in this._dep._dependentsById)
			count++;
		return count;
	};

	Meteor.ReactiveObjectMap = ReactiveObjectMap;

	module.exports = ReactiveObjectMap;
};
<|endoftext|>