From 193b50efc723252a98a159c22c7d6f9d076d5f5e Mon Sep 17 00:00:00 2001
From: MattIPv4 <me@mattcowley.co.uk>
Date: Wed, 27 May 2020 21:15:30 +0100
Subject: [PATCH] Backwards compatibility for global options

---
 src/nginxconfig/templates/app.vue             |  4 +-
 .../util/backwards_compatibility.js           | 68 +++++++++++++++++++
 src/nginxconfig/util/import_data.js           |  4 ++
 3 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 src/nginxconfig/util/backwards_compatibility.js

diff --git a/src/nginxconfig/templates/app.vue b/src/nginxconfig/templates/app.vue
index 5984aa0..edd9256 100644
--- a/src/nginxconfig/templates/app.vue
+++ b/src/nginxconfig/templates/app.vue
@@ -151,8 +151,10 @@ limitations under the License.
         },
         mounted() {
             // Import any data from the URL query params, defaulting to one domain
+            // Fallback to the window hash if no search query params, from the Angular version of nginxconfig
             // The config file watcher will handle setting the app as ready
-            importData(window.location.search, this.$data.domains, this.$data.global, this.$nextTick);
+            const query = window.location.search || window.location.hash.slice(1);
+            importData(query, this.$data.domains, this.$data.global, this.$nextTick);
         },
         methods: {
             changes(index) {
diff --git a/src/nginxconfig/util/backwards_compatibility.js b/src/nginxconfig/util/backwards_compatibility.js
new file mode 100644
index 0000000..2ccbe9f
--- /dev/null
+++ b/src/nginxconfig/util/backwards_compatibility.js
@@ -0,0 +1,68 @@
+const oldBool = val => val === '' ? true : val;
+
+const globalMap = {
+    ssl_profile:                ['https', 'sslProfile'],
+    resolver_cloudflare:        ['https', 'ocspCloudflare', oldBool],
+    resolver_google:            ['https', 'ocspGoogle', oldBool],
+    resolver_opendns:           ['https', 'ocspOpenDns', oldBool],
+    directory_letsencrypt:      ['https', 'letsEncryptRoot'],
+
+    referrer_policy:            ['security', 'referrerPolicy'],
+    content_security_policy:    ['security', 'contentSecurityPolicy'],
+    server_tokens:              ['security', 'serverTokens', oldBool],
+    limit_req:                  ['security', 'limitReq', oldBool],
+
+    php_server:                 ['php', 'phpServer'],
+    php_server_backup:          ['php', 'phpBackupServer'],
+
+    python_server:              ['python', 'pythonServer'],
+
+    gzip:                       ['performance', 'gzipCompression', oldBool],
+    brotli:                     ['performance', 'brotliCompression', oldBool],
+    expires_assets:             ['performance', 'assetsExpiration'],
+    expires_media:              ['performance', 'mediaExpiration'],
+    expires_svg:                ['performance', 'svgExpiration'],
+    expires_fonts:              ['performance', 'fontsExpiration'],
+
+    access_log:                 ['logging', 'accessLog'],
+    error_log:                  ['logging', 'errorLog'],
+    log_not_found:              ['logging', 'logNotFound', oldBool],
+
+    directory_nginx:            ['nginx', 'nginxConfigDirectory'],
+    worker_processes:           ['nginx', 'workerProcesses'],
+    user:                       ['nginx', 'user'],
+    pid:                        ['nginx', 'pid'],
+    client_max_body_size:       ['nginx', 'clientMaxBodySize'],
+
+    file_structure:             ['tools', 'modularizedStructure', val => val.toLowerCase().trim() === 'modularized'],
+    symlink:                    ['tools', 'symlinkVhost', oldBool],
+};
+
+// Handle converting the old query format from nginxconfig.io-angular to our new query params
+export default data => {
+    // Handle converting global settings & storing domains
+    for (const key in data) {
+        if (!Object.prototype.hasOwnProperty.call(data, key)) continue;
+
+        // Map old global settings to their new ones
+        if (key in globalMap) {
+            const map = globalMap[key];
+
+            data.global = data.global || {};
+            data.global[map[0]] = data.global[map[0]] || {};
+            data.global[map[0]][map[1]] = map.length < 3 ? data[key] : map[2](data[key]);
+
+            delete data[key];
+            continue;
+        }
+
+        // If not a global setting and if this is an integer
+        // Then, this is probably an old domain, so we'll try to convert it as such
+        if (!isNaN(parseInt(key))) {
+            data.domains = data.domains || [];
+            data.domains.push(data[key]);
+        }
+    }
+
+    // TODO: Handle converting domain settings
+};
diff --git a/src/nginxconfig/util/import_data.js b/src/nginxconfig/util/import_data.js
index 836dc3f..2373bfc 100644
--- a/src/nginxconfig/util/import_data.js
+++ b/src/nginxconfig/util/import_data.js
@@ -2,6 +2,7 @@ import qs from 'qs';
 import clone from 'clone';
 import Domain from '../templates/domain';
 import isObject from './is_object';
+import backwardsCompatibility from './backwards_compatibility';
 
 const applyCategories = (categories, target) => {
     // Work through each potential category
@@ -57,6 +58,9 @@ export default (query, domains, global, nextTick) => {
         },
     });
 
+    // Handle converting nginxconfig.io-angular params to the current version
+    backwardsCompatibility(data);
+
     // Handle domains
     if ('domains' in data) {
         // Check its an array or object