Merge pull request #272 from allerta-vvf/fix_csp

Better csp support
This commit is contained in:
Matteo Gheza 2021-05-29 00:04:43 +02:00 committed by GitHub
commit 9e70f1ee46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 250 additions and 100 deletions

View File

@ -41,7 +41,7 @@ tasks:
echo "$(tput setaf 2)Full webserver url$(tput sgr0) $(tput setaf 4)$WEBSERVER_URL$(tput sgr0)";
echo "$(tput setaf 2)Allerta username$(tput sgr0) $(tput setaf 4)admin$(tput sgr0)";
echo "$(tput setaf 2)Allerta password$(tput sgr0) $(tput setaf 4)password$(tput sgr0)";
echo "$(tput setaf 2)PHP Adminer url$(tput sgr0) $(tput setaf 4)$WEBSERVER_URL/adminer.php$(tput sgr0)";
echo "$(tput setaf 2)PHP Adminer$(tput sgr0) $(tput setaf 4)$WEBSERVER_URL/adminer.php$(tput sgr0)";
echo "$(tput setaf 2)DB user$(tput sgr0) $(tput setaf 4)allerta$(tput sgr0)";
echo "$(tput setaf 2)DB password$(tput sgr0) $(tput setaf 4)allerta_pwd$(tput sgr0)";
echo "$(tput setaf 2)DB name$(tput sgr0) $(tput setaf 4)allerta$(tput sgr0)";

View File

