<commit_before>import * as utils from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import {BANNER} from '../src/mediaTypes.js';
const BIDDER_CODE = 'zeta_global';
const PREBID_DEFINER_ID = '44253'
const ENDPOINT_URL = 'https://prebid.rfihub.com/prebid';
const USER_SYNC_URL = 'https://p.rfihub.com/cm?in=1&pub=';
const DEFAULT_CUR = 'USD';
const TTL = 200;
const NET_REV = true;

export const spec = {
  code: BIDDER_CODE,
  supportedMediaTypes: [BANNER],

  /**
     * Determines whether or not the given bid request is valid.
     *
     * @param {BidRequest} bid The bid params to validate.
     * @return boolean True if this is a valid bid, and false otherwise.
     */
  isBidRequestValid: function(bid) {
    // check for all required bid fields
    if (!(bid &&
          bid.bidId &&
          bid.params)) {
      utils.logWarn('Invalid bid request - missing required bid data');
      return false;
    }

    if (!(bid.params.user &&
          bid.params.user.buyeruid)) {
      utils.logWarn('Invalid bid request - missing required user data');
      return false;
    }

    if (!(bid.params.device &&
          bid.params.device.ip)) {
      utils.logWarn('Invalid bid request - missing required device data');
      return false;
    }

    if (!(bid.params.device.geo &&
          bid.params.device.geo.country)) {
      utils.logWarn('Invalid bid request - missing required geo data');
      return false;
    }

    if (!bid.params.definerId) {
      utils.logWarn('Invalid bid request - missing required definer data');
      return false;
    }

    return true;
  },

  /**
     * Make a server request from the list of BidRequests.
     *
     * @param {Bids[]} validBidRequests - an array of bidRequest objects
     * @param {BidderRequest} bidderRequest - master bidRequest object
     * @return ServerRequest Info describing the request to the server.
     */
  buildRequests: function(validBidRequests, bidderRequest) {
    const secure = 1; // treat all requests as secure
    const request = validBidRequests[0];
    const params = request.params;
    let impData = {
      id: request.bidId,
      secure: secure,
      banner: buildBanner(request)
    };
    let payload = {
      id: bidderRequest.auctionId,
      imp: [impData],
      site: params.site ? params.site : {},
      app: params.app ? params.app : {},
      device: params.device ? params.device : {},
      user: params.user ? params.user : {},
      at: params.at,
      tmax: params.tmax,
      wseat: params.wseat,
      bseat: params.bseat,
      allimps: params.allimps,
      cur: [DEFAULT_CUR],
      wlang: params.wlang,
      bcat: params.bcat,
      badv: params.badv,
      bapp: params.bapp,
      source: params.source ? params.source : {},
      regs: params.regs ? params.regs : {},
      ext: params.ext ? params.ext : {}
    };

    payload.device.ua = navigator.userAgent;
    payload.device.ip = navigator.ip;
    payload.site.page = bidderRequest.refererInfo.referer;
    payload.site.mobile = /(ios|ipod|ipad|iphone|android)/i.test(navigator.userAgent) ? 1 : 0;
    payload.ext.definerId = params.definerId;

    if (params.test) {
      payload.test = params.test;
    }
    if (request.gdprConsent) {
      payload.regs.ext = Object.assign(
        payload.regs.ext,
        {gdpr: request.gdprConsent.gdprApplies === true ? 1 : 0}
      );
    }
    if (request.gdprConsent && request.gdprConsent.gdprApplies) {
      payload.user.ext = Object.assign(
        payload.user.ext,
        {consent: request.gdprConsent.consentString}
      );
    }
    const postUrl = params.definerId !== PREBID_DEFINER_ID ? ENDPOINT_URL.concat('/', params.definerId) : ENDPOINT_URL;
    return {
      method: 'POST',
      url: postUrl,
      data: JSON.stringify(payload),
    };
  },

  /**
     * Unpack the response from the server into a list of bids.
     *
     * @param {ServerResponse} serverResponse A successful response from the server.
     * @param bidRequest The payload from the server's response.
     * @return {Bid[]} An array of bids which were nested inside the server.
     */
  interpretResponse: function(serverResponse, bidRequest) {
    let bidResponse = [];
    if (Object.keys(serverResponse.body).length !== 0) {
      let zetaResponse = serverResponse.body;
      let zetaBid = zetaResponse.seatbid[0].bid[0];
      let bid = {
        requestId: zetaBid.impid,
        cpm: zetaBid.price,
        currency: zetaResponse.cur,
        width: zetaBid.w,
        height: zetaBid.h,
        ad: zetaBid.adm,
        ttl: TTL,
        creativeId: zetaBid.crid,
        netRevenue: NET_REV
      };
      bidResponse.push(bid);
    }
    return bidResponse;
  },

  /**
     * Register the user sync pixels which should be dropped after the auction.
     *
     * @param {SyncOptions} syncOptions Which user syncs are allowed?
     * @param {ServerResponse[]} serverResponses List of server's responses.
     * @param gdprConsent The GDPR consent parameters
     * @param uspConsent The USP consent parameters
     * @return {UserSync[]} The user syncs which should be dropped.
     */
  getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {
    const syncs = [];
    if (syncOptions.iframeEnabled) {
      syncs.push({
        type: 'iframe',
        url: USER_SYNC_URL.concat(PREBID_DEFINER_ID)
      });
    }
    return syncs;
  }
}

function buildBanner(request) {
  let sizes = request.sizes;
  if (request.mediaTypes &&
    request.mediaTypes.banner &&
    request.mediaTypes.banner.sizes) {
    sizes = request.mediaTypes.banner.sizes;
  }
  return {
    w: sizes[0][0],
    h: sizes[0][1]
  };
}

