diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
new file mode 100644
index 0000000..e8b190d
--- /dev/null
+++ b/.github/release-drafter.yml
@@ -0,0 +1,4 @@
+name-template: '$NEXT_PATCH_VERSION'
+tag-template: '$NEXT_PATCH_VERSION'
+template: |
+ $CHANGES
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3475a04..2ffa886 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -1,19 +1,58 @@
-name: Build
+name: Build and Publish
on:
push:
+ release:
+ types: [published]
jobs:
- validate:
- name: Validate
+ check:
+ name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - name: Use Node 12.18.x
- uses: actions/setup-node@v1
- with:
- node-version: 12.18.x
- name: Install dependencies
run: |
npm install
- name: Lint
run: |
npm run lint
+ - name: Build
+ run: |
+ cat << CONFIG > src/config/config.json
+ {
+ "hostname": "box.example.com",
+ "mockApi": true
+ }
+ CONFIG
+ npm run build
+ publish:
+ needs: [check]
+ name: Publish
+ runs-on: ubuntu-latest
+ if: github.event_name == 'release' && github.event.action == 'published'
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install dependencies
+ run: |
+ npm install
+ - name: Build
+ run: |
+ cat << CONFIG > src/config/config.json
+ {
+ "hostname": "box.example.com",
+ "mockApi": true
+ }
+ CONFIG
+ PUBLIC_URL=/mailinabox-ui/ npm run build
+ - name: Publish
+ run: |
+ mv build .build
+ tag=${GITHUB_REF#refs/tags/}
+ git checkout gh-pages
+ rm -rf *
+ mv .build/* .
+ rm -rf .build
+ git config user.name github-actions
+ git config user.email github-actions@github.com
+ git add .
+ git commit -m "Add build for version $tag"
+ git push
diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml
new file mode 100644
index 0000000..5892747
--- /dev/null
+++ b/.github/workflows/release-drafter.yml
@@ -0,0 +1,13 @@
+name: Release Drafter
+on:
+ push:
+ branches:
+ - master
+jobs:
+ update-release-draft:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Draft release
+ uses: release-drafter/release-drafter@v5
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 044f1d7..444b2b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,4 @@
npm-debug.log*
# config files
-/src/config/index.json
+/src/config/config.json
diff --git a/README.md b/README.md
index f5f4261..bf3a7f1 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ An experimental SPA user interface for Mail-in-a-Box, using the following tools:
### Instructions
1. Clone the repo
-2. Copy `src/config/index.example.json` to `src/config/index.json` and update the `hostname` field within `index.json` to point to your box
+2. Copy `src/config/config.example.json` to `src/config/config.json` and update the `hostname` field within `index.json` to point to your box
3. From the root of the project:
1. Run `npm install`
2. Run `npm start`
diff --git a/package-lock.json b/package-lock.json
index 740d255..27acdfa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7631,6 +7631,37 @@
"bser": "2.1.1"
}
},
+ "fetch-mock": {
+ "version": "9.10.6",
+ "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.10.6.tgz",
+ "integrity": "sha512-kqAV3C8KNmNZcY87e2yP4qBbRD1H4i0Cndw0bKmXNBItuEdTfCmDlDdIGviFbS5bqp0pS9GZ721aAQud+zRmJQ==",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "core-js": "^3.0.0",
+ "debug": "^4.1.1",
+ "glob-to-regexp": "^0.4.0",
+ "is-subset": "^0.1.1",
+ "lodash.isequal": "^4.5.0",
+ "path-to-regexp": "^2.2.1",
+ "querystring": "^0.2.0",
+ "whatwg-url": "^6.5.0"
+ },
+ "dependencies": {
+ "glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz",
+ "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==",
+ "dev": true
+ }
+ }
+ },
"figgy-pudding": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@@ -9335,6 +9366,12 @@
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
"dev": true
},
+ "is-subset": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
+ "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
+ "dev": true
+ },
"is-svg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz",
@@ -12029,6 +12066,12 @@
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
"dev": true
},
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
diff --git a/package.json b/package.json
index 460d00c..b835b70 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",
+ "fetch-mock": "^9.10.6",
"http-proxy-middleware": "^1.0.5",
"mailinabox-api": "^0.46.4",
"prettier": "^2.0.5",
diff --git a/src/api/mockApi.ts b/src/api/mockApi.ts
new file mode 100644
index 0000000..2609839
--- /dev/null
+++ b/src/api/mockApi.ts
@@ -0,0 +1,17 @@
+import fetchMock from 'fetch-mock';
+import { mocks } from './mocks';
+
+Object.keys(mocks).forEach((url) => {
+ const methods = mocks[url];
+ Object.keys(methods).forEach((method) => {
+ const data = mocks[url][method];
+ fetchMock.mock(
+ {
+ url,
+ method,
+ delay: 500,
+ },
+ data
+ );
+ });
+});
diff --git a/src/api/mocks/dns/data/addDnsCustomARecord.json b/src/api/mocks/dns/data/addDnsCustomARecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/addDnsCustomARecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/addDnsCustomRecord.json b/src/api/mocks/dns/data/addDnsCustomRecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/addDnsCustomRecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/addDnsSecondaryNameserver.json b/src/api/mocks/dns/data/addDnsSecondaryNameserver.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/addDnsSecondaryNameserver.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/getDnsCustomARecordsForQName.json b/src/api/mocks/dns/data/getDnsCustomARecordsForQName.json
new file mode 100644
index 0000000..34df59b
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsCustomARecordsForQName.json
@@ -0,0 +1,9 @@
+{
+ "response": [
+ {
+ "qname": "example.com",
+ "rtype": "MX",
+ "value": "10 example.com."
+ }
+ ]
+}
diff --git a/src/api/mocks/dns/data/getDnsCustomRecords.json b/src/api/mocks/dns/data/getDnsCustomRecords.json
new file mode 100644
index 0000000..8950a8b
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsCustomRecords.json
@@ -0,0 +1,74 @@
+{
+ "response": [
+ {
+ "qname": "example.com",
+ "rtype": "A",
+ "value": "11.12.13.14"
+ },
+ {
+ "qname": "example.com",
+ "rtype": "AAAA",
+ "value": "2a09:4fa:1c1c:e08a::2"
+ },
+ {
+ "qname": "example2.com",
+ "rtype": "A",
+ "value": "12.13.14.15"
+ },
+ {
+ "qname": "blog.example2.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "www.example3.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "www.example3.com",
+ "rtype": "AAAA",
+ "value": "2a11:8f8:1c1c:b688::1"
+ },
+ {
+ "qname": "blog.example3.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "blog.example3.com",
+ "rtype": "AAAA",
+ "value": "2a11:8f8:1c1c:b688::1"
+ },
+ {
+ "qname": "example4.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "example4.com",
+ "rtype": "AAAA",
+ "value": "2a11:8f8:1c1c:b688::1"
+ },
+ {
+ "qname": "shop.example4.com",
+ "rtype": "AAAA",
+ "value": "2a11:8f8:1c1c:b688::1"
+ },
+ {
+ "qname": "shop.example4.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "example5.com",
+ "rtype": "A",
+ "value": "13.14.15.16"
+ },
+ {
+ "qname": "example5.com",
+ "rtype": "AAAA",
+ "value": "2a11:8f8:1c1c:b688::1"
+ }
+ ]
+}
diff --git a/src/api/mocks/dns/data/getDnsCustomRecordsForQNameAndType.json b/src/api/mocks/dns/data/getDnsCustomRecordsForQNameAndType.json
new file mode 100644
index 0000000..34df59b
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsCustomRecordsForQNameAndType.json
@@ -0,0 +1,9 @@
+{
+ "response": [
+ {
+ "qname": "example.com",
+ "rtype": "MX",
+ "value": "10 example.com."
+ }
+ ]
+}
diff --git a/src/api/mocks/dns/data/getDnsDump.json b/src/api/mocks/dns/data/getDnsDump.json
new file mode 100644
index 0000000..b0993e9
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsDump.json
@@ -0,0 +1,880 @@
+{
+ "response": [
+ [
+ "example.com",
+ [
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example.com mail.",
+ "qname": "example.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Required. Sets the IP address of the box.",
+ "qname": "box.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Required. Sets the IPv6 address of the box.",
+ "qname": "box.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @box.example.com mail.",
+ "qname": "box.example.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example.com mail.",
+ "qname": "example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example.com mail.",
+ "qname": "mail._domainkey.example.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @box.example.com mail.",
+ "qname": "box.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @box.example.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @box.example.com mail.",
+ "qname": "mail._domainkey.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @autoconfig.box.example.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "autoconfig.box.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @autoconfig.box.example.com.",
+ "qname": "_dmarc.autoconfig.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @autodiscover.box.example.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "autodiscover.box.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @autodiscover.box.example.com.",
+ "qname": "_dmarc.autodiscover.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @ns1.box.example.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "ns1.box.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @ns1.box.example.com.",
+ "qname": "_dmarc.ns1.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @ns2.box.example.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "ns2.box.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @ns2.box.example.com.",
+ "qname": "_dmarc.ns2.box.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example.com.",
+ "qname": "_dmarc.www.example.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:e08a::2"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Optional. Provides an out-of-band method for verifying an SSH key before connecting. Use 'VerifyHostKeyDNS yes' (or 'VerifyHostKeyDNS ask') when connecting with ssh.",
+ "qname": "box.example.com",
+ "rtype": "SSHFP",
+ "value": "3 2 ( 4FB486A3269CB99075C486BF64591321A600213411EC948A25A32171331111C8 )"
+ },
+ {
+ "explanation": "Optional. Provides an out-of-band method for verifying an SSH key before connecting. Use 'VerifyHostKeyDNS yes' (or 'VerifyHostKeyDNS ask') when connecting with ssh.",
+ "qname": "box.example.com",
+ "rtype": "SSHFP",
+ "value": "4 2 ( 8888D95D0C3CD152D31F41B544024B0FC81D6AC23FA16B2142FC3D40247F6 )"
+ },
+ {
+ "explanation": "Optional. Provides an out-of-band method for verifying an SSH key before connecting. Use 'VerifyHostKeyDNS yes' (or 'VerifyHostKeyDNS ask') when connecting with ssh.",
+ "qname": "box.example.com",
+ "rtype": "SSHFP",
+ "value": "1 2 ( 888857D5CAB76684F937745FD8D6E02FC4731C05D354DF6FFB15E6FA203C4F261 )"
+ },
+ {
+ "explanation": "Recommended when DNSSEC is enabled. Advertises to mail servers connecting to the box that mandatory encryption should be used.",
+ "qname": "_25._tcp.box.example.com",
+ "rtype": "TLSA",
+ "value": "3 1 1 8882b2f8150bf467449a0e41f2d03db1dccfaddb076342404176b446ff5b30bb"
+ },
+ {
+ "explanation": "Optional. When DNSSEC is enabled, provides out-of-band HTTPS certificate validation for a few web clients that support it.",
+ "qname": "_443._tcp.box.example.com",
+ "rtype": "TLSA",
+ "value": "3 1 1 8882b2f8150bf467449a0e41f2d03db1dccfaddb076342404176b446ff5b30bb"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.box.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.box.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.box.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.box.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Optional. Sets the IP address that www.example.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that www.example.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ }
+ ]
+ ],
+ [
+ "example2.com",
+ [
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example2.com mail.",
+ "qname": "example2.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example2.com mail.",
+ "qname": "example2.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example2.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example2.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example2.com mail.",
+ "qname": "mail._domainkey.example2.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example2.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example2.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @blog.example2.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "blog.example2.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @blog.example2.com.",
+ "qname": "_dmarc.blog.example2.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example2.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example2.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example2.com.",
+ "qname": "_dmarc.www.example2.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example2.com",
+ "rtype": "A",
+ "value": "185.199.110.153"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example2.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example2.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example2.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example2.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "blog.example2.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "Optional. Sets the IP address that www.example2.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example2.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that www.example2.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example2.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ }
+ ]
+ ],
+ [
+ "example3.com",
+ [
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example3.com mail.",
+ "qname": "example3.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example3.com mail.",
+ "qname": "example3.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example3.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example3.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example3.com mail.",
+ "qname": "mail._domainkey.example3.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example3.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example3.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @shop.example3.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "shop.example3.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @shop.example3.com.",
+ "qname": "_dmarc.shop.example3.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example3.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example3.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example3.com.",
+ "qname": "_dmarc.www.example3.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example3.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example3.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:b688::1"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example3.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example3.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example3.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example3.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "shop.example3.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:b688::1"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "shop.example3.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "Optional. Sets the IP address that www.example3.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example3.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that www.example3.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example3.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ }
+ ]
+ ],
+ [
+ "example4.com",
+ [
+ {
+ "explanation": "Required. May have a different value. Sets the IP address that example4.com resolves to for web hosting and other services besides mail. The A record must be present but its value does not affect mail delivery.",
+ "qname": "example4.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example4.com mail.",
+ "qname": "example4.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example4.com mail.",
+ "qname": "example4.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example4.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example4.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example4.com mail.",
+ "qname": "mail._domainkey.example4.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example4.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example4.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example4.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example4.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example4.com.",
+ "qname": "_dmarc.www.example4.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that example4.com resolves to, e.g. for web hosting. (It is not necessary for receiving mail on this domain.)",
+ "qname": "example4.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example4.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example4.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example4.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example4.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Optional. Sets the IP address that www.example4.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example4.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that www.example4.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example4.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ }
+ ]
+ ],
+ [
+ "example5.com",
+ [
+ {
+ "explanation": "Required. May have a different value. Sets the IP address that example5.com resolves to for web hosting and other services besides mail. The A record must be present but its value does not affect mail delivery.",
+ "qname": "example5.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example5.com mail.",
+ "qname": "example5.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example5.com mail.",
+ "qname": "example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example5.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example5.com mail.",
+ "qname": "mail._domainkey.example5.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example5.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example5.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @aaaa.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "aaaa.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @aaaa.example5.com.",
+ "qname": "_dmarc.aaaa.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @dsfdsfds.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "dsfdsfds.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @dsfdsfds.example5.com.",
+ "qname": "_dmarc.dsfdsfds.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @fdsfdsfdsf.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "fdsfdsfdsf.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @fdsfdsfdsf.example5.com.",
+ "qname": "_dmarc.fdsfdsfdsf.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @hlc-medical.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "hlc-medical.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @hlc-medical.example5.com.",
+ "qname": "_dmarc.hlc-medical.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @sdcfdsfdsfds.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "sdcfdsfdsfds.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @sdcfdsfdsfds.example5.com.",
+ "qname": "_dmarc.sdcfdsfdsfds.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example5.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example5.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example5.com.",
+ "qname": "_dmarc.www.example5.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that example5.com resolves to, e.g. for web hosting. (It is not necessary for receiving mail on this domain.)",
+ "qname": "example5.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "aaaa.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example5.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example5.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example5.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example5.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "dsfdsfds.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "fdsfdsfdsf.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "hlc-medical.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "hlc-medical.example5.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:b688::1"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "sdcfdsfdsfds.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "www.example5.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "www.example5.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:b688::1"
+ }
+ ]
+ ],
+ [
+ "example6.com",
+ [
+ {
+ "explanation": "Required. Specifies the hostname (and priority) of the machine that handles @example6.com mail.",
+ "qname": "example6.com",
+ "rtype": "MX",
+ "value": "10 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies that only the box is permitted to send @example6.com mail.",
+ "qname": "example6.com",
+ "rtype": "TXT",
+ "value": "v=spf1 mx -all"
+ },
+ {
+ "explanation": "Recommended. Specifies that mail that does not originate from the box but claims to be from @example6.com or which does not have a valid DKIM signature is suspect and should be quarantined by the recipient's mail system.",
+ "qname": "_dmarc.example6.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=quarantine"
+ },
+ {
+ "explanation": "Recommended. Provides a way for recipients to verify that this machine sent @example6.com mail.",
+ "qname": "mail._domainkey.example6.com",
+ "rtype": "TXT",
+ "value": "v=DKIM1; k=rsa; s=email; p=4GNADCBiQKBgQDMw2+7dZ3Iqukz2cuSBmtD3cizDYXEqGF3iJgPS82sHI+MxY6AikD0VidG3d/NU8MQo338KwQVloGG5yboREczs7eL+J6n+oJT8Mz01NNpUONcpuM/FlhgpmEUuBBvN/gA5xDVZ6CttCSnM2SaF/Lsba+o9YxSzUflx8JyQOUGvwIDAQAB"
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_caldavs._tcp.example6.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.",
+ "qname": "_carddavs._tcp.example6.com",
+ "rtype": "SRV",
+ "value": "0 0 443 box.example.com."
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that no servers are valid sources for mail from @www.example6.com. If you do send email from this domain name you should either override this record such that the SPF rule does allow the originating server, or, take the recommended approach and have the box handle mail for this domain (simply add any receiving alias at this domain name to make this machine treat the domain name as one of its mail domains).",
+ "qname": "www.example6.com",
+ "rtype": "TXT",
+ "value": "v=spf1 -all"
+ },
+ {
+ "explanation": "Recommended. Prevents use of this domain name for outbound mail by specifying that the SPF rule should be honoured for mail from @www.example6.com.",
+ "qname": "_dmarc.www.example6.com",
+ "rtype": "TXT",
+ "value": "v=DMARC1; p=reject"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example6.com",
+ "rtype": "A",
+ "value": "116.203.79.11"
+ },
+ {
+ "explanation": "(Set by user.)",
+ "qname": "example6.com",
+ "rtype": "AAAA",
+ "value": "2a01:4f8:1c1c:b688::1"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example6.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Thunderbird Autoconfig.",
+ "qname": "autoconfig.example6.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example6.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover.",
+ "qname": "autodiscover.example6.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ },
+ {
+ "explanation": "Optional. Sets the IP address that www.example6.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example6.com",
+ "rtype": "A",
+ "value": "10.11.12.13"
+ },
+ {
+ "explanation": "Optional. Sets the IPv6 address that www.example6.com resolves to so that the box can provide a redirect to the parent domain.",
+ "qname": "www.example6.com",
+ "rtype": "AAAA",
+ "value": "8a01:8f8:1c1c:e88a::8"
+ }
+ ]
+ ]
+ ]
+}
diff --git a/src/api/mocks/dns/data/getDnsSecondaryNameserver.json b/src/api/mocks/dns/data/getDnsSecondaryNameserver.json
new file mode 100644
index 0000000..df39287
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsSecondaryNameserver.json
@@ -0,0 +1,5 @@
+{
+ "response": {
+ "hostnames": ["ns1.example.com"]
+ }
+}
diff --git a/src/api/mocks/dns/data/getDnsZones.json b/src/api/mocks/dns/data/getDnsZones.json
new file mode 100644
index 0000000..d636272
--- /dev/null
+++ b/src/api/mocks/dns/data/getDnsZones.json
@@ -0,0 +1,10 @@
+{
+ "response": [
+ "example1.com",
+ "example2.com",
+ "example3.com",
+ "example4.com",
+ "example5.com",
+ "example6.com"
+ ]
+}
diff --git a/src/api/mocks/dns/data/removeDnsCustomARecord.json b/src/api/mocks/dns/data/removeDnsCustomARecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/removeDnsCustomARecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/removeDnsCustomRecord.json b/src/api/mocks/dns/data/removeDnsCustomRecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/removeDnsCustomRecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/updateDns.json b/src/api/mocks/dns/data/updateDns.json
new file mode 100644
index 0000000..cc214a0
--- /dev/null
+++ b/src/api/mocks/dns/data/updateDns.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example1.com,example2.com"
+}
diff --git a/src/api/mocks/dns/data/updateDnsCustomARecord.json b/src/api/mocks/dns/data/updateDnsCustomARecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/updateDnsCustomARecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/data/updateDnsCustomRecord.json b/src/api/mocks/dns/data/updateDnsCustomRecord.json
new file mode 100644
index 0000000..939cd51
--- /dev/null
+++ b/src/api/mocks/dns/data/updateDnsCustomRecord.json
@@ -0,0 +1,3 @@
+{
+ "response": "updated DNS: example.com"
+}
diff --git a/src/api/mocks/dns/index.ts b/src/api/mocks/dns/index.ts
new file mode 100644
index 0000000..9a56827
--- /dev/null
+++ b/src/api/mocks/dns/index.ts
@@ -0,0 +1,47 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { Mocks } from '../types';
+import addDnsCustomARecord from './data/addDnsCustomARecord.json';
+import addDnsCustomRecord from './data/addDnsCustomRecord.json';
+import addDnsSecondaryNameserver from './data/addDnsSecondaryNameserver.json';
+import getDnsCustomARecordsForQName from './data/getDnsCustomARecordsForQName.json';
+import getDnsCustomRecords from './data/getDnsCustomRecords.json';
+import getDnsCustomRecordsForQNameAndType from './data/getDnsCustomRecordsForQNameAndType.json';
+import getDnsDump from './data/getDnsDump.json';
+import getDnsSecondaryNameserver from './data/getDnsSecondaryNameserver.json';
+import getDnsZones from './data/getDnsZones.json';
+import removeDnsCustomARecord from './data/removeDnsCustomARecord.json';
+import removeDnsCustomRecord from './data/removeDnsCustomRecord.json';
+import updateDns from './data/updateDns.json';
+import updateDnsCustomARecord from './data/updateDnsCustomARecord.json';
+import updateDnsCustomRecord from './data/updateDnsCustomRecord.json';
+
+export const dns: Mocks = {
+ 'admin/dns/secondary-nameserver': {
+ get: getDnsSecondaryNameserver.response,
+ post: addDnsSecondaryNameserver.response,
+ },
+ 'admin/dns/zones': {
+ get: getDnsZones.response,
+ },
+ 'admin/dns/update': {
+ get: updateDns.response,
+ },
+ 'admin/dns/custom': {
+ get: getDnsCustomRecords.response,
+ },
+ 'admin/dns/:qname/:rtype': {
+ get: getDnsCustomRecordsForQNameAndType.response,
+ post: addDnsCustomRecord.response,
+ put: updateDnsCustomRecord.response,
+ delete: removeDnsCustomRecord.response,
+ },
+ 'admin/dns/:qname': {
+ get: getDnsCustomARecordsForQName.response,
+ post: addDnsCustomARecord.response,
+ put: updateDnsCustomARecord.response,
+ delete: removeDnsCustomARecord.response,
+ },
+ 'admin/dns/dump': {
+ get: getDnsDump.response,
+ },
+};
diff --git a/src/api/mocks/index.ts b/src/api/mocks/index.ts
new file mode 100644
index 0000000..d41bb6a
--- /dev/null
+++ b/src/api/mocks/index.ts
@@ -0,0 +1,16 @@
+import { dns } from './dns';
+import { ssl } from './ssl';
+import { system } from './system';
+import { Mocks } from './types';
+import { user } from './user';
+import { users } from './users';
+import { web } from './web';
+
+export const mocks: Mocks = {
+ ...users,
+ ...system,
+ ...dns,
+ ...ssl,
+ ...web,
+ ...user,
+};
diff --git a/src/api/mocks/ssl/data/generateSSLCSR.json b/src/api/mocks/ssl/data/generateSSLCSR.json
new file mode 100644
index 0000000..ba6327a
--- /dev/null
+++ b/src/api/mocks/ssl/data/generateSSLCSR.json
@@ -0,0 +1,3 @@
+{
+ "response": "-----BEGIN CERTIFICATE REQUEST-----\nMIICaDCCAVACAQAwIzELMAkGA1UEBhMCQlMxFDASBgNVBAMMC2V4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3K6dwLM2Nk8kVhIBaZmp\neY6y7O0T3jrexEKlW839TVYdcH+K35V1NxilbMFKMuHeowGwFyyiqOy/OUYNeq+T\nRz3s4b1qG2p01dwlsXHHYmXLYTAhvqvY+CU5ksieuZbyHRTwbHViQ0xtRXwoVCnj\nCkN7kJVpkLfVN0/BG6NBFpv/JI8F+hwp+IHdkC1gUXRrLJNC79ERqFP8HoqdQWNw\nOGGFaOe2aQhvj2zt8wFncyKVc40UKVbSzGGzdL2MPiAJHgZ2lmeY1xDyX1lOt12R\nIFPwtxmbxaxYaVfe2hxl7m88xV3OjYcKgwVYDusk2XJ37cGew5g+NbBvzEeEUpF9\n5wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD7UPC3/Nkgpn53mT9puUonYdJg9\nSD8vvTK/N78CzoEgPNyq+bYbqlcvVPKIdItf9TMiqfOSvW3e3NvkRisYle8Qp+0C\n8pafXBvQ9eHt5CFeJn4sH9GnxeflOZT/P9Jnp71KtZQvOobirX4GgEWs79g+/NHb\nZyf8rbadt9HruNhKA5nlP8cn7Rdc/iuJU8MVSQszI1s1DEcXMPxr6iqb2g87/ifH\nlWcK59kvRJkCcPhPzjpUy9NulucH4WFA/WqKeDNFS/oC+upV5w8EDEcfnenJFG+N\nJmFDQESSfUxLPHLC660Wnf3GmrP/duZHpPC+qTe8b1AlQ7zDT3cOaAQ+Mb0=\n-----END CERTIFICATE REQUEST-----\n"
+}
diff --git a/src/api/mocks/ssl/data/getSSLStatus.json b/src/api/mocks/ssl/data/getSSLStatus.json
new file mode 100644
index 0000000..4a5af1e
--- /dev/null
+++ b/src/api/mocks/ssl/data/getSSLStatus.json
@@ -0,0 +1,142 @@
+{
+ "response": {
+ "can_provision": [],
+ "status": [
+ {
+ "domain": "box.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 82 days on 10/28/20."
+ },
+ {
+ "domain": "autoconfig.box.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autodiscover.box.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autoconfig.example2.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autoconfig.example3.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ },
+ {
+ "domain": "autoconfig.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autoconfig.example4.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ },
+ {
+ "domain": "autodiscover.example2.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autodiscover.example3.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ },
+ {
+ "domain": "autodiscover.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autodiscover.example4.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ },
+ {
+ "domain": "example5.com",
+ "status": "danger",
+ "text": "No certificate installed. The domain name does not resolve to this machine: 11.12.13.14 (A), 2222:4f1:1c1c:b666::1 (AAAA)."
+ },
+ {
+ "domain": "autoconfig.example5.com",
+ "status": "danger",
+ "text": "No certificate installed. The domain name does not resolve to this machine: [Not Set] (A), [Not Set] (AAAA)."
+ },
+ {
+ "domain": "autodiscover.example5.com",
+ "status": "danger",
+ "text": "No certificate installed. The domain name does not resolve to this machine: [Not Set] (A), [Not Set] (AAAA)."
+ },
+ {
+ "domain": "www.example5.com",
+ "status": "danger",
+ "text": "No certificate installed. The domain name does not resolve to this machine: 11.12.13.14 (A), 2222:4f1:1c1c:b666::1 (AAAA)."
+ },
+ {
+ "domain": "example6.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 26 days on 09/02/20."
+ },
+ {
+ "domain": "autoconfig.example6.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "autodiscover.example6.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ },
+ {
+ "domain": "www.example2.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 54 days on 09/30/20."
+ },
+ {
+ "domain": "www.example3.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ },
+ {
+ "domain": "www.example.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 82 days on 10/28/20."
+ },
+ {
+ "domain": "www.example4.com",
+ "status": "success",
+ "text": "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ },
+ {
+ "domain": "example4.com",
+ "status": "not-applicable",
+ "text": "The domain's website is hosted elsewhere."
+ },
+ {
+ "domain": "www.example6.com",
+ "status": "not-applicable",
+ "text": "The domain's website is hosted elsewhere."
+ },
+ {
+ "domain": "example2.com",
+ "status": "not-applicable",
+ "text": "The domain's website is hosted elsewhere."
+ },
+ {
+ "domain": "example.com",
+ "status": "not-applicable",
+ "text": "The domain's website is hosted elsewhere."
+ },
+ {
+ "domain": "example3.com",
+ "status": "not-applicable",
+ "text": "The domain's website is hosted elsewhere."
+ }
+ ]
+ }
+}
diff --git a/src/api/mocks/ssl/data/installSSLCertificate.json b/src/api/mocks/ssl/data/installSSLCertificate.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/ssl/data/installSSLCertificate.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/ssl/data/provisionSSLCertificates.json b/src/api/mocks/ssl/data/provisionSSLCertificates.json
new file mode 100644
index 0000000..503cfde
--- /dev/null
+++ b/src/api/mocks/ssl/data/provisionSSLCertificates.json
@@ -0,0 +1,13 @@
+{
+ "response": {
+ "requests": [
+ {
+ "log": [
+ "The domain name does not resolve to this machine: [Not Set] (A), [Not Set] (AAAA)."
+ ],
+ "result": "installed",
+ "domains": ["example.com"]
+ }
+ ]
+ }
+}
diff --git a/src/api/mocks/ssl/index.ts b/src/api/mocks/ssl/index.ts
new file mode 100644
index 0000000..539003d
--- /dev/null
+++ b/src/api/mocks/ssl/index.ts
@@ -0,0 +1,21 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { Mocks } from '../types';
+import generateSSLCSR from './data/generateSSLCSR.json';
+import getSSLStatus from './data/getSSLStatus.json';
+import installSSLCertificate from './data/installSSLCertificate.json';
+import provisionSSLCertificates from './data/provisionSSLCertificates.json';
+
+export const ssl: Mocks = {
+ '/admin/ssl/status': {
+ get: getSSLStatus.response,
+ },
+ 'express:/admin/ssl/csr/:domain': {
+ post: generateSSLCSR.response,
+ },
+ '/admin/ssl/install': {
+ post: installSSLCertificate.response,
+ },
+ '/admin/ssl/provision': {
+ post: provisionSSLCertificates.response,
+ },
+};
diff --git a/src/api/mocks/system/data/getSystemBackupConfig.json b/src/api/mocks/system/data/getSystemBackupConfig.json
new file mode 100644
index 0000000..31d6500
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemBackupConfig.json
@@ -0,0 +1,11 @@
+{
+ "response": {
+ "enc_pw_file": "/home/user-data/backup/secret_key.txt",
+ "file_target_directory": "/home/user-data/backup/encrypted",
+ "min_age_in_days": 3,
+ "ssh_pub_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDb root@box.example.com\\n",
+ "target": "s3://s3.eu-central-1.amazonaws.com/box-example-com",
+ "target_user": "string",
+ "target_pass": "string"
+ }
+}
diff --git a/src/api/mocks/system/data/getSystemBackupStatus.json b/src/api/mocks/system/data/getSystemBackupStatus.json
new file mode 100644
index 0000000..69234ed
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemBackupStatus.json
@@ -0,0 +1,286 @@
+{
+ "response": {
+ "backups": [
+ {
+ "date": "20200806T023704Z",
+ "date_delta": "8 hours, 10 minutes",
+ "date_str": "2020-08-06 03:37:04 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 4815926,
+ "volumes": 1
+ },
+ {
+ "date": "20200805T023706Z",
+ "date_delta": "1 day, 8 hours",
+ "date_str": "2020-08-05 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 2095573,
+ "volumes": 1
+ },
+ {
+ "date": "20200804T023706Z",
+ "date_delta": "2 days, 8 hours",
+ "date_str": "2020-08-04 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 159837,
+ "volumes": 1
+ },
+ {
+ "date": "20200803T023708Z",
+ "date_delta": "3 days, 8 hours",
+ "date_str": "2020-08-03 03:37:08 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 149769,
+ "volumes": 1
+ },
+ {
+ "date": "20200802T023705Z",
+ "date_delta": "4 days, 8 hours",
+ "date_str": "2020-08-02 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 150150,
+ "volumes": 1
+ },
+ {
+ "date": "20200801T023706Z",
+ "date_delta": "5 days, 8 hours",
+ "date_str": "2020-08-01 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 125332,
+ "volumes": 1
+ },
+ {
+ "date": "20200731T023705Z",
+ "date_delta": "6 days, 8 hours",
+ "date_str": "2020-07-31 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 386284,
+ "volumes": 1
+ },
+ {
+ "date": "20200730T023705Z",
+ "date_delta": "7 days",
+ "date_str": "2020-07-30 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 976011,
+ "volumes": 1
+ },
+ {
+ "date": "20200729T023705Z",
+ "date_delta": "8 days",
+ "date_str": "2020-07-29 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 115590,
+ "volumes": 1
+ },
+ {
+ "date": "20200728T023705Z",
+ "date_delta": "9 days",
+ "date_str": "2020-07-28 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 114946,
+ "volumes": 1
+ },
+ {
+ "date": "20200727T023707Z",
+ "date_delta": "10 days",
+ "date_str": "2020-07-27 03:37:07 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 120222,
+ "volumes": 1
+ },
+ {
+ "date": "20200726T023706Z",
+ "date_delta": "11 days",
+ "date_str": "2020-07-26 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 756060,
+ "volumes": 1
+ },
+ {
+ "date": "20200725T023705Z",
+ "date_delta": "12 days",
+ "date_str": "2020-07-25 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 190782,
+ "volumes": 1
+ },
+ {
+ "date": "20200724T023707Z",
+ "date_delta": "13 days",
+ "date_str": "2020-07-24 03:37:07 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 101592,
+ "volumes": 1
+ },
+ {
+ "date": "20200723T023705Z",
+ "date_delta": "14 days",
+ "date_str": "2020-07-23 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 861692,
+ "volumes": 1
+ },
+ {
+ "date": "20200722T023706Z",
+ "date_delta": "15 days",
+ "date_str": "2020-07-22 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 176231,
+ "volumes": 1
+ },
+ {
+ "date": "20200721T023707Z",
+ "date_delta": "16 days",
+ "date_str": "2020-07-21 03:37:07 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 159684,
+ "volumes": 1
+ },
+ {
+ "date": "20200720T023708Z",
+ "date_delta": "17 days",
+ "date_str": "2020-07-20 03:37:08 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 98158,
+ "volumes": 1
+ },
+ {
+ "date": "20200719T023705Z",
+ "date_delta": "18 days",
+ "date_str": "2020-07-19 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 528488,
+ "volumes": 1
+ },
+ {
+ "date": "20200718T023706Z",
+ "date_delta": "19 days",
+ "date_str": "2020-07-18 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 117949,
+ "volumes": 1
+ },
+ {
+ "date": "20200717T023705Z",
+ "date_delta": "20 days",
+ "date_str": "2020-07-17 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 129689,
+ "volumes": 1
+ },
+ {
+ "date": "20200716T023705Z",
+ "date_delta": "21 days",
+ "date_str": "2020-07-16 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 433329,
+ "volumes": 1
+ },
+ {
+ "date": "20200715T023705Z",
+ "date_delta": "22 days",
+ "date_str": "2020-07-15 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 77562,
+ "volumes": 1
+ },
+ {
+ "date": "20200714T023705Z",
+ "date_delta": "23 days",
+ "date_str": "2020-07-14 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 1735603,
+ "volumes": 1
+ },
+ {
+ "date": "20200713T023707Z",
+ "date_delta": "24 days",
+ "date_str": "2020-07-13 03:37:07 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 1382637,
+ "volumes": 1
+ },
+ {
+ "date": "20200712T023705Z",
+ "date_delta": "25 days",
+ "date_str": "2020-07-12 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 1504319,
+ "volumes": 1
+ },
+ {
+ "date": "20200711T023704Z",
+ "date_delta": "26 days",
+ "date_str": "2020-07-11 03:37:04 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 1193826,
+ "volumes": 1
+ },
+ {
+ "date": "20200710T023706Z",
+ "date_delta": "27 days",
+ "date_str": "2020-07-10 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 74991,
+ "volumes": 1
+ },
+ {
+ "date": "20200709T023705Z",
+ "date_delta": "28 days",
+ "date_str": "2020-07-09 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 909140,
+ "volumes": 1
+ },
+ {
+ "date": "20200708T023705Z",
+ "date_delta": "29 days",
+ "date_str": "2020-07-08 03:37:05 BST",
+ "deleted_in": "approx. 3 days",
+ "full": false,
+ "size": 999924,
+ "volumes": 1
+ },
+ {
+ "date": "20200707T023706Z",
+ "date_delta": "30 days",
+ "date_str": "2020-07-07 03:37:06 BST",
+ "deleted_in": "approx. 3 days",
+ "full": true,
+ "size": 847719844,
+ "volumes": 4
+ }
+ ],
+ "unmatched_file_size": 0
+ }
+}
diff --git a/src/api/mocks/system/data/getSystemPrivacyStatus.json b/src/api/mocks/system/data/getSystemPrivacyStatus.json
new file mode 100644
index 0000000..2d5b2d4
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemPrivacyStatus.json
@@ -0,0 +1,3 @@
+{
+ "response": false
+}
diff --git a/src/api/mocks/system/data/getSystemRebootStatus.json b/src/api/mocks/system/data/getSystemRebootStatus.json
new file mode 100644
index 0000000..2d5b2d4
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemRebootStatus.json
@@ -0,0 +1,3 @@
+{
+ "response": false
+}
diff --git a/src/api/mocks/system/data/getSystemStatus.json b/src/api/mocks/system/data/getSystemStatus.json
new file mode 100644
index 0000000..d47545c
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemStatus.json
@@ -0,0 +1,933 @@
+{
+ "response": [
+ {
+ "extra": [],
+ "text": "System",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "All system services are running.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "The SSH server on this machine permits password-based login. A more secure\n\t\t\tway to log in is using a public key. Add your SSH public key to $HOME/.ssh/authorized_keys, check\n\t\t\tthat you can log in without a password, set the option 'PasswordAuthentication no' in\n\t\t\t/etc/ssh/sshd_config, and then restart the openssh via 'sudo service ssh restart'.",
+ "type": "error"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": "libnss-systemd (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "libsystemd0 (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "libpam-systemd (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "systemd (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "udev (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "libudev1 (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "kmod (24-1ubuntu3.5)"
+ },
+ {
+ "monospace": false,
+ "text": "libkmod2 (24-1ubuntu3.5)"
+ },
+ {
+ "monospace": false,
+ "text": "systemd-sysv (237-3ubuntu10.42)"
+ },
+ {
+ "monospace": false,
+ "text": "ntp (1:4.2.8p10+dfsg-5ubuntu7.2)"
+ },
+ {
+ "monospace": false,
+ "text": "iproute2 (4.15.0-2ubuntu1.2)"
+ }
+ ],
+ "text": "There are 11 software packages that can be updated.",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "A new version of Mail-in-a-Box is available. You are running version v0.46. The latest version is v0.47. For upgrade instructions, see https://mailinabox.email. ",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "System administrator address exists as a mail alias. [administrator@box.example.com \u21a6 admin@example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "The disk has 11.20 GB space remaining.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "System memory is 64% free.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Network",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Firewall is active.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Outbound mail (SMTP port 25) is not blocked.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "IP address is not blacklisted by zen.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "box.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameserver glue records are correct at registrar. [ns1/ns2.box.example.com \u21a6 10.11.12.13]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to box's IP address. [box.example.com \u21a6 10.11.12.13 / 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Reverse DNS is set correctly at ISP. [10.11.12.13 / 8a01:8f8:8c1c:808a::1 \u21a6 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "The DANE TLSA record for incoming mail is correct (_25._tcp.box.example.com).",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Hostmaster contact address exists as a mail alias. [hostmaster@box.example.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [box.example.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Postmaster contact address exists as a mail alias. [postmaster@box.example.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 82 days on 10/28/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.box.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.box.example.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.box.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.box.example.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameservers are set correctly at registrar. [ns1.box.example.com; ns2.box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Postmaster contact address exists as a mail alias. [postmaster@example.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Web has been disabled for this domain because you have set a custom DNS record.",
+ "type": "warning"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 88abc849f4a95fc90ac37d3cad5a0cfb0cb2e77fac80f268e1b23fdf7899c83"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example.com.\t3600\tIN\tDS\t5703 7 2 88abc849f4a95fc90ac37d3cad5a0cfb0cb2e77fac80f268e1b23fdf7899c83"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.example.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.example.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "www.example.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [www.example.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 82 days on 10/28/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "example2.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameservers are set correctly at registrar. [ns1.box.example.com; ns2.box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example2.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Postmaster contact address exists as a mail alias. [postmaster@example2.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Web has been disabled for this domain because you have set a custom DNS record.",
+ "type": "warning"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 8888d50ff41e5c5ecc884ce939101a35b0148a2efac375f04369f9aeee3d"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example2.com.\t3600\tIN\tDS\t5703 7 2 8888d50ff41e5c5ecc884ce939101a35b0148a2efac375f04369f9aeee3d"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example2.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.example2.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example2.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.example2.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "www.example2.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [www.example2.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 54 days on 09/30/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "example3.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameservers are set correctly at registrar. [ns1.box.example.com; ns2.box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example3.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Postmaster contact address exists as a mail alias. [postmaster@example3.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Web has been disabled for this domain because you have set a custom DNS record.",
+ "type": "warning"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 888871077937a9d02c0e6916c317e28e9f9753698bc227ce58a53599243b442e"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example3.com.\t3600\tIN\tDS\t5703 7 2 888871077937a9d02c0e6916c317e28e9f9753698bc227ce58a53599243b442e"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example3.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.example3.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 46 days on 09/22/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example3.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.example3.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 46 days on 09/22/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "www.example3.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [www.example3.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 46 days on 09/22/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "example4.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "The nameservers set on this domain are incorrect. They are currently ns17.domaincontrol.com; ns18.domaincontrol.com. Use your domain name registrar's\n\t\t\tcontrol panel to set the nameservers to ns1.box.example.com; ns2.box.example.com.",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example4.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "This domain should resolve to your box's IP address (A 10.11.12.13) if you would like the box to serve\n\t\t\t\t\twebmail or a website on this domain. The domain currently resolves to 116.203.79.11 in public DNS. It may take several hours for\n\t\t\t\t\tpublic DNS to update after a change. This problem may result from other issues listed here.",
+ "type": "error"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 88886b2266e2e2119c6c71586e915a33853129f7caa62639c0c32e7840470c7b"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example4.com.\t3600\tIN\tDS\t5703 7 2 88886b2266e2e2119c6c71586e915a33853129f7caa62639c0c32e7840470c7b"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example4.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "This domain should resolve to your box's IP address (A 10.11.12.13) if you would like the box to serve\n\t\t\t\t\twebmail or a website on this domain. The domain currently resolves to [Not Set] in public DNS. It may take several hours for\n\t\t\t\t\tpublic DNS to update after a change. This problem may result from other issues listed here.",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example4.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "This domain should resolve to your box's IP address (A 10.11.12.13) if you would like the box to serve\n\t\t\t\t\twebmail or a website on this domain. The domain currently resolves to [Not Set] in public DNS. It may take several hours for\n\t\t\t\t\tpublic DNS to update after a change. This problem may result from other issues listed here.",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "www.example4.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "This domain should resolve to your box's IP address (A 10.11.12.13) if you would like the box to serve\n\t\t\t\t\twebmail or a website on this domain. The domain currently resolves to 116.203.79.11 in public DNS. It may take several hours for\n\t\t\t\t\tpublic DNS to update after a change. This problem may result from other issues listed here.",
+ "type": "error"
+ },
+ {
+ "extra": [],
+ "text": "example5.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameservers are set correctly at registrar. [ns1.box.example.com; ns2.box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example5.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [example5.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 26 days on 09/02/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "A redirect from 'www.example5.com' has been disabled for this domain because you have set a custom DNS record on the www subdomain.",
+ "type": "warning"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 8888f96fe79297d2065a137b0bf00e63159d57678074083031e58afd9d98fdcf"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example5.com.\t3600\tIN\tDS\t5703 7 2 8888f96fe79297d2065a137b0bf00e63159d57678074083031e58afd9d98fdcf"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example5.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.example5.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example5.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.example5.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 72 days on 10/18/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "example6.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Nameservers are set correctly at registrar. [ns1.box.example.com; ns2.box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain's email is directed to this domain. [example6.com \u21a6 10 box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Postmaster contact address exists as a mail alias. [postmaster@example6.com \u21a6 administrator@box.example.com]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Domain is not blacklisted by dbl.spamhaus.org.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "Web has been disabled for this domain because you have set a custom DNS record.",
+ "type": "warning"
+ },
+ {
+ "extra": [
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Key Tag: 5703"
+ },
+ {
+ "monospace": false,
+ "text": "Key Flags: KSK"
+ },
+ {
+ "monospace": false,
+ "text": "Algorithm: 7 / RSASHA1-NSEC3-SHA1"
+ },
+ {
+ "monospace": false,
+ "text": "Digest Type: 2 / SHA-256"
+ },
+ {
+ "monospace": false,
+ "text": "Digest: 8888803d3e5960c65aa6ed3fa7f22518050d6549cd458b2299f3d36bb095b4f1"
+ },
+ {
+ "monospace": false,
+ "text": "Public Key: "
+ },
+ {
+ "monospace": true,
+ "text": "88888Z2R/E6NTiVhHEf6gAVsk/c4eFfAd5rAfvSCMYLTlkfNBJlyKPj8z0uMkANxSRlI/8888HLSRh3UPSrJPFXBpy38PDXkW/Mu/hofCh7gI0szI7dkZ64QCaFMkKzsHHdcoXLXlca6tFZTr6Il2VioyD7X8pLD4wr0OrI+IYrcqxNtsNGT6EB7kLtYfM/JLi/RpqirY2CEAR0kcho5whxixmY4mx/6INj86BIp8ZMeR9mtZeZfwCRktaeKeJ3Rzzin8SPv+ZwU7M0Sxn8pvISddrWqKvYNaKBJKnkyHIKnACF6PZ8wGd6s5k7Gu9c2XSyO1d8+5rBAy1eMml0rfje2ne/8="
+ },
+ {
+ "monospace": false,
+ "text": ""
+ },
+ {
+ "monospace": false,
+ "text": "Bulk/Record Format:"
+ },
+ {
+ "monospace": false,
+ "text": "example6.com.\t3600\tIN\tDS\t5703 7 2 8888803d3e5960c65aa6ed3fa7f22518050d6549cd458b2299f3d36bb095b4f1"
+ },
+ {
+ "monospace": false,
+ "text": ""
+ }
+ ],
+ "text": "This domain's DNSSEC DS record is not set. The DS record is optional. The DS record activates DNSSEC.\n\t\t\t\tTo set a DS record, you must follow the instructions provided by your domain name registrar and provide to them this information:",
+ "type": "warning"
+ },
+ {
+ "extra": [],
+ "text": "autoconfig.example6.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autoconfig.example6.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 53 days on 09/29/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "autodiscover.example6.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [autodiscover.example6.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 53 days on 09/29/20.",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "www.example6.com",
+ "type": "heading"
+ },
+ {
+ "extra": [],
+ "text": "Domain resolves to this box's IP address. [www.example6.com \u21a6 10.11.12.13; 8a01:8f8:8c1c:808a::1]",
+ "type": "ok"
+ },
+ {
+ "extra": [],
+ "text": "TLS (SSL) certificate is signed & valid. The certificate expires in 53 days on 09/29/20.",
+ "type": "ok"
+ }
+ ]
+}
diff --git a/src/api/mocks/system/data/getSystemUpdates.json b/src/api/mocks/system/data/getSystemUpdates.json
new file mode 100644
index 0000000..f2e201b
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemUpdates.json
@@ -0,0 +1,3 @@
+{
+ "response": "libgnutls30 (3.5.18-1ubuntu1.4)\nlibxau6 (1:1.0.8-1ubuntu1)"
+}
diff --git a/src/api/mocks/system/data/getSystemUpstreamVersion.json b/src/api/mocks/system/data/getSystemUpstreamVersion.json
new file mode 100644
index 0000000..00c98d2
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemUpstreamVersion.json
@@ -0,0 +1,3 @@
+{
+ "response": "v0.47"
+}
diff --git a/src/api/mocks/system/data/getSystemVersion.json b/src/api/mocks/system/data/getSystemVersion.json
new file mode 100644
index 0000000..50ab012
--- /dev/null
+++ b/src/api/mocks/system/data/getSystemVersion.json
@@ -0,0 +1,3 @@
+{
+ "response": "v0.46"
+}
diff --git a/src/api/mocks/system/data/rebootSystem.json b/src/api/mocks/system/data/rebootSystem.json
new file mode 100644
index 0000000..50a8f61
--- /dev/null
+++ b/src/api/mocks/system/data/rebootSystem.json
@@ -0,0 +1,3 @@
+{
+ "response": "No reboot is required, so it is not allowed."
+}
diff --git a/src/api/mocks/system/data/updateSystemBackupConfig.json b/src/api/mocks/system/data/updateSystemBackupConfig.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/system/data/updateSystemBackupConfig.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/system/data/updateSystemPackages.json b/src/api/mocks/system/data/updateSystemPackages.json
new file mode 100644
index 0000000..8be9da7
--- /dev/null
+++ b/src/api/mocks/system/data/updateSystemPackages.json
@@ -0,0 +1,3 @@
+{
+ "response": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nCalculating upgrade...\nThe following packages will be upgraded:\n cloud-init grub-common grub-pc grub-pc-bin grub2-common libgnutls30\n libldap-2.4-2 libldap-common libxau6 linux-firmware python3-distupgrade\n qemu-guest-agent sosreport ubuntu-release-upgrader-core\n14 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\nNeed to get 79.9 MB of archives.\nAfter this operation, 3893 kB of additional disk space will be used.\nGet:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libgnutls30 amd64 3.5.18-1ubuntu1.4 [645 kB]\nPreconfiguring packages ...\nFetched 79.9 MB in 2s (52.4 MB/s)\n(Reading database ... 48457 files and directories currently installed.)"
+}
diff --git a/src/api/mocks/system/data/updateSystemPrivacy.json b/src/api/mocks/system/data/updateSystemPrivacy.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/system/data/updateSystemPrivacy.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/system/index.ts b/src/api/mocks/system/index.ts
new file mode 100644
index 0000000..f943cd0
--- /dev/null
+++ b/src/api/mocks/system/index.ts
@@ -0,0 +1,47 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { Mocks } from '../types';
+import getSystemBackupConfig from './data/getSystemBackupConfig.json';
+import getSystemBackupStatus from './data/getSystemBackupStatus.json';
+import getSystemPrivacyStatus from './data/getSystemPrivacyStatus.json';
+import getSystemRebootStatus from './data/getSystemRebootStatus.json';
+import getSystemStatus from './data/getSystemStatus.json';
+import getSystemUpdates from './data/getSystemUpdates.json';
+import getSystemUpstreamVersion from './data/getSystemUpstreamVersion.json';
+import getSystemVersion from './data/getSystemVersion.json';
+import rebootSystem from './data/rebootSystem.json';
+import updateSystemBackupConfig from './data/updateSystemBackupConfig.json';
+import updateSystemPackages from './data/updateSystemPackages.json';
+import updateSystemPrivacy from './data/updateSystemPrivacy.json';
+
+export const system: Mocks = {
+ 'admin/system/status': {
+ post: getSystemStatus.response,
+ },
+ 'admin/system/version': {
+ get: getSystemVersion.response,
+ },
+ 'admin/system/latest-updstream-version': {
+ post: getSystemUpstreamVersion.response,
+ },
+ 'admin/system/updates': {
+ get: getSystemUpdates.response,
+ },
+ 'admin/system/update-packages': {
+ post: updateSystemPackages.response,
+ },
+ 'admin/system/privacy': {
+ get: getSystemPrivacyStatus.response,
+ post: updateSystemPrivacy.response,
+ },
+ 'admin/system/reboot': {
+ get: getSystemRebootStatus.response,
+ post: rebootSystem.response,
+ },
+ 'admin/system/backup/status': {
+ get: getSystemBackupStatus.response,
+ },
+ 'admin/system/backup/config': {
+ get: getSystemBackupConfig.response,
+ post: updateSystemBackupConfig.response,
+ },
+};
diff --git a/src/api/mocks/types.ts b/src/api/mocks/types.ts
new file mode 100644
index 0000000..f2e9ea2
--- /dev/null
+++ b/src/api/mocks/types.ts
@@ -0,0 +1,7 @@
+import { MockResponse, MockResponseFunction } from 'fetch-mock';
+
+export interface Mocks {
+ [url: string]: {
+ [method: string]: MockResponse | MockResponseFunction;
+ };
+}
diff --git a/src/api/mocks/user/data/getMe.json b/src/api/mocks/user/data/getMe.json
new file mode 100644
index 0000000..13e4ac7
--- /dev/null
+++ b/src/api/mocks/user/data/getMe.json
@@ -0,0 +1,8 @@
+{
+ "response": {
+ "api_key": "1a2b3c4d5e6f7g8h9i0j",
+ "email": "user@example.com",
+ "privileges": ["admin"],
+ "status": "ok"
+ }
+}
diff --git a/src/api/mocks/user/index.ts b/src/api/mocks/user/index.ts
new file mode 100644
index 0000000..30f9252
--- /dev/null
+++ b/src/api/mocks/user/index.ts
@@ -0,0 +1,9 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { Mocks } from '../types';
+import getMe from './data/getMe.json';
+
+export const user: Mocks = {
+ 'admin/me': {
+ get: getMe.response,
+ },
+};
diff --git a/src/api/mocks/users/data/addMailAlias.json b/src/api/mocks/users/data/addMailAlias.json
new file mode 100644
index 0000000..43b3593
--- /dev/null
+++ b/src/api/mocks/users/data/addMailAlias.json
@@ -0,0 +1,3 @@
+{
+ "response": "alias added"
+}
diff --git a/src/api/mocks/users/data/addMailUser.json b/src/api/mocks/users/data/addMailUser.json
new file mode 100644
index 0000000..20ec753
--- /dev/null
+++ b/src/api/mocks/users/data/addMailUser.json
@@ -0,0 +1,3 @@
+{
+ "response": "mail user added\nupdated DNS: OpenDKIM configuration"
+}
diff --git a/src/api/mocks/users/data/addMailUserPrivilege.json b/src/api/mocks/users/data/addMailUserPrivilege.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/users/data/addMailUserPrivilege.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/users/data/getMailAliases.json b/src/api/mocks/users/data/getMailAliases.json
new file mode 100644
index 0000000..c1bfea1
--- /dev/null
+++ b/src/api/mocks/users/data/getMailAliases.json
@@ -0,0 +1,221 @@
+{
+ "response": [
+ {
+ "aliases": [
+ {
+ "address": "abuse@box.example.com",
+ "address_display": "abuse@box.example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@box.example.com",
+ "address_display": "admin@box.example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "administrator@box.example.com",
+ "address_display": "administrator@box.example.com",
+ "forwards_to": ["admin@example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "hostmaster@box.example.com",
+ "address_display": "hostmaster@box.example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@box.example.com",
+ "address_display": "postmaster@box.example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "box.example.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "abuse@example.com",
+ "address_display": "abuse@example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example.com",
+ "address_display": "postmaster@example.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "abuse@example2.com",
+ "address_display": "abuse@example2.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@example2.com",
+ "address_display": "admin@example2.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example2.com",
+ "address_display": "postmaster@example2.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example2.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "abuse@example3.com",
+ "address_display": "abuse@example3.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@example3.com",
+ "address_display": "admin@example3.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example3.com",
+ "address_display": "postmaster@example3.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example3.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "@example4.com",
+ "address_display": "@example4.com",
+ "forwards_to": ["mailer@example5.com"],
+ "permitted_senders": null,
+ "required": false
+ },
+ {
+ "address": "abuse@example4.com",
+ "address_display": "abuse@example4.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@example4.com",
+ "address_display": "admin@example4.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example4.com",
+ "address_display": "postmaster@example4.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example4.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "@example5.com",
+ "address_display": "@example5.com",
+ "forwards_to": ["mailer@example5.com"],
+ "permitted_senders": null,
+ "required": false
+ },
+ {
+ "address": "mailer@example5.com",
+ "address_display": "mailer@example5.com",
+ "forwards_to": ["admin@example.com"],
+ "permitted_senders": null,
+ "required": false
+ },
+ {
+ "address": "www-data@example5.com",
+ "address_display": "www-data@example5.com",
+ "forwards_to": ["mailer@example5.com"],
+ "permitted_senders": null,
+ "required": false
+ },
+ {
+ "address": "abuse@example5.com",
+ "address_display": "abuse@example5.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@example5.com",
+ "address_display": "admin@example5.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example5.com",
+ "address_display": "postmaster@example5.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example5.com"
+ },
+ {
+ "aliases": [
+ {
+ "address": "abuse@example6.com",
+ "address_display": "abuse@example6.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "admin@example6.com",
+ "address_display": "admin@example6.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ },
+ {
+ "address": "postmaster@example6.com",
+ "address_display": "postmaster@example6.com",
+ "forwards_to": ["administrator@box.example.com"],
+ "permitted_senders": null,
+ "required": true
+ }
+ ],
+ "domain": "example6.com"
+ }
+ ]
+}
diff --git a/src/api/mocks/users/data/getMailDomains.json b/src/api/mocks/users/data/getMailDomains.json
new file mode 100644
index 0000000..aba6efa
--- /dev/null
+++ b/src/api/mocks/users/data/getMailDomains.json
@@ -0,0 +1,3 @@
+{
+ "response": "example1.com\nexample2.com"
+}
diff --git a/src/api/mocks/users/data/getMailUserPrivileges.json b/src/api/mocks/users/data/getMailUserPrivileges.json
new file mode 100644
index 0000000..2f30103
--- /dev/null
+++ b/src/api/mocks/users/data/getMailUserPrivileges.json
@@ -0,0 +1,3 @@
+{
+ "response": "admin"
+}
diff --git a/src/api/mocks/users/data/getMailUsers.json b/src/api/mocks/users/data/getMailUsers.json
new file mode 100644
index 0000000..f35394f
--- /dev/null
+++ b/src/api/mocks/users/data/getMailUsers.json
@@ -0,0 +1,80 @@
+{
+ "response": [
+ {
+ "domain": "example.com",
+ "users": [
+ {
+ "email": "admin@example.com",
+ "privileges": ["admin"],
+ "status": "active"
+ },
+ {
+ "email": "root@example.com",
+ "privileges": [],
+ "status": "active"
+ }
+ ]
+ },
+ {
+ "domain": "example2.com",
+ "users": [
+ {
+ "email": "richard@example2.com",
+ "privileges": ["admin"],
+ "status": "active"
+ }
+ ]
+ },
+ {
+ "domain": "example3.com",
+ "users": [
+ {
+ "email": "info@example3.com",
+ "privileges": [],
+ "status": "active"
+ }
+ ]
+ },
+ {
+ "domain": "example4.com",
+ "users": [
+ {
+ "email": "info@example4.com",
+ "privileges": [],
+ "status": "active"
+ }
+ ]
+ },
+ {
+ "domain": "example5.com",
+ "users": [
+ {
+ "email": "mailer@example5.com",
+ "privileges": ["admin"],
+ "status": "active"
+ },
+ {
+ "email": "richard@example5.com",
+ "privileges": ["admin"],
+ "status": "active"
+ },
+ {
+ "email": "www-data@example5.com",
+ "mailbox": "/home/user-data/mail/mailboxes/example5.com/www-data",
+ "privileges": [],
+ "status": "inactive"
+ }
+ ]
+ },
+ {
+ "domain": "example6.com",
+ "users": [
+ {
+ "email": "info@example6.com",
+ "privileges": ["admin"],
+ "status": "active"
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/api/mocks/users/data/removeMailAlias.json b/src/api/mocks/users/data/removeMailAlias.json
new file mode 100644
index 0000000..bd9894f
--- /dev/null
+++ b/src/api/mocks/users/data/removeMailAlias.json
@@ -0,0 +1,3 @@
+{
+ "response": "alias removed"
+}
diff --git a/src/api/mocks/users/data/removeMailUser.json b/src/api/mocks/users/data/removeMailUser.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/users/data/removeMailUser.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/users/data/removeMailUserPrivilege.json b/src/api/mocks/users/data/removeMailUserPrivilege.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/users/data/removeMailUserPrivilege.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/users/data/setMailUserPassword.json b/src/api/mocks/users/data/setMailUserPassword.json
new file mode 100644
index 0000000..83dd17f
--- /dev/null
+++ b/src/api/mocks/users/data/setMailUserPassword.json
@@ -0,0 +1,3 @@
+{
+ "response": "OK"
+}
diff --git a/src/api/mocks/users/data/updateMailAlias.json b/src/api/mocks/users/data/updateMailAlias.json
new file mode 100644
index 0000000..642412f
--- /dev/null
+++ b/src/api/mocks/users/data/updateMailAlias.json
@@ -0,0 +1,3 @@
+{
+ "response": "alias updated"
+}
diff --git a/src/api/mocks/users/index.ts b/src/api/mocks/users/index.ts
new file mode 100644
index 0000000..ed0da22
--- /dev/null
+++ b/src/api/mocks/users/index.ts
@@ -0,0 +1,178 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { MockRequest, MockResponse } from 'fetch-mock';
+import { MailUserPrivilege, MailUserStatus } from 'mailinabox-api';
+import { Mocks } from '../types';
+import addMailAlias from './data/addMailAlias.json';
+import addMailUser from './data/addMailUser.json';
+import addMailUserPrivilege from './data/addMailUserPrivilege.json';
+import getMailAliases from './data/getMailAliases.json';
+import getMailDomains from './data/getMailDomains.json';
+import getMailUserPrivileges from './data/getMailUserPrivileges.json';
+import getMailUsers from './data/getMailUsers.json';
+import removeMailAlias from './data/removeMailAlias.json';
+import removeMailUser from './data/removeMailUser.json';
+import removeMailUserPrivilege from './data/removeMailUserPrivilege.json';
+import setMailUserPassword from './data/setMailUserPassword.json';
+import updateMailAlias from './data/updateMailAlias.json';
+
+export const users: Mocks = {
+ 'admin/mail/users?format=json': {
+ get: getMailUsers.response,
+ },
+ 'admin/mail/users/add': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const email = (opts.body as URLSearchParams).get('email') as string;
+ const privileges = (opts.body as URLSearchParams).get(
+ 'privileges'
+ ) as string;
+ const privilegesList =
+ privileges === MailUserPrivilege.Empty ? [] : [privileges];
+ const domain = email.split('@').pop() as string;
+ getMailUsers.response.push({
+ domain,
+ users: [
+ {
+ email,
+ privileges: privilegesList,
+ status: MailUserStatus.Active,
+ },
+ ],
+ });
+ return addMailUser.response;
+ },
+ },
+ 'admin/mail/users/remove': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const email = (opts.body as URLSearchParams).get('email') as string;
+ const userDomain = email.split('@').pop() as string;
+ const domainObject = getMailUsers.response.find((domain) => {
+ return domain.domain === userDomain;
+ });
+ const userIndex = domainObject!.users.findIndex(
+ (user) => user.email === email
+ );
+ domainObject!.users.splice(userIndex, 1);
+ if (!domainObject!.users.length) {
+ const domainIndex = getMailUsers.response.indexOf(domainObject!);
+ getMailUsers.response.splice(domainIndex, 1);
+ }
+ return removeMailUser.response;
+ },
+ },
+ 'admin/mail/users/privileges/remove': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const email = (opts.body as URLSearchParams).get('email') as string;
+ const privilege = (opts.body as URLSearchParams).get(
+ 'privilege'
+ ) as MailUserPrivilege;
+ const userDomain = email.split('@').pop() as string;
+ const domainObject = getMailUsers.response.find((domain) => {
+ return domain.domain === userDomain;
+ });
+ const user = domainObject!.users.find((user) => user.email === email);
+ const index = (user!.privileges as MailUserPrivilege[]).indexOf(
+ privilege
+ );
+ user!.privileges.splice(index, 1);
+ return removeMailUserPrivilege.response;
+ },
+ },
+ 'admin/mail/users/privileges/add': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const email = (opts.body as URLSearchParams).get('email') as string;
+ const privilege = (opts.body as URLSearchParams).get(
+ 'privilege'
+ ) as MailUserPrivilege;
+ const userDomain = email.split('@').pop() as string;
+ const domainObject = getMailUsers.response.find((domain) => {
+ return domain.domain === userDomain;
+ });
+ const user = domainObject!.users.find((user) => user.email === email);
+ (user!.privileges as MailUserPrivilege[]).push(privilege);
+ return addMailUserPrivilege.response;
+ },
+ },
+ 'admin/mail/users/password': {
+ post: setMailUserPassword.response,
+ },
+ 'admin/mail/users/privileges': {
+ get: getMailUserPrivileges.response,
+ },
+ 'admin/mail/domains': {
+ get: getMailDomains.response,
+ },
+ 'admin/mail/aliases?format=json': {
+ get: getMailAliases.response,
+ },
+ 'admin/mail/aliases/add': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const address = (opts.body as URLSearchParams).get('address') as string;
+ const updateIfExists = Number(
+ (opts.body as URLSearchParams).get('update_if_exists')
+ );
+ const forwardsTo = (opts.body as URLSearchParams).get(
+ 'forwards_to'
+ ) as string;
+ const permittedSenders = (opts.body as URLSearchParams).get(
+ 'permitted_senders'
+ ) as string;
+ const aliasDomain = address.split('@').pop() as string;
+ let domainObject = getMailAliases.response.find((domain) => {
+ return domain.domain === aliasDomain;
+ });
+ const forwardToList =
+ forwardsTo.indexOf(',') > -1
+ ? forwardsTo.split(',')
+ : forwardsTo.split('\n');
+ const permittedSendersList =
+ permittedSenders.indexOf(',') > -1
+ ? permittedSenders.split(',')
+ : permittedSenders.split('\n');
+ if (updateIfExists) {
+ const alias = domainObject!.aliases.find(
+ (alias) => alias.address === address
+ );
+ alias!.address = address;
+ alias!.address_display = address;
+ alias!.forwards_to = forwardToList;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ alias!.permitted_senders = permittedSendersList;
+ return updateMailAlias.response;
+ } else {
+ if (!domainObject) {
+ domainObject = { domain: aliasDomain, aliases: [] };
+ getMailAliases.response.push(domainObject);
+ }
+ domainObject!.aliases.push({
+ address,
+ address_display: address,
+ forwards_to: forwardToList,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ permitted_senders: permittedSendersList,
+ required: true,
+ });
+ return addMailAlias.response;
+ }
+ },
+ },
+ 'admin/mail/aliases/remove': {
+ post: (_url: string, opts: MockRequest): MockResponse => {
+ const address = (opts.body as URLSearchParams).get('address') as string;
+ const userDomain = address.split('@').pop() as string;
+ const domainObject = getMailAliases.response.find((domain) => {
+ return domain.domain === userDomain;
+ });
+ const aliasIndex = domainObject!.aliases.findIndex(
+ (alias) => alias.address === address
+ );
+ domainObject!.aliases.splice(aliasIndex, 1);
+ if (!domainObject!.aliases.length) {
+ const domainIndex = getMailAliases.response.indexOf(domainObject!);
+ getMailAliases.response.splice(domainIndex, 1);
+ }
+ return removeMailAlias.response;
+ },
+ },
+};
diff --git a/src/api/mocks/web/data/getWebDomains.json b/src/api/mocks/web/data/getWebDomains.json
new file mode 100644
index 0000000..6432e3d
--- /dev/null
+++ b/src/api/mocks/web/data/getWebDomains.json
@@ -0,0 +1,212 @@
+{
+ "response": [
+ {
+ "custom_root": "/home/user-data/www/box.example.com",
+ "domain": "box.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 82 days on 10/28/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.box.example.com",
+ "domain": "autoconfig.box.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.box.example.com",
+ "domain": "autodiscover.box.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example2.com",
+ "domain": "autoconfig.example2.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example3.com",
+ "domain": "autoconfig.example3.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example.com",
+ "domain": "autoconfig.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example4.com",
+ "domain": "autoconfig.example4.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example2.com",
+ "domain": "autodiscover.example2.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example3.com",
+ "domain": "autodiscover.example3.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example.com",
+ "domain": "autodiscover.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example4.com",
+ "domain": "autodiscover.example4.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/example5.com",
+ "domain": "example5.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": ["danger", "No certificate installed."],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example5.com",
+ "domain": "autoconfig.example5.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": ["danger", "No certificate installed."],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example5.com",
+ "domain": "autodiscover.example5.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": ["danger", "No certificate installed."],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/www.example5.com",
+ "domain": "www.example5.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": ["danger", "No certificate installed."],
+ "static_enabled": false
+ },
+ {
+ "custom_root": "/home/user-data/www/example6.com",
+ "domain": "example6.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 26 days on 09/02/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autoconfig.example6.com",
+ "domain": "autoconfig.example6.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/autodiscover.example6.com",
+ "domain": "autodiscover.example6.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 72 days on 10/18/20."
+ ],
+ "static_enabled": true
+ },
+ {
+ "custom_root": "/home/user-data/www/www.example2.com",
+ "domain": "www.example2.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 54 days on 09/30/20."
+ ],
+ "static_enabled": false
+ },
+ {
+ "custom_root": "/home/user-data/www/www.example3.com",
+ "domain": "www.example3.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 46 days on 09/22/20."
+ ],
+ "static_enabled": false
+ },
+ {
+ "custom_root": "/home/user-data/www/www.example.com",
+ "domain": "www.example.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 82 days on 10/28/20."
+ ],
+ "static_enabled": false
+ },
+ {
+ "custom_root": "/home/user-data/www/www.example4.com",
+ "domain": "www.example4.com",
+ "root": "/home/user-data/www/default",
+ "ssl_certificate": [
+ "success",
+ "Signed & valid. The certificate expires in 53 days on 09/29/20."
+ ],
+ "static_enabled": false
+ }
+ ]
+}
diff --git a/src/api/mocks/web/data/updateWeb.json b/src/api/mocks/web/data/updateWeb.json
new file mode 100644
index 0000000..cfa4793
--- /dev/null
+++ b/src/api/mocks/web/data/updateWeb.json
@@ -0,0 +1,3 @@
+{
+ "response": "web updated"
+}
diff --git a/src/api/mocks/web/index.ts b/src/api/mocks/web/index.ts
new file mode 100644
index 0000000..420a460
--- /dev/null
+++ b/src/api/mocks/web/index.ts
@@ -0,0 +1,13 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
+import { Mocks } from '../types';
+import getWebDomains from './data/getWebDomains.json';
+import updateWeb from './data/updateWeb.json';
+
+export const web: Mocks = {
+ 'admin/web/domains': {
+ get: getWebDomains.response,
+ },
+ 'admin/web/update': {
+ post: updateWeb.response,
+ },
+};
diff --git a/src/components/routes/MainRoute/WebRoute/WebRoute.tsx b/src/components/routes/MainRoute/WebRoute/WebRoute.tsx
index 21286e7..1d1fe4b 100644
--- a/src/components/routes/MainRoute/WebRoute/WebRoute.tsx
+++ b/src/components/routes/MainRoute/WebRoute/WebRoute.tsx
@@ -1,7 +1,7 @@
import { Link, PivotItem, Stack, Text } from '@fluentui/react';
import React, { useState } from 'react';
import { Route, Switch, useRouteMatch } from 'react-router-dom';
-import config from '../../../../config/index.json';
+import { config } from '../../../../config';
import { Body } from '../../../ui/Body/Body';
import { BodyBreadcrumb } from '../../../ui/BodyBreadcrumb/BodyBreadcrumb';
import { BodyPanel } from '../../../ui/BodyPanel/BodyPanel';
diff --git a/src/components/routes/MainRoute/mail/InstructionsRoute/InstructionsRoute.tsx b/src/components/routes/MainRoute/mail/InstructionsRoute/InstructionsRoute.tsx
index 184d5eb..543360c 100644
--- a/src/components/routes/MainRoute/mail/InstructionsRoute/InstructionsRoute.tsx
+++ b/src/components/routes/MainRoute/mail/InstructionsRoute/InstructionsRoute.tsx
@@ -8,7 +8,7 @@ import {
} from '@fluentui/react';
import { useId } from '@uifabric/react-hooks';
import React from 'react';
-import config from '../../../../../config/index.json';
+import { config } from '../../../../../config';
import { Body } from '../../../../ui/Body/Body';
import { BodyBreadcrumb } from '../../../../ui/BodyBreadcrumb/BodyBreadcrumb';
import { BodyPanel } from '../../../../ui/BodyPanel/BodyPanel';
diff --git a/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx b/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx
index 58b7065..f9f0365 100644
--- a/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx
+++ b/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx
@@ -15,7 +15,7 @@ import {
useLocation,
useRouteMatch,
} from 'react-router-dom';
-import config from '../../../../../config/index.json';
+import { config } from '../../../../../config';
import {
getSSLStatus,
resetSSLAction,
diff --git a/src/components/ui/BackupConfigure/BackupConfigure.tsx b/src/components/ui/BackupConfigure/BackupConfigure.tsx
index 163f4e8..9ee1346 100644
--- a/src/components/ui/BackupConfigure/BackupConfigure.tsx
+++ b/src/components/ui/BackupConfigure/BackupConfigure.tsx
@@ -19,7 +19,7 @@ import {
} from 'mailinabox-api';
import React, { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
import {
getStatus,
updateConfig,
diff --git a/src/components/ui/BackupConfigure/rsync/BackupConfigureRsync.tsx b/src/components/ui/BackupConfigure/rsync/BackupConfigureRsync.tsx
index ebe82d1..86347c4 100644
--- a/src/components/ui/BackupConfigure/rsync/BackupConfigureRsync.tsx
+++ b/src/components/ui/BackupConfigure/rsync/BackupConfigureRsync.tsx
@@ -1,6 +1,6 @@
import { TextField } from '@fluentui/react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import config from '../../../../config/index.json';
+import { config } from '../../../../config';
import {
onRenderTextFieldLabel,
textfieldWithLabelInfoStyles,
diff --git a/src/components/ui/Header/Header.tsx b/src/components/ui/Header/Header.tsx
index 94b56e3..b062abf 100644
--- a/src/components/ui/Header/Header.tsx
+++ b/src/components/ui/Header/Header.tsx
@@ -1,5 +1,6 @@
-import { getTheme, mergeStyles, Stack, Text } from '@fluentui/react';
+import { getTheme, Image, mergeStyles, Stack, Text } from '@fluentui/react';
import React from 'react';
+import logo from '../../../images/logo.png';
import { PrimaryNav } from '../PrimaryNav/PrimaryNav';
const className = mergeStyles({
@@ -32,6 +33,9 @@ export const Header: React.FunctionComponent = () => {
box.example.com
*/}
+
+
+
Mail-in-a-Box
diff --git a/src/components/ui/LoginHeader/LoginHeader.tsx b/src/components/ui/LoginHeader/LoginHeader.tsx
index c5db9d5..5ed49c4 100644
--- a/src/components/ui/LoginHeader/LoginHeader.tsx
+++ b/src/components/ui/LoginHeader/LoginHeader.tsx
@@ -1,6 +1,6 @@
import { Image, Stack, Text } from '@fluentui/react';
import React from 'react';
-import logo from './logo.png';
+import logo from '../../../images/logo.png';
export const LoginHeader: React.FunctionComponent = () => {
return (
diff --git a/src/components/ui/MailExchangeSettingsList/MailExchangeSettingsList.tsx b/src/components/ui/MailExchangeSettingsList/MailExchangeSettingsList.tsx
index 450ba5e..e9ee6c1 100644
--- a/src/components/ui/MailExchangeSettingsList/MailExchangeSettingsList.tsx
+++ b/src/components/ui/MailExchangeSettingsList/MailExchangeSettingsList.tsx
@@ -6,7 +6,7 @@ import {
SelectionMode,
} from '@fluentui/react';
import React from 'react';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
const columns: IColumn[] = [
{
diff --git a/src/components/ui/MailSettingsList/MailSettingsList.tsx b/src/components/ui/MailSettingsList/MailSettingsList.tsx
index 99aff82..a9c84d0 100644
--- a/src/components/ui/MailSettingsList/MailSettingsList.tsx
+++ b/src/components/ui/MailSettingsList/MailSettingsList.tsx
@@ -6,7 +6,7 @@ import {
SelectionMode,
} from '@fluentui/react';
import React from 'react';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
const columns: IColumn[] = [
{
key: 'column1',
diff --git a/src/components/ui/SyncListBrowser/SyncListBrowser.tsx b/src/components/ui/SyncListBrowser/SyncListBrowser.tsx
index 4320759..1271e65 100644
--- a/src/components/ui/SyncListBrowser/SyncListBrowser.tsx
+++ b/src/components/ui/SyncListBrowser/SyncListBrowser.tsx
@@ -9,7 +9,7 @@ import {
Text,
} from '@fluentui/react';
import React from 'react';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
const theme = getTheme();
diff --git a/src/components/ui/SyncListMobile/SyncListMobileSettings.tsx b/src/components/ui/SyncListMobile/SyncListMobileSettings.tsx
index da6961f..18d3a43 100644
--- a/src/components/ui/SyncListMobile/SyncListMobileSettings.tsx
+++ b/src/components/ui/SyncListMobile/SyncListMobileSettings.tsx
@@ -7,7 +7,7 @@ import {
Text,
} from '@fluentui/react';
import React from 'react';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
interface SyncListItem {
option: string;
diff --git a/src/components/ui/SystemStatusActions/SystemStatusActions.tsx b/src/components/ui/SystemStatusActions/SystemStatusActions.tsx
index d9fcd01..9afc872 100644
--- a/src/components/ui/SystemStatusActions/SystemStatusActions.tsx
+++ b/src/components/ui/SystemStatusActions/SystemStatusActions.tsx
@@ -11,12 +11,12 @@ export const SystemStatusActions: React.FunctionComponent = () => {
return (
<>
{!rebootStatus && (
-
+
No reboot is necessary.
)}
{rebootStatus && (
-
+
A reboot is required.
)}
diff --git a/src/components/ui/WebInstructions/WebInstructions.tsx b/src/components/ui/WebInstructions/WebInstructions.tsx
index f7ad730..b85226f 100644
--- a/src/components/ui/WebInstructions/WebInstructions.tsx
+++ b/src/components/ui/WebInstructions/WebInstructions.tsx
@@ -1,6 +1,6 @@
import { Link, Stack, Text } from '@fluentui/react';
import React from 'react';
-import config from '../../../config/index.json';
+import { config } from '../../../config';
import { MessageBar } from '../MessageBar/MessageBar';
export const WebInstructions: React.FunctionComponent = () => {
diff --git a/src/config/config.example.json b/src/config/config.example.json
new file mode 100644
index 0000000..7e7825e
--- /dev/null
+++ b/src/config/config.example.json
@@ -0,0 +1,4 @@
+{
+ "hostname": "box.example.com",
+ "mockApi": false
+}
diff --git a/src/config/index.example.json b/src/config/index.example.json
deleted file mode 100644
index 810da67..0000000
--- a/src/config/index.example.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "hostname": "box.example.com"
-}
diff --git a/src/config/index.ts b/src/config/index.ts
new file mode 100644
index 0000000..f23ab3b
--- /dev/null
+++ b/src/config/index.ts
@@ -0,0 +1,4 @@
+import configJson from './config.json';
+import { Config } from './types';
+
+export const config: Config = configJson;
diff --git a/src/config/types.ts b/src/config/types.ts
new file mode 100644
index 0000000..12f6e5a
--- /dev/null
+++ b/src/config/types.ts
@@ -0,0 +1,4 @@
+export interface Config {
+ hostname: string;
+ mockApi: boolean;
+}
diff --git a/src/components/ui/LoginHeader/logo.png b/src/images/logo.png
similarity index 100%
rename from src/components/ui/LoginHeader/logo.png
rename to src/images/logo.png
diff --git a/src/index.tsx b/src/index.tsx
index 8c3d9bd..83a1bc4 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,6 +3,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { App } from './components/ui/App/App';
+import { config } from './config';
import { store } from './store';
initializeIcons(/* optional base url */);
@@ -28,11 +29,24 @@ mergeStyles({
},
});
-ReactDOM.render(
-
-
-
-
- ,
- document.getElementById('app')
-);
+function renderApp(): void {
+ ReactDOM.render(
+
+
+
+
+ ,
+ document.getElementById('app')
+ );
+}
+
+if (config.mockApi) {
+ import('./api/mockApi').then(
+ () => renderApp(),
+ () => {
+ console.error('There was an error loading the mock api');
+ }
+ );
+} else {
+ renderApp();
+}
diff --git a/src/setupProxy.js b/src/setupProxy.js
index 51a835f..39d4f8b 100644
--- a/src/setupProxy.js
+++ b/src/setupProxy.js
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { createProxyMiddleware } = require('http-proxy-middleware');
-const config = require('./config');
+const config = require('./config/config.json');
module.exports = function (app) {
app.use(