Determining location with restrictions disabled, cleaned up.

This commit is contained in:
2026-07-23 05:34:28 +02:00
parent 4c48700086
commit 77b27a56f7
28 changed files with 590 additions and 71 deletions

View File

@@ -1,6 +1,4 @@
<script setup> <script setup>
import { ref } from 'vue';
// import Checkbox from '#/components/form/checkbox.vue'; // import Checkbox from '#/components/form/checkbox.vue';
</script> </script>

View File

@@ -49,6 +49,10 @@ async function updateAccount() {
appendErrorMessage: true, appendErrorMessage: true,
}); });
currentPassword.value = null;
credentials.email = null;
credentials.password = null;
submitted.value = true; submitted.value = true;
} }
finally { finally {

View File

@@ -1,4 +1,5 @@
import antfu from '@antfu/eslint-config'; import antfu from '@antfu/eslint-config';
import importX, { createNodeResolver } from 'eslint-plugin-import-x';
export default antfu( export default antfu(
{ {
@@ -18,11 +19,21 @@ export default antfu(
}, },
}, },
{ {
plugins: { 'import-x': importX },
languageOptions: { languageOptions: {
globals: { globals: {
CONFIG: 'readonly', CONFIG: 'readonly',
}, },
}, },
settings: {
// mirrors the '#'/'#root' aliases in vite.config.js, which is what actually resolves these at build/runtime
'import-x/resolver-next': [createNodeResolver({
alias: {
'#': [import.meta.dirname],
'#root': [import.meta.dirname],
},
})],
},
rules: { rules: {
'default-param-last': 'off', 'default-param-last': 'off',
'no-underscore-dangle': 'off', 'no-underscore-dangle': 'off',
@@ -33,6 +44,7 @@ export default antfu(
ignorePropertyModificationsFor: ['state', 'acc', 'req'], ignorePropertyModificationsFor: ['state', 'acc', 'req'],
}], }],
'prefer-destructuring': 'off', 'prefer-destructuring': 'off',
'import-x/no-unresolved': 'error',
'import/prefer-default-export': 'off', 'import/prefer-default-export': 'off',
'unused-imports/no-unused-vars': ['error', { 'unused-imports/no-unused-vars': ['error', {
args: 'after-used', args: 'after-used',

478
package-lock.json generated
View File

@@ -36,6 +36,7 @@
"ejs": "^6.0.1", "ejs": "^6.0.1",
"error-stack-parser": "^2.1.4", "error-stack-parser": "^2.1.4",
"escape-string-regexp": "^5.0.0", "escape-string-regexp": "^5.0.0",
"eslint-plugin-import-x": "^4.17.1",
"express": "^5.2.1", "express": "^5.2.1",
"express-session": "^1.19.0", "express-session": "^1.19.0",
"floating-vue": "^5.2.2", "floating-vue": "^5.2.2",
@@ -6113,7 +6114,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz",
"integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==", "integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.63.0", "@typescript-eslint/tsconfig-utils": "^8.63.0",
@@ -6339,7 +6340,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz",
"integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==", "integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.63.0", "@typescript-eslint/types": "8.63.0",
@@ -6357,7 +6358,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz",
"integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==", "integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6399,7 +6400,6 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz",
"integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==", "integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6413,7 +6413,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz",
"integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==", "integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.63.0", "@typescript-eslint/project-service": "8.63.0",
@@ -6441,7 +6441,7 @@
"version": "7.8.5", "version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true, "devOptional": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
@@ -6454,7 +6454,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz",
"integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==", "integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.9.1", "@eslint-community/eslint-utils": "^4.9.1",
@@ -6478,7 +6478,7 @@
"version": "8.63.0", "version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz",
"integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==", "integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.63.0", "@typescript-eslint/types": "8.63.0",
@@ -6496,7 +6496,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^20.19.0 || ^22.13.0 || >=24" "node": "^20.19.0 || ^22.13.0 || >=24"
@@ -6663,6 +6663,328 @@
"@universal-middleware/core": "^0.4.18" "@universal-middleware/core": "^0.4.18"
} }
}, },
"node_modules/@unrs/resolver-binding-android-arm-eabi": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz",
"integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@unrs/resolver-binding-android-arm64": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz",
"integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@unrs/resolver-binding-darwin-arm64": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz",
"integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@unrs/resolver-binding-darwin-x64": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz",
"integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@unrs/resolver-binding-freebsd-x64": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz",
"integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz",
"integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz",
"integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz",
"integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-arm64-musl": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz",
"integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-loong64-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz",
"integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-loong64-musl": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz",
"integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz",
"integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz",
"integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz",
"integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz",
"integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-x64-gnu": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
"integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-linux-x64-musl": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz",
"integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@unrs/resolver-binding-openharmony-arm64": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz",
"integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"openharmony"
]
},
"node_modules/@unrs/resolver-binding-wasm32-wasi": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz",
"integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==",
"cpu": [
"wasm32"
],
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "1.10.0",
"@emnapi/runtime": "1.10.0",
"@napi-rs/wasm-runtime": "^1.1.4"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
}
},
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
"integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz",
"integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@unrs/resolver-binding-win32-x64-msvc": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz",
"integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@videojs/http-streaming": { "node_modules/@videojs/http-streaming": {
"version": "3.17.5", "version": "3.17.5",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.17.5.tgz", "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.17.5.tgz",
@@ -8363,7 +8685,6 @@
"version": "1.4.5", "version": "1.4.5",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.5.tgz", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.5.tgz",
"integrity": "sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==", "integrity": "sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 12.0.0" "node": ">= 12.0.0"
@@ -9756,6 +10077,30 @@
"node": "^20.19.0 || ^22.13.0 || >=24" "node": "^20.19.0 || ^22.13.0 || >=24"
} }
}, },
"node_modules/eslint-import-context": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz",
"integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==",
"license": "MIT",
"dependencies": {
"get-tsconfig": "^4.10.1",
"stable-hash-x": "^0.2.0"
},
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint-import-context"
},
"peerDependencies": {
"unrs-resolver": "^1.0.0"
},
"peerDependenciesMeta": {
"unrs-resolver": {
"optional": true
}
}
},
"node_modules/eslint-import-resolver-node": { "node_modules/eslint-import-resolver-node": {
"version": "0.3.10", "version": "0.3.10",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
@@ -9932,6 +10277,54 @@
"eslint": "^9.0.0 || ^10.0.0" "eslint": "^9.0.0 || ^10.0.0"
} }
}, },
"node_modules/eslint-plugin-import-x": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.17.1.tgz",
"integrity": "sha512-4cdstYkKCyjumM2Q9NSI03K8D2a9F4Ssz33K2lv2hQa4KmR9jPLwk3uWGtNvclfqBrPGfGuMBwsGMbe6dMRbfg==",
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "^8.56.0",
"comment-parser": "^1.4.1",
"debug": "^4.4.1",
"eslint-import-context": "^0.1.9",
"is-glob": "^4.0.3",
"minimatch": "^9.0.3 || ^10.1.2",
"semver": "^7.7.2",
"stable-hash-x": "^0.2.0",
"unrs-resolver": "^1.9.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint-plugin-import-x"
},
"peerDependencies": {
"@typescript-eslint/utils": "^8.56.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"eslint-import-resolver-node": "*"
},
"peerDependenciesMeta": {
"@typescript-eslint/utils": {
"optional": true
},
"eslint-import-resolver-node": {
"optional": true
}
}
},
"node_modules/eslint-plugin-import-x/node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/eslint-plugin-jsdoc": { "node_modules/eslint-plugin-jsdoc": {
"version": "63.0.13", "version": "63.0.13",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-63.0.13.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-63.0.13.tgz",
@@ -11318,7 +11711,6 @@
"version": "4.14.0", "version": "4.14.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
"integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"resolve-pkg-maps": "^1.0.0" "resolve-pkg-maps": "^1.0.0"
@@ -15871,6 +16263,21 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/napi-postinstall": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
"integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
"license": "MIT",
"bin": {
"napi-postinstall": "lib/cli.js"
},
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/napi-postinstall"
}
},
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -17694,7 +18101,6 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
@@ -18478,6 +18884,15 @@
"node": ">=20.16.0" "node": ">=20.16.0"
} }
}, },
"node_modules/stable-hash-x": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz",
"integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/stack-trace": { "node_modules/stack-trace": {
"version": "0.0.10", "version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
@@ -19412,7 +19827,7 @@
"version": "2.5.0", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18.12" "node": ">=18.12"
@@ -20320,6 +20735,43 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/unrs-resolver": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz",
"integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"napi-postinstall": "^0.3.4"
},
"funding": {
"url": "https://opencollective.com/unrs-resolver"
},
"optionalDependencies": {
"@unrs/resolver-binding-android-arm-eabi": "1.12.2",
"@unrs/resolver-binding-android-arm64": "1.12.2",
"@unrs/resolver-binding-darwin-arm64": "1.12.2",
"@unrs/resolver-binding-darwin-x64": "1.12.2",
"@unrs/resolver-binding-freebsd-x64": "1.12.2",
"@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2",
"@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2",
"@unrs/resolver-binding-linux-arm64-gnu": "1.12.2",
"@unrs/resolver-binding-linux-arm64-musl": "1.12.2",
"@unrs/resolver-binding-linux-loong64-gnu": "1.12.2",
"@unrs/resolver-binding-linux-loong64-musl": "1.12.2",
"@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2",
"@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2",
"@unrs/resolver-binding-linux-riscv64-musl": "1.12.2",
"@unrs/resolver-binding-linux-s390x-gnu": "1.12.2",
"@unrs/resolver-binding-linux-x64-gnu": "1.12.2",
"@unrs/resolver-binding-linux-x64-musl": "1.12.2",
"@unrs/resolver-binding-openharmony-arm64": "1.12.2",
"@unrs/resolver-binding-wasm32-wasi": "1.12.2",
"@unrs/resolver-binding-win32-arm64-msvc": "1.12.2",
"@unrs/resolver-binding-win32-ia32-msvc": "1.12.2",
"@unrs/resolver-binding-win32-x64-msvc": "1.12.2"
}
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",

View File

@@ -37,6 +37,7 @@
"ejs": "^6.0.1", "ejs": "^6.0.1",
"error-stack-parser": "^2.1.4", "error-stack-parser": "^2.1.4",
"escape-string-regexp": "^5.0.0", "escape-string-regexp": "^5.0.0",
"eslint-plugin-import-x": "^4.17.1",
"express": "^5.2.1", "express": "^5.2.1",
"express-session": "^1.19.0", "express-session": "^1.19.0",
"floating-vue": "^5.2.2", "floating-vue": "^5.2.2",

View File

@@ -191,4 +191,8 @@ onMounted(() => {
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
} }
.button-submit {
padding: .75rem 1rem;
}
</style> </style>

View File

@@ -221,6 +221,7 @@ onMounted(() => {
} }
.button-submit { .button-submit {
padding: .75rem 1rem;
margin-top: .5rem; margin-top: .5rem;
} }

View File

@@ -4,7 +4,7 @@ export async function onBeforeRender(pageContext) {
const networks = await fetchEntities(pageContext.urlParsed.search.q const networks = await fetchEntities(pageContext.urlParsed.search.q
? { query: pageContext.urlParsed.search.q } ? { query: pageContext.urlParsed.search.q }
: { type: 'primary' }, { : { type: 'primary' }, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
return { return {

View File

@@ -21,7 +21,7 @@ async function fetchReleases(pageContext, entityId) {
limit: Number(pageContext.urlParsed.search.limit) || 30, limit: Number(pageContext.urlParsed.search.limit) || 30,
aggregate: true, aggregate: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
} }
@@ -35,7 +35,7 @@ async function fetchReleases(pageContext, entityId) {
limit: Number(pageContext.urlParsed.search.limit) || 30, limit: Number(pageContext.urlParsed.search.limit) || 30,
aggregate: true, aggregate: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
} }
@@ -52,7 +52,7 @@ export async function onBeforeRender(pageContext) {
entityReleases, entityReleases,
] = await Promise.all([ ] = await Promise.all([
fetchEntitiesById([Number(entityId)], { includeChildren: true }, pageContext.user, { fetchEntitiesById([Number(entityId)], { includeChildren: true }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}), }),
fetchReleases(pageContext, entityId), fetchReleases(pageContext, entityId),
]); ]);

View File

@@ -10,7 +10,7 @@ export async function onBeforeRender(pageContext) {
limit: Number(pageContext.urlParsed.search.limit) || 50, limit: Number(pageContext.urlParsed.search.limit) || 50,
dedupe: true, dedupe: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
return { return {

View File

@@ -18,7 +18,7 @@ function getTitle(movie) {
export async function onBeforeRender(pageContext) { export async function onBeforeRender(pageContext) {
const [[movie], movieScenes] = await Promise.all([ const [[movie], movieScenes] = await Promise.all([
fetchMoviesById([Number(pageContext.routeParams.movieId)], pageContext.user, { restriction: pageContext.restriction }), fetchMoviesById([Number(pageContext.routeParams.movieId)], pageContext.user, { restriction: pageContext.geo.restriction }),
fetchScenes(await curateScenesQuery({ fetchScenes(await curateScenesQuery({
...pageContext.urlQuery, ...pageContext.urlQuery,
scope: 'oldest', scope: 'oldest',
@@ -28,7 +28,7 @@ export async function onBeforeRender(pageContext) {
limit: Number(pageContext.urlParsed.search.limit) || 30, limit: Number(pageContext.urlParsed.search.limit) || 30,
aggregate: true, aggregate: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}), }),
]); ]);

View File

@@ -18,7 +18,7 @@ export async function onBeforeRender(pageContext) {
aggregate: true, aggregate: true,
dedupe: true, dedupe: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}), }),
getRandomCampaigns([ getRandomCampaigns([
{ minRatio: 0.75, maxRatio: 1.25 }, { minRatio: 0.75, maxRatio: 1.25 },

View File

@@ -25,7 +25,7 @@ export async function onBeforeRender(pageContext) {
includeAssets: true, includeAssets: true,
includePartOf: true, includePartOf: true,
actorStashes: true, actorStashes: true,
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
if (!scene) { if (!scene) {

View File

@@ -16,24 +16,24 @@ export async function onBeforeRender(pageContext) {
}), { }), {
page: Number(pageContext.routeParams.page) || 1, page: Number(pageContext.routeParams.page) || 1,
limit: Number(pageContext.urlParsed.search.limit) || 15, limit: Number(pageContext.urlParsed.search.limit) || 15,
}, pageContext.user, { restriction: pageContext.restriction }), }, pageContext.user, { restriction: pageContext.geo.restriction }),
fetchActors(curateActorsQuery(pageContext.urlQuery), { fetchActors(curateActorsQuery(pageContext.urlQuery), {
page: Number(pageContext.routeParams.page) || 1, page: Number(pageContext.routeParams.page) || 1,
limit: Number(pageContext.urlParsed.search.limit) || 10, limit: Number(pageContext.urlParsed.search.limit) || 10,
order: ['results', 'desc'], order: ['results', 'desc'],
}, pageContext.user, { restriction: pageContext.restriction }), }, pageContext.user, { restriction: pageContext.geo.restriction }),
fetchMovies(await curateMoviesQuery({ fetchMovies(await curateMoviesQuery({
...pageContext.urlQuery, ...pageContext.urlQuery,
scope: pageContext.routeParams.scope || 'results', scope: pageContext.routeParams.scope || 'results',
}), { }), {
page: Number(pageContext.routeParams.page) || 1, page: Number(pageContext.routeParams.page) || 1,
limit: Number(pageContext.urlParsed.search.limit) || 5, limit: Number(pageContext.urlParsed.search.limit) || 5,
}, pageContext.user, { restriction: pageContext.restriction }), }, pageContext.user, { restriction: pageContext.geo.restriction }),
fetchEntities({ fetchEntities({
query: pageContext.urlParsed.search.q, query: pageContext.urlParsed.search.q,
limit: 5, limit: 5,
}, { }, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}), }),
]); ]);

View File

@@ -118,7 +118,7 @@ const tagSlugs = {
}; };
async function searchTags(pageContext) { async function searchTags(pageContext) {
const tags = await fetchTags({ query: pageContext.urlParsed.search.q }, { restriction: pageContext.restriction }); const tags = await fetchTags({ query: pageContext.urlParsed.search.q }, { restriction: pageContext.geo.restriction });
return { return {
pageContext: { pageContext: {
@@ -137,13 +137,13 @@ export async function onBeforeRender(pageContext) {
return searchTags(pageContext); return searchTags(pageContext);
} }
const tags = await fetchTagsById(Object.values(tagSlugs).flat(), {}, pageContext.user, { restriction: pageContext.restriction }); const tags = await fetchTagsById(Object.values(tagSlugs).flat(), {}, pageContext.user, { restriction: pageContext.geo.restriction });
const filteredTags = tags.filter((tag) => !pageContext.tagFilter.includes(tag.name) && !pageContext.tagFilter.includes(tag.slug)); const filteredTags = tags.filter((tag) => !pageContext.tagFilter.includes(tag.name) && !pageContext.tagFilter.includes(tag.slug));
const tagsBySlug = Object.fromEntries(filteredTags.map((tag) => [tag.slug, tag])); const tagsBySlug = Object.fromEntries(filteredTags.map((tag) => [tag.slug, tag]));
const tagShowcase = Object.fromEntries(Object.entries(tagSlugs).map(([category, categorySlugs]) => [ const tagShowcase = Object.fromEntries(Object.entries(tagSlugs).map(([category, categorySlugs]) => [
censor(category, pageContext.restriction), censor(category, pageContext.geo.restriction),
categorySlugs.map((slug) => tagsBySlug[slug]).filter(Boolean), categorySlugs.map((slug) => tagsBySlug[slug]).filter(Boolean),
])); ]));

View File

@@ -23,7 +23,7 @@ async function fetchReleases(pageContext) {
limit: Number(pageContext.urlParsed.search.limit) || 30, limit: Number(pageContext.urlParsed.search.limit) || 30,
aggregate: true, aggregate: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
} }
@@ -37,13 +37,13 @@ async function fetchReleases(pageContext) {
limit: Number(pageContext.urlParsed.search.limit) || 30, limit: Number(pageContext.urlParsed.search.limit) || 30,
aggregate: true, aggregate: true,
}, pageContext.user, { }, pageContext.user, {
restriction: pageContext.restriction, restriction: pageContext.geo.restriction,
}); });
} }
export async function onBeforeRender(pageContext) { export async function onBeforeRender(pageContext) {
const tagSlug = pageContext.routeParams.tagSlug; const tagSlug = pageContext.routeParams.tagSlug;
const [tag] = await fetchTagsById([tagSlug], {}, pageContext.user, { restriction: pageContext.restriction }); const [tag] = await fetchTagsById([tagSlug], {}, pageContext.user, { restriction: pageContext.geo.restriction });
if (tag.aliasFor) { if (tag.aliasFor) {
throw redirect(`/tag/${tag.aliasFor}`); throw redirect(`/tag/${tag.aliasFor}`);

View File

@@ -19,7 +19,7 @@ export async function onBeforeRender(pageContext) {
limit: Number(pageContext.urlParsed.search.limit) || 29, limit: Number(pageContext.urlParsed.search.limit) || 29,
aggregate: withQuery, aggregate: withQuery,
dedupe: true, dedupe: true,
}, pageContext.user, { restriction: pageContext.restriction }), }, pageContext.user, { restriction: pageContext.geo.restriction }),
getRandomCampaigns([ getRandomCampaigns([
{ minRatio: 2.0, maxRatio: 5 }, { minRatio: 2.0, maxRatio: 5 },
{ minRatio: 0.75, maxRatio: 1.25 }, { minRatio: 0.75, maxRatio: 1.25 },

View File

@@ -9,6 +9,6 @@ export default {
'assets', 'assets',
'campaigns', 'campaigns',
'meta', 'meta',
'restriction', 'geo',
], ],
}; };

View File

@@ -423,7 +423,7 @@ async function updatePassword(password, reqUser, reqSession) {
.where('id', reqUser.id) .where('id', reqUser.id)
.update('password', storedPassword); .update('password', storedPassword);
const country = reqSession.country && await knex('countries').where('alpha2', reqSession.country).first(); const country = reqSession.geo?.country && await knex('countries').where('alpha2', reqSession.geo.country).first();
await sendEmails([{ await sendEmails([{
template: 'password', template: 'password',

View File

@@ -1,7 +1,7 @@
import { pageContext } from '../renderer/usePageContext.js'; import { pageContext } from '../renderer/usePageContext.js';
function getBasePath(media, options) { function getBasePath(media, options) {
if (pageContext.restriction) { if (pageContext.geo.restriction) {
return pageContext.env.media.assetPath; return pageContext.env.media.assetPath;
} }
@@ -17,11 +17,11 @@ function getBasePath(media, options) {
} }
function getFilename(media, type, options) { function getFilename(media, type, options) {
if (pageContext.restriction && type && !options?.original) { if (pageContext.geo.restriction && type && !options?.original) {
return media.sfw?.[type]; return media.sfw?.[type];
} }
if (pageContext.restriction) { if (pageContext.geo.restriction) {
return media.sfw?.path; return media.sfw?.path;
} }

View File

@@ -1,6 +1,7 @@
import crypto from 'node:crypto';
import { Router } from 'express'; import { Router } from 'express';
import IPCIDR from 'ip-cidr'; import IPCIDR from 'ip-cidr';
import runtimeId from '../../utils/runtime-id.js';
import argv from '../argv.js'; import argv from '../argv.js';
import { import {
@@ -24,7 +25,6 @@ import {
// changes every time the process restarts, so a deploy invalidates all cached session users // changes every time the process restarts, so a deploy invalidates all cached session users
// even if they're within the staleness window below // even if they're within the staleness window below
const runtimeId = crypto.randomUUID();
const sessionStaleThreshold = 5 * 60 * 1000; const sessionStaleThreshold = 5 * 60 * 1000;
// spread into a new object rather than mutating the user we're about to hand back to the // spread into a new object rather than mutating the user we're about to hand back to the

View File

@@ -60,7 +60,7 @@ export default async function mainHandler(req, res, next) {
siteKey: config.auth.captcha.siteKey, siteKey: config.auth.captcha.siteKey,
}, },
}, },
restriction: req.restriction, geo: req.geo,
meta: { meta: {
now: new Date().toISOString(), now: new Date().toISOString(),
}, },

View File

@@ -31,7 +31,7 @@ export async function fetchMoviesApi(req, res) {
} = await fetchMovies(await curateMoviesQuery(req.query), { } = await fetchMovies(await curateMoviesQuery(req.query), {
page: Number(req.query.page) || 1, page: Number(req.query.page) || 1,
limit: Number(req.query.limit) || 30, limit: Number(req.query.limit) || 30,
}, req.user, { restriction: req.restriction }); }, req.user, { restriction: req.geo.restriction });
res.send({ res.send({
movies, movies,
@@ -45,7 +45,7 @@ export async function fetchMoviesApi(req, res) {
} }
export async function fetchMovieApi(req, res) { export async function fetchMovieApi(req, res) {
const [movie] = await fetchMoviesById([Number(req.params.movieId)], { reqUser: req.user }, { restriction: req.restriction }); const [movie] = await fetchMoviesById([Number(req.params.movieId)], { reqUser: req.user }, { restriction: req.geo.restriction });
if (!movie) { if (!movie) {
throw new HttpError(`No movie with ID ${req.params.movieId} found`, 404); throw new HttpError(`No movie with ID ${req.params.movieId} found`, 404);
@@ -135,7 +135,7 @@ export async function fetchMoviesGraphql(query, req) {
page: query.page || 1, page: query.page || 1,
limit: query.limit || 30, limit: query.limit || 30,
aggregate: false, aggregate: false,
}, req.user, { restriction: req.restriction }); }, req.user, { restriction: req.geo.restriction });
return { return {
nodes: movies, nodes: movies,

View File

@@ -2,6 +2,7 @@ import path from 'node:path';
import { Reader } from '@maxmind/geoip2-node'; import { Reader } from '@maxmind/geoip2-node';
import config from 'config'; import config from 'config';
import runtimeId from '../../utils/runtime-id.js';
import initLogger from '../logger.js'; import initLogger from '../logger.js';
const logger = initLogger(); const logger = initLogger();
@@ -11,22 +12,47 @@ export default async function initRestrictionHandler() {
const reader = await Reader.open('assets/GeoLite2-City.mmdb'); const reader = await Reader.open('assets/GeoLite2-City.mmdb');
function getRestriction(req) { function getRestriction(req) {
if (Object.hasOwn(req.session, 'restriction') && Object.hasOwn(req.session, 'country') && req.session.restrictionIp === req.userIp) { if (req.session.geo
return { && Object.hasOwn(req.session.geo, 'country')
restriction: req.session.restriction, && req.session.geo.ip === req.userIp
country: req.session.country, && req.session.geo.runtimeId === runtimeId) {
}; const { country, subdivision } = req.session.geo;
if (!config.restrictions.enabled) {
return {
restriction: 0,
country,
subdivision,
};
}
if (Object.hasOwn(req.session.geo, 'restriction')) {
return {
restriction: req.session.geo.restriction,
country,
subdivision,
};
}
} }
const location = reader.city(req.userIp); const location = reader.city(req.userIp);
const country = location.country.isoCode; const country = location.country.isoCode;
const subdivision = location.subdivisions?.[0]?.isoCode; const subdivision = location.subdivisions?.[0]?.isoCode;
if (!config.restrictions.enabled) {
return {
restriction: 0,
country,
subdivision,
};
}
if (regions[country]?.[subdivision]) { if (regions[country]?.[subdivision]) {
// state or province restriction // state or province restriction
return { return {
restriction: config.restrictions.modes[regions[country][subdivision]], restriction: config.restrictions.modes[regions[country][subdivision]],
country, country,
subdivision,
}; };
} }
@@ -35,23 +61,24 @@ export default async function initRestrictionHandler() {
return { return {
restriction: config.restrictions.modes[regions[country]], restriction: config.restrictions.modes[regions[country]],
country, country,
subdivision,
}; };
} }
return { return {
restriction: null, restriction: null,
country, country,
subdivision,
}; };
} }
function restrictionHandler(req, res, next) { function restrictionHandler(req, res, next) {
if (!config.restrictions.enabled) {
next();
return;
}
try { try {
const { restriction, country } = getRestriction(req); const {
restriction,
country,
subdivision,
} = getRestriction(req);
if (restriction === 'block' || req.path === '/sfw/') { if (restriction === 'block' || req.path === '/sfw/') {
res.render(path.join(import.meta.dirname, '../../assets/sfw.ejs'), { res.render(path.join(import.meta.dirname, '../../assets/sfw.ejs'), {
@@ -61,21 +88,38 @@ export default async function initRestrictionHandler() {
return; return;
} }
if (req.session.restriction !== restriction) { if (req.session.geo?.restriction !== restriction) {
req.session.restrictionIp = req.userIp; req.session.geo = {
req.session.restriction = restriction; ip: req.userIp,
req.session.country = country; runtimeId,
restriction,
country,
subdivision,
};
} }
req.restriction = restriction; req.geo = {
req.country = country; restriction,
country,
subdivision,
};
} }
catch (error) { catch (error) {
logger.error(`Failed Maxmind IP lookup for ${req.ip}: ${error.message}`); logger.error(`Failed Maxmind IP lookup for ${req.ip}: ${error.message}`);
req.session.restrictionIp = req.userIp; req.session.geo = {
req.session.restriction = 0; ip: req.userIp,
req.session.country = null; runtimeId,
restriction: 0,
country: null,
subdivision: null,
};
req.geo = {
restriction: 0,
country: null,
subdivision: null,
};
} }
next(); next();

View File

@@ -70,7 +70,7 @@ async function fetchScenesApi(req, res) {
page: Number(req.query.page) || 1, page: Number(req.query.page) || 1,
limit: Number(req.query.limit) || 30, limit: Number(req.query.limit) || 30,
}, req.user, { }, req.user, {
restriction: req.restriction, restriction: req.geo.restriction,
}); });
res.send({ res.send({
@@ -254,7 +254,7 @@ export async function fetchScenesGraphql(query, req) {
} }
async function fetchSceneApi(req, res) { async function fetchSceneApi(req, res) {
const [scene] = await fetchScenesById([Number(req.params.sceneId)], { reqUser: req.user }, { restriction: req.restriction }); const [scene] = await fetchScenesById([Number(req.params.sceneId)], { reqUser: req.user }, { restriction: req.geo.restriction });
if (!scene) { if (!scene) {
throw new HttpError(`No scene with ID ${req.params.sceneId} found`, 404); throw new HttpError(`No scene with ID ${req.params.sceneId} found`, 404);
@@ -267,7 +267,7 @@ export async function fetchScenesByIdGraphql(query, req) {
const scenes = await fetchScenesById([].concat(query.id, query.ids).filter(Boolean), { const scenes = await fetchScenesById([].concat(query.id, query.ids).filter(Boolean), {
reqUser: req.user, reqUser: req.user,
includePartOf: true, includePartOf: true,
restriction: req.restriction, restriction: req.geo.restriction,
}); });
if (query.ids) { if (query.ids) {

View File

@@ -4,7 +4,7 @@ export async function fetchTagsApi(req, res) {
const tags = await fetchTags({ const tags = await fetchTags({
query: req.query.query, query: req.query.query,
}, { }, {
restriction: req.restriction, restriction: req.geo.restriction,
}); });
res.send(tags); res.send(tags);

View File

@@ -1,6 +1,6 @@
import { MerkleJson } from 'merkle-json'; import { MerkleJson } from 'merkle-json';
import knex from '../knex.js'; import knex from '../src/knex.js';
const mj = new MerkleJson(); const mj = new MerkleJson();

3
utils/runtime-id.js Normal file
View File

@@ -0,0 +1,3 @@
import crypto from 'node:crypto';
export default crypto.randomUUID();