registerBidder(spec);
<commit_msg>Zeta Bid Adapter: update Cookie Sync URL (#7090)<commit_after>import * as utils from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import {BANNER} from '../src/mediaTypes.js';
const BIDDER_CODE = 'zeta_global';
const PREBID_DEFINER_ID = '44253'
const ENDPOINT_URL = 'https://prebid.rfihub.com/prebid';
const USER_SYNC_URL = 'https://p.rfihub.com/cm?in=1&pub=';
const DEFAULT_CUR = 'USD';
const TTL = 200;
const NET_REV = true;

export const spec = {
  code: BIDDER_CODE,
  supportedMediaTypes: [BANNER],

  /**
     * Determines whether or not the given bid request is valid.
     *
     * @param {BidRequest} bid The bid params to validate.
     * @return boolean True if this is a valid bid, and false otherwise.
     */
  isBidRequestValid: function(bid) {
    // check for all required bid fields
    if (!(bid &&
          bid.bidId &&
          bid.params)) {
      utils.logWarn('Invalid bid request - missing required bid data');
      return false;
    }

    if (!(bid.params.user &&
          bid.params.user.buyeruid)) {
      utils.logWarn('Invalid bid request - missing required user data');
      return false;
    }

    if (!(bid.params.device &&
          bid.params.device.ip)) {
      utils.logWarn('Invalid bid request - missing required device data');
      return false;
    }

    if (!(bid.params.device.geo &&
          bid.params.device.geo.country)) {
      utils.logWarn('Invalid bid request - missing required geo data');
      return false;
    }

    if (!bid.params.definerId) {
      utils.logWarn('Invalid bid request - missing required definer data');
      return false;
    }

    return true;
  },

  /**
     * Make a server request from the list of BidRequests.
     *
     * @param {Bids[]} validBidRequests - an array of bidRequest objects
     * @param {BidderRequest} bidderRequest - master bidRequest object
     * @return ServerRequest Info describing the request to the server.
     */
  buildRequests: function(validBidRequests, bidderRequest) {
    const secure = 1; // treat all requests as secure
    const request = validBidRequests[0];
    const params = request.params;
    let impData = {
      id: request.bidId,
      secure: secure,
      banner: buildBanner(request)
    };
    let payload = {
      id: bidderRequest.auctionId,
      imp: [impData],
      site: params.site ? params.site : {},
      app: params.app ? params.app : {},
      device: params.device ? params.device : {},
      user: params.user ? params.user : {},
      at: params.at,
      tmax: params.tmax,
      wseat: params.wseat,
      bseat: params.bseat,
      allimps: params.allimps,
      cur: [DEFAULT_CUR],
      wlang: params.wlang,
      bcat: params.bcat,
      badv: params.badv,
      bapp: params.bapp,
      source: params.source ? params.source : {},
      regs: params.regs ? params.regs : {},
      ext: params.ext ? params.ext : {}
    };

    payload.device.ua = navigator.userAgent;
    payload.device.ip = navigator.ip;
    payload.site.page = bidderRequest.refererInfo.referer;
    payload.site.mobile = /(ios|ipod|ipad|iphone|android)/i.test(navigator.userAgent) ? 1 : 0;
    payload.ext.definerId = params.definerId;

    if (params.test) {
      payload.test = params.test;
    }
    if (request.gdprConsent) {
      payload.regs.ext = Object.assign(
        payload.regs.ext,
        {gdpr: request.gdprConsent.gdprApplies === true ? 1 : 0}
      );
    }
    if (request.gdprConsent && request.gdprConsent.gdprApplies) {
      payload.user.ext = Object.assign(
        payload.user.ext,
        {consent: request.gdprConsent.consentString}
      );
    }
    const postUrl = params.definerId !== PREBID_DEFINER_ID ? ENDPOINT_URL.concat('/', params.definerId) : ENDPOINT_URL;
    return {
      method: 'POST',
      url: postUrl,
      data: JSON.stringify(payload),
    };
  },

  /**
     * Unpack the response from the server into a list of bids.
     *
     * @param {ServerResponse} serverResponse A successful response from the server.
     * @param bidRequest The payload from the server's response.
     * @return {Bid[]} An array of bids which were nested inside the server.
     */
  interpretResponse: function(serverResponse, bidRequest) {
    let bidResponse = [];
    if (Object.keys(serverResponse.body).length !== 0) {
      let zetaResponse = serverResponse.body;
      let zetaBid = zetaResponse.seatbid[0].bid[0];
      let bid = {
        requestId: zetaBid.impid,
        cpm: zetaBid.price,
        currency: zetaResponse.cur,
        width: zetaBid.w,
        height: zetaBid.h,
        ad: zetaBid.adm,
        ttl: TTL,
        creativeId: zetaBid.crid,
        netRevenue: NET_REV
      };
      bidResponse.push(bid);
    }
    return bidResponse;
  },

  /**
   * Register the user sync pixels which should be dropped after the auction.
   *
   * @param {SyncOptions} syncOptions Which user syncs are allowed?
   * @param {ServerResponse[]} serverResponses List of server's responses.
   * @param definerId The calling entity's definer id
   * @param gdprConsent The GDPR consent parameters
   * @param uspConsent The USP consent parameters
   * @return {UserSync[]} The user syncs which should be dropped.
   */
  getUserSyncs: function(syncOptions, serverResponses, definerId, gdprConsent, uspConsent) {
    const syncs = [];
    if (definerId === '' || definerId === null) {
      definerId = PREBID_DEFINER_ID;
    }
    if (syncOptions.iframeEnabled) {
      syncs.push({
        type: 'iframe',
        url: USER_SYNC_URL.concat(definerId)
      });
    }
    return syncs;
  }
}

function buildBanner(request) {
  let sizes = request.sizes;
  if (request.mediaTypes &&
    request.mediaTypes.banner &&
    request.mediaTypes.banner.sizes) {
    sizes = request.mediaTypes.banner.sizes;
  }
  return {
    w: sizes[0][0],
    h: sizes[0][1]
  };
}

registerBidder(spec);
<|endoftext|>


<commit_before>$(document).ready(function() {
    $('form').on('submit', function(event) {
        event.preventDefault();
        submit_form();
    });

    $('a.edit').on('click', function(event) {
        event.preventDefault();
        device = load_device($(this).attr('data-id'));
    });

    $('a.delete').on('click', function(event) {
        event.preventDefault();
        confirm_delete_device($(this).attr('data-id'));
    });
});

function set_errors(errors) {
    $.each(errors, function (name, text) {
        $('form').find('label[for=' + name + ']').first().after(
            '' + text + '');
    });
}

function submit_form() {
    form = $('form');

    form.find('span.error').remove();
    form_error = $('#form-error');
    form_error.slideUp(200, 'easeInQuart');

    var post_data = form.find(':input').serializeArray();
    post_data['csrfmiddlewaretoken'] =
        $('#metadata').attr('data-csrfmiddlewaretoken');

    $('img#loading').css('display', 'inline');
    $.post(document.pathname, post_data, function(data) {
        location.reload();
    }, 'json').fail(function(data) {
        $('img#loading').css('display', 'none');
        if (data.status == 422) {
            set_errors(data.responseJSON);
        } else {
            form_error.html('A server error occurred.');
            form_error.slideDown(200, 'easeInQuart');
        };
    });
}

function load_device(id) {
    $('#form-error').slideUp(200, 'easeInQuart');
    $('#device-list-server-error').slideUp(200, 'easeInQuart');
    $(':input').attr('disabled', false);

    $('#form-title').html('Change a device');

    $.get('/device?id=' + id, function(data) {
        $.each(data, function(name, value) {
            $('form').find('input[name=' + name + ']').val(value);
        });
    }, 'json').fail(function() {
        $('#device-list-server-error').slideDown(200, 'easeInQuart');
    });
}

function confirm_delete_device(id) {
    btn = $('button#deleteDevice');

    btn.attr('data-id', id);

    btn.on('click', function(event) {
        event.preventDefault();
        $('img#loadingDelete').css('display', 'inline');
        delete_device($(this).attr('data-id'));
    });
    $("#deleteDeviceModal").modal();
}

function delete_device(id) {
    $('#device-list-server-error').slideUp(200, 'easeInQuart');

    post_data = {
        'id': id,
        'csrfmiddlewaretoken': $('#metadata').attr('data-csrfmiddlewaretoken')
    };

    $.post('/delete_device', post_data, function(data) {
        location.reload();
    }).fail(function() {
        $('img#loadingDelete').css('display', 'none');
        $('#device-list-server-error').slideDown(200, 'easeInQuart');
    });
}
<commit_msg>Fix whitespace things<commit_after>$(document).ready(function() {
    $('form').on('submit', function(event) {
        event.preventDefault();
        submit_form();
    });

    $('a.edit').on('click', function(event) {
        event.preventDefault();
        device = load_device($(this).attr('data-id'));
    });

    $('a.delete').on('click', function(event) {
        event.preventDefault();
        confirm_delete_device($(this).attr('data-id'));
    });
});

function set_errors(errors) {
    $.each(errors, function (name, text) {
        $('form').find('label[for=' + name + ']').first().after(
            '' + text + '');
    });
}

function submit_form() {
    form = $('form');

    form.find('span.error').remove();
    form_error = $('#form-error');
    form_error.slideUp(200, 'easeInQuart');

    var post_data = form.find(':input').serializeArray();
    post_data['csrfmiddlewaretoken'] =
        $('#metadata').attr('data-csrfmiddlewaretoken');

    $('img#loading').css('display', 'inline');
    $.post(document.pathname, post_data, function(data) {
        location.reload();
    }, 'json').fail(function(data) {
        $('img#loading').css('display', 'none');
        if (data.status == 422) {
            set_errors(data.responseJSON);
        } else {
            form_error.html('A server error occurred.');
            form_error.slideDown(200, 'easeInQuart');
        };
    });
}

function load_device(id) {
    $('#form-error').slideUp(200, 'easeInQuart');
    $('#device-list-server-error').slideUp(200, 'easeInQuart');
    $(':input').attr('disabled', false);

    $('#form-title').html('Change a device');

    $.get('/device?id=' + id, function(data) {
        $.each(data, function(name, value) {
            $('form').find('input[name=' + name + ']').val(value);
        });
    }, 'json').fail(function() {
        $('#device-list-server-error').slideDown(200, 'easeInQuart');
    });
}

function confirm_delete_device(id) {
    btn = $('button#deleteDevice');

    btn.attr('data-id', id);

    btn.on('click', function(event) {
        event.preventDefault();
        $('img#loadingDelete').css('display', 'inline');
        delete_device($(this).attr('data-id'));
    });
    $("#deleteDeviceModal").modal();
}

function delete_device(id) {
    $('#device-list-server-error').slideUp(200, 'easeInQuart');

    post_data = {
        'id': id,
        'csrfmiddlewaretoken': $('#metadata').attr('data-csrfmiddlewaretoken')
    };

    $.post('/delete_device', post_data, function(data) {
        location.reload();
    }).fail(function() {
        $('img#loadingDelete').css('display', 'none');
        $('#device-list-server-error').slideDown(200, 'easeInQuart');
    });
}
<|endoftext|>


<commit_before>/**
 * block ajax
 */

!function(global, $) {
    'use strict';

    function ConcreteFileManager($element, options) {
        'use strict';
        var my = this;
        options = $.extend({
            'mode': 'menu',
            'uploadElement': 'body',
            'bulkParameterName': 'fID'
        }, options);

        my.options = options;
        my._templateFileProgress = _.template('

' +
            '<% if (progress == \'-1\') { %>' +
                '

' +
            '<% } else { %>' +
                '
<div class="progress-bar" style="width: <%=progress%>%;">

' +
                '<% } %>' +
            '

');
        my._templateSearchResultsMenu = _.template(ConcreteFileManagerMenu.get());

        ConcreteAjaxSearch.call(my, $element, options);

        my.setupFileDownloads();
        my.setupFileUploads();
        my.setupEvents();

    }

    ConcreteFileManager.prototype = Object.create(ConcreteAjaxSearch.prototype);

    ConcreteFileManager.prototype.setupFileDownloads = function() {
        var my = this;
        if (!$('#ccm-file-manager-download-target').length) {
            my.$downloadTarget = $('', {
                'name': 'ccm-file-manager-download-target',
                'id': 'ccm-file-manager-download-target'
            }).appendTo(document.body);
        } else {
            my.$downloadTarget = $('#ccm-file-manager-download-target');
        }
    };

    ConcreteFileManager.prototype.setupFileUploads = function() {
        var my = this,
            $fileUploader = $('.ccm-file-manager-upload'),
            args = {
                url: CCM_DISPATCHER_FILENAME + '/ccm/system/file/upload',
                dataType: 'json',
                formData: {'ccm_token': CCM_SECURITY_TOKEN},
                error: function(r) {
                    jQuery.fn.dialog.closeTop();
                    var message = r.responseText;
                    try {
                        message = jQuery.parseJSON(message).errors.join('
');
                    } catch (e) {}
                    ConcreteAlert.dialog('Error', message);
                },
                progressall: function(e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#ccm-file-upload-progress-wrapper').html(my._templateFileProgress({'progress': progress}));
                },
                start: function() {
                    $('#ccm-file-upload-progress-wrapper').remove();
                    $('
', {'id': 'ccm-file-upload-progress-wrapper'}).html(my._templateFileProgress({'progress': -1})).appendTo(document.body);
                    $.fn.dialog.open({
                        title: ccmi18n_filemanager.uploadProgress,
                        width: 400,
                        height: 50,
                        element: $('#ccm-file-upload-progress-wrapper'),
                        modal: true
                    });
                },
                stop: function() {
                    jQuery.fn.dialog.closeTop();
                    my.refreshResults();
                }
            };

        $fileUploader.on('click', function() {
            $(this).find('input').trigger('click');
        });

        $fileUploader.fileupload(args);
    };

    ConcreteFileManager.prototype.setupEvents = function() {
        var my = this;
        ConcreteEvent.subscribe('FileManagerUpdateRequestComplete', function(e) {
            my.refreshResults();
        });
    };

    ConcreteFileManager.prototype.setupStarredResults = function() {
        var my = this;
        my.$element.unbind('.concreteFileManagerStar').on('click.concreteFileManagerStar', 'a[data-search-toggle=star]', function() {
            var $link = $(this);
            var data = {'fID': $(this).attr('data-search-toggle-file-id')};
            my.ajaxUpdate($link.attr('data-search-toggle-url'), data, function(r) {
                if (r.star) {
                    $link.parent().addClass('ccm-file-manager-search-results-star-active');
                } else {
                    $link.parent().removeClass('ccm-file-manager-search-results-star-active');
                }
            });
            return false;
        });
    };

    ConcreteFileManager.prototype.updateResults = function(result) {
        var my = this;
        ConcreteAjaxSearch.prototype.updateResults.call(my, result);
        my.setupStarredResults();
        if (my.options.mode == 'choose') {
            my.$element.unbind('.concreteFileManagerHoverFile');
            my.$element.on('mouseover.concreteFileManagerHoverFile', 'tr[data-file-manager-file]', function() {
                $(this).addClass('ccm-search-select-hover');
            });
            my.$element.on('mouseout.concreteFileManagerHoverFile', 'tr[data-file-manager-file]', function() {
                $(this).removeClass('ccm-search-select-hover');
            });
            my.$element.unbind('.concreteFileManagerChooseFile').on('click.concreteFileManagerChooseFile', 'tr[data-file-manager-file]', function() {
                ConcreteEvent.publish('FileManagerBeforeSelectFile', {fID: $(this).attr('data-file-manager-file')});
                ConcreteEvent.publish('FileManagerSelectFile', {fID: $(this).attr('data-file-manager-file')});
                return false;
            });
        }
    };

    ConcreteFileManager.prototype.handleSelectedBulkAction = function(value, type, $option, $items) {
        var my = this, itemIDs = [];
        $.each($items, function(i, checkbox) {
            itemIDs.push({'name': 'item[]', 'value': $(checkbox).val()});
        });

        if (value == 'download') {
            my.$downloadTarget.get(0).src = CCM_TOOLS_PATH + '/files/download?' + jQuery.param(itemIDs);
        } else {
            ConcreteAjaxSearch.prototype.handleSelectedBulkAction.call(this, value, type, $option, $items);
        }
    };

    ConcreteAjaxSearch.prototype.createMenu = function($selector) {
        var my = this;
        $selector.concreteFileMenu({
            'container': my,
            'menu': $('[data-search-menu=' + $selector.attr('data-launch-search-menu') + ']')
        });
    };

    /**
     * Static Methods
     */
    ConcreteFileManager.launchDialog = function(callback) {
        var w = $(window).width() - 53;

        $.fn.dialog.open({
            width: w,
            height: '100%',
            href: CCM_DISPATCHER_FILENAME + '/ccm/system/dialogs/file/search',
            modal: true,
            title: ccmi18n_filemanager.title,
            onOpen: function() {
                ConcreteEvent.unsubscribe('FileManagerSelectFile');
                ConcreteEvent.subscribe('FileManagerSelectFile', function(e, data) {
                    jQuery.fn.dialog.closeTop();
                    callback(data);
                });
            }
        });
    };

    ConcreteFileManager.getFileDetails = function(fID, callback) {
        $.ajax({
            type: 'post',
            dataType: 'json',
            url: CCM_DISPATCHER_FILENAME + '/ccm/system/file/get_json',
            data: {'fID': fID},
            error: function(r) {
                ConcreteAlert.dialog('Error', r.responseText);
            },
            success: function(r) {
                callback(r);
            }
        });
    };

    var ConcreteFileManagerMenu = {

        get: function() {
            return '
<div class="ccm-popover-file-menu popover fade" data-search-file-menu="<%=item.fID%>" data-search-menu="<%=item.fID%>">' +
                '

' +
                '<% if (typeof(displayClear) != \'undefined\' && displayClear) { %>' +
                '
' + ccmi18n_filemanager.clear + '
' +
                '

' +
                '<% } %>' +
                '<% if (item.canViewFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="false" dialog-append-buttons="true" dialog-width="90%" dialog-height="75%" dialog-title="' + ccmi18n_filemanager.view + '" href="' + CCM_TOOLS_PATH + '/files/view?fID=<%=item.fID%>">' + ccmi18n_filemanager.view + '
' +
                '<% } %>' +
                '
<a href="#" onclick="window.frames[\'ccm-file-manager-download-target\'].location=\'' + CCM_TOOLS_PATH + '/files/download?fID=<%=item.fID%>\'; return false">' + ccmi18n_filemanager.download + '
' +
                '<% if (item.canEditFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="90%" dialog-height="70%" dialog-title="' + ccmi18n_filemanager.edit + '" href="' + CCM_TOOLS_PATH + '/files/edit?fID=<%=item.fID%>">' + ccmi18n_filemanager.edit + '
' +
                '<% } %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="680" dialog-height="450" dialog-title="' + ccmi18n_filemanager.properties + '" href="' + CCM_DISPATCHER_FILENAME + '/ccm/system/dialogs/file/properties?fID=<%=item.fID%>">' + ccmi18n_filemanager.properties + '
' +
                '<% if (item.canReplaceFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="300" dialog-height="320" dialog-title="' + ccmi18n_filemanager.replace + '" href="' + CCM_TOOLS_PATH + '/files/replace?fID=<%=item.fID%>">' + ccmi18n_filemanager.replace + '
' +
                '<% } %>' +
                '<% if (item.canCopyFile) { %>' +
                    '
' + ccmi18n_filemanager.duplicate + '
' +
                '<% } %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="500" dialog-height="400" dialog-title="' + ccmi18n_filemanager.sets + '" href="' + CCM_TOOLS_PATH + '/files/add_to?fID=<%=item.fID%>">' + ccmi18n_filemanager.sets + '
' +
                '<% if (item.canDeleteFile || item.canEditFilePermissions) { %>' +
                    '

' +
                '<% } %>' +
                '<% if (item.canEditFilePermissions) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="520" dialog-height="450" dialog-title="' + ccmi18n_filemanager.permissions + '" href="' + CCM_TOOLS_PATH + '/files/permissions?fID=<%=item.fID%>">' + ccmi18n_filemanager.permissions + '
' +
                '<% } %>' +
                '<% if (item.canDeleteFile) { %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="500" dialog-height="200" dialog-title="' + ccmi18n_filemanager.deleteFile + '" href="' + CCM_TOOLS_PATH + '/files/delete?fID=<%=item.fID%>">' + ccmi18n_filemanager.deleteFile + '
' +
                '<% } %>' +
            '

';
        }
    };

    // jQuery Plugin
    $.fn.concreteFileManager = function(options) {
        return $.each($(this), function(i, obj) {
            new ConcreteFileManager($(this), options);
        });
    };

    global.ConcreteFileManager = ConcreteFileManager;
    global.ConcreteFileManagerMenu = ConcreteFileManagerMenu;

}(window, $);
<commit_msg>Make the progress bar always striped, add a notification that upload completed.<commit_after>/**
 * block ajax
 */

!function(global, $) {
    'use strict';

    function ConcreteFileManager($element, options) {
        'use strict';
        var my = this;
        options = $.extend({
            'mode': 'menu',
            'uploadElement': 'body',
            'bulkParameterName': 'fID'
        }, options);

        my.options = options;
        my._templateFileProgress = _.template('

' +
            '
<div class="progress-bar" style="width: <%=progress%>%;">

' +
            '

');
        my._templateSearchResultsMenu = _.template(ConcreteFileManagerMenu.get());

        ConcreteAjaxSearch.call(my, $element, options);

        my.setupFileDownloads();
        my.setupFileUploads();
        my.setupEvents();

    }

    ConcreteFileManager.prototype = Object.create(ConcreteAjaxSearch.prototype);

    ConcreteFileManager.prototype.setupFileDownloads = function() {
        var my = this;
        if (!$('#ccm-file-manager-download-target').length) {
            my.$downloadTarget = $('', {
                'name': 'ccm-file-manager-download-target',
                'id': 'ccm-file-manager-download-target'
            }).appendTo(document.body);
        } else {
            my.$downloadTarget = $('#ccm-file-manager-download-target');
        }
    };

    ConcreteFileManager.prototype.setupFileUploads = function() {
        var my = this,
            $fileUploader = $('.ccm-file-manager-upload'),
            args = {
                url: CCM_DISPATCHER_FILENAME + '/ccm/system/file/upload',
                dataType: 'json',
                formData: {'ccm_token': CCM_SECURITY_TOKEN},
                error: function(r) {
                    jQuery.fn.dialog.closeTop();
                    var message = r.responseText;
                    try {
                        message = jQuery.parseJSON(message).errors.join('
');
                    } catch (e) {}
                    ConcreteAlert.dialog('Error', message);
                },
                progressall: function(e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#ccm-file-upload-progress-wrapper').html(my._templateFileProgress({'progress': progress}));
                },
                start: function() {
                    $('#ccm-file-upload-progress-wrapper').remove();
                    $('
', {'id': 'ccm-file-upload-progress-wrapper'}).html(my._templateFileProgress({'progress': 100})).appendTo(document.body);
                    $.fn.dialog.open({
                        title: ccmi18n_filemanager.uploadProgress,
                        width: 400,
                        height: 50,
                        element: $('#ccm-file-upload-progress-wrapper'),
                        modal: true
                    });
                },
                stop: function() {
                    jQuery.fn.dialog.closeTop();
                    my.refreshResults();

                    ConcreteAlert.notify({
                        'message': ccmi18n_filemanager.uploadComplete,
                        'title': ccmi18n_filemanager.title
                    });
                }
            };

        $fileUploader.on('click', function() {
            $(this).find('input').trigger('click');
        });

        $fileUploader.fileupload(args);
    };

    ConcreteFileManager.prototype.setupEvents = function() {
        var my = this;
        ConcreteEvent.subscribe('FileManagerUpdateRequestComplete', function(e) {
            my.refreshResults();
        });
    };

    ConcreteFileManager.prototype.setupStarredResults = function() {
        var my = this;
        my.$element.unbind('.concreteFileManagerStar').on('click.concreteFileManagerStar', 'a[data-search-toggle=star]', function() {
            var $link = $(this);
            var data = {'fID': $(this).attr('data-search-toggle-file-id')};
            my.ajaxUpdate($link.attr('data-search-toggle-url'), data, function(r) {
                if (r.star) {
                    $link.parent().addClass('ccm-file-manager-search-results-star-active');
                } else {
                    $link.parent().removeClass('ccm-file-manager-search-results-star-active');
                }
            });
            return false;
        });
    };

    ConcreteFileManager.prototype.updateResults = function(result) {
        var my = this;
        ConcreteAjaxSearch.prototype.updateResults.call(my, result);
        my.setupStarredResults();
        if (my.options.mode == 'choose') {
            my.$element.unbind('.concreteFileManagerHoverFile');
            my.$element.on('mouseover.concreteFileManagerHoverFile', 'tr[data-file-manager-file]', function() {
                $(this).addClass('ccm-search-select-hover');
            });
            my.$element.on('mouseout.concreteFileManagerHoverFile', 'tr[data-file-manager-file]', function() {
                $(this).removeClass('ccm-search-select-hover');
            });
            my.$element.unbind('.concreteFileManagerChooseFile').on('click.concreteFileManagerChooseFile', 'tr[data-file-manager-file]', function() {
                ConcreteEvent.publish('FileManagerBeforeSelectFile', {fID: $(this).attr('data-file-manager-file')});
                ConcreteEvent.publish('FileManagerSelectFile', {fID: $(this).attr('data-file-manager-file')});
                return false;
            });
        }
    };

    ConcreteFileManager.prototype.handleSelectedBulkAction = function(value, type, $option, $items) {
        var my = this, itemIDs = [];
        $.each($items, function(i, checkbox) {
            itemIDs.push({'name': 'item[]', 'value': $(checkbox).val()});
        });

        if (value == 'download') {
            my.$downloadTarget.get(0).src = CCM_TOOLS_PATH + '/files/download?' + jQuery.param(itemIDs);
        } else {
            ConcreteAjaxSearch.prototype.handleSelectedBulkAction.call(this, value, type, $option, $items);
        }
    };

    ConcreteAjaxSearch.prototype.createMenu = function($selector) {
        var my = this;
        $selector.concreteFileMenu({
            'container': my,
            'menu': $('[data-search-menu=' + $selector.attr('data-launch-search-menu') + ']')
        });
    };

    /**
     * Static Methods
     */
    ConcreteFileManager.launchDialog = function(callback) {
        var w = $(window).width() - 53;

        $.fn.dialog.open({
            width: w,
            height: '100%',
            href: CCM_DISPATCHER_FILENAME + '/ccm/system/dialogs/file/search',
            modal: true,
            title: ccmi18n_filemanager.title,
            onOpen: function() {
                ConcreteEvent.unsubscribe('FileManagerSelectFile');
                ConcreteEvent.subscribe('FileManagerSelectFile', function(e, data) {
                    jQuery.fn.dialog.closeTop();
                    callback(data);
                });
            }
        });
    };

    ConcreteFileManager.getFileDetails = function(fID, callback) {
        $.ajax({
            type: 'post',
            dataType: 'json',
            url: CCM_DISPATCHER_FILENAME + '/ccm/system/file/get_json',
            data: {'fID': fID},
            error: function(r) {
                ConcreteAlert.dialog('Error', r.responseText);
            },
            success: function(r) {
                callback(r);
            }
        });
    };

    var ConcreteFileManagerMenu = {

        get: function() {
            return '
<div class="ccm-popover-file-menu popover fade" data-search-file-menu="<%=item.fID%>" data-search-menu="<%=item.fID%>">' +
                '

' +
                '<% if (typeof(displayClear) != \'undefined\' && displayClear) { %>' +
                '
' + ccmi18n_filemanager.clear + '
' +
                '

' +
                '<% } %>' +
                '<% if (item.canViewFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="false" dialog-append-buttons="true" dialog-width="90%" dialog-height="75%" dialog-title="' + ccmi18n_filemanager.view + '" href="' + CCM_TOOLS_PATH + '/files/view?fID=<%=item.fID%>">' + ccmi18n_filemanager.view + '
' +
                '<% } %>' +
                '
<a href="#" onclick="window.frames[\'ccm-file-manager-download-target\'].location=\'' + CCM_TOOLS_PATH + '/files/download?fID=<%=item.fID%>\'; return false">' + ccmi18n_filemanager.download + '
' +
                '<% if (item.canEditFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="90%" dialog-height="70%" dialog-title="' + ccmi18n_filemanager.edit + '" href="' + CCM_TOOLS_PATH + '/files/edit?fID=<%=item.fID%>">' + ccmi18n_filemanager.edit + '
' +
                '<% } %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="680" dialog-height="450" dialog-title="' + ccmi18n_filemanager.properties + '" href="' + CCM_DISPATCHER_FILENAME + '/ccm/system/dialogs/file/properties?fID=<%=item.fID%>">' + ccmi18n_filemanager.properties + '
' +
                '<% if (item.canReplaceFile) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="300" dialog-height="320" dialog-title="' + ccmi18n_filemanager.replace + '" href="' + CCM_TOOLS_PATH + '/files/replace?fID=<%=item.fID%>">' + ccmi18n_filemanager.replace + '
' +
                '<% } %>' +
                '<% if (item.canCopyFile) { %>' +
                    '
' + ccmi18n_filemanager.duplicate + '
' +
                '<% } %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="500" dialog-height="400" dialog-title="' + ccmi18n_filemanager.sets + '" href="' + CCM_TOOLS_PATH + '/files/add_to?fID=<%=item.fID%>">' + ccmi18n_filemanager.sets + '
' +
                '<% if (item.canDeleteFile || item.canEditFilePermissions) { %>' +
                    '

' +
                '<% } %>' +
                '<% if (item.canEditFilePermissions) { %>' +
                    '
<a class="dialog-launch" dialog-modal="true" dialog-width="520" dialog-height="450" dialog-title="' + ccmi18n_filemanager.permissions + '" href="' + CCM_TOOLS_PATH + '/files/permissions?fID=<%=item.fID%>">' + ccmi18n_filemanager.permissions + '
' +
                '<% } %>' +
                '<% if (item.canDeleteFile) { %>' +
                '
<a class="dialog-launch" dialog-modal="true" dialog-width="500" dialog-height="200" dialog-title="' + ccmi18n_filemanager.deleteFile + '" href="' + CCM_TOOLS_PATH + '/files/delete?fID=<%=item.fID%>">' + ccmi18n_filemanager.deleteFile + '
' +
                '<% } %>' +
            '

';
        }
    };

    // jQuery Plugin
    $.fn.concreteFileManager = function(options) {
        return $.each($(this), function(i, obj) {
            new ConcreteFileManager($(this), options);
        });
    };

    global.ConcreteFileManager = ConcreteFileManager;
    global.ConcreteFileManagerMenu = ConcreteFileManagerMenu;

}(window, $);
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/css",
    "firebug/lib/dom",
    "firebug/lib/locale",
    "firebug/lib/options",
    "firebug/chrome/module",
    "firebug/console/commandLine",
],
function(Firebug, FBTrace, Obj, Css, Dom, Locale, Options, Module, CommandLine) {

"use strict";

// ********************************************************************************************* //
// Constants

var TraceError = FBTrace.toError();
var Trace = FBTrace.to("DBG_COMMANDEDITOR");

// ********************************************************************************************* //
// ToggleCommandEditor Implementation

/**
 * @module This module is responsible for toggling visibility of the Command editor.
 *
 * The Command editor should be implemented as a standard side panel, which also
 * allows to have more instances of the editor at the same time.
 *
 * See also related issues:
 * 1) Issue 988: Make the Command Editor independent from the Command Line
 * 2) Issue 6028: Allow to have multiple instances of the Command Editor
 */
var ToggleCommandEditor = Obj.extend(Module,
/** @lends ToggleCommandEditor */
{
    dispatchName: "ToggleCommandEditor",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Module

    initialize: function()
    {
        Module.initialize.apply(this, arguments);

        this.updateButtonState();
        this.updateButtonVisibility();

        // Register a command handlers for XUL buttons dynamically, so we don't have to
        // expose this object into the firebugOverlay.xul scope.
        this.registerListeners();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Framework Events

    showPanel: function(browser, panel)
    {
        if (panel && panel.name == "console")
            this.updateButtonVisibility();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Options

    updateOption: function(name, value)
    {
        if (name == "viewPanelOrient" || name == "commandEditor")
        {
            this.updateButtonState();
            this.updateButtonVisibility();
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // XUL Command

    /**
     * Executed when the user presses 'fbToggleCommandEditor' or 'fbToggleCommandEditor2'
     * button on the toolbar.
     */
    toggle: function()
    {
        if (Trace.active)
        {
            var editorVisible = Options.get("commandEditor");
            Trace.sysout("toggleCommandEditor.toggle; prev value: " + editorVisible);
        }

        Options.togglePref("commandEditor");

        Firebug.chrome.focus();

        // xxxHonza: we should not be using Firebug.currentContext global.
        var context = Firebug.currentContext;
        CommandLine.getCommandLine(context).focus();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Helpers

    /**
     * Update visibility of both XUL buttons (used to toggle the side panel box).
     */
    updateButtonVisibility: function()
    {
        var editorVisible = Options.get("commandEditor");
        var orient = Options.get("viewPanelOrient");

        Trace.sysout("toggleCommandEditor.updateButtonVisibility; editor visible: " +
            editorVisible + ", orient: " + orient);

        var box = Firebug.chrome.$("fbToggleCommandEditorBox");
        Dom.collapse(box, editorVisible);

        var box2 = Firebug.chrome.$("fbToggleCommandEditor2");
        Dom.collapse(box2, !editorVisible);

        if (orient)
        {
            Dom.collapse(box, false);
            Dom.collapse(box2, true);
        }
    },

    /**
     * Update visibility of both XUL buttons (used to toggle the side panel box),
     * so the proper icon is displayed.
     */
    updateButtonState: function()
    {
        var editorVisible = Options.get("commandEditor");

        Trace.sysout("toggleCommandEditor.updateButtonState; editor visible: " +
            editorVisible);

        var button = Firebug.chrome.$("fbToggleCommandEditor");
        if (editorVisible)
            Css.removeClass(button, "closed");
        else
            Css.setClass(button, "closed");

        var button2 = Firebug.chrome.$("fbToggleCommandEditor2");
        if (editorVisible)
            Css.removeClass(button2, "closed");
        else
            Css.setClass(button2, "closed");
    },

    /**
     * Register listeners for XUL UI. This module is not exposed to the XUL space.
     */
    registerListeners: function()
    {
        var button = Firebug.chrome.$("fbToggleCommandEditor");
        button.addEventListener("command", this.toggle.bind(this), false);

        var button2 = Firebug.chrome.$("fbToggleCommandEditor2");
        button2.addEventListener("command", this.toggle.bind(this), false);

        var tooltip = Firebug.chrome.$("fbToggleCommandEditorTooltip");
        tooltip.addEventListener("popupshowing",
            this.onToggleCommandEditorShowTooltip.bind(this, tooltip), false);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Tooltips

    onToggleCommandEditorShowTooltip: function(tooltip)
    {
        // fbToggleCommandEditor buttons is displayed all the time in case of
        // |Vertical Panes| mode. So, update its tooltip according to the
        // current visibility of the Command Editor.
        var editorVisible = Options.get("commandEditor");
        tooltip.label = editorVisible ? Locale.$STR("console.option.Show_Command_Line") :
            Locale.$STR("console.option.Show_Command_Editor");
    },
});

// ********************************************************************************************* //
// Registration

Firebug.registerModule(ToggleCommandEditor);

return ToggleCommandEditor;

// ********************************************************************************************* //
});
<commit_msg>Update comment<commit_after>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/css",
    "firebug/lib/dom",
    "firebug/lib/locale",
    "firebug/lib/options",
    "firebug/chrome/module",
    "firebug/console/commandLine",
],
function(Firebug, FBTrace, Obj, Css, Dom, Locale, Options, Module, CommandLine) {

"use strict";

// ********************************************************************************************* //
// Constants

var TraceError = FBTrace.toError();
var Trace = FBTrace.to("DBG_COMMANDEDITOR");

// ********************************************************************************************* //
// ToggleCommandEditor Implementation

/**
 * @module This module is responsible for toggling visibility of the Command editor.
 *
 * The Command editor should be implemented as a standard side panel, which also
 * allows to have more instances of the editor at the same time.
 *
 * See also related issues:
 * 1) Issue 988: Make the Command Editor independent from the Command Line
 * 2) Issue 6028: Allow to have multiple instances of the Command Editor
 */
var ToggleCommandEditor = Obj.extend(Module,
/** @lends ToggleCommandEditor */
{
    dispatchName: "ToggleCommandEditor",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Module

    initialize: function()
    {
        Module.initialize.apply(this, arguments);

        this.updateButtonState();
        this.updateButtonVisibility();

        // Register a command handlers for XUL buttons dynamically, so we don't have to
        // expose this object into the firebugOverlay.xul scope.
        this.registerListeners();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Framework Events

    showPanel: function(browser, panel)
    {
        if (panel && panel.name == "console")
            this.updateButtonVisibility();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Options

    updateOption: function(name, value)
    {
        if (name == "viewPanelOrient" || name == "commandEditor")
        {
            this.updateButtonState();
            this.updateButtonVisibility();
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // XUL Command

    /**
     * Executed when the user presses 'fbToggleCommandEditor' or 'fbToggleCommandEditor2'
     * button on the toolbar.
     */
    toggle: function()
    {
        if (Trace.active)
        {
            var editorVisible = Options.get("commandEditor");
            Trace.sysout("toggleCommandEditor.toggle; prev value: " + editorVisible);
        }

        Options.togglePref("commandEditor");

        Firebug.chrome.focus();

        // xxxHonza: we should not be using Firebug.currentContext global.
        var context = Firebug.currentContext;
        CommandLine.getCommandLine(context).focus();
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Helpers

    /**
     * Update visibility of XUL buttons.
     */
    updateButtonVisibility: function()
    {
        var editorVisible = Options.get("commandEditor");
        var orient = Options.get("viewPanelOrient");

        Trace.sysout("toggleCommandEditor.updateButtonVisibility; editor visible: " +
            editorVisible + ", orient: " + orient);

        var box = Firebug.chrome.$("fbToggleCommandEditorBox");
        Dom.collapse(box, editorVisible);

        var box2 = Firebug.chrome.$("fbToggleCommandEditor2");
        Dom.collapse(box2, !editorVisible);

        if (orient)
        {
            Dom.collapse(box, false);
            Dom.collapse(box2, true);
        }
    },

    /**
     * Update state of XUL buttons, so the proper icon is displayed.
     */
    updateButtonState: function()
    {
        var editorVisible = Options.get("commandEditor");

        Trace.sysout("toggleCommandEditor.updateButtonState; editor visible: " +
            editorVisible);

        var button = Firebug.chrome.$("fbToggleCommandEditor");
        if (editorVisible)
            Css.removeClass(button, "closed");
        else
            Css.setClass(button, "closed");

        var button2 = Firebug.chrome.$("fbToggleCommandEditor2");
        if (editorVisible)
            Css.removeClass(button2, "closed");
        else
            Css.setClass(button2, "closed");
    },

    /**
     * Register listeners for XUL UI. This module is not exposed to the XUL space.
     */
    registerListeners: function()
    {
        var button = Firebug.chrome.$("fbToggleCommandEditor");
        button.addEventListener("command", this.toggle.bind(this), false);

        var button2 = Firebug.chrome.$("fbToggleCommandEditor2");
        button2.addEventListener("command", this.toggle.bind(this), false);

        var tooltip = Firebug.chrome.$("fbToggleCommandEditorTooltip");
        tooltip.addEventListener("popupshowing",
            this.onToggleCommandEditorShowTooltip.bind(this, tooltip), false);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Tooltips

    onToggleCommandEditorShowTooltip: function(tooltip)
    {
        // fbToggleCommandEditor buttons is displayed all the time in case of
        // |Vertical Panes| mode. So, update its tooltip according to the
        // current visibility of the Command Editor.
        var editorVisible = Options.get("commandEditor");
        tooltip.label = editorVisible ? Locale.$STR("console.option.Show_Command_Line") :
            Locale.$STR("console.option.Show_Command_Editor");
    },
});

// ********************************************************************************************* //
// Registration

Firebug.registerModule(ToggleCommandEditor);

return ToggleCommandEditor;

// ********************************************************************************************* //
});
<|endoftext|>


<commit_before>var UnauthorizedError = require('../util/errors/unauthorized');
var InvalidRequestError = require('../util/errors/invalid-request');
var UnknownResourceError = require('../util/errors/unknown-resource');
var check = require('validator').check;
var Record = require('../models/record');
var rbac = require('mongoose-rbac');
var ops = require('../util/ops');
var helpers = require('../util/helpers.js');
var _ = require('lodash');
var async = require('async');

function getAccessControlHandler(action) {
	return function(user, record, done) {
		var categories = record.getIncludingCategories();
		var actsAndSubs = categories.map(function(cat) {
			return [action, cat.join('.')];
		});
		return user.canAny(actsAndSubs, done);
	}
}

module.exports = exports = function(app, api) {

	// GET /api/records(?skip=<skip_results>)(&limit=<limit_results>)(&search=<search_filter) -> [Record...]
	app.get(
		'/records',
		helpers.getModelQueryHandler(Record, {
			searchFields: ['label', 'tags', 'category'],
			controlAccess: getAccessControlHandler(ops.READ)
		})
	);

	app.get('/records/categories', function(req, res, next) {

		var user = req.user;
		var op = req.param('op');

		try {
      check(op, 'op parameter must me a valid action !').isIn(_.values(ops));
    } catch(err) {
      return next(err);
    }

		var subjects = api.acl.getAvailableSubjects();
		async.reduce(
			subjects,
			[],
			function(result, sub, next) {
				user.can(op, sub.join('.'), function(err, can) {
					if(err) {
						return next(err);
					}
					if(can) {
						result.push(sub);
					}
					return next(null, result);
				});
			},
			function(err, result) {
				if(err) {
					return next(err);
				}
				return res.send(result);
			}
		);

	});

	app.get(
		'/records/stats',
		helpers.getModelQueryHandler(Record, {
			searchFields: ['label', 'tags', 'category'],
			transform: function(records, done) {
				return done(null, {total: records.length});
			}
		})
	);

	app.post(
		'/records',
		helpers.getModelCreateHandler(Record, {
			controlAccess: getAccessControlHandler(ops.CREATE),
			update: function(record, data, done) {

				if(data.text) {
					record.text = data.text;
				}

				if(data.label) {
					record.label = data.label;
				}

				if(Array.isArray(data.tags)) {
					record.tags = data.tags;
				}

				if(data.category) {
					record.category = data.category;
				}

				return done();

			},
			transform: function(record, done) {
				return done(null, record.decrypt());
			}
		})
	);

	app.put('/records/:id', helpers.getModelUpdateHandler(Record, {
		controlAccess: getAccessControlHandler(ops.UPDATE),
		update: function(record, update, done) {

			if(!('revision' in update)) {
				return done(new InvalidRequestError('Invalid revision number !'));
			} else {
				record.revision = update.revision;
			}

			if('label' in update) {
				record.label = update.label;
			}

			if(Array.isArray(update.category)) {
				//TODO validate category against configuration
				record.category = update.category;
			}

			if('text' in update) {
				record.text = update.text;
			}

			if(Array.isArray(update.tags)) {
				record.tags = update.tags;
			}

			return done();
		},

		transform: function(record, done) {
			return done(null, record.decrypt());
		}

	}));

	// GET /api/records/<recordId> -> Record
	app.get('/records/:id', helpers.getModelGetOneHandler(Record, {
		controlAccess: getAccessControlHandler(ops.READ),
	}));

	// DEL /api/records/<recordId> -> 204
	app.del('/records/:id', helpers.getModelDeleteHandler(Record, {
		controlAccess: getAccessControlHandler(ops.DELETE)
	}));

};<commit_msg>Ajout validation des catégories lors de la création/modification d'un Record<commit_after>var UnauthorizedError = require('../util/errors/unauthorized');
var InvalidRequestError = require('../util/errors/invalid-request');
var UnknownResourceError = require('../util/errors/unknown-resource');
var check = require('validator').check;
var Record = require('../models/record');
var rbac = require('mongoose-rbac');
var ops = require('../util/ops');
var helpers = require('../util/helpers.js');
var _ = require('lodash');
var async = require('async');

function getAccessControlHandler(action) {
	return function(user, record, done) {
		var categories = record.getIncludingCategories();
		var actsAndSubs = categories.map(function(cat) {
			return [action, cat.join('.')];
		});
		return user.canAny(actsAndSubs, done);
	}
}

module.exports = exports = function(app, api) {

	// GET /api/records(?skip=<skip_results>)(&limit=<limit_results>)(&search=<search_filter) -> [Record...]
	app.get(
		'/records',
		helpers.getModelQueryHandler(Record, {
			searchFields: ['label', 'tags', 'category'],
			controlAccess: getAccessControlHandler(ops.READ)
		})
	);

	app.get('/records/categories', function(req, res, next) {

		var user = req.user;
		var op = req.param('op');

		try {
      check(op, 'op parameter must me a valid action !').isIn(_.values(ops));
    } catch(err) {
      return next(err);
    }

		var subjects = api.acl.getAvailableSubjects();
		async.reduce(
			subjects,
			[],
			function(result, sub, next) {
				user.can(op, sub.join('.'), function(err, can) {
					if(err) {
						return next(err);
					}
					if(can) {
						result.push(sub);
					}
					return next(null, result);
				});
			},
			function(err, result) {
				if(err) {
					return next(err);
				}
				return res.send(result);
			}
		);

	});

	app.get(
		'/records/stats',
		helpers.getModelQueryHandler(Record, {
			searchFields: ['label', 'tags', 'category'],
			transform: function(records, done) {
				return done(null, {total: records.length});
			}
		})
	);

	function completeRecord(record, data, done) {

		if('text' in data) {
			record.text = data.text;
		}

		if('label' in data) {
			record.label = data.label;
		}

		if(Array.isArray(data.tags)) {
			record.tags = data.tags;
		}

		if(Array.isArray(data.category)) {
			var subjects = api.acl.getAvailableSubjects();
			var isIn = _.any(subjects, function(sub) {
				return sub.toString() === data.category.toString();
			});
			if(isIn) {
				record.category = data.category;
			} else {
				return new Error('Invalid category !');
			}
		}

		return done();

	}

	app.post(
		'/records',
		helpers.getModelCreateHandler(Record, {
			controlAccess: getAccessControlHandler(ops.CREATE),
			update: completeRecord,
			transform: function(record, done) {
				return done(null, record.decrypt());
			}
		})
	);

	app.put('/records/:id', helpers.getModelUpdateHandler(Record, {
		controlAccess: getAccessControlHandler(ops.UPDATE),
		update: completeRecord,
		transform: function(record, done) {
			return done(null, record.decrypt());
		}
	}));

	// GET /api/records/<recordId> -> Record
	app.get('/records/:id', helpers.getModelGetOneHandler(Record, {
		controlAccess: getAccessControlHandler(ops.READ),
	}));

	// DEL /api/records/<recordId> -> 204
	app.del('/records/:id', helpers.getModelDeleteHandler(Record, {
		controlAccess: getAccessControlHandler(ops.DELETE)
	}));

};<|endoftext|>


<commit_before>(function (angular) {
    'use strict';
    var archivoPerfilControllerApp = angular.module('archivoPerfil', ['ngAnimate', 'ngSanitize', 'ui.bootstrap', 'ui.grid', 'ngTouch', 'ui.grid.edit', 'ui.grid.autoResize', 'ui.grid.selection', 'ui.grid.cellNav', 'xeditable'])
    .controller('archivoPerfilController', ['$scope', '$http', '$window', '$location', '$filter', 'uiGridConstants', 'i18nService', '$scope', function ($scope, $http, $window, $location, $filter, i18nService, uiGridConstants) {
        var init = function () {
            $scope.archivoID = $window.localStorage.getItem("archivoID");
            // DATOS PRINCIPALES
            $scope.cargarDatosPrincipales();
            // ANOTACIONES
            $scope.cargarNotas();
        };

        //Datos principales
        $scope.archivoDatos = {};
        $scope.datosPrincipales = {};
        $scope.datosPrincipales.archivoTitulo = "";
        $scope.datosPrincipales.archivoNombre = "";
        $scope.datosPrincipales.institucionFondo = "";
        $scope.datosPrincipales.seccion = "";
        $scope.datosPrincipales.numRefDentroFondo = "";
        $scope.datosPrincipales.archivoFecha = "";
        $scope.datosPrincipales.folioInicial = "";
        $scope.datosPrincipales.folioFinal = "";
        $scope.datosPrincipales.legajo = "";
        $scope.datosPrincipales.numOrden = "";
        $scope.datosPrincipales.numPaginas = "";
        $scope.datosPrincipales.palabrasClaves = {};
        $scope.datosPrincipales.disponibilidad = "";

        //Bandera para saber cuando guardar o no
        $scope.datosPrincipales.editado = false;

        $scope.cargarDatosPrincipales = function () {
            $http.get('http://monsalvediaz.com:5000/PIMC0.1/ConsultaArchivo?archivoID=' + $scope.archivoID).then(function (data) {
                //Obtener los datos JSON
                $scope.archivoDatos = data.data[0];
                //Log
                console.log($scope.archivoDatos);

                //Llenamos los datos del archivo
                $scope.datosPrincipales.archivoTitulo = $scope.archivoDatos.titulo;
                $scope.datosPrincipales.archivoNombre = $scope.archivoDatos.fondo;
                $scope.datosPrincipales.institucionFondo = $scope.archivoDatos.institucionFondo;
                $scope.datosPrincipales.seccion = $scope.archivoDatos.seccion;
                $scope.datosPrincipales.numRefDentroFondo = $scope.archivoDatos.numRefDentroFondo;
                $scope.datosPrincipales.archivoFecha = $filter('date')(new Date($scope.archivoDatos.fechaInicial), String($scope.archivoDatos.fechaInicialFormato).toLowerCase()) + " - " + $filter('date')(new Date($scope.archivoDatos.fechaFinal), String($scope.archivoDatos.fechaFinalFormato).toLowerCase());
                $scope.datosPrincipales.folioInicial = $scope.archivoDatos.folioInicial;
                $scope.datosPrincipales.folioFinal = $scope.archivoDatos.folioFinal;
                $scope.datosPrincipales.legajo = $scope.archivoDatos.legajo;
                $scope.datosPrincipales.numOrden = $scope.archivoDatos.numOrden;
                $scope.datosPrincipales.numPaginas = $scope.archivoDatos.numPaginas;
                $scope.datosPrincipales.palabrasClaves = $scope.archivoDatos.palabrasClaves.split(",");
                $scope.datosPrincipales.palabrasClaves = $scope.datosPrincipales.palabrasClaves.map(function (e) { return e.trim(); });

                $scope.datosPrincipales.disponibilidad = $scope.archivoDatos.disponibilidad;
                //Limpiamos la bandera de editado
                $scope.datosPrincipales.editado = false;

                //Para palabras claves
                $scope.palabraNueva = {mensaje:"+Agregar"};

            });
        };

        // Anotaciones
        $scope.notas = "";
        $scope.cargarNotas = function () {
            $http.get('http://monsalvediaz.com:5000/PIMC0.1/Consulta/ArchivosNotas?archivoID=' + $scope.archivoID).then(function (data) {
                if (String(data).startsWith("[WARNING]")) {
                    $scope.notas = data.data;
                    // LOG
                    console.log($scope.notas);
                }
            });

        };
        $scope.agregarNotaVacia = function () {
            if ($scope.notas === "") {
                $scope.notas = {{
                    nota:"",
                    referencia:"",
                    fechaHistorica:"",
                    fechaHistFormato:""
                }};
            } else {
                $scope.notas.push({
                nota:"",
                referencia:"",
                fechaHistorica:"",
                fechaHistFormato:""
            });
            }
        }

        // Initialization fucntion
        init();

        // Button functions
        $scope.borrarCambios = function () {
            if (window.confirm("Esta Seguro que quiere borrar los cambios?") === true) {
                init();
            }
        };
        $scope.guardarCambios = function () {
            if($scope.guardarDatos) {

                //Revisamos datos principales editados
                if ($scope.datosPrincipales.editado) {

                }
            }
        };

        // Para borrar palabras claves
        $scope.borrarSiVacio = function (indexEditada, palabra) {
            if (palabra == "") {
                $scope.datosPrincipales.palabrasClaves.splice(indexEditada,1);
            }
        }
        //Para agregar palabras claves
        $scope.palabraNueva = {mensaje: '+Agregar'};

        $scope.borrarCampo = function () {
            $scope.palabraNueva.mensaje = "";
        }
        $scope.mostrarCampo = function () {
            $scope.palabraNueva.mensaje = "+Agregar";
        }
        $scope.agregarPalabraNueva = function (palabra) {
            if (!$scope.datosPrincipales.palabrasClaves.includes(palabra) && palabra.length != 0) {
                $scope.datosPrincipales.palabrasClaves.push(palabra);
            }
            $scope.palabraNueva.mensaje = "+Agregar";
        }

        //Para guardar
        $scope.guardarDatos = false;

    }]);
    archivoPerfilControllerApp.run(function (editableOptions,editableThemes) {
        editableThemes.bs3.inputClass = 'input-sm';
        editableThemes.bs3.buttonsClass = 'btn-sm';
        editableOptions.theme = 'bs3';
        editableOptions.buttons = 'no';
    });
})(window.angular);

<commit_msg>Agregar Notas<commit_after>(function (angular) {
    'use strict';
    var archivoPerfilControllerApp = angular.module('archivoPerfil', ['ngAnimate', 'ngSanitize', 'ui.bootstrap', 'ui.grid', 'ngTouch', 'ui.grid.edit', 'ui.grid.autoResize', 'ui.grid.selection', 'ui.grid.cellNav', 'xeditable'])
    .controller('archivoPerfilController', ['$scope', '$http', '$window', '$location', '$filter', 'uiGridConstants', 'i18nService', '$scope', function ($scope, $http, $window, $location, $filter, i18nService, uiGridConstants) {
        var init = function () {
            $scope.archivoID = $window.localStorage.getItem("archivoID");
            // DATOS PRINCIPALES
            $scope.cargarDatosPrincipales();
            // ANOTACIONES
            $scope.cargarNotas();
        };

        //Datos principales
        $scope.archivoDatos = {};
        $scope.datosPrincipales = {};
        $scope.datosPrincipales.archivoTitulo = "";
        $scope.datosPrincipales.archivoNombre = "";
        $scope.datosPrincipales.institucionFondo = "";
        $scope.datosPrincipales.seccion = "";
        $scope.datosPrincipales.numRefDentroFondo = "";
        $scope.datosPrincipales.archivoFecha = "";
        $scope.datosPrincipales.folioInicial = "";
        $scope.datosPrincipales.folioFinal = "";
        $scope.datosPrincipales.legajo = "";
        $scope.datosPrincipales.numOrden = "";
        $scope.datosPrincipales.numPaginas = "";
        $scope.datosPrincipales.palabrasClaves = {};
        $scope.datosPrincipales.disponibilidad = "";

        //Bandera para saber cuando guardar o no
        $scope.datosPrincipales.editado = false;

        $scope.cargarDatosPrincipales = function () {
            $http.get('http://monsalvediaz.com:5000/PIMC0.1/ConsultaArchivo?archivoID=' + $scope.archivoID).then(function (data) {
                //Obtener los datos JSON
                $scope.archivoDatos = data.data[0];
                //Log
                console.log($scope.archivoDatos);

                //Llenamos los datos del archivo
                $scope.datosPrincipales.archivoTitulo = $scope.archivoDatos.titulo;
                $scope.datosPrincipales.archivoNombre = $scope.archivoDatos.fondo;
                $scope.datosPrincipales.institucionFondo = $scope.archivoDatos.institucionFondo;
                $scope.datosPrincipales.seccion = $scope.archivoDatos.seccion;
                $scope.datosPrincipales.numRefDentroFondo = $scope.archivoDatos.numRefDentroFondo;
                $scope.datosPrincipales.archivoFecha = $filter('date')(new Date($scope.archivoDatos.fechaInicial), String($scope.archivoDatos.fechaInicialFormato).toLowerCase()) + " - " + $filter('date')(new Date($scope.archivoDatos.fechaFinal), String($scope.archivoDatos.fechaFinalFormato).toLowerCase());
                $scope.datosPrincipales.folioInicial = $scope.archivoDatos.folioInicial;
                $scope.datosPrincipales.folioFinal = $scope.archivoDatos.folioFinal;
                $scope.datosPrincipales.legajo = $scope.archivoDatos.legajo;
                $scope.datosPrincipales.numOrden = $scope.archivoDatos.numOrden;
                $scope.datosPrincipales.numPaginas = $scope.archivoDatos.numPaginas;
                $scope.datosPrincipales.palabrasClaves = $scope.archivoDatos.palabrasClaves.split(",");
                $scope.datosPrincipales.palabrasClaves = $scope.datosPrincipales.palabrasClaves.map(function (e) { return e.trim(); });

                $scope.datosPrincipales.disponibilidad = $scope.archivoDatos.disponibilidad;
                //Limpiamos la bandera de editado
                $scope.datosPrincipales.editado = false;

                //Para palabras claves
                $scope.palabraNueva = {mensaje:"+Agregar"};

            });
        };

        // Anotaciones
        $scope.notas = "";
        $scope.cargarNotas = function () {
            $http.get('http://monsalvediaz.com:5000/PIMC0.1/Consulta/ArchivosNotas?archivoID=' + $scope.archivoID).then(function (data) {
                if (String(data).startsWith("[WARNING]")) {
                    $scope.notas = data.data;
                    // LOG
                    console.log($scope.notas);
                }
            });

        };
        $scope.agregarNotaVacia = function () {
            if ($scope.notas === "") {
                $scope.notas = [{
                    nota:"",
                    referencia:"",
                    fechaHistorica:"",
                    fechaHistFormato:""
                }];
            } else {
                $scope.notas.push({
                nota:"",
                referencia:"",
                fechaHistorica:"",
                fechaHistFormato:""
            });
            }
        }

        // Initialization fucntion
        init();

        // Button functions
        $scope.borrarCambios = function () {
            if (window.confirm("Esta Seguro que quiere borrar los cambios?") === true) {
                init();
            }
        };
        $scope.guardarCambios = function () {
            if($scope.guardarDatos) {

                //Revisamos datos principales editados
                if ($scope.datosPrincipales.editado) {

                }
            }
        };

        // Para borrar palabras claves
        $scope.borrarSiVacio = function (indexEditada, palabra) {
            if (palabra == "") {
                $scope.datosPrincipales.palabrasClaves.splice(indexEditada,1);
            }
        }
        //Para agregar palabras claves
        $scope.palabraNueva = {mensaje: '+Agregar'};

        $scope.borrarCampo = function () {
            $scope.palabraNueva.mensaje = "";
        }
        $scope.mostrarCampo = function () {
            $scope.palabraNueva.mensaje = "+Agregar";
        }
        $scope.agregarPalabraNueva = function (palabra) {
            if (!$scope.datosPrincipales.palabrasClaves.includes(palabra) && palabra.length != 0) {
                $scope.datosPrincipales.palabrasClaves.push(palabra);
            }
            $scope.palabraNueva.mensaje = "+Agregar";
        }

        //Para guardar
        $scope.guardarDatos = false;

    }]);
    archivoPerfilControllerApp.run(function (editableOptions,editableThemes) {
        editableThemes.bs3.inputClass = 'input-sm';
        editableThemes.bs3.buttonsClass = 'btn-sm';
        editableOptions.theme = 'bs3';
        editableOptions.buttons = 'no';
    });
})(window.angular);

<|endoftext|>


<commit_before>import React from 'react'
import './HomeView.scss'
import Content from './Content'
import Splash from './Splash'

import AppBar from 'material-ui/AppBar'
import Toolbar from 'material-ui/Toolbar'
import Button from 'material-ui/Button'
import IconButton from 'material-ui/IconButton'
import TextField from 'material-ui/TextField'

class HomeView extends React.Component {
  constructor(props) {
    super(props)
    this.state = {fieldValue: '', searchText: '', searched: false}
  }

  onSearchClick () {
    this.setState({searched: true});

    // update children
    this.setState({searchText: this.state.fieldValue})
  }

  onChange(e) {
    this.setState({fieldValue: e.target.value})
  }

  render () {
    let content = this.state.searched ? (<Content searchText={this.state.searchText}/>) : (<Splash/>)

    return (

        <AppBar position='static'>
          <Toolbar className='toolBar'>
            Stock The Prices
            <form className='form' >
              <TextField
                value={this.state.fieldValue}
                onChange={this.onChange.bind(this)}
              />

              <Button
                color="contrast"
                onClick={this.onSearchClick.bind(this)}
              >
                Search
              </Button>
            </form>
          </Toolbar>
        </AppBar>

        {content}

      )
  }
}

export default HomeView
<commit_msg>fixed enter button for search bar<commit_after>import React from 'react'
import './HomeView.scss'
import Content from './Content'
import Splash from './Splash'

import AppBar from 'material-ui/AppBar'
import Toolbar from 'material-ui/Toolbar'
import Button from 'material-ui/Button'
import IconButton from 'material-ui/IconButton'
import TextField from 'material-ui/TextField'

class HomeView extends React.Component {
  constructor(props) {
    super(props)
    this.state = {fieldValue: '', searchText: '', searched: false}
  }

  onSearchClick () {
    this.setState({searched: true});

    // update children
    this.setState({searchText: this.state.fieldValue})
  }

  onSearchEnter (ev) {
    // console.log(`Pressed keyCode ${ev.key}`);
    if (ev.key === 'Enter') {
        this.setState({searched: true});

        // update children
        this.setState({searchText: this.state.fieldValue})
        ev.preventDefault();
    }
  }

  onChange(e) {
    this.setState({fieldValue: e.target.value})
  }

  render () {
    let content = this.state.searched ? (<Content searchText={this.state.searchText}/>) : (<Splash/>)

    return (

        <AppBar position='static'>
          <Toolbar className='toolBar'>
            Stock The Prices
            <form className='form' >
              <TextField
                value={this.state.fieldValue}
                onChange={this.onChange.bind(this)}
                onKeyPress={this.onSearchEnter.bind(this)}
              />

              <Button
                color="contrast"
                onClick={this.onSearchClick.bind(this)}
              >
                Search
              </Button>
            </form>
          </Toolbar>
        </AppBar>

        {content}

      )
  }
}

export default HomeView
<|endoftext|>


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

/*jslint sub: true */

//#include aura.locker.SecureWindow
//#include aura.locker.SecureDocument
//#include aura.locker.SecureComponent

function LockerService() {
	"use strict";

	var lockers = [];
	var keyToEnvironmentMap = {};

	var validSymbolNameRegEx = /^[a-z$_][a-z0-9$_]*$/i;

	function getShadows(imports) {
		var globalKeys = Object.getOwnPropertyNames(window).concat(
			Object.getOwnPropertyNames(Object)).concat(Object.getOwnPropertyNames(Object.prototype));

		var candidates = [ "$A", "document", "window", "self", "top", "console", "Error", "Function" ].concat(globalKeys);

		function getInitialWhitelist(symbols) {
			var skip = {};

			for (var i = 0; i < symbols.length; i++) {
				var symbol = symbols[i];
				skip["#" + symbol] = true;
			}

			return skip;
		}

		// eval and arguments keywords are protected by strict mode
		var used = getInitialWhitelist([ "eval", "arguments", "undefined", "NaN", "Date", "Number", "Boolean", "alert" ]);

		var shadows = [];
		for (var n = 0; n < candidates.length; n++) {
			var candidate = candidates[n];
			var usedKey = "#" + candidate;
			if (!used[usedKey]) {
				if (!imports || !imports[candidate]) {
					// Skip over non-viable names
					if (validSymbolNameRegEx.test(candidate)) {
						shadows.push(candidate);
					}
				}

				used[usedKey] = true;
			}
		}

		return shadows;
	}

	function verifyShadows(expectedShadows, imports) {
		var shadows = getShadows(imports);
		if (shadows.length !== expectedShadows.length) {
			return false;
		}

		// DCHASMAN TODO W-2837786 Scan shadows and expected shadows for equality

		return undefined;
	}

	function preprocessSource(code) {
		// Block use of __proto__
		if (code.indexOf("__proto__") >= 0 || code.indexOf("__defineGetter__") >= 0 || code.indexOf("__defineSetter__") >= 0) {
			throw Error("Security violation: use of __proto__, __defineGetter__, and __defineSetter__ is not permitted!");
		}

		// Rewrite references to eval to avoid implicit calls leaking global state
		// NOTE: strict mode does not allow the symbol eval to be redefined, passed as parameter, so a simple regex can rewrite this during lockering
		return code.replace(/\beval\b/g, "_lsSafeEval");
	}

	function isSafeModeEnabled() {
		return $A.util.globalEval("(function() { 'use strict'; return this === undefined; })()");
	}

	var service = {
		createForDef : function(code, def) {
			var namespace = def.getDescriptor().getNamespace();
			var key = $A.lockerService.util.getKeyForNamespace(namespace);

			// Key this def so we can transfer the key to component instances
			$A.lockerService.util.applyKey(def, key);

			return this.create(code, key);
		},

		create : function(code, key, imports) {
			if (!isSafeModeEnabled()) {
				throw new Error("$A.lockerService.create() is only supported in strict mode capable browsers!");
			}

			return (function() {
				var shadows = getShadows(imports);

				var shadowingIIFESource = "function(" + shadows.toString() + ") {\n\"use strict\";\n";

				// DCHASMAN TODO W-2837788 Figure out the scoping issues here (e.g. component, helper, etc is not visible and maybe that is ok???)
				shadowingIIFESource += "var that = this; function _lsSafeEval(code) { return eval(\"'use strict';\" + that.secureSource(code)); }\n";

				shadowingIIFESource += preprocessSource(code) + "\n}";

				var locker;
				try {
					locker = $A.util.globalEval(shadowingIIFESource);
				} catch (x) {
					throw new Error("Unable to create locker IIFE: " + x);
				}

				locker.verifyShadows = function() {
					return verifyShadows(shadows, imports);
				};

				// For debugging purposes only. We return a copy to avoid leaking a mutatable reference that would allow hacking of verifyShadows()!
				Object.defineProperty(locker, "$shadows", {
					get : function() {
						return shadows.slice(0);
					}
				});

				// DCHASMAN TODO W-2837795 reuse of environments uses JSON.stringify(key) as the index into the key to environment map - is this OK or do we need something stronger
				var psuedoKeySymbol = JSON.stringify(key);
				var env = keyToEnvironmentMap[psuedoKeySymbol];
				if (!env) {
					env = keyToEnvironmentMap[psuedoKeySymbol] = {
						sWindow : new SecureWindow(window, key),

						sAura : Object.create($A, {
							getComponent : {
								value : function(globalId) {
									var c = $A.getComponent(globalId);
									$A.lockerService.util.verifyAccess(key, c);
									return service.wrapComponent(c);
								}
							},

							toString : {
								value : function() {
									return "SecureAura: { key: " + JSON.stringify(key) + " }";
								}
							}
						}),

						sUtils : Object.create(Object.prototype, {
							"secureSource" : {
								value : preprocessSource
							},

							toString : {
								value : function() {
									return "SecureUtils: { key: " + JSON.stringify(key) + " }";
								}
							}
						}),

						sDocument : new SecureDocument(document, key)
					};

					$A.lockerService.util.applyKey(env.sAura, key);
					$A.lockerService.util.applyKey(env.sWindow, key);

					Object.freeze(env.sAura);
				}

				function sFunction() {
					/*jslint evil: true */
					var args = Array.prototype.slice.call(arguments);
					args[args.length - 1] = "'use strict'; " + args[args.length - 1];
					return Function.apply(undefined, args);
				}

				// function getCtor(o) { if (o.constructor === Function.constructor) { throw new Error("You cannot get Function.ctor!") } return o.constructor; }

				// We pass in SecureUtils as this to provide an object that cannot be replaced/spoofed
				var sWindow = env.sWindow;
				var result = locker.call(env.sUtils, env.sAura, env.sDocument, sWindow, sWindow, sWindow, console, Error, sFunction);

				Object.defineProperty(locker, "$result", {
					value : result
				});

				lockers.push(locker);

				Object.freeze(locker);

				return locker;
			})();
		},

		verifyAll : function() {
			for (var n = 0; n < lockers.length; n++) {
				var locker = lockers[n];
				if (!locker.verifyShadows()) {
					return false;
				}
			}

			return true;
		},

		destroy : function(locker) {
			var index = lockers.indexOf(locker);
			if (index >= 0) {
				lockers.splice(index, 1);
			}
		},

		destroyAll : function() {
			lockers = [];
		},

		wrapComponent : function(component, referencingKey) {
			if (!component) {
				return component;
			}

			var key = !referencingKey ? $A.lockerService.util._getKey(component, $A.lockerService.masterKey) : referencingKey;
			if (!key) {
				return component;
			}

			if (!referencingKey) {
				var def = component.getDef();
				if ($A.clientService.isPrivilegedNamespace(def.getDescriptor().getNamespace()) && !def.isInstanceOf("aura:requireLocker")) {
					return component;
				}
			}

			// Store the SC on the component???
			var sc = component["$lsComponent"];
			if (!sc) {
				sc = new SecureComponent(component, key);
				Object.defineProperty(component, "$lsComponent", {
					value : sc
				});
			}

			return sc;
		},

		unwrap : function(elements) {
			if (!$A.lockerService.util.isKeyed(elements)) {
				return elements;
			}

			if ($A.util.isArray(elements)) {
				for (var n = 0; n < elements.length; n++) {
					var value = elements[n];
					if (value && value.unwrap) {
						elements[n] = value.unwrap($A.lockerService.masterKey);
					}
				}
			} else {
				if (elements && elements.unwrap) {
					elements = elements.unwrap($A.lockerService.masterKey);
				}
			}

			return elements;
		},

		trust : function(from) {
			var key = $A.lockerService.util._getKey(from, $A.lockerService.masterKey);
			if (key) {
				for (var n = 1; n < arguments.length; n++) {
					$A.lockerService.util.applyKey(arguments[n], key);
				}
			}
		},

		showLockedNodes : function showLockedNodes(root) {
			if ($A.lockerService.util.isKeyed(root)) {
				$A.util.addClass(root, "lockerizedNode");
			}

			var children = root.childNodes;
			for (var i = 0; i < children.length; i++) {
				showLockedNodes(children[i]);
			}
		},

		// Master key will be hidden by both locker shadowing and scope
		masterKey : Object.freeze({
			name : "master"
		})
	};

	service.util = (function() {
		var lockerNamespaceKeys = {};

		function getKey(thing) {
			var f = thing["$lsKey"];
			return f ? f($A.lockerService.masterKey) : undefined;
		}

		var util = {
			getKeyForNamespace : function(namespace) {
		    	// Get the locker key for this namespace
				var key = lockerNamespaceKeys[namespace];
				if (!key) {
		    		key = lockerNamespaceKeys[namespace] = Object.freeze({
		    			namespace: namespace
		    		});
				}

				return key;
			},

			_getKey : function(thing, mk) {
				if (mk !== $A.lockerService.masterKey) {
					throw Error("Access denied");
				}

				return getKey(thing);
			},

			isKeyed : function(thing) {
				return getKey(thing) !== undefined;
			},

			hasAccess : function(from, to) {
				var fromKey = getKey(from);
				var toKey = getKey(to);

				return (fromKey === $A.lockerService.masterKey) || (fromKey === toKey);
			},

			verifyAccess : function(from, to) {
				if (!$A.lockerService.util.hasAccess(from, to)) {
					var fromKey = getKey(from);
					var toKey = getKey(to);

					throw new Error("Access denied: " + JSON.stringify({
						from : fromKey,
						to : toKey
					}));
				}
			},

			applyKey : function(thing, key) {
				var keyToCheck = getKey(thing);
				if (!keyToCheck) {
					Object.defineProperty(thing, "$lsKey", {
						value : function(mk) {
							if (mk !== $A.lockerService.masterKey) {
								throw new Error("Access denied");
							}

							return key;
						}
					});
				} else {
					if (keyToCheck !== key) {
						throw new Error("Re-keying of " + thing + " is prohibited");
					}
				}
			}
		};

		Object.freeze(util);

		return util;
	})();

	service["createForDef"] = service.createForDef;
	service["trust"] = service.trust;
	service["showLockedNodes"] = service.showLockedNodes;

	Object.freeze(service);

	return service;
}

Aura.Services.LockerService = LockerService;

<commit_msg>dispatching events inside component's controller methods with secure events and secure components. making  undefined inside a controller's method to align with renderers and avoid exposing an action instance inside controller's methods.<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*jslint sub: true */

//#include aura.locker.SecureWindow
//#include aura.locker.SecureDocument
//#include aura.locker.SecureComponent

function LockerService() {
	"use strict";

	var lockers = [];
	var keyToEnvironmentMap = {};

	var validSymbolNameRegEx = /^[a-z$_][a-z0-9$_]*$/i;

	function getShadows(imports) {
		var globalKeys = Object.getOwnPropertyNames(window).concat(
			Object.getOwnPropertyNames(Object)).concat(Object.getOwnPropertyNames(Object.prototype));

		var candidates = [ "$A", "document", "window", "self", "top", "console", "Error", "Function" ].concat(globalKeys);

		function getInitialWhitelist(symbols) {
			var skip = {};

			for (var i = 0; i < symbols.length; i++) {
				var symbol = symbols[i];
				skip["#" + symbol] = true;
			}

			return skip;
		}

		// eval and arguments keywords are protected by strict mode
		var used = getInitialWhitelist([ "eval", "arguments", "undefined", "NaN", "Date", "Number", "Boolean", "alert" ]);

		var shadows = [];
		for (var n = 0; n < candidates.length; n++) {
			var candidate = candidates[n];
			var usedKey = "#" + candidate;
			if (!used[usedKey]) {
				if (!imports || !imports[candidate]) {
					// Skip over non-viable names
					if (validSymbolNameRegEx.test(candidate)) {
						shadows.push(candidate);
					}
				}

				used[usedKey] = true;
			}
		}

		return shadows;
	}

	function verifyShadows(expectedShadows, imports) {
		var shadows = getShadows(imports);
		if (shadows.length !== expectedShadows.length) {
			return false;
		}

		// DCHASMAN TODO W-2837786 Scan shadows and expected shadows for equality

		return undefined;
	}

	function preprocessSource(code) {
		// Block use of __proto__
		if (code.indexOf("__proto__") >= 0 || code.indexOf("__defineGetter__") >= 0 || code.indexOf("__defineSetter__") >= 0) {
			throw Error("Security violation: use of __proto__, __defineGetter__, and __defineSetter__ is not permitted!");
		}

		// Rewrite references to eval to avoid implicit calls leaking global state
		// NOTE: strict mode does not allow the symbol eval to be redefined, passed as parameter, so a simple regex can rewrite this during lockering
		return code.replace(/\beval\b/g, "_lsSafeEval");
	}

	function isSafeModeEnabled() {
		return $A.util.globalEval("(function() { 'use strict'; return this === undefined; })()");
	}

	var service = {
		createForDef : function(code, def) {
			var namespace = def.getDescriptor().getNamespace();
			var key = $A.lockerService.util.getKeyForNamespace(namespace);

			// Key this def so we can transfer the key to component instances
			$A.lockerService.util.applyKey(def, key);

			return this.create(code, key);
		},

		create : function(code, key, imports) {
			if (!isSafeModeEnabled()) {
				throw new Error("$A.lockerService.create() is only supported in strict mode capable browsers!");
			}

			return (function() {
				var shadows = getShadows(imports);

				var shadowingIIFESource = "function(" + shadows.toString() + ") {\n\"use strict\";\n";

				// DCHASMAN TODO W-2837788 Figure out the scoping issues here (e.g. component, helper, etc is not visible and maybe that is ok???)
				shadowingIIFESource += "var that = this; function _lsSafeEval(code) { return eval(\"'use strict';\" + that.secureSource(code)); }\n";

				shadowingIIFESource += preprocessSource(code) + "\n}";

				var locker;
				try {
					locker = $A.util.globalEval(shadowingIIFESource);
				} catch (x) {
					throw new Error("Unable to create locker IIFE: " + x);
				}

				locker.verifyShadows = function() {
					return verifyShadows(shadows, imports);
				};

				// For debugging purposes only. We return a copy to avoid leaking a mutatable reference that would allow hacking of verifyShadows()!
				Object.defineProperty(locker, "$shadows", {
					get : function() {
						return shadows.slice(0);
					}
				});

				// DCHASMAN TODO W-2837795 reuse of environments uses JSON.stringify(key) as the index into the key to environment map - is this OK or do we need something stronger
				var psuedoKeySymbol = JSON.stringify(key);
				var env = keyToEnvironmentMap[psuedoKeySymbol];
				if (!env) {
					env = keyToEnvironmentMap[psuedoKeySymbol] = {
						sWindow : new SecureWindow(window, key),

						sAura : Object.create($A, {
							getComponent : {
								value : function(globalId) {
									var c = $A.getComponent(globalId);
									$A.lockerService.util.verifyAccess(key, c);
									return service.wrapComponent(c, key);
								}
							},

							toString : {
								value : function() {
									return "SecureAura: { key: " + JSON.stringify(key) + " }";
								}
							}
						}),

						sUtils : Object.create(Object.prototype, {
							"secureSource" : {
								value : preprocessSource
							},

							toString : {
								value : function() {
									return "SecureUtils: { key: " + JSON.stringify(key) + " }";
								}
							}
						}),

						sDocument : new SecureDocument(document, key)
					};

					$A.lockerService.util.applyKey(env.sAura, key);
					$A.lockerService.util.applyKey(env.sWindow, key);

					Object.freeze(env.sAura);
				}

				function sFunction() {
					/*jslint evil: true */
					var args = Array.prototype.slice.call(arguments);
					args[args.length - 1] = "'use strict'; " + args[args.length - 1];
					return Function.apply(undefined, args);
				}

				// function getCtor(o) { if (o.constructor === Function.constructor) { throw new Error("You cannot get Function.ctor!") } return o.constructor; }

				// We pass in SecureUtils as this to provide an object that cannot be replaced/spoofed
				var sWindow = env.sWindow;
				var result = locker.call(env.sUtils, env.sAura, env.sDocument, sWindow, sWindow, sWindow, console, Error, sFunction);

				Object.defineProperty(locker, "$result", {
					value : result
				});

				lockers.push(locker);

				Object.freeze(locker);

				return locker;
			})();
		},

		verifyAll : function() {
			for (var n = 0; n < lockers.length; n++) {
				var locker = lockers[n];
				if (!locker.verifyShadows()) {
					return false;
				}
			}

			return true;
		},

		destroy : function(locker) {
			var index = lockers.indexOf(locker);
			if (index >= 0) {
				lockers.splice(index, 1);
			}
		},

		destroyAll : function() {
			lockers = [];
		},

		wrapComponent : function(component, referencingKey) {
			if (!component) {
				return component;
			}

			var key = !referencingKey ? $A.lockerService.util._getKey(component, $A.lockerService.masterKey) : referencingKey;
			if (!key) {
				return component;
			}

			if (!referencingKey) {
				var def = component.getDef();
				if ($A.clientService.isPrivilegedNamespace(def.getDescriptor().getNamespace()) && !def.isInstanceOf("aura:requireLocker")) {
					return component;
				}
			}

			// Store the SC on the component???
			var sc = component["$lsComponent"];
			if (!sc) {
				sc = new SecureComponent(component, key);
				Object.defineProperty(component, "$lsComponent", {
					value : sc
				});
			}

			return sc;
		},

		wrapComponentEvent : function(component, event) {
			if (!event || !component) {
				return event;
			}

			var key = $A.lockerService.util._getKey(component, $A.lockerService.masterKey);
			if (!key) {
				return event;
			}

			return new SecureAuraEvent(event, key);
		},

		unwrap : function(elements) {
			if (!$A.lockerService.util.isKeyed(elements)) {
				return elements;
			}

			if ($A.util.isArray(elements)) {
				for (var n = 0; n < elements.length; n++) {
					var value = elements[n];
					if (value && value.unwrap) {
						elements[n] = value.unwrap($A.lockerService.masterKey);
					}
				}
			} else {
				if (elements && elements.unwrap) {
					elements = elements.unwrap($A.lockerService.masterKey);
				}
			}

			return elements;
		},

		trust : function(from) {
			var key = $A.lockerService.util._getKey(from, $A.lockerService.masterKey);
			if (key) {
				for (var n = 1; n < arguments.length; n++) {
					$A.lockerService.util.applyKey(arguments[n], key);
				}
			}
		},

		showLockedNodes : function showLockedNodes(root) {
			if ($A.lockerService.util.isKeyed(root)) {
				$A.util.addClass(root, "lockerizedNode");
			}

			var children = root.childNodes;
			for (var i = 0; i < children.length; i++) {
				showLockedNodes(children[i]);
			}
		},

		// Master key will be hidden by both locker shadowing and scope
		masterKey : Object.freeze({
			name : "master"
		})
	};

	service.util = (function() {
		var lockerNamespaceKeys = {};

		function getKey(thing) {
			var f = thing["$lsKey"];
			return f ? f($A.lockerService.masterKey) : undefined;
		}

		var util = {
			getKeyForNamespace : function(namespace) {
		    	// Get the locker key for this namespace
				var key = lockerNamespaceKeys[namespace];
				if (!key) {
		    		key = lockerNamespaceKeys[namespace] = Object.freeze({
		    			namespace: namespace
		    		});
				}

				return key;
			},

			_getKey : function(thing, mk) {
				if (mk !== $A.lockerService.masterKey) {
					throw Error("Access denied");
				}

				return getKey(thing);
			},

			isKeyed : function(thing) {
				return getKey(thing) !== undefined;
			},

			hasAccess : function(from, to) {
				var fromKey = getKey(from);
				var toKey = getKey(to);

				return (fromKey === $A.lockerService.masterKey) || (fromKey === toKey);
			},

			verifyAccess : function(from, to) {
				if (!$A.lockerService.util.hasAccess(from, to)) {
					var fromKey = getKey(from);
					var toKey = getKey(to);

					throw new Error("Access denied: " + JSON.stringify({
						from : fromKey,
						to : toKey
					}));
				}
			},

			applyKey : function(thing, key) {
				var keyToCheck = getKey(thing);
				if (!keyToCheck) {
					Object.defineProperty(thing, "$lsKey", {
						value : function(mk) {
							if (mk !== $A.lockerService.masterKey) {
								throw new Error("Access denied");
							}

							return key;
						}
					});
				} else {
					if (keyToCheck !== key) {
						throw new Error("Re-keying of " + thing + " is prohibited");
					}
				}
			}
		};

		Object.freeze(util);

		return util;
	})();

	service["createForDef"] = service.createForDef;
	service["trust"] = service.trust;
	service["showLockedNodes"] = service.showLockedNodes;

	Object.freeze(service);

	return service;
}

Aura.Services.LockerService = LockerService;
<|endoftext|>