@ -6,6 +6,10 @@
{
"type": "vcs",
"url": "https://github.com/allerta-vvf/tiny-html-minifier"
},
{
"type": "vcs",
"url": "https://github.com/allerta-vvf/php-debugbar"
}
],
"require": {
@ -17,7 +21,7 @@
"ezyang/htmlpurifier": "^4.13",
"brick/phonenumber": "^0.2.2",
"sentry/sdk": "^3.1",
"maximebf/debugbar": "^1.16",
"maximebf/debugbar": "dev-master",
"azuyalabs/yasumi": "^2.4",
"ministryofweb/php-osm-tiles": "^2.0",
"jenstornell/tiny-html-minifier": "dev-master",

30
server/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b75ca84c59d5468883ebe8a230f59fe9",
"content-hash": "4c5225e9eaf82f46758dd24bc5717c7d",
"packages": [
{
"name": "azuyalabs/yasumi",
@ -876,16 +876,16 @@
},
{
"name": "maximebf/debugbar",
"version": "v1.16.5",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/maximebf/php-debugbar.git",
"reference": "6d51ee9e94cff14412783785e79a4e7ef97b9d62"
"url": "https://github.com/allerta-vvf/php-debugbar.git",
"reference": "f9b3c4b7c1a79db817435d3817c3a997101fefa9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/6d51ee9e94cff14412783785e79a4e7ef97b9d62",
"reference": "6d51ee9e94cff14412783785e79a4e7ef97b9d62",
"url": "https://api.github.com/repos/allerta-vvf/php-debugbar/zipball/f9b3c4b7c1a79db817435d3817c3a997101fefa9",
"reference": "f9b3c4b7c1a79db817435d3817c3a997101fefa9",
"shasum": ""
},
"require": {
@ -901,6 +901,7 @@
"monolog/monolog": "Log using Monolog",
"predis/predis": "Redis storage"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
@ -912,7 +913,6 @@
"DebugBar\\": "src/DebugBar/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -934,10 +934,9 @@
"debugbar"
],
"support": {
"issues": "https://github.com/maximebf/php-debugbar/issues",
"source": "https://github.com/maximebf/php-debugbar/tree/v1.16.5"
"source": "https://github.com/allerta-vvf/php-debugbar/tree/master"
},
"time": "2020-12-07T11:07:24+00:00"
"time": "2021-05-27T13:04:53+00:00"
},
{
"name": "ministryofweb/php-osm-tiles",
@ -998,12 +997,12 @@
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "b5543adef5e16738471a52fdf55ff802edf1141d"
"reference": "dafa1911fd7c1560c64d19556cbd4c599fed15ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5543adef5e16738471a52fdf55ff802edf1141d",
"reference": "b5543adef5e16738471a52fdf55ff802edf1141d",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/dafa1911fd7c1560c64d19556cbd4c599fed15ea",
"reference": "dafa1911fd7c1560c64d19556cbd4c599fed15ea",
"shasum": ""
},
"require": {
@ -1011,7 +1010,7 @@
},
"require-dev": {
"doctrine/coding-standard": "^9.0",
"phpbench/phpbench": "^1.0@beta",
"phpbench/phpbench": "^1.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12",
@ -1053,7 +1052,7 @@
"issues": "https://github.com/nikic/FastRoute/issues",
"source": "https://github.com/nikic/FastRoute/tree/master"
},
"time": "2021-04-27T09:57:16+00:00"
"time": "2021-05-24T09:28:21+00:00"
},
{
"name": "php-http/client-common",
@ -3135,6 +3134,7 @@
"minimum-stability": "stable",
"stability-flags": {
"nikic/fast-route": 20,
"maximebf/debugbar": 20,
"jenstornell/tiny-html-minifier": 20
},
"prefer-stable": false,

View File

@ -48,7 +48,17 @@ class tools
{
$this->db = $db;
$this->profiler_enabled = $profiler_enabled;
$this->script_nonce = $this->generateNonce(16);
if(defined("UI_MODE")){
if(isset($_SESSION["script_nonce"]) && (
(isset($_SERVER["HTTP_X_PJAX"]) || isset($_GET["X_PJAX"]) || isset($_GET["_PJAX"])) ||
strpos($_SERVER['REQUEST_URI'], "edit_")
)){
$this->script_nonce = $_SESSION["script_nonce"];
} else {
$this->script_nonce = $this->generateNonce(16);
$_SESSION["script_nonce"] = $this->script_nonce;
}
}
}
public function validate_form($data, $expected_value=null, $data_source=null)
@ -909,12 +919,13 @@ function init_class($enableDebugger=true, $headers=true)
if($headers) {
//TODO adding require-trusted-types-for 'script';
$script_nonce_csp = defined("UI_MODE") ? "'nonce-{$tools->script_nonce}' " : "";
$csp_rules = [
"default-src 'self' data: *.tile.openstreetmap.org nominatim.openstreetmap.org",
"connect-src 'self' *.sentry.io nominatim.openstreetmap.org",
"script-src 'nonce-{$tools->script_nonce}' 'self'",
"script-src {$script_nonce_csp}'self' 'unsafe-eval'",
"img-src 'self' data: *.tile.openstreetmap.org",
"object-src",
"object-src 'self'",
"style-src 'self' 'unsafe-inline'",
"base-uri 'self'"
];

View File

@ -1,6 +1,6 @@
<?php
function show_error_page($error=null, $error_message=null, $error_message_advanced=null){
global $webpack_manifest_path;
global $tools, $webpack_manifest_path;
$error = !is_null($error) ? $error : (isset($_GET["error"]) ? $_GET["error"] : 404);
if(is_null($error_message)){
switch ($error){
@ -65,6 +65,12 @@ function show_error_page($error=null, $error_message=null, $error_message_advanc
$key = isset($_GET["force_page"]) ? $_GET["force_page"] : array_rand($error_templates);
$credits = $credits_list[$key];
echo($error_templates[$key]);
$nonce = false;
try {
if (is_object($tools)) $nonce = $tools->script_nonce;
} catch (\Exception $e) {
}
?>
<br><br>
<?php
@ -80,8 +86,8 @@ if(!is_null($game_script_url)){
<div class="credits" style="position:absolute;opacity: 0.5;bottom: 5px;right: 5px;">
Error page based on work by <?php echo($credits); ?>.
</div>
<script src="<?php echo($main_script_url); ?>"></script>
<script src="<?php echo($game_script_url); ?>"></script>
<script src="<?php echo($main_script_url); ?>"<?php if($nonce){ echo("nonce='{$nonce}'"); } ?>></script>
<script src="<?php echo($game_script_url); ?>"<?php if($nonce){ echo("nonce='{$nonce}'"); } ?>></script>
<?php
}
}

View File

@ -43,6 +43,8 @@ $days = [
t("Sun",false)
];
$nonce = isset($_GET["nonce"]) ? $_GET["nonce"] : "";
$user_id = $user->auth->getUserId();
$result = $db->select("SELECT * FROM `".DB_PREFIX."_schedules` WHERE `user`={$user_id}");
if(!empty($result)){
@ -140,7 +142,15 @@ $holidays_select_none = t("Remove selections", false);
echo(<<<EOL
<div class="form-group">
<label>{$holidays_selection_question}</label>
<a onclick="$('.holiday_check').prop('checked', true);" class="text-primary">{$holidays_select_all}</a> / <a onclick="$('.holiday_check').prop('checked', false);" class="text-primary">{$holidays_select_none}</a>
<a id="select-all-holiday" class="text-primary">{$holidays_select_all}</a> / <a id="select-none-holiday" class="text-primary">{$holidays_select_none}</a>
<script nonce="{$nonce}">
$('#select-all-holiday').click(function(){
$('.holiday_check').prop('checked', true);
});
$('#select-none-holiday').click(function(){
$('.holiday_check').prop('checked', false);
});
</script>
EOL);
$i = 0;
@ -161,9 +171,9 @@ EOT);
echo("</div>");
?>
<script nonce="<?php echo(isset($_GET["nonce"]) ? $_GET["nonce"] : ""); ?>">
<script nonce="<?php echo($nonce); ?>">
function init_modal() {
<?php if($orienation == "landscape"){ ?>$(".modal-dialog").css("max-width", "99%");<?php } ?>
<?php if($orienation == "landscape"){ ?> $(".modal-dialog").css("max-width", "99%"); <?php } ?>
var isMouseDown = false;
$(document).mouseup(function () {
isMouseDown = false;

View File

@ -12,10 +12,9 @@ foreach(!is_null($result) ? $result : [] as $row){
if($user->requireRole(Role::FULL_VIEWER)){
$name = $user->nameById($row["id"]);
$name_encoded = urlencode($user->name());
$functionName = $row["available"] ? "allertaJS.main.deactivate" : "allertaJS.main.activate";
$helmet_colour = $row["chief"] ? "red" : "black";
$firstCell = "<a id='username-{$row['id']}' style='text-align: left;' onclick='$functionName(".$row["id"].",0);'><img alt='{$helmet_colour} helmet' src='./resources/images/{$helmet_colour}_helmet.png' width='20px'>$name</a>";
$secondCell = $row["available"] ? "<a onclick='$functionName(".$row["id"].",0);'><i class='fa fa-check' style='color:green'></i></a>" : "<a onclick='$functionName(".$row["id"].",0);'><i class='fa fa-times' style='color:red'></i></a>";
$firstCell = "<a id='username-{$row['id']}' style='text-align: left;'><img alt='{$helmet_colour} helmet' src='./resources/images/{$helmet_colour}_helmet.png' width='20px'>$name</a>";
$secondCell = $row["available"] ? "<a><i class='fa fa-check' style='color:green'></i></a>" : "<a><i class='fa fa-times' style='color:red'></i></a>";
$response[] = [
(time()-$row["online_time"])<=30 ? "<u>".$firstCell."</u>" : $firstCell,
$secondCell,

View File

@ -10,7 +10,7 @@ import "time-input-polyfill/auto";
import "jquery-pjax";
import toastr from "expose-loader?exposes=toastr!toastr";
import "toastr/build/toastr.css";
window.toastr = toastr;
toastr.options = {
closeButton: false,
@ -29,10 +29,10 @@ toastr.options = {
showMethod: "fadeIn",
hideMethod: "fadeOut"
};
$.fn.loading = function (action = "start", options) {
const opts = $.extend({}, $.fn.loading.defaults, options);
if (action === "show") {
this.addClass("loading_blur");
$("body").append("<div id='loading_div' class='loading_overlay'><p class=''><b>" + opts.message + "</b></p></div>");
@ -45,16 +45,16 @@ $.fn.loading = function (action = "start", options) {
$("#loading_div").remove();
}
};
$.fn.loading.defaults = {
message: "Loading..."
};
console.log("Commit: " + process.env.GIT_VERSION);
console.log("Date: " + process.env.GIT_AUTHOR_DATE);
console.log("Bundle mode: " + process.env.BUNDLE_MODE);
console.log("Bundle date: " + new Date(process.env.BUNDLE_DATE).toISOString());
$(document).pjax("a:not(.pjax_disable)", "#content", { timeout: 100000 });
$(document).on("pjax:start", function () {
if (document.getElementById("topNavBar") !== undefined) {
@ -68,7 +68,7 @@ $(document).on("pjax:start", function () {
loadTableInterval = undefined;
}
});
// Cookie functions from w3schools
function setCookie (cname, cvalue, exdays) {
const d = new Date();
@ -91,14 +91,14 @@ function getCookie (cname) {
}
return "";
}
$(document).ajaxError(function (event, xhr, settings, error) {
console.error("Error requesting content: " + error + " - status code " + xhr.status);
console.log(event);
console.log(xhr);
console.log(settings);
});
if (getCookie("authenticated")) {
var installServiceWorker = false;
if (window.skipServiceWorkerInstallation !== undefined) { // if you want to disable SW for example via GreasyFork userscript
@ -135,7 +135,7 @@ if (installServiceWorker) {
});
});
}
$(function () {
if ($("#frontend_version") !== undefined) {
$("#frontend_version").append(process.env.GIT_VERSION + " aggiornamento " + new Date(process.env.BUNDLE_DATE).toLocaleString());
@ -144,16 +144,16 @@ $(function () {
location.href="?JSless=0";
}
});
var offline = false;
var loadTableInterval = undefined;
var oldData = "null";
var tableEngine = "datatables";
var fillTable = undefined;
var fillTableLoaded = undefined;
window.addEventListener("securitypolicyviolation", console.error.bind(console));
$(function() {
$("#topNavBar").show();
$("#content").show();
@ -167,8 +167,17 @@ $(function() {
}
});
});
export async function loadTable ({ tablePage, setTableRefreshInterval = true, interval = 10000, onlineReload = false, useCustomTableEngine = false, callback = false }) {
export var lastTableLoadConfig = {
tablePage: undefined,
setTableRefreshInterval: true,
interval: 10000,
onlineReload: false,
useCustomTableEngine: false,
callback: false
}
export async function loadTable ({ tablePage, setTableRefreshInterval = true, interval = 10000, onlineReload = false, useCustomTableEngine = false, callbackRepeat = false, callback = false, saveFuncParam = true }) {
if(loadTableInterval !== undefined) {
clearInterval(loadTableInterval);
loadTableInterval = undefined;
@ -196,6 +205,16 @@ export async function loadTable ({ tablePage, setTableRefreshInterval = true, in
if ("deviceMemory" in navigator && navigator.deviceMemory < 0.2) {
return;
}
if(saveFuncParam){
lastTableLoadConfig = {
tablePage: tablePage,
setTableRefreshInterval: setTableRefreshInterval,
interval: interval,
onlineReload: onlineReload,
useCustomTableEngine: useCustomTableEngine,
callback: callback
}
}
const replaceLatLngWithMap = tablePage === "services" || tablePage === "trainings";
$.getJSON({
url: "resources/ajax/ajax_" + tablePage + ".php",
@ -250,11 +269,25 @@ export async function loadTable ({ tablePage, setTableRefreshInterval = true, in
}
console.log("table_load interval " + interval);
loadTableInterval = setInterval(function () {
loadTable({ tablePage, setTableRefreshInterval: false, interval, onlineReload, useCustomTableEngine, callback: false });
loadTable({ tablePage, setTableRefreshInterval: false, interval, onlineReload, useCustomTableEngine, callback: callbackRepeat ? callback : false, saveFuncParam: false });
}, interval);
}
}
export function reloadTable(){
allertaJS.main.loadTable({
tablePage: lastTableLoadConfig.tablePage,
setTableRefreshInterval: lastTableLoadConfig.setTableRefreshInterval,
interval: lastTableLoadConfig.interval,
onlineReload: lastTableLoadConfig.onlineReload,
useCustomTableEngine: lastTableLoadConfig.useCustomTableEngine,
callback: lastTableLoadConfig.callback,
});
if (loadTableInterval !== undefined) {
clearInterval(loadTableInterval);
loadTableInterval = undefined;
}
}
export function activate(id, token_list) {
$.ajax({
url: "resources/ajax/ajax_change_availability.php",
@ -268,11 +301,11 @@ export function activate(id, token_list) {
success: function (data) {
console.log(data);
toastr.success(data.message);
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
allertaJS.main.reloadTable();
}
});
}
export function deactivate(id, token_list) {
$.ajax({
url: "resources/ajax/ajax_change_availability.php",
@ -286,7 +319,7 @@ export function deactivate(id, token_list) {
success: function (data) {
console.log(data);
toastr.success(data.message);
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
allertaJS.main.reloadTable();
}
});
}
}

View File

@ -18,9 +18,9 @@ const iconDefault = new L.Icon({
shadowSize: [41, 41]
});
let marker;
let feature;
let map;
var marker;
var feature;
var map;
export function setMarker (LatLng, move=false) {
if (marker) {
@ -32,6 +32,7 @@ export function setMarker (LatLng, move=false) {
if ($("input[name='place']").val() !== undefined) {
$("input[name='place']").val(LatLng.lat + ";" + LatLng.lng);
}
console.log(map);
marker = L.marker(LatLng, { icon: iconDefault }).addTo(map);
if(move){
map.setView(LatLng, 17);
@ -51,16 +52,23 @@ export function loadMap (lat = undefined, lng = undefined, selectorId = undefine
selectorId = "map";
}
let container = L.DomUtil.get(selectorId);
if(container._leaflet_id){
console.log(mapsList);
if(removeMap){
mapsList[0].off();
mapsList[0].remove();
mapsList.splice(0, 1);
} else {
console.log("Skipping map loading because already loaded...");
return true;
console.log(container);
try{
if(container._leaflet_id){
console.log(mapsList);
if(removeMap){
mapsList[0].off();
mapsList[0].remove();
mapsList.splice(0, 1);
} else {
console.log("Skipping map loading because already loaded...");
return true;
}
}
} catch(e){
//console.log(e);
console.log("Skipping map loading...");
return true;
}
const zoom = select ? 10 : 17;
const latLng = new L.LatLng(lat, lng);
@ -210,19 +218,53 @@ export function addrSearch (stringResultsFound= undefined, stringResultsNotFound
}
} else if (!checkClipboard) {
$.getJSON("https://nominatim.openstreetmap.org/search?format=json&limit=5&q=" + inp, function (data) {
const items = [];
console.log(data);
var list = document.createElement('ul');
list.classList.add("results-list");
$.each(data, function (key, val) {
items.push("<li><a href='' onclick='allertaJS.maps.chooseAddr(\"" + val.lat + "\", \"" + val.lon + "\", undefined, " + val.boundingbox[0] + ", " + val.boundingbox[2] + ", " + val.boundingbox[1] + ", " + val.boundingbox[3] + ", \"" + val.osm_type + "\"); return false;'>" + val.display_name + "</a></li>");
var item_a = document.createElement('a');
item_a.href = "#";
item_a.textContent = val.display_name;
item_a.dataset.addrLat = val.lat;
item_a.dataset.addrLng = val.lon;
item_a.dataset.zoom = undefined;
item_a.dataset.lat1 = val.boundingbox[0];
item_a.dataset.lng1 = val.boundingbox[2];
item_a.dataset.lat2 = val.boundingbox[1];
item_a.dataset.lng2 = val.boundingbox[3];
item_a.dataset.osmType = val.osm_type;
var item = document.createElement('li');
item.appendChild(item_a);
list.appendChild(item);
});
if (items.length !== 0) {
console.log(list);
if (data.length !== 0) {
$("#results").empty();
$("<p>", { html: stringResultsFound+ ":" }).appendTo("#results");
$("<ul/>", {
class: "results-list",
html: items.join("")
}).appendTo("#results");
$(list).appendTo("#results");
$("#results li").click(function(e){
e.preventDefault()
var row = e.target;
console.log(row);
console.log(row.dataset);
allertaJS.maps.chooseAddr(
row.dataset.addrLat,
row.dataset.addrLng,
row.dataset.zoom,
row.dataset.lat1,
row.dataset.lng1,
row.dataset.lat2,
row.dataset.lng2,
row.dataset.osmType
);
})
} else {
$("#results").empty();
$("<p>", { html: stringResultsNotFound }).appendTo("#results");
@ -232,3 +274,10 @@ export function addrSearch (stringResultsFound= undefined, stringResultsNotFound
return false;
}
}
$(function () {
if(typeof loadMapOnScriptLoad !== undefined){
console.log("Loading map...");
allertaJS.maps.loadMap();
}
});

View File

@ -41,7 +41,7 @@ TODO
{% endif %}
{% endfor %}
</div>
<script>
<script nonce="{{ nonce }}">
$('.chief').on('change', function () {
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
});
@ -87,14 +87,14 @@ TODO
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
<button id="search_button" type="button" class="btn btn-primary mb-2">
{{ 'Search'|t }}
</button>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
{{ script('maps.js', 'allertaJS.maps.loadMap();') }}
{% else %}
<div class="form-group">
<label>{{ 'Service place'|t }}</label>
@ -127,7 +127,7 @@ TODO
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
</div>
</form>
<script>
<script nonce="{{ nonce }}">
$( "#types" ).change(function() {
$('#empty_option').remove();
var type = "";
@ -198,7 +198,7 @@ TODO
<input id="id" type="hidden" value="{{ service.id }}" name="id"></input>
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
</form>
<script>
<script nonce="{{ nonce }}">
$('form').submit(function () {
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
});

View File

@ -41,7 +41,7 @@ TODO
{% endif %}
{% endfor %}
</div>
<script>
<script nonce="{{ nonce }}">
$('.chief').on('change', function () {
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
});
@ -71,14 +71,14 @@ TODO
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
<button id="search_button" type="button" class="btn btn-primary mb-2">
{{ 'Search'|t }}
</button>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
{{ script('maps.js', 'allertaJS.maps.loadMap();') }}
{% else %}
<div class="form-group">
<label for="place">{{ 'Training place'|t }}</label>
@ -97,7 +97,7 @@ TODO
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
</div>
</form>
<script>
<script nonce="{{ nonce }}">
{% if training.modalità == "edit" %}
{% if option('use_location_picker') %}
{% set place = values.place|split('#')[0] %}
@ -122,7 +122,7 @@ TODO
<input id="id" type="hidden" value="{{ training.id }}" name="id"></input>
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
</form>
<script>
<script nonce="{{ nonce }}">
$('form').submit(function () {
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
});

View File

@ -70,7 +70,7 @@ TODO
<input id="id" type="hidden" value="{{ id }}" name="id"></input>
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
</form>
<script>
<script nonce="{{ nonce }}">
$('form').submit(function () {
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
});

View File

@ -62,9 +62,12 @@
<a href="{{ urlsoftware }}trainings.php">{{ 'Trainings'|t }}</a>
<a href="{{ urlsoftware }}log.php">{{ 'Logs'|t }}</a>
<a style="float: right;" id="logout">{{ 'Hi, %s.'|t|format(user.name) }} <b
onclick="location.href='{{ urlsoftware }}logout.php';">{{ 'Logout'|t }}</b></a>
id="logout-text">{{ 'Logout'|t }}</b></a>
<a class="pjax_disable icon" id="menuButton"></a>
</div>
<script nonce="{{ nonce }}">
$("#logout-text").click(function(){ location.href='{{ urlsoftware }}logout.php'; });
</script>
{# /Menu #}
{% endblock %}
{% endif %}

View File

@ -86,14 +86,21 @@
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
<button id="search_button" type="button" class="btn btn-primary mb-2">
{{ 'Search'|t }}
</button>
<script nonce="{{ nonce }}">
$("#search_button").click(function(){
allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');
});
</script>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
{{ script('maps.js', 'allertaJS.maps.loadMap();') }}
<script nonce="{{ nonce }}">window.loadMapOnScriptLoad = true;</script>
{{ script('maps.js') }}
{% else %}
<div class="form-group">
<label>{{ 'Service place'|t }}</label>
@ -154,7 +161,9 @@
{% if service.modalità == "edit" %}
{% if option('use_location_picker') %}
{% set place = values.place|split('#')[0] %}
allertaJS.maps.setMarker(new L.LatLng({{place|split(';')[0]}}, {{place|split(';')[1]}}), true);
$(function(){
allertaJS.maps.setMarker(new L.LatLng({{place|split(';')[0]}}, {{place|split(';')[1]}}), true);
});
{% endif %}
$.each('{{ values.chief }}'.split(','), function (index, value) {
$('.chief-' + value).prop('checked', true);
@ -208,4 +217,4 @@
{% block footer %}
{% endblock %}
{% endblock %}
{% endblock %}

View File

@ -70,14 +70,21 @@
<input type="text" class="form-control" name="addr" value="" id="addr" size="50" />
</div>
<div class="form-group mx-sm-3 mb-2">
<button id="search_button" type="button" onclick="allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');"
class="btn btn-primary mb-2">{{ 'Search'|t }}</button>
<button id="search_button" type="button" class="btn btn-primary mb-2">
{{ 'Search'|t }}
</button>
<script nonce="{{ nonce }}">
$("#search_button").click(function(){
allertaJS.maps.addrSearch('{{ 'Search results'|t }}', '{{ 'No results found'|t }}');
});
</script>
</div>
</div>
<div id="results"></div>
</div>
<input type="hidden" name="place" value="" />
{{ script('maps.js', 'allertaJS.maps.loadMap();') }}
<script nonce="{{ nonce }}">window.loadMapOnScriptLoad = true;</script>
{{ script('maps.js') }}
{% else %}
<div class="form-group">
<label for="place">{{ 'Training place'|t }}</label>
@ -100,7 +107,9 @@
{% if training.modalità == "edit" %}
{% if option('use_location_picker') %}
{% set place = values.place|split('#')[0] %}
allertaJS.maps.setMarker(new L.LatLng({{place|split(';')[0]}}, {{place|split(';')[1]}}), true);
$(function(){
allertaJS.maps.setMarker(new L.LatLng({{place|split(';')[0]}}, {{place|split(';')[1]}}), true);
});
{% endif %}
$.each('{{ values.chief|striptags|e("js") }}'.split(','), function (index, value) {
$('.chief-' + value).prop('checked', true);

View File

@ -36,9 +36,8 @@
</div>
<div class="text-center">
<p>{{ 'Are you available in case of alert?'|t }}</p>
<button class="btn btn-lg btn-success" onclick="allertaJS.main.activate('{{ user.id }}', '')">{{ 'Activate'|t }}</button>
<button class="btn btn-lg btn-danger" style="background-color: red"
onclick="allertaJS.main.deactivate('{{ user.id }}', '')">{{ 'Deactivate'|t }}</button>
<button id="activate-btn" class="btn btn-lg btn-success">{{ 'Activate'|t }}</button>
<button id="deactivate-btn" class="btn btn-lg btn-danger" style="background-color: red">{{ 'Deactivate'|t }}</button>
<br>
<button type="button" class="btn btn-lg" data-toggle="modal" data-target="#schedulesModal">
{{ 'Edit availability schedules'|t }}
@ -70,7 +69,26 @@
</tbody>
</table>
<script nonce="{{ nonce }}">
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
$("#activate-btn").click(function(){
allertaJS.main.activate('{{ user.id }}', '');
});
$("#deactivate-btn").click(function(){
allertaJS.main.deactivate('{{ user.id }}', '');
});
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default", callbackRepeat: true, callback: function() {
$("tbody tr").each(function(key, el) {
$(el.children[1]).click(function(event) {
console.log(event.target);
userId = event.target.parentElement.parentElement.parentElement.firstElementChild.firstElementChild.firstElementChild.id.replace("username-","");
console.log(userId);
if(event.target.classList.contains("fa-times")) {
allertaJS.main.activate(userId,0);
} else {
allertaJS.main.deactivate(userId,0);
}
});
});
}});
</script>
</div>

View File

@ -1,4 +1,5 @@
<?php
define("UI_MODE", true);
require_once 'core.php';
init_class();
@ -10,6 +11,7 @@ if(!is_null($debugbar)){
$debugbarRenderer->disableVendor("jquery");
$debugbarRenderer->setEnableJqueryNoConflict(false);
$debugbarRenderer->setOpenHandlerUrl('debug_open.php');
$debugbarRenderer->setJSNonce($nonce);
} else {
$enable_debugbar = false;
}
@ -95,15 +97,12 @@ $function_resource = new \Twig\TwigFunction(
$twig->addFunction($function_resource);
$function_script = new \Twig\TwigFunction(
'script', function ($file, $onLoad=false) {
'script', function ($file) {
global $nonce, $url_software, $webpack_manifest;
$script_url = $url_software . "/resources/dist/" . $webpack_manifest[$file]["src"];
$script_integrity = $webpack_manifest[$file]["integrity"];
$script_tag = "<script src='{$script_url}' integrity='{$script_integrity}' crossorigin='anonymous' nonce='".$nonce."'";
if($onLoad){
$script_tag .= " onload='{$onLoad}'";
}
$script_tag .= "></script>";
return $script_tag;
}, ['is_safe' => ['html']]