HEX
Server: Apache
System: Linux srv13.cpanelhost.cl 3.10.0-962.3.2.lve1.5.38.el7.x86_64 #1 SMP Thu Jun 18 05:28:41 EDT 2020 x86_64
User: cca63905 (4205)
PHP: 7.3.20
Disabled: NONE
Upload Files
File: //proc/self/root/proc/self/root/proc/self/cwd/nueva/modules/wnetsecurity/views/js/admin/config.js
/**
 * Copyright since 2014 Waynet Sp. z o.o.
 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.md.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/OSL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to kontakt@waynet.pl so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to https://devdocs.prestashop-project.org/ for more information.
 *
 * @author    Waynet Sp. z o.o. <kontakt@waynet.pl>
 * @copyright since 2014 Waynet Sp. z o.o.
 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
 */
document.addEventListener("DOMContentLoaded", () => {
  window?.psaccountsVue?.init();

  if (!window?.psaccountsVue?.isOnboardingCompleted()) {
    return;
  }

  const cdc = window.cloudSyncSharingConsent;
  cdc.init('#prestashop-cloudsync');

  class VulnerabilityReportsList {
    initialized = false;
    templates = {};
    selectors = {
      container: '.js-vulnerability-reports-container',
      info: '.js-vulnerability-reports-info',
      templates: {
        report: '.js-vulnerability-report-template',
        item: '.js-vulnerability-report-item-template',
        loadMore: '.js-load-vulnerability-reports-template',
      },
      report: {
        container: '.js-report-container',
        date: '.js-report-date',
        button: '.js-report-collapse-toggle',
        itemsWrapper: '.js-vulnerability-report-items-wrapper',
        items: '.js-vulnerability-report-items',
        showHidden: '.js-show-hidden-report-items',
      },
      item: {
        container: '.js-report-item-container',
        identifier: '.js-item-identifier',
        type: '.js-item-type',
        severity: '.js-item-severity',
        description: '.js-item-description',
        contactLink: '.js-item-contact-link',
        toggleHidden: '.js-item-toggle-hidden-button',
      },
      loadMore: '.js-load-vulnerability-reports',
    }
    classes = {
      hideItems: 'vulnerability-report-hide-items',
    }

    constructor(wrapper, config) {
      this.wrapper = wrapper;
      this.config = config;
      this.nextPage = 1;

      this.container = wrapper.querySelector(this.selectors.container);
      this.info = wrapper.querySelector(this.selectors.info);
      for (const [key, selector] of Object.entries(this.selectors.templates)) {
        this.templates[key] = wrapper.querySelector(selector);
      }
    }

    init() {
      if (this.initialized) {
        return;
      }

      if (!this.config.hasValidSubscription) {
        this.info.textContent = this.config.translations.status.subscribe;

        return;
      }

      this.initReports().then((report) => {
        if (null !== report) {
          this.initEvents();
          this.initialized = true;
        } else {
          setTimeout(this.init, 1.2e6)
        }
      });
    }

    initReports() {
      return this.getLastReport()
        .then((report) => {
          if (null !== report) {
            this.container.appendChild(this.createReportNode(report));
            const loadMoreWrapper = this.templates.loadMore.content.cloneNode(true);
            this.loadMoreButton = loadMoreWrapper.querySelector(this.selectors.loadMore);
            this.container.appendChild(loadMoreWrapper);
            this.info.textContent = '';
          } else {
            this.info.textContent = this.config.translations.status.firstReport;
          }

          return report;
        })
        .catch(error => this.handleRequestError(error));
    }

    initEvents() {
      const itemToggleHiddenClass = this.selectors.item.toggleHidden.substring(1);
      const reportShowHiddenClass = this.selectors.report.showHidden.substring(1);

      this.loadMoreButton.addEventListener('click', (e) => this.handleLoadMore(e));
      this.wrapper.addEventListener('click', (e) => {
        if (e.target.classList.contains(itemToggleHiddenClass)) {
          this.handleToggleHiddenItem(e);
        } else if (e.target.classList.contains(reportShowHiddenClass)) {
          this.handleShowHidden(e);
        }
      });
    }

    handleToggleHiddenItem(e) {
      e.preventDefault();

      const toggleHidden = e.target;
      const container = toggleHidden.closest(this.selectors.item.container);
      const hidden = 'false' === container.dataset.hidden;
      const uri = container.dataset.uri;

      this.updateItem(uri, hidden)
        .then(() => {
          this.wrapper
            .querySelectorAll(`${this.selectors.item.container}[data-uri="${uri}"]`)
            .forEach((container) => {
              container.dataset.hidden = hidden;
              container.querySelector(this.selectors.item.toggleHidden).textContent = hidden
                ? this.config.translations.item.show
                : this.config.translations.item.hide;

              const reportContainer = container.closest(this.selectors.report.container);
              const showHidden = reportContainer.querySelector(this.selectors.report.showHidden);

              const count = hidden ? parseInt(showHidden.dataset.count) + 1 : parseInt(showHidden.dataset.count) - 1;
              showHidden.dataset.count = count.toString();
              showHidden.textContent = showHidden.dataset.text.replace('{count}', count);
              if (0 === count) {
                showHidden.style.display = 'none';
              } else if (reportContainer.classList.contains(this.classes.hideItems)) {
                showHidden.style.removeProperty('display');
              }
            });
        })
        .catch(error => this.handleRequestError(error));
    }

    handleShowHidden(e) {
      e.preventDefault();
      e.stopPropagation();

      const showHidden = e.target;
      const container = showHidden.closest(this.selectors.report.container);

      container.classList.remove(this.classes.hideItems);
      showHidden.style.display = 'none';
    }

    handleLoadMore(e) {
      e.preventDefault();

      this.getReports(this.nextPage)
        .then((data) => {
          for (const report of data.reports) {
            if (null !== this.wrapper.querySelector(`${this.selectors.report.container}[data-id="${report.id}"]`)) {
              continue;
            }

            this.container.insertBefore(this.createReportNode(report), this.loadMoreButton.parentNode);
          }

          if (null !== data.nextPageUri) {
            this.nextPage += 1;
          } else {
            this.loadMoreButton.remove();
            this.loadMoreButton = null;
          }
        })
        .catch(error => this.handleRequestError(error));
    }

    async getLastReport() {
      return this.sendRequest(this.config.urls.lastReport).then((response) => {
        switch (response.status) {
          case 200:
            return response.json();
          case 404:
            return null;
          default:
            throw response;
        }
      });
    }

    async getReports(page = 1) {
      const url = new URL(this.config.urls.reports);
      url.searchParams.set('page', page.toString());

      return this.sendRequest(url).then((response) => {
        if (200 === response.status) {
          return response.json();
        }

        throw response;
      });
    }

    async updateItem(uri, hidden) {
      const payload = {
        uri,
        hidden,
      }

      return this.sendRequest(this.config.urls.updateVulnerability, {
        method: 'PATCH',
        body: JSON.stringify(payload),
        headers: {
          'content-type': 'application/json'
        },
      })
        .then((response) => {
          if (204 === response.status) {
            return;
          }

          throw response;
        });
    }

    createReportNode(report) {
      const wrapperId = `report_${report.id}`;
      const node = this.templates.report.content.cloneNode(true);
      node.querySelector(this.selectors.report.container).dataset.id = report.id;
      node.querySelector(this.selectors.report.date).textContent = report.createdAt;
      node.querySelector(this.selectors.report.button).dataset.target = `#${wrapperId}`;
      node.querySelector(this.selectors.report.itemsWrapper).id = wrapperId;

      let hiddenCount = 0;

      const itemsContainer = node.querySelector(this.selectors.report.items);
      for (const vulnerability of report.items) {
        itemsContainer.appendChild(this.createItemNode(vulnerability));
        if (vulnerability.hidden) {
          ++hiddenCount;
        }
      }

      const showHidden = node.querySelector(this.selectors.report.showHidden);
      showHidden.dataset.count = hiddenCount;
      if (0 === hiddenCount) {
        showHidden.style.display = 'none';
      } else {
        showHidden.textContent = showHidden.dataset.text.replace('{count}', hiddenCount);
      }

      return node;
    }

    createItemNode(vulnerability) {
      const node = this.templates.item.content.cloneNode(true);
      const container = node.querySelector(this.selectors.item.container);
      container.classList.add(this.getItemContainerClass(vulnerability.severity));
      container.dataset.uri = vulnerability.uri;
      container.dataset.hidden = vulnerability.hidden;

      const link = node.querySelector(this.selectors.item.identifier);
      link.href = vulnerability.source;
      link.textContent = vulnerability.identifier;

      node.querySelector(this.selectors.item.severity).textContent = this.translateSeverity(vulnerability.severity);
      node.querySelector(this.selectors.item.type).textContent = this.translateType(vulnerability.type);
      node.querySelector(this.selectors.item.description).textContent = vulnerability.description;
      node.querySelector(this.selectors.item.toggleHidden).textContent = vulnerability.hidden
        ? this.config.translations.item.show
        : this.config.translations.item.hide;

      const contactLink = node.querySelector(this.selectors.item.contactLink);
      const url = new URL(contactLink.href);
      const subject = contactLink.dataset.subject.replace('{vulnerability_id}', vulnerability.identifier);
      url.searchParams.set('subject', subject);
      url.search = url.search.replaceAll('+', '%20');
      contactLink.href = url.toString();

      return node;
    }

    async sendRequest(url, config = {}) {
      config.headers ??= {};
      config.headers.accept = 'application/json';

      return fetch(url, config);
    }

    translateType(value) {
      return this.config.translations.vulnerability.type[value] ?? value;
    }

    translateSeverity(value) {
      return this.config.translations.vulnerability.severity[value] ?? value;
    }

    getItemContainerClass(severity) {
      switch (severity) {
        case 'CRITICAL':
          return 'bg-dark';
        case 'HIGH':
          return 'bg-danger';
        case 'MEDIUM':
          return 'bg-warning';
        default:
          return 'bg-info';
      }
    }

    handleRequestError(error) {
      if (error instanceof Response) {
        this.handleResponseError(error);
      }

      console.log(error);
    }

    handleResponseError(response) {
      response.json().then((data) => {
        if ('error' in data) {
          showErrorMessage(data.error);
        }

        console.log(data);
      });
    }
  }

  const wrapper = document.getElementById('vulnerability-reports-wrapper');
  wrapper.style.removeProperty('display');

  const reportList = new VulnerabilityReportsList(wrapper, window.wnetSecurityConfig);
  reportList.init();

  window.psBilling.initialize(window.psBillingContext.context, '#ps-billing', '#ps-modal', (type) => {
    switch (type) {
      case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_CREATED:
      case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_UPDATED:
      case window.psBilling.EVENT_HOOK_TYPE.SUBSCRIPTION_REACTIVATED:
        window.wnetSecurityConfig.hasValidSubscription = true;
        reportList.init();
        break;
      default:
        break;
    }
  });
});