diff --git a/docker-compose.yml b/docker-compose.yml index a650739d..f70bd862 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,6 +52,7 @@ services: ORIGIN: http://localhost:3000 BODY_SIZE_LIMIT: Infinity PUBLIC_POCKETBASE_URL: http://db:8090 + PUBLIC_DISABLE_SIGNUP: false ports: - "3000:3000" networks: diff --git a/web/Dockerfile b/web/Dockerfile index 2d2d29c0..154feac9 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -7,7 +7,7 @@ EXPOSE 3000 ENV NODE_ENV=production ENV PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090 -ENV PUBLIC_MEILISEARCH_URL=http://127.0.0.1:7700 -ENV PUBLIC_MEILISEARCH_API_TOKEN= +ENV MEILI_URL=http://127.0.0.1:7700 +ENV PUBLIC_DISABLE_SIGNUP=false CMD [ "node", "build" ] \ No newline at end of file diff --git a/web/package-lock.json b/web/package-lock.json index 227a04af..a27dec65 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,6 +16,7 @@ "@types/three": "^0.161.2", "crypto-random-string": "^5.0.0", "date-fns": "^3.3.1", + "jsdom": "^24.0.0", "leaflet": "^1.9.4", "leaflet-gpx": "^1.7.0", "leaflet.awesome-markers": "^2.0.5", @@ -32,6 +33,7 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@types/jsdom": "^21.1.6", "@types/leaflet": "^1.9.8", "@types/leaflet-gpx": "^1.3.7", "@types/node": "^20.11.25", @@ -1049,6 +1051,17 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.13.tgz", "integrity": "sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==" }, + "node_modules/@types/jsdom": { + "version": "21.1.6", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.6.tgz", + "integrity": "sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, "node_modules/@types/leaflet": { "version": "1.9.8", "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.8.tgz", @@ -1110,6 +1123,12 @@ "meshoptimizer": "~0.18.1" } }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, "node_modules/@types/webxr": { "version": "0.5.14", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.14.tgz", @@ -1204,6 +1223,17 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -1270,6 +1300,11 @@ "node": "*" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/autoprefixer": { "version": "10.4.17", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", @@ -1560,6 +1595,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1648,6 +1694,17 @@ "node": ">=4" } }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -1657,6 +1714,49 @@ "type": "^1.0.1" } }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/date-fns": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz", @@ -1682,6 +1782,11 @@ } } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -1702,6 +1807,14 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1763,6 +1876,17 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es5-ext": { "version": "0.10.64", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", @@ -1995,6 +2119,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -2114,6 +2251,41 @@ "node": ">= 0.4" } }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -2123,6 +2295,17 @@ "node": ">=16.17.0" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2254,6 +2437,11 @@ "node": ">=0.12.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -2312,6 +2500,76 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jsdom": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", + "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.7", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.6.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.3", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.16.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/jsonc-parser": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", @@ -2475,6 +2733,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -2684,6 +2961,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2752,6 +3034,17 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -3068,6 +3361,24 @@ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3123,6 +3434,11 @@ "node": ">=0.10.0" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3201,6 +3517,11 @@ "fsevents": "~2.3.2" } }, + "node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3235,6 +3556,11 @@ "node": ">=6" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/sander": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", @@ -3247,6 +3573,17 @@ "rimraf": "^2.5.2" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/set-cookie-parser": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", @@ -3698,6 +4035,11 @@ } } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, "node_modules/tailwindcss": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", @@ -3853,6 +4195,20 @@ "node": ">=6" } }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -3946,6 +4302,14 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "devOptional": true }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -3976,6 +4340,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4150,6 +4523,17 @@ } } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/webgl-sdf-generator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz", @@ -4160,6 +4544,25 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -4308,6 +4711,39 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, "node_modules/yaml": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", diff --git a/web/package.json b/web/package.json index b5224317..c4a07597 100644 --- a/web/package.json +++ b/web/package.json @@ -17,6 +17,7 @@ "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@types/jsdom": "^21.1.6", "@types/leaflet": "^1.9.8", "@types/leaflet-gpx": "^1.3.7", "@types/node": "^20.11.25", @@ -40,6 +41,7 @@ "@types/three": "^0.161.2", "crypto-random-string": "^5.0.0", "date-fns": "^3.3.1", + "jsdom": "^24.0.0", "leaflet": "^1.9.4", "leaflet-gpx": "^1.7.0", "leaflet.awesome-markers": "^2.0.5", diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index 2f873060..3b85b48a 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -1,4 +1,6 @@ import { env } from '$env/dynamic/private' +import { env as envPub } from '$env/dynamic/public' + import { pb } from '$lib/pocketbase' import { isRouteProtected } from '$lib/util/authorization_util' import { redirect, type Handle } from '@sveltejs/kit' @@ -11,11 +13,14 @@ export const handle: Handle = async ({ event, resolve }) => { const url = new URL(event.request.url); + // validate the user existence and if the path is acceesible if (!pb.authStore.model && isRouteProtected(url.pathname)) { throw redirect(302, '/login?r=' + url.pathname); } else if (pb.authStore.model && url.pathname === "/login") { throw redirect(302, '/'); + } else if (envPub.PUBLIC_DISABLE_SIGNUP === "true" && url.pathname === "/register") { + throw redirect(302, '/'); } try { @@ -34,7 +39,7 @@ export const handle: Handle = async ({ event, resolve }) => { } else { const r = await event.fetch(pb.buildUrl("/public/search/token")); const response = await r.json(); - meiliApiKey = response.token; + meiliApiKey = response.token; } const ms = new MeiliSearch({ host: env.MEILI_URL, apiKey: meiliApiKey }); diff --git a/web/src/lib/stores/trail_store.ts b/web/src/lib/stores/trail_store.ts index 9b638e0a..1efc7f5e 100644 --- a/web/src/lib/stores/trail_store.ts +++ b/web/src/lib/stores/trail_store.ts @@ -193,10 +193,10 @@ export async function trails_show(id: string, loadGPX?: boolean, f: (url: Reques return response; } -export async function trails_create(trail: Trail, photos: File[], gpx: File | null) { +export async function trails_create(trail: Trail, photos: File[], gpx: File | Blob | null, f: (url: RequestInfo | URL, config?: RequestInit) => Promise = fetch) { if (!pb.authStore.model) { - throw new Error("Unauthenticated"); + throw new ClientResponseError({ status: 401, response: { message: "Forbidden" } }); } for (const waypoint of trail.expand.waypoints) { @@ -213,7 +213,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | nu trail.author = pb.authStore.model!.id - let r = await fetch('/api/v1/trail', { + let r = await f('/api/v1/trail', { method: 'PUT', body: JSON.stringify({ ...trail, expand: undefined }), }) @@ -233,7 +233,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | nu formData.append("photos", photo) } - r = await fetch(`/api/v1/trail/${model.id!}/file`, { + r = await f(`/api/v1/trail/${model.id!}/file`, { method: 'POST', body: formData, }) diff --git a/web/src/lib/util/authorization_util.ts b/web/src/lib/util/authorization_util.ts index 800043a8..699a70eb 100644 --- a/web/src/lib/util/authorization_util.ts +++ b/web/src/lib/util/authorization_util.ts @@ -1,10 +1,10 @@ const privateRoutes = [ - "/profile", - "/lists", - ] - - export function isRouteProtected(path: string) { - return privateRoutes.some(allowedPath => - path === allowedPath || path.startsWith(allowedPath + '/') - ); - } \ No newline at end of file + "/profile", + "/lists", +] + +export function isRouteProtected(path: string) { + return privateRoutes.some(allowedPath => + path === allowedPath || path.startsWith(allowedPath + '/') + ); +} \ No newline at end of file diff --git a/web/src/lib/util/gpx_util.ts b/web/src/lib/util/gpx_util.ts new file mode 100644 index 00000000..9ea3d86b --- /dev/null +++ b/web/src/lib/util/gpx_util.ts @@ -0,0 +1,38 @@ +import { Trail } from "$lib/models/trail"; +import { Waypoint } from "$lib/models/waypoint"; +import { JSDOM } from "jsdom" + +export function gpx2trail(gpx: string) { + const xml = new JSDOM(gpx).window.document + const trail = new Trail(""); + + let name = xml.getElementsByTagName('name'); + if (name.length > 0) { + trail.name = name[0].textContent ?? ""; + } + let desc = xml.getElementsByTagName('desc'); + if (desc.length > 0) { + trail.description = desc[0].textContent ?? ""; + } + + const el = xml.getElementsByTagName('wpt'); + for (let i = 0; i < el.length; i++) { + const wp = new Waypoint(parseFloat(el[i].getAttribute('lat')!), parseFloat(el[i].getAttribute('lon')!)); + + let nameEl = el[i].getElementsByTagName('name'); + wp.name = nameEl.length > 0 ? nameEl[0].textContent ?? "" : ''; + + let descEl = el[i].getElementsByTagName('desc'); + wp.description = descEl.length > 0 ? descEl[0].textContent ?? "" : ''; + + trail.expand.waypoints.push(wp); + } + + const startPoint = xml.getElementsByTagName("trk")[0].getElementsByTagName("trkseg")[0].getElementsByTagName("trkpt")[0]; + if(startPoint) { + trail.lat = parseFloat(startPoint.getAttribute('lat')!) + trail.lon = parseFloat(startPoint.getAttribute('lon')!) + } + + return trail +} \ No newline at end of file diff --git a/web/src/routes/api/v1/auth/login/+server.ts b/web/src/routes/api/v1/auth/login/+server.ts index 4f941526..29c7f141 100644 --- a/web/src/routes/api/v1/auth/login/+server.ts +++ b/web/src/routes/api/v1/auth/login/+server.ts @@ -1,9 +1,16 @@ import { pb } from "$lib/pocketbase"; import { error, json, type RequestEvent } from "@sveltejs/kit"; +import { ClientResponseError } from "pocketbase"; export async function POST(event: RequestEvent) { - const data = await event.request.json() try { + let data; + try { + data = await event.request.json() + } catch (e) { + throw new ClientResponseError({ status: 400, response: { message: "Invalid json" } }) + } + const r = await pb.collection('users').authWithPassword(data.email ?? data.username!, data.password); return json(r); } catch (e: any) { diff --git a/web/src/routes/api/v1/list/+server.ts b/web/src/routes/api/v1/list/+server.ts index 9b9b17d1..633ab7a6 100644 --- a/web/src/routes/api/v1/list/+server.ts +++ b/web/src/routes/api/v1/list/+server.ts @@ -13,7 +13,6 @@ export async function GET(event: RequestEvent) { } catch (e: any) { throw error(e.status, e); } - } export async function PUT(event: RequestEvent) { diff --git a/web/src/routes/api/v1/list/[id]/+server.ts b/web/src/routes/api/v1/list/[id]/+server.ts index c0fd4995..f293010b 100644 --- a/web/src/routes/api/v1/list/[id]/+server.ts +++ b/web/src/routes/api/v1/list/[id]/+server.ts @@ -2,6 +2,16 @@ import { pb } from "$lib/pocketbase"; import { error, json, type RequestEvent } from "@sveltejs/kit"; import type { List } from "postcss/lib/list"; +export async function GET(event: RequestEvent) { + try { + const r = await pb.collection('lists') + .getOne(event.params.id as string, { expand: "trails,trails.waypoints,trails.category" }) + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} + export async function POST(event: RequestEvent) { const data = await event.request.json() @@ -16,7 +26,7 @@ export async function POST(event: RequestEvent) { export async function DELETE(event: RequestEvent) { try { const r = await pb.collection('lists').delete(event.params.id as string) - return json(r); + return json({ 'acknowledged': r }); } catch (e: any) { throw error(e.status, e) } diff --git a/web/src/routes/api/v1/summit-log/+server.ts b/web/src/routes/api/v1/summit-log/+server.ts index 41f9b585..eba59ba3 100644 --- a/web/src/routes/api/v1/summit-log/+server.ts +++ b/web/src/routes/api/v1/summit-log/+server.ts @@ -2,6 +2,15 @@ import type { SummitLog } from '$lib/models/summit_log'; import { pb } from '$lib/pocketbase'; import { error, json, type RequestEvent } from '@sveltejs/kit'; +export async function GET(event: RequestEvent) { + try { + const r: SummitLog[] = await pb.collection('summit_logs').getFullList() + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} + export async function PUT(event: RequestEvent) { const data = await event.request.json(); diff --git a/web/src/routes/api/v1/summit-log/[id]/+server.ts b/web/src/routes/api/v1/summit-log/[id]/+server.ts index c7dd13a6..92cc0e70 100644 --- a/web/src/routes/api/v1/summit-log/[id]/+server.ts +++ b/web/src/routes/api/v1/summit-log/[id]/+server.ts @@ -3,6 +3,16 @@ import { pb } from "$lib/pocketbase"; import { error, json, type RequestEvent } from "@sveltejs/kit"; +export async function GET(event: RequestEvent) { + try { + const r = await pb.collection('summit_logs') + .getOne(event.params.id as string) + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} + export async function POST(event: RequestEvent) { const data = await event.request.json() try { @@ -16,7 +26,7 @@ export async function POST(event: RequestEvent) { export async function DELETE(event: RequestEvent) { try { const r = await pb.collection('summit_logs').delete(event.params.id as string) - return json(r); + return json({ 'acknowledged': r }); } catch (e: any) { throw error(e.status, e) } diff --git a/web/src/routes/api/v1/trail/[id]/+server.ts b/web/src/routes/api/v1/trail/[id]/+server.ts index a20399c7..0ef2ce9f 100644 --- a/web/src/routes/api/v1/trail/[id]/+server.ts +++ b/web/src/routes/api/v1/trail/[id]/+server.ts @@ -28,7 +28,7 @@ export async function POST(event: RequestEvent) { export async function DELETE(event: RequestEvent) { try { const r = await pb.collection('trails').delete(event.params.id as string) - return json(r); + return json({ 'acknowledged': r }); } catch (e: any) { throw error(e.status, e) } diff --git a/web/src/routes/api/v1/trail/upload/+server.ts b/web/src/routes/api/v1/trail/upload/+server.ts new file mode 100644 index 00000000..64ebc5eb --- /dev/null +++ b/web/src/routes/api/v1/trail/upload/+server.ts @@ -0,0 +1,33 @@ +import type { Trail } from "$lib/models/trail"; +import { trails_create } from "$lib/stores/trail_store"; +import { gpx2trail } from "$lib/util/gpx_util"; +import { error, json, type RequestEvent } from "@sveltejs/kit"; +import { ClientResponseError } from "pocketbase"; + +export async function PUT(event: RequestEvent) { + try { + const data = await event.request.blob(); + const gpx = await data.text(); + if (!gpx.length) { + throw new ClientResponseError({ status: 400, response: { message: "Empty file" } }) + } + let trail: Trail; + try { + trail = gpx2trail(gpx); + } catch (e: any) { + throw new ClientResponseError({ status: 400, response: { message: "Invalid GPX file" } }) + } + + try { + await trails_create(trail, [], data, event.fetch); + } catch(e: any) { + console.log(e); + + throw e + } + return json(trail); + + } catch (e: any) { + throw error(e.status, e) + } +} \ No newline at end of file diff --git a/web/src/routes/api/v1/user/+server.ts b/web/src/routes/api/v1/user/+server.ts index 99a7191a..ae5cb0c6 100644 --- a/web/src/routes/api/v1/user/+server.ts +++ b/web/src/routes/api/v1/user/+server.ts @@ -1,10 +1,15 @@ +import { env } from '$env/dynamic/public'; import { pb } from '$lib/pocketbase'; import type { User } from '$lib/stores/user_store'; import { error, json, type RequestEvent } from '@sveltejs/kit' +import { ClientResponseError } from 'pocketbase'; export async function PUT(event: RequestEvent) { const data = await event.request.json() try { + if (env.PUBLIC_DISABLE_SIGNUP === "true") { + throw new ClientResponseError({ status: 401, response: { messgage: "Forbidden" } }) + } const r = await pb.collection('users').create(data) return json(r); } catch (e: any) { diff --git a/web/src/routes/api/v1/user/[id]/+server.ts b/web/src/routes/api/v1/user/[id]/+server.ts index 5a8b9393..a4007199 100644 --- a/web/src/routes/api/v1/user/[id]/+server.ts +++ b/web/src/routes/api/v1/user/[id]/+server.ts @@ -2,6 +2,16 @@ import { pb } from '$lib/pocketbase'; import type { User } from '$lib/stores/user_store'; import { error, json, type RequestEvent } from '@sveltejs/kit' +export async function GET(event: RequestEvent) { + try { + const r = await pb.collection('users') + .getOne(event.params.id as string) + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} + export async function POST(event: RequestEvent) { const data = await event.request.json() try { @@ -15,7 +25,7 @@ export async function POST(event: RequestEvent) { export async function DELETE(event: RequestEvent) { try { const r = await pb.collection('users').delete(event.params.id as string) - return json(r); + return json({ 'acknowledged': r }); } catch (e: any) { throw error(e.status, e) } diff --git a/web/src/routes/api/v1/waypoint/+server.ts b/web/src/routes/api/v1/waypoint/+server.ts index 1d43d576..59da13ff 100644 --- a/web/src/routes/api/v1/waypoint/+server.ts +++ b/web/src/routes/api/v1/waypoint/+server.ts @@ -2,6 +2,15 @@ import type { Waypoint } from '$lib/models/waypoint'; import { pb } from '$lib/pocketbase'; import { error, json, type RequestEvent } from '@sveltejs/kit'; +export async function GET(event: RequestEvent) { + try { + const r: Waypoint[] = await pb.collection('waypoints').getFullList() + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} + export async function PUT(event: RequestEvent) { const data = await event.request.json(); diff --git a/web/src/routes/api/v1/waypoint/[id]/+server.ts b/web/src/routes/api/v1/waypoint/[id]/+server.ts index 8d2931f2..8074bc81 100644 --- a/web/src/routes/api/v1/waypoint/[id]/+server.ts +++ b/web/src/routes/api/v1/waypoint/[id]/+server.ts @@ -2,6 +2,15 @@ import type { Waypoint } from "$lib/models/waypoint"; import { pb } from "$lib/pocketbase"; import { error, json, type RequestEvent } from "@sveltejs/kit"; +export async function GET(event: RequestEvent) { + try { + const r = await pb.collection('waypoints') + .getOne(event.params.id as string) + return json(r) + } catch (e: any) { + throw error(e.status, e); + } +} export async function POST(event: RequestEvent){ const data = await event.request.json() @@ -16,7 +25,7 @@ export async function POST(event: RequestEvent){ export async function DELETE(event: RequestEvent) { try { const r = await pb.collection('waypoints').delete(event.params.id as string) - return json(r); + return json({ 'acknowledged': r }); } catch (e: any) { throw error(e.status, e) } diff --git a/web/src/routes/lists/+page.svelte b/web/src/routes/lists/+page.svelte index df7ac74a..460b938c 100644 --- a/web/src/routes/lists/+page.svelte +++ b/web/src/routes/lists/+page.svelte @@ -205,6 +205,8 @@ [minLat, maxLon], ]; map.fitBounds(boundingBox); + } else { + map.setView([0, 0], 4); } } @@ -213,7 +215,7 @@ {$_("list", { values: { n: 2 } })} | wanderer
    import { goto } from "$app/navigation"; + import { page } from "$app/stores"; + import { env } from "$env/dynamic/public"; import Button from "$lib/components/base/button.svelte"; import TextField from "$lib/components/base/text_field.svelte"; import LogoTextTwoLineDark from "$lib/components/logo/logo_text_two_line_dark.svelte"; import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte"; + import { theme } from "$lib/stores/theme_store"; import { show_toast } from "$lib/stores/toast_store"; import { login, type User } from "$lib/stores/user_store"; import { createForm } from "$lib/vendor/svelte-form-lib"; import { ClientResponseError } from "pocketbase"; - import { object, string } from "yup"; - import { theme } from "$lib/stores/theme_store"; import { _ } from "svelte-i18n"; - import { page } from "$app/stores"; + import { object, string } from "yup"; let loading: boolean = false; const { form, errors, handleChange, handleSubmit } = createForm({ @@ -37,13 +38,13 @@ show_toast({ icon: "close", type: "error", - text: $_('wrong-username-or-password'), + text: $_("wrong-username-or-password"), }); } else { show_toast({ icon: "close", type: "error", - text: $_('error-during-login'), + text: $_("error-during-login"), }); } } finally { @@ -90,11 +91,13 @@ {loading}>Login - {$_("no-account")} - {$_("make-one")} + {#if env.PUBLIC_DISABLE_SIGNUP === "false"} + {$_("no-account")} + {$_("make-one")} + {/if}
diff --git a/web/src/routes/trail/edit/[id]/+page.svelte b/web/src/routes/trail/edit/[id]/+page.svelte index 5bfe7273..8baa4b78 100644 --- a/web/src/routes/trail/edit/[id]/+page.svelte +++ b/web/src/routes/trail/edit/[id]/+page.svelte @@ -242,6 +242,8 @@ }) .on("loaded", function (e: LeafletEvent) { map.fitBounds(e.target.getBounds()); + $form.name = e.target._info.name; + $form.description = e.target._info.desc; $form.distance = Math.round(e.target.get_distance()); $form.elevation_gain = Math.round( e.target.get_elevation_gain(),