diff --git a/domain-server/resources/web/images/checkmark.svg b/domain-server/resources/web/images/checkmark.svg
new file mode 100644
index 0000000000..f4403921ee
--- /dev/null
+++ b/domain-server/resources/web/images/checkmark.svg
@@ -0,0 +1,25 @@
+
diff --git a/domain-server/resources/web/settings/js/sha256.js b/domain-server/resources/web/js/sha256.js
similarity index 100%
rename from domain-server/resources/web/settings/js/sha256.js
rename to domain-server/resources/web/js/sha256.js
diff --git a/domain-server/resources/web/js/shared.js b/domain-server/resources/web/js/shared.js
index 4e2392f0bb..2382a4ce2e 100644
--- a/domain-server/resources/web/js/shared.js
+++ b/domain-server/resources/web/js/shared.js
@@ -1,6 +1,5 @@
Settings = {
showAdvanced: false,
- METAVERSE_URL: 'https://staging.highfidelity.com',
ADVANCED_CLASS: 'advanced-setting',
DEPRECATED_CLASS: 'deprecated-setting',
TRIGGER_CHANGE_CLASS: 'trigger-change',
@@ -44,6 +43,11 @@ Settings = {
DATA_ROW_INDEX: 'data-row-index'
};
+var URLs = {
+ METAVERSE_URL: 'https://metaverse.highfidelity.com',
+ PLACE_URL: 'https://hifi.place',
+};
+
Strings = {
LOADING_SETTINGS_ERROR: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
@@ -79,6 +83,9 @@ Strings = {
ADD_PLACE_NO_PLACES_BUTTON: "Create new place",
ADD_PLACE_UNABLE_TO_LOAD_ERROR: "We were unable to load your place names. Please try again later.",
ADD_PLACE_LOADING_DIALOG: "Loading your places...",
+
+ ADD_PLACE_NOT_CONNECTED_TITLE: "Access token required",
+ ADD_PLACE_NOT_CONNECTED_MESSAGE: "You must have an access token to query your High Fidelity places.
Please follow the instructions on the settings page to add an access token.",
};
var DOMAIN_ID_TYPE_NONE_OR_UNKNOWN = 0;
@@ -154,6 +161,8 @@ function chooseFromHighFidelityPlaces(accessToken, forcePathTo, onSuccessfullyAd
modal_body = $('
@@ -41,6 +44,10 @@
+
+
-
-
diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js
index 26c457abf1..e1bb914956 100644
--- a/domain-server/resources/web/settings/js/settings.js
+++ b/domain-server/resources/web/settings/js/settings.js
@@ -288,7 +288,11 @@ $(document).ready(function(){
$('#' + Settings.FORM_ID).on('click', '#' + Settings.CONNECT_ACCOUNT_BTN_ID, function(e){
$(this).blur();
- prepareAccessTokenPrompt();
+ prepareAccessTokenPrompt(function(accessToken) {
+ // we have an access token - set the access token input with this and save settings
+ $(Settings.ACCESS_TOKEN_SELECTOR).val(accessToken).change();
+ saveSettings();
+ });
});
var panelsSource = $('#panels-template').html()
@@ -323,6 +327,29 @@ $(document).ready(function(){
});
});
+function getShareName(callback) {
+ getDomainFromAPI(function(data){
+ // check if we have owner_places (for a real domain) or a name (for a temporary domain)
+ if (data && data.status == "success") {
+ var shareName;
+ if (data.domain.default_place_name) {
+ shareName = data.domain.default_place_name;
+ } else if (data.domain.name) {
+ shareName = data.domain.name;
+ } else if (data.domain.network_address) {
+ shareName = data.domain.network_address;
+ if (data.domain.network_port !== 40102) {
+ shareName += ':' + data.domain.network_port;
+ }
+ }
+
+ callback(true, shareName);
+ } else {
+ callback(false);
+ }
+ })
+}
+
function handleAction() {
// check if we were passed an action to handle
var action = qs["action"];
@@ -331,16 +358,8 @@ function handleAction() {
// figure out if we already have a stored domain ID
if (Settings.data.values.metaverse.id.length > 0) {
// we need to ask the API what a shareable name for this domain is
- getDomainFromAPI(function(data){
- // check if we have owner_places (for a real domain) or a name (for a temporary domain)
- if (data && data.status == "success") {
- var shareName;
- if (data.domain.owner_places) {
- shareName = data.domain.owner_places[0].name
- } else if (data.domain.name) {
- shareName = data.domain.name;
- }
-
+ getShareName(function(success, shareName){
+ if (success) {
var shareLink = "hifi://" + shareName;
console.log(shareLink);
@@ -438,7 +457,7 @@ function setupHFAccountButton() {
buttonSetting.button_label = "Connect High Fidelity Account";
buttonSetting.html_id = Settings.CONNECT_ACCOUNT_BTN_ID;
- buttonSetting.href = Settings.METAVERSE_URL + "/user/tokens/new?for_domain_server=true";
+ buttonSetting.href = URLs.METAVERSE_URL + "/user/tokens/new?for_domain_server=true";
// since we do not have an access token we change hide domain ID and auto networking settings
// without an access token niether of them can do anything
@@ -471,57 +490,6 @@ function disonnectHighFidelityAccount() {
});
}
-function prepareAccessTokenPrompt() {
- swal({
- title: "Connect Account",
- type: "input",
- text: "Paste your created access token here." +
- "If you did not successfully create an access token click cancel below and attempt to connect your account again.",
- showCancelButton: true,
- closeOnConfirm: false,
- html: true
- }, function(inputValue){
- if (inputValue === false) return false;
-
- if (inputValue === "") {
- swal.showInputError("Please paste your access token in the input field.")
- return false
- }
-
- // we have an input value - set the access token input with this and save settings
- $(Settings.ACCESS_TOKEN_SELECTOR).val(inputValue).change();
-
- console.log("Prepping access token prompt");
-
- swal.close();
- saveSettings();
- });
-}
-
-function showDomainIDChoiceAlert() {
- swal({
- title: 'Domain ID',
- type: 'info',
- text: "You do not currently have a domain ID." +
- "This is required to point place names at your domain and to use automatic networking." +
- "Would you like to create a domain ID via the Metaverse API?",
- showCancelButton: true,
- confirmButtonText: "Create new domain ID",
- cancelButtonText: "Skip",
- closeOnConfirm: false,
- html: true
- }, function(isConfirm){
- if (isConfirm) {
- // show the swal to create a new domain via API
- showDomainCreationAlert(true);
- } else {
- // user cancelled, close this swal and save the access token we got
- swal.close();
- saveSettings();
- }
- });
-}
-
function showSpinnerAlert(title) {
swal({
title: title,
@@ -557,12 +525,10 @@ function showDomainCreationAlert(justConnected) {
});
}
-//function createDomainID()
-
function createNewDomainID(label, justConnected) {
// get the JSON object ready that we'll use to create a new domain
var domainJSON = {
- "label": label
+ "label": label
//"access_token": $(Settings.ACCESS_TOKEN_SELECTOR).val()
}
@@ -661,7 +627,7 @@ function setupDomainLabelSetting() {
if (!domainIDIsSet() || !accessTokenIsSet()) {
$(".panel#label").hide();
return;
- }
+ }
var html = "
"
html += " Edit";
@@ -779,8 +745,8 @@ function setupDomainNetworkingSettings() {
form = $(form);
form.find('#edit-network-address-port').click(function(ev) {
- ev.preventDefault();
-
+ ev.preventDefault();
+
var address = DomainInfo.network_address === null ? '' : DomainInfo.network_address;
var port = DomainInfo.network_port === null ? '' : DomainInfo.network_port;
var modal_body = "
";
@@ -887,7 +853,7 @@ function setupPlacesTable() {
label: 'Places',
html_id: Settings.PLACES_TABLE_ID,
help: "The following places currently point to this domain.To point places to this domain, "
- + " go to the My Places "
+ + " go to the My Places "
+ "page in your High Fidelity Metaverse account.",
read_only: true,
can_add_new_rows: false,
@@ -1001,16 +967,6 @@ function placeTableRowForPlaceObject(place) {
return placeTableRow(place.name, placePathOrIndex, false, place.id);
}
-function getDomainFromAPI2(callback) {
- // we only need to do this if we have a current domain ID
- var domainID = Settings.data.values.metaverse.id;
- if (domainID.length > 0) {
- var domainURL = Settings.METAVERSE_URL + "/api/v1/domains/" + domainID;
-
- $.getJSON(domainURL, callback).fail(callback);
- }
-}
-
function getDomainFromAPI(callback) {
var domainID = Settings.data.values.metaverse.id;
$.ajax({
@@ -1093,22 +1049,6 @@ function showDomainSettingsModal(clickedButton) {
})
}
-function sendCreateDomainRequest(onSuccess, onError) {
- $.ajax({
- url: '/api/domains',
- type: 'POST',
- data: { label: "" },
- success: function(data) {
- //if (data.status === 'success') {
- onSuccess(data.domain_id);
- //} else {
- //onError();
- //}
- },
- error: onError
- });
-}
-
function editHighFidelityPlace(placeID, name, path) {
var dialog;
@@ -1237,7 +1177,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
modal_buttons["success"] = {
label: 'Create new domain',
callback: function() {
- window.open(Settings.METAVERSE_URL + "/user/domains", '_blank');
+ window.open(URLs.METAVERSE_URL + "/user/domains", '_blank');
}
}
modal_body = "
You do not have any domains in your High Fidelity account." +
@@ -1284,7 +1224,7 @@ function createTemporaryDomain() {
showSpinnerAlert('Creating temporary place name');
// make a get request to get a temporary domain
- $.post(Settings.METAVERSE_URL + '/api/v1/domains/temporary', function(data){
+ $.post(URLs.METAVERSE_URL + '/api/v1/domains/temporary', function(data){
if (data.status == "success") {
var domain = data.data.domain;
@@ -1311,24 +1251,6 @@ function createTemporaryDomain() {
});
}
-function waitForDomainServerBackUp(callback) {
- function checkForDomainUp() {
- $.ajax('', {
- success: function() {
- console.log("Domain is back up");
- callback();
- },
- error: function() {
- setTimeout(checkForDomainUp, 50);
- console.log("Fail");
- }
- });
- }
-
- setTimeout(checkForDomainUp, 10);
-
-}
-
function reloadSettings(callback) {
$.getJSON('/settings.json', function(data){
_.extend(data, viewHelpers)
@@ -1354,6 +1276,26 @@ function reloadSettings(callback) {
if (Settings.data.values.metaverse.id.length > 0) {
// now, ask the API for what places, if any, point to this domain
reloadDomainInfo();
+
+ // we need to ask the API what a shareable name for this domain is
+ getShareName(function(success, shareName) {
+ if (success) {
+ var shareLink = "https://hifi.place/" + shareName;
+ $('#visit-domain-link').attr("href", shareLink).show();
+ }
+ });
+ }
+
+ if (Settings.data.values.wizard.cloud_domain) {
+ $('#manage-cloud-domains-link').show();
+
+ var cloudWizardExit = qs["cloud-wizard-exit"];
+ if (cloudWizardExit != undefined) {
+ $('#cloud-domains-alert').show();
+ $('#cloud-domains-alert .glyphicon').on('click', function() {
+ $('#cloud-domains-alert').remove();
+ });
+ }
}
// setup any bootstrap switches
diff --git a/domain-server/resources/web/wizard/css/style.css b/domain-server/resources/web/wizard/css/style.css
new file mode 100644
index 0000000000..dcb34ef887
--- /dev/null
+++ b/domain-server/resources/web/wizard/css/style.css
@@ -0,0 +1,89 @@
+label {
+ font-style: normal;
+ font-weight: normal;
+ line-height: 24px;
+ font-size: 16px;
+
+ color: #373A3C;
+}
+
+.step-title {
+ margin-bottom: 20px;
+ line-height: 26px;
+ font-size: 24px;
+
+ color: #373A3C;
+}
+
+.step-description {
+ line-height: 24px;
+ font-size: 16px;
+
+ color: #818A91;
+}
+
+.step-info {
+ font-style: normal;
+ font-weight: normal;
+ line-height: 24px;
+ font-size: 16px;
+
+ color: #373A3C;
+}
+
+#admin-row {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+#connect-question {
+ margin-top: 10px;
+}
+
+#connect-account-btn {
+ margin-top: 30px;
+ margin-bottom: 205px;
+}
+
+#place-name-group {
+ margin-top: 42px;
+ margin-bottom: 140px;
+ display: inline-block;
+}
+
+#place-name-link {
+ line-height: 38px;
+ font-size: 32px;
+
+ display: inline-block;
+
+ color: #373A3C;
+}
+
+#place-name-edit {
+ text-align: right;
+}
+
+#change-place-name {
+ line-height: 24px;
+ font-size: 18px;
+}
+
+#rez-options-row {
+ margin-bottom: 60px;
+}
+
+#verify-password-row {
+ margin-bottom: 33px;
+}
+
+#checkmark-image {
+ margin-top: 66px;
+ margin-bottom: 59px;
+ width: 169px;
+ height: 169px;
+}
+
+#visit-domain-row {
+ margin-bottom: 68px;
+}
diff --git a/domain-server/resources/web/wizard/header.html b/domain-server/resources/web/wizard/header.html
new file mode 100644
index 0000000000..2b829f9837
--- /dev/null
+++ b/domain-server/resources/web/wizard/header.html
@@ -0,0 +1,30 @@
+
+
+
+ domain-server
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/domain-server/resources/web/wizard/index.shtml b/domain-server/resources/web/wizard/index.shtml
new file mode 100644
index 0000000000..7205e3fea2
--- /dev/null
+++ b/domain-server/resources/web/wizard/index.shtml
@@ -0,0 +1,229 @@
+
+
+
+
+
+ By connecting you High Fidelity Account you will be granting access to your account information.
+
+
+ Place names are similar to web addresses. Users who want to visit your domain can
+ enter its Place Name in High Fidelity's Interface. You can choose a Place Name for your domain.
+ People can also use your domain's IP address (shown below) to visit your High Fidelity domain.
+
+
Localhost has been granted administrator privileges to this domain. (Localhost is anyuser on the same machine as the High Fidelity Server)
+
+
+
+ Add your High Fidelity username and any other usernames to grant administrator privileges.
+
+
+
+
+ separate by commas (user1, user2,..)
+
+
+
+
+
+ Grant basic permissions to other users. You can change these later.
+
+
+
+
+
+
+ Who can connect to your domain?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Who can rez items in your domain?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Your server settings are currently accessible without a username and password.
+ Adding credentials will ensure that only authorized users have access to modify the settings.
+
+
+
+
+
+
Create a username and password to secure the access to your domain server settings.
+
+
+
Username
+
+
+ This does not have to be your High Fidelity username
+
+
+
+
Enter password
+
+
+ This should not be the same as your High Fidelity password
+
+
+
+
Re-enter password
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Congratulations! You have successfully setup and configured your cloud hosted domain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/domain-server/resources/web/wizard/js/wizard.js b/domain-server/resources/web/wizard/js/wizard.js
new file mode 100644
index 0000000000..c14f0cddb2
--- /dev/null
+++ b/domain-server/resources/web/wizard/js/wizard.js
@@ -0,0 +1,468 @@
+var Metaverse = {
+ accessToken: null
+}
+
+$(document).ready(function(){
+ Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE = "You must have an access token to query your High Fidelity places.
" +
+ "Please go back and connect your account.";
+
+ $('[data-toggle="tooltip"]').tooltip();
+
+ $('body').on('click', '.next-button', function() {
+ goToNextStep();
+ });
+
+ $('body').on('click', '.back-button', function() {
+ goToPreviousStep();
+ });
+
+ $('body').on('click', '#skip-wizard-button', function() {
+ skipWizard();
+ })
+
+ $('body').on('click', '#connect-account-btn', function() {
+ $(this).blur();
+ prepareAccessTokenPrompt(function(accessToken) {
+ Metaverse.accessToken = accessToken;
+ saveAccessToken();
+ });
+ });
+
+ $('body').on('click', '#save-permissions', function() {
+ savePermissions();
+ });
+
+ function triggerSaveUsernamePassword(event) {
+ if (event.keyCode === 13) {
+ $("#save-username-password").click();
+ }
+ }
+ $("#http_username").keyup(triggerSaveUsernamePassword);
+ $("#http_password").keyup(triggerSaveUsernamePassword);
+ $("#verify_http_password").keyup(triggerSaveUsernamePassword);
+ $('body').on('click', '#save-username-password', function() {
+ saveUsernamePassword();
+ });
+
+ $('body').on('click', '#change-place-name', function() {
+ chooseFromHighFidelityPlaces(Settings.data.values.metaverse.access_token, "/0,-10,0", function(placeName) {
+ updatePlaceNameLink(placeName);
+ });
+ });
+
+ $('body').on('click', '#explore-settings', function() {
+ console.log('explore-settings')
+ exploreSettings();
+ });
+
+ reloadSettings(function(success) {
+ if (success) {
+ setupWizardSteps();
+ updatePlaceNameDisplay();
+ updateUsernameDisplay();
+ } else {
+ swal({
+ title: '',
+ type: 'error',
+ text: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
+ });
+ }
+ });
+});
+
+function setupWizardSteps() {
+ var stepsCompleted = Settings.data.values.wizard.steps_completed;
+ var steps = null;
+
+ if (Settings.data.values.wizard.cloud_domain) {
+ $('.desktop-only').remove();
+ $('.wizard-step').find('.back-button').hide();
+
+ steps = $('.wizard-step');
+ $(steps).each(function(i) {
+ $(this).children(".step-title").text("Step " + (i + 1) + " of " + (steps.length - 1));
+ });
+
+ $('#permissions-description').html('You have been assigned administrator privileges to this domain.');
+ $('#admin-description').html('Add more High Fidelity usernames to grant administrator privileges.');
+ } else {
+ $('.cloud-only').remove();
+ $('#save-permissions').text("Finish");
+
+ steps = $('.wizard-step');
+ $(steps).each(function(i) {
+ $(this).children(".step-title").text("Step " + (i + 1) + " of " + steps.length);
+ });
+
+ if (stepsCompleted == 0) {
+ $('#skip-wizard-button').show();
+ }
+ }
+
+ var currentStep = steps[stepsCompleted];
+ $(currentStep).show();
+}
+
+function updatePlaceNameLink(address) {
+ if (address) {
+ $('#place-name-link').html('Your domain is reachable at: ' + address + '');
+ }
+}
+
+function updatePlaceNameDisplay() {
+ if (Settings.data.values.metaverse.id) {
+ $.getJSON(URLs.METAVERSE_URL + '/api/v1/domains/' + Settings.data.values.metaverse.id, function(data) {
+
+ if (data.status === 'success') {
+ if (data.domain.default_place_name) {
+ // Place name
+ updatePlaceNameLink(data.domain.default_place_name);
+ } else if (data.domain.name) {
+ // Temporary name
+ updatePlaceNameLink(data.domain.name);
+ } else if (data.domain.network_address) {
+ if (data.domain.network_port !== 40102) {
+ // IP:PORT
+ updatePlaceNameLink(data.domain.network_address + ':' + data.domain.network_port);
+ } else {
+ // IP
+ updatePlaceNameLink(data.domain.network_address);
+ }
+ }
+ } else {
+ console.warn('Request Failed');
+ }
+ }).fail(function() {
+ console.warn('Request Failed');
+ });
+ } else {
+ console.warn('No metaverse domain ID!');
+ }
+}
+
+function updateUsernameDisplay() {
+ var permissions = Settings.data.values.security.permissions;
+ if (permissions.length > 0) {
+ $('#username-display').html('(' + permissions[0].permissions_id + ') ');
+ }
+}
+
+function reloadSettings(callback) {
+ $.getJSON('/settings.json', function(data){
+ Settings.data = data;
+
+ if (callback) {
+ // call the callback now that settings are loaded
+ callback(true);
+ }
+ }).fail(function() {
+ if (callback) {
+ // call the failure object since settings load failed
+ callback(false)
+ }
+ });
+}
+
+function postSettings(jsonSettings, callback) {
+ console.log("----- SAVING ------");
+ console.log(JSON.stringify(jsonSettings));
+
+ // POST the form JSON to the domain-server settings.json endpoint so the settings are saved
+ $.ajax('/settings.json', {
+ data: JSON.stringify(jsonSettings),
+ contentType: 'application/json',
+ type: 'POST'
+ }).done(function(data){
+ if (data.status == "success") {
+ if (callback) {
+ callback();
+ }
+ reloadSettings();
+ } else {
+ swal("Error", Strings.LOADING_SETTINGS_ERROR)
+ reloadSettings();
+ }
+ }).fail(function(){
+ swal("Error", Strings.LOADING_SETTINGS_ERROR)
+ reloadSettings();
+ });
+}
+
+function goToNextStep() {
+ $('#skip-wizard-button').hide();
+
+ var currentStep = $('body').find('.wizard-step:visible');
+ var nextStep = currentStep.next('.wizard-step');
+
+ var formJSON = {
+ "wizard": {}
+ }
+
+ if (nextStep.length > 0) {
+ currentStep.hide();
+ nextStep.show();
+
+ var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
+
+ postSettings({
+ "wizard": {
+ "steps_completed": currentStepNumber.toString()
+ }
+ });
+ } else {
+ postSettings({
+ "wizard": {
+ "steps_completed": "0",
+ "completed_once": true
+ }
+ }, redirectToSettings);
+ }
+}
+
+function goToPreviousStep() {
+ var currentStep = $('body').find('.wizard-step:visible');
+ var previousStep = currentStep.prev('.wizard-step');
+
+ var formJSON = {
+ "wizard": {}
+ }
+
+ if (previousStep.length > 0) {
+ currentStep.hide();
+ previousStep.show();
+
+ var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) - 1;
+
+ postSettings({
+ "wizard": {
+ "steps_completed": currentStepNumber.toString()
+ }
+ });
+ }
+}
+
+function skipWizard() {
+ postSettings({
+ "wizard": {
+ "steps_completed": "0",
+ "completed_once": true
+ }
+ }, redirectToSettings);
+}
+
+function redirectToSettings() {
+ var redirectURL = "/settings" + location.search;
+ if (Settings.data.values.wizard.cloud_domain) {
+ if (location.search.length > 0) {
+ redirectURL += "&";
+ } else {
+ redirectURL += "?";
+ }
+ redirectURL += "cloud-wizard-exit";
+ }
+ location.href = redirectURL;
+}
+
+function saveAccessToken() {
+ var formJSON = {
+ "metaverse": {}
+ }
+ if (Metaverse.accessToken) {
+ formJSON.metaverse.access_token = Metaverse.accessToken;
+ }
+
+ // remove focus from the button
+ $(this).blur();
+
+ // POST the form JSON to the domain-server settings.json endpoint so the settings are saved
+ postSettings(formJSON, goToNextStep);
+}
+
+function getSettingDescriptionForKey(groupKey, settingKey) {
+ for (var i in Settings.data.descriptions) {
+ var group = Settings.data.descriptions[i];
+ if (group.name === groupKey) {
+ for (var j in group.settings) {
+ var setting = group.settings[j];
+ if (setting.name === settingKey) {
+ return setting;
+ }
+ }
+ }
+ }
+}
+
+function savePermissions() {
+ var localhostPermissions = (Settings.data.values.wizard.cloud_domain !== true)
+ var anonymousCanConnect = false;
+ var friendsCanConnect = false;
+ var loggedInCanConnect = false;
+ var anonymousCanRez = false;
+ var friendsCanRez = false;
+ var loggedInCanRez = false;
+
+ var connectValue = $('input[name=connect-radio]:checked').val();
+ var rezValue = $('input[name=rez-radio]:checked').val();
+
+ switch (connectValue) {
+ case "friends":
+ friendsCanConnect = true;
+ break;
+ case "logged-in":
+ friendsCanConnect = true;
+ loggedInCanConnect = true;
+ break;
+ case "everyone":
+ anonymousCanConnect = true;
+ friendsCanConnect = true;
+ loggedInCanConnect = true;
+ break;
+ }
+
+ switch (rezValue) {
+ case "friends":
+ friendsCanRez = true;
+ break;
+ case "logged-in":
+ friendsCanRez = true;
+ loggedInCanRez = true;
+ break;
+ case "everyone":
+ anonymousCanRez = true;
+ friendsCanRez = true;
+ loggedInCanRez = true;
+ break;
+ }
+
+ var admins = $('#admin-usernames').val().split(',');
+
+ var existingAdmins = Settings.data.values.security.permissions.map(function(value) {
+ return value.permissions_id;
+ });
+ admins = admins.concat(existingAdmins);
+
+ // Filter out unique values
+ admins = _.uniq(admins.map(function(username) {
+ return username.trim();
+ })).filter(function(username) {
+ return username !== "";
+ });
+
+ var formJSON = {
+ "security": {
+ "standard_permissions": [
+ {
+ "id_can_connect": anonymousCanConnect,
+ "id_can_rez": anonymousCanRez,
+ "id_can_rez_certified": anonymousCanRez,
+ "id_can_rez_tmp": anonymousCanRez,
+ "id_can_rez_tmp_certified": anonymousCanRez,
+ "permissions_id": "anonymous"
+ },
+ {
+ "id_can_connect": friendsCanConnect,
+ "id_can_rez": friendsCanRez,
+ "id_can_rez_certified": friendsCanRez,
+ "id_can_rez_tmp": friendsCanRez,
+ "id_can_rez_tmp_certified": friendsCanRez,
+ "permissions_id": "friends"
+ },
+ {
+ "id_can_connect": loggedInCanConnect,
+ "id_can_rez": loggedInCanRez,
+ "id_can_rez_certified": loggedInCanRez,
+ "id_can_rez_tmp": loggedInCanRez,
+ "id_can_rez_tmp_certified": loggedInCanRez,
+ "permissions_id": "logged-in"
+ },
+ {
+ "id_can_adjust_locks": localhostPermissions,
+ "id_can_connect": localhostPermissions,
+ "id_can_connect_past_max_capacity": localhostPermissions,
+ "id_can_kick": localhostPermissions,
+ "id_can_replace_content": localhostPermissions,
+ "id_can_rez": localhostPermissions,
+ "id_can_rez_tmp": localhostPermissions,
+ "id_can_write_to_asset_server": localhostPermissions,
+ "permissions_id": "localhost"
+ }
+ ]
+ }
+ }
+
+ if (admins.length > 0) {
+ formJSON.security.permissions = [];
+
+ var permissionsDesc = getSettingDescriptionForKey("security", "permissions");
+ for (var i in admins) {
+ var admin = admins[i];
+ var perms = {};
+ for (var i in permissionsDesc.columns) {
+ var name = permissionsDesc.columns[i].name;
+ if (name === "permissions_id") {
+ perms[name] = admin;
+ } else {
+ perms[name] = true;
+ }
+ }
+ formJSON.security.permissions.push(perms);
+ }
+ }
+
+ // remove focus from the button
+ $(this).blur();
+
+ postSettings(formJSON, goToNextStep);
+}
+
+function saveUsernamePassword() {
+ var username = $("#http_username").val();
+ var password = $("#http_password").val();
+ var verify_password = $("#verify_http_password").val();
+
+ if (username.length == 0) {
+ bootbox.alert({ "message": "You must set a username!", "title": "Username Error" });
+ return;
+ }
+
+ if (password.length == 0) {
+ bootbox.alert({ "message": "You must set a password!", "title": "Password Error" });
+ return;
+ }
+
+ if (password != verify_password) {
+ bootbox.alert({ "message": "Passwords must match!", "title": "Password Error" });
+ return;
+ }
+
+ var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
+
+ var formJSON = {
+ "security": {
+ "http_username": username,
+ "http_password": sha256_digest(password)
+ },
+ "wizard": {
+ "steps_completed": currentStepNumber.toString()
+ }
+ }
+
+ // remove focus from the button
+ $(this).blur();
+
+ // POST the form JSON to the domain-server settings.json endpoint so the settings are saved
+ postSettings(formJSON, function() {
+ location.reload();
+ });
+}
+
+function exploreSettings() {
+ if ($('#go-to-domain').is(":checked")) {
+ var link = $('#place-name-link a:first');
+ if (link.length > 0) {
+ window.open(link.attr("href"));
+ }
+ }
+
+ goToNextStep();
+}
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index b32e0873d9..de80851e72 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -1760,11 +1760,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
auto nodeList = DependencyManager::get();
- // allow sub-handlers to handle requests that do not require authentication
- if (_settingsManager.handlePublicHTTPRequest(connection, url)) {
- return true;
- }
-
// check if this is a request for a scripted assignment (with a temp unique UUID)
const QString ASSIGNMENT_REGEX_STRING = QString("\\%1\\/(%2)\\/?$").arg(URI_ASSIGNMENT).arg(UUID_REGEX_STRING);
QRegExp assignmentRegex(ASSIGNMENT_REGEX_STRING);
@@ -1825,6 +1820,31 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return true;
}
+ // Check if we should redirect/prevent access to the wizard
+ if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
+ const QString URI_WIZARD = "/wizard/";
+ const QString WIZARD_COMPLETED_ONCE_KEY_PATH = "wizard.completed_once";
+ const QVariant* wizardCompletedOnce = valueForKeyPath(_settingsManager.getSettingsMap(), WIZARD_COMPLETED_ONCE_KEY_PATH);
+ const bool completedOnce = wizardCompletedOnce && wizardCompletedOnce->toBool();
+
+ if (url.path() != URI_WIZARD && url.path().endsWith('/') && !completedOnce) {
+ // First visit, redirect to the wizard
+ QUrl redirectedURL = url;
+ redirectedURL.setPath(URI_WIZARD);
+
+ Headers redirectHeaders;
+ redirectHeaders.insert("Location", redirectedURL.toEncoded());
+
+ connection->respond(HTTPConnection::StatusCode302,
+ QByteArray(), HTTPConnection::DefaultContentType, redirectHeaders);
+ return true;
+ } else if (url.path() == URI_WIZARD && completedOnce) {
+ // Wizard already completed, return 404
+ connection->respond(HTTPConnection::StatusCode404, "Resource not found.");
+ return true;
+ }
+ }
+
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
if (url.path() == "/assignments.json") {
// user is asking for json list of assignments
@@ -1937,7 +1957,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return;
}
- static const char* CONTENT_TYPE_JSON { "application/json" };
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
@@ -1964,7 +1983,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return;
}
- static const char* CONTENT_TYPE_JSON { "application/json" };
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
@@ -1989,7 +2007,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return;
}
- static const char* CONTENT_TYPE_JSON { "application/json" };
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
@@ -2073,8 +2090,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
// this is an entity file upload, ask the HTTPConnection to parse the data
QList formData = connection->parseFormData();
- Headers redirectHeaders;
-
if (formData.size() > 0 && formData[0].second.size() > 0) {
// invoke our method to hand the new octree file off to the octree server
QMetaObject::invokeMethod(this, "handleOctreeFileReplacement",
@@ -2219,7 +2234,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return;
}
- static const char* CONTENT_TYPE_JSON { "application/json" };
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
@@ -2284,7 +2298,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return;
}
- static const char* CONTENT_TYPE_JSON { "application/json" };
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp
index c801a4a71a..1d5515b61a 100644
--- a/domain-server/src/DomainServerSettingsManager.cpp
+++ b/domain-server/src/DomainServerSettingsManager.cpp
@@ -960,29 +960,6 @@ QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QStrin
return QVariant();
}
-bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) {
- if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == SETTINGS_PATH_JSON) {
- // this is a GET operation for our settings
-
- // check if there is a query parameter for settings affecting a particular type of assignment
- const QString SETTINGS_TYPE_QUERY_KEY = "type";
- QUrlQuery settingsQuery(url);
- QString typeValue = settingsQuery.queryItemValue(SETTINGS_TYPE_QUERY_KEY);
-
- if (!typeValue.isEmpty()) {
- QJsonObject responseObject = responseObjectForType(typeValue);
-
- connection->respond(HTTPConnection::StatusCode200, QJsonDocument(responseObject).toJson(), "application/json");
-
- return true;
- } else {
- return false;
- }
- }
-
- return false;
-}
-
bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection *connection, const QUrl &url) {
if (connection->requestOperation() == QNetworkAccessManager::PostOperation && url.path() == SETTINGS_PATH_JSON) {
// this is a POST operation to change one or more settings
@@ -1214,6 +1191,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
static const QString SECURITY_ROOT_KEY = "security";
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
static const QString BROADCASTING_KEY = "broadcasting";
+ static const QString WIZARD_KEY = "wizard";
static const QString DESCRIPTION_ROOT_KEY = "descriptors";
auto& settingsVariant = _configMap.getConfig();
@@ -1266,7 +1244,8 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
if (!matchingDescriptionObject.isEmpty()) {
updateSetting(rootKey, rootValue, *thisMap, matchingDescriptionObject);
- if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != SETTINGS_PATHS_KEY ) {
+ if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY &&
+ rootKey != SETTINGS_PATHS_KEY && rootKey != WIZARD_KEY) {
needRestart = true;
}
} else {
@@ -1282,8 +1261,9 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
if (!matchingDescriptionObject.isEmpty()) {
const QJsonValue& settingValue = rootValue.toObject()[settingKey];
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
- if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != DESCRIPTION_ROOT_KEY)
- || settingKey == AC_SUBNET_WHITELIST_KEY) {
+ if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY &&
+ rootKey != DESCRIPTION_ROOT_KEY && rootKey != WIZARD_KEY) ||
+ settingKey == AC_SUBNET_WHITELIST_KEY) {
needRestart = true;
}
} else {
diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h
index 4c7d8dfbc9..d2f6d1e526 100644
--- a/domain-server/src/DomainServerSettingsManager.h
+++ b/domain-server/src/DomainServerSettingsManager.h
@@ -43,7 +43,6 @@ class DomainServerSettingsManager : public QObject {
Q_OBJECT
public:
DomainServerSettingsManager();
- bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url);
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
void setupConfigMap(const QStringList& argumentList);
diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h
index b91b75625c..a512ae8887 100644
--- a/libraries/networking/src/NetworkingConstants.h
+++ b/libraries/networking/src/NetworkingConstants.h
@@ -15,7 +15,7 @@
#include
namespace NetworkingConstants {
- const QUrl METAVERSE_SERVER_URL = QUrl("https://staging.highfidelity.com");
+ const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com");
}
#endif // hifi_NetworkingConstants_h