Browse Source

Several changes:

* Add redirect mode (read more at http://on.loki/faq#redirect)
* Add server side host caching to reduce lag
* Add FAQs accordions listening to hash
* Fix not being able to register a subdomain
* Fix placeholder service file so it's like the readme says it is
master
massivebox 4 months ago
parent
commit
d778ac9507
  1. 6
      components/accordion.js
  2. 15
      components/addrecord.js
  3. 23
      components/layout.js
  4. 6
      onloki.service
  5. 387
      package-lock.json
  6. 5
      package.json
  7. 15
      pages/api/addrecord.js
  8. 2
      pages/api/resolve.js
  9. 40
      pages/faq.js
  10. 18
      pages/index.js
  11. 18
      pages/tos.js
  12. 7
      prisma/.env
  13. BIN
      prisma/schema.db
  14. 13
      prisma/schema.prisma
  15. 85
      server.js

6
components/accordion.js

@ -1,13 +1,13 @@
import React, { useState } from 'react';
const Accordion = ({ title, content }) => {
const Accordion = ({ acckey, title, content, hash }) => {
const [isActive, setIsActive] = useState(false);
const [isActive, setIsActive] = useState(acckey==hash);
return (
<div className="accordion-item">
<div className="accordion-title" onClick={() => setIsActive(!isActive)}>
<p>
<p id={acckey}>
<b>{title}</b>
<span style={{float: "right"}}><b>{isActive ? '-' : '+'}</b></span>
</p>

15
components/addrecord.js

@ -1,4 +1,5 @@
import React, { Component } from 'react';
import Link from 'next/link'
class AddRecordForm extends Component {
@ -9,6 +10,7 @@ class AddRecordForm extends Component {
message: "",
subdomain: "",
pointsto: "",
redirectmode: false
}
}
@ -24,14 +26,14 @@ class AddRecordForm extends Component {
let resp, data;
try {
resp = await fetch(
`http://on.loki/api/addrecord`,
`/api/addrecord`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ subdomain: this.state.subdomain, pointsto: this.state.pointsto }),
body: JSON.stringify({ subdomain: this.state.subdomain, pointsto: this.state.pointsto, redirect: this.state.redirectmode }),
}
);
data = await resp.json();
@ -70,8 +72,15 @@ class AddRecordForm extends Component {
/>.loki
<br />
<input
value={this.state.redirectmode}
onChange={(e) => this.setState({redirectmode: !this.state.redirectmode})}
type="checkbox"
/>Redirect Mode <Link href="/faq#redirect">(?)</Link>
<br />
<button type="submit">
Submit
Register
</button>
</div>

23
components/layout.js

@ -0,0 +1,23 @@
import Head from 'next/head'
import Link from 'next/link'
export const HtmlHead = () => (
<Head>
<title>OnLoki</title>
<meta name="description" content="Get a free subdomain for Lokinet SNApps." />
<link rel="icon" href="/favicon.ico" />
</Head>
)
export const PageHead = () => (
<div>
<h1 className="title">
On.Loki
</h1>
<p className="description">
Get a short <b>free</b> subdomain to access your Lokinet SNApp.<br />
<Link href="/">Home</Link> - <Link href="/faq">FAQ</Link> - <Link href="/tos">TOS</Link> - <a target="_blank" href="http://gitea.on.loki/massivebox/onloki" rel="noopener noreferrer">Code</a>
</p>
</div>
)

6
onloki.service

@ -7,9 +7,9 @@ StartLimitIntervalSec=0
Type=simple
Restart=always
RestartSec=1
User=massive
WorkingDirectory=/home/massive/onloki
ExecStart=/home/massive/onloki/start.sh
User=YOUR_USER
WorkingDirectory=ONLOKI_PATH
ExecStart=ONLOKI_PATH/start.sh
[Install]
WantedBy=multi-user.target

387
package-lock.json generated

@ -5,16 +5,15 @@
"packages": {
"": {
"dependencies": {
"@prisma/client": "2.1.1",
"dynamic-reverse-proxy": "^0.7.0-alpha2",
"@prisma/client": "3.7.0",
"express": "^4.17.2",
"express-http-proxy": "^1.6.3",
"http-proxy": "^1.18.1",
"http-proxy-middleware": "^2.0.1",
"next": "12.0.7",
"node-cache": "5.1.2",
"prisma": "^3.7.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"uuid": "^8.3.2"
"uuid": "8.3.2"
},
"devDependencies": {
"eslint": "8.5.0",
@ -1117,56 +1116,43 @@
"node": ">= 8"
}
},
"node_modules/@prisma/cli": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@prisma/cli/-/cli-2.1.1.tgz",
"integrity": "sha512-QtGZ7KgfeIGVT/SGHI+WoZfvKRiyZ/euafjRGEE2pU/OzT+snSt2gNAjra0JdH5j8onfktZYmdkkgKu+dW9e2w==",
"deprecated": "Prisma CLI package was renamed to 'prisma'. Check it out here: https://www.npmjs.com/package/prisma",
"hasInstallScript": true,
"optional": true,
"peer": true,
"bin": {
"prisma": "build/index.js",
"prisma2": "build/index.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@prisma/client": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-2.1.1.tgz",
"integrity": "sha512-7r0iqBWZ1sxvLI5Bp3/NgYCmBrkbmsr4ml7wZ9JeuyXYPUgwFCfu3Wtv3IMcKbmiGoE3mCV6tnHg0isv6FRgig==",
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.7.0.tgz",
"integrity": "sha512-fUJMvBOX5C7JPc0e3CJD6Gbelbu4dMJB4ScYpiht8HMUnRShw20ULOipTopjNtl6ekHQJ4muI7pXlQxWS9nMbw==",
"hasInstallScript": true,
"dependencies": {
"pkg-up": "^3.1.0"
"@prisma/engines-version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f"
},
"engines": {
"node": ">=10"
"node": ">=12.6"
},
"peerDependencies": {
"@prisma/cli": "*"
"prisma": "*"
},
"peerDependenciesMeta": {
"@prisma/cli": {
"prisma": {
"optional": true
}
}
},
"node_modules/@prisma/engines": {
"version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz",
"integrity": "sha512-W549ub5NlgexNhR8EFstA/UwAWq3Zq0w9aNkraqsozVCt2CsX+lK4TK7IW5OZVSnxHwRjrgEAt3r9yPy8nZQRg==",
"hasInstallScript": true
},
"node_modules/@prisma/engines-version": {
"version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz",
"integrity": "sha512-+qx2b+HK7BKF4VCa0LZ/t1QCXsu6SmvhUQyJkOD2aPpmOzket4fEnSKQZSB0i5tl7rwCDsvAiSeK8o7rf+yvwg=="
},
"node_modules/@rushstack/eslint-patch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
"dev": true
},
"node_modules/@types/http-proxy": {
"version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
"integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -1925,6 +1911,14 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -2232,17 +2226,6 @@
"url": "https://bevry.me/fund"
}
},
"node_modules/dynamic-reverse-proxy": {
"version": "0.7.0-alpha2",
"resolved": "https://registry.npmjs.org/dynamic-reverse-proxy/-/dynamic-reverse-proxy-0.7.0-alpha2.tgz",
"integrity": "sha1-entEefEGWBkgb/k614ZOLuxBWs0=",
"dependencies": {
"http-proxy": "^1.9.0"
},
"engines": {
"node": "*"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -2368,11 +2351,6 @@
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
},
"node_modules/es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -3140,32 +3118,6 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-http-proxy": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/express-http-proxy/-/express-http-proxy-1.6.3.tgz",
"integrity": "sha512-/l77JHcOUrDUX8V67E287VEUQT0lbm71gdGVoodnlWBziarYKgMcpqT7xvh/HM8Jv52phw8Bd8tY+a7QjOr7Yg==",
"dependencies": {
"debug": "^3.0.1",
"es6-promise": "^4.1.1",
"raw-body": "^2.3.0"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/express-http-proxy/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/express-http-proxy/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/express/node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@ -3615,21 +3567,6 @@
"node": ">=8.0.0"
}
},
"node_modules/http-proxy-middleware": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz",
"integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==",
"dependencies": {
"@types/http-proxy": "^1.17.5",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@ -3919,17 +3856,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
"integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@ -4280,6 +4206,7 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
"integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
"dev": true,
"dependencies": {
"braces": "^3.0.1",
"picomatch": "^2.2.3"
@ -4496,6 +4423,17 @@
}
}
},
"node_modules/node-cache": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
"integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
"dependencies": {
"clone": "2.x"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
@ -4862,73 +4800,6 @@
"node": ">=8"
}
},
"node_modules/pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"dependencies": {
"find-up": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-up/node_modules/find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dependencies": {
"locate-path": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/pkg-up/node_modules/locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dependencies": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/pkg-up/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pkg-up/node_modules/p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dependencies": {
"p-limit": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/pkg-up/node_modules/path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"engines": {
"node": ">=4"
}
},
"node_modules/platform": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
@ -4968,6 +4839,22 @@
"node": ">= 0.8.0"
}
},
"node_modules/prisma": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.7.0.tgz",
"integrity": "sha512-pzgc95msPLcCHqOli7Hnabu/GRfSGSUWl5s2P6N13T/rgMB+NNeKbxCmzQiZT2yLOeLEPivV6YrW1oeQIwJxcg==",
"hasInstallScript": true,
"dependencies": {
"@prisma/engines": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f"
},
"bin": {
"prisma": "build/index.js",
"prisma2": "build/index.js"
},
"engines": {
"node": ">=12.6"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@ -6846,35 +6733,30 @@
"fastq": "^1.6.0"
}
},
"@prisma/cli": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@prisma/cli/-/cli-2.1.1.tgz",
"integrity": "sha512-QtGZ7KgfeIGVT/SGHI+WoZfvKRiyZ/euafjRGEE2pU/OzT+snSt2gNAjra0JdH5j8onfktZYmdkkgKu+dW9e2w==",
"optional": true,
"peer": true
},
"@prisma/client": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-2.1.1.tgz",
"integrity": "sha512-7r0iqBWZ1sxvLI5Bp3/NgYCmBrkbmsr4ml7wZ9JeuyXYPUgwFCfu3Wtv3IMcKbmiGoE3mCV6tnHg0isv6FRgig==",
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.7.0.tgz",
"integrity": "sha512-fUJMvBOX5C7JPc0e3CJD6Gbelbu4dMJB4ScYpiht8HMUnRShw20ULOipTopjNtl6ekHQJ4muI7pXlQxWS9nMbw==",
"requires": {
"pkg-up": "^3.1.0"
"@prisma/engines-version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f"
}
},
"@prisma/engines": {
"version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz",
"integrity": "sha512-W549ub5NlgexNhR8EFstA/UwAWq3Zq0w9aNkraqsozVCt2CsX+lK4TK7IW5OZVSnxHwRjrgEAt3r9yPy8nZQRg=="
},
"@prisma/engines-version": {
"version": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz",
"integrity": "sha512-+qx2b+HK7BKF4VCa0LZ/t1QCXsu6SmvhUQyJkOD2aPpmOzket4fEnSKQZSB0i5tl7rwCDsvAiSeK8o7rf+yvwg=="
},
"@rushstack/eslint-patch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
"dev": true
},
"@types/http-proxy": {
"version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
"integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
"requires": {
"@types/node": "*"
}
},
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -7438,6 +7320,11 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
},
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -7699,14 +7586,6 @@
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.19.0.tgz",
"integrity": "sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ=="
},
"dynamic-reverse-proxy": {
"version": "0.7.0-alpha2",
"resolved": "https://registry.npmjs.org/dynamic-reverse-proxy/-/dynamic-reverse-proxy-0.7.0-alpha2.tgz",
"integrity": "sha1-entEefEGWBkgb/k614ZOLuxBWs0=",
"requires": {
"http-proxy": "^1.9.0"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -7813,11 +7692,6 @@
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
},
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@ -8407,31 +8281,6 @@
}
}
},
"express-http-proxy": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/express-http-proxy/-/express-http-proxy-1.6.3.tgz",
"integrity": "sha512-/l77JHcOUrDUX8V67E287VEUQT0lbm71gdGVoodnlWBziarYKgMcpqT7xvh/HM8Jv52phw8Bd8tY+a7QjOr7Yg==",
"requires": {
"debug": "^3.0.1",
"es6-promise": "^4.1.1",
"raw-body": "^2.3.0"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -8761,18 +8610,6 @@
"requires-port": "^1.0.0"
}
},
"http-proxy-middleware": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz",
"integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==",
"requires": {
"@types/http-proxy": "^1.17.5",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
}
},
"https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@ -8955,11 +8792,6 @@
"has-tostringtag": "^1.0.0"
}
},
"is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
"integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA=="
},
"is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@ -9221,6 +9053,7 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
"integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
"dev": true,
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.2.3"
@ -9372,6 +9205,14 @@
"watchpack": "2.3.0"
}
},
"node-cache": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
"integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
"requires": {
"clone": "2.x"
}
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
@ -9641,54 +9482,6 @@
"find-up": "^4.0.0"
}
},
"pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
"requires": {
"find-up": "^3.0.0"
},
"dependencies": {
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"requires": {
"locate-path": "^3.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"requires": {
"p-limit": "^2.0.0"
}
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
}
}
},
"platform": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
@ -9717,6 +9510,14 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
"prisma": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.7.0.tgz",
"integrity": "sha512-pzgc95msPLcCHqOli7Hnabu/GRfSGSUWl5s2P6N13T/rgMB+NNeKbxCmzQiZT2yLOeLEPivV6YrW1oeQIwJxcg==",
"requires": {
"@prisma/engines": "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f"
}
},
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",

