Merge branch 'develop' into 1.9

# Conflicts:
#	languages/en.yaml
#	themes/grav/css-compiled/preset.css
#	themes/grav/css-compiled/preset.css.map
#	themes/grav/js/admin.min.js
#	themes/grav/js/vendor.min.js
#	themes/grav/scss/preset.scss
This commit is contained in:
Andy Miller
2018-09-29 21:47:54 -06:00
14 changed files with 669 additions and 989 deletions

2
.gitignore vendored
View File

@@ -6,7 +6,7 @@ themes/grav/.sass-cache
themes/grav/js/admin.js
themes/grav/js/vendor.js
themes/grav/js/*.map
/.idea
.idea
tests/_output/*
tests/_support/_generated/*

View File

@@ -2,6 +2,7 @@
## mm/dd/2018
1. [](#new)
* IMPORTANT: Non `admin.super` users are now subject to XSS validation in Page content. Configurable via Configuration / Security
* Added new event `onAdminPage` which allows plugins to customize `Page` object in `$event['page']`
1. [](#improved)
* Use `Url:post()` to get the `$_POST` variable (allows common security checks/filtering for the POST data)

View File

@@ -611,6 +611,8 @@ class AdminController extends AdminBaseController
$reorder = true;
$data = (array)$this->data;
$this->grav['twig']->twig_vars['current_form_data'] = $data;
// Special handler for user data.
if ($this->view === 'user') {
if (!$this->grav['user']->exists()) {
@@ -645,10 +647,20 @@ class AdminController extends AdminBaseController
// Ensure route is prefixed with a forward slash.
$route = '/' . ltrim($route, '/');
// XSS Checks for page content
$xss_whitelist = $this->grav['config']->get('security.xss_whitelist', 'admin.super');
if (!$this->admin->authorize($xss_whitelist)) {
if ($issue = Utils::detectXss($data['content'])) {
$this->admin->setMessage(sprintf($this->admin->translate('PLUGIN_ADMIN.XSS_ISSUE'), $issue),
'error');
return false;
}
}
// Check for valid frontmatter
if (isset($data['frontmatter']) && !$this->checkValidFrontmatter($data['frontmatter'])) {
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.INVALID_FRONTMATTER_COULD_NOT_SAVE'),
'error');
return false;
}

View File

@@ -755,4 +755,14 @@ PLUGIN_ADMIN:
SCHEDULER_POST_INSTRUCTIONS: "To enable the Scheduler's functionality, you must add the <b>Grav Scheduler</b> to your system's crontab file. Run the command above from the terminal to add it automatically. Once saved, refresh this page to see the status Ready."
SCHEDULER_JOBS: "Custom Scheduler Jobs"
SCHEDULER_STATUS: "Scheduler Status"
SECURITY: "Security"
XSS_SECURITY: "XSS Security"
XSS_WHITELIST_PERMISSIONS: "Whitelist Permissions"
XSS_WHITELIST_PERMISSIONS_HELP: "Users with these permissions will skip the XSS rules when saving content"
XSS_RULES: "Rules"
XSS_RULES_HELP: "Be careful when tweaking these rules, a broken regex will break things badly!"
XSS_RULE_LABEL: "Label"
XSS_RULE_REGEX: "Regex"
XSS_ISSUE: "Save failed: Found potential XSS code of type: <strong>%s</strong>, please remove or disable the XSS filter in <strong>Configuration</strong> / <strong>Security</strong>."

View File

@@ -14,12 +14,7 @@ import request from './utils/request';
import './utils/2fa';
// bootstrap jQuery extensions
// import 'bootstrap/js/transition';
// import 'bootstrap/js/dist/util';
// import 'bootstrap/js/dist/dropdown';
// import 'bootstrap/js/dist/collapse';
import './utils/bootstrap-transition';
import './utils/bootstrap-dropdown';
import './utils/bootstrap-collapse';
// tabs memory

View File

@@ -138,7 +138,7 @@ import jQuery from 'jquery';
};
Collapse.prototype.getParent = function() {
return $(document).find(this.options.parent)
return $(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function(i, element) {
var $element = $(element);
@@ -161,7 +161,7 @@ import jQuery from 'jquery';
var target = $trigger.attr('data-target') ||
(href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, ''); // strip for ie7
return $(document).find(target);
return $(target);
}
// COLLAPSE PLUGIN DEFINITION

View File

@@ -1,163 +0,0 @@
import jQuery from 'jquery';
/* ========================================================================
* Bootstrap: dropdown.js v3.4.0
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+(function($) {
'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop';
var toggle = '[data-toggle="dropdown"]';
var Dropdown = function(element) {
$(element).on('click.bs.dropdown', this.toggle);
};
Dropdown.VERSION = '3.4.0';
function getParent($this) {
var selector = $this.attr('data-target');
if (!selector) {
selector = $this.attr('href');
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); // strip for ie7
}
var $parent = selector && $(document).find(selector);
return $parent && $parent.length ? $parent : $this.parent();
}
function clearMenus(e) {
if (e && e.which === 3) return;
$(backdrop).remove();
$(toggle).each(function() {
var $this = $(this);
var $parent = getParent($this);
var relatedTarget = { relatedTarget: this };
if (!$parent.hasClass('open')) return;
if (e && e.type === 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return;
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget));
if (e.isDefaultPrevented()) return;
$this.attr('aria-expanded', 'false');
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget));
});
}
Dropdown.prototype.toggle = function(e) {
var $this = $(this);
if ($this.is('.disabled, :disabled')) return;
var $parent = getParent($this);
var isActive = $parent.hasClass('open');
clearMenus();
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$(document.createElement('div'))
.addClass('dropdown-backdrop')
.insertAfter($(this))
.on('click', clearMenus);
}
var relatedTarget = { relatedTarget: this };
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget));
if (e.isDefaultPrevented()) return;
$this
.trigger('focus')
.attr('aria-expanded', 'true');
$parent
.toggleClass('open')
.trigger($.Event('shown.bs.dropdown', relatedTarget));
}
return false;
};
Dropdown.prototype.keydown = function(e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return;
var $this = $(this);
e.preventDefault();
e.stopPropagation();
if ($this.is('.disabled, :disabled')) return;
var $parent = getParent($this);
var isActive = $parent.hasClass('open');
if (!isActive && e.which !== 27 || isActive && e.which === 27) {
if (e.which === 27) $parent.find(toggle).trigger('focus');
return $this.trigger('click');
}
var desc = ' li:not(.disabled):visible a';
var $items = $parent.find('.dropdown-menu' + desc);
if (!$items.length) return;
var index = $items.index(e.target);
if (e.which === 38 && index > 0) index--; // up
if (e.which === 40 && index < $items.length - 1) index++; // down
if (!~index) index = 0;
$items.eq(index).trigger('focus');
};
// DROPDOWN PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function() {
var $this = $(this);
var data = $this.data('bs.dropdown');
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)));
if (typeof option === 'string') data[option].call($this);
});
}
var old = $.fn.dropdown;
$.fn.dropdown = Plugin;
$.fn.dropdown.Constructor = Dropdown;
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function() {
$.fn.dropdown = old;
return this;
};
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function(e) { e.stopPropagation(); })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown);
}(jQuery));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,6 @@
"author": "RocketTheme, LLC",
"license": "MIT",
"dependencies": {
"bootstrap": "^4.1.3",
"chartist": "0.11.0",
"codemirror": "^5.30.0",
"cookies-js": "^1.2.3",

View File

@@ -567,6 +567,16 @@ tr {
}
}
.sidebar-mobile-open {
#admin-main {
.lines-button {
.lines, .lines:before, .lines:after {
background: $logo-link;
}
}
}
}
#admin-dashboard {
.admin-block {

View File

@@ -32,13 +32,13 @@
{% if field.resizer is not defined or field.resizer not in ['off', 'false', 0] %}<div class="grav-editor-resizer"></div>{% endif %}
{% if field.description %}
<div class="form-extra-wrapper {{ field.size }} {{ field.wrapper_classes }}">
<span class="form-description">
{% if field.markdown %}
{{ field.description|tu|markdown(false)|raw }}
{% else %}
{{ field.description|tu|raw }}
{% endif %}
</span>
<span class="form-description">
{% if field.markdown %}
{{ field.description|tu|markdown(false)|raw }}
{% else %}
{{ field.description|tu|raw }}
{% endif %}
</span>
</div>
{% endif %}
</div>

View File

@@ -132,6 +132,7 @@
{% endif %}
{% block titlebar %}
<div class="button-bar">
{% if mode == 'list' %}
<a class="button" href="{{ base_url }}"><i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|tu }}</a>
@@ -319,6 +320,10 @@
</div>
{# Set current form data back into page content #}
{% if current_form_data %}
{% do context.content(current_form_data.content) %}
{% endif %}
{% if context.blueprints.fields and admin.session.expert == '0' %}
{% include 'partials/blueprints.html.twig' with { blueprints: context.blueprints, data: context } %}
{% else %}

File diff suppressed because it is too large Load Diff