From c1b86fe3d2309d9f344520001f9360d0ef6fa49a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 16:16:11 -0700 Subject: [PATCH 01/42] Update progress.js to only track total number of downloads --- scripts/system/progress.js | 78 +++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index c6537eef52..a072378dd6 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -39,6 +39,7 @@ background2D = {}, bar2D = {}, SCALE_2D = 0.35, // Scale the SVGs for 2D display. + //SCALE_2D = 1.0, // Scale the SVGs for 2D display. background3D = {}, bar3D = {}, PROGRESS_3D_DIRECTION = 0.0, // Degrees from avatar orientation. @@ -96,19 +97,41 @@ }); } + var maxSeen = 0; + var bestRawProgress = 0; + var wasActive = false; function onDownloadInfoChanged(info) { var i; // Update raw progress value if (info.downloading.length + info.pending === 0) { + wasActive = false; rawProgress = 100; + bestRawProgress = 100; } else { - rawProgress = 0; - for (i = 0; i < info.downloading.length; i += 1) { - rawProgress += info.downloading[i]; + var count = info.downloading.length + info.pending; + if (!wasActive) { + wasActive = true; + if (count > maxSeen) { + maxSeen = count; + } + bestRawProgress = 0; + } + //for (i = 0; i < info.downloading.length; i += 1) { + //rawProgress += info.downloading[i]; + //} + //rawProgress = rawProgress / (info.downloading.length + info.pending); + rawProgress = ((maxSeen - count) / maxSeen) * 100; + //rawProgress += 1; + //if (rawProgress > 90) { + //rawProgress = 20 + //} + + if (rawProgress > bestRawProgress) { + bestRawProgress = rawProgress; } - rawProgress = rawProgress / (info.downloading.length + info.pending); } + //print(rawProgress, bestRawProgress, maxSeen); } function createOverlays() { @@ -126,9 +149,9 @@ bar3D.overlay = Overlays.addOverlay("image3d", { url: BAR_URL, subImage: { - x: BAR_WIDTH, + x: 0, y: 0, - width: BAR_WIDTH, + width: 480, height: BAR_HEIGHT }, scale: SCALE_3D * BAR_WIDTH, @@ -150,7 +173,7 @@ bar2D.overlay = Overlays.addOverlay("image", { imageURL: BAR_URL, subImage: { - x: BAR_WIDTH, + x: 0, y: 0, width: BAR_WIDTH, height: BAR_HEIGHT @@ -168,16 +191,30 @@ Overlays.deleteOverlay(isOnHMD ? bar3D.overlay : bar2D.overlay); } + var b = 0; function update() { + /* + maxSeen = 100; + b++; + rawProgress = b; + if (rawProgress == 100) { + b = 0 + } + bestRawProgress = rawProgress; + print(rawProgress, bestRawProgress); + */ + + //print(rawProgress, bestRawProgress, maxSeen); var viewport, eyePosition, avatarOrientation; - if (isOnHMD !== HMD.active) { - deleteOverlays(); - isOnHMD = !isOnHMD; - createOverlays(); - } + hmdActive = HMD.active; + //if (isOnHMD !== HMD.active) { + //deleteOverlays(); + //isOnHMD = !isOnHMD; + //createOverlays(); + //} // Calculate progress value to display if (rawProgress === 0 && displayProgress <= DISPLAY_PROGRESS_MINOR_MAXIMUM) { @@ -187,6 +224,7 @@ } else if (rawProgress > displayProgress) { displayProgress = Math.min(rawProgress, displayProgress + DISPLAY_PROGRESS_MAJOR_INCREMENT); } // else (rawProgress === displayProgress); do nothing. + displayProgress = bestRawProgress; // Update state if (!visible) { // Not visible because no recent downloads @@ -232,7 +270,7 @@ y: 0, width: BAR_WIDTH, height: BAR_HEIGHT - } + }, }); // Update position @@ -258,20 +296,25 @@ windowWidth = viewport.x; windowHeight = viewport.y; + var yOffset = hmdActive ? -300 : 0; + Overlays.editOverlay(background2D.overlay, { x: windowWidth / 2 - background2D.width / 2, - y: windowHeight - background2D.height - bar2D.height + y: windowHeight - background2D.height - bar2D.height + yOffset }); Overlays.editOverlay(bar2D.overlay, { x: windowWidth / 2 - bar2D.width / 2, - y: windowHeight - background2D.height - bar2D.height + (background2D.height - bar2D.height) / 2 + y: windowHeight - background2D.height - bar2D.height + (background2D.height - bar2D.height) / 2 + yOffset }); } } } } + function setProgressBar(progress) { + } + function setUp() { background2D.width = SCALE_2D * BACKGROUND_WIDTH; background2D.height = SCALE_2D * BACKGROUND_HEIGHT; @@ -302,6 +345,7 @@ setUp(); GlobalServices.downloadInfoChanged.connect(onDownloadInfoChanged); GlobalServices.updateDownloadInfo(); - Script.update.connect(update); + //Script.update.connect(update); + Script.setInterval(update, 16); Script.scriptEnding.connect(tearDown); -}()); \ No newline at end of file +}()); From 873e7b63dfe7366e487111695523d31a5b1b9a36 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 16:26:12 -0700 Subject: [PATCH 02/42] Update progress-bar.svg --- scripts/system/assets/images/progress-bar.svg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/assets/images/progress-bar.svg b/scripts/system/assets/images/progress-bar.svg index 0df6f98686..bd35b4ce53 100644 --- a/scripts/system/assets/images/progress-bar.svg +++ b/scripts/system/assets/images/progress-bar.svg @@ -1,7 +1,7 @@ - - + viewBox="0 0 960 30" enable-background="new -159 536 960 30" xml:space="preserve"> + + From a786224297f229728af9c2dbce03ccce7b352885 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 16:55:45 -0700 Subject: [PATCH 03/42] Add easing back to progress.js --- scripts/system/progress.js | 58 ++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index a072378dd6..dcd52bce98 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -100,9 +100,11 @@ var maxSeen = 0; var bestRawProgress = 0; var wasActive = false; + var cooldown = 1000; function onDownloadInfoChanged(info) { var i; + print("PROGRESS: DOwnload info changed ", info.downloading.length, info.pending, maxSeen); // Update raw progress value if (info.downloading.length + info.pending === 0) { wasActive = false; @@ -112,26 +114,33 @@ var count = info.downloading.length + info.pending; if (!wasActive) { wasActive = true; - if (count > maxSeen) { - maxSeen = count; - } + maxSeen = count; bestRawProgress = 0; + rawProgress = 0; + cooldown = 2000; + displayProgress = 0; } - //for (i = 0; i < info.downloading.length; i += 1) { - //rawProgress += info.downloading[i]; - //} - //rawProgress = rawProgress / (info.downloading.length + info.pending); - rawProgress = ((maxSeen - count) / maxSeen) * 100; - //rawProgress += 1; - //if (rawProgress > 90) { - //rawProgress = 20 - //} + if (count > maxSeen) { + maxSeen = count; + } + if (cooldown < 0) { + print("PROGRESS: OUT OF COOLDOWN"); + //for (i = 0; i < info.downloading.length; i += 1) { + //rawProgress += info.downloading[i]; + //} + //rawProgress = rawProgress / (info.downloading.length + info.pending); + rawProgress = ((maxSeen - count) / maxSeen) * 100; + //rawProgress += 1; + //if (rawProgress > 90) { + //rawProgress = 20 + //} - if (rawProgress > bestRawProgress) { - bestRawProgress = rawProgress; + if (rawProgress > bestRawProgress) { + bestRawProgress = rawProgress; + } } } - //print(rawProgress, bestRawProgress, maxSeen); + print("PROGRESS:", rawProgress, bestRawProgress, maxSeen); } function createOverlays() { @@ -193,6 +202,7 @@ var b = 0; function update() { + cooldown -= 16; /* maxSeen = 100; b++; @@ -216,6 +226,7 @@ //createOverlays(); //} + /* // Calculate progress value to display if (rawProgress === 0 && displayProgress <= DISPLAY_PROGRESS_MINOR_MAXIMUM) { displayProgress = Math.min(displayProgress + DISPLAY_PROGRESS_MINOR_INCREMENT, DISPLAY_PROGRESS_MINOR_MAXIMUM); @@ -224,7 +235,18 @@ } else if (rawProgress > displayProgress) { displayProgress = Math.min(rawProgress, displayProgress + DISPLAY_PROGRESS_MAJOR_INCREMENT); } // else (rawProgress === displayProgress); do nothing. - displayProgress = bestRawProgress; + //displayProgress = bestRawProgress; + //*/ + if (displayProgress < rawProgress) { + var diff = rawProgress - displayProgress; + if (diff < 0.1) { + displayProgress = rawProgress; + } else { + displayProgress += diff * 0.2; + } + } + print('PROGRESS:', displayProgress); + // Update state if (!visible) { // Not visible because no recent downloads @@ -235,7 +257,7 @@ } } else if (alphaDelta !== 0.0) { // Fading in or out if (alphaDelta > 0) { - if (displayProgress === 100) { // Was downloading but now have finished so fade out + if (rawProgress === 100) { // Was downloading but now have finished so fade out alphaDelta = ALPHA_DELTA_OUT; } } else { @@ -245,7 +267,7 @@ } } else { // Fully visible because downloading or recently so if (fadeWaitTimer === null) { - if (displayProgress === 100) { // Was downloading but have finished so fade out soon + if (rawProgress === 100) { // Was downloading but have finished so fade out soon fadeWaitTimer = Script.setTimeout(function() { alphaDelta = ALPHA_DELTA_OUT; fadeTimer = Script.setInterval(fade, FADE_INTERVAL); From 58932a6806f726b2337c94166d80b567d3d7f208 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 17:13:05 -0700 Subject: [PATCH 04/42] Add reset of progress bar when domain changes --- scripts/system/progress.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index dcd52bce98..660dfc4b98 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -96,6 +96,15 @@ visible: visible }); } + function resetProgress() { + wasActive = true; + bestRawProgress = 0; + rawProgress = 0; + cooldown = 1000; + displayProgress = 0; + } + + Window.domainChanged.connect(resetProgress); var maxSeen = 0; var bestRawProgress = 0; @@ -113,12 +122,8 @@ } else { var count = info.downloading.length + info.pending; if (!wasActive) { - wasActive = true; + resetProgress(); maxSeen = count; - bestRawProgress = 0; - rawProgress = 0; - cooldown = 2000; - displayProgress = 0; } if (count > maxSeen) { maxSeen = count; @@ -242,7 +247,7 @@ if (diff < 0.1) { displayProgress = rawProgress; } else { - displayProgress += diff * 0.2; + displayProgress += diff * 0.1; } } print('PROGRESS:', displayProgress); From 91f847a7f0aa8561a63119bb612d6b9c4e2e34b7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 28 Jul 2016 17:24:35 -0700 Subject: [PATCH 05/42] Update progress bar image --- scripts/system/assets/images/progress-bar.svg | 9 +++++++-- scripts/system/progress.js | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/system/assets/images/progress-bar.svg b/scripts/system/assets/images/progress-bar.svg index bd35b4ce53..360aa3f1a9 100644 --- a/scripts/system/assets/images/progress-bar.svg +++ b/scripts/system/assets/images/progress-bar.svg @@ -1,7 +1,12 @@ - - + + + + + + + diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 660dfc4b98..fc813ada88 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -250,7 +250,7 @@ displayProgress += diff * 0.1; } } - print('PROGRESS:', displayProgress); + //print('PROGRESS:', displayProgress); // Update state From 6279b96223aaa24d90f994b39f001e669c0c9b22 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 29 Jul 2016 10:11:12 -0700 Subject: [PATCH 06/42] Add minor tweaks to progress.js --- scripts/system/progress.js | 60 ++++++++++---------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index fc813ada88..0628974043 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -28,10 +28,10 @@ FADE_OUT_WAIT = 1000, // Wait before starting to fade out after progress 100%. visible = false, BAR_WIDTH = 480, // Dimension of SVG in pixels of visible portion (half) of the bar. - BAR_HEIGHT = 30, + BAR_HEIGHT = 10, BAR_URL = Script.resolvePath("assets/images/progress-bar.svg"), - BACKGROUND_WIDTH = 540, - BACKGROUND_HEIGHT = 90, + BACKGROUND_WIDTH = 520, + BACKGROUND_HEIGHT = 50, BACKGROUND_URL = Script.resolvePath("assets/images/progress-bar-background.svg"), isOnHMD = false, windowWidth = 0, @@ -45,8 +45,9 @@ PROGRESS_3D_DIRECTION = 0.0, // Degrees from avatar orientation. PROGRESS_3D_DISTANCE = 0.602, // Horizontal distance from avatar position. PROGRESS_3D_ELEVATION = -0.8, // Height of top middle of top notification relative to avatar eyes. + PROGRESS_3D_ELEVATION = -0.0, // Height of top middle of top notification relative to avatar eyes. PROGRESS_3D_YAW = 0.0, // Degrees relative to notifications direction. - PROGRESS_3D_PITCH = -60.0, // Degrees from vertical. + PROGRESS_3D_PITCH = -0.0, // Degrees from vertical. SCALE_3D = 0.0011, // Scale the bar SVG for 3D display. BACKGROUND_3D_SIZE = { x: 0.76, @@ -57,7 +58,7 @@ green: 2, blue: 2 }, - BACKGROUND_3D_ALPHA = 0.7; + BACKGROUND_3D_ALPHA = 1.0; function fade() { @@ -119,6 +120,7 @@ wasActive = false; rawProgress = 100; bestRawProgress = 100; + cooldown = 0; } else { var count = info.downloading.length + info.pending; if (!wasActive) { @@ -128,17 +130,8 @@ if (count > maxSeen) { maxSeen = count; } - if (cooldown < 0) { - print("PROGRESS: OUT OF COOLDOWN"); - //for (i = 0; i < info.downloading.length; i += 1) { - //rawProgress += info.downloading[i]; - //} - //rawProgress = rawProgress / (info.downloading.length + info.pending); + if (cooldown <= 0) { rawProgress = ((maxSeen - count) / maxSeen) * 100; - //rawProgress += 1; - //if (rawProgress > 90) { - //rawProgress = 20 - //} if (rawProgress > bestRawProgress) { bestRawProgress = rawProgress; @@ -208,46 +201,23 @@ var b = 0; function update() { cooldown -= 16; - /* - maxSeen = 100; - b++; - rawProgress = b; - if (rawProgress == 100) { - b = 0 - } - bestRawProgress = rawProgress; - print(rawProgress, bestRawProgress); - */ - - //print(rawProgress, bestRawProgress, maxSeen); var viewport, eyePosition, avatarOrientation; hmdActive = HMD.active; - //if (isOnHMD !== HMD.active) { - //deleteOverlays(); - //isOnHMD = !isOnHMD; - //createOverlays(); - //} + // if (isOnHMD !== HMD.active) { + // deleteOverlays(); + // isOnHMD = !isOnHMD; + // createOverlays(); + // } - /* - // Calculate progress value to display - if (rawProgress === 0 && displayProgress <= DISPLAY_PROGRESS_MINOR_MAXIMUM) { - displayProgress = Math.min(displayProgress + DISPLAY_PROGRESS_MINOR_INCREMENT, DISPLAY_PROGRESS_MINOR_MAXIMUM); - } else if (rawProgress < displayProgress) { - displayProgress = rawProgress; - } else if (rawProgress > displayProgress) { - displayProgress = Math.min(rawProgress, displayProgress + DISPLAY_PROGRESS_MAJOR_INCREMENT); - } // else (rawProgress === displayProgress); do nothing. - //displayProgress = bestRawProgress; - //*/ if (displayProgress < rawProgress) { var diff = rawProgress - displayProgress; if (diff < 0.1) { displayProgress = rawProgress; } else { - displayProgress += diff * 0.1; + displayProgress += diff * 0.05; } } //print('PROGRESS:', displayProgress); @@ -323,7 +293,7 @@ windowWidth = viewport.x; windowHeight = viewport.y; - var yOffset = hmdActive ? -300 : 0; + var yOffset = hmdActive ? -300 : -10; Overlays.editOverlay(background2D.overlay, { x: windowWidth / 2 - background2D.width / 2, From 9f6da23b15b7d9d14ce24dd7353383c34a38665e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 29 Jul 2016 10:11:28 -0700 Subject: [PATCH 07/42] Update progress bar images --- scripts/system/assets/images/progress-bar-background.svg | 4 ++-- scripts/system/assets/images/progress-bar.svg | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/assets/images/progress-bar-background.svg b/scripts/system/assets/images/progress-bar-background.svg index 732acd05ad..0499edfa16 100644 --- a/scripts/system/assets/images/progress-bar-background.svg +++ b/scripts/system/assets/images/progress-bar-background.svg @@ -1,5 +1,5 @@  - - + + diff --git a/scripts/system/assets/images/progress-bar.svg b/scripts/system/assets/images/progress-bar.svg index 360aa3f1a9..e24a2cbff4 100644 --- a/scripts/system/assets/images/progress-bar.svg +++ b/scripts/system/assets/images/progress-bar.svg @@ -1,12 +1,12 @@ + viewBox="0 0 960 10" enable-background="new -159 536 960 30" xml:space="preserve"> - - + + From 800c2b9ec0fcdb1f038b8713b4db59abcb4e84b2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 30 Jul 2016 11:21:40 +1200 Subject: [PATCH 08/42] Refresh file dialog when directory content changes --- interface/resources/qml/dialogs/FileDialog.qml | 11 +++++++++++ libraries/ui/src/FileDialogHelper.cpp | 12 ++++++++++++ libraries/ui/src/FileDialogHelper.h | 12 +++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index fa5be18cd3..6a37886cb3 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -87,6 +87,15 @@ ModalWindow { currentSelection.text = d.capitalizeDrive(helper.urlToPath(initialFolder)); } + helper.contentsChanged.connect(function() { + if (folderListModel) { + // Make folderListModel refresh. + var save = folderListModel.folder; + folderListModel.folder = ""; + folderListModel.folder = save; + } + }); + fileTableView.forceActiveFocus(); } @@ -343,12 +352,14 @@ ModalWindow { onFolderChanged: { if (folder === rootFolder) { model = driveListModel; + helper.monitorDirectory(""); update(); } else { var needsUpdate = model === driveListModel && folder === folderListModel.folder; model = folderListModel; folderListModel.folder = folder; + helper.monitorDirectory(helper.urlToPath(folder)); if (needsUpdate) { update(); diff --git a/libraries/ui/src/FileDialogHelper.cpp b/libraries/ui/src/FileDialogHelper.cpp index 3a12e054df..9d791ec562 100644 --- a/libraries/ui/src/FileDialogHelper.cpp +++ b/libraries/ui/src/FileDialogHelper.cpp @@ -115,3 +115,15 @@ QList FileDialogHelper::urlToList(const QUrl& url) { return results; } +void FileDialogHelper::monitorDirectory(const QString& path) { + if (!_fsWatcherPath.isEmpty()) { + _fsWatcher.removePath(_fsWatcherPath); + _fsWatcherPath = ""; + } + + if (!path.isEmpty()) { + _fsWatcher.addPath(path); + _fsWatcherPath = path; + connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &FileDialogHelper::contentsChanged); + } +} diff --git a/libraries/ui/src/FileDialogHelper.h b/libraries/ui/src/FileDialogHelper.h index 6058f8f7bb..6c352ecdfc 100644 --- a/libraries/ui/src/FileDialogHelper.h +++ b/libraries/ui/src/FileDialogHelper.h @@ -9,11 +9,12 @@ #ifndef hifi_ui_FileDialogHelper_h #define hifi_ui_FileDialogHelper_h +#include #include #include -#include #include #include +#include class FileDialogHelper : public QObject { @@ -61,6 +62,15 @@ public: Q_INVOKABLE QList urlToList(const QUrl& url); Q_INVOKABLE void openDirectory(const QString& path); + + Q_INVOKABLE void monitorDirectory(const QString& path); + +signals: + void contentsChanged(); + +private: + QFileSystemWatcher _fsWatcher; + QString _fsWatcherPath; }; From 5d50389e29adaead7dc9428ddab62af704d9d9d6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 29 Jul 2016 17:17:59 -0700 Subject: [PATCH 09/42] Make updates to the hmd progress bar --- .../assets/images/progress-bar-background.svg | 2 +- scripts/system/progress.js | 242 +++++++++++------- 2 files changed, 152 insertions(+), 92 deletions(-) diff --git a/scripts/system/assets/images/progress-bar-background.svg b/scripts/system/assets/images/progress-bar-background.svg index 0499edfa16..a8b4e1aab5 100644 --- a/scripts/system/assets/images/progress-bar-background.svg +++ b/scripts/system/assets/images/progress-bar-background.svg @@ -1,5 +1,5 @@  - + diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 0628974043..faf8d1bd38 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -33,7 +33,7 @@ BACKGROUND_WIDTH = 520, BACKGROUND_HEIGHT = 50, BACKGROUND_URL = Script.resolvePath("assets/images/progress-bar-background.svg"), - isOnHMD = false, + use3DOverlay = false, windowWidth = 0, windowHeight = 0, background2D = {}, @@ -45,10 +45,10 @@ PROGRESS_3D_DIRECTION = 0.0, // Degrees from avatar orientation. PROGRESS_3D_DISTANCE = 0.602, // Horizontal distance from avatar position. PROGRESS_3D_ELEVATION = -0.8, // Height of top middle of top notification relative to avatar eyes. - PROGRESS_3D_ELEVATION = -0.0, // Height of top middle of top notification relative to avatar eyes. + PROGRESS_3D_ELEVATION = -0.2, // Height of top middle of top notification relative to avatar eyes. PROGRESS_3D_YAW = 0.0, // Degrees relative to notifications direction. PROGRESS_3D_PITCH = -0.0, // Degrees from vertical. - SCALE_3D = 0.0011, // Scale the bar SVG for 3D display. + SCALE_3D = 0.0004, // Scale the bar SVG for 3D display. BACKGROUND_3D_SIZE = { x: 0.76, y: 0.08 @@ -66,9 +66,7 @@ if (alpha < 0) { alpha = 0; - } - - if (alpha > 1) { + } else if (alpha > 1) { alpha = 1; } @@ -81,9 +79,9 @@ visible = false; } - if (isOnHMD) { + if (use3DOverlay) { Overlays.editOverlay(background3D.overlay, { - backgroundAlpha: alpha * BACKGROUND_3D_ALPHA, + alpha: alpha, visible: visible }); } else { @@ -92,7 +90,7 @@ visible: visible }); } - Overlays.editOverlay(isOnHMD ? bar3D.overlay : bar2D.overlay, { + Overlays.editOverlay(use3DOverlay ? bar3D.overlay : bar2D.overlay, { alpha: alpha, visible: visible }); @@ -105,7 +103,12 @@ displayProgress = 0; } - Window.domainChanged.connect(resetProgress); + Window.domainChanged.connect(function() { + hasShownOnThisDomain = false; + resetProgress(); + }); + + var hasShownOnThisDomain = false; var maxSeen = 0; var bestRawProgress = 0; @@ -114,7 +117,7 @@ function onDownloadInfoChanged(info) { var i; - print("PROGRESS: DOwnload info changed ", info.downloading.length, info.pending, maxSeen); + print("PROGRESS: Download info changed ", info.downloading.length, info.pending, maxSeen); // Update raw progress value if (info.downloading.length + info.pending === 0) { wasActive = false; @@ -142,79 +145,87 @@ } function createOverlays() { - if (isOnHMD) { + background3D.overlay = Overlays.addOverlay("image3d", { + url: BACKGROUND_URL, + subImage: { + x: 0, + y: 0, + width: BACKGROUND_WIDTH, + height: BACKGROUND_HEIGHT + }, + scale: SCALE_3D * BACKGROUND_WIDTH, + isFacingAvatar: false, + visible: false, + alpha: 1.0, + ignoreRayIntersection: true, + emissive: true, + isFacingAvatar: true, + drawInFront: true + }); + bar3D.overlay = Overlays.addOverlay("image3d", { + url: BAR_URL, + subImage: { + x: 0, + y: 0, + width: BAR_WIDTH, + height: BAR_HEIGHT + }, + scale: SCALE_3D * BAR_WIDTH, + isFacingAvatar: false, + visible: false, + alpha: 1.0, + ignoreRayIntersection: true, + emissive: true, + isFacingAvatar: true, + drawInFront: true + }); - background3D.overlay = Overlays.addOverlay("rectangle3d", { - size: BACKGROUND_3D_SIZE, - color: BACKGROUND_3D_COLOR, - alpha: BACKGROUND_3D_ALPHA, - solid: true, - isFacingAvatar: false, - visible: false, - ignoreRayIntersection: true - }); - bar3D.overlay = Overlays.addOverlay("image3d", { - url: BAR_URL, - subImage: { - x: 0, - y: 0, - width: 480, - height: BAR_HEIGHT - }, - scale: SCALE_3D * BAR_WIDTH, - isFacingAvatar: false, - visible: false, - alpha: 0.0, - ignoreRayIntersection: true - }); - - } else { - - background2D.overlay = Overlays.addOverlay("image", { - imageURL: BACKGROUND_URL, - width: background2D.width, - height: background2D.height, - visible: false, - alpha: 0.0 - }); - bar2D.overlay = Overlays.addOverlay("image", { - imageURL: BAR_URL, - subImage: { - x: 0, - y: 0, - width: BAR_WIDTH, - height: BAR_HEIGHT - }, - width: bar2D.width, - height: bar2D.height, - visible: false, - alpha: 0.0 - }); - } + background2D.overlay = Overlays.addOverlay("image", { + imageURL: BACKGROUND_URL, + width: background2D.width, + height: background2D.height, + visible: false, + alpha: 0.0 + }); + bar2D.overlay = Overlays.addOverlay("image", { + imageURL: BAR_URL, + subImage: { + x: 0, + y: 0, + width: BAR_WIDTH, + height: BAR_HEIGHT + }, + width: bar2D.width, + height: bar2D.height, + visible: false, + alpha: 0.0 + }); } function deleteOverlays() { - Overlays.deleteOverlay(isOnHMD ? background3D.overlay : background2D.overlay); - Overlays.deleteOverlay(isOnHMD ? bar3D.overlay : bar2D.overlay); + Overlays.deleteOverlay(background3D.overlay); + Overlays.deleteOverlay(bar3D.overlay); + + Overlays.deleteOverlay(background2D.overlay); + Overlays.deleteOverlay(bar2D.overlay); } var b = 0; + var worldOverlayOn = false; + var currentOrientation = null; function update() { - cooldown -= 16; + cooldown -= 30; var viewport, eyePosition, avatarOrientation; - hmdActive = HMD.active; - // if (isOnHMD !== HMD.active) { - // deleteOverlays(); - // isOnHMD = !isOnHMD; - // createOverlays(); - // } + if (use3DOverlay !== worldOverlayOn) { + use3DOverlay = !use3DOverlay; + } if (displayProgress < rawProgress) { var diff = rawProgress - displayProgress; - if (diff < 0.1) { + if (diff < 0.5) { displayProgress = rawProgress; } else { displayProgress += diff * 0.05; @@ -222,7 +233,6 @@ } //print('PROGRESS:', displayProgress); - // Update state if (!visible) { // Not visible because no recent downloads if (displayProgress < 100) { // Have started downloading so fade in @@ -257,11 +267,19 @@ } } + if (use3DOverlay) { + Overlays.editOverlay(background2D.overlay, { visible: false }); + Overlays.editOverlay(bar2D.overlay, { visible: false }); + } else { + Overlays.editOverlay(background3D.overlay, { visible: false }); + Overlays.editOverlay(bar3D.overlay, { visible: false }); + } + if (visible) { // Update progress bar - Overlays.editOverlay(isOnHMD ? bar3D.overlay : bar2D.overlay, { - visible: visible, + Overlays.editOverlay(use3DOverlay ? bar3D.overlay : bar2D.overlay, { + visible: true, subImage: { x: BAR_WIDTH * (1 - displayProgress / 100), y: 0, @@ -270,19 +288,27 @@ }, }); + Overlays.editOverlay(use3DOverlay ? background3D.overlay : background2D.overlay, { + visible: true, + }); + // Update position - if (isOnHMD) { + if (use3DOverlay) { + print("HERE"); // Update 3D overlays to maintain positions relative to avatar eyePosition = MyAvatar.getDefaultEyePosition(); - avatarOrientation = MyAvatar.orientation; + avatarOrientation = Camera.orientation; + + currentOrientation = Quat.slerp(currentOrientation, avatarOrientation, 0.10); + avatarOrientation = currentOrientation; Overlays.editOverlay(background3D.overlay, { position: Vec3.sum(eyePosition, Vec3.multiplyQbyV(avatarOrientation, background3D.offset)), - rotation: Quat.multiply(avatarOrientation, background3D.orientation) + //rotation: Quat.multiply(avatarOrientation, background3D.orientation) }); Overlays.editOverlay(bar3D.overlay, { position: Vec3.sum(eyePosition, Vec3.multiplyQbyV(avatarOrientation, bar3D.offset)), - rotation: Quat.multiply(avatarOrientation, bar3D.orientation) + //rotation: Quat.multiply(avatarOrientation, bar3D.orientation) }); } else { @@ -290,25 +316,44 @@ viewport = Controller.getViewportDimensions(); if (viewport.x !== windowWidth || viewport.y !== windowHeight) { - windowWidth = viewport.x; - windowHeight = viewport.y; - - var yOffset = hmdActive ? -300 : -10; - - Overlays.editOverlay(background2D.overlay, { - x: windowWidth / 2 - background2D.width / 2, - y: windowHeight - background2D.height - bar2D.height + yOffset - }); - - Overlays.editOverlay(bar2D.overlay, { - x: windowWidth / 2 - bar2D.width / 2, - y: windowHeight - background2D.height - bar2D.height + (background2D.height - bar2D.height) / 2 + yOffset - }); + updateProgressBarLocation(); } } } } + function updateProgressBarLocation() { + viewport = Controller.getViewportDimensions(); + windowWidth = viewport.x; + windowHeight = viewport.y; + + var yOffset = HMD.active ? -300 : -10; + yOffset += yAdjust; + // if (hmdActive) { + // if (true) { //hasShownOnThisDomain) { + // yOffset = -100; + // SCALE_2D = 1.0/3; + // } else { + // yOffset = -300; + // SCALE_2D = 2.0/3; + // } + // } + background2D.width = SCALE_2D * BACKGROUND_WIDTH; + background2D.height = SCALE_2D * BACKGROUND_HEIGHT; + bar2D.width = SCALE_2D * BAR_WIDTH; + bar2D.height = SCALE_2D * BAR_HEIGHT; + + Overlays.editOverlay(background2D.overlay, { + x: windowWidth / 2 - background2D.width / 2, + y: windowHeight - background2D.height - bar2D.height + yOffset + }); + + Overlays.editOverlay(bar2D.overlay, { + x: windowWidth / 2 - bar2D.width / 2, + y: windowHeight - background2D.height - bar2D.height + (background2D.height - bar2D.height) / 2 + yOffset + }); + } + function setProgressBar(progress) { } @@ -339,10 +384,25 @@ deleteOverlays(); } + var yAdjust = 0; + function keyPress(event) { + print("Key event: ", event.text); + if (event.text == '.') { + yAdjust -= 10; + updateProgressBarLocation(); + } else if (event.text == ',') { + yAdjust += 10; + updateProgressBarLocation(); + } else if (event.text == 'SPACE') { + worldOverlayOn = !worldOverlayOn; + } + } + setUp(); GlobalServices.downloadInfoChanged.connect(onDownloadInfoChanged); GlobalServices.updateDownloadInfo(); //Script.update.connect(update); - Script.setInterval(update, 16); + Script.setInterval(update, 1000/60); Script.scriptEnding.connect(tearDown); + Controller.keyPressEvent.connect(keyPress); }()); From 6836b09f8740d9c43a7e3cb4e2efaf8aaa6a3da8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 15:36:12 -0700 Subject: [PATCH 10/42] add sections to DS security for IP/Subnet --- .../resources/describe-settings.json | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 7600aefc09..6081a603f3 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -638,6 +638,148 @@ } ] }, + { + "name": "ip_permissions", + "type": "table", + "caption": "Permissions for Users from IP Addresses or Subnets", + "can_add_new_rows": true, + "groups": [ + { + "label": "IP/Subnet", + "span": 1 + }, + { + "label": "Permissions ?", + "span": 6 + } + ], + + "columns": [ + { + "name": "permissions_id", + "label": "IP/Subnet" + }, + { + "name": "group_id", + "label": "Group ID", + "readonly": true, + "hidden": true + }, + { + "name": "id_can_connect", + "label": "Connect", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_adjust_locks", + "label": "Lock / Unlock", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_rez", + "label": "Rez", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_rez_tmp", + "label": "Rez Temporary", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_write_to_asset_server", + "label": "Write Assets", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_connect_past_max_capacity", + "label": "Ignore Max Capacity", + "type": "checkbox", + "editable": true, + "default": false + } + ] + }, + { + "name": "ip_forbidden", + "type": "table", + "caption": "Permissions denied to Users from IP addresses or Subnets", + "can_add_new_rows": true, + "groups": [ + { + "label": "IP/Subnet", + "span": 1 + }, + { + "label": "Permissions ?", + "span": 6 + } + ], + + "columns": [ + { + "name": "permissions_id", + "label": "IP/Subnet" + }, + { + "name": "group_id", + "label": "Group ID", + "readonly": true, + "hidden": true + }, + { + "name": "id_can_connect", + "label": "Connect", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_adjust_locks", + "label": "Lock / Unlock", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_rez", + "label": "Rez", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_rez_tmp", + "label": "Rez Temporary", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_write_to_asset_server", + "label": "Write Assets", + "type": "checkbox", + "editable": true, + "default": false + }, + { + "name": "id_can_connect_past_max_capacity", + "label": "Ignore Max Capacity", + "type": "checkbox", + "editable": true, + "default": false + } + ] + }, { "name": "permissions", "type": "table", From edce249d2c82fe1a6aff3d41e49ca4e718c04485 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 15:42:33 -0700 Subject: [PATCH 11/42] remove subnet from IP address security --- .../resources/describe-settings.json | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 6081a603f3..1e8c0238cb 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -641,15 +641,15 @@ { "name": "ip_permissions", "type": "table", - "caption": "Permissions for Users from IP Addresses or Subnets", + "caption": "Permissions for Users from IP Addresses", "can_add_new_rows": true, "groups": [ { - "label": "IP/Subnet", + "label": "IP Address", "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 6 } ], @@ -657,13 +657,7 @@ "columns": [ { "name": "permissions_id", - "label": "IP/Subnet" - }, - { - "name": "group_id", - "label": "Group ID", - "readonly": true, - "hidden": true + "label": "" }, { "name": "id_can_connect", @@ -712,15 +706,15 @@ { "name": "ip_forbidden", "type": "table", - "caption": "Permissions denied to Users from IP addresses or Subnets", + "caption": "Permissions denied to Users from IP Addresses", "can_add_new_rows": true, "groups": [ { - "label": "IP/Subnet", + "label": "IP", "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 6 } ], @@ -728,13 +722,7 @@ "columns": [ { "name": "permissions_id", - "label": "IP/Subnet" - }, - { - "name": "group_id", - "label": "Group ID", - "readonly": true, - "hidden": true + "label": "" }, { "name": "id_can_connect", From a674c843c28294d0adccad517772c4ad8d5628a2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 16:40:51 -0700 Subject: [PATCH 12/42] add unpack for IP, DRYup unpackPermissions --- .../src/DomainServerSettingsManager.cpp | 154 +++++++----------- .../src/DomainServerSettingsManager.h | 15 ++ 2 files changed, 77 insertions(+), 92 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index a02b19f9fd..7a31aca4e3 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -430,114 +430,84 @@ void DomainServerSettingsManager::packPermissions() { _configMap.loadMasterAndUserConfig(_argumentList); } -void DomainServerSettingsManager::unpackPermissions() { - // transfer details from _configMap to _agentPermissions; +bool DomainServerSettingsManager::unpackPermissionsForKeypath(const QString& keyPath, + NodePermissionsMap* mapPointer, + std::function customUnpacker) { - _standardAgentPermissions.clear(); - _agentPermissions.clear(); - _groupPermissions.clear(); - _groupForbiddens.clear(); + mapPointer->clear(); - bool foundLocalhost = false; - bool foundAnonymous = false; - bool foundLoggedIn = false; - bool foundFriends = false; - bool needPack = false; - - QVariant* standardPermissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_STANDARD_PERMISSIONS_KEYPATH); - if (!standardPermissions || !standardPermissions->canConvert(QMetaType::QVariantList)) { - qDebug() << "failed to extract standard permissions from settings."; - standardPermissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_STANDARD_PERMISSIONS_KEYPATH, true); - (*standardPermissions) = QVariantList(); - } - QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH); - if (!permissions || !permissions->canConvert(QMetaType::QVariantList)) { - qDebug() << "failed to extract permissions from settings."; - permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH, true); + QVariant* permissions = valueForKeyPath(_configMap.getMergedConfig(), keyPath, true); + if (!permissions->canConvert(QMetaType::QVariantList)) { + qDebug() << "Failed to extract permissions for key path" << keyPath << "from settings."; (*permissions) = QVariantList(); } - QVariant* groupPermissions = valueForKeyPath(_configMap.getUserConfig(), GROUP_PERMISSIONS_KEYPATH); - if (!groupPermissions || !groupPermissions->canConvert(QMetaType::QVariantList)) { - qDebug() << "failed to extract group permissions from settings."; - groupPermissions = valueForKeyPath(_configMap.getUserConfig(), GROUP_PERMISSIONS_KEYPATH, true); - (*groupPermissions) = QVariantList(); - } - QVariant* groupForbiddens = valueForKeyPath(_configMap.getUserConfig(), GROUP_FORBIDDENS_KEYPATH); - if (!groupForbiddens || !groupForbiddens->canConvert(QMetaType::QVariantList)) { - qDebug() << "failed to extract group forbiddens from settings."; - groupForbiddens = valueForKeyPath(_configMap.getUserConfig(), GROUP_FORBIDDENS_KEYPATH, true); - (*groupForbiddens) = QVariantList(); - } - QList standardPermissionsList = standardPermissions->toList(); - foreach (QVariant permsHash, standardPermissionsList) { - NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) }; - QString id = perms->getID(); - NodePermissionsKey idKey = NodePermissionsKey(id, 0); - foundLocalhost |= (idKey == NodePermissions::standardNameLocalhost); - foundAnonymous |= (idKey == NodePermissions::standardNameAnonymous); - foundLoggedIn |= (idKey == NodePermissions::standardNameLoggedIn); - foundFriends |= (idKey == NodePermissions::standardNameFriends); - if (_standardAgentPermissions.contains(idKey)) { - qDebug() << "duplicate name in standard permissions table: " << id; - *(_standardAgentPermissions[idKey]) |= *perms; - needPack = true; - } else { - _standardAgentPermissions[idKey] = perms; - } - } + bool needPack = false; QList permissionsList = permissions->toList(); foreach (QVariant permsHash, permissionsList) { NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) }; QString id = perms->getID(); - NodePermissionsKey idKey = NodePermissionsKey(id, 0); - if (_agentPermissions.contains(idKey)) { - qDebug() << "duplicate name in permissions table: " << id; - *(_agentPermissions[idKey]) |= *perms; + + NodePermissionsKey idKey = perms->getKey(); + + if (mapPointer->contains(idKey)) { + qDebug() << "Duplicate name in permissions table for" << keyPath << " - " << id; + (*mapPointer)[idKey] |= perms; needPack = true; } else { - _agentPermissions[idKey] = perms; + (*mapPointer)[idKey] = perms; + } + + if (customUnpacker) { + customUnpacker(perms); } } - QList groupPermissionsList = groupPermissions->toList(); - foreach (QVariant permsHash, groupPermissionsList) { - NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) }; - QString id = perms->getID(); - NodePermissionsKey idKey = perms->getKey(); - if (_groupPermissions.contains(idKey)) { - qDebug() << "duplicate name in group permissions table: " << id; - *(_groupPermissions[idKey]) |= *perms; - needPack = true; - } else { - *(_groupPermissions[idKey]) = *perms; - } - if (perms->isGroup()) { - // the group-id was cached. hook-up the uuid in the uuid->group hash - _groupPermissionsByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRankID())] = _groupPermissions[idKey]; - needPack |= setGroupID(perms->getID(), perms->getGroupID()); - } - } + return needPack; - QList groupForbiddensList = groupForbiddens->toList(); - foreach (QVariant permsHash, groupForbiddensList) { - NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) }; - QString id = perms->getID(); - NodePermissionsKey idKey = perms->getKey(); - if (_groupForbiddens.contains(idKey)) { - qDebug() << "duplicate name in group forbiddens table: " << id; - *(_groupForbiddens[idKey]) |= *perms; - needPack = true; - } else { - _groupForbiddens[idKey] = perms; - } - if (perms->isGroup()) { - // the group-id was cached. hook-up the uuid in the uuid->group hash - _groupForbiddensByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRankID())] = _groupForbiddens[idKey]; - needPack |= setGroupID(perms->getID(), perms->getGroupID()); - } - } +} + +void DomainServerSettingsManager::unpackPermissions() { + // transfer details from _configMap to _agentPermissions; + + bool foundLocalhost = false; + bool foundAnonymous = false; + bool foundLoggedIn = false; + bool foundFriends = false; + + bool needPack = false; + + needPack |= unpackPermissionsForKeypath(AGENT_STANDARD_PERMISSIONS_KEYPATH, &_standardAgentPermissions, + [&foundLocalhost, &foundAnonymous, &foundLoggedIn, &foundFriends](NodePermissionsPointer perms){ + NodePermissionsKey idKey = perms->getKey(); + foundLocalhost |= (idKey == NodePermissions::standardNameLocalhost); + foundAnonymous |= (idKey == NodePermissions::standardNameAnonymous); + foundLoggedIn |= (idKey == NodePermissions::standardNameLoggedIn); + foundFriends |= (idKey == NodePermissions::standardNameFriends); + }); + + needPack |= unpackPermissionsForKeypath(AGENT_PERMISSIONS_KEYPATH, &_agentPermissions); + needPack |= unpackPermissionsForKeypath(IP_PERMISSIONS_KEYPATH, &_ipPermissions); + needPack |= unpackPermissionsForKeypath(IP_FORBIDDENS_KEYPATH, &_ipForbiddens); + + needPack |= unpackPermissionsForKeypath(GROUP_PERMISSIONS_KEYPATH, &_groupPermissions, + [&](NodePermissionsPointer perms){ + if (perms->isGroup()) { + // the group-id was cached. hook-up the uuid in the uuid->group hash + _groupPermissionsByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRankID())] = _groupPermissions[perms->getKey()]; + needPack |= setGroupID(perms->getID(), perms->getGroupID()); + } + }); + + needPack |= unpackPermissionsForKeypath(GROUP_FORBIDDENS_KEYPATH, &_groupForbiddens, + [&](NodePermissionsPointer perms) { + if (perms->isGroup()) { + // the group-id was cached. hook-up the uuid in the uuid->group hash + _groupForbiddensByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRankID())] = _groupForbiddens[perms->getKey()]; + needPack |= setGroupID(perms->getID(), perms->getGroupID()); + } + }); // if any of the standard names are missing, add them if (!foundLocalhost) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index f56b1ecd21..754b62a72b 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -27,6 +27,8 @@ const QString SETTINGS_PATH = "/settings"; const QString SETTINGS_PATH_JSON = SETTINGS_PATH + ".json"; const QString AGENT_STANDARD_PERMISSIONS_KEYPATH = "security.standard_permissions"; const QString AGENT_PERMISSIONS_KEYPATH = "security.permissions"; +const QString IP_PERMISSIONS_KEYPATH = "security.ip_permissions"; +const QString IP_FORBIDDENS_KEYPATH = "security.ip_forbiddens"; const QString GROUP_PERMISSIONS_KEYPATH = "security.group_permissions"; const QString GROUP_FORBIDDENS_KEYPATH = "security.group_forbiddens"; @@ -58,6 +60,14 @@ public: NodePermissions getPermissionsForName(const NodePermissionsKey& key) const { return getPermissionsForName(key.first); } QStringList getAllNames() const; + // these give access to permissions for specific IPs from the domain-server settings page + bool havePermissionsForIP(const QHostAddress& address) const { return _ipPermissions.contains(address.toString(), 0); } + NodePermissions getPermissionsForIP(const QHostAddress& address) const; + + // these remove permissions from users connecting from specific IPs + bool haveForbiddensForIP(const QHostAddress& address) const { return _ipForbiddens.contains(address.toString(), 0); } + NodePermissions getForbiddensForIP(const QHostAddress& address) const; + // these give access to permissions for specific groups from the domain-server settings page bool havePermissionsForGroup(const QString& groupName, QUuid rankID) const { return _groupPermissions.contains(groupName, rankID); @@ -129,11 +139,16 @@ private: void packPermissionsForMap(QString mapName, NodePermissionsMap& permissionsRows, QString keyPath); void packPermissions(); void unpackPermissions(); + bool unpackPermissionsForKeypath(const QString& keyPath, NodePermissionsMap* destinationMapPointer, + std::function customUnpacker = {}); bool ensurePermissionsForGroupRanks(); NodePermissionsMap _standardAgentPermissions; // anonymous, logged-in, localhost, friend-of-domain-owner NodePermissionsMap _agentPermissions; // specific account-names + NodePermissionsMap _ipPermissions; // permissions granted by node IP address + NodePermissionsMap _ipForbiddens; // permissions denied by node IP address + NodePermissionsMap _groupPermissions; // permissions granted by membership to specific groups NodePermissionsMap _groupForbiddens; // permissions denied due to membership in a specific group // these are like _groupPermissions and _groupForbiddens but with uuids rather than group-names in the keys From f8ea1801277cc612a0fa13698910525eeeebc50a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 16:42:54 -0700 Subject: [PATCH 13/42] match naming of forbidden IP settings group to groups --- domain-server/resources/describe-settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 1e8c0238cb..11d21b3ab0 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -704,7 +704,7 @@ ] }, { - "name": "ip_forbidden", + "name": "ip_forbiddens", "type": "table", "caption": "Permissions denied to Users from IP Addresses", "can_add_new_rows": true, From cd436355fc6a193c97529c3a1180d245a9bf0fe4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 16:50:34 -0700 Subject: [PATCH 14/42] cleanup handling of defaults for standard user perms --- .../src/DomainServerSettingsManager.cpp | 53 +++++++------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 7a31aca4e3..341275fe13 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -469,23 +469,11 @@ bool DomainServerSettingsManager::unpackPermissionsForKeypath(const QString& key } void DomainServerSettingsManager::unpackPermissions() { - // transfer details from _configMap to _agentPermissions; - - bool foundLocalhost = false; - bool foundAnonymous = false; - bool foundLoggedIn = false; - bool foundFriends = false; + // transfer details from _configMap to _agentPermissions bool needPack = false; - needPack |= unpackPermissionsForKeypath(AGENT_STANDARD_PERMISSIONS_KEYPATH, &_standardAgentPermissions, - [&foundLocalhost, &foundAnonymous, &foundLoggedIn, &foundFriends](NodePermissionsPointer perms){ - NodePermissionsKey idKey = perms->getKey(); - foundLocalhost |= (idKey == NodePermissions::standardNameLocalhost); - foundAnonymous |= (idKey == NodePermissions::standardNameAnonymous); - foundLoggedIn |= (idKey == NodePermissions::standardNameLoggedIn); - foundFriends |= (idKey == NodePermissions::standardNameFriends); - }); + needPack |= unpackPermissionsForKeypath(AGENT_STANDARD_PERMISSIONS_KEYPATH, &_standardAgentPermissions); needPack |= unpackPermissionsForKeypath(AGENT_PERMISSIONS_KEYPATH, &_agentPermissions); needPack |= unpackPermissionsForKeypath(IP_PERMISSIONS_KEYPATH, &_ipPermissions); @@ -510,26 +498,23 @@ void DomainServerSettingsManager::unpackPermissions() { }); // if any of the standard names are missing, add them - if (!foundLocalhost) { - NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLocalhost) }; - perms->setAll(true); - _standardAgentPermissions[perms->getKey()] = perms; - needPack = true; - } - if (!foundAnonymous) { - NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameAnonymous) }; - _standardAgentPermissions[perms->getKey()] = perms; - needPack = true; - } - if (!foundLoggedIn) { - NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLoggedIn) }; - _standardAgentPermissions[perms->getKey()] = perms; - needPack = true; - } - if (!foundFriends) { - NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameFriends) }; - _standardAgentPermissions[perms->getKey()] = perms; - needPack = true; + foreach(const QString& standardName, NodePermissions::standardNames) { + NodePermissionsKey standardKey { standardName, 0 }; + if (!_standardAgentPermissions.contains(standardKey)) { + // we don't have permissions for one of the standard groups, so we'll add them now + NodePermissionsPointer perms { new NodePermissions(standardKey) }; + + // the localhost user is granted all permissions by default + if (standardKey == NodePermissions::standardNameLocalhost) { + perms->setAll(true); + } + + // add the permissions to the standard map + _standardAgentPermissions[standardKey] = perms; + + // this will require a packing of permissions + needPack = true; + } } needPack |= ensurePermissionsForGroupRanks(); From f7298ef767e64fbd5154152beb8fe09cc92ba0e0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 17:12:16 -0700 Subject: [PATCH 15/42] add packing of IP perms, small cleanup in packing --- .../src/DomainServerSettingsManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 341275fe13..d5bc732c13 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -354,16 +354,14 @@ void DomainServerSettingsManager::packPermissionsForMap(QString mapName, NodePermissionsMap& permissionsRows, QString keyPath) { // find (or create) the "security" section of the settings map - QVariant* security = valueForKeyPath(_configMap.getUserConfig(), "security"); - if (!security || !security->canConvert(QMetaType::QVariantMap)) { - security = valueForKeyPath(_configMap.getUserConfig(), "security", true); + QVariant* security = valueForKeyPath(_configMap.getUserConfig(), "security", true); + if (!security->canConvert(QMetaType::QVariantMap)) { (*security) = QVariantMap(); } // find (or create) whichever subsection of "security" we are packing - QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath); - if (!permissions || !permissions->canConvert(QMetaType::QVariantList)) { - permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath, true); + QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath, true); + if (!permissions->canConvert(QMetaType::QVariantList)) { (*permissions) = QVariantList(); } @@ -420,6 +418,12 @@ void DomainServerSettingsManager::packPermissions() { // save settings for specific users packPermissionsForMap("permissions", _agentPermissions, AGENT_PERMISSIONS_KEYPATH); + // save settings for IP addresses + packPermissionsForMap("permissions", _ipPermissions, IP_PERMISSIONS_KEYPATH); + + // save settings for IP address blacklist + packPermissionsForMap("permissions", _ipForbiddens, IP_FORBIDDENS_KEYPATH); + // save settings for groups packPermissionsForMap("permissions", _groupPermissions, GROUP_PERMISSIONS_KEYPATH); From b1e0e6d7081ccc356ef04d5274af91387e4003bf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 17:35:22 -0700 Subject: [PATCH 16/42] use replacement for IP address perms, not additive --- .../resources/describe-settings.json | 67 +------------------ domain-server/src/DomainGatekeeper.cpp | 33 +++++++-- domain-server/src/DomainGatekeeper.h | 3 +- .../src/DomainServerSettingsManager.cpp | 17 +++-- .../src/DomainServerSettingsManager.h | 7 +- 5 files changed, 44 insertions(+), 83 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 11d21b3ab0..cfba2ae4f3 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -649,72 +649,7 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 6 - } - ], - - "columns": [ - { - "name": "permissions_id", - "label": "" - }, - { - "name": "id_can_connect", - "label": "Connect", - "type": "checkbox", - "editable": true, - "default": false - }, - { - "name": "id_can_adjust_locks", - "label": "Lock / Unlock", - "type": "checkbox", - "editable": true, - "default": false - }, - { - "name": "id_can_rez", - "label": "Rez", - "type": "checkbox", - "editable": true, - "default": false - }, - { - "name": "id_can_rez_tmp", - "label": "Rez Temporary", - "type": "checkbox", - "editable": true, - "default": false - }, - { - "name": "id_can_write_to_asset_server", - "label": "Write Assets", - "type": "checkbox", - "editable": true, - "default": false - }, - { - "name": "id_can_connect_past_max_capacity", - "label": "Ignore Max Capacity", - "type": "checkbox", - "editable": true, - "default": false - } - ] - }, - { - "name": "ip_forbiddens", - "type": "table", - "caption": "Permissions denied to Users from IP Addresses", - "can_add_new_rows": true, - "groups": [ - { - "label": "IP", - "span": 1 - }, - { - "label": "Permissions ?", + "label": "Permissions ?", "span": 6 } ], diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 5b2e5a2bb0..0abbf38c72 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -120,8 +120,9 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer_settingsManager.hasPermissionsForIP(senderAddress)) { + // this user comes from an IP we have in our permissions table, apply those permissions + userPerms = _server->_settingsManager.getPermissionsForIP(senderAddress); + +#ifdef WANT_DEBUG + qDebug() << "| user-permissions: specific IP matches, so:" << userPerms; +#endif + } } else { userPerms.setID(verifiedUsername); if (_server->_settingsManager.havePermissionsForName(verifiedUsername)) { userPerms = _server->_settingsManager.getPermissionsForName(verifiedUsername); - userPerms.setVerifiedUserName(verifiedUsername); #ifdef WANT_DEBUG qDebug() << "| user-permissions: specific user matches, so:" << userPerms; +#endif + } else if (_server->_settingsManager.hasPermissionsForIP(senderAddress)) { + // this user comes from an IP we have in our permissions table, apply those permissions + userPerms = _server->_settingsManager.getPermissionsForIP(senderAddress); + +#ifdef WANT_DEBUG + qDebug() << "| user-permissions: specific IP matches, so:" << userPerms; #endif } else { - userPerms.setVerifiedUserName(verifiedUsername); + // they are logged into metaverse, but we don't have specific permissions for them. userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn); #ifdef WANT_DEBUG @@ -191,6 +207,8 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin } } } + + userPerms.setVerifiedUserName(verifiedUsername); } #ifdef WANT_DEBUG @@ -225,7 +243,12 @@ void DomainGatekeeper::updateNodePermissions() { const QHostAddress& addr = node->getLocalSocket().getAddress(); bool isLocalUser = (addr == limitedNodeList->getLocalSockAddr().getAddress() || addr == QHostAddress::LocalHost); - userPerms = setPermissionsForUser(isLocalUser, verifiedUsername); + + // at this point we don't have a sending socket for packets from this node - assume it is the active socket + // or the public socket if we haven't activated a socket for the node yet + HifiSockAddr connectingAddr = node->getActiveSocket() ? node->getPublicSocket() : *node->getActiveSocket(); + + userPerms = setPermissionsForUser(isLocalUser, verifiedUsername, connectingAddr.getAddress()); } node->setPermissions(userPerms); @@ -337,7 +360,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect } } - userPerms = setPermissionsForUser(isLocalUser, verifiedUsername); + userPerms = setPermissionsForUser(isLocalUser, verifiedUsername, nodeConnection.senderSockAddr.getAddress()); if (!userPerms.can(NodePermissions::Permission::canConnectToDomain)) { sendConnectionDeniedPacket("You lack the required permissions to connect to this domain.", diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 12697b8f3b..06ecfcf285 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -106,7 +106,8 @@ private: QSet _domainOwnerFriends; // keep track of friends of the domain owner QSet _inFlightGroupMembershipsRequests; // keep track of which we've already asked for - NodePermissions setPermissionsForUser(bool isLocalUser, QString verifiedUsername); + NodePermissions setPermissionsForUser(bool isLocalUser, QString verifiedUsername, const QHostAddress& senderAddress); + void getGroupMemberships(const QString& username); // void getIsGroupMember(const QString& username, const QUuid groupID); void getDomainOwnerFriendsList(); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index d5bc732c13..81794b2899 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -421,9 +421,6 @@ void DomainServerSettingsManager::packPermissions() { // save settings for IP addresses packPermissionsForMap("permissions", _ipPermissions, IP_PERMISSIONS_KEYPATH); - // save settings for IP address blacklist - packPermissionsForMap("permissions", _ipForbiddens, IP_FORBIDDENS_KEYPATH); - // save settings for groups packPermissionsForMap("permissions", _groupPermissions, GROUP_PERMISSIONS_KEYPATH); @@ -457,7 +454,7 @@ bool DomainServerSettingsManager::unpackPermissionsForKeypath(const QString& key if (mapPointer->contains(idKey)) { qDebug() << "Duplicate name in permissions table for" << keyPath << " - " << id; - (*mapPointer)[idKey] |= perms; + *((*mapPointer)[idKey]) |= *perms; needPack = true; } else { (*mapPointer)[idKey] = perms; @@ -480,8 +477,8 @@ void DomainServerSettingsManager::unpackPermissions() { needPack |= unpackPermissionsForKeypath(AGENT_STANDARD_PERMISSIONS_KEYPATH, &_standardAgentPermissions); needPack |= unpackPermissionsForKeypath(AGENT_PERMISSIONS_KEYPATH, &_agentPermissions); + needPack |= unpackPermissionsForKeypath(IP_PERMISSIONS_KEYPATH, &_ipPermissions); - needPack |= unpackPermissionsForKeypath(IP_FORBIDDENS_KEYPATH, &_ipForbiddens); needPack |= unpackPermissionsForKeypath(GROUP_PERMISSIONS_KEYPATH, &_groupPermissions, [&](NodePermissionsPointer perms){ @@ -634,6 +631,16 @@ NodePermissions DomainServerSettingsManager::getPermissionsForName(const QString return nullPermissions; } +NodePermissions DomainServerSettingsManager::getPermissionsForIP(const QHostAddress& address) const { + NodePermissionsKey ipKey = NodePermissionsKey(address.toString(), 0); + if (_ipPermissions.contains(ipKey)) { + return *(_ipPermissions[ipKey].get()); + } + NodePermissions nullPermissions; + nullPermissions.setAll(false); + return nullPermissions; +} + NodePermissions DomainServerSettingsManager::getPermissionsForGroup(const QString& groupName, QUuid rankID) const { NodePermissionsKey groupRankKey = NodePermissionsKey(groupName, rankID); if (_groupPermissions.contains(groupRankKey)) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 754b62a72b..440cd8fe24 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -28,7 +28,6 @@ const QString SETTINGS_PATH_JSON = SETTINGS_PATH + ".json"; const QString AGENT_STANDARD_PERMISSIONS_KEYPATH = "security.standard_permissions"; const QString AGENT_PERMISSIONS_KEYPATH = "security.permissions"; const QString IP_PERMISSIONS_KEYPATH = "security.ip_permissions"; -const QString IP_FORBIDDENS_KEYPATH = "security.ip_forbiddens"; const QString GROUP_PERMISSIONS_KEYPATH = "security.group_permissions"; const QString GROUP_FORBIDDENS_KEYPATH = "security.group_forbiddens"; @@ -61,13 +60,9 @@ public: QStringList getAllNames() const; // these give access to permissions for specific IPs from the domain-server settings page - bool havePermissionsForIP(const QHostAddress& address) const { return _ipPermissions.contains(address.toString(), 0); } + bool hasPermissionsForIP(const QHostAddress& address) const { return _ipPermissions.contains(address.toString(), 0); } NodePermissions getPermissionsForIP(const QHostAddress& address) const; - // these remove permissions from users connecting from specific IPs - bool haveForbiddensForIP(const QHostAddress& address) const { return _ipForbiddens.contains(address.toString(), 0); } - NodePermissions getForbiddensForIP(const QHostAddress& address) const; - // these give access to permissions for specific groups from the domain-server settings page bool havePermissionsForGroup(const QString& groupName, QUuid rankID) const { return _groupPermissions.contains(groupName, rankID); From 5d69c9c81ed8e89651d39288665ae2857c1b3b76 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 17:54:57 -0700 Subject: [PATCH 17/42] fix sockaddr choice for local nodes --- domain-server/src/DomainGatekeeper.cpp | 2 +- domain-server/src/DomainServerSettingsManager.cpp | 2 +- domain-server/src/DomainServerSettingsManager.h | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 0abbf38c72..eb907aace4 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -246,7 +246,7 @@ void DomainGatekeeper::updateNodePermissions() { // at this point we don't have a sending socket for packets from this node - assume it is the active socket // or the public socket if we haven't activated a socket for the node yet - HifiSockAddr connectingAddr = node->getActiveSocket() ? node->getPublicSocket() : *node->getActiveSocket(); + HifiSockAddr connectingAddr = node->getActiveSocket() ? *node->getActiveSocket() : node->getPublicSocket(); userPerms = setPermissionsForUser(isLocalUser, verifiedUsername, connectingAddr.getAddress()); } diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 81794b2899..72aa5bada6 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -528,7 +528,7 @@ void DomainServerSettingsManager::unpackPermissions() { qDebug() << "--------------- permissions ---------------------"; QList> permissionsSets; permissionsSets << _standardAgentPermissions.get() << _agentPermissions.get() - << _groupPermissions.get() << _groupForbiddens.get(); + << _groupPermissions.get() << _groupForbiddens.get() << _ipPermissions.get(); foreach (auto permissionSet, permissionsSets) { QHashIterator i(permissionSet); while (i.hasNext()) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 440cd8fe24..49c3ac95b7 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -142,7 +142,6 @@ private: NodePermissionsMap _agentPermissions; // specific account-names NodePermissionsMap _ipPermissions; // permissions granted by node IP address - NodePermissionsMap _ipForbiddens; // permissions denied by node IP address NodePermissionsMap _groupPermissions; // permissions granted by membership to specific groups NodePermissionsMap _groupForbiddens; // permissions denied due to membership in a specific group From f04996a53d09ab6690ae07a183c01bf2642edafc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 18:01:04 -0700 Subject: [PATCH 18/42] add the kick permission to domain server settings --- .../resources/describe-settings.json | 45 ++++++++++++++++--- libraries/networking/src/NodePermissions.cpp | 5 +++ libraries/networking/src/NodePermissions.h | 3 +- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index cfba2ae4f3..b2a749a66d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -395,7 +395,7 @@ }, { "label": "Permissions ?", - "span": 6 + "span": 7 } ], @@ -445,6 +445,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_kick", + "label": "Kick Users", + "type": "checkbox", + "editable": true, + "default": false } ], @@ -468,7 +475,7 @@ }, { "label": "Permissions ?", - "span": 6 + "span": 7 } ], @@ -543,6 +550,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_kick", + "label": "Kick Users", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -563,7 +577,7 @@ }, { "label": "Permissions ?", - "span": 6 + "span": 7 } ], @@ -635,6 +649,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_kick", + "label": "Kick Users", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -650,7 +671,7 @@ }, { "label": "Permissions ?", - "span": 6 + "span": 7 } ], @@ -700,6 +721,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_kick", + "label": "Kick Users", + "type": "checkbox", + "editable": true, + "default": false } ] }, @@ -716,7 +744,7 @@ }, { "label": "Permissions ?", - "span": 6 + "span": 7 } ], @@ -766,6 +794,13 @@ "type": "checkbox", "editable": true, "default": false + }, + { + "name": "id_can_kick", + "label": "Kick Users", + "type": "checkbox", + "editable": true, + "default": false } ] } diff --git a/libraries/networking/src/NodePermissions.cpp b/libraries/networking/src/NodePermissions.cpp index a815884dc5..a1d4fc182e 100644 --- a/libraries/networking/src/NodePermissions.cpp +++ b/libraries/networking/src/NodePermissions.cpp @@ -44,6 +44,7 @@ NodePermissions::NodePermissions(QMap perms) { permissions |= perms["id_can_write_to_asset_server"].toBool() ? Permission::canWriteToAssetServer : Permission::none; permissions |= perms["id_can_connect_past_max_capacity"].toBool() ? Permission::canConnectPastMaxCapacity : Permission::none; + permissions |= perms["id_can_kick"].toBool() ? Permission::canKick : Permission::none; } QVariant NodePermissions::toVariant(QHash groupRanks) { @@ -63,6 +64,7 @@ QVariant NodePermissions::toVariant(QHash groupRanks) { values["id_can_rez_tmp"] = can(Permission::canRezTemporaryEntities); values["id_can_write_to_asset_server"] = can(Permission::canWriteToAssetServer); values["id_can_connect_past_max_capacity"] = can(Permission::canConnectPastMaxCapacity); + values["id_can_kick"] = can(Permission::canKick); return QVariant(values); } @@ -123,6 +125,9 @@ QDebug operator<<(QDebug debug, const NodePermissions& perms) { if (perms.can(NodePermissions::Permission::canConnectPastMaxCapacity)) { debug << " ignore-max-cap"; } + if (perms.can(NodePermissions::Permission::canKick)) { + debug << " kick"; + } debug.nospace() << "]"; return debug.nospace(); } diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index 6f4309a447..5d2755f9b5 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -63,7 +63,8 @@ public: canRezPermanentEntities = 4, canRezTemporaryEntities = 8, canWriteToAssetServer = 16, - canConnectPastMaxCapacity = 32 + canConnectPastMaxCapacity = 32, + canKick = 64 }; Q_DECLARE_FLAGS(Permissions, Permission) Permissions permissions; From eaf52ae11118dbed0b6e5181df465e668e35477f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 18:23:21 -0700 Subject: [PATCH 19/42] default kick perms for localhost --- domain-server/resources/describe-settings.json | 2 +- domain-server/src/DomainServerSettingsManager.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index b2a749a66d..524a687772 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.5, + "version": 1.6, "settings": [ { "name": "metaverse", diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 72aa5bada6..aba2c25db5 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -273,6 +273,15 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // This was prior to operating hours, so add default hours validateDescriptorsMap(); } + + if (oldVersion < 1.6) { + unpackPermissions(); + + // This was prior to addition of kick permissions, add that to localhost permissions by default + _standardAgentPermissions[NodePermissions::standardNameLocalhost]->set(NodePermissions::Permission::canKick); + + packPermissions(); + } } unpackPermissions(); From 94b97e8119598cb32de3538f6b3564a5ed4d6b70 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 18:23:37 -0700 Subject: [PATCH 20/42] expose kick perms from LNL and Node --- libraries/networking/src/LimitedNodeList.h | 1 + libraries/networking/src/Node.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 7cbdcd5361..2b2f660569 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -110,6 +110,7 @@ public: bool getThisNodeCanRez() const { return _permissions.can(NodePermissions::Permission::canRezPermanentEntities); } bool getThisNodeCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); } bool getThisNodeCanWriteAssets() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); } + bool getThisNodeCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } quint16 getSocketLocalPort() const { return _nodeSocket.localPort(); } QUdpSocket& getDTLSSocket(); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 270814c35c..18088c6cea 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -69,6 +69,7 @@ public: bool getCanRez() const { return _permissions.can(NodePermissions::Permission::canRezPermanentEntities); } bool getCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); } bool getCanWriteToAssetServer() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); } + bool getCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } void parseIgnoreRequestMessage(QSharedPointer message); void addIgnoredNode(const QUuid& otherNodeID); From 7e6dbf2d1a8869c2d28619ddd08b13fd182cb155 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jul 2016 18:39:22 -0700 Subject: [PATCH 21/42] add a kick request packet and send from NL --- libraries/networking/src/NodeList.cpp | 27 ++++++++++++++++++- libraries/networking/src/NodeList.h | 2 ++ .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- .../src/UsersScriptingInterface.cpp | 5 ++++ .../src/UsersScriptingInterface.h | 1 + 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 05b5532560..781cc00c1c 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -727,7 +727,7 @@ void NodeList::ignoreNodeBySessionID(const QUuid& nodeID) { emit ignoredNode(nodeID); } else { - qWarning() << "UsersScriptingInterface::ignore called with an invalid ID or an ID which matches the current session ID."; + qWarning() << "NodeList::ignoreNodeBySessionID called with an invalid ID or an ID which matches the current session ID."; } } @@ -759,3 +759,28 @@ void NodeList::maybeSendIgnoreSetToNode(SharedNodePointer newNode) { } } } + +void NodeList::kickNodeBySessionID(const QUuid& nodeID) { + // send a request to domain-server to kick the node with the given session ID + // the domain-server will handle the persistence of the kick (via username or IP) + + if (!nodeID.isNull() && _sessionUUID != nodeID ) { + if (getThisNodeCanKick()) { + // setup the packet + auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID, true); + + // write the node ID to the packet + kickPacket->write(nodeID.toRfc4122()); + + qDebug() << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID); + + sendPacket(std::move(kickPacket), _domainHandler.getSockAddr()); + } else { + qWarning() << "You do not have permissions to kick in this domain." + << "Request to kick node" << uuidStringWithoutCurlyBraces(nodeID) << "will not be sent"; + } + } else { + qWarning() << "NodeList::kickNodeBySessionID called with an invalid ID or an ID which matches the current session ID."; + + } +} diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index ff994ce612..f3cd5bed0d 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -73,6 +73,8 @@ public: void ignoreNodeBySessionID(const QUuid& nodeID); bool isIgnoringNode(const QUuid& nodeID) const; + void kickNodeBySessionID(const QUuid& nodeID); + public slots: void reset(); void sendDomainServerCheckIn(); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index ce1f25d45d..e9d61a827a 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -26,7 +26,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::OctreeDataNack << PacketType::EntityEditNack << PacketType::DomainListRequest << PacketType::StopNode - << PacketType::DomainDisconnectRequest; + << PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest; const QSet NON_SOURCED_PACKETS = QSet() << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 7281e24fa9..40524e2288 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -98,7 +98,8 @@ public: NegotiateAudioFormat, SelectedAudioFormat, MoreEntityShapes, - LAST_PACKET_TYPE = MoreEntityShapes + NodeKickRequest, + LAST_PACKET_TYPE = NodeKickRequest }; }; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index ff7ccb0164..6be3aa39ac 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -17,3 +17,8 @@ void UsersScriptingInterface::ignore(const QUuid& nodeID) { // ask the NodeList to ignore this user (based on the session ID of their node) DependencyManager::get()->ignoreNodeBySessionID(nodeID); } + +void UsersScriptingInterface::kick(const QUuid& nodeID) { + // ask the NodeList to kick the user with the given session ID + DependencyManager::get()->kickNodeBySessionID(nodeID); +} diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 0dc62c088c..c5929dc8b2 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -22,6 +22,7 @@ class UsersScriptingInterface : public QObject, public Dependency { public slots: void ignore(const QUuid& nodeID); + void kick(const QUuid& nodeID); }; From 5b04ab6d530fa8d7347be6841e3548ca0dc7d436 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jul 2016 09:58:34 -0700 Subject: [PATCH 22/42] add node kick request handling to DS --- domain-server/src/DomainServer.cpp | 1 + .../src/DomainServerSettingsManager.cpp | 59 +++++++++++++++++++ .../src/DomainServerSettingsManager.h | 1 + 3 files changed, 61 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8af364992c..23e37efaf1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -411,6 +411,7 @@ void DomainServer::setupNodeListAndAssignments() { // NodeList won't be available to the settings manager when it is created, so call registerListener here packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket"); + packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket"); // register the gatekeeper for the packets it needs to receive packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index aba2c25db5..639098fdef 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -613,6 +613,65 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() { return changed; } + +void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode) { + // before we do any processing on this packet make sure it comes from a node that is allowed to kick + if (sendingNode->getCanKick()) { + // pull the UUID being kicked from the packet + QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { + // make sure we actually have a node with this UUID + auto limitedNodeList = DependencyManager::get(); + + auto matchingNode = limitedNodeList->nodeWithUUID(nodeUUID); + + if (matchingNode) { + // we have a matching node, time to decide how to store updated permissions for this node + + NodePermissionsPointer destinationPermissions; + + auto verifiedUsername = matchingNode->getPermissions().getVerifiedUserName(); + + if (!verifiedUsername.isEmpty()) { + // if we have a verified user name for this user, we apply the kick to the username + + // grab or create permissions for the given username + destinationPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; + } else { + // otherwise we apply the kick to the IP from active socket for this node + // (falling back to the public socket if not yet active) + auto& kickAddress = matchingNode->getActiveSocket() + ? matchingNode->getActiveSocket()->getAddress() + : matchingNode->getPublicSocket().getAddress(); + + // grab or create permissions for the given IP address + NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); + destinationPermissions = _ipPermissions[ipAddressKey]; + } + + // ensure that the connect permission is clear + destinationPermissions->clear(NodePermissions::Permission::canConnectToDomain); + + // we've changed permissions, time to store them to disk and emit our signal to say they have changed + packPermissions(); + + emit updateNodePermissions(); + + } else { + qWarning() << "Node kick request received for unknown node. Refusing to process."; + } + } else { + // this isn't a UUID we can use + qWarning() << "Node kick request received for invalid node ID or from node being kicked. Refusing to process."; + } + + } else { + qWarning() << "Refusing to process a kick packet from node" << uuidStringWithoutCurlyBraces(sendingNode->getUUID()) + << "that does not have kick permissions."; + } +} + QStringList DomainServerSettingsManager::getAllNames() const { QStringList result; foreach (auto key, _agentPermissions.keys()) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 49c3ac95b7..d551132006 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -105,6 +105,7 @@ public slots: private slots: void processSettingsRequestPacket(QSharedPointer message); + void processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode); private: QStringList _argumentList; From 285478f1b25cc920dc3be25004aae7bc0bef4db6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jul 2016 10:23:09 -0700 Subject: [PATCH 23/42] don't repack the same permissions after kick --- .../src/DomainServerSettingsManager.cpp | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 639098fdef..e85eebd309 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -633,9 +633,14 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetPermissions().getVerifiedUserName(); + bool hadExistingPermissions = false; + if (!verifiedUsername.isEmpty()) { // if we have a verified user name for this user, we apply the kick to the username + // check if there were already permissions + hadExistingPermissions = havePermissionsForName(verifiedUsername); + // grab or create permissions for the given username destinationPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; } else { @@ -645,18 +650,37 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetActiveSocket()->getAddress() : matchingNode->getPublicSocket().getAddress(); - // grab or create permissions for the given IP address NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); + + // check if there were already permissions for the IP + hadExistingPermissions = hasPermissionsForIP(kickAddress); + + // grab or create permissions for the given IP address destinationPermissions = _ipPermissions[ipAddressKey]; } - // ensure that the connect permission is clear - destinationPermissions->clear(NodePermissions::Permission::canConnectToDomain); + // make sure we didn't already have existing permissions that disallowed connect + if (!hadExistingPermissions + || destinationPermissions->can(NodePermissions::Permission::canConnectToDomain)) { - // we've changed permissions, time to store them to disk and emit our signal to say they have changed - packPermissions(); + qDebug() << "Removing connect permission for node" << uuidStringWithoutCurlyBraces(matchingNode->getUUID()) + << "after kick request"; - emit updateNodePermissions(); + // ensure that the connect permission is clear + destinationPermissions->clear(NodePermissions::Permission::canConnectToDomain); + + // we've changed permissions, time to store them to disk and emit our signal to say they have changed + packPermissions(); + + emit updateNodePermissions(); + } else { + qWarning() << "Received kick request for node" << uuidStringWithoutCurlyBraces(matchingNode->getUUID()) + << "that already did not have permission to connect"; + + // in this case, though we don't expect the node to be connected to the domain, it is + // emit updateNodePermissions so that the DomainGatekeeper kicks it out + emit updateNodePermissions(); + } } else { qWarning() << "Node kick request received for unknown node. Refusing to process."; From 62af203d08f4ffd398e555fc82c0fe176024fcca Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jul 2016 13:19:10 -0700 Subject: [PATCH 24/42] migrate the deprecated merged master/user config --- .../resources/describe-settings.json | 2 +- domain-server/resources/web/css/style.css | 9 ---- .../resources/web/settings/index.shtml | 6 +-- .../resources/web/settings/js/settings.js | 50 +++++++------------ .../src/DomainServerSettingsManager.cpp | 32 ++++++++---- libraries/shared/src/HifiConfigVariantMap.cpp | 13 +++-- libraries/shared/src/HifiConfigVariantMap.h | 1 + 7 files changed, 52 insertions(+), 61 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 524a687772..c888fa301b 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.6, + "version": 1.7, "settings": [ { "name": "metaverse", diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index b66b7df258..ef967a47bf 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -75,15 +75,6 @@ span.port { color: #666666; } -.locked { - color: #428bca; -} - -.locked-table { - cursor: not-allowed; - background-color: #eee; -} - .advanced-setting { display: none; } diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 3f969ef913..4c937d6139 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -57,15 +57,13 @@
<% _.each(split_settings[0], function(setting) { %> <% keypath = isGrouped ? group.name + "." + setting.name : setting.name %> - <%= getFormGroup(keypath, setting, values, false, - (_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %> + <%= getFormGroup(keypath, setting, values, false) %> <% }); %> <% if (!_.isEmpty(split_settings[1])) { %> <% $("#advanced-toggle-button").show() %> <% _.each(split_settings[1], function(setting) { %> <% keypath = isGrouped ? group.name + "." + setting.name : setting.name %> - <%= getFormGroup(keypath, setting, values, true, - (_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %> + <%= getFormGroup(keypath, setting, values, true) %> <% }); %> <% }%>
diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index c1005de105..42fcb05d2e 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -41,7 +41,7 @@ var Settings = { }; var viewHelpers = { - getFormGroup: function(keypath, setting, values, isAdvanced, isLocked) { + getFormGroup: function(keypath, setting, values, isAdvanced) { form_group = "
"; setting_value = _(values).valueForKeyPath(keypath); @@ -54,9 +54,6 @@ var viewHelpers = { } label_class = 'control-label'; - if (isLocked) { - label_class += ' locked'; - } function common_attrs(extra_classes) { extra_classes = (!_.isUndefined(extra_classes) ? extra_classes : ""); @@ -71,9 +68,8 @@ var viewHelpers = { form_group += "" } - form_group += "
" - form_group += "" + form_group += "
" + form_group += "" if (setting.help) { form_group += "" + setting.help + ""; @@ -88,7 +84,7 @@ var viewHelpers = { } if (input_type === 'table') { - form_group += makeTable(setting, keypath, setting_value, isLocked) + form_group += makeTable(setting, keypath, setting_value) } else { if (input_type === 'select') { form_group += "" + "' value='" + setting_value + "'/>" } form_group += "" + setting.help + "" @@ -459,10 +453,8 @@ function setupHFAccountButton() { $("[data-keypath='metaverse.automatic_networking']").hide(); } - var tokenLocked = _(Settings.data).valueForKeyPath("locked.metaverse.access_token"); - // use the existing getFormGroup helper to ask for a button - var buttonGroup = viewHelpers.getFormGroup('', buttonSetting, Settings.data.values, false, tokenLocked); + var buttonGroup = viewHelpers.getFormGroup('', buttonSetting, Settings.data.values, false); // add the button group to the top of the metaverse panel $('#metaverse .panel-body').prepend(buttonGroup); @@ -673,7 +665,7 @@ function setupPlacesTable() { } // get a table for the places - var placesTableGroup = viewHelpers.getFormGroup('', placesTableSetting, Settings.data.values, false, false); + var placesTableGroup = viewHelpers.getFormGroup('', placesTableSetting, Settings.data.values, false); // append the places table in the right place $('#places_paths .panel-body').prepend(placesTableGroup); @@ -873,10 +865,8 @@ function reloadSettings(callback) { Settings.data = data; Settings.initialValues = form2js('settings-form', ".", false, cleanupFormValues, true); - if (!_.has(data["locked"], "metaverse") && !_.has(data["locked"]["metaverse"], "id")) { - // append the domain selection modal, as long as it's not locked - appendDomainIDButtons(); - } + // append the domain selection modal + appendDomainIDButtons(); // call our method to setup the HF account button setupHFAccountButton(); @@ -889,12 +879,6 @@ function reloadSettings(callback) { $('[data-toggle="tooltip"]').tooltip(); - // add tooltip to locked settings - $('label.locked').tooltip({ - placement: 'right', - title: 'This setting is in the master config file and cannot be changed' - }); - // call the callback now that settings are loaded callback(true); }).fail(function() { @@ -943,11 +927,11 @@ $('body').on('click', '.save-button', function(e){ return false; }); -function makeTable(setting, keypath, setting_value, isLocked) { +function makeTable(setting, keypath, setting_value) { var isArray = !_.has(setting, 'key'); var categoryKey = setting.categorize_by_key; var isCategorized = !!categoryKey && isArray; - + if (!isArray && setting.can_order) { setting.can_order = false; } @@ -961,7 +945,7 @@ function makeTable(setting, keypath, setting_value, isLocked) { var nonDeletableRowKey = setting["non-deletable-row-key"]; var nonDeletableRowValues = setting["non-deletable-row-values"]; - html += ""; @@ -976,7 +960,7 @@ function makeTable(setting, keypath, setting_value, isLocked) { _.each(setting.groups, function (group) { html += "" }) - if (!isLocked && !setting.read_only) { + if (!setting.read_only) { if (setting.can_order) { html += ""; @@ -1004,7 +988,7 @@ function makeTable(setting, keypath, setting_value, isLocked) { (col.class ? col.class : '') + "'>" + col.label + "" // Data }) - if (!isLocked && !setting.read_only) { + if (!setting.read_only) { if (setting.can_order) { numVisibleColumns++; html += "
" + group.label + "" @@ -1108,7 +1092,7 @@ function makeTable(setting, keypath, setting_value, isLocked) { } // populate inputs in the table for new values - if (!isLocked && !setting.read_only) { + if (!setting.read_only) { if (setting.can_add_new_categories) { html += makeTableCategoryInput(setting, numVisibleColumns); } diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index e85eebd309..bd916a43fe 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -95,6 +95,8 @@ void DomainServerSettingsManager::processSettingsRequestPacket(QSharedPointerclear(); - QVariant* permissions = valueForKeyPath(_configMap.getMergedConfig(), keyPath, true); + QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath, true); if (!permissions->canConvert(QMetaType::QVariantList)) { qDebug() << "Failed to extract permissions for key path" << keyPath << "from settings."; (*permissions) = QVariantList(); @@ -777,7 +788,7 @@ NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QUuid& } QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QString& keyPath) { - const QVariant* foundValue = valueForKeyPath(_configMap.getMergedConfig(), keyPath); + const QVariant* foundValue = valueForKeyPath(_configMap.getUserConfig(), keyPath); if (foundValue) { return *foundValue; @@ -860,12 +871,10 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection // setup a JSON Object with descriptions and non-omitted settings const QString SETTINGS_RESPONSE_DESCRIPTION_KEY = "descriptions"; const QString SETTINGS_RESPONSE_VALUE_KEY = "values"; - const QString SETTINGS_RESPONSE_LOCKED_VALUES_KEY = "locked"; QJsonObject rootObject; rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray; rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true); - rootObject[SETTINGS_RESPONSE_LOCKED_VALUES_KEY] = QJsonDocument::fromVariant(_configMap.getMasterConfig()).object(); connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json"); } @@ -910,13 +919,13 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty QVariant variantValue; if (!groupKey.isEmpty()) { - QVariant settingsMapGroupValue = _configMap.getMergedConfig().value(groupKey); + QVariant settingsMapGroupValue = _configMap.getUserConfig().value(groupKey); if (!settingsMapGroupValue.isNull()) { variantValue = settingsMapGroupValue.toMap().value(settingName); } } else { - variantValue = _configMap.getMergedConfig().value(settingName); + variantValue = _configMap.getUserConfig().value(settingName); } QJsonValue result; @@ -1208,6 +1217,9 @@ void DomainServerSettingsManager::persistToFile() { settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson()); } else { qCritical("Could not write to JSON settings file. Unable to persist settings."); + + // failed to write, reload whatever the current config state is + _configMap.loadConfig(_argumentList); } } diff --git a/libraries/shared/src/HifiConfigVariantMap.cpp b/libraries/shared/src/HifiConfigVariantMap.cpp index 5ae5ff740d..30eb200770 100644 --- a/libraries/shared/src/HifiConfigVariantMap.cpp +++ b/libraries/shared/src/HifiConfigVariantMap.cpp @@ -111,6 +111,13 @@ void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentLi loadMapFromJSONFile(_masterConfig, masterConfigFilepath); } + // load the user config - that method replaces loadMasterAndUserConfig after the 1.7 migration + loadConfig(argumentList); + + mergeMasterAndUserConfigs(); +} + +void HifiConfigVariantMap::loadConfig(const QStringList& argumentList) { // load the user config const QString USER_CONFIG_FILE_OPTION = "--user-config"; static const QString USER_CONFIG_FILE_NAME = "config.json"; @@ -159,12 +166,10 @@ void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentLi } } } - + } - + loadMapFromJSONFile(_userConfig, _userConfigFilename); - - mergeMasterAndUserConfigs(); } void HifiConfigVariantMap::mergeMasterAndUserConfigs() { diff --git a/libraries/shared/src/HifiConfigVariantMap.h b/libraries/shared/src/HifiConfigVariantMap.h index e92561cff5..06e28cf182 100644 --- a/libraries/shared/src/HifiConfigVariantMap.h +++ b/libraries/shared/src/HifiConfigVariantMap.h @@ -21,6 +21,7 @@ public: HifiConfigVariantMap(); void loadMasterAndUserConfig(const QStringList& argumentList); + void loadConfig(const QStringList& argumentList); const QVariantMap& getMasterConfig() const { return _masterConfig; } QVariantMap& getUserConfig() { return _userConfig; } From 39e6ac09746b4d55122309cc26b0361ebbe24964 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jul 2016 13:46:28 -0700 Subject: [PATCH 25/42] cleanup API for HifiConfigVariantMap after migration --- .../src/DomainServerSettingsManager.cpp | 47 +++++++++---------- .../src/DomainServerSettingsManager.h | 3 +- libraries/shared/src/HifiConfigVariantMap.cpp | 2 +- libraries/shared/src/HifiConfigVariantMap.h | 11 +++-- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index bd916a43fe..c47c786efa 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -120,7 +120,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // This was prior to the introduction of security.restricted_access // If the user has a list of allowed users then set their value for security.restricted_access to true - QVariant* allowedUsers = valueForKeyPath(_configMap.getMergedConfig(), ALLOWED_USERS_SETTINGS_KEYPATH); + QVariant* allowedUsers = _configMap.valueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH); if (allowedUsers && allowedUsers->canConvert(QMetaType::QVariantList) @@ -131,9 +131,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // In the pre-toggle system the user had a list of allowed users, so // we need to set security.restricted_access to true - QVariant* restrictedAccess = valueForKeyPath(_configMap.getUserConfig(), - RESTRICTED_ACCESS_SETTINGS_KEYPATH, - true); + QVariant* restrictedAccess = _configMap.valueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH, true); *restrictedAccess = QVariant(true); @@ -151,21 +149,20 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList static const QString ENTITY_FILE_PATH_KEYPATH = ENTITY_SERVER_SETTINGS_KEY + ".persistFilePath"; // this was prior to change of poorly named entitiesFileName to entitiesFilePath - QVariant* persistFileNameVariant = valueForKeyPath(_configMap.getMergedConfig(), - ENTITY_SERVER_SETTINGS_KEY + "." + ENTITY_FILE_NAME_KEY); + QVariant* persistFileNameVariant = _configMap.valueForKeyPath(ENTITY_SERVER_SETTINGS_KEY + "." + ENTITY_FILE_NAME_KEY); if (persistFileNameVariant && persistFileNameVariant->canConvert(QMetaType::QString)) { QString persistFileName = persistFileNameVariant->toString(); qDebug() << "Migrating persistFilename to persistFilePath for entity-server settings"; // grab the persistFilePath option, create it if it doesn't exist - QVariant* persistFilePath = valueForKeyPath(_configMap.getUserConfig(), ENTITY_FILE_PATH_KEYPATH, true); + QVariant* persistFilePath = _configMap.valueForKeyPath(ENTITY_FILE_PATH_KEYPATH, true); // write the migrated value *persistFilePath = persistFileName; // remove the old setting - QVariant* entityServerVariant = valueForKeyPath(_configMap.getUserConfig(), ENTITY_SERVER_SETTINGS_KEY); + QVariant* entityServerVariant = _configMap.valueForKeyPath(ENTITY_SERVER_SETTINGS_KEY); if (entityServerVariant && entityServerVariant->canConvert(QMetaType::QVariantMap)) { QVariantMap entityServerMap = entityServerVariant->toMap(); entityServerMap.remove(ENTITY_FILE_NAME_KEY); @@ -187,7 +184,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // If we have a password in the previous settings file, make it base 64 static const QString BASIC_AUTH_PASSWORD_KEY_PATH { "security.http_password" }; - QVariant* passwordVariant = valueForKeyPath(_configMap.getUserConfig(), BASIC_AUTH_PASSWORD_KEY_PATH); + QVariant* passwordVariant = _configMap.valueForKeyPath(BASIC_AUTH_PASSWORD_KEY_PATH); if (passwordVariant && passwordVariant->canConvert(QMetaType::QString)) { QString plaintextPassword = passwordVariant->toString(); @@ -292,7 +289,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList qDebug() << "Migrating merged config to user config file. The master config file is deprecated."; // replace the user config by the merged config - _configMap.getUserConfig() = _configMap.getMergedConfig(); + _configMap.getConfig() = _configMap.getMergedConfig(); // persist the new config so the user config file has the correctly merged config persistToFile(); @@ -317,9 +314,9 @@ void DomainServerSettingsManager::validateDescriptorsMap() { static const QString WEEKEND_HOURS{ "descriptors.weekend_hours" }; static const QString UTC_OFFSET{ "descriptors.utc_offset" }; - QVariant* weekdayHours = valueForKeyPath(_configMap.getUserConfig(), WEEKDAY_HOURS, true); - QVariant* weekendHours = valueForKeyPath(_configMap.getUserConfig(), WEEKEND_HOURS, true); - QVariant* utcOffset = valueForKeyPath(_configMap.getUserConfig(), UTC_OFFSET, true); + QVariant* weekdayHours = _configMap.valueForKeyPath(WEEKDAY_HOURS, true); + QVariant* weekendHours = _configMap.valueForKeyPath(WEEKEND_HOURS, true); + QVariant* utcOffset = _configMap.valueForKeyPath(UTC_OFFSET, true); static const QString OPEN{ "open" }; static const QString CLOSE{ "close" }; @@ -375,13 +372,13 @@ void DomainServerSettingsManager::packPermissionsForMap(QString mapName, NodePermissionsMap& permissionsRows, QString keyPath) { // find (or create) the "security" section of the settings map - QVariant* security = valueForKeyPath(_configMap.getUserConfig(), "security", true); + QVariant* security = _configMap.valueForKeyPath("security", true); if (!security->canConvert(QMetaType::QVariantMap)) { (*security) = QVariantMap(); } // find (or create) whichever subsection of "security" we are packing - QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath, true); + QVariant* permissions = _configMap.valueForKeyPath(keyPath, true); if (!permissions->canConvert(QMetaType::QVariantList)) { (*permissions) = QVariantList(); } @@ -457,7 +454,7 @@ bool DomainServerSettingsManager::unpackPermissionsForKeypath(const QString& key mapPointer->clear(); - QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath, true); + QVariant* permissions = _configMap.valueForKeyPath(keyPath, true); if (!permissions->canConvert(QMetaType::QVariantList)) { qDebug() << "Failed to extract permissions for key path" << keyPath << "from settings."; (*permissions) = QVariantList(); @@ -788,7 +785,7 @@ NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QUuid& } QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QString& keyPath) { - const QVariant* foundValue = valueForKeyPath(_configMap.getUserConfig(), keyPath); + const QVariant* foundValue = _configMap.valueForKeyPath(keyPath); if (foundValue) { return *foundValue; @@ -919,13 +916,13 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty QVariant variantValue; if (!groupKey.isEmpty()) { - QVariant settingsMapGroupValue = _configMap.getUserConfig().value(groupKey); + QVariant settingsMapGroupValue = _configMap.value(groupKey); if (!settingsMapGroupValue.isNull()) { variantValue = settingsMapGroupValue.toMap().value(settingName); } } else { - variantValue = _configMap.getUserConfig().value(settingName); + variantValue = _configMap.value(settingName); } QJsonValue result; @@ -1067,7 +1064,7 @@ QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJson } bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject) { - auto& settingsVariant = _configMap.getUserConfig(); + auto& settingsVariant = _configMap.getConfig(); bool needRestart = false; // Iterate on the setting groups @@ -1179,22 +1176,22 @@ bool permissionVariantLessThan(const QVariant &v1, const QVariant &v2) { void DomainServerSettingsManager::sortPermissions() { // sort the permission-names - QVariant* standardPermissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_STANDARD_PERMISSIONS_KEYPATH); + QVariant* standardPermissions = _configMap.valueForKeyPath(AGENT_STANDARD_PERMISSIONS_KEYPATH); if (standardPermissions && standardPermissions->canConvert(QMetaType::QVariantList)) { QList* standardPermissionsList = reinterpret_cast(standardPermissions); std::sort((*standardPermissionsList).begin(), (*standardPermissionsList).end(), permissionVariantLessThan); } - QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH); + QVariant* permissions = _configMap.valueForKeyPath(AGENT_PERMISSIONS_KEYPATH); if (permissions && permissions->canConvert(QMetaType::QVariantList)) { QList* permissionsList = reinterpret_cast(permissions); std::sort((*permissionsList).begin(), (*permissionsList).end(), permissionVariantLessThan); } - QVariant* groupPermissions = valueForKeyPath(_configMap.getUserConfig(), GROUP_PERMISSIONS_KEYPATH); + QVariant* groupPermissions = _configMap.valueForKeyPath(GROUP_PERMISSIONS_KEYPATH); if (groupPermissions && groupPermissions->canConvert(QMetaType::QVariantList)) { QList* permissionsList = reinterpret_cast(groupPermissions); std::sort((*permissionsList).begin(), (*permissionsList).end(), permissionVariantLessThan); } - QVariant* forbiddenPermissions = valueForKeyPath(_configMap.getUserConfig(), GROUP_FORBIDDENS_KEYPATH); + QVariant* forbiddenPermissions = _configMap.valueForKeyPath(GROUP_FORBIDDENS_KEYPATH); if (forbiddenPermissions && forbiddenPermissions->canConvert(QMetaType::QVariantList)) { QList* permissionsList = reinterpret_cast(forbiddenPermissions); std::sort((*permissionsList).begin(), (*permissionsList).end(), permissionVariantLessThan); @@ -1214,7 +1211,7 @@ void DomainServerSettingsManager::persistToFile() { QFile settingsFile(_configMap.getUserConfigFilename()); if (settingsFile.open(QIODevice::WriteOnly)) { - settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson()); + settingsFile.write(QJsonDocument::fromVariant(_configMap.getConfig()).toJson()); } else { qCritical("Could not write to JSON settings file. Unable to persist settings."); diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index d551132006..144589326c 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -44,8 +44,7 @@ public: void setupConfigMap(const QStringList& argumentList); QVariant valueOrDefaultValueForKeyPath(const QString& keyPath); - QVariantMap& getUserSettingsMap() { return _configMap.getUserConfig(); } - QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); } + QVariantMap& getSettingsMap() { return _configMap.getConfig(); } QVariantMap& getDescriptorsMap(); diff --git a/libraries/shared/src/HifiConfigVariantMap.cpp b/libraries/shared/src/HifiConfigVariantMap.cpp index 30eb200770..252079f182 100644 --- a/libraries/shared/src/HifiConfigVariantMap.cpp +++ b/libraries/shared/src/HifiConfigVariantMap.cpp @@ -111,7 +111,7 @@ void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentLi loadMapFromJSONFile(_masterConfig, masterConfigFilepath); } - // load the user config - that method replaces loadMasterAndUserConfig after the 1.7 migration + // load the user config - that method replace loadMasterAndUserConfig after the 1.7 migration loadConfig(argumentList); mergeMasterAndUserConfigs(); diff --git a/libraries/shared/src/HifiConfigVariantMap.h b/libraries/shared/src/HifiConfigVariantMap.h index 06e28cf182..cb6e92df96 100644 --- a/libraries/shared/src/HifiConfigVariantMap.h +++ b/libraries/shared/src/HifiConfigVariantMap.h @@ -15,6 +15,8 @@ #include #include +QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath, bool shouldCreateIfMissing = false); + class HifiConfigVariantMap { public: static QVariantMap mergeCLParametersWithJSONConfig(const QStringList& argumentList); @@ -23,9 +25,12 @@ public: void loadMasterAndUserConfig(const QStringList& argumentList); void loadConfig(const QStringList& argumentList); - const QVariantMap& getMasterConfig() const { return _masterConfig; } - QVariantMap& getUserConfig() { return _userConfig; } + const QVariant value(const QString& key) const { return _userConfig.value(key); } + QVariant* valueForKeyPath(const QString& keyPath, bool shouldCreateIfMissing = false) + { return ::valueForKeyPath(_userConfig, keyPath, shouldCreateIfMissing); } + QVariantMap& getMergedConfig() { return _mergedConfig; } + QVariantMap& getConfig() { return _userConfig; } void mergeMasterAndUserConfigs(); @@ -41,6 +46,4 @@ private: void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap); }; -QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath, bool shouldCreateIfMissing = false); - #endif // hifi_HifiConfigVariantMap_h From 4cdc98287bb110a1121ae22cb34c9563231bca7a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jul 2016 17:06:51 -0700 Subject: [PATCH 26/42] add canKick to USI, revert constants to production --- libraries/networking/src/LimitedNodeList.cpp | 4 ++++ libraries/networking/src/LimitedNodeList.h | 1 + .../script-engine/src/UsersScriptingInterface.cpp | 11 +++++++++++ libraries/script-engine/src/UsersScriptingInterface.h | 10 ++++++++++ 4 files changed, 26 insertions(+) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b470c2fe25..431d372089 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -151,6 +151,10 @@ void LimitedNodeList::setPermissions(const NodePermissions& newPermissions) { newPermissions.can(NodePermissions::Permission::canWriteToAssetServer)) { emit canWriteAssetsChanged(_permissions.can(NodePermissions::Permission::canWriteToAssetServer)); } + if (originalPermissions.can(NodePermissions::Permission::canKick) != + newPermissions.can(NodePermissions::Permission::canKick)) { + emit canKickChanged(_permissions.can(NodePermissions::Permission::canKick)); + } } QUdpSocket& LimitedNodeList::getDTLSSocket() { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 2b2f660569..48379b5e39 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -259,6 +259,7 @@ signals: void canRezChanged(bool canRez); void canRezTmpChanged(bool canRezTmp); void canWriteAssetsChanged(bool canWriteAssets); + void canKickChanged(bool canKick); protected slots: void connectedForLocalSocketTest(); diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 6be3aa39ac..69ad8e04ad 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -13,6 +13,12 @@ #include +UsersScriptingInterface::UsersScriptingInterface() { + // emit a signal when kick permissions have changed + auto nodeList = DependencyManager::get(); + connect(nodeList.data(), &LimitedNodeList::canKickChanged, this, &UsersScriptingInterface::canKickChanged); +} + void UsersScriptingInterface::ignore(const QUuid& nodeID) { // ask the NodeList to ignore this user (based on the session ID of their node) DependencyManager::get()->ignoreNodeBySessionID(nodeID); @@ -22,3 +28,8 @@ void UsersScriptingInterface::kick(const QUuid& nodeID) { // ask the NodeList to kick the user with the given session ID DependencyManager::get()->kickNodeBySessionID(nodeID); } + +bool UsersScriptingInterface::getCanKick() { + // ask the NodeList to return our ability to kick + return DependencyManager::get()->getThisNodeCanKick(); +} diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index c5929dc8b2..712eeedeb6 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -20,9 +20,19 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY + Q_PROPERTY(bool canKick READ getCanKick) + +public: + UsersScriptingInterface(); + public slots: void ignore(const QUuid& nodeID); void kick(const QUuid& nodeID); + + bool getCanKick(); + +signals: + void canKickChanged(bool canKick); }; From 5eb890e4f5c85379d16de3939ddae35851341847 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 13:26:25 -0700 Subject: [PATCH 27/42] add a simple IP address sanitizer for DS settings save --- domain-server/src/DomainServerSettingsManager.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c47c786efa..dc49bc6126 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -495,7 +495,17 @@ void DomainServerSettingsManager::unpackPermissions() { needPack |= unpackPermissionsForKeypath(AGENT_PERMISSIONS_KEYPATH, &_agentPermissions); - needPack |= unpackPermissionsForKeypath(IP_PERMISSIONS_KEYPATH, &_ipPermissions); + needPack |= unpackPermissionsForKeypath(IP_PERMISSIONS_KEYPATH, &_ipPermissions, + [&](NodePermissionsPointer perms){ + // make sure that this permission row is for a valid IP address + if (QHostAddress(perms->getKey().first).isNull()) { + _ipPermissions.remove(perms->getKey()); + + // we removed a row from the IP permissions, we'll need a re-pack + needPack = true; + } + }); + needPack |= unpackPermissionsForKeypath(GROUP_PERMISSIONS_KEYPATH, &_groupPermissions, [&](NodePermissionsPointer perms){ From a15aef34dfc050faffcde02e7da9eeb39363ff8d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 13:30:33 -0700 Subject: [PATCH 28/42] modify ignore script to handle kicking --- .../system/assets/images/ignore-target-01.svg | 37 ----- .../system/assets/images/ignore-target.svg | 52 +++++++ scripts/system/assets/images/kick-target.svg | 34 +++++ scripts/system/assets/images/tools/kick.svg | 140 ++++++++++++++++++ scripts/system/ignore.js | 23 ++- 5 files changed, 246 insertions(+), 40 deletions(-) delete mode 100644 scripts/system/assets/images/ignore-target-01.svg create mode 100644 scripts/system/assets/images/ignore-target.svg create mode 100644 scripts/system/assets/images/kick-target.svg create mode 100644 scripts/system/assets/images/tools/kick.svg diff --git a/scripts/system/assets/images/ignore-target-01.svg b/scripts/system/assets/images/ignore-target-01.svg deleted file mode 100644 index 98cee89ca1..0000000000 --- a/scripts/system/assets/images/ignore-target-01.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/ignore-target.svg b/scripts/system/assets/images/ignore-target.svg new file mode 100644 index 0000000000..ca6aca3a5a --- /dev/null +++ b/scripts/system/assets/images/ignore-target.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/kick-target.svg b/scripts/system/assets/images/kick-target.svg new file mode 100644 index 0000000000..e1ff64d272 --- /dev/null +++ b/scripts/system/assets/images/kick-target.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/tools/kick.svg b/scripts/system/assets/images/tools/kick.svg new file mode 100644 index 0000000000..1eed6e7f43 --- /dev/null +++ b/scripts/system/assets/images/tools/kick.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/ignore.js b/scripts/system/ignore.js index 1c996a7fcc..fac20eb02f 100644 --- a/scripts/system/ignore.js +++ b/scripts/system/ignore.js @@ -12,10 +12,14 @@ // grab the toolbar var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); +function buttonImageURL() { + return Script.resolvePath("assets/images/tools/" + (Users.canKick ? 'kick.svg' : 'ignore.svg')); +} + // setup the ignore button and add it to the toolbar var button = toolbar.addButton({ objectName: 'ignore', - imageURL: Script.resolvePath("assets/images/tools/ignore.svg"), + imageURL: buttonImageURL(), visible: true, buttonState: 1, defaultState: 2, @@ -23,6 +27,11 @@ var button = toolbar.addButton({ alpha: 0.9 }); +// if this user's kick permissions change, change the state of the button in the HUD +Users.canKickChanged.connect(function(canKick){ + button.writeProperty('imageURL', buttonImageURL()); +}); + var isShowingOverlays = false; var ignoreOverlays = {}; @@ -54,6 +63,10 @@ function buttonClicked(){ button.clicked.connect(buttonClicked); +function overlayURL() { + return Script.resolvePath("assets/images/" + (Users.canKick ? "kick-target.svg" : "ignore-target.svg")); +} + function updateOverlays() { if (isShowingOverlays) { @@ -88,7 +101,7 @@ function updateOverlays() { } else { // add the overlay above this avatar var newOverlay = Overlays.addOverlay("image3d", { - url: Script.resolvePath("assets/images/ignore-target-01.svg"), + url: overlayURL(), position: overlayPosition, size: 0.4, scale: 0.4, @@ -130,7 +143,11 @@ function handleSelectedOverlay(clickedOverlay) { if (clickedOverlay.overlayID == ignoreOverlay) { // matched to an overlay, ask for the matching avatar to be ignored - Users.ignore(avatarID); + if (Users.canKick) { + Users.kick(avatarID); + } else { + Users.ignore(avatarID); + } // cleanup of the overlay is handled by the connection to avatarRemovedEvent } From 7d9937e412e81c89b5a75304cbff7a659facf061 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 13:35:41 -0700 Subject: [PATCH 29/42] handle overlay change if permissions change --- scripts/system/ignore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/ignore.js b/scripts/system/ignore.js index fac20eb02f..cae4e14638 100644 --- a/scripts/system/ignore.js +++ b/scripts/system/ignore.js @@ -96,7 +96,8 @@ function updateOverlays() { if (avatarID in ignoreOverlays) { // keep the overlay above the current position of this avatar Overlays.editOverlay(ignoreOverlays[avatarID], { - position: overlayPosition + position: overlayPosition, + url: overlayURL() }); } else { // add the overlay above this avatar From 6051fcd8f948686e408e91326e363a02763ff641 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 14:37:09 -0700 Subject: [PATCH 30/42] use click instead of trigger, change targets to PNG --- .../system/assets/images/ignore-target.png | Bin 0 -> 8055 bytes .../system/assets/images/ignore-target.svg | 52 ------------------ scripts/system/assets/images/kick-target.png | Bin 0 -> 6540 bytes scripts/system/assets/images/kick-target.svg | 34 ------------ scripts/system/ignore.js | 40 ++++---------- 5 files changed, 12 insertions(+), 114 deletions(-) create mode 100644 scripts/system/assets/images/ignore-target.png delete mode 100644 scripts/system/assets/images/ignore-target.svg create mode 100644 scripts/system/assets/images/kick-target.png delete mode 100644 scripts/system/assets/images/kick-target.svg diff --git a/scripts/system/assets/images/ignore-target.png b/scripts/system/assets/images/ignore-target.png new file mode 100644 index 0000000000000000000000000000000000000000..697cbaeb6b66dc70e9cf1b198fe5f2d63f299b9d GIT binary patch literal 8055 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 literal 0 HcmV?d00001 diff --git a/scripts/system/assets/images/ignore-target.svg b/scripts/system/assets/images/ignore-target.svg deleted file mode 100644 index ca6aca3a5a..0000000000 --- a/scripts/system/assets/images/ignore-target.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/system/assets/images/kick-target.png b/scripts/system/assets/images/kick-target.png new file mode 100644 index 0000000000000000000000000000000000000000..491d5d8dc76fc64e11b9dc89412840f9bc6714b7 GIT binary patch literal 6540 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 literal 0 HcmV?d00001 diff --git a/scripts/system/assets/images/kick-target.svg b/scripts/system/assets/images/kick-target.svg deleted file mode 100644 index e1ff64d272..0000000000 --- a/scripts/system/assets/images/kick-target.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/scripts/system/ignore.js b/scripts/system/ignore.js index cae4e14638..ea53efb2ce 100644 --- a/scripts/system/ignore.js +++ b/scripts/system/ignore.js @@ -64,7 +64,7 @@ function buttonClicked(){ button.clicked.connect(buttonClicked); function overlayURL() { - return Script.resolvePath("assets/images/" + (Users.canKick ? "kick-target.svg" : "ignore-target.svg")); + return Script.resolvePath("assets/images/" + (Users.canKick ? "kick-target.png" : "ignore-target.png")); } function updateOverlays() { @@ -104,7 +104,7 @@ function updateOverlays() { var newOverlay = Overlays.addOverlay("image3d", { url: overlayURL(), position: overlayPosition, - size: 0.4, + size: 1, scale: 0.4, color: { red: 255, green: 255, blue: 255}, alpha: 1, @@ -179,14 +179,8 @@ Controller.mousePressEvent.connect(function(event){ // But we dont' get mousePressEvents. var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); -var TRIGGER_GRAB_VALUE = 0.85; // From handControllerGrab/Pointer.js. Should refactor. -var TRIGGER_ON_VALUE = 0.4; -var TRIGGER_OFF_VALUE = 0.15; -var triggered = false; -var activeHand = Controller.Standard.RightHand; - -function controllerComputePickRay() { - var controllerPose = Controller.getPoseValue(activeHand); +function controllerComputePickRay(hand) { + var controllerPose = Controller.getPoseValue(hand); if (controllerPose.valid && triggered) { var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation), MyAvatar.position); @@ -196,31 +190,21 @@ function controllerComputePickRay() { } } -function makeTriggerHandler(hand) { +function makeClickHandler(hand) { return function (value) { if (isShowingOverlays) { - if (!triggered && (value > TRIGGER_GRAB_VALUE)) { // should we smooth? - triggered = true; - if (activeHand !== hand) { - // No switching while the other is already triggered, so no need to release. - activeHand = (activeHand === Controller.Standard.RightHand) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + var pickRay = controllerComputePickRay(hand); + if (pickRay) { + var overlayIntersection = Overlays.findRayIntersection(pickRay); + if (overlayIntersection.intersects) { + handleSelectedOverlay(overlayIntersection); } - - var pickRay = controllerComputePickRay(); - if (pickRay) { - var overlayIntersection = Overlays.findRayIntersection(pickRay); - if (overlayIntersection.intersects) { - handleSelectedOverlay(overlayIntersection); - } - } - } else if (triggered && (value < TRIGGER_OFF_VALUE)) { - triggered = false; } } }; } -triggerMapping.from(Controller.Standard.RT).peek().to(makeTriggerHandler(Controller.Standard.RightHand)); -triggerMapping.from(Controller.Standard.LT).peek().to(makeTriggerHandler(Controller.Standard.LeftHand)); +triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); +triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); triggerMapping.enable(); From 6d38301a3a00cb917033723ef74377d42a71c391 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 15:03:33 -0700 Subject: [PATCH 31/42] rename ignore script to mod.js --- scripts/system/{ignore.js => mod.js} | 46 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) rename scripts/system/{ignore.js => mod.js} (85%) diff --git a/scripts/system/ignore.js b/scripts/system/mod.js similarity index 85% rename from scripts/system/ignore.js rename to scripts/system/mod.js index ea53efb2ce..74888e7d12 100644 --- a/scripts/system/ignore.js +++ b/scripts/system/mod.js @@ -1,5 +1,5 @@ // -// ignore.js +// mod.js // scripts/system/ // // Created by Stephen Birarda on 07/11/2016 @@ -16,9 +16,9 @@ function buttonImageURL() { return Script.resolvePath("assets/images/tools/" + (Users.canKick ? 'kick.svg' : 'ignore.svg')); } -// setup the ignore button and add it to the toolbar +// setup the mod button and add it to the toolbar var button = toolbar.addButton({ - objectName: 'ignore', + objectName: 'mod', imageURL: buttonImageURL(), visible: true, buttonState: 1, @@ -33,18 +33,18 @@ Users.canKickChanged.connect(function(canKick){ }); var isShowingOverlays = false; -var ignoreOverlays = {}; +var modOverlays = {}; function removeOverlays() { // enumerate the overlays and remove them - var ignoreOverlayKeys = Object.keys(ignoreOverlays); + var modOverlayKeys = Object.keys(modOverlays); - for (i = 0; i < ignoreOverlayKeys.length; ++i) { - var avatarID = ignoreOverlayKeys[i]; - Overlays.deleteOverlay(ignoreOverlays[avatarID]); + for (i = 0; i < modOverlayKeys.length; ++i) { + var avatarID = modOverlayKeys[i]; + Overlays.deleteOverlay(modOverlays[avatarID]); } - ignoreOverlays = {}; + modOverlays = {}; } // handle clicks on the toolbar button @@ -93,9 +93,9 @@ function updateOverlays() { var overlayPosition = avatar.getJointPosition("Head"); overlayPosition.y += 0.45; - if (avatarID in ignoreOverlays) { + if (avatarID in modOverlays) { // keep the overlay above the current position of this avatar - Overlays.editOverlay(ignoreOverlays[avatarID], { + Overlays.editOverlay(modOverlays[avatarID], { position: overlayPosition, url: overlayURL() }); @@ -114,7 +114,7 @@ function updateOverlays() { }); // push this overlay to our array of overlays - ignoreOverlays[avatarID] = newOverlay; + modOverlays[avatarID] = newOverlay; } } } @@ -127,23 +127,23 @@ AvatarList.avatarRemovedEvent.connect(function(avatarID){ // we are currently showing overlays and an avatar just went away // first remove the rendered overlay - Overlays.deleteOverlay(ignoreOverlays[avatarID]); + Overlays.deleteOverlay(modOverlays[avatarID]); - // delete the saved ID of the overlay from our ignored overlays object - delete ignoreOverlays[avatarID]; + // delete the saved ID of the overlay from our mod overlays object + delete modOverlays[avatarID]; } }); function handleSelectedOverlay(clickedOverlay) { - // see this is one of our ignore overlays + // see this is one of our mod overlays - var ignoreOverlayKeys = Object.keys(ignoreOverlays) - for (i = 0; i < ignoreOverlayKeys.length; ++i) { - var avatarID = ignoreOverlayKeys[i]; - var ignoreOverlay = ignoreOverlays[avatarID]; + var modOverlayKeys = Object.keys(modOverlays) + for (i = 0; i < modOverlayKeys.length; ++i) { + var avatarID = modOverlayKeys[i]; + var modOverlay = modOverlays[avatarID]; - if (clickedOverlay.overlayID == ignoreOverlay) { - // matched to an overlay, ask for the matching avatar to be ignored + if (clickedOverlay.overlayID == modOverlay) { + // matched to an overlay, ask for the matching avatar to be kicked or ignored if (Users.canKick) { Users.kick(avatarID); } else { @@ -210,7 +210,7 @@ triggerMapping.enable(); // cleanup the toolbar button and overlays when script is stopped Script.scriptEnding.connect(function() { - toolbar.removeButton('ignore'); + toolbar.removeButton('mod'); removeOverlays(); triggerMapping.disable(); }); From 6e50e110027390d4821a64447d7b14a22e1be819 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 15:04:27 -0700 Subject: [PATCH 32/42] replace ignore in default scripts with mod --- scripts/defaultScripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 817d63582d..0efcd0c140 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -17,7 +17,7 @@ Script.load("system/goto.js"); Script.load("system/hmd.js"); Script.load("system/marketplace.js"); Script.load("system/edit.js"); -Script.load("system/ignore.js"); +Script.load("system/mod.js"); Script.load("system/selectAudioDevice.js"); Script.load("system/notifications.js"); Script.load("system/controllers/handControllerGrab.js"); From 760223a550021c511ea3e7baaafc4376c84c72eb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jul 2016 18:04:47 -0700 Subject: [PATCH 33/42] check for existing public key with lowercase username --- domain-server/src/DomainGatekeeper.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index eb907aace4..690c11e07f 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -453,11 +453,11 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node bool DomainGatekeeper::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr) { - // it's possible this user can be allowed to connect, but we need to check their username signature - QByteArray publicKeyArray = _userPublicKeys.value(username.toLower()); + auto lowerUsername = username.toLower(); + QByteArray publicKeyArray = _userPublicKeys.value(lowerUsername); - const QUuid& connectionToken = _connectionTokenHash.value(username.toLower()); + const QUuid& connectionToken = _connectionTokenHash.value(lowerUsername); if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { // if we do have a public key for the user, check for a signature match @@ -467,8 +467,8 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username, // first load up the public key into an RSA struct RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - QByteArray lowercaseUsername = username.toLower().toUtf8(); - QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QByteArray lowercaseUsernameUTF8 = lowerUsername.toUtf8(); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsernameUTF8.append(connectionToken.toRfc4122()), QCryptographicHash::Sha256); if (rsaPublicKey) { @@ -598,10 +598,7 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); QString username = extractUsernameFromPublicKeyRequest(requestReply); - if (jsonObject["status"].toString() == "success" && username != "") { - // figure out which user this is for - const QString PUBLIC_KEY_URL_REGEX_STRING = "api\\/v1\\/users\\/([A-Za-z0-9_\\.]+)\\/public_key"; - qDebug() << "Storing a public key for user" << username; + if (jsonObject["status"].toString() == "success" && !username.isEmpty()) { // pull the public key as a QByteArray from this response const QString JSON_DATA_KEY = "data"; const QString JSON_PUBLIC_KEY_KEY = "public_key"; From f02f6195975178290de3cfc5b92c8311cb2fee0d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jul 2016 10:21:17 -0700 Subject: [PATCH 34/42] use boolean from RTClick and LTClick --- scripts/system/mod.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/mod.js b/scripts/system/mod.js index 74888e7d12..f381ab3703 100644 --- a/scripts/system/mod.js +++ b/scripts/system/mod.js @@ -191,8 +191,8 @@ function controllerComputePickRay(hand) { } function makeClickHandler(hand) { - return function (value) { - if (isShowingOverlays) { + return function(clicked) { + if (clicked && isShowingOverlays) { var pickRay = controllerComputePickRay(hand); if (pickRay) { var overlayIntersection = Overlays.findRayIntersection(pickRay); From fa9199c419e237207628730c6be0cf8eceb0246b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jul 2016 10:25:36 -0700 Subject: [PATCH 35/42] use float for clicked value in mod.js --- scripts/system/mod.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/mod.js b/scripts/system/mod.js index f381ab3703..f60ad7b35c 100644 --- a/scripts/system/mod.js +++ b/scripts/system/mod.js @@ -192,7 +192,7 @@ function controllerComputePickRay(hand) { function makeClickHandler(hand) { return function(clicked) { - if (clicked && isShowingOverlays) { + if (clicked == 1.0 && isShowingOverlays) { var pickRay = controllerComputePickRay(hand); if (pickRay) { var overlayIntersection = Overlays.findRayIntersection(pickRay); From 6196f5e86f739d5587959b6b62af37f772bf5407 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jul 2016 12:04:28 -0700 Subject: [PATCH 36/42] switch back to SVGs, remove triggered for controller pose --- .../system/assets/images/ignore-target.png | Bin 8055 -> 0 bytes .../system/assets/images/ignore-target.svg | 53 ++++++++++++++++++ scripts/system/assets/images/kick-target.png | Bin 6540 -> 0 bytes scripts/system/assets/images/kick-target.svg | 33 +++++++++++ scripts/system/mod.js | 4 +- 5 files changed, 88 insertions(+), 2 deletions(-) delete mode 100644 scripts/system/assets/images/ignore-target.png create mode 100644 scripts/system/assets/images/ignore-target.svg delete mode 100644 scripts/system/assets/images/kick-target.png create mode 100644 scripts/system/assets/images/kick-target.svg diff --git a/scripts/system/assets/images/ignore-target.png b/scripts/system/assets/images/ignore-target.png deleted file mode 100644 index 697cbaeb6b66dc70e9cf1b198fe5f2d63f299b9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8055 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 diff --git a/scripts/system/assets/images/ignore-target.svg b/scripts/system/assets/images/ignore-target.svg new file mode 100644 index 0000000000..3d685139ec --- /dev/null +++ b/scripts/system/assets/images/ignore-target.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/assets/images/kick-target.png b/scripts/system/assets/images/kick-target.png deleted file mode 100644 index 491d5d8dc76fc64e11b9dc89412840f9bc6714b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6540 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 diff --git a/scripts/system/assets/images/kick-target.svg b/scripts/system/assets/images/kick-target.svg new file mode 100644 index 0000000000..21cb3a5462 --- /dev/null +++ b/scripts/system/assets/images/kick-target.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + diff --git a/scripts/system/mod.js b/scripts/system/mod.js index f60ad7b35c..035d7726a1 100644 --- a/scripts/system/mod.js +++ b/scripts/system/mod.js @@ -64,7 +64,7 @@ function buttonClicked(){ button.clicked.connect(buttonClicked); function overlayURL() { - return Script.resolvePath("assets/images/" + (Users.canKick ? "kick-target.png" : "ignore-target.png")); + return Script.resolvePath("assets") + "/images/" + (Users.canKick ? "kick-target.svg" : "ignore-target.svg"); } function updateOverlays() { @@ -181,7 +181,7 @@ var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); function controllerComputePickRay(hand) { var controllerPose = Controller.getPoseValue(hand); - if (controllerPose.valid && triggered) { + if (controllerPose.valid) { var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation), MyAvatar.position); // This gets point direction right, but if you want general quaternion it would be more complicated: From a1220b87f13f57058b07bced6afca403a86634b8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 29 Jul 2016 15:53:45 -0700 Subject: [PATCH 37/42] set key ID for verified user in right place --- domain-server/src/DomainGatekeeper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 690c11e07f..8f8c8e001c 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -147,7 +147,6 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin #endif } } else { - userPerms.setID(verifiedUsername); if (_server->_settingsManager.havePermissionsForName(verifiedUsername)) { userPerms = _server->_settingsManager.getPermissionsForName(verifiedUsername); #ifdef WANT_DEBUG @@ -161,7 +160,6 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin qDebug() << "| user-permissions: specific IP matches, so:" << userPerms; #endif } else { - // they are logged into metaverse, but we don't have specific permissions for them. userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn); #ifdef WANT_DEBUG @@ -208,6 +206,7 @@ NodePermissions DomainGatekeeper::setPermissionsForUser(bool isLocalUser, QStrin } } + userPerms.setID(verifiedUsername); userPerms.setVerifiedUserName(verifiedUsername); } From 79a243b1713859ee973262e00a3d4b56ae0ec8f7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Aug 2016 16:19:38 -0700 Subject: [PATCH 38/42] Clean up progress.js --- scripts/system/progress.js | 79 ++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index faf8d1bd38..821fc872b7 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -13,6 +13,11 @@ (function() { + function debug() { + return; + print.apply(null, arguments); + } + var rawProgress = 100, // % raw value. displayProgress = 100, // % smoothed value to display. DISPLAY_PROGRESS_MINOR_MAXIMUM = 8, // % displayed progress bar goes up to while 0% raw progress. @@ -39,7 +44,6 @@ background2D = {}, bar2D = {}, SCALE_2D = 0.35, // Scale the SVGs for 2D display. - //SCALE_2D = 1.0, // Scale the SVGs for 2D display. background3D = {}, bar3D = {}, PROGRESS_3D_DIRECTION = 0.0, // Degrees from avatar orientation. @@ -96,44 +100,58 @@ }); } function resetProgress() { - wasActive = true; + isDownloading = true; bestRawProgress = 0; rawProgress = 0; - cooldown = 1000; + initialDelayCooldown = INITIAL_DELAY_COOLDOWN_TIME; displayProgress = 0; } Window.domainChanged.connect(function() { - hasShownOnThisDomain = false; resetProgress(); }); - var hasShownOnThisDomain = false; - + // Max seen since downloads started. This is reset when all downloads have completed. var maxSeen = 0; + + // Progress is defined as: (pending_downloads + active_downloads) / max_seen + // We keep track of both the current progress (rawProgress) and the + // best progress we've seen (bestRawProgress). As you are downloading, you may + // encounter new assets that require downloads, increasing the number of + // pending downloads and thus decreasing your overall progress. var bestRawProgress = 0; - var wasActive = false; - var cooldown = 1000; + + // True if we have known active downloads + var isDownloading = false; + + // Entities are streamed to users, so you don't receive them all at once; instead, you + // receive them over a period of time. In many cases we end up in a situation where + // + // The initial delay cooldown keeps us from tracking progress before the allotted time + // has passed. + var INITIAL_DELAY_COOLDOWN_TIME = 1000; + var initialDelayCooldown = 0; function onDownloadInfoChanged(info) { var i; - print("PROGRESS: Download info changed ", info.downloading.length, info.pending, maxSeen); + debug("PROGRESS: Download info changed ", info.downloading.length, info.pending, maxSeen); + // Update raw progress value if (info.downloading.length + info.pending === 0) { - wasActive = false; + isDownloading = false; rawProgress = 100; bestRawProgress = 100; - cooldown = 0; + initialDelayCooldown = INITIAL_DELAY_COOLDOWN_TIME; } else { var count = info.downloading.length + info.pending; - if (!wasActive) { + if (!isDownloading) { resetProgress(); maxSeen = count; } if (count > maxSeen) { maxSeen = count; } - if (cooldown <= 0) { + if (initialDelayCooldown <= 0) { rawProgress = ((maxSeen - count) / maxSeen) * 100; if (rawProgress > bestRawProgress) { @@ -141,7 +159,7 @@ } } } - print("PROGRESS:", rawProgress, bestRawProgress, maxSeen); + debug("PROGRESS:", rawProgress, bestRawProgress, maxSeen); } function createOverlays() { @@ -214,7 +232,7 @@ var worldOverlayOn = false; var currentOrientation = null; function update() { - cooldown -= 30; + initialDelayCooldown -= 30; var viewport, eyePosition, avatarOrientation; @@ -231,7 +249,6 @@ displayProgress += diff * 0.05; } } - //print('PROGRESS:', displayProgress); // Update state if (!visible) { // Not visible because no recent downloads @@ -328,16 +345,7 @@ windowHeight = viewport.y; var yOffset = HMD.active ? -300 : -10; - yOffset += yAdjust; - // if (hmdActive) { - // if (true) { //hasShownOnThisDomain) { - // yOffset = -100; - // SCALE_2D = 1.0/3; - // } else { - // yOffset = -300; - // SCALE_2D = 2.0/3; - // } - // } + background2D.width = SCALE_2D * BACKGROUND_WIDTH; background2D.height = SCALE_2D * BACKGROUND_HEIGHT; bar2D.width = SCALE_2D * BAR_WIDTH; @@ -354,9 +362,6 @@ }); } - function setProgressBar(progress) { - } - function setUp() { background2D.width = SCALE_2D * BACKGROUND_WIDTH; background2D.height = SCALE_2D * BACKGROUND_HEIGHT; @@ -384,25 +389,9 @@ deleteOverlays(); } - var yAdjust = 0; - function keyPress(event) { - print("Key event: ", event.text); - if (event.text == '.') { - yAdjust -= 10; - updateProgressBarLocation(); - } else if (event.text == ',') { - yAdjust += 10; - updateProgressBarLocation(); - } else if (event.text == 'SPACE') { - worldOverlayOn = !worldOverlayOn; - } - } - setUp(); GlobalServices.downloadInfoChanged.connect(onDownloadInfoChanged); GlobalServices.updateDownloadInfo(); - //Script.update.connect(update); Script.setInterval(update, 1000/60); Script.scriptEnding.connect(tearDown); - Controller.keyPressEvent.connect(keyPress); }()); From 1f2e34d59b85c3a265f7955401c112f396914888 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Aug 2016 16:29:40 -0700 Subject: [PATCH 39/42] Remove 3d overlay from progress.js --- scripts/system/progress.js | 155 +++++-------------------------------- 1 file changed, 21 insertions(+), 134 deletions(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 821fc872b7..67ef1e203c 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -38,31 +38,11 @@ BACKGROUND_WIDTH = 520, BACKGROUND_HEIGHT = 50, BACKGROUND_URL = Script.resolvePath("assets/images/progress-bar-background.svg"), - use3DOverlay = false, windowWidth = 0, windowHeight = 0, background2D = {}, bar2D = {}, - SCALE_2D = 0.35, // Scale the SVGs for 2D display. - background3D = {}, - bar3D = {}, - PROGRESS_3D_DIRECTION = 0.0, // Degrees from avatar orientation. - PROGRESS_3D_DISTANCE = 0.602, // Horizontal distance from avatar position. - PROGRESS_3D_ELEVATION = -0.8, // Height of top middle of top notification relative to avatar eyes. - PROGRESS_3D_ELEVATION = -0.2, // Height of top middle of top notification relative to avatar eyes. - PROGRESS_3D_YAW = 0.0, // Degrees relative to notifications direction. - PROGRESS_3D_PITCH = -0.0, // Degrees from vertical. - SCALE_3D = 0.0004, // Scale the bar SVG for 3D display. - BACKGROUND_3D_SIZE = { - x: 0.76, - y: 0.08 - }, // Match up with the 3D background with those of notifications.js notices. - BACKGROUND_3D_COLOR = { - red: 2, - green: 2, - blue: 2 - }, - BACKGROUND_3D_ALPHA = 1.0; + SCALE_2D = 0.35; // Scale the SVGs for 2D display. function fade() { @@ -83,32 +63,21 @@ visible = false; } - if (use3DOverlay) { - Overlays.editOverlay(background3D.overlay, { - alpha: alpha, - visible: visible - }); - } else { - Overlays.editOverlay(background2D.overlay, { - alpha: alpha, - visible: visible - }); - } - Overlays.editOverlay(use3DOverlay ? bar3D.overlay : bar2D.overlay, { + Overlays.editOverlay(background2D.overlay, { + alpha: alpha, + visible: visible + }); + Overlays.editOverlay(bar2D.overlay, { alpha: alpha, visible: visible }); } - function resetProgress() { - isDownloading = true; - bestRawProgress = 0; - rawProgress = 0; - initialDelayCooldown = INITIAL_DELAY_COOLDOWN_TIME; - displayProgress = 0; - } Window.domainChanged.connect(function() { - resetProgress(); + isDownloading = false; + bestRawProgress = 100; + rawProgress = 100; + displayProgress = 100; }); // Max seen since downloads started. This is reset when all downloads have completed. @@ -145,7 +114,11 @@ } else { var count = info.downloading.length + info.pending; if (!isDownloading) { - resetProgress(); + isDownloading = true; + bestRawProgress = 0; + rawProgress = 0; + initialDelayCooldown = INITIAL_DELAY_COOLDOWN_TIME; + displayProgress = 0; maxSeen = count; } if (count > maxSeen) { @@ -163,41 +136,6 @@ } function createOverlays() { - background3D.overlay = Overlays.addOverlay("image3d", { - url: BACKGROUND_URL, - subImage: { - x: 0, - y: 0, - width: BACKGROUND_WIDTH, - height: BACKGROUND_HEIGHT - }, - scale: SCALE_3D * BACKGROUND_WIDTH, - isFacingAvatar: false, - visible: false, - alpha: 1.0, - ignoreRayIntersection: true, - emissive: true, - isFacingAvatar: true, - drawInFront: true - }); - bar3D.overlay = Overlays.addOverlay("image3d", { - url: BAR_URL, - subImage: { - x: 0, - y: 0, - width: BAR_WIDTH, - height: BAR_HEIGHT - }, - scale: SCALE_3D * BAR_WIDTH, - isFacingAvatar: false, - visible: false, - alpha: 1.0, - ignoreRayIntersection: true, - emissive: true, - isFacingAvatar: true, - drawInFront: true - }); - background2D.overlay = Overlays.addOverlay("image", { imageURL: BACKGROUND_URL, width: background2D.width, @@ -221,15 +159,11 @@ } function deleteOverlays() { - Overlays.deleteOverlay(background3D.overlay); - Overlays.deleteOverlay(bar3D.overlay); - Overlays.deleteOverlay(background2D.overlay); Overlays.deleteOverlay(bar2D.overlay); } var b = 0; - var worldOverlayOn = false; var currentOrientation = null; function update() { initialDelayCooldown -= 30; @@ -237,10 +171,6 @@ eyePosition, avatarOrientation; - if (use3DOverlay !== worldOverlayOn) { - use3DOverlay = !use3DOverlay; - } - if (displayProgress < rawProgress) { var diff = rawProgress - displayProgress; if (diff < 0.5) { @@ -284,18 +214,10 @@ } } - if (use3DOverlay) { - Overlays.editOverlay(background2D.overlay, { visible: false }); - Overlays.editOverlay(bar2D.overlay, { visible: false }); - } else { - Overlays.editOverlay(background3D.overlay, { visible: false }); - Overlays.editOverlay(bar3D.overlay, { visible: false }); - } - if (visible) { // Update progress bar - Overlays.editOverlay(use3DOverlay ? bar3D.overlay : bar2D.overlay, { + Overlays.editOverlay(bar2D.overlay, { visible: true, subImage: { x: BAR_WIDTH * (1 - displayProgress / 100), @@ -305,36 +227,15 @@ }, }); - Overlays.editOverlay(use3DOverlay ? background3D.overlay : background2D.overlay, { + Overlays.editOverlay(background2D.overlay, { visible: true, }); - // Update position - if (use3DOverlay) { - print("HERE"); - // Update 3D overlays to maintain positions relative to avatar - eyePosition = MyAvatar.getDefaultEyePosition(); - avatarOrientation = Camera.orientation; + // Update 2D overlays to maintain positions at bottom middle of window + viewport = Controller.getViewportDimensions(); - currentOrientation = Quat.slerp(currentOrientation, avatarOrientation, 0.10); - avatarOrientation = currentOrientation; - - Overlays.editOverlay(background3D.overlay, { - position: Vec3.sum(eyePosition, Vec3.multiplyQbyV(avatarOrientation, background3D.offset)), - //rotation: Quat.multiply(avatarOrientation, background3D.orientation) - }); - Overlays.editOverlay(bar3D.overlay, { - position: Vec3.sum(eyePosition, Vec3.multiplyQbyV(avatarOrientation, bar3D.offset)), - //rotation: Quat.multiply(avatarOrientation, bar3D.orientation) - }); - - } else { - // Update 2D overlays to maintain positions at bottom middle of window - viewport = Controller.getViewportDimensions(); - - if (viewport.x !== windowWidth || viewport.y !== windowHeight) { - updateProgressBarLocation(); - } + if (viewport.x !== windowWidth || viewport.y !== windowHeight) { + updateProgressBarLocation(); } } } @@ -368,20 +269,6 @@ bar2D.width = SCALE_2D * BAR_WIDTH; bar2D.height = SCALE_2D * BAR_HEIGHT; - background3D.offset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, PROGRESS_3D_DIRECTION, 0), { - x: 0, - y: 0, - z: -PROGRESS_3D_DISTANCE - }); - background3D.offset.y += PROGRESS_3D_ELEVATION; - background3D.orientation = Quat.fromPitchYawRollDegrees(PROGRESS_3D_PITCH, PROGRESS_3D_DIRECTION + PROGRESS_3D_YAW, 0); - bar3D.offset = Vec3.sum(background3D.offset, { - x: 0, - y: 0, - z: 0.001 - }); // Just in front of background - bar3D.orientation = background3D.orientation; - createOverlays(); } From 5d3e125a0668d57a34bae8f35fb83303d6a2b21a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Aug 2016 16:32:41 -0700 Subject: [PATCH 40/42] make failed geomtetry request not hold physics --- .../src/RenderableModelEntityItem.cpp | 10 ++++++++++ .../entities-renderer/src/RenderableModelEntityItem.h | 2 ++ .../src/model-networking/ModelCache.cpp | 2 ++ .../model-networking/src/model-networking/ModelCache.h | 3 +++ libraries/render-utils/src/Model.cpp | 7 ++++++- libraries/render-utils/src/Model.h | 8 +++++++- 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4e8ecf3054..564a58708f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -916,6 +916,16 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const { return false; } +bool RenderableModelEntityItem::shouldBePhysical() const { + // If we have a model, make sure it hasn't failed to download. + // If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready. + if (_model && _model->didGeometryRequestFail()) { + return false; + } else { + return ModelEntityItem::shouldBePhysical(); + } +} + glm::quat RenderableModelEntityItem::getAbsoluteJointRotationInObjectFrame(int index) const { if (_model) { glm::quat result; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 339c907532..f487e79880 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -65,6 +65,8 @@ public: virtual bool contains(const glm::vec3& point) const override; + virtual bool shouldBePhysical() const override; + // these are in the frame of this object (model space) virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 26798070a6..c4b2a6dd22 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -403,6 +403,8 @@ void GeometryResourceWatcher::setResource(GeometryResource::Pointer resource) { void GeometryResourceWatcher::resourceFinished(bool success) { if (success) { _geometryRef = std::make_shared(*_resource); + } else { + emit resourceFailed(); } } diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 4a0a921a04..62037d67bc 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -111,6 +111,9 @@ public: QUrl getURL() const { return (bool)_resource ? _resource->getURL() : QUrl(); } +signals: + void resourceFailed(); + private: void startWatching(); void stopWatching(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b04a1d8023..581bd285e2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -102,13 +102,17 @@ Model::Model(RigPointer rig, QObject* parent) : _calculatedMeshTrianglesValid(false), _meshGroupsKnown(false), _isWireframe(false), - _rig(rig) { + _rig(rig) +{ // we may have been created in the network thread, but we live in the main thread if (_viewState) { moveToThread(_viewState->getMainThread()); } setSnapModelToRegistrationPoint(true, glm::vec3(0.5f)); + + // handle download failure reported by the GeometryResourceWatcher + connect(&_renderWatcher, &GeometryResourceWatcher::resourceFailed, this, &Model::handleGeometryResourceFailure); } Model::~Model() { @@ -818,6 +822,7 @@ void Model::setURL(const QUrl& url) { _needsReload = true; _needsUpdateTextures = true; _meshGroupsKnown = false; + _geometryRequestFailed = false; invalidCalculatedMeshBoxes(); deleteGeometry(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 98e50c66f4..b95c0318b4 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -147,8 +147,9 @@ public: Q_INVOKABLE void setCollisionModelURL(const QUrl& url); const QUrl& getCollisionURL() const { return _collisionUrl; } - bool isActive() const { return isLoaded(); } + + bool didGeometryRequestFail() const { return _geometryRequestFailed; } bool convexHullContains(glm::vec3 point); @@ -392,6 +393,11 @@ protected: RigPointer _rig; uint32_t _deleteGeometryCounter { 0 }; + + bool _geometryRequestFailed { false }; + +private slots: + void handleGeometryResourceFailure() { _geometryRequestFailed = true; } }; Q_DECLARE_METATYPE(ModelPointer) From adbd9ff85428bc99fcb28cc8db6bf190b0f0eb4e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Aug 2016 16:34:57 -0700 Subject: [PATCH 41/42] Add constants for progress bar offset --- scripts/system/progress.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 67ef1e203c..7c1c475e99 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -34,6 +34,8 @@ visible = false, BAR_WIDTH = 480, // Dimension of SVG in pixels of visible portion (half) of the bar. BAR_HEIGHT = 10, + BAR_Y_OFFSET_2D = -10, // Offset of progress bar while in desktop mode + BAR_Y_OFFSET_HMD = -300, // Offset of progress bar while in HMD BAR_URL = Script.resolvePath("assets/images/progress-bar.svg"), BACKGROUND_WIDTH = 520, BACKGROUND_HEIGHT = 50, @@ -245,7 +247,7 @@ windowWidth = viewport.x; windowHeight = viewport.y; - var yOffset = HMD.active ? -300 : -10; + var yOffset = HMD.active ? BAR_Y_OFFSET_HMD : BAR_Y_OFFSET_2D; background2D.width = SCALE_2D * BACKGROUND_WIDTH; background2D.height = SCALE_2D * BACKGROUND_HEIGHT; From 3c30743d0dcc8f3e1d7c538cdf86f223914d8686 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 2 Aug 2016 16:48:39 -0700 Subject: [PATCH 42/42] Remove url change debug info for WebView --- interface/resources/qml/controls-uit/WebView.qml | 1 - interface/resources/qml/controls/WebView.qml | 1 - 2 files changed, 2 deletions(-) diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 4c165fc587..b599e29fe0 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -35,7 +35,6 @@ WebEngineView { } onUrlChanged: { - console.log("Url changed to " + url); var originalUrl = url.toString(); newUrl = urlHandler.fixupUrl(originalUrl).toString(); if (newUrl !== originalUrl) { diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 2f94740fe6..bba91c64f6 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -26,7 +26,6 @@ WebEngineView { } onUrlChanged: { - console.log("Url changed to " + url); var originalUrl = url.toString(); newUrl = urlHandler.fixupUrl(originalUrl).toString(); if (newUrl !== originalUrl) {