5
package.json

@ -17,10 +17,11 @@
"express": "^4.17.2",
"http-proxy": "^1.18.1",
"next": "12.0.7",
"prisma": "3.7.0",
"node-cache": "5.1.2",
"prisma": "^3.7.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"uuid": "^8.3.2"
"uuid": "8.3.2"
},
"devDependencies": {
"eslint": "8.5.0",

15
pages/api/addrecord.js

@ -4,7 +4,7 @@ const prisma = new PrismaClient();
export default async(req, res) => {
const { subdomain, pointsto } = req.body;
const { subdomain, pointsto, redirect } = req.body;
if(subdomain == "" || pointsto == "") {
res.json({ ok: false, error: "Missing fields." });
@ -14,8 +14,16 @@ export default async(req, res) => {
res.json({ ok: false, error: "Subdomain must be at least 3 characters long." });
return;
}
if(pointsto.length < 53) {
res.json({ ok: false, error: "PointsTo doesn't look like a valid SNApp address: it must have at least 53 characters." });
if(pointsto.length < 52) {
res.json({ ok: false, error: "PointsTo doesn't look like a valid SNApp address: it must have at least 52 characters." });
return;
}
if(subdomain.endsWith(".loki")){
res.json({ ok: false, error: "Subdomain doesn't have to include \".loki\"." });
return;
}
if(pointsto.endsWith(".loki")){
res.json({ ok: false, error: "PointsTo doesn't have to include \".loki\"." });
return;
}
@ -29,6 +37,7 @@ export default async(req, res) => {
pointsto,
uuid,
renew,
redirect: redirect ? 1 : 0
},
});
} catch (error) {

2
pages/api/resolve.js

@ -47,6 +47,6 @@ export default async(req, res) => {
return;
}
res.status(200).json({ ok: true, address: record.pointsto })
res.status(200).json({ ok: true, address: record.pointsto, redirect: record.redirect })
}

40
pages/faq.js

@ -1,9 +1,10 @@
import Head from 'next/head'
import Link from 'next/link'
import { HtmlHead, PageHead } from '../components/layout'
import Accordion from '../components/accordion'
import { useRouter } from 'next/router'
const accordionData = [
{
key: "substitute",
title: "Is OnLoki a substitute to ONS (Oxen Name Service)?",
content: `<b>Absolutely not!</b> This is a much inferior product.<br>
OnLoki is centralized, while ONS is decentralized.<br>
@ -13,18 +14,29 @@ const accordionData = [
Sounds cool? You can get an ONS name from the <a target="_blank" href="https://docs.oxen.io/downloads" rel="noopener noreferrer">Desktop wallet. (CLEARNET, UNDER CLOUDFLARE)</a>`,
},
{
key: "for",
title: "Who is OnLoki for?",
content: `OnLoki is for everyone who wants to have a simple, rememberable name for their Lokinet SNApps that respect our TOS, but don't have OXEN to buy a real ONS name.<br>
If you have enough OXEN, please consider buying an ONS name to support the network.<br>
If you don't have any OXEN, you can get yourself some on <a target="_blank" href="https://coingecko.com" rel="noopener noreferrer">CoinGecko (CLEARNET, UNDER CLOUDFLARE)</a>.`
},
{
key: "how",
title: "How does OnLoki work?",
content: `OnLoki works by reverse-proxying all incoming requests from <code>yoursubdomain.on.loki</code> to <code>yourserver.loki</code>.<br>
Proxying is achieved using the <code>http-proxy</code> library for NodeJS.<br>
Yes. You read that right. NodeJS. Because I could.`
},
{
key: "redirect",
title: "What is the \"Redirect Mode\"?",
content: `With OnLoki domains, all requests that reach our server are passed to yours via reverse proxy by default.<br>
While this looks good (the end user never sees the long \".loki\" address of your server), it is terrible for performance.<br>
\"Redirect Mode\" instead redirect the user to your SNapp's address, preserving the query URL for GET requests, which avoids having to route all calls through OnLoki's reverse proxy.<br>
It's arguably uglier, and it doesn't work for anything but HTTP GET, but it's way faster, and recommended for heavy SNApps.`
},
{
key: "renew",
title: "Are OnLoki subdomains free? How do I renew my OnLoki subdomain?",
content: `Yes, OnLoki is free for everyone, and there are no advantages for users who donate.<br>
However, to prevent spam, you must renew your subdomain at least once a week. If you don't renew your subdomain for more than a week, it will get suspended:
@ -32,6 +44,7 @@ const accordionData = [
When you register an OnLoki subdomain, you will be given an URL for renewal. There is no captcha required or anything, so you can simply use a cronjob to curl the URL every 7 days.`
},
{
key: "support",
title: "How can I support OnLoki?",
content: `That's very kind of you! I try to keep costs low, but at the bare minimum I need 7 OXEN a year for the <code>on.loki</code> domain.<br />
If you have some OXEN and you're willing to help me pay the fees, feel free to donate any amount of Oxen at this address:<br />
@ -42,31 +55,22 @@ const accordionData = [
const Faq = () => {
const router = useRouter();
return (
<div className="container">
<Head>
<title>OnLoki</title>
<meta name="description" content="Get a free subdomain for Lokinet SNApps." />
<link rel="icon" href="/favicon.ico" />
</Head>
<HtmlHead />
<main className="main">
<h1 className="title">
On.Loki
</h1>
<p className="description">
Get a short <b>free</b> subdomain to access your Lokinet SNApp.<br />
<Link href="/">Home</Link> - <Link href="/faq">FAQ</Link> - <Link href="/tos">TOS</Link> - <a target="_blank" href="http://gitea.on.loki/massivebox/onloki" rel="noopener noreferrer">Code</a>
</p>
<PageHead />
<h1>FAQ</h1>
<p>Here are some FAQs for OnLoki. If you can't find the answer to your question, contact <code>massivebox</code> (ONS name on Session).<br /></p>
<div className="accordion" style={{width: "100%"}}>
{accordionData.map(({ title, content }) => (
<Accordion title={title} content={content} key={title} />
<div className="accordion" style={{width: "100%"}} suppressHydrationWarning={true}>
{process.browser && accordionData.map(({ key, title, content }) => (
<Accordion acckey={key} title={title} content={content} hash={router.asPath.split("#")[1]} key={key} />
))}
</div>

18
pages/index.js

@ -1,27 +1,15 @@
import Head from 'next/head'
import Link from 'next/link'
import { HtmlHead, PageHead } from '../components/layout'
import AddRecordForm from '../components/addrecord'
export default function Home() {
return (
<div className="container">
<Head>
<title>OnLoki</title>
<meta name="description" content="Get a free subdomain for Lokinet SNApps." />
<link rel="icon" href="/favicon.ico" />
</Head>
<HtmlHead />
<main className="main">
<h1 className="title">
On.Loki
</h1>
<p className="description">
Get a short <b>free</b> subdomain to access your Lokinet SNApp.<br />
<Link href="/">Home</Link> - <Link href="/faq">FAQ</Link> - <Link href="/tos">TOS</Link> - <a target="_blank" href="http://gitea.on.loki/massivebox/onloki" rel="noopener noreferrer">Code</a>
</p>
<PageHead />
<AddRecordForm />

18
pages/tos.js

@ -1,26 +1,14 @@
import Head from 'next/head'
import Link from 'next/link'
import { HtmlHead, PageHead } from '../components/layout';
const Faq = () => {
return (
<div className="container">
<Head>
<title>OnLoki</title>
<meta name="description" content="Get a free subdomain for Lokinet SNApps." />
<link rel="icon" href="/favicon.ico" />
</Head>
<HtmlHead />
<main className="main">
<h1 className="title">
On.Loki
</h1>
<p className="description">
Get a short <b>free</b> subdomain to access your Lokinet SNApp.<br />
<Link href="/">Home</Link> - <Link href="/faq">FAQ</Link> - <Link href="/tos">TOS</Link> - <a target="_blank" href="http://gitea.on.loki/massivebox/onloki" rel="noopener noreferrer">Code</a>
</p>
<PageHead />
<h1>TOS</h1>
<p>

7
prisma/.env

@ -1,7 +0,0 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables
# Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"

BIN
prisma/schema.db

Binary file not shown.

13
prisma/schema.prisma

@ -8,9 +8,10 @@ datasource db {
}
model records {
id Int @default(autoincrement()) @id
pointsto String @unique
renew Int? @default(0)
subdomain String @unique
uuid String @unique
}
id Int @id @default(autoincrement())
subdomain String @unique(map: "sqlite_autoindex_records_1")
pointsto String @unique(map: "sqlite_autoindex_records_2")
uuid String @unique(map: "sqlite_autoindex_records_3")
renew Int @default(0)
redirect Int @default(0)
}

85
server.js

@ -1,12 +1,15 @@
const next = require('next')
var express = require('express')
var httpProxy = require('http-proxy');
const dev = process.env.NODE_ENV == 'development'
const port = process.env.PORT || 3000
const app = next({ dev })
const handle = app.getRequestHandler()
var proxy = httpProxy.createProxyServer({});
const next = require('next');
express = require('express');
httpProxy = require('http-proxy');
NodeCache = require( "node-cache" );
dev = process.env.NODE_ENV == 'development';
cacheDefaultTTL = dev ? 60 : 300;
myCache = new NodeCache( {stdTTL: cacheDefaultTTL, checkperiod: cacheDefaultTTL+1} );
port = process.env.PORT || 3000;
host = dev ? `http://localhost:${port}` : `http://on.loki`;
app = next({ dev });
handle = app.getRequestHandler();
proxy = httpProxy.createProxyServer({});
app.prepare().then(() => {
@ -15,44 +18,64 @@ app.prepare().then(() => {
var subdomain = req.headers.host;
if(subdomain == `localhost:${port}` || subdomain == "on.loki") {
if(subdomain == "on.loki" || subdomain == `localhost:${port}`) {
handle(req, res);
return;
}
let resp, data;
try {
resp = await fetch(
`http://on.loki/api/resolve`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ subdomain: subdomain.replace(".on.loki", "").replace(`:${port}`, "") }),
}
);
data = await resp.json();
} catch (error) {
res.send("Internal error");
console.log(error);
return;
data = myCache.get(subdomain);
if(data == undefined) {
try {
resp = await fetch(
host + `/api/resolve`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ subdomain: subdomain.replace(".on.loki", "").replace(`:${port}`, "") }),
}
);
data = await resp.json();
} catch (error) {
res.send("Internal error");
console.log(error);
return;
}
myCache.set(subdomain, data);
}
if(data.ok) {
proxy.web(req, res, { target: "http://" + data.address + ".loki" });
if(data.redirect == 1) {
res.redirect("http://" + data.address + ".loki" + req.originalUrl);
}else{
try {
proxy.web(req, res, { target: "http://" + data.address + ".loki" });
}catch(error) {
console.log(error);
res.send("Error proxying request.");
return
}
}
}else{
res.send(data.error);
}
})
.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
if (err) throw err;
console.log(`> Ready on ${host}`);
})
}).catch(err => {
console.log('Error:::::', err)
console.log('Error:::::', err);
})
Loading…
Cancel
Save